Skip to content
Snippets Groups Projects
Commit 301a23b1 authored by Alexander Rose's avatar Alexander Rose
Browse files

refactored cellpack curve to resuse Vec3 objects

parent e53bb51f
No related branches found
No related tags found
No related merge requests found
...@@ -14,31 +14,35 @@ interface Frame { ...@@ -14,31 +14,35 @@ interface Frame {
s: Vec3, s: Vec3,
} }
function CubicInterpolate(y0: Vec3, y1: Vec3, y2: Vec3, y3: Vec3, mu: number): Vec3 { const a0Tmp = Vec3()
const out = Vec3.zero() const a1Tmp = Vec3()
const a2Tmp = Vec3()
const a3Tmp = Vec3()
function CubicInterpolate(out: Vec3, y0: Vec3, y1: Vec3, y2: Vec3, y3: Vec3, mu: number): Vec3 {
const mu2 = mu * mu; const mu2 = mu * mu;
const a0 = Vec3() Vec3.sub(a0Tmp, y3, y2)
const a1 = Vec3() Vec3.sub(a0Tmp, a0Tmp, y0)
const a2 = Vec3() Vec3.add(a0Tmp, a0Tmp, y1)
const a3 = Vec3()
Vec3.sub(a0, y3, y2)
Vec3.sub(a0, a0, y0)
Vec3.add(a0, a0, y1)
Vec3.sub(a1, y0, y1) Vec3.sub(a1Tmp, y0, y1)
Vec3.sub(a1, a1, a0) Vec3.sub(a1Tmp, a1Tmp, a0Tmp)
Vec3.sub(a2, y2, y0) Vec3.sub(a2Tmp, y2, y0)
Vec3.copy(a3, y1) Vec3.copy(a3Tmp, y1)
out[0] = a0[0] * mu * mu2 + a1[0] * mu2 + a2[0] * mu + a3[0] out[0] = a0Tmp[0] * mu * mu2 + a1Tmp[0] * mu2 + a2Tmp[0] * mu + a3Tmp[0]
out[1] = a0[1] * mu * mu2 + a1[1] * mu2 + a2[1] * mu + a3[1] out[1] = a0Tmp[1] * mu * mu2 + a1Tmp[1] * mu2 + a2Tmp[1] * mu + a3Tmp[1]
out[2] = a0[2] * mu * mu2 + a1[2] * mu2 + a2[2] * mu + a3[2] out[2] = a0Tmp[2] * mu * mu2 + a1Tmp[2] * mu2 + a2Tmp[2] * mu + a3Tmp[2]
return out return out
} }
const cp0 = Vec3()
const cp1 = Vec3()
const cp2 = Vec3()
const cp3 = Vec3()
const currentPosition = Vec3()
function ResampleControlPoints(points: NumberArray, segmentLength: number) { function ResampleControlPoints(points: NumberArray, segmentLength: number) {
const nP = points.length / 3 const nP = points.length / 3
// insert a point at the end and at the begining // insert a point at the end and at the begining
...@@ -50,23 +54,28 @@ function ResampleControlPoints(points: NumberArray, segmentLength: number) { ...@@ -50,23 +54,28 @@ function ResampleControlPoints(points: NumberArray, segmentLength: number) {
// resampledControlPoints.Add(controlPoints[1]); // resampledControlPoints.Add(controlPoints[1]);
let idx = 1 let idx = 1
let currentPosition = Vec3.create(points[idx * 3], points[idx * 3 + 1], points[idx * 3 + 2]) // const currentPosition = Vec3.create(points[idx * 3], points[idx * 3 + 1], points[idx * 3 + 2])
Vec3.fromArray(currentPosition, points, idx * 3)
let lerpValue = 0.0 let lerpValue = 0.0
// Normalize the distance between control points // Normalize the distance between control points
while (true) { while (true) {
if (idx + 2 >= nP) break if (idx + 2 >= nP) break
const cp0 = Vec3.create(points[(idx-1)*3], points[(idx-1)*3+1], points[(idx-1)*3+2]) // controlPoints[currentPointId - 1]; Vec3.fromArray(cp0, points, (idx - 1) * 3)
const cp1 = Vec3.create(points[idx*3], points[idx*3+1], points[idx*3+2]) // controlPoints[currentPointId]; Vec3.fromArray(cp1, points, idx * 3)
const cp2 = Vec3.create(points[(idx+1)*3], points[(idx+1)*3+1], points[(idx+1)*3+2]) // controlPoints[currentPointId + 1]; Vec3.fromArray(cp2, points, (idx + 1) * 3)
const cp3 = Vec3.create(points[(idx+2)*3], points[(idx+2)*3+1], points[(idx+2)*3+2]); // controlPoints[currentPointId + 2]; Vec3.fromArray(cp3, points, (idx + 2) * 3)
// const cp0 = Vec3.create(points[(idx-1)*3], points[(idx-1)*3+1], points[(idx-1)*3+2]) // controlPoints[currentPointId - 1];
// const cp1 = Vec3.create(points[idx*3], points[idx*3+1], points[idx*3+2]) // controlPoints[currentPointId];
// const cp2 = Vec3.create(points[(idx+1)*3], points[(idx+1)*3+1], points[(idx+1)*3+2]) // controlPoints[currentPointId + 1];
// const cp3 = Vec3.create(points[(idx+2)*3], points[(idx+2)*3+1], points[(idx+2)*3+2]); // controlPoints[currentPointId + 2];
let found = false let found = false
for (; lerpValue <= 1; lerpValue += 0.01) { for (; lerpValue <= 1; lerpValue += 0.01) {
// lerp?slerp // lerp?slerp
// let candidate:Vec3 = Vec3.lerp(Vec3.zero(), cp0, cp1, lerpValue); // let candidate:Vec3 = Vec3.lerp(Vec3.zero(), cp0, cp1, lerpValue);
// const candidate:Vec3 = Vec3.bezier(Vec3.zero(), cp0, cp1, cp2, cp3, lerpValue); // const candidate:Vec3 = Vec3.bezier(Vec3.zero(), cp0, cp1, cp2, cp3, lerpValue);
const candidate = CubicInterpolate(cp0, cp1, cp2, cp3, lerpValue) const candidate = CubicInterpolate(Vec3(), cp0, cp1, cp2, cp3, lerpValue)
const d = Vec3.distance(currentPosition, candidate); const d = Vec3.distance(currentPosition, candidate);
if (d > segmentLength) { if (d > segmentLength) {
resampledControlPoints.push(candidate) resampledControlPoints.push(candidate)
...@@ -83,6 +92,12 @@ function ResampleControlPoints(points: NumberArray, segmentLength: number) { ...@@ -83,6 +92,12 @@ function ResampleControlPoints(points: NumberArray, segmentLength: number) {
return resampledControlPoints return resampledControlPoints
} }
const prevV = Vec3()
const tmpV1 = Vec3()
const tmpV2 = Vec3()
const tmpV3 = Vec3()
// easier to align to theses normals // easier to align to theses normals
function GetSmoothNormals(points: Vec3[]) { function GetSmoothNormals(points: Vec3[]) {
const nP: number = points.length; const nP: number = points.length;
...@@ -92,79 +107,99 @@ function GetSmoothNormals(points: Vec3[]) { ...@@ -92,79 +107,99 @@ function GetSmoothNormals(points: Vec3[]) {
smoothNormals.push(Vec3.normalize(Vec3(), points[i])) smoothNormals.push(Vec3.normalize(Vec3(), points[i]))
return smoothNormals; return smoothNormals;
} }
let p0 = Vec3.copy(Vec3(), points[0]) // undefined? let p0 = points[0]
let p1 = Vec3.copy(Vec3(), points[1]) let p1 = points[1]
let p2 = Vec3.copy(Vec3(), points[2]) let p2 = points[2]
const p21 = Vec3.sub(Vec3(), p2, p1) const p21 = Vec3.sub(tmpV1, p2, p1)
const p01 = Vec3.sub(Vec3(), p0, p1) const p01 = Vec3.sub(tmpV2, p0, p1)
const p0121 = Vec3.cross(Vec3(), p01, p21) const p0121 = Vec3.cross(tmpV3, p01, p21)
let last = Vec3.normalize(Vec3(), p0121) Vec3.normalize(prevV, p0121)
smoothNormals.push(last) smoothNormals.push(Vec3.clone(prevV))
for (let i = 1; i < points.length - 1; ++i) { for (let i = 1; i < points.length - 1; ++i) {
p0 = points[i - 1] p0 = points[i - 1]
p1 = points[i] p1 = points[i]
p2 = points[i + 1] p2 = points[i + 1]
const t = Vec3.normalize(Vec3(), Vec3.sub(Vec3(), p2 , p0)) const t = Vec3.normalize(tmpV1, Vec3.sub(tmpV1, p2 , p0))
const b = Vec3.normalize(Vec3(), Vec3.cross(Vec3(), t, last)) const b = Vec3.normalize(tmpV2, Vec3.cross(tmpV2, t, prevV))
let n = Vec3.normalize(Vec3(), Vec3.cross(Vec3(), t, b)) const n = Vec3.normalize(Vec3(), Vec3.cross(tmpV3, t, b))
n = Vec3.scale(n, n, -1.0) Vec3.negate(n, n)
last = Vec3.copy(last, n) Vec3.copy(prevV, n)
smoothNormals.push(n) smoothNormals.push(n)
} }
last = Vec3.normalize(Vec3(), Vec3.cross(Vec3(), Vec3.sub(Vec3(), points[nP - 3], points[nP-2]), Vec3.sub(Vec3(), points[nP-2] , points[nP-1]))) const last = Vec3()
Vec3.normalize(last, Vec3.cross(last,
Vec3.sub(tmpV1, points[nP - 3], points[nP-2]),
Vec3.sub(tmpV2, points[nP-2] , points[nP-1]))
)
smoothNormals.push(last) smoothNormals.push(last)
return smoothNormals; return smoothNormals;
} }
const frameTmpV1 = Vec3()
const frameTmpV2 = Vec3()
const frameTmpV3 = Vec3()
function getFrame(reference: Vec3, tangent: Vec3) { function getFrame(reference: Vec3, tangent: Vec3) {
const t: Vec3 = Vec3.normalize(Vec3(), tangent); const t = Vec3.normalize(Vec3(), tangent);
// make reference vector orthogonal to tangent // make reference vector orthogonal to tangent
const proj_r_to_t: Vec3 = Vec3.scale( const proj_r_to_t = Vec3.scale(
Vec3(), tangent, Vec3.dot(reference, tangent) / Vec3.dot(tangent, tangent) frameTmpV1, tangent, Vec3.dot(reference, tangent) / Vec3.dot(tangent, tangent)
) )
const r: Vec3 = Vec3.normalize(Vec3(), Vec3.sub(Vec3(), reference , proj_r_to_t)) const r = Vec3.normalize(Vec3(), Vec3.sub(frameTmpV2, reference, proj_r_to_t))
// make bitangent vector orthogonal to the others // make bitangent vector orthogonal to the others
const s: Vec3 = Vec3.normalize(Vec3(), Vec3.cross(Vec3(), t, r)) const s = Vec3.normalize(Vec3(), Vec3.cross(frameTmpV3, t, r))
return { t, r, s } return { t, r, s }
} }
const mfTmpV1 = Vec3()
const mfTmpV2 = Vec3()
const mfTmpV3 = Vec3()
const mfTmpV4 = Vec3()
const mfTmpV5 = Vec3()
const mfTmpV6 = Vec3()
const mfTmpV7 = Vec3()
const mfTmpV8 = Vec3()
const mfTmpV9 = Vec3()
// easier to align to theses normals // easier to align to theses normals
// https://github.com/bzamecnik/gpg/blob/master/rotation-minimizing-frame/rmf.py // https://github.com/bzamecnik/gpg/blob/master/rotation-minimizing-frame/rmf.py
function GetMiniFrame(points: Vec3[], normals: Vec3[]) { function GetMiniFrame(points: Vec3[], normals: Vec3[]) {
const frames: Frame[] = []; const frames: Frame[] = [];
const t0: Vec3 = Vec3.normalize(Vec3(), Vec3.sub(Vec3(), points[1], points[0])) const t0 = Vec3.normalize(mfTmpV1, Vec3.sub(mfTmpV1, points[1], points[0]))
frames.push(getFrame(normals[0], t0)) frames.push(getFrame(normals[0], t0))
for (let i = 0; i< points.length-2; ++i) { for (let i = 0; i< points.length-2; ++i) {
const t2 = Vec3.normalize(Vec3(), Vec3.sub(Vec3(), points[i+2], points[i+1])) const t2 = Vec3.normalize(mfTmpV1, Vec3.sub(mfTmpV1, points[i+2], points[i+1]))
const v1: Vec3 = Vec3.sub(Vec3(), points[i + 1], points[i]) // this is tangeant const v1 = Vec3.sub(mfTmpV2, points[i + 1], points[i]) // this is tangeant
const c1 = Vec3.dot(v1, v1) const c1 = Vec3.dot(v1, v1)
// compute r_i^L = R_1 * r_i // compute r_i^L = R_1 * r_i
const v1r = Vec3.scale(Vec3(), v1, (2.0/c1)*Vec3.dot(v1, frames[i].r)) const v1r = Vec3.scale(mfTmpV3, v1, (2.0 / c1) * Vec3.dot(v1, frames[i].r))
const ref_L_i: Vec3 = Vec3.sub(Vec3(), frames[i].r, v1r) const ref_L_i = Vec3.sub(mfTmpV4, frames[i].r, v1r)
// compute t_i^L = R_1 * t_i // compute t_i^L = R_1 * t_i
const v1t = Vec3.scale(Vec3(), v1, (2.0/c1) * Vec3.dot(v1, frames[i].t)) const v1t = Vec3.scale(mfTmpV5, v1, (2.0 / c1) * Vec3.dot(v1, frames[i].t))
const tan_L_i: Vec3 = Vec3.sub(Vec3(), frames[i].t, v1t) const tan_L_i = Vec3.sub(mfTmpV6, frames[i].t, v1t)
// # compute reflection vector of R_2 // # compute reflection vector of R_2
const v2: Vec3 = Vec3.sub(Vec3(), t2 , tan_L_i) const v2 = Vec3.sub(mfTmpV7, t2 , tan_L_i)
const c2 = Vec3.dot(v2, v2) const c2 = Vec3.dot(v2, v2)
// compute r_(i+1) = R_2 * r_i^L // compute r_(i+1) = R_2 * r_i^L
const v2l = Vec3.scale(Vec3(), v1, (2.0/c2) * Vec3.dot(v2, ref_L_i)) const v2l = Vec3.scale(mfTmpV8, v1, (2.0/c2) * Vec3.dot(v2, ref_L_i))
const ref_next = Vec3.sub(Vec3(), ref_L_i, v2l) // ref_L_i - (2 / c2) * v2.dot(ref_L_i) * v2 const ref_next = Vec3.sub(mfTmpV9, ref_L_i, v2l) // ref_L_i - (2 / c2) * v2.dot(ref_L_i) * v2
frames.push(getFrame(ref_next, t2)) // frames.append(Frame(ref_next, tangents[i+1])) frames.push(getFrame(ref_next, t2)) // frames.append(Frame(ref_next, tangents[i+1]))
} }
return frames; return frames;
} }
const rpTmpVec1 = Vec3()
export function getMatFromResamplePoints(points: NumberArray) { export function getMatFromResamplePoints(points: NumberArray) {
let segmentLength = 3.4 const segmentLength = 3.4
let new_points: Vec3[] = ResampleControlPoints(points, 3.4) const new_points = ResampleControlPoints(points, 3.4)
const npoints = new_points.length const npoints = new_points.length
let new_normal: Vec3[] = GetSmoothNormals(new_points) const new_normal = GetSmoothNormals(new_points)
let frames: Frame[] = GetMiniFrame(new_points, new_normal) const frames = GetMiniFrame(new_points, new_normal)
const limit = npoints const limit = npoints
let transforms: Mat4[] = [] const transforms: Mat4[] = []
let pti: Vec3 = Vec3.copy(Vec3(), new_points[0]); const pti = Vec3.copy(rpTmpVec1, new_points[0]);
// console.log(new_points.length) // console.log(new_points.length)
// console.log(points.length/3) // console.log(points.length/3)
// console.log(limit) // console.log(limit)
...@@ -174,9 +209,9 @@ export function getMatFromResamplePoints(points: NumberArray) { ...@@ -174,9 +209,9 @@ export function getMatFromResamplePoints(points: NumberArray) {
const d = Vec3.distance(pti, pti1) const d = Vec3.distance(pti, pti1)
if (d >= segmentLength) { if (d >= segmentLength) {
// use twist or random? // use twist or random?
const quat: Quat = Quat.rotationTo(Quat.zero(), Vec3.create(0, 0, 1), frames[i].t) // Quat.rotationTo(Quat.zero(), Vec3.create(0,0,1),new_normal[i]);//Quat.rotationTo(Quat.zero(), Vec3.create(0,0,1),direction);new_normal const quat = Quat.rotationTo(Quat.zero(), Vec3.create(0, 0, 1), frames[i].t) // Quat.rotationTo(Quat.zero(), Vec3.create(0,0,1),new_normal[i]);//Quat.rotationTo(Quat.zero(), Vec3.create(0,0,1),direction);new_normal
const rq: Quat = Quat.setAxisAngle(Quat.zero(), frames[i].t, Math.random()*3.60 ) // Quat.setAxisAngle(Quat.zero(),direction, Math.random()*3.60 );//Quat.identity();// const rq = Quat.setAxisAngle(Quat.zero(), frames[i].t, Math.random()*3.60 ) // Quat.setAxisAngle(Quat.zero(),direction, Math.random()*3.60 );//Quat.identity();//
let m: Mat4 = Mat4.fromQuat(Mat4.zero(), Quat.multiply(Quat.zero(), rq, quat)) // Mat4.fromQuat(Mat4.zero(),Quat.multiply(Quat.zero(),quat1,quat2));//Mat4.fromQuat(Mat4.zero(),quat);//Mat4.identity();//Mat4.fromQuat(Mat4.zero(),Quat.multiply(Quat.zero(),rq,quat)); const m = Mat4.fromQuat(Mat4.zero(), Quat.multiply(Quat.zero(), rq, quat)) // Mat4.fromQuat(Mat4.zero(),Quat.multiply(Quat.zero(),quat1,quat2));//Mat4.fromQuat(Mat4.zero(),quat);//Mat4.identity();//Mat4.fromQuat(Mat4.zero(),Quat.multiply(Quat.zero(),rq,quat));
// let pos:Vec3 = Vec3.add(Vec3.zero(),pti1,pti) // let pos:Vec3 = Vec3.add(Vec3.zero(),pti1,pti)
// pos = Vec3.scale(pos,pos,1.0/2.0); // pos = Vec3.scale(pos,pos,1.0/2.0);
// Vec3.makeRotation(Mat4.zero(),Vec3.create(0,0,1),frames[i].t);// // Vec3.makeRotation(Mat4.zero(),Vec3.create(0,0,1),frames[i].t);//
...@@ -185,9 +220,9 @@ export function getMatFromResamplePoints(points: NumberArray) { ...@@ -185,9 +220,9 @@ export function getMatFromResamplePoints(points: NumberArray) {
// let q:Quat = Quat.rotationTo(Quat.zero(), Vec3.create(0,1,0),Vec3.create(0,0,1)) // let q:Quat = Quat.rotationTo(Quat.zero(), Vec3.create(0,1,0),Vec3.create(0,0,1))
// m2=Mat4.mul(Mat4.identity(),Mat4.fromQuat(Mat4.zero(),q),m2); // m2=Mat4.mul(Mat4.identity(),Mat4.fromQuat(Mat4.zero(),q),m2);
transforms.push(m) transforms.push(m)
pti = Vec3.copy(pti, pti1) Vec3.copy(pti, pti1)
} }
if (transforms.length >= limit) break if (transforms.length >= limit) break
} }
return transforms return transforms
} }
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment