//anchor is local //vertices are local //have vector2 return? /// <summary> /// Rebuilds the anchor. /// </summary> /// <param name="anchor">The anchor (In local space).</param> /// <param name="isAnchorA">Whether to rebuild the first anchor as opposed to rebuilding the second anchor.</param> /// <param name="useBaseShape">Whether use JelloBody.Shape instead of JelloPointMass.Position. Has no effect if Transform has no JelloBody attached.</param> /// <param name="affectedIndices">The indices of the affected / affecting JelloPointMass objects. Has no effect if Transform has no JelloBody attached.</param> /// <param name="affectedVertices">The positions (in local space) of the affected / affecting JelloPointMass objects. Has no effect if Transform has no JelloBody attached.</param> public void RebuildAnchor(Vector2 anchor, bool isAnchorA, bool useBaseShape, int[] affectedIndices = null, Vector2[] affectedVertices = null) { //Vector2 point; if(isAnchorA) { localAnchorA = anchor; if(mTransformA == null) return; if(bodyA != null) { if(affectedIndices == null) affectedIndices = affectedIndicesA; else affectedIndicesA = affectedIndices; if(affectedVertices == null)//grab from point mass positions? { if(useBaseShape) { affectedVertices = new Vector2[affectedIndicesA.Length]; for(int i = 0; i < affectedIndicesA.Length; i++) affectedVertices[i] = bodyA.Shape.getVertex(affectedIndicesA[i]); } else { affectedVertices = new Vector2[affectedIndicesA.Length]; for(int i = 0; i < affectedIndicesA.Length; i++) affectedVertices[i] = bodyA.getPointMass(affectedIndicesA[i]).LocalPosition; } } if(affectedIndices != null) { if(affectedIndices.Length == 1) { scalarsA = new float[1]; scalarsA[0] = 1f; } else if(affectedIndices.Length == 2) { Vector2 hit; scalarsA = new float[2]; JelloVectorTools.getClosestPointOnSegmentSquared (localAnchorA, affectedVertices[0], affectedVertices[1], out hit, out scalarsA[1]); scalarsA[0] = 1 - scalarsA[1]; } else if(affectedIndices.Length == 3) { scalarsA = JelloShapeTools.GetBarycentricCoords(localAnchorA, affectedVertices); } } } } else { localAnchorB = anchor; if(mTransformB == null) return; if(bodyB != null) { if(affectedIndices == null) affectedIndices = affectedIndicesB; else affectedIndicesB = affectedIndices; if(affectedVertices == null)//grab from point mass positions? { if(useBaseShape) { affectedVertices = new Vector2[affectedIndicesB.Length]; for(int i = 0; i < affectedIndicesB.Length; i++) affectedVertices[i] = bodyB.Shape.getVertex(affectedIndicesB[i]); } else { affectedVertices = new Vector2[affectedIndicesB.Length]; for(int i = 0; i < affectedIndicesB.Length; i++) affectedVertices[i] = bodyB.getPointMass(affectedIndicesB[i]).LocalPosition; } } if(affectedIndices != null) { if(affectedIndices.Length == 1) { scalarsB = new float[1]; scalarsB[0] = 1f; } else if(affectedIndices.Length == 2) { Vector2 hit; scalarsB = new float[2]; JelloVectorTools.getClosestPointOnSegmentSquared (localAnchorB, affectedVertices[0], affectedVertices[1], out hit, out scalarsB[1]); scalarsB[0] = 1 - scalarsB[1]; } else if(affectedIndices.Length == 3) { scalarsB = JelloShapeTools.GetBarycentricCoords(localAnchorB, affectedVertices); } } } } }
/// <summary> /// Update this JelloAttachPoint . /// Will derive the new position for the JelloAttachPoint.point, AttachTransform.Position and AttachedTrasnform.Angle. /// This will be called by the simulation and should not need to be called manualy. /// </summary> /// <param name="useBaseShape">Whether to use the JelloBody.Shape positions to determine the new position.</param> public Vector2 Update(bool useBaseShape) { point = Vector2.zero; if (useBaseShape) { for (int i = 0; i < affectedIndices.Length; i++) { point += body.Shape.getVertex(affectedIndices[i]) * scalars[i]; } if (point.x == float.NaN) { for (int i = 0; i < affectedIndices.Length; i++) { Debug.Log(body.Shape.getVertex(affectedIndices[i]) + " " + scalars[i]); } } } else { for (int i = 0; i < affectedIndices.Length; i++) { point += body.getPointMass(affectedIndices[i]).Position *scalars[i]; } point = transform.InverseTransformPoint(point); if (point.x == float.NaN) { for (int i = 0; i < affectedIndices.Length; i++) { Debug.Log(body.getPointMass(affectedIndices[i]).Position + " " + scalars[i]); } } } if (mAttachedTransform != null) { Vector3 newPos = transform.TransformPoint(point); newPos.z = mAttachedTransform.position.z; mAttachedTransform.position = newPos; if (rotate) { float angle = 0; int originalSign = 1; float originalAngle = 0; float thisAngle; Vector2 center = Vector2.zero; Vector2 centerGlobal = Vector2.zero; if (affectedIndices.Length == 1) { centerGlobal = body.Position; } else { for (int i = 0; i < affectedIndices.Length; i++) { center += body.Shape.getVertex(affectedIndices[i]); } center /= affectedIndices.Length; centerGlobal = Vector2.zero; for (int i = 0; i < affectedIndices.Length; i++) { centerGlobal += body.getPointMass(affectedIndices[i]).Position; } centerGlobal /= affectedIndices.Length; } for (int i = 0; i < affectedIndices.Length; i++) { thisAngle = Vector2.Angle(body.Shape.getVertex(affectedIndices[i]) - center, body.getPointMass(affectedIndices[i]).Position - centerGlobal); //(Vector2)body.transform.TransformPoint(center)); if (Vector3.Cross(body.Shape.getVertex(affectedIndices[i]) - center, body.getPointMass(affectedIndices[i]).Position - centerGlobal).z < 0f) //(Vector2)body.transform.TransformPoint(center)).z < 0f) { thisAngle *= -1f; } if (i == 0) { originalSign = (thisAngle >= 0f) ? 1 : -1; originalAngle = thisAngle; } else { if ((Mathf.Abs(thisAngle - originalAngle) > 180f) && ((thisAngle >= 0f ? 1 : -1) != originalSign)) { thisAngle = ((thisAngle >= 0f ? 1 : -1) == -1) ? 360f + thisAngle : -thisAngle; } } angle += thisAngle; } angle /= affectedIndices.Length; mAttachedTransform.eulerAngles = new Vector3(mAttachedTransform.eulerAngles.x, mAttachedTransform.eulerAngles.y, angle + transformAngle); } } return(point); }
/// <summary> /// Rebuild this JelloAttachPoint. /// </summary> /// <param name="attachPoint">The point (local to the JelloAttachPoint.body) at which to attach the JelloAttachPoint.AttachedTransform.</param> /// <param name="jelloBody">The JelloBody to to be attached to.</param> /// <param name="indices">The JelloPointMass Indices. Should have a length of 1, 2, or 3.</param> /// <param name="useBaseShape">Whether to use the JelloBody.Shape positions (instead of JelloPointMass.Position) when building the JelloAttachPoint.</param> public void Rebuild(Vector2 attachPoint, JelloBody jelloBody, int[] indices, bool useBaseShape = true) { body = jelloBody; transform = body.transform; if (indices == null) { if (affectedIndices == null) { Rebuild(attachPoint, jelloBody, useBaseShape); return; } else { indices = affectedIndices; } } else if (indices.Length > 4) { affectedIndices = new int[3]; for (int i = 0; i < 3; i++) { affectedIndices[i] = indices[i]; } } else { affectedIndices = indices; } Vector2[] verts = new Vector2[3]; if (useBaseShape) { for (int i = 0; i < affectedIndices.Length; i++) { verts[i] = body.Shape.getVertex(affectedIndices[i]); } } else { attachPoint = transform.TransformPoint(attachPoint); for (int i = 0; i < affectedIndices.Length; i++) { verts[i] = body.getPointMass(affectedIndices[i]).Position; } } if (affectedIndices.Length == 1) { scalars = new float[1]; scalars[0] = 1f; } else if (affectedIndices.Length == 2) { Vector2 hit; scalars = new float[2]; JelloVectorTools.getClosestPointOnSegmentSquared(attachPoint, verts[0], verts[1], out hit, out scalars[1]); scalars[0] = 1 - scalars[1]; } else if (affectedIndices.Length == 3) { scalars = JelloShapeTools.GetBarycentricCoords(attachPoint, verts); } //throw into for loop... point = Vector2.zero; for (int i = 0; i < affectedIndices.Length; i++) { point += scalars[i] * verts[i]; } if (!useBaseShape) { point = transform.InverseTransformPoint(point); } if (mAttachedTransform != null) { Vector3 newPos = transform.TransformPoint(point); newPos.z = mAttachedTransform.position.z; mAttachedTransform.position = newPos; } }
/// <summary> /// Rebuild this JelloAttachPoint. /// </summary> /// <param name="attachPoint">The point (local to the JelloAttachPoint.body) at which to attach the JelloAttachPoint.AttachedTransform.</param> /// <param name="jelloBody">The JelloBody to to be attached to.</param> /// <param name="useBaseShape">Whether to use the JelloBody.Shape positions (instead of JelloPointMass.Position) when building the JelloAttachPoint.</param> /// <param name="numLegs">Number of JelloPointMass objects to use as "legs" (use 1, 2, or 3).</param> public void Rebuild(Vector2 attachPoint, JelloBody jelloBody, bool useBaseShape = true, int numLegs = 0) { body = jelloBody; transform = body.transform; if (numLegs != 0) { if (numLegs < 0) { numLegs = 1; } if (numLegs > 3) { numLegs = 3; } affectedIndices = new int[numLegs]; } else if (affectedIndices == null || affectedIndices.Length == 0 || affectedIndices.Length > 3) { affectedIndices = new int[2]; //default to 3? } Vector2[] shape = new Vector2[body.Shape.VertexCount]; if (useBaseShape) { for (int i = 0; i < shape.Length; i++) { shape[i] = body.Shape.getVertex(i); } } else { attachPoint = transform.TransformPoint(attachPoint); for (int i = 0; i < shape.Length; i++) { shape[i] = body.getPointMass(i).Position; } } if (affectedIndices.Length == 1) { affectedIndices = JelloShapeTools.GetClosestIndices(attachPoint, shape, 1); scalars = new float[1]; scalars[0] = 1f; } else if (affectedIndices.Length == 2) { Vector2 hit; affectedIndices = JelloShapeTools.FindClosestEdgeOnShape(attachPoint, shape); scalars = new float[2]; JelloVectorTools.getClosestPointOnSegmentSquared(attachPoint, shape[affectedIndices[0]], shape[affectedIndices[1]], out hit, out scalars[1]); scalars[0] = 1 - scalars[1]; } else if (affectedIndices.Length == 3) { Vector2[] shapePerimeter = new Vector2[body.EdgePointMassCount]; if (useBaseShape) { shapePerimeter = body.Shape.EdgeVertices; } else { for (int i = 0; i < shapePerimeter.Length; i++) { shapePerimeter[i] = body.getEdgePointMass(i).Position; } } affectedIndices = JelloShapeTools.FindContainingTriangle(attachPoint, shape, shapePerimeter, body.Shape.Triangles, out scalars); } point = Vector2.zero; for (int i = 0; i < affectedIndices.Length; i++) { point += shape[affectedIndices[i]] * scalars[i]; } if (!useBaseShape) { point = transform.InverseTransformPoint(point); } if (mAttachedTransform != null) { Vector3 newPos = transform.TransformPoint(point); newPos.z = mAttachedTransform.position.z; mAttachedTransform.position = newPos; } }
/// <summary> /// Rebuild this JelloAttachPoint. /// </summary> /// <param name="attachPoint">The point (local to the JelloAttachPoint.body) at which to attach the JelloAttachPoint.AttachedTransform.</param> /// <param name="jelloBody">The JelloBody to to be attached to.</param> /// <param name="indices">The JelloPointMass Indices. Should have a length of 1, 2, or 3.</param> /// <param name="useBaseShape">Whether to use the JelloBody.Shape positions (instead of JelloPointMass.Position) when building the JelloAttachPoint.</param> public void Rebuild(Vector2 attachPoint, JelloBody jelloBody, int[] indices, bool useBaseShape = true) { body = jelloBody; transform = body.transform; if(indices == null) { if(affectedIndices == null) { Rebuild(attachPoint, jelloBody, useBaseShape); return; } else { indices = affectedIndices; } } else if(indices.Length > 4) { affectedIndices = new int[3]; for(int i = 0; i < 3; i++) affectedIndices[i] = indices[i]; } else { affectedIndices = indices; } Vector2[] verts = new Vector2[3]; if(useBaseShape) { for(int i = 0; i < affectedIndices.Length; i++) verts[i] = body.Shape.getVertex(affectedIndices[i]); } else { attachPoint = transform.TransformPoint(attachPoint); for(int i = 0; i < affectedIndices.Length; i++) verts[i] = body.getPointMass(affectedIndices[i]).Position; } if(affectedIndices.Length == 1) { scalars = new float[1]; scalars[0] = 1f; } else if(affectedIndices.Length == 2) { Vector2 hit; scalars = new float[2]; JelloVectorTools.getClosestPointOnSegmentSquared (attachPoint, verts[0], verts[1], out hit, out scalars[1]); scalars[0] = 1 - scalars[1]; } else if (affectedIndices.Length == 3) { scalars = JelloShapeTools.GetBarycentricCoords(attachPoint, verts); } //throw into for loop... point = Vector2.zero; for(int i = 0; i < affectedIndices.Length; i++) point += scalars[i] * verts[i]; if(!useBaseShape) point = transform.InverseTransformPoint(point); if(mAttachedTransform != null) { Vector3 newPos = transform.TransformPoint(point); newPos.z = mAttachedTransform.position.z; mAttachedTransform.position = newPos; } }
/// <summary> /// Rebuild this JelloAttachPoint. /// </summary> /// <param name="attachPoint">The point (local to the JelloAttachPoint.body) at which to attach the JelloAttachPoint.AttachedTransform.</param> /// <param name="jelloBody">The JelloBody to to be attached to.</param> /// <param name="useBaseShape">Whether to use the JelloBody.Shape positions (instead of JelloPointMass.Position) when building the JelloAttachPoint.</param> /// <param name="numLegs">Number of JelloPointMass objects to use as "legs" (use 1, 2, or 3).</param> public void Rebuild(Vector2 attachPoint, JelloBody jelloBody, bool useBaseShape = true, int numLegs = 0) { body = jelloBody; transform = body.transform; if(numLegs != 0) { if(numLegs < 0) numLegs = 1; if(numLegs > 3) numLegs = 3; affectedIndices = new int[numLegs]; } else if(affectedIndices == null || affectedIndices.Length == 0 || affectedIndices.Length > 3) affectedIndices = new int[2];//default to 3? Vector2[] shape = new Vector2[body.Shape.VertexCount]; if(useBaseShape) { for(int i = 0; i < shape.Length; i++) shape[i] = body.Shape.getVertex(i); } else { attachPoint = transform.TransformPoint(attachPoint); for(int i = 0; i < shape.Length; i++) shape[i] = body.getPointMass(i).Position; } if(affectedIndices.Length == 1) { affectedIndices = JelloShapeTools.GetClosestIndices(attachPoint, shape, 1); scalars = new float[1]; scalars[0] = 1f; } else if(affectedIndices.Length == 2) { Vector2 hit; affectedIndices = JelloShapeTools.FindClosestEdgeOnShape(attachPoint, shape); scalars = new float[2]; JelloVectorTools.getClosestPointOnSegmentSquared (attachPoint, shape[affectedIndices[0]], shape[affectedIndices[1]], out hit, out scalars[1]); scalars[0] = 1 - scalars[1]; } else if(affectedIndices.Length == 3) { Vector2[] shapePerimeter = new Vector2[body.EdgePointMassCount]; if(useBaseShape) { shapePerimeter = body.Shape.EdgeVertices; } else { for(int i = 0; i < shapePerimeter.Length; i++) shapePerimeter[i] = body.getEdgePointMass(i).Position; } affectedIndices = JelloShapeTools.FindContainingTriangle(attachPoint, shape, shapePerimeter, body.Shape.Triangles, out scalars); } point = Vector2.zero; for(int i = 0; i < affectedIndices.Length; i++) point += shape[affectedIndices[i]] * scalars[i]; if(!useBaseShape) point = transform.InverseTransformPoint(point); if(mAttachedTransform != null) { Vector3 newPos = transform.TransformPoint(point); newPos.z = mAttachedTransform.position.z; mAttachedTransform.position = newPos; } }