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 2 years ago
parent e60008d71a
commit 1dd1c47903

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

@ -61,7 +61,10 @@ class KnotSimulation {
this.ghostPath = []
}
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
}
if (buttons === 4) {
@ -147,35 +150,62 @@ class KnotSimulation {
const next = positions.at((i + 1) % N)
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[i], Vec3.scale(baseForce, jointFactor))
Vec3.Mutate.add(positions.at((i + 1) % N), Vec3.scale(baseForce, -jointFactor / 2))
}
// repulsione per ogni coppia
for (let i = 0; i < N; i++) {
for (let j = 0; j < N; j++) {
if (
i < j &&
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 <= NODE_BALL_RADIUS) {
const [newPt1, newPt2] = enforceDistance(p1, p2, NODE_BALL_RADIUS)
positions[i] = newPt1
positions[j] = newPt2
// the error of the next constraint will be at most of 90%
let globalNodeMinDistance = 0
let iter = 0
while (globalNodeMinDistance < NODE_BALL_RADIUS * 0.99 && iter++ < 100) {
// repulsione per ogni coppia
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 <= 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)
// attrito viscoso

Loading…
Cancel
Save