/** * Returns the first normal, tangent, and bitangent for this face, using the first triangle available for tangent and bitangent. * Does not rely on mesh.msh for normal or uv information - uses mesh.vertices & mesh.uv. */ public static void NormalTangentBitangent(Vector3[] vertices, Vector2[] uv, qe_Triangle tri, out Vector3 normal, out Vector3 tangent, out Vector3 bitangent) { normal = qe_Math.Normal(vertices[tri.x], vertices[tri.y], vertices[tri.z]); Vector3 tan1 = Vector3.zero; Vector3 tan2 = Vector3.zero; Vector4 tan = new Vector4(0f, 0f, 0f, 1f); long i1 = tri.x; long i2 = tri.y; long i3 = tri.z; Vector3 v1 = vertices[i1]; Vector3 v2 = vertices[i2]; Vector3 v3 = vertices[i3]; Vector2 w1 = uv[i1]; Vector2 w2 = uv[i2]; Vector2 w3 = uv[i3]; float x1 = v2.x - v1.x; float x2 = v3.x - v1.x; float y1 = v2.y - v1.y; float y2 = v3.y - v1.y; float z1 = v2.z - v1.z; float z2 = v3.z - v1.z; float s1 = w2.x - w1.x; float s2 = w3.x - w1.x; float t1 = w2.y - w1.y; float t2 = w3.y - w1.y; float r = 1.0f / (s1 * t2 - s2 * t1); Vector3 sdir = new Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r); Vector3 tdir = new Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r); tan1 += sdir; tan2 += tdir; Vector3 n = normal; Vector3.OrthoNormalize(ref n, ref tan1); tan.x = tan1.x; tan.y = tan1.y; tan.z = tan1.z; tan.w = (Vector3.Dot(Vector3.Cross(n, tan1), tan2) < 0.0f) ? -1.0f : 1.0f; tangent = ((Vector3)tan) * tan.w; bitangent = Vector3.Cross(normal, tangent); }
/** * Get an array of qe_Triangle from this mesh. */ public qe_Triangle[] GetFaces() { int[] tris = cloneMesh.triangles; qe_Triangle[] t = new qe_Triangle[tris.Length / 3]; int index = 0; for (int i = 0; i < tris.Length; i += 3) { t[index++] = new qe_Triangle(tris[i], tris[i + 1], tris[i + 2]); } return(t); }
void OnMouseUp(Event e) { if (!e.shift) { Undo.RecordObject(selection, "Clear Selection"); selection.Clear(); } switch (elementMode) { case ElementMode.Vertex: { int index = -1; if (qe_Editor_Utility.VertexRaycast(e.mousePosition, CLICK_RECT, selection, out index)) { List <int> sel = selection.userIndices; int indexOf = sel.IndexOf(index); if (indexOf < 0) { sel.Add(index); } else { sel.RemoveAt(indexOf); } selection.SetIndices(sel); break; } else { goto default; } } case ElementMode.Edge: { qe_Edge edge; if (qe_Editor_Utility.EdgeRaycast(e.mousePosition, selection, out edge)) { List <qe_Edge> sel = selection.edges.Distinct().ToList(); int index = sel.IndexOf(edge); if (index > -1) { sel.RemoveAt(index); } else { sel.Add(edge); } selection.SetEdges(sel); } else { goto case ElementMode.Face; } break; } case ElementMode.Face: default: { qe_RaycastHit hit; if (qe_Editor_Utility.MeshRaycast(HandleUtility.GUIPointToWorldRay(e.mousePosition), selection.mesh, out hit)) { List <qe_Triangle> sel = selection.faces; qe_Triangle tri = selection.mesh.faces[hit.FaceIndex]; int index = sel.IndexOf(tri); if (index > -1) { sel.RemoveAt(index); } else { sel.Add(tri); } selection.SetFaces(sel); } break; } } ResetHandles(); CacheIndicesForGraphics(); UpdateGraphics(); }
void UpdateElementHover(Vector2 mousePosition) { hovering.mode = elementMode; int hash = hovering.hashCode; bool wasValid = hovering.valid; hovering.valid = false; switch (elementMode) { case ElementMode.Vertex: { int tri = -1; if (qe_Editor_Utility.VertexRaycast(mousePosition, CLICK_RECT, selection, out tri)) { hovering.valid = true; hovering.hashCode = tri.GetHashCode(); hovering.vertices[0] = selection.verticesInWorldSpace[tri]; } } break; case ElementMode.Face: { qe_RaycastHit hit; if (qe_Editor_Utility.MeshRaycast(HandleUtility.GUIPointToWorldRay(mousePosition), selection.mesh, out hit)) { qe_Triangle face = selection.mesh.faces[hit.FaceIndex]; hovering.valid = true; if (hash != face.GetHashCode()) { hovering.hashCode = face.GetHashCode(); hovering.vertices[0] = selection.verticesInWorldSpace[face.x]; hovering.vertices[1] = selection.verticesInWorldSpace[face.y]; hovering.vertices[2] = selection.verticesInWorldSpace[face.z]; #if !UNITY_5 hovering.vertices[3] = selection.verticesInWorldSpace[face.z]; #endif } } } break; case ElementMode.Edge: { qe_Edge edge; if (qe_Editor_Utility.EdgeRaycast(mousePosition, selection, out edge)) { hovering.valid = true; if (hash != edge.GetHashCode()) { hovering.hashCode = edge.GetHashCode(); hovering.vertices[0] = selection.verticesInWorldSpace[edge.x]; hovering.vertices[1] = selection.verticesInWorldSpace[edge.y]; } } } break; } if (hash != hovering.hashCode || hovering.valid != wasValid) { SceneView.RepaintAll(); } }
public static Vector3 Normal(this qe_Mesh mesh, qe_Triangle tri) { return(Normal(mesh.vertices[tri.x], mesh.vertices[tri.y], mesh.vertices[tri.z])); }