verlet gravity first cut
This commit is contained in:
parent
429357469d
commit
3b2122d2e6
@ -14,12 +14,12 @@ export const VELOCITY_VECTOR_COLOR = 'rgb(150, 150, 150)'; // optionally set to
|
|||||||
export const VELOCITY_VECTOR_WIDTH = 1.5;
|
export const VELOCITY_VECTOR_WIDTH = 1.5;
|
||||||
export const VELOCITY_VECTOR_ARROWHEAD = true;
|
export const VELOCITY_VECTOR_ARROWHEAD = true;
|
||||||
|
|
||||||
export const ACCELERATION_VECTOR_SCALE = 1E-4;
|
export const ACCELERATION_VECTOR_SCALE = 1E-1;
|
||||||
export const ACCELERATION_VECTOR_COLOR = 'rgb(0, 255, 0)'; // optionally set to 'object color'
|
export const ACCELERATION_VECTOR_COLOR = 'rgb(0, 255, 0)'; // optionally set to 'object color'
|
||||||
export const ACCELERATION_VECTOR_WIDTH = 1.5;
|
export const ACCELERATION_VECTOR_WIDTH = 1.5;
|
||||||
export const ACCELERATION_VECTOR_ARROWHEAD = true;
|
export const ACCELERATION_VECTOR_ARROWHEAD = true;
|
||||||
|
|
||||||
export const MOTION_TIME_SCALE = 5E-4;
|
export const MOTION_TIME_SCALE = 5E-5;
|
||||||
export const PAN_VELOCITY_SCALE_FACTOR = 1E-3;
|
export const PAN_VELOCITY_SCALE_FACTOR = 1E-3;
|
||||||
|
|
||||||
export const ARROWHEAD_LENGTH = 7;
|
export const ARROWHEAD_LENGTH = 7;
|
||||||
@ -31,7 +31,7 @@ export const ZOOM_IN_FACTOR = 1;
|
|||||||
export const ZOOM_OUT_FACTOR = -1;
|
export const ZOOM_OUT_FACTOR = -1;
|
||||||
export const SCALE_POWER_MAX = 8;
|
export const SCALE_POWER_MAX = 8;
|
||||||
export const SCALE_POWER_MIN = -8;
|
export const SCALE_POWER_MIN = -8;
|
||||||
export const GRAVITATIONAL_CONSTANT = 1E6;
|
export const GRAVITATIONAL_CONSTANT = 1E5;
|
||||||
|
|
||||||
export const DRAGGABLE_ELEMENT_CLASSNAME = 'lhg-draggable-element';
|
export const DRAGGABLE_ELEMENT_CLASSNAME = 'lhg-draggable-element';
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,7 @@ export class MassObject {
|
|||||||
color = {r: undefined, g: undefined, b: undefined};
|
color = {r: undefined, g: undefined, b: undefined};
|
||||||
created = undefined;
|
created = undefined;
|
||||||
forces = []; // [{x, y}]
|
forces = []; // [{x, y}]
|
||||||
|
active = false;
|
||||||
|
|
||||||
constructor(x, y, index) {
|
constructor(x, y, index) {
|
||||||
this.index = index;
|
this.index = index;
|
||||||
|
|||||||
39
objects.js
39
objects.js
@ -24,7 +24,11 @@ export class Objects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
doneCreatingObject() {
|
doneCreatingObject() {
|
||||||
this.creatingObject = undefined;
|
if (this.creatingObject !== undefined) {
|
||||||
|
const obj = this.objects[this.creatingObject];
|
||||||
|
obj.active = true;
|
||||||
|
this.creatingObject = undefined;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object(i) {
|
object(i) {
|
||||||
@ -119,6 +123,7 @@ export class Objects {
|
|||||||
const A = this.objects[i];
|
const A = this.objects[i];
|
||||||
for (let j = i + 1; j < this.objects.length; j++) {
|
for (let j = i + 1; j < this.objects.length; j++) {
|
||||||
const B = this.objects[j];
|
const B = this.objects[j];
|
||||||
|
if (!A.active || !B.active) continue;
|
||||||
const dx = (B.position.x - A.position.x);
|
const dx = (B.position.x - A.position.x);
|
||||||
const dy = (B.position.y - A.position.y);
|
const dy = (B.position.y - A.position.y);
|
||||||
const dSquared = dx ** 2 + dy ** 2;
|
const dSquared = dx ** 2 + dy ** 2;
|
||||||
@ -145,20 +150,38 @@ export class Objects {
|
|||||||
// Calculate forces due to gravity.
|
// Calculate forces due to gravity.
|
||||||
this.computeForces(elapsedTime);
|
this.computeForces(elapsedTime);
|
||||||
|
|
||||||
// Update velocities. Simple euler method for now.
|
// Generate predicted positions (Velocity verlet method)
|
||||||
for (let i = 0; i < this.objects.length; i++) {
|
for (let i = 0; i < this.objects.length; i++) {
|
||||||
const obj = this.objects[i];
|
const obj = this.objects[i];
|
||||||
const acceleration = obj.acceleration;
|
obj.currentAcceleration = {...obj.acceleration};
|
||||||
obj.velocity.x += acceleration.x * MOTION_TIME_SCALE * elapsedTime;
|
obj.projectedPosition = {
|
||||||
obj.velocity.y += acceleration.y * MOTION_TIME_SCALE * elapsedTime;
|
x: obj.position.x + MOTION_TIME_SCALE * elapsedTime *
|
||||||
|
(obj.velocity.x + 1/2 * obj.currentAcceleration.x * elapsedTime),
|
||||||
|
y: obj.position.y + MOTION_TIME_SCALE * elapsedTime *
|
||||||
|
(obj.velocity.y + 1/2 * obj.currentAcceleration.y * elapsedTime),
|
||||||
|
};
|
||||||
|
obj.currentPosition = {...obj.position};
|
||||||
|
obj.position = obj.projectedPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update positions. Simple Euler method for now.
|
// Recompute forces
|
||||||
|
this.computeForces();
|
||||||
|
|
||||||
|
// Average first and second predicted accelerations
|
||||||
for (let i = 0; i < this.objects.length; i++) {
|
for (let i = 0; i < this.objects.length; i++) {
|
||||||
const obj = this.objects[i];
|
const obj = this.objects[i];
|
||||||
obj.position.x += obj.velocity.x * MOTION_TIME_SCALE * elapsedTime;
|
const acceleration = {...obj.acceleration};
|
||||||
obj.position.y += obj.velocity.y * MOTION_TIME_SCALE * elapsedTime;
|
const meanAcceleration = {
|
||||||
|
x: (obj.currentAcceleration.x + acceleration.x) / 2,
|
||||||
|
y: (obj.currentAcceleration.y + acceleration.y) / 2,
|
||||||
|
};
|
||||||
|
obj.velocity.x += meanAcceleration.x * MOTION_TIME_SCALE * elapsedTime;
|
||||||
|
obj.velocity.y += meanAcceleration.y * MOTION_TIME_SCALE * elapsedTime;
|
||||||
|
|
||||||
|
obj.position.x = obj.currentPosition.x + obj.velocity.x * MOTION_TIME_SCALE * elapsedTime;
|
||||||
|
obj.position.y = obj.currentPosition.y + obj.velocity.y * MOTION_TIME_SCALE * elapsedTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display objects info
|
// Display objects info
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user