/** * Supply a vertex to return the distance to that vertex from this one. * @param toVertex The vertex to measure the distance too. * @param normalise Indicates that the difference values are to be normalised. * @return A four item array, containing the distance and the x y z difference between the vertices. Normalised if told too. */ public float[] distanceToVertex(RFrame_Vertex toVertex, bool normalise) { float diffX = toVertex.x - this.x; float diffY = toVertex.y - this.y; float diffZ = toVertex.z - this.z; float dist = Mathf.Sqrt(diffX * diffX + diffY * diffY + diffZ * diffZ); float[] returnVals = { dist, diffX, diffY, diffZ }; if (normalise) { returnVals[1] = diffX / dist; returnVals[2] = diffY / dist; returnVals[3] = diffZ / dist; } return(returnVals); }
public void calculateDistancesThenOrientate() { RFrame_Strut strutPull; foreach (GameObject strutObject in struts) { strutPull = strutObject.GetComponent <RFrame_Strut>(); GameObject v1Obj = allVertices[strutPull.v1]; GameObject v2Obj = allVertices[strutPull.v2]; RFrame_Vertex v1 = v1Obj.GetComponent <RFrame_Vertex>(); RFrame_Vertex v2 = v2Obj.GetComponent <RFrame_Vertex>(); strutPull.length = Mathf.Abs(v1.distanceToVertex(v2, false)[0]); checkIfShortestStrut(strutPull); // Update the line renderers. Vector3[] positions = { v1Obj.transform.localPosition, v2Obj.transform.localPosition }; strutPull.updateLineRenderPositions(positions); } }
public void performCyclesV2(RFrame_Object[] frameObjects, int affirmPerCycle) { // ****************************************************************** // ****************************************************************** // ****************************************************************** RFrame_Strut strut; if (frameObjects != null) { if (frameObjects.Length == 0) { return; } // Bin out if there's nothing to work on. //Debug.Log("Frame objects detected. Peforming cycles"); for (int i = 0; i < affirmPerCycle; i++) { // Update the work align switch - Moved to here from the start of the function // on the 20 March 2019. workAlignSwitch = !workAlignSwitch; // Swap over the work alignment // Pass through each frame in the array and process their vertices and struts. foreach (RFrame_Object frameObject in frameObjects) { // Set the adjustment values per frame. //adjustmentThreshhold = 0.0f; //frameObject.GetShortestStrutLength() * 0.05f; affirmRatio = 1.0f; //adjustmentThreshhold * 0.2f; // Work through strut array and affirm strut lengths foreach (GameObject strutGameObject in frameObject.struts) { strut = strutGameObject.GetComponent <RFrame_Strut>(); // Collect the vertices involved with this strut. RFrame_Vertex v1 = frameObject.allVertices[strut.v1].GetComponent <RFrame_Vertex>(); RFrame_Vertex v2 = frameObject.allVertices[strut.v2].GetComponent <RFrame_Vertex>(); // Get the distance between the two, along with normalised // axis vector pointing in the direction of the two. float[] distNormV1 = v1.distanceToVertex(v2, true); strut.actualLength = distNormV1[0]; // Record the current length to the strut. // No need to call the method for the other way round. // Just reverse the normals. float limitDiff = strut.distanceOutFromAcceptableRange(distNormV1[0]); // strut.length - distNormV1[0]; // If the difference between the length and measured distance // between the two vertices, is greater than the adjustmentThreshold // variable, then adjust the vertices to the correct distance // IDEA - Have a think about percentage shift bias for each vertex, depending on how many struts are connected to it. //if (Mathf.Abs(limitDiff)>adjustmentThreshhold) { // Calculate the translation for each vertex. float v1xShift = -(limitDiff * affirmRatio * distNormV1[1]); float v1yShift = -(limitDiff * affirmRatio * distNormV1[2]); float v1zShift = -(limitDiff * affirmRatio * distNormV1[3]); // This will simply be the reverse direction. float v2xShift = -v1xShift; float v2yShift = -v1yShift; float v2zShift = -v1zShift; // Applying the translations to the vertices. // Only apply if not locked in place. if (!v1.lockedInPlace) { v1.applyTranslationV2(v1xShift, v1yShift, v1zShift, this); } else { v1.applyTranslationV2(0, 0, 0, this); } if (!v2.lockedInPlace) { v2.applyTranslationV2(v2xShift, v2yShift, v2zShift, this); } else { v2.applyTranslationV2(0, 0, 0, this); } //} } // For each vertex that was effected, have it's movement divided // by the amount of effects applied to it. // foreach (GameObject vertex in frameObject.allVertices) { // vertex.GetComponent<RFrame_Vertex>().finaliseTranslations(this); // } // Updating the line renderers // RFrame_Strut strutPull; // foreach (GameObject strutObj in frameObject.struts) { // strutPull = strutObj.GetComponent<RFrame_Strut>(); // GameObject v1Obj = frameObject.allVertices[strutPull.v1]; // GameObject v2Obj = frameObject.allVertices[strutPull.v2]; // Vector3[] positions = {v1Obj.transform.position,v2Obj.transform.position}; // strutPull.updateLineRenderPositions(positions); // } } } } // ****************************************************************** // ****************************************************************** // ****************************************************************** }
/** * Test method for creating a Frame_Object from an OBJ file * 23 Jan 2019 - Updated to read from modified OBJ files. * @param objFile The filename of the OBJ file * @return A Frame_Object file * @throws FileNotFoundException */ void createFromOBJ(TextAsset objFile) { //System.out.println("Loading OBJ file : " + objFile.toString()); string[] inFile = objFile.text.Split('\n'); List <GameObject> verticesBuild = new List <GameObject>(); List <GameObject> strutBuild = new List <GameObject>(); List <GameObject> angleViewBuild = new List <GameObject>(); List <GameObject> compRepBuild = new List <GameObject>(); List <GameObject> balPosBuild = new List <GameObject>(); List <GameObject> disHolBuild = new List <GameObject>(); List <GameObject> ancPoiBuild = new List <GameObject>(); int vertexIndex = 0; foreach (string objLine in inFile) { //System.out.println(objLine); // Debug print to console the current line. // Reading in a vertex line if (objLine.StartsWith("v") && !objLine.StartsWith("vn") && !objLine.StartsWith("vt") && !objLine.StartsWith("vp")) { // Split the string using space. e.g. v 3.00 2.00 -2.00 //System.out.println("Vertex : " + objLine); string[] splits = objLine.Split(' '); float x = float.Parse(splits[1]); float y = float.Parse(splits[2]); float z = float.Parse(splits[3]); GameObject vertexGameObject = Instantiate(VertexInstantiator, this.transform); vertexGameObject.name = vertexGameObject.name + "_" + vertexIndex; vertexGameObject.transform.localPosition = new Vector3(x, y, z); RFrame_Vertex vertexScript = vertexGameObject.GetComponent <RFrame_Vertex>(); vertexScript.x = x; vertexScript.y = y; vertexScript.z = z; // Check for lock character if (splits.Length > 4) { if (splits[4] == "l") { vertexScript.lockedInPlace = true; } } verticesBuild.Add(vertexGameObject); vertexIndex++; } else if (objLine.StartsWith("l")) { // This is for any standalone lines, which will be turned into struts. // Modified to only work with the first two vertice indexes string[] splits = objLine.Split(' '); // Remember that indexes start at 1 in the obj/txt file and need converting to zero-indexed. int v1 = int.Parse(splits[1]) - 1; int v2 = int.Parse(splits[2]) - 1; GameObject strutGameObject = RFrame_Object.createStrutIfNotExisting(this, StrutInstantiator, strutBuild, v1, v2); // Check if strut is displayed. This is determined by having more than three entries in splits. // Basically any character entered after the 2 indexes will trigger this. //if(strutGameObject!=null && splits.Length > 3) { if (splits.Length == 5) { RFrame_Strut strutScript = strutGameObject.GetComponent <RFrame_Strut>(); strutScript.minLength = float.Parse(splits[3]); strutScript.maxLength = float.Parse(splits[4]); } // All line renderers will be switched off. LineRenderer lineRenderer = strutGameObject.GetComponent <LineRenderer>(); // Used when debugging the a fresh OBJ frame. lineRenderer.enabled = transform.GetComponentInParent <RFrame_Bridge>().displayStrutsOnLoad; //} } else if (objLine.StartsWith("anglink")) { // Angle link entry. // Requires 4 vertex indexes and a link channel number which will represent the angle measurer struts. // and the actuator/motor/servo this is linked too. // Centering and angle limits should be entered. string[] splits = objLine.Split(' '); int centerVertex = int.Parse(splits[1]); int upVertex = int.Parse(splits[2]); int measure1 = int.Parse(splits[3]); int measure2 = int.Parse(splits[4]); int channel = int.Parse(splits[5]); // Channel number should already be zero-indexed. bool invertChannel = bool.Parse(splits[6]); // Should be 0, 1, true or false float minChannelAngle = float.Parse(splits[7]); // Channel won't be sent any number smaller than this. float maxChannelAngle = float.Parse(splits[8]); // Channel won't be sent any number larger than this. float biasAngle = float.Parse(splits[9]); // The bias to apply. Indicates that a servo may need recentering int angleMeasureType = int.Parse(splits[10]); // Quaternion or dot product angle float scaleChangedAngled = float.Parse(splits[11]); // How much to scale the change in angle from initial. Increases range of movement. GameObject angleViewerObj = Instantiate(AngleViewerInstantiator, this.transform); RFrame_AngleLink angleLinker = angleViewerObj.GetComponent <RFrame_AngleLink>(); angleLinker.centerVertex = centerVertex; angleLinker.upVertex = upVertex; angleLinker.measure1 = measure1; angleLinker.measure2 = measure2; angleLinker.linkChannel = channel; angleLinker.invertedSendAngle = invertChannel; angleLinker.minimumAngle = minChannelAngle; angleLinker.maximumAngle = maxChannelAngle; angleLinker.biasAngle = biasAngle; angleLinker.angleChangeScaling = scaleChangedAngled; switch (angleMeasureType) { case 0: { angleLinker.angleMeasureType = RFrame_AngleLink.AngleMeasureTypeEnum.quaternionBased; break; } case 1: { angleLinker.angleMeasureType = RFrame_AngleLink.AngleMeasureTypeEnum.lineBased; break; } default: { angleLinker.angleMeasureType = RFrame_AngleLink.AngleMeasureTypeEnum.quaternionBased; break; } } angleViewBuild.Add(angleViewerObj); } else if (objLine.StartsWith("comprep") && transform.GetComponentInParent <RFrame_Bridge>().displayComponentRepsOnLoad) { // Component representation string[] splits = objLine.Split(' '); int centerVertex = int.Parse(splits[1]); int upVertex = int.Parse(splits[2]); int forwardVertex = int.Parse(splits[3]); string meshName = splits[4]; float xRot = float.Parse(splits[5]); float yRot = float.Parse(splits[6]); float zRot = float.Parse(splits[7]); float xTran = float.Parse(splits[8]); float yTran = float.Parse(splits[9]); float zTran = float.Parse(splits[10]); GameObject compRepObj = Instantiate(ComponentRepresentorInstantiator, this.transform); RFrame_Component componentRep = compRepObj.GetComponent <RFrame_Component>(); componentRep.centerVertex = centerVertex; componentRep.forwardVertex = forwardVertex; componentRep.upVertex = upVertex; GameObject meshObject = Instantiate(Resources.Load <GameObject>(meshName), compRepObj.transform); meshObject.transform.localPosition = new Vector3(xTran, yTran, zTran); meshObject.transform.localRotation = Quaternion.Euler(xRot, yRot, zRot); } else if (objLine.StartsWith("balpos")) { // Balance position behaviour module building here string[] splits = objLine.Split(' '); int vertexAttachIndex = int.Parse(splits[1]); float reduceRatio = float.Parse(splits[2]); GameObject balPolObj = Instantiate(BalancePositionInstantiator, this.transform); BMod_BalancePosition balPosMod = balPolObj.GetComponent <BMod_BalancePosition>(); balPosMod.restrictionAreaShrinkRatio = reduceRatio; balPosMod.controlVertex = verticesBuild[vertexAttachIndex].GetComponent <RFrame_Vertex>(); //balPosMod.controlVertex.lockedInPlace = true; balPosBuild.Add(balPolObj); } else if (objLine.StartsWith("dishol")) { // Distance holder behaviour module building here string[] splits = objLine.Split(' '); int balPosIndex = int.Parse(splits[1]); int vertexAttachIndex = int.Parse(splits[2]); float distanceToHold = float.Parse(splits[3]); int typeOfDisHol = int.Parse(splits[4]); GameObject disHolObj = Instantiate(DistanceHolderInstantiator, balPosBuild[balPosIndex].transform); BMod_DistanceHolder disHolMod = disHolObj.GetComponent <BMod_DistanceHolder>(); disHolMod.vertexPoint = verticesBuild[vertexAttachIndex].GetComponent <RFrame_Vertex>(); // Experimenting with not locking the vertex in place. // Need to make sure frame doesn't move out of place. disHolMod.vertexPoint.lockedInPlace = true; disHolMod.distanceToHold = distanceToHold; switch (typeOfDisHol) { case 0: disHolMod.moduleType = BMod_DistanceHolder.DistanceModuleType.groundDistance; break; case 1: disHolMod.moduleType = BMod_DistanceHolder.DistanceModuleType.allRoundDistance; break; default: disHolMod.moduleType = BMod_DistanceHolder.DistanceModuleType.groundDistance; break; } disHolBuild.Add(disHolObj); } else if (objLine.StartsWith("ancpoi")) { // Anchor Point behaviour module building here string[] splits = objLine.Split(' '); int disHolIndex = int.Parse(splits[1]); int vertexAttachIndex = int.Parse(splits[2]); int priorityValue = int.Parse(splits[3]); int typeOfAnchor = int.Parse(splits[4]); GameObject anchorObj = Instantiate(AnchorPointInstantiator, disHolBuild[disHolIndex].transform); BMod_AnchorPoint anchorMod = anchorObj.GetComponent <BMod_AnchorPoint>(); anchorMod.anchorVertex = verticesBuild[vertexAttachIndex].GetComponent <RFrame_Vertex>(); anchorMod.anchorVertex.lockedInPlace = true; anchorMod.priorityIndex = priorityValue; switch (typeOfAnchor) { case 0: anchorMod.anchorType = BMod_AnchorPoint.AnchorTypeEnum.primaryAnchor; break; case 1: anchorMod.anchorType = BMod_AnchorPoint.AnchorTypeEnum.secondaryAnchor; break; case 2: anchorMod.anchorType = BMod_AnchorPoint.AnchorTypeEnum.tertiaryAnchor; break; default: anchorMod.anchorType = BMod_AnchorPoint.AnchorTypeEnum.primaryAnchor; break; } ancPoiBuild.Add(anchorObj); } } // Set the parents of the objects instatiated to this object and // call the function for calculating all the distances between // struts. if (verticesBuild.Count != 0 && strutBuild.Count != 0) { // Apply the created vertices and struts to this object. // Set the parent of the vertices and struts to the transform of this frame object. // foreach (GameObject vertex in verticesBuild) { // vertex.transform.SetParent(this.transform); // } // foreach (GameObject strut in strutBuild) { // strut.transform.SetParent(this.transform); // } allVertices = verticesBuild; struts = strutBuild; angleLinks = angleViewBuild; compReps = compRepBuild; this.calculateDistancesThenOrientate(); // Get the initial measured angles for each angle link. foreach (GameObject angleLinkObj in angleViewBuild) { angleLinkObj.GetComponent <RFrame_AngleLink>().measureAngle(true); } //frame.gatherBounds(); } }