the constraint solver for non auto-intersections now iterates untils the min-error distance is low enough, for now max error is of 1%
This commit is contained in:
@@ -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]
|
||||
// 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
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user