dm3/anchor.js

77 lines
3.0 KiB
JavaScript

class Anchor{
constructor(opt={}){
this.p=opt.p||[0,0,0]
this.a=opt.a||[[1,0,0],[0,1,0]]
this.r=opt.r||[[0,0,0],[0,0,0]]
this.v=opt.v||[0,0,0]
this.forces=[[0,0,0],[0,0,0],[0,0,0]]
this.pr={p:[...this.p],a:[[...this.a[0]],[...this.a[1]],vcross(...this.a)]}
}
update(dt=1){
this.pr={p:[...this.p],a:[[...this.a[0]],[...this.a[1]],vcross(...this.a)]}
for(let i=0;i<2;i++){for(let j=0;j<3;j++){this.r[i][j]+=this.forces[i][j]*dt}}
for(let z=0;z<3;z++){this.v[z]+=this.forces[2][z]*dt}
this.forces=[[0,0,0],[0,0,0],[0,0,0]]
for(let i=0;i<2;i++){for(let j=0;j<3;j++){this.r[i][j]*=cnst.drag.rot;if(i)this.v[j]*=cnst.drag.mov}}
for(let z=0;z<3;z++){this.p[z]+=this.v[z]*dt}
let b=[[...this.a[0]],[...this.a[1]],vcross(...this.a)]
for(let i=0;i<2;i++){for(let j=0;j<3;j++){for(let z=0;z<3;z++){this.a[i][z]+=this.r[i][j]*b[j][z]*dt}}}
this.a[1]=vnorm(vmultf(vcross(this.a[0],vcross(...this.a)),-1))
this.a[0]=vnorm(this.a[0])
}
applyForce(p,d){
this.forces[0][1]-=cnst.inertia.rot*p[1]*d[0]
this.forces[0][1]+=cnst.inertia.rot*p[0]*d[1]
this.forces[0][2]-=cnst.inertia.rot*p[2]*d[0]
this.forces[0][2]+=cnst.inertia.rot*p[0]*d[2]
this.forces[1][0]-=cnst.inertia.rot*p[1]*d[0]
this.forces[1][0]+=cnst.inertia.rot*p[0]*d[1]
this.forces[1][2]-=cnst.inertia.rot*p[2]*d[1]
this.forces[1][2]+=cnst.inertia.rot*p[1]*d[2]
let a=[...this.a,vcross(...this.a)]
for(let i=0;i<3;i++){for(let z=0;z<3;z++){this.forces[2][i]+=cnst.inertia.mov*d[z]*a[z][i]}}
}
applyWorldForce(p,d){
this.applyForce(toGrid(p),absolNormal(d))
}
//clarify: toGrid() is used to convert from world-space to internal grid space, fromGrid() is used to convert from internal grid space back to world space
toGrid(p){
let a=[p[0]-this.p[0],p[1]-this.p[1],p[2]-this.p[2]]
return [vdot(a,this.a[0]),vdot(a,this.a[1]),vdot(a,vcross(...this.a))]
}
fromGrid(p){
let a=[...this.p],b=[...this.a,vcross(...this.a)]
for(let z=0;z<3;z++){for(let i=0;i<3;i++){a[i]+=b[z][i]*p[z]}}
return a
}
//clarify: absolNormal() converts a world-space vector to a grid-space vector, for example you can use to apply a constant upwards force independent of rotation
//gridNormal() can be used to display a grid-space vector in world-space
absolNormal(p){
return [vdot(p,this.a[0]),vdot(p,this.a[1]),vdot(p,vcross(...this.a))]
}
gridNormal(p){
let a=[0,0,0],b=[...this.a,vcross(...this.a)]
for(let z=0;z<3;z++){for(let i=0;i<3;i++){a[i]+=b[z][i]*p[z]}}
return a
}
pr_toGrid(p){
let a=[p[0]-this.pr.p[0],p[1]-this.pr.p[1],p[2]-this.pr.p[2]]
return [vdot(a,this.pr.a[0]),vdot(a,this.pr.a[1]),vdot(a,vcross(...this.pr.a))]
}
pr_fromGrid(p){
let a=[...this.pr.p],b=[...this.pr.a,vcross(...this.pr.a)]
for(let z=0;z<3;z++){for(let i=0;i<3;i++){a[i]+=b[z][i]*p[z]}}
return a
}
pr_absolNormal(p){
return [vdot(p,this.pr.a[0]),vdot(p,this.pr.a[1]),vdot(p,vcross(...this.pr.a))]
}
pr_gridNormal(p){
let a=[0,0,0],b=[...this.pr.a,vcross(...this.pr.a)]
for(let z=0;z<3;z++){for(let i=0;i<3;i++){a[i]+=b[z][i]*p[z]}}
return a
}
}