mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 12:57:59 +02:00
Removing edge finding calculations
This commit is contained in:
parent
ebb530aaac
commit
cffb0be384
7 changed files with 47 additions and 418 deletions
|
@ -16,7 +16,7 @@ Script.include("magSticks/handController.js");
|
||||||
var magBalls = new MagBalls();
|
var magBalls = new MagBalls();
|
||||||
|
|
||||||
// Clear any previous balls
|
// Clear any previous balls
|
||||||
magBalls.clear();
|
// magBalls.clear();
|
||||||
|
|
||||||
// How close do we need to be to a ball to select it.... radius + 10%
|
// How close do we need to be to a ball to select it.... radius + 10%
|
||||||
var BALL_SELECTION_RADIUS = BALL_SIZE / 2.0 * 1.5;
|
var BALL_SELECTION_RADIUS = BALL_SIZE / 2.0 * 1.5;
|
||||||
|
|
|
@ -1,3 +1,10 @@
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 2015/08/29
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
// A collection of nodes and edges connecting them.
|
// A collection of nodes and edges connecting them.
|
||||||
Graph = function() {
|
Graph = function() {
|
||||||
|
|
|
@ -1,28 +1,14 @@
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 2015/08/29
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
LEFT_CONTROLLER = 0;
|
LEFT_CONTROLLER = 0;
|
||||||
RIGHT_CONTROLLER = 1;
|
RIGHT_CONTROLLER = 1;
|
||||||
|
|
||||||
WAND_LIFETIME = 30;
|
// FIXME add a customizable wand model and a mechanism to switch between wands
|
||||||
|
|
||||||
var WAND_PROPERTIES = {
|
|
||||||
type: "Model",
|
|
||||||
modelURL: "file:///f:/Downloads/wand.FBX",
|
|
||||||
ignoreForCollisions: true,
|
|
||||||
dimensions: {
|
|
||||||
x: 0.1,
|
|
||||||
y: 0.1,
|
|
||||||
z: 0.1
|
|
||||||
},
|
|
||||||
lifetime: 30
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!Date.now) {
|
|
||||||
Date.now = function now() {
|
|
||||||
return new Date().getTime();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
HandController = function(side) {
|
HandController = function(side) {
|
||||||
this.side = side;
|
this.side = side;
|
||||||
this.palm = 2 * side;
|
this.palm = 2 * side;
|
||||||
|
@ -38,9 +24,7 @@ HandController = function(side) {
|
||||||
solid: true,
|
solid: true,
|
||||||
visible: false,
|
visible: false,
|
||||||
});
|
});
|
||||||
//this.wand = Entities.addEntity(WAND_PROPERTIES);
|
|
||||||
|
|
||||||
|
|
||||||
// Connect to desired events
|
// Connect to desired events
|
||||||
var _this = this;
|
var _this = this;
|
||||||
Controller.actionEvent.connect(function(action, state) {
|
Controller.actionEvent.connect(function(action, state) {
|
||||||
|
|
|
@ -1,3 +1,10 @@
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 2015/08/29
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
var SELECTION_OVERLAY = {
|
var SELECTION_OVERLAY = {
|
||||||
position: {
|
position: {
|
||||||
x: 0,
|
x: 0,
|
||||||
|
|
|
@ -1,3 +1,10 @@
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 2015/08/29
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
var BALL_NAME = "MagBall"
|
var BALL_NAME = "MagBall"
|
||||||
var EDGE_NAME = "MagStick"
|
var EDGE_NAME = "MagStick"
|
||||||
|
@ -70,14 +77,7 @@ var EDGE_PROTOTYPE = LINE_PROTOTYPE;
|
||||||
// A collection of balls and edges connecting them.
|
// A collection of balls and edges connecting them.
|
||||||
MagBalls = function() {
|
MagBalls = function() {
|
||||||
this.selectedNodes = {};
|
this.selectedNodes = {};
|
||||||
|
|
||||||
Graph.call(this);
|
Graph.call(this);
|
||||||
|
|
||||||
var _this = this;
|
|
||||||
Script.update.connect(function(deltaTime) {
|
|
||||||
_this.onUpdate(deltaTime);
|
|
||||||
});
|
|
||||||
|
|
||||||
Script.scriptEnding.connect(function() {
|
Script.scriptEnding.connect(function() {
|
||||||
_this.onCleanup();
|
_this.onCleanup();
|
||||||
});
|
});
|
||||||
|
@ -94,10 +94,10 @@ MagBalls.prototype.createNodeEntity = function(customProperies) {
|
||||||
return Entities.addEntity(mergeObjects(BALL_PROTOTYPE, customProperies));
|
return Entities.addEntity(mergeObjects(BALL_PROTOTYPE, customProperies));
|
||||||
}
|
}
|
||||||
|
|
||||||
MagBalls.prototype.getEdgeProperties = function(nodeIdA, nodeIdB) {
|
MagBalls.prototype.createEdgeEntity = function(nodeIdA, nodeIdB) {
|
||||||
var apos = this.getNodePosition(nodeIdA);
|
var apos = this.getNodePosition(nodeIdA);
|
||||||
var bpos = this.getNodePosition(nodeIdB);
|
var bpos = this.getNodePosition(nodeIdB);
|
||||||
return {
|
return Entities.addEntity(mergeObjects(EDGE_PROTOTYPE, {
|
||||||
position: apos,
|
position: apos,
|
||||||
linePoints: [ ZERO_VECTOR, Vec3.subtract(bpos, apos) ],
|
linePoints: [ ZERO_VECTOR, Vec3.subtract(bpos, apos) ],
|
||||||
userData: JSON.stringify({
|
userData: JSON.stringify({
|
||||||
|
@ -107,12 +107,7 @@ MagBalls.prototype.getEdgeProperties = function(nodeIdA, nodeIdB) {
|
||||||
length: BALL_DISTANCE
|
length: BALL_DISTANCE
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
};
|
}));
|
||||||
}
|
|
||||||
|
|
||||||
MagBalls.prototype.createEdgeEntity = function(nodeIdA, nodeIdB) {
|
|
||||||
var customProperties = this.getEdgeProperties(nodeIdA, nodeIdB)
|
|
||||||
return Entities.addEntity(mergeObjects(EDGE_PROTOTYPE, customProperties));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MagBalls.prototype.findPotentialEdges = function(nodeId) {
|
MagBalls.prototype.findPotentialEdges = function(nodeId) {
|
||||||
|
@ -178,340 +173,10 @@ MagBalls.prototype.releaseBall = function(releasedBall) {
|
||||||
for (var otherBallId in targets) {
|
for (var otherBallId in targets) {
|
||||||
this.createEdge(otherBallId, releasedBall);
|
this.createEdge(otherBallId, releasedBall);
|
||||||
}
|
}
|
||||||
this.clean();
|
|
||||||
return;
|
|
||||||
|
|
||||||
// sort other balls by distance from the stick length
|
|
||||||
var createdEdge = false;
|
|
||||||
while (true) {
|
|
||||||
// Get the list of candidate connections
|
|
||||||
var variances = this.findPotentialEdges(releasedBall);
|
|
||||||
// sort them by the difference from an ideal distance
|
|
||||||
var targetBalls = Object.keys(variances);
|
|
||||||
if (!targetBalls.length) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// special case when there are 2 potential matches,
|
|
||||||
// try to create a ring on a plane
|
|
||||||
if (targetBalls.length == 2 && this.tryCreateRing(targetBalls, releasedBall)) {
|
|
||||||
createdEdge = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// special case when there are 3 potential matches,
|
|
||||||
// try create a fan
|
|
||||||
if (targetBalls.length == 3 && this.tryCreateFan(targetBalls, releasedBall)) {
|
|
||||||
createdEdge = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
targetBalls.sort(function(a, b){
|
|
||||||
return variances[a] - variances[b];
|
|
||||||
});
|
|
||||||
|
|
||||||
// find the nearest matching unconnected ball and create an edge to it
|
|
||||||
// if possible
|
|
||||||
// note that createEdge will preferentially move the second entity, the
|
|
||||||
// released ball
|
|
||||||
// in order to create a fit
|
|
||||||
var str = "Attempt to create edge between " + targetBalls[0] + " and " + releasedBall;
|
|
||||||
if (!this.tryCreateEdge(targetBalls[0], releasedBall)) {
|
|
||||||
logDebug(str + "failed");
|
|
||||||
var nodeDistance = this.getNodeDistance(targetBalls[0], releasedBall);
|
|
||||||
var variance = this.getVariance(nodeDistance);
|
|
||||||
logDebug("Distance was " + (nodeDistance * 100).toFixed(2) + "cm with a variance of " + variance);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
logDebug(str + " succeeded");
|
|
||||||
|
|
||||||
releasePosition = this.getNodePosition(releasedBall);
|
|
||||||
|
|
||||||
// Record that we created at least one edge
|
|
||||||
createdEdge = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (createdEdge) {
|
|
||||||
// FIXME play a snap sound
|
|
||||||
}
|
|
||||||
|
|
||||||
this.clean();
|
this.clean();
|
||||||
this.validate();
|
this.validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
MagBalls.prototype.tryCreateEdge = function(from, to) {
|
|
||||||
var fromPos = this.getNodePosition(from);
|
|
||||||
var toPos = this.getNodePosition(to);
|
|
||||||
var vector = Vec3.subtract(toPos, fromPos);
|
|
||||||
var originalLength = Vec3.length(vector);
|
|
||||||
|
|
||||||
var variance = this.getVariance(originalLength);
|
|
||||||
// if they're already at a close enough distance, just create the edge
|
|
||||||
if (variance < EPSILON) {
|
|
||||||
logDebug("Length " + originalLength + " with variance of " + (variance * 100).toFixed(2) + " is within epislon " + EPSILON) ;
|
|
||||||
// close enough for government work
|
|
||||||
this.createEdge(from, to);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME find the constraints on `from` and `to` and determine if there is a
|
|
||||||
// new positiong
|
|
||||||
// for 'to' that keeps it's current connections and connects with 'from'
|
|
||||||
// Do only first order scanning for now, unless we can expose a mechanism
|
|
||||||
// for interacting
|
|
||||||
// to reach equilibrium via Bullet
|
|
||||||
// * a ball zero edges is fully free...
|
|
||||||
// * a ball with one edge free to move on a sphere section
|
|
||||||
// * a ball with two edges is free to move in a circle
|
|
||||||
// * a ball with more than two edges is not free to move
|
|
||||||
|
|
||||||
// Zero edges for the destination
|
|
||||||
var existingEdges = Object.keys(this.nodes[to]);
|
|
||||||
var edgeCount = existingEdges.length;
|
|
||||||
if (!edgeCount) {
|
|
||||||
// Easy case 1: unconnected ball
|
|
||||||
// Move the ball along it's current path to match the desired distance
|
|
||||||
vector = Vec3.multiply(BALL_DISTANCE, Vec3.normalize(vector));
|
|
||||||
// Add the vector to the starting position to find the new position
|
|
||||||
var newPosition = Vec3.sum(vector, fromPos);
|
|
||||||
// update the entity
|
|
||||||
Entities.editEntity(to, { position: newPosition });
|
|
||||||
moved = true;
|
|
||||||
} else if (edgeCount > 2) {
|
|
||||||
// Easy case 2: locked position ball
|
|
||||||
// FIXME should check the target ball to see if it can be moved.
|
|
||||||
// Possible easy solution is to recurse into this.createEdge and swap
|
|
||||||
// the parameters,
|
|
||||||
// but need to prevert infinite recursion
|
|
||||||
// for now...
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
var connectedBalls = this.getConnectedNodes(to);
|
|
||||||
// find the other balls connected, will be either 1 or 2
|
|
||||||
var origin = { x: 0, y: 0, z: 0 };
|
|
||||||
for (var nodeId in connectedBalls) {
|
|
||||||
origin = Vec3.sum(origin, this.getNodePosition(nodeId));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (edgeCount > 1) {
|
|
||||||
origin = Vec3.multiply(origin, 1 / edgeCount);
|
|
||||||
}
|
|
||||||
// logDebug("Using origin " + vec3toStr(origin));
|
|
||||||
|
|
||||||
if (edgeCount == 1) {
|
|
||||||
// vectors from the temp origin to the two balls.
|
|
||||||
var v1 = Vec3.subtract(toPos, origin);
|
|
||||||
var v2 = Vec3.subtract(fromPos, origin);
|
|
||||||
|
|
||||||
// ortogonal to the solution plane
|
|
||||||
var o1 = Vec3.normalize(Vec3.cross(Vec3.normalize(v2), Vec3.normalize(v1)));
|
|
||||||
// addLine(origin, o1, COLORS.RED); // debugging
|
|
||||||
|
|
||||||
// orthogonal to o1, lying on the solution plane
|
|
||||||
var o2 = Vec3.normalize(Vec3.cross(o1, Vec3.normalize(v2)));
|
|
||||||
// addLine(origin, o2, COLORS.YELLOW); // debugging
|
|
||||||
|
|
||||||
// The adjacent side of a right triangle containg the
|
|
||||||
// solution as one of the points
|
|
||||||
var v3 = Vec3.multiply(0.5, v2);
|
|
||||||
|
|
||||||
// The length of the adjacent side of the triangle
|
|
||||||
var l1 = Vec3.length(v3);
|
|
||||||
// The length of the hypotenuse
|
|
||||||
var r = BALL_DISTANCE;
|
|
||||||
|
|
||||||
// No connection possible
|
|
||||||
if (l1 > r) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The length of the opposite side
|
|
||||||
var l2 = Math.sqrt(r * r - l1 * l1);
|
|
||||||
|
|
||||||
// vector with the length and direction of the opposite side
|
|
||||||
var v4 = Vec3.multiply(l2, Vec3.normalize(o2));
|
|
||||||
|
|
||||||
// Add the adjacent vector and the opposite vector to get the
|
|
||||||
// hypotenuse vector
|
|
||||||
var result = Vec3.sum(v3, v4);
|
|
||||||
// move back into world space
|
|
||||||
result = Vec3.sum(origin, result);
|
|
||||||
// update the entity
|
|
||||||
Entities.editEntity(to, { position: result });
|
|
||||||
} else {
|
|
||||||
// Has a bug of some kind... validation fails after this
|
|
||||||
|
|
||||||
// Debugging marker
|
|
||||||
//Entities.addEntity(mergeObjects(BALL_PROTOTYPE, {
|
|
||||||
// position: origin,
|
|
||||||
// color: COLORS.YELLOW,
|
|
||||||
// dimensions: Vec3.multiply(0.4, BALL_DIMENSIONS)
|
|
||||||
//}));
|
|
||||||
|
|
||||||
var v1 = Vec3.subtract(fromPos, origin);
|
|
||||||
// addLine(origin, v1, COLORS.RED); // debugging
|
|
||||||
|
|
||||||
|
|
||||||
var v2 = Vec3.subtract(toPos, origin);
|
|
||||||
// addLine(origin, v2, COLORS.GREEN); // debugging
|
|
||||||
|
|
||||||
// the lengths of v1 and v2 represent the lengths of two sides
|
|
||||||
// of the triangle we need to build.
|
|
||||||
var l1 = Vec3.length(v1);
|
|
||||||
var l2 = Vec3.length(v2);
|
|
||||||
// The remaining side is the edge we are trying to create, so
|
|
||||||
// it will be of length BALL_DISTANCE
|
|
||||||
var l3 = BALL_DISTANCE;
|
|
||||||
// given this triangle, we want to know the angle between l1 and l2
|
|
||||||
// (this is NOT the same as the angle between v1 and v2, because we
|
|
||||||
// are trying to rotate v2 around o1 to find a solution
|
|
||||||
// Use law of cosines to find the angle: cos A = (b^2 + c^2 − a^2) /
|
|
||||||
// 2bc
|
|
||||||
var cosA = (l1 * l1 + l2 * l2 - l3 * l3) / (2.0 * l1 * l2);
|
|
||||||
|
|
||||||
// Having this angle gives us all three angles of the right triangle
|
|
||||||
// containing
|
|
||||||
// the solution, along with the length of the hypotenuse, which is
|
|
||||||
// l2
|
|
||||||
var hyp = l2;
|
|
||||||
// We need to find the length of the adjacent and opposite sides
|
|
||||||
// since cos(A) = adjacent / hypotenuse, then adjacent = hypotenuse
|
|
||||||
// * cos(A)
|
|
||||||
var adj = hyp * cosA;
|
|
||||||
// Pythagoras gives us the opposite side length
|
|
||||||
var opp = Math.sqrt(hyp * hyp - adj * adj);
|
|
||||||
|
|
||||||
// v1 is the direction vector we need for the adjacent side, so
|
|
||||||
// resize it to
|
|
||||||
// the proper length
|
|
||||||
v1 = Vec3.multiply(adj, Vec3.normalize(v1));
|
|
||||||
// addLine(origin, v1, COLORS.GREEN); // debugging
|
|
||||||
|
|
||||||
// FIXME, these are not the right normals, because the ball needs to rotate around the origin
|
|
||||||
|
|
||||||
// This is the normal to the plane on which our solution lies
|
|
||||||
var o1 = Vec3.cross(v1, v2);
|
|
||||||
|
|
||||||
// Our final side is a normal to the plane defined by o1 and v1
|
|
||||||
// and is of length opp
|
|
||||||
var o2 = Vec3.multiply(opp, Vec3.normalize(Vec3.cross(o1, v1)));
|
|
||||||
|
|
||||||
// Our final result is the sum of v1 and o2 (opposite side vector +
|
|
||||||
// adjacent side vector)
|
|
||||||
var result = Vec3.sum(v1, o2);
|
|
||||||
// Move back into world space
|
|
||||||
result = Vec3.sum(origin, result);
|
|
||||||
// update the entity
|
|
||||||
Entities.editEntity(to, { position: result });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fixup existing edges if we moved the ball
|
|
||||||
for (var edgeId in this.nodes[to]) {
|
|
||||||
this.fixupEdge(edgeId);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.createEdge(from, to);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
MagBalls.prototype.tryCreateRing = function(fromBalls, to) {
|
|
||||||
// FIXME, if the user tries to connect two points, attempt to
|
|
||||||
// walk the graph and see if they're creating a ring of 4 or
|
|
||||||
// more vertices, if so and they're within N percent of lying
|
|
||||||
// on a plane, then adjust them all so they lie on a plance
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function pausecomp(millis) {
|
|
||||||
var date = new Date();
|
|
||||||
var curDate = null;
|
|
||||||
do { curDate = new Date(); } while(curDate-date < millis);
|
|
||||||
}
|
|
||||||
|
|
||||||
// find a normal between three points
|
|
||||||
function findNormal(a, b, c) {
|
|
||||||
var aa = Vec3.subtract(a, b);
|
|
||||||
var cc = Vec3.subtract(c, b);
|
|
||||||
return Vec3.cross(aa, cc);
|
|
||||||
}
|
|
||||||
|
|
||||||
MagBalls.prototype.tryCreateFan = function(fromBalls, to) {
|
|
||||||
logDebug("Attempting to create fan");
|
|
||||||
// if the user tries to connect three points, attempt to
|
|
||||||
// walk the graph and see if they're creating fan, adjust all the
|
|
||||||
// points to lie on a plane an equidistant from the shared vertex
|
|
||||||
|
|
||||||
// A fan may exist if given three potential connections, two of the connection
|
|
||||||
// share and edge with the third
|
|
||||||
var a = fromBalls[0];
|
|
||||||
var b = fromBalls[1];
|
|
||||||
var c = fromBalls[2];
|
|
||||||
var ab = this.areConnected(a, b);
|
|
||||||
var bc = this.areConnected(b, c);
|
|
||||||
var ca = this.areConnected(c, a);
|
|
||||||
if (ab && bc && ca) {
|
|
||||||
// tetrahedron, let the generic code handle it
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
var crux = null;
|
|
||||||
var left = null;
|
|
||||||
var right = null;
|
|
||||||
if (ab && bc) {
|
|
||||||
crux = b;
|
|
||||||
left = a;
|
|
||||||
right = c;
|
|
||||||
} else if (bc && ca) {
|
|
||||||
crux = a;
|
|
||||||
left = b;
|
|
||||||
right = a;
|
|
||||||
} else if (ca && ab) {
|
|
||||||
crux = a;
|
|
||||||
left = c;
|
|
||||||
right = b;
|
|
||||||
}
|
|
||||||
if (crux == null) {
|
|
||||||
// we don't have two nodes which share edges with the third, so fail
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
var loop = this.findShortestPath(left, right, { exclude: crux });
|
|
||||||
if (!loop) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// find the normal to the target plane
|
|
||||||
var origin = this.getNodePosition(crux);
|
|
||||||
var normals = [];
|
|
||||||
var averageNormal = ZERO_VECTOR;
|
|
||||||
for (var i = 0; i < loop.length - 2; ++i) {
|
|
||||||
var a = loop[i];
|
|
||||||
var b = loop[i + 1];
|
|
||||||
var c = loop[i + 2];
|
|
||||||
var apos = this.getNodePosition(a);
|
|
||||||
var bpos = this.getNodePosition(b);
|
|
||||||
var cpos = this.getNodePosition(c);
|
|
||||||
var normal = Vec3.normalize(findNormal(apos, bpos, cpos));
|
|
||||||
averageNormal = Vec3.sum(averageNormal, normal);
|
|
||||||
addLine(bpos, normal, COLORS.YELLOW);
|
|
||||||
normals.push(normal);
|
|
||||||
}
|
|
||||||
averageNormal = Vec3.normalize(Vec3.multiply(1 / normals.length, averageNormal));
|
|
||||||
|
|
||||||
addLine(origin, averageNormal, COLORS.RED);
|
|
||||||
|
|
||||||
// FIXME need to account for locked nodes... if there are 3 locked nodes on the loop,
|
|
||||||
// then find their cross product
|
|
||||||
// if there are more than 3 locked nodes on the loop, check if they have matching cross
|
|
||||||
// products, otherwise fail
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
MagBalls.prototype.fixupEdge = function(edgeId) {
|
|
||||||
var ballsInEdge = Object.keys(this.edges[edgeId]);
|
|
||||||
var customProperties = this.getEdgeProperties(ballsInEdge[0], ballsInEdge[1]);
|
|
||||||
Entities.editEntity(edgeId, customProperties);
|
|
||||||
}
|
|
||||||
|
|
||||||
MagBalls.prototype.getVariance = function(distance) {
|
MagBalls.prototype.getVariance = function(distance) {
|
||||||
// Given two points, how big is the difference between their distance
|
// Given two points, how big is the difference between their distance
|
||||||
|
@ -550,24 +215,3 @@ MagBalls.prototype.clear = function() {
|
||||||
}, this);
|
}, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Override to check lengths as well as connection consistency
|
|
||||||
MagBalls.prototype.validate = function() {
|
|
||||||
var error = Graph.prototype.validate.call(this);
|
|
||||||
|
|
||||||
if (!error) {
|
|
||||||
for (edgeId in this.edges) {
|
|
||||||
var length = this.getEdgeLength(edgeId);
|
|
||||||
var variance = this.getVariance(length);
|
|
||||||
if (variance > EPSILON) {
|
|
||||||
Entities.editEntity(edgeId, { color: COLORS.RED });
|
|
||||||
|
|
||||||
logDebug("Edge " + edgeId + " length " + (length * 100).toFixed(2) + " cm variance " + (variance * 100).toFixed(3) + "%");
|
|
||||||
error = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (error) {
|
|
||||||
logDebug(EPSILON);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
(function(){
|
(function(){
|
||||||
this.preload = function(entityId) {
|
this.preload = function(entityId) {
|
||||||
this.MIN_CHECK_INTERVAL = 0.05;
|
this.MIN_CHECK_INTERVAL = 0.05;
|
||||||
|
@ -18,26 +17,22 @@
|
||||||
var userData = JSON.parse(properties.userData);
|
var userData = JSON.parse(properties.userData);
|
||||||
this.start = userData.magBalls.start;
|
this.start = userData.magBalls.start;
|
||||||
this.end = userData.magBalls.end;
|
this.end = userData.magBalls.end;
|
||||||
this.originalColor = properties.color;
|
|
||||||
this.desiredLength = userData.magBalls.length;
|
this.desiredLength = userData.magBalls.length;
|
||||||
this.timeSinceLastUpdate = 0;
|
this.timeSinceLastUpdate = 0;
|
||||||
this.nextCheckInterval = this.MIN_CHECK_INTERVAL;
|
this.nextCheckInterval = this.MIN_CHECK_INTERVAL;
|
||||||
|
|
||||||
print("preload("+entityId+") " + this.start + " -> " + this.end + " " + this.desiredLength);
|
// FIXME do I really need to do this nonsense?
|
||||||
|
|
||||||
var _this = this;
|
var _this = this;
|
||||||
this.updateWrapper = function(deltaTime) {
|
this.updateWrapper = function(deltaTime) {
|
||||||
_this.onUpdate(deltaTime);
|
_this.onUpdate(deltaTime);
|
||||||
};
|
};
|
||||||
Script.update.connect(this.updateWrapper);
|
Script.update.connect(this.updateWrapper);
|
||||||
|
|
||||||
Script.scriptEnding.connect(function() {
|
Script.scriptEnding.connect(function() {
|
||||||
_this.onCleanup();
|
_this.onCleanup();
|
||||||
});
|
});
|
||||||
|
|
||||||
Entities.deletingEntity.connect(function(entityId) {
|
Entities.deletingEntity.connect(function(entityId) {
|
||||||
if (_this.entityId == entityId) {
|
_this.onCleanup();
|
||||||
_this.onCleanup();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -57,20 +52,12 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.decrementCheckInterval();
|
this.decrementCheckInterval();
|
||||||
print("Length is wrong: " + (length * 100).toFixed(1) + "cm variance " + variance);
|
|
||||||
|
|
||||||
var adjustmentVector = Vec3.multiply(variance / 4, this.vector);
|
var adjustmentVector = Vec3.multiply(variance / 4, this.vector);
|
||||||
var newPosition = Vec3.sum(Vec3.multiply(-1, adjustmentVector), this.position);
|
var newPosition = Vec3.sum(Vec3.multiply(-1, adjustmentVector), this.position);
|
||||||
var newVector = Vec3.sum(Vec3.multiply(2, adjustmentVector), this.vector);
|
var newVector = Vec3.sum(Vec3.multiply(2, adjustmentVector), this.vector);
|
||||||
var newLength = Vec3.length(newVector);
|
var newLength = Vec3.length(newVector);
|
||||||
var newVariance = this.getVariance(newLength);
|
var newVariance = this.getVariance(newLength);
|
||||||
var color = { color: this.originalColor }
|
|
||||||
if (Math.abs(newVariance) > this.MAX_VARIANCE) {
|
|
||||||
color = { red: 255, green: 0, blue: 0 };
|
|
||||||
}
|
|
||||||
print("Updating entity to new variance " + newVariance);
|
|
||||||
Entities.editEntity(this.entityId, {
|
Entities.editEntity(this.entityId, {
|
||||||
color: color,
|
|
||||||
position: newPosition,
|
position: newPosition,
|
||||||
linePoints: [ this.ZERO_VECTOR, newVector ]
|
linePoints: [ this.ZERO_VECTOR, newVector ]
|
||||||
});
|
});
|
||||||
|
@ -80,7 +67,6 @@
|
||||||
Entities.editEntity(this.end, {
|
Entities.editEntity(this.end, {
|
||||||
position: Vec3.sum(newPosition, newVector)
|
position: Vec3.sum(newPosition, newVector)
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,8 +79,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
this.onCleanup = function() {
|
this.onCleanup = function() {
|
||||||
print("Stopping spring script");
|
if (this.updateWrapper) {
|
||||||
Script.update.disconnect(this.updateWrapper);
|
Script.update.disconnect(this.updateWrapper);
|
||||||
|
delete this.updateWrapper;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.getVariance = function(length) {
|
this.getVariance = function(length) {
|
||||||
|
@ -132,12 +120,4 @@
|
||||||
}
|
}
|
||||||
this.position = startPos;
|
this.position = startPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.enterEntity = function(entityId) {
|
|
||||||
print("enterEntity("+entityId+")");
|
|
||||||
};
|
|
||||||
|
|
||||||
this.leaveEntity = function(entityId) {
|
|
||||||
print("leaveEntity("+entityId+")");
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,3 +1,10 @@
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 2015/08/29
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
vec3toStr = function (v, digits) {
|
vec3toStr = function (v, digits) {
|
||||||
if (!digits) { digits = 3; }
|
if (!digits) { digits = 3; }
|
||||||
|
|
Loading…
Reference in a new issue