disable physics test in instancing

This commit is contained in:
Nick Fisher
2025-06-26 08:47:22 +08:00
parent fac0c727e4
commit f4b473b9ae

View File

@@ -77,9 +77,7 @@ void main() async {
var asset = await viewer.loadGltf(
"file://${testHelper.testDir}/assets/cube.glb",
addToScene: false,
numInstances: 2,
keepData: true
);
numInstances: 2, keepData: true);
var defaultInstance = await asset.getInstance(0);
await viewer.addToScene(defaultInstance);
await testHelper.capture(viewer.view, "gltf_without_instance");
@@ -103,157 +101,157 @@ void main() async {
}, addSkybox: true);
});
test('physics simulation with 100 instances', () async {
await testHelper.withViewer((viewer) async {
// --- Scene Setup ---
await viewer
.loadIbl("file://${testHelper.testDir}/assets/default_env_ibl.ktx");
await viewer.loadSkybox(
"file://${testHelper.testDir}/assets/default_env_skybox.ktx");
await viewer.setPostProcessing(true);
await viewer.setAntiAliasing(false, true, false); // Enable FXAA
final camera = await viewer.getActiveCamera();
final orbitDist = 12.0; // Slightly further back to see spread pattern
final lookAtTarget = Vector3(0, 0.5, 0); // Look at middle of trajectory
// test('physics simulation with 100 instances', () async {
// await testHelper.withViewer((viewer) async {
// // --- Scene Setup ---
// await viewer
// .loadIbl("file://${testHelper.testDir}/assets/default_env_ibl.ktx");
// await viewer.loadSkybox(
// "file://${testHelper.testDir}/assets/default_env_skybox.ktx");
// await viewer.setPostProcessing(true);
// await viewer.setAntiAliasing(false, true, false); // Enable FXAA
// final camera = await viewer.getActiveCamera();
// final orbitDist = 12.0; // Slightly further back to see spread pattern
// final lookAtTarget = Vector3(0, 0.5, 0); // Look at middle of trajectory
// --- Load Asset & Create/Prepare Instances ---
print("Loading asset...");
var numInstances = 100;
var asset = await viewer.loadGltf(
"file://${testHelper.testDir}/assets/cube.glb",
numInstances: numInstances,
addToScene: false, keepData: true);
// // --- Load Asset & Create/Prepare Instances ---
// print("Loading asset...");
// var numInstances = 100;
// var asset = await viewer.loadGltf(
// "file://${testHelper.testDir}/assets/cube.glb",
// numInstances: numInstances,
// addToScene: false, keepData: true);
print("Creating 100 instances...");
List<PhysicsState> instanceStates = [];
final rnd = Random();
for (int i = 0; i < numInstances - 1; i++) {
var mi = await FilamentApp.instance!
.createUbershaderMaterialInstance(unlit: true);
var instance = await asset.createInstance(materialInstances: [mi]);
await viewer.removeFromScene(instance);
await mi.setParameterFloat4("baseColorFactor", rnd.nextDouble(),
rnd.nextDouble(), rnd.nextDouble(), 1.0);
var scale = max(0.25, rnd.nextDouble());
// print("Creating 100 instances...");
// List<PhysicsState> instanceStates = [];
// final rnd = Random();
// for (int i = 0; i < numInstances - 1; i++) {
// var mi = await FilamentApp.instance!
// .createUbershaderMaterialInstance(unlit: true);
// var instance = await asset.createInstance(materialInstances: [mi]);
// await viewer.removeFromScene(instance);
// await mi.setParameterFloat4("baseColorFactor", rnd.nextDouble(),
// rnd.nextDouble(), rnd.nextDouble(), 1.0);
// var scale = max(0.25, rnd.nextDouble());
instanceStates.add(PhysicsState(instance, scale));
}
print("Instances created and colored.");
// instanceStates.add(PhysicsState(instance, scale));
// }
// print("Instances created and colored.");
// --- Simulation Parameters ---
final gravity = Vector3(0, -9.81, 0);
// // --- Simulation Parameters ---
// final gravity = Vector3(0, -9.81, 0);
// Calculate initial velocity to reach 1 meter in 1 second
// Using kinematics: y = v0*t + 0.5*a*t^2
// At t=1s, y=1m, a=-9.81m/s^2
// Solving for v0: v0 = 1 - 0.5*(-9.81)*1^2 = 1 + 4.905 = 5.905 m/s
final initialUpwardSpeed = 5.905; // Calculated for 1m height in 1s
// // Calculate initial velocity to reach 1 meter in 1 second
// // Using kinematics: y = v0*t + 0.5*a*t^2
// // At t=1s, y=1m, a=-9.81m/s^2
// // Solving for v0: v0 = 1 - 0.5*(-9.81)*1^2 = 1 + 4.905 = 5.905 m/s
// final initialUpwardSpeed = 5.905; // Calculated for 1m height in 1s
final timeStep = 1 / 60.0; // Simulate at 60 FPS
final frameDuration =
Duration(microseconds: (timeStep * 1000000).round());
final launchInterval = 0.5; // 100 ms between launches
final totalSimulationTime = 20.0; // Simulation duration in seconds
final orbitDuration = 10.0; // Time for one full camera orbit
// final timeStep = 1 / 60.0; // Simulate at 60 FPS
// final frameDuration =
// Duration(microseconds: (timeStep * 1000000).round());
// final launchInterval = 0.5; // 100 ms between launches
// final totalSimulationTime = 20.0; // Simulation duration in seconds
// final orbitDuration = 10.0; // Time for one full camera orbit
// --- Simulation Loop ---
double currentTime = 0.0;
double timeSinceLastLaunch =
launchInterval; // Start launching immediately
int launchedCount = 0;
int frameCounter = 0;
int captureCounter = 0;
// // --- Simulation Loop ---
// double currentTime = 0.0;
// double timeSinceLastLaunch =
// launchInterval; // Start launching immediately
// int launchedCount = 0;
// int frameCounter = 0;
// int captureCounter = 0;
print("Starting simulation loop (${totalSimulationTime}s)...");
final startTime = DateTime.now();
// print("Starting simulation loop (${totalSimulationTime}s)...");
// final startTime = DateTime.now();
while (currentTime < totalSimulationTime) {
final loopStart = DateTime.now();
// while (currentTime < totalSimulationTime) {
// final loopStart = DateTime.now();
// 1. Launch Instance Logic
if (launchedCount < instanceStates.length &&
timeSinceLastLaunch >= launchInterval) {
final state = instanceStates[launchedCount];
if (!state.launched) {
print("Launching instance ${launchedCount + 1}/100");
// Add a slight angle to launch direction
// Using a spiral pattern with increasing angle
final angle = (launchedCount * 0.2) %
(2 * pi); // Increasing angle creating spiral
final horizontalComponent =
initialUpwardSpeed * 0.15; // 15% horizontal velocity
state.velocity = Vector3(
horizontalComponent * cos(angle),
initialUpwardSpeed,
horizontalComponent * sin(angle)); // Angled velocity
state.position = Vector3(0, 0.1, 0); // Start slightly above origin
state.launched = true;
await viewer
.addToScene(state.instance); // Add to scene ONLY when launched
state.addedToScene = true;
launchedCount++;
timeSinceLastLaunch -= launchInterval;
}
}
// // 1. Launch Instance Logic
// if (launchedCount < instanceStates.length &&
// timeSinceLastLaunch >= launchInterval) {
// final state = instanceStates[launchedCount];
// if (!state.launched) {
// print("Launching instance ${launchedCount + 1}/100");
// // Add a slight angle to launch direction
// // Using a spiral pattern with increasing angle
// final angle = (launchedCount * 0.2) %
// (2 * pi); // Increasing angle creating spiral
// final horizontalComponent =
// initialUpwardSpeed * 0.15; // 15% horizontal velocity
// state.velocity = Vector3(
// horizontalComponent * cos(angle),
// initialUpwardSpeed,
// horizontalComponent * sin(angle)); // Angled velocity
// state.position = Vector3(0, 0.1, 0); // Start slightly above origin
// state.launched = true;
// await viewer
// .addToScene(state.instance); // Add to scene ONLY when launched
// state.addedToScene = true;
// launchedCount++;
// timeSinceLastLaunch -= launchInterval;
// }
// }
// 2. Update Physics and Transforms for launched instances
List<Future> transformUpdates = [];
for (var state in instanceStates) {
if (state.launched) {
// Basic Euler integration
state.velocity.add(gravity * timeStep);
state.position.add(state.velocity * timeStep);
// // 2. Update Physics and Transforms for launched instances
// List<Future> transformUpdates = [];
// for (var state in instanceStates) {
// if (state.launched) {
// // Basic Euler integration
// state.velocity.add(gravity * timeStep);
// state.position.add(state.velocity * timeStep);
// Queue the asynchronous transform update
transformUpdates.add(state.instance.setTransform(Matrix4.compose(
state.position,
Quaternion.identity(),
Vector3.all(state.scale))));
}
}
// Wait for all instance transforms in this step to complete
if (transformUpdates.isNotEmpty) {
await Future.wait(transformUpdates);
}
// // Queue the asynchronous transform update
// transformUpdates.add(state.instance.setTransform(Matrix4.compose(
// state.position,
// Quaternion.identity(),
// Vector3.all(state.scale))));
// }
// }
// // Wait for all instance transforms in this step to complete
// if (transformUpdates.isNotEmpty) {
// await Future.wait(transformUpdates);
// }
// 3. Update Camera Orbit
final angle = (currentTime / orbitDuration) * 2 * pi;
await camera.lookAt(
Vector3(
sin(angle) * orbitDist,
orbitDist * 0.3, // Lower camera height to see 1-meter trajectories
cos(angle) * orbitDist,
),
focus: lookAtTarget, // Point towards the peak of trajectories
up: Vector3(0, 1, 0), // Keep up vector standard
);
// // 3. Update Camera Orbit
// final angle = (currentTime / orbitDuration) * 2 * pi;
// await camera.lookAt(
// Vector3(
// sin(angle) * orbitDist,
// orbitDist * 0.3, // Lower camera height to see 1-meter trajectories
// cos(angle) * orbitDist,
// ),
// focus: lookAtTarget, // Point towards the peak of trajectories
// up: Vector3(0, 1, 0), // Keep up vector standard
// );
// 4. Capture Frame Periodically (e.g., every 6 physics steps => 10 captures/sec)
if (frameCounter % 6 == 0) {
await testHelper.capture(viewer.view,
"capture_physics_orbit_${captureCounter.toString().padLeft(3, '0')}");
captureCounter++;
}
// // 4. Capture Frame Periodically (e.g., every 6 physics steps => 10 captures/sec)
// if (frameCounter % 6 == 0) {
// await testHelper.capture(viewer.view,
// "capture_physics_orbit_${captureCounter.toString().padLeft(3, '0')}");
// captureCounter++;
// }
// 5. Advance Time and Wait
currentTime += timeStep;
timeSinceLastLaunch += timeStep;
frameCounter++;
// // 5. Advance Time and Wait
// currentTime += timeStep;
// timeSinceLastLaunch += timeStep;
// frameCounter++;
// Ensure the loop doesn't run faster than the desired frame rate
final elapsed = loopStart.difference(loopStart);
if (elapsed < frameDuration) {
await Future.delayed(frameDuration - elapsed);
}
}
// // Ensure the loop doesn't run faster than the desired frame rate
// final elapsed = loopStart.difference(loopStart);
// if (elapsed < frameDuration) {
// await Future.delayed(frameDuration - elapsed);
// }
// }
final endTime = DateTime.now();
print(
"Simulation loop finished in ${endTime.difference(startTime).inSeconds} seconds.");
print("Captured $captureCounter frames.");
// final endTime = DateTime.now();
// print(
// "Simulation loop finished in ${endTime.difference(startTime).inSeconds} seconds.");
// print("Captured $captureCounter frames.");
// Optional: Capture one final frame after simulation ends
await testHelper.capture(viewer.view, "capture_physics_orbit_final");
}, viewportDimensions: (width: 1024, height: 1024)); // End withViewer
});
// // Optional: Capture one final frame after simulation ends
// await testHelper.capture(viewer.view, "capture_physics_orbit_final");
// }, viewportDimensions: (width: 1024, height: 1024)); // End withViewer
// });
}