the constraint solver for non auto-intersections now iterates untils the min-error distance is low enough, for now max error is of 1%

main
Antonio De Lucreziis 3 years ago
parent e60008d71a
commit 1dd1c47903

@ -50,6 +50,22 @@ export const Vec2 = {
const norm = Vec2.norm2([x, y]) const norm = Vec2.norm2([x, y])
return [x / norm, y / norm] return [x / norm, y / norm]
}, },
findNearest(curve, pt) {
let index = -1
let minDist = +Infinity
for (let i = 0; i < curve.length; i++) {
const d = Vec2.distance2(curve[i], pt)
if (d < minDist) {
index = i
minDist = d
}
}
return [index, minDist]
},
} }
export const Vec3 = { export const Vec3 = {
@ -99,9 +115,9 @@ export const Vec3 = {
const norm = Vec3.norm2([x, y, z]) const norm = Vec3.norm2([x, y, z])
return [x / norm, y / norm, z / norm] return [x / norm, y / norm, z / norm]
}, },
findNearest3d(curve, pt) { findNearest(curve, pt) {
let index = 0 let index = -1
let minDist = Infinity let minDist = +Infinity
for (let i = 0; i < curve.length; i++) { for (let i = 0; i < curve.length; i++) {
const d = Vec3.distance2(curve[i], pt) const d = Vec3.distance2(curve[i], pt)

@ -61,7 +61,10 @@ class KnotSimulation {
this.ghostPath = [] this.ghostPath = []
} }
if (buttons === 2) { if (buttons === 2) {
const [i] = Vec3.findNearest3d(this.particleSimulation.positions, [...this.mousePosition, 0]) const [i] = Vec2.findNearest(
this.particleSimulation.positions.map(([x, y]) => [x, y]),
this.mousePosition
)
this.draggingIndex = i this.draggingIndex = i
} }
if (buttons === 4) { if (buttons === 4) {
@ -147,35 +150,62 @@ class KnotSimulation {
const next = positions.at((i + 1) % N) const next = positions.at((i + 1) % N)
const baseForce = Vec3.scale(Vec3.add(Vec3.sub(prev, curr), Vec3.sub(next, curr)), 0.5) const baseForce = Vec3.scale(Vec3.add(Vec3.sub(prev, curr), Vec3.sub(next, curr)), 0.5)
const jointFactor = 0.5 const jointFactor = 0.1
Vec3.Mutate.add(positions.at((i - 1) % N), Vec3.scale(baseForce, -jointFactor / 2)) Vec3.Mutate.add(positions.at((i - 1) % N), Vec3.scale(baseForce, -jointFactor / 2))
Vec3.Mutate.add(positions[i], Vec3.scale(baseForce, jointFactor)) Vec3.Mutate.add(positions[i], Vec3.scale(baseForce, jointFactor))
Vec3.Mutate.add(positions.at((i + 1) % N), Vec3.scale(baseForce, -jointFactor / 2)) Vec3.Mutate.add(positions.at((i + 1) % N), Vec3.scale(baseForce, -jointFactor / 2))
} }
// repulsione per ogni coppia // the error of the next constraint will be at most of 90%
for (let i = 0; i < N; i++) { let globalNodeMinDistance = 0
for (let j = 0; j < N; j++) { let iter = 0
if ( while (globalNodeMinDistance < NODE_BALL_RADIUS * 0.99 && iter++ < 100) {
i < j && // repulsione per ogni coppia
Math.abs(i - j) > PASSTHROUGH_MIN_INDICES && for (let i = 0; i < N; i++) {
Math.abs(i - j + N) > PASSTHROUGH_MIN_INDICES && for (let j = i + 1; j < N; j++) {
Math.abs(i - j - N) > PASSTHROUGH_MIN_INDICES if (
) { Math.abs(i - j) > PASSTHROUGH_MIN_INDICES &&
const p1 = positions[i] Math.abs(i - j + N) > PASSTHROUGH_MIN_INDICES &&
const p2 = positions[j] Math.abs(i - j - N) > PASSTHROUGH_MIN_INDICES
) {
const dist = Vec3.distance2(p1, p2) const p1 = positions[i]
if (dist <= NODE_BALL_RADIUS) { const p2 = positions[j]
const [newPt1, newPt2] = enforceDistance(p1, p2, NODE_BALL_RADIUS)
positions[i] = newPt1 const dist = Vec3.distance2(p1, p2)
positions[j] = newPt2 if (dist <= NODE_BALL_RADIUS) {
const [newPt1, newPt2] = enforceDistance(p1, p2, NODE_BALL_RADIUS)
positions[i] = newPt1
positions[j] = newPt2
}
}
}
}
// estimating global previous constraint error
globalNodeMinDistance = +Infinity
for (let i = 0; i < N; i++) {
for (let j = i + 1; j < N; j++) {
if (
Math.abs(i - j) > PASSTHROUGH_MIN_INDICES &&
Math.abs(i - j + N) > PASSTHROUGH_MIN_INDICES &&
Math.abs(i - j - N) > PASSTHROUGH_MIN_INDICES
) {
const p1 = positions[i]
const p2 = positions[j]
const dist = Vec3.distance2(p1, p2)
if (dist < globalNodeMinDistance) {
globalNodeMinDistance = dist
}
} }
} }
} }
} }
console.log(`Reached solution in ${iter} iterations with global min distance ${globalNodeMinDistance}`)
this.particleSimulation.update(newAccelerations) this.particleSimulation.update(newAccelerations)
// attrito viscoso // attrito viscoso

Loading…
Cancel
Save