mirror of
https://github.com/Pomax/BezierInfo-2.git
synced 2025-08-25 09:30:52 +02:00
updated 3d normals
This commit is contained in:
@@ -9,7 +9,59 @@ function normalize(v) {
|
||||
return { x:v.x/d, y:v.y/d, z:v.z/d };
|
||||
}
|
||||
|
||||
function vdot(v1, v2) {
|
||||
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
|
||||
}
|
||||
|
||||
function vscale(v1, s) {
|
||||
return {
|
||||
x: s * v1.x,
|
||||
y: s * v1.y,
|
||||
z: s * v1.z
|
||||
};
|
||||
}
|
||||
|
||||
function vplus(v1, v2) {
|
||||
return {
|
||||
x: v1.x + v2.x,
|
||||
y: v1.y + v2.y,
|
||||
z: v1.z + v2.z
|
||||
};
|
||||
}
|
||||
|
||||
function vminus(v1, v2) {
|
||||
return {
|
||||
x: v1.x - v2.x,
|
||||
y: v1.y - v2.y,
|
||||
z: v1.z - v2.z
|
||||
};
|
||||
}
|
||||
|
||||
function vcross(v1, v2) {
|
||||
return {
|
||||
x: v1.y * v2.z - v1.z * v2.y,
|
||||
y: v1.z * v2.x - v1.x * v2.z,
|
||||
z: v1.x * v2.y - v1.y * v2.x
|
||||
};
|
||||
}
|
||||
|
||||
function vlerp(t, v1, v2) {
|
||||
return {
|
||||
x: (1-t)*v1.x + t*v2.x,
|
||||
y: (1-t)*v1.y + t*v2.y,
|
||||
z: (1-t)*v1.z + t*v2.z
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
setup: function(api) {
|
||||
vectorOffset = {
|
||||
x: 2 * api.getPanelWidth() / 5,
|
||||
y: 4 * api.getPanelHeight() / 5
|
||||
};
|
||||
api.setSize(1.25 * api.getPanelWidth(),api.getPanelHeight());
|
||||
},
|
||||
|
||||
drawCube: function(api) {
|
||||
var prj = p => api.project(p, vectorOffset);
|
||||
|
||||
@@ -78,40 +130,66 @@ module.exports = {
|
||||
api.drawCurve({ points: curve2d });
|
||||
},
|
||||
|
||||
getVectors: function(d1curve, t) {
|
||||
var dt, a, ddt, d, r, R, n;
|
||||
// get the normalized tangent
|
||||
dt = d1curve.get(t);
|
||||
|
||||
// and then let's work in the change in tangent
|
||||
a = d1curve.derivative(t);
|
||||
ddt = { x: dt.x + a.x, y: dt.y + a.y, z: dt.z + a.z };
|
||||
|
||||
// compute the crossproduct, and normalize it
|
||||
r = {
|
||||
x: ddt.y * dt.z - ddt.z * dt.y,
|
||||
y: ddt.z * dt.x - ddt.x * dt.z,
|
||||
z: ddt.x * dt.y - ddt.y * dt.x
|
||||
};
|
||||
d = Math.sqrt(r.x*r.x + r.y*r.y + r.z*r.z);
|
||||
r = { x: r.x/d, y: r.y/d, z: r.z/d };
|
||||
|
||||
// compute the normal, which should not need renormalization
|
||||
R = [
|
||||
r.x*r.x, r.x*r.y -r.z, r.x*r.z + r.y,
|
||||
r.x*r.y + r.z, r.y*r.y, r.y*r.z - r.x,
|
||||
r.x*r.z - r.y, r.y*r.z + r.x, r.z*r.z
|
||||
];
|
||||
n = {
|
||||
x: dt.x * R[0] + dt.y * R[1] + dt.z * R[2],
|
||||
y: dt.x * R[3] + dt.y * R[4] + dt.z * R[5],
|
||||
z: dt.x * R[6] + dt.y * R[7] + dt.z * R[8]
|
||||
};
|
||||
|
||||
return { dt, a, ddt, r, R, n };
|
||||
getFrenetVectors: function(t, curve, d1curve) {
|
||||
var o = curve.get(t),
|
||||
// get the normalized tangent
|
||||
dt = d1curve.get(t),
|
||||
// and then let's work in the change in tangent
|
||||
ddt = d1curve.derivative(t),
|
||||
b = normalize(vplus(dt, ddt)),
|
||||
// compute the normalized axis of rotation
|
||||
r = normalize(vcross(b, dt)),
|
||||
// compute the normal
|
||||
n = normalize(vcross(r, dt));
|
||||
return { o, dt, r, n };
|
||||
},
|
||||
|
||||
drawVector: function(api, from, to, len, r,g,b, project) {
|
||||
lerpVectors(t, v1, v2) {
|
||||
var v = {};
|
||||
['o', 'dt', 'r', 'n'].forEach(p => {
|
||||
v[p] = vlerp(t, v1[p], v2[p]);
|
||||
});
|
||||
return v;
|
||||
},
|
||||
|
||||
generateRMF: function(curve, d1curve) {
|
||||
var frames = [], step = 0.05;
|
||||
frames.push(this.getFrenetVectors(0, curve, d1curve));
|
||||
for(var t0=0; t0<=1; t0+=step) {
|
||||
var x0 = frames.slice(-1)[0],
|
||||
t1 = t0 + step,
|
||||
x1 = { o: curve.get(t1), dt: d1curve.get(t1) },
|
||||
v1 = vminus(x1.o, x0.o),
|
||||
c1 = vdot(v1, v1),
|
||||
riL = vminus(x0.r, vscale(v1, 2/c1 * vdot(v1, x0.r))),
|
||||
tiL = vminus(x0.dt, vscale(v1, 2/c1 * vdot(v1, x0.dt))),
|
||||
v2 = vminus(x1.dt, tiL),
|
||||
c2 = vdot(v2, v2);
|
||||
x1.r = vminus(riL, vscale(v2, 2/c2 * vdot(v2, riL)));
|
||||
x1.n = vcross(x1.r, x1.dt);
|
||||
frames.push(x1); }
|
||||
return frames;
|
||||
},
|
||||
|
||||
getRMF: function(t, curve, d1curve) {
|
||||
if (!this.rmf_LUT) {
|
||||
this.rmf_LUT = this.generateRMF(curve, d1curve);
|
||||
}
|
||||
// find integer index
|
||||
var l = this.rmf_LUT.length;
|
||||
var i = t * l;
|
||||
if (i != (i|0)) {
|
||||
// no intenger index: interpolate values?
|
||||
i = (i|0);
|
||||
if (i===l-1) return this.rmf_LUT[i-1];
|
||||
var j = i + 1, ti = i/l, tj = j/l;
|
||||
t = (t - ti) / (tj - ti);
|
||||
return this.lerpVectors(t, this.rmf_LUT[i], this.rmf_LUT[j]);
|
||||
}
|
||||
return this.rmf_LUT[i];
|
||||
},
|
||||
|
||||
drawVector: function(api, from, to, len, r,g,b) {
|
||||
var prj = p => api.project(p, vectorOffset);
|
||||
to = normalize(to);
|
||||
to = {
|
||||
@@ -122,62 +200,9 @@ module.exports = {
|
||||
api.setColor(`rgba(${r},${g},${b},1)`);
|
||||
// draw the actual vector
|
||||
api.drawLine(prj(from), prj(to));
|
||||
|
||||
if (project) {
|
||||
// and the side projections.
|
||||
api.setColor(`rgba(${r},${g},${b},${SHADOW_ALPHA})`);
|
||||
api.drawLine(api.projectXY(from, vectorOffset), api.projectXY(to, vectorOffset));
|
||||
api.drawLine(api.projectXZ(from, vectorOffset), api.projectXZ(to, vectorOffset));
|
||||
api.drawLine(api.projectYZ(from, vectorOffset), api.projectYZ(to, vectorOffset));
|
||||
}
|
||||
},
|
||||
|
||||
setup: function(api) {
|
||||
vectorOffset = {
|
||||
x: 2 * api.getPanelWidth() / 5,
|
||||
y: 4 * api.getPanelHeight() / 5
|
||||
};
|
||||
api.setSize(1.25 * api.getPanelWidth(),api.getPanelHeight());
|
||||
},
|
||||
|
||||
drawVectors: function(api) {
|
||||
api.reset();
|
||||
var prj = p => api.project(p, vectorOffset);
|
||||
|
||||
this.drawCube(api);
|
||||
|
||||
var curvepoints = [
|
||||
{x:120,y:0,z:0},
|
||||
{x:120,y:220,z:0},
|
||||
{x:30,y:0,z:30},
|
||||
{x:0,y:0,z:200}
|
||||
];
|
||||
|
||||
this.drawCurve(api, curvepoints);
|
||||
|
||||
// let's mark t
|
||||
var curve = new api.Bezier(curvepoints);
|
||||
var d1curve = new api.Bezier(curve.dpoints[0]);
|
||||
var t = Math.max(api.hover.x? api.hover.x / api.getPanelWidth() : 0, 0);
|
||||
var mt = curve.get(t);
|
||||
api.drawCircle(prj(mt), 3);
|
||||
|
||||
// draw the tangent, rotational axis, and normal
|
||||
var vectors = this.getVectors(d1curve, t);
|
||||
this.drawVector(api, mt, vectors.dt, 40, 0,200,0);
|
||||
this.drawVector(api, mt, vectors.r, 40, 0,0,200);
|
||||
this.drawVector(api, mt, vectors.n, 40, 200,0,0);
|
||||
},
|
||||
|
||||
setupNormals: function(api) {
|
||||
normalsOffset = {
|
||||
x: 2 * api.getPanelWidth() / 5,
|
||||
y: 4 * api.getPanelHeight() / 5
|
||||
};
|
||||
api.setSize(1.25 * api.getPanelWidth(),api.getPanelHeight());
|
||||
},
|
||||
|
||||
drawNormals: function(api) {
|
||||
drawFrenetVectors: function(api) {
|
||||
api.reset();
|
||||
var prj = p => api.project(p, vectorOffset);
|
||||
|
||||
@@ -200,9 +225,38 @@ module.exports = {
|
||||
api.drawCircle(prj(mt), 3);
|
||||
|
||||
// draw the tangent, rotational axis, and normal
|
||||
var vectors = this.getVectors(d1curve, t);
|
||||
this.drawVector(api, mt, vectors.dt, 40, 0,200,0, SHOW_PROJECTIONS);
|
||||
this.drawVector(api, mt, vectors.r, 40, 0,0,200, SHOW_PROJECTIONS);
|
||||
this.drawVector(api, mt, vectors.n, 40, 200,0,0, SHOW_PROJECTIONS);
|
||||
var vectors = this.getFrenetVectors(t, curve, d1curve);
|
||||
this.drawVector(api, mt, vectors.dt, 40, 0,200,0);
|
||||
this.drawVector(api, mt, vectors.r, 40, 0,0,200);
|
||||
this.drawVector(api, mt, vectors.n, 40, 200,0,0);
|
||||
},
|
||||
|
||||
drawRMFNormals: function(api) {
|
||||
api.reset();
|
||||
var prj = p => api.project(p, vectorOffset);
|
||||
|
||||
this.drawCube(api);
|
||||
|
||||
var curvepoints = [
|
||||
{x:120,y:0,z:0},
|
||||
{x:120,y:220,z:0},
|
||||
{x:30,y:0,z:30},
|
||||
{x:0,y:0,z:200}
|
||||
];
|
||||
|
||||
this.drawCurve(api, curvepoints, SHOW_PROJECTIONS);
|
||||
|
||||
// let's mark t
|
||||
var curve = new api.Bezier(curvepoints);
|
||||
var d1curve = new api.Bezier(curve.dpoints[0]);
|
||||
var t = Math.max(api.hover.x? api.hover.x / api.getPanelWidth() : 0, 0);
|
||||
var mt = curve.get(t);
|
||||
api.drawCircle(prj(mt), 3);
|
||||
|
||||
// draw the tangent, rotational axis, and normal
|
||||
var vectors = this.getRMF(t, curve, d1curve);
|
||||
this.drawVector(api, mt, vectors.dt, 40, 0,200,0);
|
||||
this.drawVector(api, mt, vectors.r, 40, 0,0,200);
|
||||
this.drawVector(api, mt, vectors.n, 40, 200,0,0);
|
||||
}
|
||||
};
|
||||
|
Reference in New Issue
Block a user