|
| 1 | +import 'package:flutter/material.dart'; |
| 2 | +import 'dart:math' as math; |
| 3 | +import 'dart:convert'; |
| 4 | +import 'package:flutter/services.dart'; |
| 5 | + |
| 6 | +class CameraSimulation extends StatefulWidget { |
| 7 | + @override |
| 8 | + _CameraSimulationState createState() => _CameraSimulationState(); |
| 9 | +} |
| 10 | + |
| 11 | +class _CameraSimulationState extends State<CameraSimulation> { |
| 12 | + double _rotateX = 0; |
| 13 | + double _rotateY = 0; |
| 14 | + double _rotateZ = 0; |
| 15 | + double _translateX = 0; |
| 16 | + double _translateY = 0; |
| 17 | + double _translateZ = 0; |
| 18 | + double _perspectiveX = 0.00; |
| 19 | + double _perspectiveY = 0.00; |
| 20 | + double _perspectiveZ = 0.00; |
| 21 | + double _zoom = 1.0; |
| 22 | + |
| 23 | +// working bottom left |
| 24 | +// Transform( |
| 25 | +// transform: Matrix4.identity() |
| 26 | +// // ..setEntry(3, 2, _perspectiveZ) // Z perspective |
| 27 | +// // ..setEntry(3, 1, _perspectiveY) // Y perspective |
| 28 | +// // ..setEntry(3, 0, _perspectiveX) // X perspective |
| 29 | +// // ..translate(50.0, -50.0, 0.0) |
| 30 | +// ..rotateX(-0.3) |
| 31 | +// ..rotateY(-0.3) |
| 32 | +// ..rotateZ(0.02094395102393154), |
| 33 | +// // ..scale(_zoom), |
| 34 | +// // ..setEntry(3, 2, _perspective) // perspective |
| 35 | +// // ..rotateX(_rotateX) |
| 36 | +// // ..rotateY(_rotateY) |
| 37 | +// // ..rotateZ(_rotateZ) |
| 38 | +// // ..translate(_translateX, _translateY, _translateZ) |
| 39 | +// // ..scale(_zoom), // Add zoom effect |
| 40 | +// alignment: FractionalOffset.center, |
| 41 | +// child: _build3DScene(), |
| 42 | +// ) |
| 43 | + @override |
| 44 | + Widget build(BuildContext context) { |
| 45 | +// setEntry(0, 3, x): Translates along the X-axis |
| 46 | +// setEntry(1, 3, y): Translates along the Y-axis |
| 47 | +// setEntry(2, 3, z): Translates along the Z-axis |
| 48 | + return Column( |
| 49 | + children: [ |
| 50 | + Stack( |
| 51 | + alignment: Alignment.center, |
| 52 | + children: [ |
| 53 | + Container( |
| 54 | + height: 400, |
| 55 | + width: double.infinity, |
| 56 | + child: Image.asset( |
| 57 | + "assets/images/tracing_cards.png", |
| 58 | + fit: BoxFit.fitHeight, |
| 59 | + ), |
| 60 | + ), |
| 61 | + // transform = Matrix4.identity() |
| 62 | + // ..translate(50.0, -50.0, 0.0) |
| 63 | + // ..rotateX(-0.3) |
| 64 | + // ..rotateY(-0.3); |
| 65 | + Container( |
| 66 | + height: 400, |
| 67 | + child: Transform( |
| 68 | + transform: Matrix4.identity() |
| 69 | + ..rotateX(0.3) |
| 70 | + ..rotateY(0.3) |
| 71 | + ..rotateZ(-0.02094395102393154) |
| 72 | + ..translate(_translateX, _translateY, _translateZ), |
| 73 | + // ..setEntry(3, 2, _perspectiveZ) // Z perspective |
| 74 | + // ..setEntry(3, 1, _perspectiveY) // Y perspective |
| 75 | + // ..setEntry(3, 0, _perspectiveX) // X perspective |
| 76 | + // ..translate(_translateX, _translateY, _translateZ) |
| 77 | + // ..rotateX(_rotateX) |
| 78 | + // ..rotateY(_rotateY) |
| 79 | + // ..rotateZ(_rotateZ) |
| 80 | + // ..scale(_zoom), |
| 81 | + alignment: FractionalOffset.center, |
| 82 | + child: _build3DScene(), |
| 83 | + ), |
| 84 | + ) |
| 85 | + ], |
| 86 | + ), |
| 87 | + _buildControls(), |
| 88 | + _buildExportButton(), |
| 89 | + ], |
| 90 | + ); |
| 91 | + } |
| 92 | + |
| 93 | + Widget _build3DScene() { |
| 94 | + return Stack( |
| 95 | + alignment: Alignment.center, |
| 96 | + children: [ |
| 97 | + // Back plane (blue) |
| 98 | + |
| 99 | + Transform( |
| 100 | + transform: Matrix4.translationValues(0, 0, 0), |
| 101 | + child: Container(color: Colors.blue, width: 200, height: 288), |
| 102 | + ), |
| 103 | + |
| 104 | + Transform( |
| 105 | + transform: Matrix4.translationValues(0, 0, 100.0), |
| 106 | + child: Container(color: Colors.red, width: 200, height: 288), |
| 107 | + ), |
| 108 | + |
| 109 | + Transform( |
| 110 | + transform: Matrix4.translationValues(0, 0, 200.0), |
| 111 | + child: Container(color: Colors.yellow, width: 200, height: 288), |
| 112 | + ), |
| 113 | + ], |
| 114 | + ); |
| 115 | + } |
| 116 | + |
| 117 | + Widget _buildControls() { |
| 118 | + return Column( |
| 119 | + children: [ |
| 120 | + Slider( |
| 121 | + value: _rotateX, |
| 122 | + min: -math.pi, |
| 123 | + max: math.pi, |
| 124 | + divisions: 300, |
| 125 | + onChanged: (value) => setState(() => _rotateX = value), |
| 126 | + label: 'Rotate X: ${_rotateX.toStringAsFixed(2)}', |
| 127 | + ), |
| 128 | + Slider( |
| 129 | + value: _rotateY, |
| 130 | + min: -math.pi, |
| 131 | + max: math.pi, |
| 132 | + divisions: 300, |
| 133 | + onChanged: (value) => setState(() => _rotateY = value), |
| 134 | + label: 'Rotate Y: ${_rotateY.toStringAsFixed(2)}', |
| 135 | + ), |
| 136 | + Slider( |
| 137 | + value: _rotateZ, |
| 138 | + min: -math.pi, |
| 139 | + max: math.pi, |
| 140 | + divisions: 300, |
| 141 | + onChanged: (value) => setState(() => _rotateZ = value), |
| 142 | + label: 'Rotate Z:${_rotateZ.toStringAsFixed(2)}', |
| 143 | + ), |
| 144 | + Slider( |
| 145 | + value: _translateX, |
| 146 | + min: -200, |
| 147 | + max: 200, |
| 148 | + divisions: 400, |
| 149 | + onChanged: (value) => setState(() => _translateX = value), |
| 150 | + label: 'Translate X: ${_translateX.toStringAsFixed(2)}', |
| 151 | + ), |
| 152 | + Slider( |
| 153 | + value: _translateY, |
| 154 | + min: -200, |
| 155 | + max: 200, |
| 156 | + divisions: 400, |
| 157 | + onChanged: (value) => setState(() => _translateY = value), |
| 158 | + label: 'Translate Y: ${_translateY.toStringAsFixed(2)}', |
| 159 | + ), |
| 160 | + Slider( |
| 161 | + value: _translateZ, |
| 162 | + min: -200, |
| 163 | + max: 200, |
| 164 | + divisions: 400, |
| 165 | + onChanged: (value) => setState(() => _translateZ = value), |
| 166 | + label: 'Translate Z: ${_translateZ.toStringAsFixed(2)}', |
| 167 | + ), |
| 168 | + Text("PerspectiveX"), |
| 169 | + Slider( |
| 170 | + value: _perspectiveX, |
| 171 | + min: -0.01, //0.0001, |
| 172 | + max: 0.01, |
| 173 | + divisions: 300, |
| 174 | + onChanged: (value) => setState(() => _perspectiveX = value), |
| 175 | + label: 'PerspectiveX: ${_perspectiveX.toStringAsFixed(4)}', |
| 176 | + ), |
| 177 | + Text("PerspectiveY"), |
| 178 | + Slider( |
| 179 | + value: _perspectiveY, |
| 180 | + min: -0.01, //0.0001, |
| 181 | + max: 0.01, |
| 182 | + divisions: 300, |
| 183 | + onChanged: (value) => setState(() => _perspectiveY = value), |
| 184 | + label: 'PerspectiveY: ${_perspectiveY.toStringAsFixed(4)}', |
| 185 | + ), |
| 186 | + Text("PerspectiveZ"), |
| 187 | + Slider( |
| 188 | + value: _perspectiveZ, |
| 189 | + min: -0.01, //0.0001, |
| 190 | + max: 0.01, |
| 191 | + divisions: 300, |
| 192 | + onChanged: (value) => setState(() => _perspectiveZ = value), |
| 193 | + label: 'PerspectiveZ: ${_perspectiveZ.toStringAsFixed(4)}', |
| 194 | + ), |
| 195 | + Slider( |
| 196 | + value: _zoom, |
| 197 | + min: 0.5, |
| 198 | + max: 2.0, |
| 199 | + divisions: 150, |
| 200 | + onChanged: (value) => setState(() => _zoom = value), |
| 201 | + label: 'Zoom: ${_zoom.toStringAsFixed(2)}', |
| 202 | + ), |
| 203 | + ], |
| 204 | + ); |
| 205 | + } |
| 206 | + |
| 207 | + Widget _buildExportButton() { |
| 208 | + return ElevatedButton( |
| 209 | + child: Text('Export Settings to Clipboard'), |
| 210 | + onPressed: _exportSettings, |
| 211 | + ); |
| 212 | + } |
| 213 | + |
| 214 | + void _exportSettings() { |
| 215 | + final settings = { |
| 216 | + 'rotateX': _rotateX, |
| 217 | + 'rotateY': _rotateY, |
| 218 | + 'rotateZ': _rotateZ, |
| 219 | + 'translateX': _translateX, |
| 220 | + 'translateY': _translateY, |
| 221 | + 'translateZ': _translateZ, |
| 222 | + 'perspectiveX': _perspectiveX, |
| 223 | + 'perspectiveY': _perspectiveY, |
| 224 | + 'perspectiveZ': _perspectiveZ, |
| 225 | + 'zoom': _zoom, |
| 226 | + }; |
| 227 | + |
| 228 | + final jsonString = JsonEncoder.withIndent(' ').convert(settings); |
| 229 | + Clipboard.setData(ClipboardData(text: jsonString)); |
| 230 | + |
| 231 | + ScaffoldMessenger.of(context).showSnackBar( |
| 232 | + SnackBar(content: Text('Settings and code copied to clipboard')), |
| 233 | + ); |
| 234 | + } |
| 235 | +} |
| 236 | +// import 'package:flutter/material.dart'; |
| 237 | +// import 'dart:math' as math; |
| 238 | + |
| 239 | +// class CameraSimulation extends StatefulWidget { |
| 240 | +// @override |
| 241 | +// _CameraSimulationState createState() => _CameraSimulationState(); |
| 242 | +// } |
| 243 | + |
| 244 | +// class _CameraSimulationState extends State<CameraSimulation> { |
| 245 | +// double _rotateX = 0; |
| 246 | +// double _rotateY = 0; |
| 247 | +// double _translateZ = 0; |
| 248 | +// double _perspective = 0; |
| 249 | + |
| 250 | +// @override |
| 251 | +// Widget build(BuildContext context) { |
| 252 | +// return Column( |
| 253 | +// children: [ |
| 254 | +// Container( |
| 255 | +// height: 300, |
| 256 | +// child: Transform( |
| 257 | +// transform: Matrix4.identity() |
| 258 | +// ..setEntry(3, 2, 0.001) // perspective |
| 259 | +// ..rotateX(_rotateX) |
| 260 | +// ..rotateY(_rotateY) |
| 261 | +// ..translate(0.0, 0.0, _translateZ), |
| 262 | +// alignment: FractionalOffset.center, |
| 263 | +// child: _build3DScene(), |
| 264 | +// ), |
| 265 | +// ), |
| 266 | +// _buildControls(), |
| 267 | +// ], |
| 268 | +// ); |
| 269 | +// } |
| 270 | + |
| 271 | +// Widget _build3DScene() { |
| 272 | +// return Stack( |
| 273 | +// children: [ |
| 274 | +// // Back plane (blue) |
| 275 | +// Transform( |
| 276 | +// transform: Matrix4.translationValues(0, 0, -100), |
| 277 | +// child: Container(color: Colors.blue, width: 200, height: 200), |
| 278 | +// ), |
| 279 | +// // Left plane (red) |
| 280 | +// Transform( |
| 281 | +// transform: Matrix4.identity() |
| 282 | +// ..translate(-100.0, 0.0, -50) |
| 283 | +// ..rotateY(math.pi / 2), |
| 284 | +// child: Container(color: Colors.red, width: 200, height: 200), |
| 285 | +// ), |
| 286 | +// // Right plane (green) |
| 287 | +// Transform( |
| 288 | +// transform: Matrix4.identity() |
| 289 | +// ..translate(100.0, 0.0, -50) |
| 290 | +// ..rotateY(-math.pi / 2), |
| 291 | +// child: Container(color: Colors.green, width: 200, height: 200), |
| 292 | +// ), |
| 293 | +// // Front object (yellow cube) |
| 294 | +// Transform( |
| 295 | +// transform: Matrix4.translationValues(0, 0, 50), |
| 296 | +// child: Container(color: Colors.yellow, width: 50, height: 50), |
| 297 | +// ), |
| 298 | +// ], |
| 299 | +// ); |
| 300 | +// } |
| 301 | + |
| 302 | +// Widget _buildControls() { |
| 303 | +// return Column( |
| 304 | +// children: [ |
| 305 | +// Slider( |
| 306 | +// value: _rotateX, |
| 307 | +// min: -math.pi / 4, |
| 308 | +// max: math.pi / 4, |
| 309 | +// onChanged: (value) => setState(() => _rotateX = value), |
| 310 | +// label: 'Rotate X: ${_rotateX.toStringAsFixed(2)}', |
| 311 | +// ), |
| 312 | +// Slider( |
| 313 | +// value: _rotateY, |
| 314 | +// min: -math.pi / 4, |
| 315 | +// max: math.pi / 4, |
| 316 | +// onChanged: (value) => setState(() => _rotateY = value), |
| 317 | +// label: 'Rotate Y: ${_rotateY.toStringAsFixed(2)}', |
| 318 | +// ), |
| 319 | +// Slider( |
| 320 | +// value: _translateZ, |
| 321 | +// min: -200, |
| 322 | +// max: 200, |
| 323 | +// onChanged: (value) => setState(() => _translateZ = value), |
| 324 | +// label: 'Translate Z: ${_translateZ.toStringAsFixed(2)}', |
| 325 | +// ), |
| 326 | +// ], |
| 327 | +// ); |
| 328 | +// } |
| 329 | +// } |
0 commit comments