private void AdjustEdgeHandleColor(Vector3 handlePos, Vector3 slideDir1, Vector3 slideDir2, Matrix4x4 transform, float alphaFactor) { bool flag; Vector3 inPoint = transform.MultiplyPoint(handlePos); Vector3 normalized = transform.MultiplyVector(slideDir1).normalized; Vector3 rhs = transform.MultiplyVector(slideDir2).normalized; if (Camera.current.isOrthoGraphic) { flag = (Vector3.Dot(-Camera.current.transform.forward, normalized) < 0f) && (Vector3.Dot(-Camera.current.transform.forward, rhs) < 0f); } else { Plane plane = new Plane(normalized, inPoint); Plane plane2 = new Plane(rhs, inPoint); flag = !plane.GetSide(Camera.current.transform.position) && !plane2.GetSide(Camera.current.transform.position); } if (flag) { alphaFactor *= 0.2f; } if (alphaFactor < 1f) { Handles.color = new Color(Handles.color.r, Handles.color.g, Handles.color.b, Handles.color.a * alphaFactor); } }
// Handle map in the leaf level, so no care face level //ArrayList findVisibleFaces(ArrayList visibleLeafs) { // if (visibleLeafs == null) { // throw new ArgumentException(); // } // bool[] alreadyVisibleFaces = new bool[_faces.Length]; // ArrayList visibleFaces = new ArrayList(); // foreach(int i in visibleLeafs) { // BSPTreeLeaf lf = _leafs[i]; // for(int j=lf.leafface; j<lf.leafface+lf.n_leaffaces; j++) { // int faceIndex = _leaffaces[j]; // if(!alreadyVisibleFaces[faceIndex]) { // alreadyVisibleFaces[faceIndex] = true; // visibleFaces.Add(faceIndex); // } // } // } // return visibleFaces; //} // Handle map in the leaf level, so no care face level //ArrayList backfaceCulling(Camera cam, ArrayList visibleFaces) { // ArrayList visible = new ArrayList (); // foreach (int i in visibleFaces) { // BSPFileParser.Face f = _faces[i]; // Vector3 normal = Right2Left(new Vector3(f.normal[0], f.normal[1], f.normal[2])); // if(Vector3.Dot(cam.transform.forward, normal) < BACKCULLINGFACTOR) { // visible.Add(i); // } // } // return visible; //} int findLeafIndex(Vector3 position) { if (position == null) { throw new ArgumentException(); } int index = 0; while (index >= 0) { BSPFileParser.BSPTreeNode node = _nodes[index]; UnityEngine.Plane plane = planes[node.plane]; if (plane.GetSide(position)) { index = node.children[0]; } else { index = node.children[1]; } } // When index < 0, meaning this is a BSP Leaf Index // convert into correct leaf index: -index-1 return(-index - 1); }
internal bool Internal_RaycastRef(Ray ray, ref UIHotSpot.Hit hit) { float single; Vector2 vector2 = new Vector2(); if (this.radius == 0f) { return false; } Plane plane = new Plane(UIHotSpot.forward, this.center); if (!plane.Raycast(ray, out single)) { hit = new UIHotSpot.Hit(); return false; } hit.point = ray.GetPoint(single); hit.normal = (!plane.GetSide(ray.origin) ? UIHotSpot.backward : UIHotSpot.forward); vector2.x = hit.point.x - this.center.x; vector2.y = hit.point.y - this.center.y; float single1 = vector2.x * vector2.x + vector2.y * vector2.y; if (single1 >= this.radius * this.radius) { return false; } hit.distance = Mathf.Sqrt(single1); return true; }
public static CausticDecalPolygon ClipPolygon(CausticDecalPolygon polygon, Plane plane) { bool[] positive = new bool[9]; int positiveCount = 0; for(int i = 0; i < polygon.vertices.Count; i++) { positive[i] = !plane.GetSide( polygon.vertices[i] ); if(positive[i]) positiveCount++; } if(positiveCount == 0) return null; // полностью за плоскостью if(positiveCount == polygon.vertices.Count) return polygon; // полностью перед плоскостью CausticDecalPolygon tempPolygon = new CausticDecalPolygon(); for(int i = 0; i < polygon.vertices.Count; i++) { int next = i + 1; next %= polygon.vertices.Count; if( positive[i] ) { tempPolygon.vertices.Add( polygon.vertices[i] ); } if( positive[i] != positive[next] ) { Vector3 v1 = polygon.vertices[next]; Vector3 v2 = polygon.vertices[i]; Vector3 v = LineCast(plane, v1, v2); tempPolygon.vertices.Add( v ); } } return tempPolygon; }
void OnGUI() { Vector3 position = transform.position + Offset; Plane plane = new Plane( Camera.main.transform.forward, Camera.main.transform.position ); //If the object is behind the camera, then don't draw it if( plane.GetSide( position ) == false ) { return; } //Calculate the 2D position of the position where the icon should be drawn Vector3 viewportPoint = Camera.main.WorldToViewportPoint( position ); //The viewportPoint coordinates are between 0 and 1, so we have to convert them into screen space here Vector2 drawPosition = new Vector2( viewportPoint.x * Screen.width, Screen.height * ( 1 - viewportPoint.y ) ); float clampBorder = 12; //Clamp the position to the edge of the screen in case the icon would be drawn outside the screen drawPosition.x = Mathf.Clamp( drawPosition.x, clampBorder, Screen.width - clampBorder ); drawPosition.y = Mathf.Clamp( drawPosition.y, clampBorder, Screen.height - clampBorder ); GUI.color = Color; GUI.DrawTexture( new Rect( drawPosition.x - Icon.width * 0.5f, drawPosition.y - Icon.height * 0.5f, Icon.width, Icon.height ), Icon ); }
public static bool IsHandInBag(Vector3 pos_) { // The player is supposed to stand up while playing. Vector3 forward = Vector3.zero; if (Mathf.Abs(Vector3.Dot(Vector3.up, _head.forward)) < _tolerance) { Debug.LogWarning("Chosen forward = cam.forward"); forward = _head.forward; } else if (Mathf.Abs(Vector3.Dot(Vector3.up, _head.up)) < _tolerance) { Debug.LogWarning("Chosen forward = cam.up"); forward = _head.up; } else { Debug.LogWarning("Chosen forward = mix"); // Is that ok... ? forward = (_head.forward + _head.up).normalized; } Plane pl = new Plane(forward, _head.position - forward * 0.15f); if (!pl.GetSide(pos_)) { Debug.LogWarning("Point on negative side"); if (pos_.y < _head.position.y) { Debug.LogWarning("Point lower than head"); if (_head.position.y - pos_.y < Hub.playerHeight * 0.45f) { Debug.LogWarning("Point higher than waist"); Vector3 headPosFromTop = _head.position; headPosFromTop.y = 0f; Vector3 handPosFromTop = pos_; handPosFromTop.y = 0f; if ((headPosFromTop - handPosFromTop).magnitude < 0.55f) { Debug.LogWarning("Point within tube"); return true; } } } } else { Debug.LogWarning("Point on positive side"); } return false; }
static public int GetSide(IntPtr l) { try{ UnityEngine.Plane self=(UnityEngine.Plane)checkSelf(l); UnityEngine.Vector3 a1; checkType(l,2,out a1); System.Boolean ret=self.GetSide(a1); pushValue(l,ret); return 1; } catch(Exception e) { LuaDLL.luaL_error(l, e.ToString()); return 0; } }
void GizmosDrawCameraInsideLeaf(Camera cam) { Color tc = Gizmos.color; Color[] cs = new Color[] { Color.gray, Color.yellow, Color.magenta, Color.red }; // from light to dark int colorIndex = 0; Vector3 position = cam.transform.position; // Camera Gizmos.DrawCube(position, new Vector3(200, 200, 200)); int index = 0; while (index >= 0) { Gizmos.color = cs[colorIndex++ % cs.Length]; BSPFileParser.BSPTreeNode node = _nodes[index]; UnityEngine.Plane plane = planes[node.plane]; Bounds b = new Bounds(); b.SetMinMax(new Vector3(node.mins[0], node.mins[1], node.mins[2]), new Vector3(node.maxs[0], node.maxs[1], node.maxs[2])); b = Right2Left(b); // Draw Sub-Space(BSP Tree Node bounding box) Gizmos.DrawWireCube(b.center, b.size); // Draw Split-Plane GizmosDrawPlane(GetOnePointOnPlane(plane), plane.normal, 5000.0f); if (plane.GetSide(position)) { index = node.children[0]; //Debug.Log("Front"); } else { index = node.children[1]; //Debug.Log("Back"); } } // Draw BSP Tree Leaf bounding box BSPFileParser.BSPTreeLeaf lf = _leafs[-index - 1]; Bounds temp = new Bounds(); temp.SetMinMax(new Vector3(lf.mins[0], lf.mins[1], lf.mins[2]), new Vector3(lf.maxs[0], lf.maxs[1], lf.maxs[2])); temp = Right2Left(temp); Gizmos.color = Color.white; Gizmos.DrawWireCube(temp.center, temp.size); Gizmos.color = tc; }
public bool IsPointInside(Mesh aMesh, Vector3 aLocalPoint) { var verts = aMesh.vertices; var tris = aMesh.triangles; int triangleCount = tris.Length / 3; for (int i = 0; i < triangleCount; i++) { var V1 = verts[tris[i * 3]]; var V2 = verts[tris[i * 3 + 1]]; var V3 = verts[tris[i * 3 + 2]]; var P = new Plane(V1, V2, V3); if (P.GetSide(aLocalPoint)) return false; } return true; }
int findLeafIndex(Vector3 position) { if (position == null) { throw new ArgumentException(); } int index = 0; while (index >= 0) { BSPFileParser.BSPTreeNode node = _nodes[index]; UnityEngine.Plane plane = planes[node.plane]; if (plane.GetSide(position)) { index = node.children[0]; } else { index = node.children[1]; } } return(-index - 1); }
static void DrawRotateGUI() { Handles.color = Color.white; ShapeGUI.NameNextHandle("RotateHandle"); EditorGUI.BeginChangeCheck(); Vector3 topCenterWorld = transform.TransformPoint( topCenter ); Vector3 rotateHandle = topCenterWorld + transform.up * HandleUtility.GetHandleSize(topCenterWorld) *.5f; rotateHandle = ShapeGUI.VectorHandle( rotateHandle ); Handles.DrawLine( rotateHandle, transform.TransformPoint( topCenter ) ); Plane plane = new Plane( transform.forward, transform.position ); Ray ray = new Ray( rotateHandle, plane.GetSide(rotateHandle) ? -transform.forward : transform.forward ); float d = 0; plane.Raycast( ray, out d ); rotateHandle = ray.GetPoint(d); Vector3 rotateVector = (rotateHandle - transform.position).normalized; float angle = Vector3.Angle( rotateVector, Vector3.up ); float snappedAngle = Mathf.Round( angle / 15 ) * 15; Vector3 snappedVector = Vector2.up.Rotate( snappedAngle ); if( Event.current.type == EventType.Used ) { isRotating = EditorGUI.EndChangeCheck(); } if( GUI.changed ) { Quaternion newRotation = Quaternion.LookRotation( transform.forward, Event.current.shift ? snappedVector : rotateVector ); if( transform.rotation != newRotation ) { Transform[] parents = new Transform[ shapes.Length ]; for( int i = 0; i < shapes.Length; i++) { Shape shape = shapes[i]; parents[i] = shape.transform.parent; Undo.SetTransformParent( shape.transform, transform, "Rotate Shapes" ); } Undo.RecordObject( transform, "Rotate Shapes" ); transform.rotation = newRotation; for( int i = 0; i < shapes.Length; i++) { Shape shape = shapes[i]; Undo.SetTransformParent( shape.transform, parents[i], "Rotate Shapes" ); } } GUI.changed = false; } }
/// <summary> /// Cut the specified victim, blade_plane and capMaterial. /// </summary> /// <param name="victim">Victim.</param> /// <param name="blade_plane">Blade plane.</param> /// <param name="capMaterial">Cap material.</param> public static GameObject[] Cut(GameObject victim, Vector3 anchorPoint, Vector3 normalDirection, Material capMaterial) { // set the blade relative to victim blade = new Plane(victim.transform.InverseTransformDirection(-normalDirection), victim.transform.InverseTransformPoint(anchorPoint)); // get the victims mesh victim_mesh = victim.GetComponent<MeshFilter>().mesh; // reset values new_vertices.Clear(); left_side.ClearAll(); right_side.ClearAll(); bool[] sides = new bool[3]; int[] indices; int p1,p2,p3; // go throught the submeshes for(int sub=0; sub<victim_mesh.subMeshCount; sub++){ indices = victim_mesh.GetIndices(sub); left_side.subIndices.Add(new List<int>()); right_side.subIndices.Add(new List<int>()); for(int i=0; i<indices.Length; i+=3){ p1 = indices[i]; p2 = indices[i+1]; p3 = indices[i+2]; sides[0] = blade.GetSide(victim_mesh.vertices[p1]); sides[1] = blade.GetSide(victim_mesh.vertices[p2]); sides[2] = blade.GetSide(victim_mesh.vertices[p3]); // whole triangle if(sides[0] == sides[1] && sides[0] == sides[2]){ if(sides[0]){ // left side left_side.AddTriangle(p1,p2,p3,sub); }else{ right_side.AddTriangle(p1,p2,p3,sub); } }else{ // cut the triangle Cut_this_Face(sub, sides, p1, p2, p3); } } } Material[] mats = victim.GetComponent<MeshRenderer>().sharedMaterials; if(mats[mats.Length-1].name != capMaterial.name){ // add cap indices left_side.subIndices.Add(new List<int>()); right_side.subIndices.Add(new List<int>()); Material[] newMats = new Material[mats.Length+1]; mats.CopyTo(newMats, 0); newMats[mats.Length] = capMaterial; mats = newMats; } // cap the opennings Capping(); // Left Mesh Mesh left_HalfMesh = new Mesh(); left_HalfMesh.name = "Split Mesh Left"; left_HalfMesh.vertices = left_side.vertices.ToArray(); left_HalfMesh.triangles = left_side.triangles.ToArray(); left_HalfMesh.normals = left_side.normals.ToArray(); left_HalfMesh.uv = left_side.uvs.ToArray(); left_HalfMesh.subMeshCount = left_side.subIndices.Count; for(int i=0; i<left_side.subIndices.Count; i++) left_HalfMesh.SetIndices(left_side.subIndices[i].ToArray(), MeshTopology.Triangles, i); // Right Mesh Mesh right_HalfMesh = new Mesh(); right_HalfMesh.name = "Split Mesh Right"; right_HalfMesh.vertices = right_side.vertices.ToArray(); right_HalfMesh.triangles = right_side.triangles.ToArray(); right_HalfMesh.normals = right_side.normals.ToArray(); right_HalfMesh.uv = right_side.uvs.ToArray(); right_HalfMesh.subMeshCount = right_side.subIndices.Count; for(int i=0; i<right_side.subIndices.Count; i++) right_HalfMesh.SetIndices(right_side.subIndices[i].ToArray(), MeshTopology.Triangles, i); // assign the game objects victim.name = "left side"; victim.GetComponent<MeshFilter>().mesh = left_HalfMesh; GameObject leftSideObj = victim; GameObject rightSideObj = new GameObject("right side", typeof(MeshFilter), typeof(MeshRenderer)); rightSideObj.transform.position = victim.transform.position; rightSideObj.transform.rotation = victim.transform.rotation; rightSideObj.transform.localScale = victim.transform.localScale; rightSideObj.GetComponent<MeshFilter>().mesh = right_HalfMesh; // assign mats leftSideObj.GetComponent<MeshRenderer>().materials = mats; rightSideObj.GetComponent<MeshRenderer>().materials = mats; return new GameObject[]{ leftSideObj, rightSideObj }; }
private void Split(Plane worldPlane, Vector3 lineStart, Vector3 lineEnd, int casts) { if (!splitting) return; // Sometimes there is null here // Too lazy to find real reason right now if (transform == null) return; float distance = worldPlane.GetDistanceToPoint(transform.position); Plane plane = new Plane(); Vector3 newNormal = transform.InverseTransformDirection(worldPlane.normal); //Vector3 newNormal = Quaternion.Inverse(transform.rotation) * worldPlane.normal; plane.SetNormalAndPosition(newNormal, newNormal * -distance); posNormals.Add(-newNormal); negNormals.Add(newNormal); posNormals.AddRange(mesh.normals); negNormals.AddRange(mesh.normals); for (int i = 0; i < triangles.Length; i += 3) { int i1 = triangles[i];//index 1, 2 and 3 of vertices int i2 = triangles[i + 1]; int i3 = triangles[i + 2]; bool side1 = plane.GetSide(vertices[i1]); bool side2 = plane.GetSide(vertices[i2]); bool side3 = plane.GetSide(vertices[i3]); if (side1 == true && side2 == true && side3 == true) { posTriangles.Add(i1 + 1); //first index is reserved for interior face middle vertex so every index is incremented by 1 posTriangles.Add(i2 + 1); posTriangles.Add(i3 + 1); } else if (side1 == false && side2 == false && side3 == false) { negTriangles.Add(i1 + 1); negTriangles.Add(i2 + 1); negTriangles.Add(i3 + 1); } else { //find odd boolean value(expression found using karnaugh map) bool odd = (!side1 && !side2) || (!side1 && !side3) || (!side2 && !side3); //find vertex with odd boolean value int vertex1, vertex2; if (side1 == odd) { vertex1 = findNewVertex(i1, i2, plane); vertex2 = findNewVertex(i1, i3, plane); if (side1 == true) { // i1 /\ Positive Side posTriangles.Add(i1 + 1); // / \ posTriangles.Add(vertex1 + 1); // vertex1/____\vertex2 posTriangles.Add(vertex2 + 1); // / _-'\ // i2/_.-'____\i3 Negative Side negTriangles.Add(i2 + 1); negTriangles.Add(i3 + 1); negTriangles.Add(vertex2 + 1); negTriangles.Add(i2 + 1); negTriangles.Add(vertex2 + 1); negTriangles.Add(vertex1 + 1); } else { // i1 /\ Negative Side negTriangles.Add(i1 + 1); // / \ negTriangles.Add(vertex1 + 1); // vertex1/____\vertex2 negTriangles.Add(vertex2 + 1); // / _-'\ // i2/_.-'____\i3 Positive Side posTriangles.Add(i2 + 1); posTriangles.Add(i3 + 1); posTriangles.Add(vertex2 + 1); posTriangles.Add(i2 + 1); posTriangles.Add(vertex2 + 1); posTriangles.Add(vertex1 + 1); } } else if (side2 == odd) { vertex1 = findNewVertex(i2, i3, plane); vertex2 = findNewVertex(i2, i1, plane); if (side2 == true) { // i2 /\ Positive Side posTriangles.Add(i2 + 1); // / \ posTriangles.Add(vertex1 + 1); // vertex1/____\vertex2 posTriangles.Add(vertex2 + 1); // / _-'\ // i3/_.-'____\i1 Negative Side negTriangles.Add(i3 + 1); negTriangles.Add(i1 + 1); negTriangles.Add(vertex2 + 1); negTriangles.Add(i3 + 1); negTriangles.Add(vertex2 + 1); negTriangles.Add(vertex1 + 1); } else { // i2 /\ Negative Side negTriangles.Add(i2 + 1); // / \ negTriangles.Add(vertex1 + 1); // vertex1/____\vertex2 negTriangles.Add(vertex2 + 1); // / _-'\ // i3/_.-'____\i1 Positive Side posTriangles.Add(i3 + 1); posTriangles.Add(i1 + 1); posTriangles.Add(vertex2 + 1); posTriangles.Add(i3 + 1); posTriangles.Add(vertex2 + 1); posTriangles.Add(vertex1 + 1); } } else { vertex1 = findNewVertex(i3, i1, plane); vertex2 = findNewVertex(i3, i2, plane); if (side3 == true) { // i3 /\ Positive Side posTriangles.Add(i3 + 1); // / \ posTriangles.Add(vertex1 + 1); // vertex1/____\vertex2 posTriangles.Add(vertex2 + 1); // / _-'\ // i1/_.-'____\i2 Negative Side negTriangles.Add(i1 + 1); negTriangles.Add(i2 + 1); negTriangles.Add(vertex2 + 1); negTriangles.Add(i1 + 1); negTriangles.Add(vertex2 + 1); negTriangles.Add(vertex1 + 1); } else { // i3 /\ Negative Side negTriangles.Add(i3 + 1); // / \ negTriangles.Add(vertex1 + 1); // vertex1/____\vertex2 negTriangles.Add(vertex2 + 1); // / _-'\ // i1/_.-'____\i2 Positive Side posTriangles.Add(i1 + 1); posTriangles.Add(i2 + 1); posTriangles.Add(vertex2 + 1); posTriangles.Add(i1 + 1); posTriangles.Add(vertex2 + 1); posTriangles.Add(vertex1 + 1); } } if (odd == true) { //add inner triangles posInnerTriangles.Add(vertex1 + 2); posInnerTriangles.Add(0); posInnerTriangles.Add(vertex2 + 2); negInnerTriangles.Add(vertex1 + 2); negInnerTriangles.Add(vertex2 + 2); negInnerTriangles.Add(0); } else { negInnerTriangles.Add(vertex1 + 2); negInnerTriangles.Add(0); negInnerTriangles.Add(vertex2 + 2); posInnerTriangles.Add(vertex1 + 2); posInnerTriangles.Add(vertex2 + 2); posInnerTriangles.Add(0); } /*if (odd == true) { //add inner triangles posTriangles.Add(vertex1 + 1); posTriangles.Add(0); posTriangles.Add(vertex2 + 1); negTriangles.Add(vertex1 + 1); negTriangles.Add(vertex2 + 1); negTriangles.Add(0); } else { negTriangles.Add(vertex1 + 1); negTriangles.Add(0); negTriangles.Add(vertex2 + 1); posTriangles.Add(vertex1 + 1); posTriangles.Add(vertex2 + 1); posTriangles.Add(0); }*/ } } //now average all seam vertices to find center of inner face float x = 0; float y = 0; float z = 0; int n = seamVertices.Count; for (int j = 0; j < n; j++) { Vector3 current = seamVertices[j]; x += current.x; y += current.y; z += current.z; } Vector3 center = new Vector3(x / n, y / n, z / n); var newVertices = new List<Vector3>(); newVertices.Add(center); // at index 0 newVertices.AddRange(vertices); // index 1 to vertices.length newVertices.AddRange(seamVertices); // then add the new seam vertices Vector3[] doneVertices = newVertices.ToArray(); Vector2[] uvs = uv.ToArray(); if (posTriangles.Count != 0 && negTriangles.Count != 0)//dont bother creating a gameobject if there are no triangles { Vector3 force = plane.normal * 50f; CreateNewSplit(doneVertices, posTriangles.ToArray(), posInnerTriangles.ToArray(), uvs, posNormals.ToArray(), force); CreateNewSplit(doneVertices, negTriangles.ToArray(), negInnerTriangles.ToArray(), uvs, negNormals.ToArray(), -force); if (OnSplit != null) OnSplit(); } else { return; } splitting = false; PlaneGenerator.OnGeneration -= Split; Destroy(gameObject); }
private void HandleCam() { //Debug.Log(deltaAimAngle_X); //Debug.Log(deltaAimAngle_Y); //Debug.DrawRay(tf.position, deltaAimPos_X, Color.red); //Debug.DrawRay(tf.position, deltaAimPos_Y, Color.green); //Debug.DrawRay(tf.position, Vector3.back * 10.0f); //HORIZONTAL Quaternion newHorRot = GetNewHorCamRot(deltaAimAngle_X); tf.rotation = Quaternion.Slerp(tf.rotation, newHorRot, Time.deltaTime * aimSensitivity); //VERTICAL //if (Mathf.Sign(deltaAimDirec.y) > 0.0f && Vector3.Angle(camTF.forward, Vector3.forward) < 90.0f) Quaternion newVertRot = GetNewVertCamRot(deltaAimAngle_Y); Quaternion finalVertRot = Quaternion.Slerp(camNeckTf.rotation, newVertRot, Time.deltaTime * aimSensitivity); //Debug.DrawRay(camNeckTf.position, finalVertRot * Vector3.forward, Color.red); //planes for limiting player's view rotation (currently generated every frame, this is only ideal if we change the player's orientation, like if gravity changed) Plane forwardPlane = new Plane(tf.forward, camNeckTf.position); Plane upPlane = new Plane(tf.up, camNeckTf.position); if (!forwardPlane.GetSide((finalVertRot * Vector3.forward) + camNeckTf.position)) { //LIMIT UP if (upPlane.GetSide((finalVertRot * Vector3.forward) + camNeckTf.position)) { //Debug.Log("up"); finalVertRot = tf.rotation; finalVertRot *= Quaternion.LookRotation(tf.up, tf.up); } //LIMIT DOWN else { //Debug.Log("down"); finalVertRot = tf.rotation; finalVertRot *= Quaternion.LookRotation(-tf.up, tf.up); } } //Debug.DrawRay(camNeckTf.position, upPlane.normal * 2.0f, Color.blue); camNeckTf.rotation = finalVertRot; }
public void CutMeshToSelectionWithPlanes(Mesh mesh, GameObject meshObject, GameObject selectionArea) { meshObject.GetComponent <MeshFilter>().mesh = mesh; var planes = new OrderedDictionary() { { new Vector3(1, 0, 0), new Vector3(0.5f, 0, 0) }, { new Vector3(-1, 0, 0), new Vector3(-0.5f, 0, 0) }, { new Vector3(0, 1, 0), new Vector3(0, 0.5f, 0) }, { new Vector3(0, -1, 0), new Vector3(0, -0.5f, 0) }, { new Vector3(0, 0, 1), new Vector3(0, 0, 0.5f) }, { new Vector3(0, 0, -1), new Vector3(0, 0, -0.5f) }, }; var meshFilter = gameObject.AddComponent <MeshFilter>(); foreach (var n in planes.Keys) { var point = planes[n]; var res = EzyCut((Vector3)point, (Vector3)n, meshObject, selectionArea, true); MeshFilter newMeshFilter = null; if (res is null) { newMeshFilter = meshObject.GetComponent <MeshFilter>(); } else if (res.Length == 2) { newMeshFilter = res[0].GetComponent <MeshFilter>(); Destroy(res[0]); Destroy(res[1]); } meshFilter.mesh = CutMeshToSelection(meshObject.GetComponent <MeshFilter>().mesh, (vertices) => { var result = new List <int>(); var worldN = selectionArea.transform.TransformDirection((Vector3)n); var worldPoint = selectionArea.transform.TransformPoint((Vector3)point); var plane = new UnityEngine.Plane(worldN, worldPoint); for (var j = 0; j < vertices.Length; j++) { if (!plane.GetSide(vertices[j])) { result.Add(j); } } return(result); }); if (res != null && res.Length == 2) { var listMeshFilters = new List <MeshFilter>() { newMeshFilter, meshFilter }; var combined = CombineMeshes(listMeshFilters); meshFilter.mesh = combined; } meshObject.GetComponent <MeshFilter>().mesh = meshFilter.mesh; } meshObject.SetActive(true); Destroy(meshFilter); }
void Save() { model = transform.root.GetComponentInChildren<SkinnedMeshRenderer>(); if (!Split) return; //foreach (var a in this.transform.root.GetComponentsInChildren<Rigidbody>()) // a.isKinematic = true; var r = model; var lcp = r.transform.localPosition; var lcr = r.transform.localRotation; var lcp2 = r.transform.root.position; var lcr2 = r.transform.root.rotation; r.transform.localPosition = Vector3.zero; r.transform.localRotation = Quaternion.identity; r.transform.root.position = Vector3.zero; r.transform.root.rotation = Quaternion.identity; plane = new Plane(transform.up, transform.position); var sharedMesh = new Mesh(); r.BakeMesh(sharedMesh); vertices = sharedMesh.vertices; var Points = new Point[vertices.Length]; var triangles = sharedMesh.triangles; boneWeights = r.sharedMesh.boneWeights; var bones = new List<Transform>(r.bones); foreach(var a in UpperBones) { var indexOf = bones.IndexOf(a); if (indexOf != -1) ubID.Add(indexOf); } if (ubID.Count == 0) throw new Exception("upper bone not found "); foreach (var a in lowerBones) { var indexOf = bones.IndexOf(a); if (indexOf != -1) lbID.Add(indexOf); } if (lbID.Count == 0) throw new Exception("lower bone not found "); Transform[] bt = UpperBones[0].GetComponentsInChildren<Transform>(); for (int i = 0; i < bt.Length; i++) { var indexOf = bones.IndexOf(bt[i]); if (indexOf != -1) temp.Add(new BoneSave() { boneid = indexOf, i = i }); } Dictionary<KeyValuePair<int, int>, int> dict = new Dictionary<KeyValuePair<int, int>, int>(); for (int i = 0; i < vertices.Length; i++) { Points[i] = new Point(vertices[i]) { index = i }; var side = plane.GetSide(vertices[i]); var v = vertices[i]; v += plane.normal * -plane.GetDistanceToPoint(v); if (this.collider.bounds.Contains(v)) for (int j = 0; j < 4; j++) { var boneid = GetBone(boneWeights[i], j); if (lbID.Contains(boneid) && side) { SetBone(ref boneWeights[i], j, ubID[0]); dict[new KeyValuePair<int, int>(i, j)] = ubID[0]; } if (ubID.Contains(boneid) && !side) { SetBone(ref boneWeights[i], j, lbID[0]); dict[new KeyValuePair<int, int>(i, j)] = lbID[0]; } } } boneSave.Clear(); foreach (var a in dict) boneSave.Add(new BoneSave() { vertex = a.Key.Key, i = a.Key.Value, boneid = a.Value }); triangleSave.Clear(); for (int i = 0; i < triangles.Length / 3; i++) { var index0 = i * 3; Point p0 = Points[triangles[index0]]; Point p1 = Points[triangles[index0 + 1]]; Point p2 = Points[triangles[index0 + 2]]; var sameSide = SameSide(p0, p1) && SameSide(p0, p2) && SameSide(p1, p2); if (drawGizmo) { Debug.DrawLine(p0.pos, p1.pos, sameSide ? Color.blue : Color.red, 5); Debug.DrawLine(p1.pos, p2.pos, sameSide ? Color.blue : Color.red, 5); Debug.DrawLine(p2.pos, p0.pos, sameSide ? Color.blue : Color.red, 5); } if (!sameSide) { triangleSave.Add(index0); triangles[index0] = 0; triangles[index0 + 1] = 0; triangles[index0 + 2] = 0; } } //r.sharedMesh = (Mesh)Instantiate(r.sharedMesh); //r.sharedMesh.boneWeights = boneWeights.ToArray(); //r.sharedMesh.triangles = triangles.ToArray(); SetDirty(); r.transform.localPosition = lcp; r.transform.localRotation = lcr; r.transform.root.position = lcp2; r.transform.root.rotation = lcr2; }
public Vector3 PlaneAvoidance() { makeFeelers(); Plane worldPlane = new Plane(new Vector3(0, 1, 0), 0); Vector3 force = Vector3.zero; foreach (Vector3 feeler in PlaneAvoidanceFeelers) { if (!worldPlane.GetSide(feeler)) { float distance = Math.Abs(worldPlane.GetDistanceToPoint(feeler)); force += worldPlane.normal * distance; } } if (force.magnitude > 0.0) { DrawFeelers(); } return force; }
private bool UpdateRectSelection() { bool flag1 = false; SkinnedMeshRenderer component = this.cloth.GetComponent<SkinnedMeshRenderer>(); Vector3[] normals = this.cloth.normals; ClothSkinningCoefficient[] coefficients = this.cloth.coefficients; float x1 = Mathf.Min(this.m_SelectStartPoint.x, this.m_SelectMousePoint.x); float x2 = Mathf.Max(this.m_SelectStartPoint.x, this.m_SelectMousePoint.x); float y1 = Mathf.Min(this.m_SelectStartPoint.y, this.m_SelectMousePoint.y); float y2 = Mathf.Max(this.m_SelectStartPoint.y, this.m_SelectMousePoint.y); Ray worldRay1 = HandleUtility.GUIPointToWorldRay(new Vector2(x1, y1)); Ray worldRay2 = HandleUtility.GUIPointToWorldRay(new Vector2(x2, y1)); Ray worldRay3 = HandleUtility.GUIPointToWorldRay(new Vector2(x1, y2)); Ray worldRay4 = HandleUtility.GUIPointToWorldRay(new Vector2(x2, y2)); Plane plane1 = new Plane(worldRay2.origin + worldRay2.direction, worldRay1.origin + worldRay1.direction, worldRay1.origin); Plane plane2 = new Plane(worldRay3.origin + worldRay3.direction, worldRay4.origin + worldRay4.direction, worldRay4.origin); Plane plane3 = new Plane(worldRay1.origin + worldRay1.direction, worldRay3.origin + worldRay3.direction, worldRay3.origin); Plane plane4 = new Plane(worldRay4.origin + worldRay4.direction, worldRay2.origin + worldRay2.direction, worldRay2.origin); Quaternion rotation = component.actualRootBone.rotation; for (int index = 0; index < coefficients.Length; ++index) { Vector3 lastVertex = this.m_LastVertices[index]; bool flag2 = (double) Vector3.Dot(rotation * normals[index], Camera.current.transform.forward) <= 0.0; bool flag3 = plane1.GetSide(lastVertex) && plane2.GetSide(lastVertex) && plane3.GetSide(lastVertex) && plane4.GetSide(lastVertex) && (this.state.ManipulateBackfaces || flag2); if (this.m_RectSelection[index] != flag3) { this.m_RectSelection[index] = flag3; flag1 = true; } } return flag1; }
static bool Plane_GetSide__Vector3(JSVCall vc, int argc) { int len = argc; if (len == 1) { UnityEngine.Vector3 arg0 = (UnityEngine.Vector3)JSApi.getVector3S((int)JSApi.GetType.Arg); UnityEngine.Plane argThis = (UnityEngine.Plane)vc.csObj; JSApi.setBooleanS((int)JSApi.SetType.Rval, (System.Boolean)(argThis.GetSide(arg0))); JSMgr.changeJSObj(vc.jsObjID, argThis); } return(true); }
/// <summary> /// Returns true if THIS metric fits inside the given CONTAINER mesh. /// </summary> /// <param name="this_T">Transform of this metric.</param> /// <param name="other_T">Transform of the given mesh.</param> /// <param name="container">Mesh acting as a container.</param> /// Implemeted using algorithm described at /// http://answers.unity3d.com/questions/611947/am-i-inside-a-volume-without-colliders.html public bool FitsAligned(Transform this_T, Transform other_T, Mesh container) { //get edges in containers reference frame var edges = hull != null? hull.Points.ToArray() : BoundsEdges(bounds); //check each triangle of container var c_edges = container.vertices; var triangles = container.triangles; if(triangles.Length/3 > edges.Length) { for(int i = 0; i < edges.Length; i++) edges[i] = other_T.InverseTransformPoint(this_T.position+this_T.TransformDirection(edges[i]-center)); for(int i = 0; i < triangles.Length/3; i++) { var V1 = c_edges[triangles[i*3]]; var V2 = c_edges[triangles[i*3+1]]; var V3 = c_edges[triangles[i*3+2]]; var P = new Plane(V1, V2, V3); foreach(Vector3 edge in edges) { if(!P.GetSide(edge)) return false; } } } else { var planes = new Plane[triangles.Length/3]; for(int i = 0; i < triangles.Length/3; i++) { var V1 = c_edges[triangles[i*3]]; var V2 = c_edges[triangles[i*3+1]]; var V3 = c_edges[triangles[i*3+2]]; planes[i] = new Plane(V1, V2, V3); } for(int i = 0; i < edges.Length; i++) { var edge = other_T.InverseTransformPoint(this_T.position+this_T.TransformDirection(edges[i]-center)); foreach(Plane P in planes) { if(!P.GetSide(edge)) return false; } } } return true; }
private bool UpdateRectSelection() { bool flag = false; SkinnedMeshRenderer component = this.cloth.GetComponent<SkinnedMeshRenderer>(); Vector3[] normals = this.cloth.normals; ClothSkinningCoefficient[] coefficients = this.cloth.coefficients; float x = Mathf.Min(this.m_SelectStartPoint.x, this.m_SelectMousePoint.x); float num2 = Mathf.Max(this.m_SelectStartPoint.x, this.m_SelectMousePoint.x); float y = Mathf.Min(this.m_SelectStartPoint.y, this.m_SelectMousePoint.y); float num4 = Mathf.Max(this.m_SelectStartPoint.y, this.m_SelectMousePoint.y); Ray ray = HandleUtility.GUIPointToWorldRay(new Vector2(x, y)); Ray ray2 = HandleUtility.GUIPointToWorldRay(new Vector2(num2, y)); Ray ray3 = HandleUtility.GUIPointToWorldRay(new Vector2(x, num4)); Ray ray4 = HandleUtility.GUIPointToWorldRay(new Vector2(num2, num4)); Plane plane = new Plane(ray2.origin + ray2.direction, ray.origin + ray.direction, ray.origin); Plane plane2 = new Plane(ray3.origin + ray3.direction, ray4.origin + ray4.direction, ray4.origin); Plane plane3 = new Plane(ray.origin + ray.direction, ray3.origin + ray3.direction, ray3.origin); Plane plane4 = new Plane(ray4.origin + ray4.direction, ray2.origin + ray2.direction, ray2.origin); Quaternion rotation = component.actualRootBone.rotation; for (int i = 0; i < coefficients.Length; i++) { Vector3 inPt = this.m_LastVertices[i]; bool flag2 = Vector3.Dot((Vector3) (rotation * normals[i]), Camera.current.transform.forward) <= 0f; bool flag3 = (((plane.GetSide(inPt) && plane2.GetSide(inPt)) && plane3.GetSide(inPt)) && plane4.GetSide(inPt)) && (this.state.ManipulateBackfaces || flag2); if (this.m_RectSelection[i] != flag3) { this.m_RectSelection[i] = flag3; flag = true; } } return flag; }
/** * Slice the gameobject mesh (if any) using the Plane, which will generate * a maximum of 2 other Meshes. * This function will recalculate new UV coordinates to ensure textures are applied * properly. * Returns null if no intersection has been found or the GameObject does not contain * a valid mesh to cut. */ public static SlicedHull Slice(Mesh sharedMesh, Plane pl, TextureRegion region, int crossIndex, bool intersectionOnly = false) { if (sharedMesh == null) { return(null); } Vector3[] verts = sharedMesh.vertices; Vector2[] uv = sharedMesh.uv; Vector3[] norm = sharedMesh.normals; Vector4[] tan = sharedMesh.tangents; int submeshCount = sharedMesh.subMeshCount; // each submesh will be sliced and placed in its own array structure SlicedSubmesh[] slices = new SlicedSubmesh[submeshCount]; // the cross section hull is common across all submeshes List <Vector3> crossHull = new List <Vector3>(); // we reuse this object for all intersection tests IntersectionResult result = new IntersectionResult(); // see if we would like to split the mesh using uv, normals and tangents bool genUV = verts.Length == uv.Length; bool genNorm = verts.Length == norm.Length; bool genTan = verts.Length == tan.Length; // iterate over all the submeshes individually. vertices and indices // are all shared within the submesh for (int submesh = 0; submesh < submeshCount; submesh++) { int[] indices = sharedMesh.GetTriangles(submesh); int indicesCount = indices.Length; SlicedSubmesh mesh = new SlicedSubmesh(); // loop through all the mesh vertices, generating upper and lower hulls // and all intersection points for (int index = 0; index < indicesCount; index += 3) { int i0 = indices[index + 0]; int i1 = indices[index + 1]; int i2 = indices[index + 2]; Triangle newTri = new Triangle(verts[i0], verts[i1], verts[i2]); // generate UV if available if (genUV) { newTri.SetUV(uv[i0], uv[i1], uv[i2]); } // generate normals if available if (genNorm) { newTri.SetNormal(norm[i0], norm[i1], norm[i2]); } // generate tangents if available if (genTan) { newTri.SetTangent(tan[i0], tan[i1], tan[i2]); } // slice this particular triangle with the provided // plane result.Clear(); if (newTri.Split(pl, result)) { int upperHullCount = result.upperHullCount; int lowerHullCount = result.lowerHullCount; int interHullCount = result.intersectionPointCount; for (int i = 0; i < upperHullCount; i++) { mesh.upperHull.Add(result.upperHull[i]); } for (int i = 0; i < lowerHullCount; i++) { mesh.lowerHull.Add(result.lowerHull[i]); } for (int i = 0; i < interHullCount; i++) { crossHull.Add(result.intersectionPoints[i]); } } else if (!intersectionOnly) { var unityPl = new UnityEngine.Plane(pl.normal, pl.pos); if (unityPl.GetSide(verts[i0]) && unityPl.GetSide(verts[i1]) && unityPl.GetSide(verts[i2])) { mesh.upperHull.Add(newTri); } else { mesh.lowerHull.Add(newTri); } } } // register into the index slices[submesh] = mesh; } // check if slicing actually occured for (int i = 0; i < slices.Length; i++) { // check if at least one of the submeshes was sliced. If so, stop checking // because we need to go through the generation step if (slices[i] != null && slices[i].isValid) { return(CreateFrom(slices, CreateFrom(crossHull, pl.normal, region), crossIndex)); } } // no slicing occured, just return null to signify return(null); }
public void SliceMyMesh() { if (MyMesh) { //GameObject SlicedMesh = (GameObject) Instantiate (gameObject, transform.position, Quaternion.identity); // off set the positions after the meshes are created, by finding out the releative bounds difference SlicedCustomMesh1 = (CustomMesh) gameObject.GetComponent("CustomMesh"); //SlicedCustomMesh2 = (CustomMesh) SlicedMesh.GetComponent("CustomMesh"); //SlicedCustomMesh2.IsSingleCube = false; //MyPlaneNormal = MyPlaneRotation.transform.position; MySlicePlane = new Plane(MyPlaneNormal, PlaneDistance); MySlicePlane.SetNormalAndPosition(MyPlaneNormal, new Vector3(0,0.5f,0)); SlicedPoints1 = new List<Vector3>(); SlicedIndicies1 = new List<int>(); SlicedPoints2 = new List<Vector3>(); SlicedIndicies2 = new List<int>(); // Where the plane intersects SlicedIndicies3 = new List<int>(); SlicedIndicies4 = new List<int>(); SlicedPoints4 = new List<Vector3>(); //SlicedMesh.MyCustomMesh // Add all the indicies that intersect with the plane for (int i = 0; i < SlicedCustomMesh1.MyCustomMesh.Indicies.Count; i += 3) { // for all the meshes triangles Vector3 Vertex1 = SlicedCustomMesh1.MyCustomMesh.Verticies[SlicedCustomMesh1.MyCustomMesh.Indicies[i]]; Vector3 Vertex2 = SlicedCustomMesh1.MyCustomMesh.Verticies[SlicedCustomMesh1.MyCustomMesh.Indicies[i+1]]; Vector3 Vertex3 = SlicedCustomMesh1.MyCustomMesh.Verticies[SlicedCustomMesh1.MyCustomMesh.Indicies[i+2]]; if (MySlicePlane.GetSide(Vertex1+MyPlanePosition) && MySlicePlane.GetSide(Vertex2+MyPlanePosition) && MySlicePlane.GetSide(Vertex3+MyPlanePosition)) { // if all 3 verticies are on the same side } else if (!MySlicePlane.GetSide(Vertex1+MyPlanePosition) && !MySlicePlane.GetSide(Vertex2+MyPlanePosition) && !MySlicePlane.GetSide(Vertex3+MyPlanePosition)) { // if they are not on same side, they are intersected by the plane } else { SlicedIndicies3.Add(SlicedCustomMesh1.MyCustomMesh.Indicies[i]); SlicedIndicies3.Add(SlicedCustomMesh1.MyCustomMesh.Indicies[i+1]); SlicedIndicies3.Add(SlicedCustomMesh1.MyCustomMesh.Indicies[i+2]); SlicedPoints3.Add (Vertex1); SlicedPoints3.Add (Vertex2); SlicedPoints3.Add (Vertex3); } } // Now create slices in these triangles for (int i = 0; i < SlicedIndicies3.Count; i += 3) { // for all the meshes triangles Vector3 Vertex1 = SlicedCustomMesh1.MyCustomMesh.Verticies[SlicedIndicies3[i]]; Vector3 Vertex2 = SlicedCustomMesh1.MyCustomMesh.Verticies[SlicedIndicies3[i+1]]; Vector3 Vertex3 = SlicedCustomMesh1.MyCustomMesh.Verticies[SlicedIndicies3[i+2]]; // from a slice through a triangle // we can get a maximum of 5 points // break down 5 points into 3 triangles // test this by chose random points along the triangle lines and adding them vertexes //RaycastHit hit1; Ray Ray1 = new Ray(Vertex1, Vertex1-Vertex2); float RayDistance1 = Vector3.Distance (Vertex1, Vertex2); if (MySlicePlane.Raycast(Ray1, out RayDistance1)) { Debug.Log(" Triangles are sliced 1" ); DebugVector3 (SlicedCustomMesh1.MyCustomMesh.Verticies[SlicedIndicies3[i]]); } else { Debug.Log(i + " Triangles Not Sliced Vertex 1 - "); Debug.Log (" Distance: " + RayDistance1); DebugVector3 (Vertex1); DebugVector3 (Vertex1 + Ray1.direction*RayDistance1); if (RayDistance1 != 0) { SlicedIndicies4.Add (i); SlicedPoints4.Add (Vertex1 + Ray1.direction*RayDistance1); //SlicedCustomMesh1.MyCustomMesh.Verticies[SlicedIndicies3[i]] = Vertex1 + Ray1.direction*RayDistance1; } } Ray Ray2 = new Ray(Vertex2, Vertex2-Vertex3); float RayDistance2 = Vector3.Distance (Vertex1, Vertex2); if (MySlicePlane.Raycast(Ray2, out RayDistance2)) { Debug.Log(" Triangles are sliced 2" ); SlicedCustomMesh1.MyCustomMesh.Verticies[SlicedIndicies3[i]] = Vertex2 + Ray2.direction*RayDistance2; } else { Debug.Log(i + " Triangles Not Sliced 2 - "); Debug.Log (" Distance: " + RayDistance2); DebugVector3 (Vertex2); DebugVector3 (Vertex2 + Ray2.direction*RayDistance2); if (RayDistance2 != 0) { SlicedIndicies4.Add (i+1); SlicedPoints4.Add (Vertex2 + Ray2.direction*RayDistance2); //SlicedCustomMesh1.MyCustomMesh.Verticies[SlicedIndicies3[i]] = Vertex2 + Ray2.direction*RayDistance2; } } Ray Ray3 = new Ray(Vertex3, Vertex3-Vertex1); float RayDistance3 = Vector3.Distance (Vertex3, Vertex1); if (MySlicePlane.Raycast(Ray3, out RayDistance3)) { Debug.Log(" Triangles are sliced 3" ); DebugVector3 (Vertex2); SlicedCustomMesh1.MyCustomMesh.Verticies[SlicedIndicies3[i]] = Vertex3 + Ray3.direction*RayDistance3; } else { Debug.Log(i + " Triangles a Not Sliced 3 -"); Debug.Log (" Distance: " + RayDistance3); DebugVector3 (Vertex3); DebugVector3 (Vertex3 + Ray3.direction*RayDistance3); if (RayDistance3 != 0) { SlicedIndicies4.Add (i+2); SlicedPoints4.Add (Vertex3 + Ray3.direction*RayDistance3); //SlicedCustomMesh1.MyCustomMesh.Verticies[SlicedIndicies3[i]] = Vertex3 + Ray3.direction*RayDistance3; } } //Mathf.Int } // test slice through the middle, where the plane is .5, .5 ,.5 // Concieve a 2d plane that is the slice (sword action pewpew) // find all the intersecting points with the mesh for (int i = 0; i < SlicedCustomMesh1.MyCustomMesh.Indicies.Count; i += 3) { // for all the meshes triangles //SlicedCustomMesh2.MyCustomMesh.Indicies[i] = 0; Vector3 Vertex1 = SlicedCustomMesh1.MyCustomMesh.Verticies[SlicedCustomMesh1.MyCustomMesh.Indicies[i]]; Vector3 Vertex2 = SlicedCustomMesh1.MyCustomMesh.Verticies[SlicedCustomMesh1.MyCustomMesh.Indicies[i+1]]; Vector3 Vertex3 = SlicedCustomMesh1.MyCustomMesh.Verticies[SlicedCustomMesh1.MyCustomMesh.Indicies[i+2]]; // if our vertexes are on the positive side of the plane, add to mesh 1 //if (Vertex1.y > 0.5f) { if (MySlicePlane.GetSide(Vertex1) && MySlicePlane.GetSide(Vertex2) && MySlicePlane.GetSide(Vertex3)) { // if all 3 verticies are on the same side SlicedIndicies1.Add(SlicedCustomMesh1.MyCustomMesh.Indicies[i]); SlicedIndicies1.Add(SlicedCustomMesh1.MyCustomMesh.Indicies[i+1]); SlicedIndicies1.Add(SlicedCustomMesh1.MyCustomMesh.Indicies[i+2]); //} else { } else if (!MySlicePlane.GetSide(Vertex1) && !MySlicePlane.GetSide(Vertex2) && !MySlicePlane.GetSide(Vertex3)){ // if they are not on same side, they are intersected by the plane SlicedIndicies2.Add(SlicedCustomMesh1.MyCustomMesh.Indicies[i]); SlicedIndicies2.Add(SlicedCustomMesh1.MyCustomMesh.Indicies[i+1]); SlicedIndicies2.Add(SlicedCustomMesh1.MyCustomMesh.Indicies[i+2]); } } //for (int i = 0; i < 0 // Add all the points onto 2 new meshes // Add the rest of the meshes points onto the 2 created ones // Instantiate the new objects in the points it was cut // test this with non moving objects for positioning //SlicedCustomMesh1.MyCustomMesh.Verticies = SlicedPoints1; if (IsSlice) { SlicedCustomMesh1.MyCustomMesh.Indicies.Clear (); //SlicedCustomMesh1.MyCustomMesh.Indicies = SlicedIndicies1; SlicedCustomMesh1.MyCustomMesh.Indicies = SlicedIndicies3; //SlicedCustomMesh2.MyCustomMesh.Indicies.Clear (); //SlicedCustomMesh2.MyCustomMesh.Indicies = SlicedIndicies2; //SlicedCustomMesh1.MyCustomMesh.Refresh(SlicedPoints1, SlicedIndicies1, SlicedCustomMesh1.MyCustomMesh.TextureCoordinates); //SlicedCustomMesh2.MyCustomMesh.Refresh(SlicedPoints2, SlicedIndicies2, SlicedCustomMesh2.MyCustomMesh.TextureCoordinates); SlicedCustomMesh1.UpdateMesh(SlicedCustomMesh1.MyCustomMesh); //SlicedCustomMesh2.UpdateMesh(SlicedCustomMesh2.MyCustomMesh); } } }
public void _StrokePath() { Terrain ter = (Terrain) GetComponent(typeof(Terrain)); if (ter == null) { Debug.LogError("No terrain component on this GameObject"); return; } int Px = 0; int Py = 0; try { TerrainData terData = ter.terrainData; int Tw = terData.heightmapWidth; //heightMapResolution in pixels int Th = terData.heightmapHeight;//heightMapResolution in pixels Vector3 Ts = terData.size; //x and z and height of terrain if (VERBOSE) Debug.Log("terrainData heightmapHeight/heightmapWidth:" + Tw + " " + Tw); if (VERBOSE) Debug.Log("terrainData heightMapResolution:" + terData.heightmapResolution); if (VERBOSE) Debug.Log("terrainData size:" + terData.size); Vector3 ls = transform.localScale; //need to remember and reset the scale because the InverseTransform does not work properly for terrains because they ignore the scale transform.localScale = new Vector3(1.0f,1.0f,1.0f); List<Vector3> controlPointsLocal = new List<Vector3>();//[controlPoints.Count]; for (int i = 0; i < controlPoints.Count; i++){ //don't use inverse transform point because terrain ignores rotation and scale controlPointsLocal.Add( controlPoints[i] - transform.position ); } //Vector3 localBeginPosition = transform.InverseTransformPoint(beginRamp); //Vector3 localEndPosition = transform.InverseTransformPoint(endRamp); transform.localScale = ls; // int[] pi = terrainCordsToBitmap(terData,localBeginPosition); // int[] pf = terrainCordsToBitmap(terData,localEndPosition); for (int i = 0; i < controlPointsLocal.Count; i++){ int[] p = terrainCordsToBitmap(terData,controlPointsLocal[i]); if (p[0] < 0 || p[1] < 0 || p[0] >= Tw || p[1] >= Th){ Debug.LogError("The start point or the end point was out of bounds. Make sure the gizmo is over the terrain before setting the start and end points." + "Note: that sometimes Unity does not update the collider after changing settings in the 'Set Resolution' dialog. Entering play mode should reset the collider."); return; } } int Sx = (int) Mathf.Floor((Tw / Ts.z) * brushSize); //the x and z are mixed up intentionally int Sz = (int) Mathf.Floor((Th / Ts.x) * brushSize); //the x and z are mixed up intentionally float[,] heightMapAll = terData.GetHeights(0, 0, Tw, Th); //calculate plane. n is plane normal, localEnd and localBegin are in plane. //plane uses terrain cord system, y coordinate is in terrain height units, not world units. for (int i = 0; i < controlPointsLocal.Count; i++){ int[] p = terrainCordsToBitmap(terData,controlPointsLocal[i]); Vector3 v = controlPointsLocal[i]; v.y = heightMapAll[p[0],p[1]]; controlPointsLocal[i] = v; } calculateDistBetweenPoints(controlPointsLocal); calculateDistBetweenPointsInPixels(controlPointsLocal,terData); float timeIncrement = (float) (brushSampleDensity) / _totalLengthPixels; float timeBrushWidth = (float) (brushSize) / _totalLengthPixels; //the width of the brush in parameterized t Debug.Log("Sample w " + Sx + " h " + Sz); Debug.Log("parameterized brush width " + timeBrushWidth); if (timeBrushWidth > .5f) timeBrushWidth = .5f; if (VERBOSE){ for (int i = 0; i < controlPointsLocal.Count; i++){ int[] pi = terrainCordsToBitmap(terData,controlPointsLocal[i]); float[] temp = bitmapCordsToTerrain(terData,pi[0],pi[1]); Debug.Log(i + " Local control Pos:" + controlPointsLocal[i]); Debug.Log(i + " pixel begin coord:" + pi[0] + " " + pi[0]); Debug.Log(i + " Local begin Pos Rev Transformed:" + temp[0] + " " + temp[1]); } Debug.Log("parameterized brush width " + timeBrushWidth); } StringBuilder sb = new StringBuilder(); for(float t = 0.0f; t <= 1.0f; t += timeIncrement){ Ray psamp = parameterizedLine(t,controlPointsLocal); //localBeginPosition + t * (v1); Vector3 n = Vector3.Cross(new Vector3(-psamp.direction.z, 0.0f, psamp.direction.x), psamp.direction); n.Normalize(); if (spacingJitter > 0f){ float tt = 2f*Mathf.PI*UnityEngine.Random.value; float u = UnityEngine.Random.value+UnityEngine.Random.value; float r; if (u > 1f) { r = 2f-u; } else { r = u; } r *= spacingJitter * brushSize; Vector3 randV = new Vector3(r*Mathf.Cos(tt), 0f, r*Mathf.Sin(tt)); if (VERBOSE) Debug.Log("jittering by " + randV + " dir " + psamp.direction + " n " + n); Plane p = new Plane(n,psamp.origin); float ttt; Ray rr = new Ray(psamp.origin + randV,Vector3.up); if (p.Raycast(rr,out ttt)){ Vector3 vv = rr.origin + rr.direction * ttt; psamp.origin = vv; } } Plane beginClipPlane; Plane endClipPlane; beginClipPlane = new Plane((controlPointsLocal[0]-controlPointsLocal[1]).normalized, controlPointsLocal[0]); endClipPlane = new Plane((controlPointsLocal[controlPointsLocal.Count - 1]-controlPointsLocal[controlPointsLocal.Count - 2]).normalized, controlPointsLocal[controlPointsLocal.Count - 1]); int[] pv = terrainCordsToBitmap(terData, psamp.origin); Px = pv[0] - Sx/2; Py = pv[1] - Sz/2; float[,] heightMap = new float[Sx,Sz]; //little brush size heightmap for (int i = 0; i < Sx; i ++){ for (int j = 0; j < Sz; j++){ if (Px + i >= 0 && Py + j >=0 && Px + i < Tw && Py + j < Th) { heightMap[i,j] = heightMapAll[Px + i,Py + j] ; } else { heightMap[i,j] = 0; } } } // build a perfect ramp that is size of brush float[,] erodedheightMap = (float[,]) heightMap.Clone(); for (int Tx = 0; Tx < Sx; Tx++) { for (int Tz = 0; Tz < Sz; Tz++) { float[] My = bitmapCordsToTerrain(terData, (Px + Tx), (Py + Tz)); //don't ramp points before begin position or after end position Vector3 myV = new Vector3(My[0],0f,My[1]); Boolean clipThisPoint = false; if (beginClipPlane.GetSide(myV) && t < timeBrushWidth/2f){ clipThisPoint = true; } else if (endClipPlane.GetSide(myV) && t > 1f - timeBrushWidth/2f){ clipThisPoint = true; } if (!clipThisPoint){ //do raycast from zero straight against slope Plane p = new Plane(n,psamp.origin); Ray r = new Ray(myV,Vector3.up); float tt; if (!p.Raycast(r, out tt))continue; // sb.AppendFormat("n{0} psamp{1} r{2} t{3}\n",n,psamp.ToString("f5"),r,t); erodedheightMap[Tx,Tz] = r.origin.y + r.direction.y * tt; // Debug.Log("hm " + erodedheightMap[Tx,Tz] + " " + heightMap[Tx,Tz]); } } } // Blend it to the terrain object float sampleRadius = Mathf.Min(Sz/2.0f, Sx/2.0f); for (int Tx = 0; Tx < Sx; Tx++) { for (int Ty = 0; Ty < Sz; Ty++) { float newHeightAtPoint = erodedheightMap[Tx, Ty]; float oldHeightAtPoint = heightMap[Tx, Ty]; float distanceFromCenter = Vector2.Distance(new Vector2(Tx, Ty), new Vector2(sampleRadius, sampleRadius)); float weightAtPoint = (1.0f - distanceFromCenter / sampleRadius ) / brushSoftness; if (weightAtPoint < 0.0f) { weightAtPoint = 0.0f; } else if (weightAtPoint > 1.0f) { weightAtPoint = 1.0f; } weightAtPoint *= brushOpacity; float blendedHeightAtPoint = (newHeightAtPoint * weightAtPoint) + (oldHeightAtPoint * (1.0f - weightAtPoint)); heightMap[Tx, Ty] = blendedHeightAtPoint; } } for (int i = 0; i < Sx; i ++){ for (int j = 0; j < Sz; j++){ if (Px + i >= 0 && Py + j >=0 && Px + i < Tw && Py + j < Th) { heightMapAll[Px + i,Py + j] = heightMap[i,j]; } } } } Debug.Log(sb); terData.SetHeights(0,0,heightMapAll); //beginRamp = endRamp; } catch (Exception e) { Debug.LogError("A brush error occurred: "+e); } }
void Fracture(Vector3 point, Vector3 force, float iterations){ MeshFilter thisMeshFilter = gameObject.GetComponent<MeshFilter>(); if(instantiateOnBreak && force.magnitude >= Mathf.Max(minBreakingForce, forcePerDivision)){ if(Network.isServer || Network.isClient) Network.Instantiate(instantiateOnBreak, transform.position, transform.rotation,0); else Instantiate(instantiateOnBreak, transform.position, transform.rotation); instantiateOnBreak=null; } while (iterations > 0){ if(totalMaxFractures == 0 || Vector3.Min(thisMeshFilter.mesh.bounds.size, minFractureSize) != minFractureSize){ if(destroySmallAfterTime >= 1.0f) Destroy(gameObject, destroySmallAfterTime); totalMaxFractures = 0; return; } totalMaxFractures--; iterations--; if(fractureAtCenter) point = thisMeshFilter.mesh.bounds.center; Vector3 vec = Vector3.Scale(grain,Random.insideUnitSphere).normalized; Vector3 sub = transform.worldToLocalMatrix.MultiplyVector(force.normalized)*(useCollisionDirection ? 1 : 0)*Vector3.Dot(transform.worldToLocalMatrix.MultiplyVector(force.normalized),vec); //Vector3 sub = transform.worldToLocalMatrix.MultiplyVector(force.normalized)*useCollisionDirection*Vector3.Dot(transform.worldToLocalMatrix.MultiplyVector(force.normalized),vec); Plane plane = new Plane(vec-sub,Vector3.Scale(Random.insideUnitSphere, thisMeshFilter.mesh.bounds.size)*randomOffset+point); GameObject newObject; if(Network.isServer || Network.isClient){ newObject = _PublicData._PublicProperties.minePlayer.networkView.RPC("CreateCopyLocally",RPCMode.OthersBuffered,gameObject.transform); //newObject = Network.Instantiate(gameObject.transform, transform.position, transform.rotation,0) as GameObject; } else newObject = Instantiate(gameObject.transform, transform.position, transform.rotation) as GameObject; MeshFilter newObjectMeshFilter = newObject.GetComponent<MeshFilter>(); if(avoidSelfCollision) IgnoreCollision(newObject.collider,gameObject.collider); if(rigidbody) newObject.rigidbody.velocity = rigidbody.velocity; Vector3[] vertsA = thisMeshFilter.mesh.vertices; Vector3[] vertsB = newObjectMeshFilter.mesh.vertices; Vector3 average = Vector3.zero; foreach(Vector3 i in vertsA) average+=i; average /= thisMeshFilter.mesh.vertexCount; average -= plane.GetDistanceToPoint(average)*plane.normal; int broken = 0; if(fractureToPoint){ for(int i=0;i<thisMeshFilter.mesh.vertexCount;i++){ if(plane.GetSide(vertsA[i])){ vertsA[i] = average; broken++; } else vertsB[i] = average; } } else{ for(int ii=0;ii<thisMeshFilter.mesh.vertexCount;ii++){ if(plane.GetSide(vertsA[ii])){ vertsA[ii] -= plane.GetDistanceToPoint(vertsA[ii])*plane.normal; broken++; } else vertsB[ii] -= plane.GetDistanceToPoint(vertsB[ii])*plane.normal; } } if(broken == 0 || broken == thisMeshFilter.mesh.vertexCount){ totalMaxFractures++; iterations++; Destroy(newObject); //yield return null; //mmm } else{ thisMeshFilter.mesh.vertices = vertsA; newObjectMeshFilter.mesh.vertices = vertsB; thisMeshFilter.mesh.RecalculateNormals(); newObjectMeshFilter.mesh.RecalculateNormals(); thisMeshFilter.mesh.RecalculateBounds(); newObjectMeshFilter.mesh.RecalculateBounds(); MeshCollider thisMeshCol = gameObject.GetComponent<MeshCollider>(); if(thisMeshCol){ thisMeshCol.sharedMesh = thisMeshFilter.mesh; newObject.GetComponent<MeshCollider>().sharedMesh = newObjectMeshFilter.mesh; //mmm } else{ Destroy(collider); Destroy(gameObject, 1.0f); } } if(smartJoints){ Joint[] jointsb = GetComponents<Joint>(); if(jointsb.Length>0){ for(int iii=0;iii<jointsb.Length;iii++){ if(jointsb[iii].connectedBody!=null && plane.GetSide(transform.worldToLocalMatrix.MultiplyPoint(jointsb[iii].connectedBody.transform.position))){ Joint[] tmpJoints = jointsb[iii].gameObject.GetComponent<ObjectDestruction>().joints; if(tmpJoints.Length>0){ foreach(Joint j in tmpJoints){ //if(j == jointsb[iii]) j=newObject.GetComponents<Joint>()[iii]; //mmm } } Destroy(jointsb[iii]); } else{ Destroy(newObject.GetComponents<Joint>()[iii]); } } } if(joints!=null){ ArrayList temp; for(int iiii=0;iiii<joints.Length;iiii++){ if(joints[iiii] && plane.GetSide(transform.worldToLocalMatrix.MultiplyPoint(joints[iiii].transform.position))){ joints[iiii].connectedBody=newObject.rigidbody; temp = new ArrayList(joints); temp.RemoveAt(iiii); joints = (Joint[]) temp.ToArray(typeof(Joint)); } else{ temp = new ArrayList(joints); temp.RemoveAt(iiii); newObject.GetComponent<ObjectDestruction>().joints = (Joint[]) temp.ToArray(typeof(Joint)); } } } } else{ if(GetComponent<Joint>()){ Joint[] jnts = GetComponents<Joint>(); Joint[] newjnts = GetComponents<Joint>(); for(int i_i=0;i_i<jnts.Length;i_i++){ Destroy(jnts[i_i]); Destroy(newjnts[i_i]); } } if(joints != null){ foreach(Joint jnt in joints){ Destroy(jnt); } joints=null; } } if(!rigidbody){ gameObject.AddComponent<Rigidbody>(); newObject.AddComponent<Rigidbody>(); rigidbody.mass = totalMassIfStatic; newObject.rigidbody.mass = totalMassIfStatic; } gameObject.rigidbody.mass *= .5f; newObject.rigidbody.mass *= .5f; gameObject.rigidbody.centerOfMass = transform.worldToLocalMatrix.MultiplyPoint3x4(gameObject.collider.bounds.center); newObject.rigidbody.centerOfMass = transform.worldToLocalMatrix.MultiplyPoint3x4(newObject.collider.bounds.center); newObject.GetComponent<ObjectDestruction>().Fracture(point,force,iterations); if(destroyAllAfterTime>=1){ Destroy(newObject.GetComponent<MeshCollider>(), destroyAllAfterTime-1); Destroy(gameObject.GetComponent<MeshCollider>(), destroyAllAfterTime-1); Destroy(newObject, destroyAllAfterTime); Destroy(gameObject, destroyAllAfterTime); } //yield return null;//hmmm } if(totalMaxFractures == 0 || Vector3.Min(thisMeshFilter.mesh.bounds.size,minFractureSize)!=minFractureSize){ if(destroySmallAfterTime>=1){ Destroy(GetComponent<MeshCollider>(), destroySmallAfterTime-1); Destroy(gameObject, destroySmallAfterTime); } totalMaxFractures = 0; } }
//Calculate the plane for reflection in World Space. private static Plane ReflectionPlane(Vector3 viewerPos, Vector3 mirrorPos, Vector3 mirrorDir, float clipOffset) { float d = -Vector3.Dot (mirrorDir, mirrorPos) - clipOffset; Plane reflectionPlane = new Plane (mirrorDir, d); if (!reflectionPlane.GetSide (viewerPos)) { // Flip the reflection plane if the camera is behide mirrorDir = -mirrorDir; d = -Vector3.Dot (mirrorDir, mirrorPos) - clipOffset; reflectionPlane = new Plane (mirrorDir, d); } return reflectionPlane; }
/** * Splits a vertex in two along a plane. Returns true if the vertex can be split, false otherwise. Does not create new border * edges inside the tear in order to prevent non-manifold vertices emerging, so it is only suitable for realtime cloth tearing. * \param vertex the vertex to split. * \param splitPlane plane to split the vertex at. * \param newVertex the newly created vertex after the split operation has been performed. * \param vertices new mesh vertices list after the split operation. * \param removedEdges list of edge ids removed after splitting the vertex. * \param addedEdges list of edge ids added after splitting the vertex. * \param oldAndNewEdges a dictionary relating old and new edge ids. */ public bool SplitVertex(HEVertex vertex, Plane splitPlane, out HEVertex newVertex, out Vector3[] vertices, out HashSet<int> removedEdges, out HashSet<int> addedEdges, out Dictionary<int,int> oldAndNewEdges) { // initialize return values: removedEdges = new HashSet<int>(); addedEdges = new HashSet<int>(); oldAndNewEdges = new Dictionary<int,int>(); newVertex = null; // initialize face lists for each side of the split plane. List<HEFace> side1Faces = new List<HEFace>(); List<HEFace> side2Faces = new List<HEFace>(); HashSet<int> side2Edges = new HashSet<int>(); // Get a copy of mesh vertices: vertices = input.vertices; // classify adjacent faces depending on which side of the cut plane they reside in: foreach(HEFace face in GetNeighbourFacesEnumerator(vertex)){ int v1 = heEdges[face.edges[0]].startVertex; int v2 = heEdges[face.edges[1]].startVertex; int v3 = heEdges[face.edges[2]].startVertex; //Skip this face if it doesnt contain the splitted vertex. if (v1 != vertex.index && v2 != vertex.index && v3 != vertex.index) continue; Vector3 faceCenter = (vertices[heVertices[v1].physicalIDs[0]] + vertices[heVertices[v2].physicalIDs[0]] + vertices[heVertices[v3].physicalIDs[0]]) / 3.0f; if (splitPlane.GetSide(faceCenter)){ side1Faces.Add(face); }else{ side2Faces.Add(face); foreach(int e in face.edges) side2Edges.Add(e); } } // If the vertex cant be split, return false. if (side1Faces.Count == 0 || side2Faces.Count == 0) return false; // create new mesh vertex and triangle buffers: vertices = new Vector3[input.vertexCount+1]; Array.Copy(input.vertices,vertices,input.vertexCount); int[] triangles = input.triangles; // create a new vertex: newVertex = new HEVertex(input.vertexCount); newVertex.index = heVertices.Count; heVertices.Add(newVertex); // add the new vertex to the mesh vertices buffer: vertices[input.vertexCount] = vertices[vertex.physicalIDs[0]]; // Copy uvs, colors and other mesh info. Vector2[] uv = null; Vector2[] uv2 = null; Vector2[] uv3 = null; Vector2[] uv4 = null; Color32[] colors = null; if (input.uv.Length > 0){ uv = new Vector2[input.uv.Length+1]; Array.Copy(input.uv,uv,input.uv.Length); uv[input.uv.Length] = uv[vertex.physicalIDs[0]]; //TODO: could cause copying uvs from the other side of the cut... } if (input.uv2.Length > 0){ uv2 = new Vector2[input.uv2.Length+1]; Array.Copy(input.uv2,uv2,input.uv2.Length); uv2[input.uv2.Length] = uv2[vertex.physicalIDs[0]]; } if (input.uv3.Length > 0){ uv3 = new Vector2[input.uv3.Length+1]; Array.Copy(input.uv3,uv3,input.uv3.Length); uv3[input.uv3.Length] = uv3[vertex.physicalIDs[0]]; } if (input.uv4.Length > 0){ uv4 = new Vector2[input.uv4.Length+1]; Array.Copy(input.uv4,uv4,input.uv4.Length); uv4[input.uv4.Length] = uv4[vertex.physicalIDs[0]]; } if (input.colors32.Length > 0){ colors = new Color32[input.colors32.Length+1]; Array.Copy(input.colors32,colors,input.colors32.Length); colors[input.colors32.Length] = colors[vertex.physicalIDs[0]]; } // rearrange edges at side 1: foreach(HEFace face in side1Faces){ // find half edges that start or end at the split vertex: HEEdge edgeIn = heEdges[Array.Find<int>(face.edges,e => heEdges[e].endVertex == vertex.index)]; HEEdge edgeOut = heEdges[Array.Find<int>(face.edges,e => heEdges[e].startVertex == vertex.index)]; int oldInID = ObiUtils.Pair(edgeIn.startVertex,edgeIn.endVertex); int oldOutID = ObiUtils.Pair(edgeOut.startVertex,edgeOut.endVertex); if (ShouldRemoveEdge(edgeIn,side2Edges.Contains(edgeIn.pair))) removedEdges.Add(oldInID); if (ShouldRemoveEdge(edgeOut,side2Edges.Contains(edgeOut.pair))) removedEdges.Add(oldOutID); // stitch half edges to new vertex edgeIn.endVertex = newVertex.index; edgeOut.startVertex = newVertex.index; newVertex.halfEdgeIndex = edgeOut.index; int newInID = ObiUtils.Pair(edgeIn.startVertex,edgeIn.endVertex); int newOutID = ObiUtils.Pair(edgeOut.startVertex,edgeOut.endVertex); addedEdges.Add(newInID); addedEdges.Add(newOutID); if (!oldAndNewEdges.ContainsKey(newInID)) oldAndNewEdges.Add(newInID,oldInID); if (!oldAndNewEdges.ContainsKey(newOutID)) oldAndNewEdges.Add(newOutID,oldOutID); // update mesh triangle buffer to point at new vertex where needed: if (triangles[face.index*3] == vertex.physicalIDs[0]) triangles[face.index*3] = newVertex.physicalIDs[0]; if (triangles[face.index*3+1] == vertex.physicalIDs[0]) triangles[face.index*3+1] = newVertex.physicalIDs[0]; if (triangles[face.index*3+2] == vertex.physicalIDs[0]) triangles[face.index*3+2] = newVertex.physicalIDs[0]; } // update input mesh: input.vertices = vertices; input.triangles = triangles; if (uv != null) input.uv = uv; if (uv2 != null) input.uv2 = uv2; if (uv3 != null) input.uv3 = uv3; if (uv4 != null) input.uv4 = uv4; if (colors != null) input.colors32 = colors; _closed = false; _modified = true; return true; }
private void AdjustEdgeHandleColor(Vector3 handlePos, Vector3 slideDir1, Vector3 slideDir2, Matrix4x4 transform, float alphaFactor) { Vector3 inPoint = transform.MultiplyPoint(handlePos); Vector3 normalized = transform.MultiplyVector(slideDir1).normalized; Vector3 normalized2 = transform.MultiplyVector(slideDir2).normalized; bool flag; if (Camera.current.orthographic) { flag = (Vector3.Dot(-Camera.current.transform.forward, normalized) < 0f && Vector3.Dot(-Camera.current.transform.forward, normalized2) < 0f); } else { Plane plane = new Plane(normalized, inPoint); Plane plane2 = new Plane(normalized2, inPoint); flag = (!plane.GetSide(Camera.current.transform.position) && !plane2.GetSide(Camera.current.transform.position)); } if (flag) { alphaFactor *= this.backfaceAlphaMultiplier; } if (alphaFactor < 1f) { Handles.color = new Color(Handles.color.r, Handles.color.g, Handles.color.b, Handles.color.a * alphaFactor); } }
/// <summary> /// Finds the intersection points. /// </summary> /// <param name='index'> /// Index: the meshObject index in the meshObjects array /// </param> void FindIntersectionPoints(int index) { Plane plane = new Plane(transform.TransformDirection(Vector3.up), transform.position); List<Vector3> points = new List<Vector3>(); MeshFilter meshObject = meshObjects[index].meshObject; Mesh mesh = meshObject.mesh; if(mesh == null) return; Vector3[] vertices = mesh.vertices; //Vector3[] normals = mesh.normals; int[] triangles = mesh.triangles; //loop through triangles to find intersections or points on the plane for(int j = 0; j < (mesh.triangles.Length); j += 3) { //retrieve the vertices of the triangle Vector3 vertex1 = meshObject.transform.TransformPoint(vertices[triangles[j + 0]]); Vector3 vertex2 = meshObject.transform.TransformPoint(vertices[triangles[j + 1]]); Vector3 vertex3 = meshObject.transform.TransformPoint(vertices[triangles[j + 2]]); //find if each vertice lies directly on the plane bool onPlane1 = Mathf.Approximately(plane.GetDistanceToPoint(vertex1), 0f); bool onPlane2 = Mathf.Approximately(plane.GetDistanceToPoint(vertex2), 0f); bool onPlane3 = Mathf.Approximately(plane.GetDistanceToPoint(vertex3), 0f); //find if each vertex is in front of or behind the plane bool inFront1 = plane.GetSide(vertex1); bool inFront2 = plane.GetSide(vertex2); bool inFront3 = plane.GetSide(vertex3); Vector3? firstPoint = null; //Special handling for if a point is directly on the planes surface #region Handle Points on Plane if(onPlane1) { if(inFront2 == inFront3) continue; firstPoint = vertex1; } if(onPlane2) { if(inFront1 == inFront3) continue; if(firstPoint != null) { points.Add((Vector3)firstPoint); points.Add(vertex2); continue; } else firstPoint = vertex2; } if(onPlane3) { if(inFront1 == inFront2) continue; if(firstPoint != null) { points.Add((Vector3)firstPoint); points.Add(vertex3); continue; } else firstPoint = vertex3; } #endregion float rayDistance; Ray ray = new Ray(vertex1, vertex2 - vertex1); //For points 1 and 2, if neither are on the planes surface, check if they are on opposite sides, //if so, find the intersection point on the plane. //If the first point was found earlier, add it and the intersection point to the list and continue. #region Find Intersections if(!onPlane1 && !onPlane2 && inFront1 != inFront2 && plane.Raycast(ray, out rayDistance)) { if(firstPoint != null) { points.Add((Vector3)firstPoint); points.Add(ray.GetPoint(rayDistance)); continue; } else firstPoint = ray.GetPoint(rayDistance); } ray = new Ray(vertex2, vertex3 - vertex2); if(!onPlane2 && !onPlane3 && (inFront2 != inFront3) && plane.Raycast(ray, out rayDistance)) { if(firstPoint != null) { points.Add((Vector3)firstPoint); points.Add(ray.GetPoint(rayDistance)); continue; } else firstPoint = ray.GetPoint(rayDistance); } if(firstPoint == null) continue; ray = new Ray(vertex3, vertex1 - vertex3); if(!onPlane3 && !onPlane1 && (inFront3 != inFront1) && plane.Raycast(ray, out rayDistance)) { points.Add((Vector3)firstPoint); points.Add(ray.GetPoint(rayDistance)); } #endregion } //makes sure that all points are on the plane's surface, and removes points outside of the planes bounding box #region Cleanup Points for(int i = 0; i < points.Count; i += 2) { Vector3 p1 = ProjectPointOnPlane(plane.normal, transform.position, points[i]); Vector3 p2 = ProjectPointOnPlane(plane.normal, transform.position, points[i + 1]); bool containsP1 = GetComponent<Collider>().bounds.Contains(p1); bool containsP2 = GetComponent<Collider>().bounds.Contains(p2); if(!containsP1 && !containsP2) { points[i] = points[i + 1] = Vector3.zero; continue; } if(!containsP1 && containsP2) { Ray ray = new Ray(p1, p2 - p1); float distance; GetComponent<Collider>().bounds.IntersectRay(ray, out distance); Vector3 newP = ray.GetPoint(distance); points[i] = newP; } if(containsP1 && !containsP2) { Ray ray = new Ray(p2, p1 - p2); float distance; GetComponent<Collider>().bounds.IntersectRay(ray, out distance); Vector3 newP = ray.GetPoint(distance); points[i + 1] = newP; Debug.Log(distance.ToString()); } } #endregion meshObjects[index].points = points; }