// Create a new vertex between this vertex and `other` by linearly // interpolating all properties using a parameter of `t`. Subclasses should // override this to interpolate additional properties. public static CSG_Vertex Interpolate(CSG_Vertex a, CSG_Vertex b, float t) { CSG_Vertex ret = new CSG_Vertex(); ret.position = Vector3.Lerp(a.position, b.position, t); ret.normal = Vector3.Lerp(a.normal, b.normal, t); ret.uv = Vector2.Lerp(a.uv, b.uv, t); ret.color = (a.color + b.color) / 2f; return ret; }
// Create a new vertex between this vertex and `other` by linearly // interpolating all properties using a parameter of `t`. Subclasses should // override this to interpolate additional properties. public static CSG_Vertex Interpolate(CSG_Vertex a, CSG_Vertex b, float t) { CSG_Vertex ret = new CSG_Vertex(); ret.position = Vector3.Lerp(a.position, b.position, t); ret.normal = Vector3.Lerp(a.normal, b.normal, t); ret.uv = Vector2.Lerp(a.uv, b.uv, t); ret.color = (a.color + b.color) / 2f; return(ret); }
public static CSG_Vertex Clone(this CSG_Vertex x) { return(new CSG_Vertex() { color = x.color, normal = x.normal, position = x.position, tangent = x.tangent, uv0 = x.uv0, uv2 = x.uv2, uv3 = x.uv3, uv4 = x.uv4 }); }
/// <summary> /// Transform a vertex into world space. /// </summary> /// <param name="transform">The transform to apply.</param> /// <param name="vertex">A model space vertex.</param> /// <returns>A new vertex in world coordinate space.</returns> public static CSG_Vertex TransformVertex(this Transform transform, CSG_Vertex vertex) { var v = new CSG_Vertex(); if (vertex.HasArrays(CSG_VertexAttributes.Position)) { v.position = transform.TransformPoint(vertex.position); } if (vertex.HasArrays(CSG_VertexAttributes.Color)) { v.color = vertex.color; } if (vertex.HasArrays(CSG_VertexAttributes.Normal)) { v.normal = transform.TransformDirection(vertex.normal); } if (vertex.HasArrays(CSG_VertexAttributes.Tangent)) { v.tangent = transform.rotation * vertex.tangent; } if (vertex.HasArrays(CSG_VertexAttributes.Texture0)) { v.uv0 = vertex.uv0; } if (vertex.HasArrays(CSG_VertexAttributes.Texture1)) { v.uv2 = vertex.uv2; } if (vertex.HasArrays(CSG_VertexAttributes.Texture2)) { v.uv3 = vertex.uv3; } if (vertex.HasArrays(CSG_VertexAttributes.Texture3)) { v.uv4 = vertex.uv4; } return(v); }
// Split `polygon` by this plane if needed, then put the polygon or polygon // fragments in the appropriate lists. Coplanar polygons go into either // `coplanarFront` or `coplanarBack` depending on their orientation with // respect to this plane. Polygons in front or in back of this plane go into // either `front` or `back`. public void SplitPolygon(CSG_Polygon polygon, List <CSG_Polygon> coplanarFront, List <CSG_Polygon> coplanarBack, List <CSG_Polygon> front, List <CSG_Polygon> back) { // Classify each point as well as the entire polygon into one of the above // four classes. EPolygonType polygonType = 0; List <EPolygonType> types = new List <EPolygonType>(); for (int i = 0; i < polygon.vertices.Count; i++) { float t = Vector3.Dot(this.normal, polygon.vertices[i].position) - this.w; EPolygonType type = (t < -CSG.EPSILON) ? EPolygonType.Back : ((t > CSG.EPSILON) ? EPolygonType.Front : EPolygonType.Coplanar); polygonType |= type; types.Add(type); } // Put the polygon in the correct list, splitting it when necessary. switch (polygonType) { case EPolygonType.Coplanar: { if (Vector3.Dot(this.normal, polygon.plane.normal) > 0) { coplanarFront.Add(polygon); } else { coplanarBack.Add(polygon); } } break; case EPolygonType.Front: { front.Add(polygon); } break; case EPolygonType.Back: { back.Add(polygon); } break; case EPolygonType.Spanning: { List <CSG_Vertex> f = new List <CSG_Vertex>(); List <CSG_Vertex> b = new List <CSG_Vertex>(); for (int i = 0; i < polygon.vertices.Count; i++) { int j = (i + 1) % polygon.vertices.Count; EPolygonType ti = types[i], tj = types[j]; CSG_Vertex vi = polygon.vertices[i], vj = polygon.vertices[j]; if (ti != EPolygonType.Back) { f.Add(vi); } if (ti != EPolygonType.Front) { b.Add((ti != EPolygonType.Back) ? vi.Clone() : vi); } if ((ti | tj) == EPolygonType.Spanning) { float t = (this.w - Vector3.Dot(this.normal, vi.position)) / Vector3.Dot(this.normal, vj.position - vi.position); CSG_Vertex v = CSG_Vertex.Interpolate(vi, vj, t); f.Add(v); b.Add(v.Clone()); } } if (f.Count >= 3) { front.Add(new CSG_Polygon(f)); } if (b.Count >= 3) { back.Add(new CSG_Polygon(b)); } } break; } // End switch(polygonType) }
/// <summary> /// Linearly interpolate between two vertices. /// </summary> /// <param name="x">Left parameter.</param> /// <param name="y">Right parameter.</param> /// <param name="weight">The weight of the interpolation. 0 is fully x, 1 is fully y.</param> /// <returns>A new vertex interpolated by weight between x and y.</returns> public static CSG_Vertex Mix(this CSG_Vertex x, CSG_Vertex y, float weight) { float i = 1f - weight; CSG_Vertex v = new CSG_Vertex(); v.position = x.position * i + y.position * weight; if (x.hasColor && y.hasColor) { v.color = x.color * i + y.color * weight; } else if (x.hasColor) { v.color = x.color; } else if (y.hasColor) { v.color = y.color; } if (x.hasNormal && y.hasNormal) { v.normal = x.normal * i + y.normal * weight; } else if (x.hasNormal) { v.normal = x.normal; } else if (y.hasNormal) { v.normal = y.normal; } if (x.hasTangent && y.hasTangent) { v.tangent = x.tangent * i + y.tangent * weight; } else if (x.hasTangent) { v.tangent = x.tangent; } else if (y.hasTangent) { v.tangent = y.tangent; } if (x.hasUV0 && y.hasUV0) { v.uv0 = x.uv0 * i + y.uv0 * weight; } else if (x.hasUV0) { v.uv0 = x.uv0; } else if (y.hasUV0) { v.uv0 = y.uv0; } if (x.hasUV2 && y.hasUV2) { v.uv2 = x.uv2 * i + y.uv2 * weight; } else if (x.hasUV2) { v.uv2 = x.uv2; } else if (y.hasUV2) { v.uv2 = y.uv2; } if (x.hasUV3 && y.hasUV3) { v.uv3 = x.uv3 * i + y.uv3 * weight; } else if (x.hasUV3) { v.uv3 = x.uv3; } else if (y.hasUV3) { v.uv3 = y.uv3; } if (x.hasUV4 && y.hasUV4) { v.uv4 = x.uv4 * i + y.uv4 * weight; } else if (x.hasUV4) { v.uv4 = x.uv4; } else if (y.hasUV4) { v.uv4 = y.uv4; } return(v); }
/// <summary> /// Replace mesh values with vertex array. Mesh is cleared during this function, so be sure to set the triangles after calling. /// </summary> /// <param name="mesh">The target mesh.</param> /// <param name="vertices">The vertices to replace the mesh attributes with.</param> public static void SetMesh(Mesh mesh, IList <CSG_Vertex> vertices) { if (vertices.Count == 0) { return; } if (mesh == null) { throw new ArgumentNullException("mesh"); } if (vertices == null) { throw new ArgumentNullException("vertices"); } Vector3[] positions = null; Color[] colors = null; Vector2[] uv0s = null; Vector3[] normals = null; Vector4[] tangents = null; Vector2[] uv2s = null; List <Vector4> uv3s = null; List <Vector4> uv4s = null; GetArrays(vertices, out positions, out colors, out uv0s, out normals, out tangents, out uv2s, out uv3s, out uv4s); mesh.Clear(); CSG_Vertex first = vertices[0]; if (first.hasPosition) { mesh.vertices = positions; } if (first.hasColor) { mesh.colors = colors; } if (first.hasUV0) { mesh.uv = uv0s; } if (first.hasNormal) { mesh.normals = normals; } if (first.hasTangent) { mesh.tangents = tangents; } if (first.hasUV2) { mesh.uv2 = uv2s; } #if !UNITY_4_7 && !UNITY_5_0 if (first.hasUV3) { if (uv3s != null) { mesh.SetUVs(2, uv3s); } } if (first.hasUV4) { if (uv4s != null) { mesh.SetUVs(3, uv4s); } } #endif }
public static CSG_Vertex[] GetVertices(this Mesh mesh) { if (mesh == null) { return(null); } int vertexCount = mesh.vertexCount; CSG_Vertex[] v = new CSG_Vertex[vertexCount]; Vector3[] positions = mesh.vertices; Color[] colors = mesh.colors; Vector3[] normals = mesh.normals; Vector4[] tangents = mesh.tangents; Vector2[] uv0s = mesh.uv; Vector2[] uv2s = mesh.uv2; List <Vector4> uv3s = new List <Vector4>(); List <Vector4> uv4s = new List <Vector4>(); mesh.GetUVs(2, uv3s); mesh.GetUVs(3, uv4s); bool _hasPositions = positions != null && positions.Length == vertexCount; bool _hasColors = colors != null && colors.Length == vertexCount; bool _hasNormals = normals != null && normals.Length == vertexCount; bool _hasTangents = tangents != null && tangents.Length == vertexCount; bool _hasUv0 = uv0s != null && uv0s.Length == vertexCount; bool _hasUv2 = uv2s != null && uv2s.Length == vertexCount; bool _hasUv3 = uv3s.Count == vertexCount; bool _hasUv4 = uv4s.Count == vertexCount; for (int i = 0; i < vertexCount; i++) { v[i] = new CSG_Vertex(); if (_hasPositions) { v[i].position = positions[i]; } if (_hasColors) { v[i].color = colors[i]; } if (_hasNormals) { v[i].normal = normals[i]; } if (_hasTangents) { v[i].tangent = tangents[i]; } if (_hasUv0) { v[i].uv0 = uv0s[i]; } if (_hasUv2) { v[i].uv2 = uv2s[i]; } if (_hasUv3) { v[i].uv3 = uv3s[i]; } if (_hasUv4) { v[i].uv4 = uv4s[i]; } } return(v); }