import 'dart:math'; import 'package:flutter/material.dart'; import 'package:flutter_scene/camera.dart'; import 'package:flutter_scene/node.dart'; import 'package:flutter_scene/scene.dart'; import 'package:vector_math/vector_math.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatefulWidget { const MyApp({super.key}); @override MyAppState createState() => MyAppState(); } class MyAppState extends State with SingleTickerProviderStateMixin { double elapsedSeconds = 0.009; Scene scene = Scene(); double pointerx = 0.0; double pointery = 0.0; double cameraRotateX = 0.0; double cameraRotateY = 0.0; @override void initState() { createTicker((elapsed) { setState(() { elapsedSeconds = elapsed.inMilliseconds.toDouble() / 1000; // print(elapsedSeconds); // elapsedSeconds = cameraRotateX; }); }).start(); setState(() {}); Node.fromAsset('assets/DamagedHelmet.model').then( (model) { model.name = 'Helmet'; scene.add(model); }, ); super.initState(); } void pointerUpdate(details, BuildContext context) { final screenWidth = MediaQuery.of(context).size.width; // print(screenWidth); final lastPointerX = pointerx; final lastPointerY = pointery; pointerx = details.globalPosition.dx; pointery = details.globalPosition.dy; // print(pointerx); // print(pointery); if (pointerx > lastPointerX) { print("ROTATE RIGHT!"); setState(() { cameraRotateX += 1 / 80; }); } else { print("ROTATE LEFT!"); setState(() { cameraRotateX -= 1 / 80; }); } if (pointery > lastPointerY) { print("ROTATE RIGHT!"); setState(() { cameraRotateY += 1 / 80; }); } else { print("ROTATE LEFT!"); setState(() { cameraRotateY -= 1 / 80; }); } } @override Widget build(BuildContext context) { final painter = ScenePainter( scene: scene, camera: PerspectiveCamera( // position: Vector3(sin(cameraRotateX) * 3, 3, cos(cameraRotateX) * 3), position: Vector3(sin(elapsedSeconds) * 3, 3, cos(elapsedSeconds) * 3), target: Vector3(0, 0, 0), ), ); return MaterialApp( title: 'My 3D app', home: GestureDetector( onTapDown: (details) => pointerUpdate(details, context), onTapUp: (details) => pointerUpdate(details, context), onVerticalDragUpdate: (details) => pointerUpdate(details, context), onHorizontalDragUpdate: (details) => pointerUpdate(details, context), child: CustomPaint( painter: painter, ), ), ); } } class ScenePainter extends CustomPainter { ScenePainter({ required this.scene, required this.camera, }); Scene scene; Camera camera; @override void paint(Canvas canvas, Size size) { scene.render(camera, canvas, viewport: Offset.zero & size); } @override bool shouldRepaint(covariant CustomPainter oldDelegate) => true; }