MasahideMori-SimpleAppli / simple_3d_renderer

Sp3dObj renderer. Includes simple cameras, light, world, and more. It also supports user taps.
https://pub.dev/packages/simple_3d_renderer
MIT License
22 stars 5 forks source link

move camera around the 3d object #10

Open francescovallone opened 3 months ago

francescovallone commented 3 months ago

Hello, I'm trying to move the camera around the 3d Object instead of having the 3d object move around the origin, I have tried to use both onPanUpdate and onPanDown but when i move the camera the whole 3d world gets skewed.

How can I implement the movement of the camera around the object keeping the object in place?

MasahideMori-SimpleAppli commented 2 months ago

Hi @francescovallone , Thank you for opening this issue.

Sorry I noticed your question late. Is what you want to do something like the code below?

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:simple_3d/simple_3d.dart';
import 'package:util_simple_3d/util_simple_3d.dart';
import 'package:simple_3d_renderer/simple_3d_renderer.dart';

void main() async {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<StatefulWidget> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final List<Sp3dObj> _objs = [];
  late Sp3dWorld _world;
  bool _isLoaded = false;
  final ValueNotifier<int> _vn = ValueNotifier(0);
  final Sp3dCamera _camera = Sp3dCamera(Sp3dV3D(0, 0, 8000), 6000);

  // Camera rotation radian.
  double _cameraRotateAngle = 0;
  Timer? _timer;

  @override
  void initState() {
    super.initState();
    // Create Sp3dObj.
    Sp3dObj obj = UtilSp3dGeometry.cube(200, 200, 200, 1, 1, 1);
    obj.move(Sp3dV3D(0, 100, 0));
    obj.id = "tap_target";
    _objs.add(obj);
    for (Sp3dObj i in UtilSp3dCommonParts.worldMeshes(400)) {
      _objs.add(i);
    }
    for (Sp3dObj i in UtilSp3dCommonParts.coordinateArrows(400)) {
      _objs.add(i);
    }
    loadImage();
  }

  @override
  void dispose() {
    if (_timer != null) {
      _timer!.cancel();
    }
    super.dispose();
  }

  void loadImage() async {
    _world = Sp3dWorld(_objs);
    _world.initImages().then((List<Sp3dObj> errorObjs) {
      if (mounted) {
        setState(() {
          _isLoaded = true;
        });
      }
    });
  }

  /// camera rotation
  void _cameraRotationAnim() {
    if (_timer != null) {
      _timer!.cancel();
      _timer = null;
    } else {
      _timer =
          Timer.periodic(Duration(milliseconds: (1000 / 60).round()), (timer) {
        _cameraRotateAngle = _cameraRotateAngle + 1;
        _camera.rotate(Sp3dV3D(0, 1, 0).nor(),
            _cameraRotateAngle * Sp3dConstantValues.toRadian);
        _vn.value += 1;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    if (!_isLoaded) {
      return MaterialApp(
          title: 'Sp3dRenderer',
          home: Scaffold(
              appBar: AppBar(
                backgroundColor: const Color.fromARGB(255, 0, 255, 0),
                title: const Text("Camera rotation sample"),
              ),
              backgroundColor: const Color.fromARGB(255, 33, 33, 33),
              body: Container()));
    } else {
      final double width = MediaQuery.of(context).size.width;
      final double height = MediaQuery.of(context).size.height -
          MediaQuery.of(context).padding.top -
          kBottomNavigationBarHeight -
          kToolbarHeight;
      return MaterialApp(
        title: 'Sp3dRenderer',
        home: Scaffold(
          appBar: AppBar(
            backgroundColor: const Color.fromARGB(255, 0, 255, 0),
            title: const Text("Camera rotation sample"),
          ),
          backgroundColor: const Color.fromARGB(255, 33, 33, 33),
          body: Column(
            children: [
              Sp3dRenderer(
                Size(width, height),
                Sp3dV2D(width / 2, height / 2),
                _world,
                _camera,
                Sp3dLight(Sp3dV3D(0, 0, -1), syncCam: true),
                onPanDown: (Sp3dGestureDetails d, Sp3dFaceObj? obj) {
                  if (obj != null) {
                    if (obj.obj.id == "tap_target") {
                      // rotate camera
                      _cameraRotationAnim();
                    }
                  }
                },
                vn: _vn,
              ),
            ],
          ),
        ),
      );
    }
  }
}

In the simple code above, when you tap a square on the screen, the camera rotates on a timer. Tapping again stops the rotation.