public MeshParamData <ColliderVertexDefinition> AllocateCollider(int vertexSize, int indexSize) { Debug.Assert(vertexSize <= MeshParamData <T> .maxVertexSize); if (m_colliderData.Count == 0) { m_colliderData.Add(new MeshParamData <ColliderVertexDefinition>()); AllocateVerticesArray(m_colliderData[0], vertexSize); AllocateIndexArray(m_colliderData[0], indexSize); } var element = m_colliderData[m_data.Count - 1]; if (!element.CanAllocate(vertexSize)) { var newData = new MeshParamData <ColliderVertexDefinition>(); m_colliderData.Add(newData); AllocateVerticesArray(newData, vertexSize); AllocateIndexArray(newData, indexSize); element = newData; } if (element.verticesSize + vertexSize > element.vertices.Length) { IncreaseVerticesArray(element, vertexSize); } if (element.indexesSize + indexSize > element.indexes.Length) { IncreaseIndexArray(element, indexSize); } return(element); }
static void SetColor(MeshParamData <WorldVertexDefinition> data, int index, int size, Color32 color) { for (int i = 0; i < size; i++) { data.vertices[index + i].color = color; } }
static void SetTrianglesIndexs(MeshParamData <WorldVertexDefinition> data, int vertexIndex, int indexIndex, int triangleNb) { for (int i = 0; i < triangleNb; i++) { data.indexes[indexIndex + i * 3] = (ushort)(3 * i + vertexIndex); data.indexes[indexIndex + i * 3 + 1] = (ushort)(3 * i + 1 + vertexIndex); data.indexes[indexIndex + i * 3 + 2] = (ushort)(3 * i + 2 + vertexIndex); } }
static void RotatePos(MeshParamData <WorldVertexDefinition> data, int index, int size, Vector3 origin, Rotation rot) { for (int i = 0; i < size; i++) { var pos = data.vertices[index + i].pos - origin; var rotatedPos = RotationEx.RotateOffset(new Vector2(pos.x - 0.5f, pos.z - 0.5f), rot); pos.x = rotatedPos.x + 0.5f; pos.z = rotatedPos.y + 0.5f; data.vertices[index + i].pos = pos + origin; } }
static void AllocateVerticesArray <U>(MeshParamData <U> data, int addVertices) where U : struct { Debug.Assert(data.vertices == null); int newSize = addVertices + allocSize; if (newSize > MeshParamData <U> .maxVertexSize) { newSize = MeshParamData <U> .maxVertexSize; } data.vertices = new U[newSize]; }
static void SetQuadsIndexs(MeshParamData <WorldVertexDefinition> data, int vertexIndex, int indexIndex, int quadNb) { for (int i = 0; i < quadNb; i++) { data.indexes[indexIndex + i * 6] = (ushort)(4 * i + vertexIndex); data.indexes[indexIndex + i * 6 + 1] = (ushort)(4 * i + 1 + vertexIndex); data.indexes[indexIndex + i * 6 + 2] = (ushort)(4 * i + 2 + vertexIndex); data.indexes[indexIndex + i * 6 + 3] = (ushort)(4 * i + vertexIndex); data.indexes[indexIndex + i * 6 + 4] = (ushort)(4 * i + 2 + vertexIndex); data.indexes[indexIndex + i * 6 + 5] = (ushort)(4 * i + 3 + vertexIndex); } }
static void IncreaseIndexArray <U>(MeshParamData <U> data, int addIndexes) where U : struct { Debug.Assert(data.indexes != null); int newSize = data.indexes.Length + addIndexes + allocSize; var newIndex = new ushort[newSize]; for (int i = 0; i < data.indexesSize; i++) { newIndex[i] = data.indexes[i]; } data.indexes = newIndex; }
static void RotateUV(MeshParamData <WorldVertexDefinition> data, int index, int size, int nb) { while (nb > 0) { Vector2 uv = data.vertices[index].uv; for (int i = 0; i < size - 1; i++) { data.vertices[index + i].uv = data.vertices[index + i + 1].uv; } data.vertices[index + size - 1].uv = uv; nb--; } }
static void CloneCollisions(MeshParams <WorldVertexDefinition> meshParams, MeshParamData <WorldVertexDefinition> data, int nbVertex, int nbIndex) { var collisionData = meshParams.AllocateCollider(nbVertex, nbIndex); for (int i = 0; i < nbVertex; i++) { collisionData.vertices[collisionData.verticesSize + i].pos = data.vertices[data.verticesSize + i].pos; collisionData.vertices[collisionData.verticesSize + i].normal = data.vertices[data.verticesSize + i].normal; } for (int i = 0; i < nbIndex; i++) { collisionData.indexes[collisionData.indexesSize + i] = (ushort)(data.indexes[data.indexesSize + i] - data.verticesSize + collisionData.verticesSize); } collisionData.verticesSize += nbVertex; collisionData.indexesSize += nbIndex; }
static void IncreaseVerticesArray <U>(MeshParamData <U> data, int addVertices) where U : struct { Debug.Assert(data.vertices != null); int newSize = data.vertices.Length + addVertices + allocSize; if (newSize > MeshParamData <U> .maxVertexSize) { newSize = MeshParamData <U> .maxVertexSize; } var newArray = new U[newSize]; for (int i = 0; i < data.verticesSize; i++) { newArray[i] = data.vertices[i]; } data.vertices = newArray; }
static void BakeTangents(MeshParamData <WorldVertexDefinition> data, int index, int triangleNb) { //https://forum.unity.com/threads/how-to-calculate-mesh-tangents.38984/#post-285069 //with a small simplification : // Each vertex are linked to only one triangle. If one vertex is on multiple triangle, the combined surface is flat, we don't need to combine tangent for (int i = 0; i < triangleNb; i++) { int i1 = data.indexes[index + i * 3]; int i2 = data.indexes[index + i * 3 + 1]; int i3 = data.indexes[index + i * 3 + 2]; var v1 = data.vertices[i1]; var v2 = data.vertices[i2]; var v3 = data.vertices[i3]; float x1 = v2.pos.x - v1.pos.x; float x2 = v3.pos.x - v1.pos.x; float y1 = v2.pos.y - v1.pos.y; float y2 = v3.pos.y - v1.pos.y; float z1 = v2.pos.z - v1.pos.z; float z2 = v3.pos.z - v1.pos.z; float s1 = v2.uv.x - v1.uv.x; float s2 = v3.uv.x - v1.uv.x; float t1 = v2.uv.y - v1.uv.y; float t2 = v3.uv.y - v1.uv.y; float r = 1.0f / (s1 * t2 - s2 * t1); var sdir = new Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r); var tdir = new Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r); var tmp = (sdir - v1.normal * Vector3.Dot(v1.normal, sdir)).normalized; var w = (Vector3.Dot(Vector3.Cross(v1.normal, sdir), tdir) < 0.0f) ? -1.0f : 1.0f; var tan = new Vector4(tmp.x, tmp.y, tmp.z, w); data.vertices[i1].tangent = tan; data.vertices[i2].tangent = tan; data.vertices[i3].tangent = tan; } }
public MeshParamData <T> Allocate(int vertexSize, int indexSize, Material material) { Debug.Assert(vertexSize <= MeshParamData <T> .maxVertexSize); List <MeshParamData <T> > data = null; m_data.TryGetValue(material, out data); if (data == null) { data = new List <MeshParamData <T> >(); m_data[material] = data; data.Add(new MeshParamData <T>()); AllocateVerticesArray(data[0], vertexSize); AllocateIndexArray(data[0], indexSize); } var element = data[data.Count - 1]; if (!element.CanAllocate(vertexSize)) { var newData = new MeshParamData <T>(); data.Add(newData); AllocateVerticesArray(newData, vertexSize); AllocateIndexArray(newData, indexSize); element = newData; } if (element.verticesSize + vertexSize > element.vertices.Length) { IncreaseVerticesArray(element, vertexSize); } if (element.indexesSize + indexSize > element.indexes.Length) { IncreaseIndexArray(element, indexSize); } return(element); }
static void BakeNormals(MeshParamData <WorldVertexDefinition> data, int index, int triangleNb) { //https://math.stackexchange.com/questions/305642/how-to-find-surface-normal-of-a-triangle for (int i = 0; i < triangleNb; i++) { int i1 = data.indexes[index + i * 3]; int i2 = data.indexes[index + i * 3 + 1]; int i3 = data.indexes[index + i * 3 + 2]; var p1 = data.vertices[i1].pos; var p2 = data.vertices[i2].pos; var p3 = data.vertices[i3].pos; var v = p2 - p1; var w = p3 - p1; var n = new Vector3(v.y * w.z - v.z * w.y, v.z * w.x - v.x * w.z, v.x * w.y - v.y * w.x); data.vertices[i1].normal = n; data.vertices[i2].normal = n; data.vertices[i3].normal = n; } }
static void AllocateIndexArray <U>(MeshParamData <U> data, int addIndexes) where U : struct { Debug.Assert(data.indexes == null); data.indexes = new ushort[addIndexes + allocSize]; }