mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
309 lines
8.2 KiB
Dart
309 lines
8.2 KiB
Dart
import 'dart:math' as math;
|
|
import 'dart:typed_data';
|
|
|
|
import 'package:vector_math/vector_math_64.dart';
|
|
|
|
main() {
|
|
runTest();
|
|
}
|
|
|
|
const int numSystems = 1000;
|
|
const int numFrames = 1000;
|
|
|
|
void runTest() {
|
|
int timeStart;
|
|
timeStart = new DateTime.now().millisecondsSinceEpoch;
|
|
|
|
// Create systems
|
|
List<TestParticleSystem> systems = <TestParticleSystem>[];
|
|
for (int i = 0; i < numSystems; i++)
|
|
systems.add(new TestParticleSystem());
|
|
|
|
int timeAfterCreate = new DateTime.now().millisecondsSinceEpoch;
|
|
print("TIME creation ${(timeAfterCreate - timeStart) / 1000.0}");
|
|
timeStart = new DateTime.now().millisecondsSinceEpoch;
|
|
|
|
// Update systems
|
|
for (int frame = 0; frame < numFrames; frame++) {
|
|
for (int i = 0; i < numSystems; i++) {
|
|
systems[i].update(1.0 / 60.0);
|
|
}
|
|
}
|
|
|
|
int timeAfterUpdates = new DateTime.now().millisecondsSinceEpoch;
|
|
print("TIME updates ${(timeAfterUpdates - timeStart) / 1000.0}");
|
|
timeStart = new DateTime.now().millisecondsSinceEpoch;
|
|
|
|
// Calculate matrices
|
|
for (int frame = 0; frame < numFrames; frame++) {
|
|
for (int i = 0; i < numSystems; i++) {
|
|
systems[i].paint();
|
|
}
|
|
}
|
|
|
|
int timeAfterMatrices = new DateTime.now().millisecondsSinceEpoch;
|
|
print("TIME matrices ${(timeAfterMatrices - timeStart) / 1000.0}");
|
|
}
|
|
|
|
class TestParticle {
|
|
Vector2 pos;
|
|
Vector2 startPos;
|
|
|
|
double colorPos;
|
|
double deltaColorPos;
|
|
|
|
double size;
|
|
double deltaSize;
|
|
|
|
double rotation;
|
|
double deltaRotation;
|
|
|
|
double timeToLive;
|
|
|
|
Vector2 dir;
|
|
|
|
double radialAccel;
|
|
double tangentialAccel;
|
|
|
|
Float64List simpleColorSequence;
|
|
|
|
Matrix4 transform;
|
|
}
|
|
|
|
class TestParticleSystem {
|
|
double life;
|
|
double lifeVar;
|
|
|
|
Vector2 posVar;
|
|
|
|
double startSize;
|
|
double startSizeVar;
|
|
|
|
double endSize;
|
|
double endSizeVar;
|
|
|
|
double startRotation;
|
|
double startRotationVar;
|
|
|
|
double endRotation;
|
|
double endRotationVar;
|
|
|
|
double direction;
|
|
double directionVar;
|
|
|
|
double speed;
|
|
double speedVar;
|
|
|
|
double radialAcceleration;
|
|
double radialAccelerationVar;
|
|
|
|
double tangentialAcceleration;
|
|
double tangentialAccelerationVar;
|
|
|
|
Vector2 gravity;
|
|
|
|
int maxParticles;
|
|
int numParticlesToEmit;
|
|
double emissionRate;
|
|
|
|
List<TestParticle> _particles;
|
|
|
|
double _emitCounter;
|
|
int _numEmittedParticles = 0;
|
|
|
|
TestParticleSystem({this.life: 1.5,
|
|
this.lifeVar: 0.0,
|
|
this.startSize: 2.5,
|
|
this.startSizeVar: 0.5,
|
|
this.endSize: 0.0,
|
|
this.endSizeVar: 0.0,
|
|
this.startRotation: 0.0,
|
|
this.startRotationVar: 0.0,
|
|
this.endRotation: 0.0,
|
|
this.endRotationVar: 0.0,
|
|
this.direction: 0.0,
|
|
this.directionVar: 360.0,
|
|
this.speed: 100.0,
|
|
this.speedVar: 50.0,
|
|
this.radialAcceleration: 0.0,
|
|
this.radialAccelerationVar: 0.0,
|
|
this.tangentialAcceleration: 0.0,
|
|
this.tangentialAccelerationVar: 0.0,
|
|
this.gravity,
|
|
this.maxParticles: 100,
|
|
this.emissionRate: 50.0,
|
|
this.numParticlesToEmit: 0}) {
|
|
posVar = new Vector2.zero();
|
|
_particles = new List<TestParticle>();
|
|
_emitCounter = 0.0;
|
|
gravity = new Vector2.zero();
|
|
}
|
|
|
|
void update(double dt) {
|
|
// Create new particles
|
|
double rate = 1.0 / emissionRate;
|
|
|
|
if (_particles.length < maxParticles) {
|
|
_emitCounter += dt;
|
|
}
|
|
|
|
while(_particles.length < maxParticles
|
|
&& _emitCounter > rate
|
|
&& (numParticlesToEmit == 0 || _numEmittedParticles < numParticlesToEmit)) {
|
|
// Add a new particle
|
|
_addParticle();
|
|
_emitCounter -= rate;
|
|
}
|
|
|
|
// Iterate over all particles
|
|
for (int i = _particles.length -1; i >= 0; i--) {
|
|
TestParticle particle = _particles[i];
|
|
|
|
// Manage life time
|
|
particle.timeToLive -= dt;
|
|
if (particle.timeToLive <= 0) {
|
|
_particles.removeAt(i);
|
|
continue;
|
|
}
|
|
|
|
// Update the particle
|
|
|
|
// Radial acceleration
|
|
Vector2 radial;
|
|
if (particle.pos[0] != 0 || particle.pos[1] != 0) {
|
|
radial = new Vector2.copy(particle.pos).normalize();
|
|
} else {
|
|
radial = new Vector2.zero();
|
|
}
|
|
Vector2 tangential = new Vector2.copy(radial);
|
|
radial.scale(particle.radialAccel);
|
|
|
|
// Tangential acceleration
|
|
double newY = tangential.x;
|
|
tangential.x = -tangential.y;
|
|
tangential.y = newY;
|
|
tangential.scale(particle.tangentialAccel);
|
|
|
|
// (gravity + radial + tangential) * dt
|
|
Vector2 accel = (gravity + radial + tangential).scale(dt);
|
|
particle.dir += accel;
|
|
|
|
// Update particle position
|
|
particle.pos[0] += particle.dir[0] * dt;
|
|
particle.pos[1] += particle.dir[1] * dt;
|
|
|
|
// Size
|
|
particle.size = math.max(particle.size + particle.deltaSize * dt, 0.0);
|
|
|
|
// Angle
|
|
particle.rotation += particle.deltaRotation * dt;
|
|
|
|
// Color
|
|
if (particle.simpleColorSequence != null) {
|
|
for (int i = 0; i < 4; i++) {
|
|
particle.simpleColorSequence[i] += particle.simpleColorSequence[i + 4] * dt;
|
|
}
|
|
} else {
|
|
particle.colorPos = math.min(particle.colorPos + particle.deltaColorPos * dt, 1.0);
|
|
}
|
|
}
|
|
}
|
|
|
|
void _addParticle() {
|
|
|
|
TestParticle particle = new TestParticle();
|
|
|
|
// Time to live
|
|
particle.timeToLive = math.max(life + lifeVar * randomSignedDouble(), 0.0);
|
|
|
|
// Position
|
|
Vector2 srcPos = new Vector2.zero();
|
|
particle.pos = new Vector2(srcPos.x + posVar.x * randomSignedDouble(),
|
|
srcPos.y + posVar.y * randomSignedDouble());
|
|
|
|
// Size
|
|
particle.size = math.max(startSize + startSizeVar * randomSignedDouble(), 0.0);
|
|
double endSizeFinal = math.max(endSize + endSizeVar * randomSignedDouble(), 0.0);
|
|
particle.deltaSize = (endSizeFinal - particle.size) / particle.timeToLive;
|
|
|
|
// Rotation
|
|
particle.rotation = startRotation + startRotationVar * randomSignedDouble();
|
|
double endRotationFinal = endRotation + endRotationVar * randomSignedDouble();
|
|
particle.deltaRotation = (endRotationFinal - particle.rotation) / particle.timeToLive;
|
|
|
|
// Direction
|
|
double dirRadians = radians(direction + directionVar * randomSignedDouble());
|
|
Vector2 dirVector = new Vector2(math.cos(dirRadians), math.sin(dirRadians));
|
|
double speedFinal = speed + speedVar * randomSignedDouble();
|
|
particle.dir = dirVector.scale(speedFinal);
|
|
|
|
// Radial acceleration
|
|
particle.radialAccel = radialAcceleration + radialAccelerationVar * randomSignedDouble();
|
|
|
|
// Tangential acceleration
|
|
particle.tangentialAccel = tangentialAcceleration + tangentialAccelerationVar * randomSignedDouble();
|
|
|
|
// Colors
|
|
particle.simpleColorSequence = new Float64List(8);
|
|
particle.simpleColorSequence[0] = 255.0;
|
|
particle.simpleColorSequence[1] = 255.0;
|
|
particle.simpleColorSequence[2] = 255.0;
|
|
particle.simpleColorSequence[3] = 255.0;
|
|
|
|
particle.simpleColorSequence[4] = 255.0;
|
|
particle.simpleColorSequence[5] = 0.0;
|
|
particle.simpleColorSequence[6] = 0.0;
|
|
particle.simpleColorSequence[7] = 0.0;
|
|
|
|
// Transform
|
|
particle.transform = new Matrix4.identity();
|
|
|
|
// Add particle
|
|
_particles.add(particle);
|
|
_numEmittedParticles++;
|
|
}
|
|
|
|
|
|
void paint() {
|
|
|
|
if (!printed) {
|
|
printed = true;
|
|
}
|
|
|
|
for (int i = _particles.length -1; i >= 0; i--) {
|
|
TestParticle particle = _particles[i];
|
|
particle.rotation + randomSignedDouble();
|
|
|
|
// Transform
|
|
double c = math.cos(radians(particle.rotation));
|
|
double s = math.sin(radians(particle.rotation));
|
|
|
|
// Create transformation matrix for scale, position and rotation
|
|
Matrix4 matrix = new Matrix4(c * particle.size, s * particle.size, 0.0, 0.0,
|
|
-s * particle.size, c * particle.size, 0.0, 0.0,
|
|
0.0, 0.0, 1.0, 0.0,
|
|
particle.pos.x, particle.pos.y, 0.0, 1.0);
|
|
|
|
particle.transform.multiply(matrix);
|
|
}
|
|
}
|
|
}
|
|
|
|
math.Random _random = new math.Random();
|
|
|
|
bool printed = false;
|
|
|
|
// Random methods
|
|
|
|
double randomDouble() {
|
|
return _random.nextDouble();
|
|
}
|
|
|
|
double randomSignedDouble() {
|
|
return _random.nextDouble() * 2.0 - 1.0;
|
|
}
|
|
|
|
int randomInt(int max) {
|
|
return _random.nextInt(max);
|
|
}
|