public GrimMat4x3(GrimVec3 baseX, GrimVec3 baseY, GrimVec3 baseZ, GrimVec3 translation) { BaseX = baseX; BaseY = baseY; BaseZ = baseZ; Translation = translation; }
public GrimModelMeshEntity(GrimModelMeshData meshData, GrimModelBone[] bones, GrimVec3 emissiveColor, bool castShadow) { MeshData = meshData; Bones = bones; EmissiveColor = emissiveColor; CastShadow = castShadow; }
public override void ResetToDefaultParameters() { BaseX = new GrimVec3(); BaseY = new GrimVec3(); BaseZ = new GrimVec3(); Translation = new GrimVec3(); }
protected override void DoRead(System.IO.BinaryReader reader) { BaseX = new GrimVec3(reader); BaseY = new GrimVec3(reader); BaseZ = new GrimVec3(reader); Translation = new GrimVec3(reader); }
public void putVertexDataAsVec3Array(GrimVec3[] data) { if (data == null) { return; } DataType = DataTypeFloat; Dim = 3; Stride = 4 * Dim; RawVertexData = new byte[Stride * data.Length]; MemoryStream memoryStream = new MemoryStream(RawVertexData); BinaryWriter binaryWriter = new BinaryWriter(memoryStream); for (int i = 0; i < data.Length; i++) { if (data[i] == null) { data[i] = new GrimVec3(); //throw new Exception("GrimModelVertexArray: Provided Vec3 array contains a null value."); } data[i].Write(binaryWriter); } }
public override void ResetToDefaultParameters() { MeshData = null; Bones = null; EmissiveColor = new GrimVec3(); CastShadow = false; }
public static GrimVec3 Cross(GrimVec3 left, GrimVec3 right) { GrimVec3 returnValue = new GrimVec3(); returnValue.X = left.Y * right.Z - left.Z * right.Y; returnValue.Y = left.Z * right.X - left.X * right.Z; returnValue.Z = left.X * right.Y - left.Y * right.X; return(returnValue); }
protected override void DoRead(System.IO.BinaryReader reader) { Magic = new GrimFourCC(reader); Version = reader.ReadInt32(); NumVertices = reader.ReadInt32(); if (!Magic.Value.Equals("MESH")) { throw new Exception("GrimModelMeshData: Invalid FourCC"); } if (NumVertices > 0) { for (int i = 0; i < VertexArrays.Length; i++) { VertexArrays[i] = new GrimModelVertexArray(this, reader); } } int NumIndices = reader.ReadInt32(); Indices = new UInt32[NumIndices]; for (int i = 0; i < NumIndices; i++) { Indices[i] = reader.ReadUInt32(); } int NumSegments = reader.ReadInt32(); Segments = new GrimModelMeshSegment[NumSegments]; for (int i = 0; i < NumSegments; i++) { GrimModelMeshSegment segment = new GrimModelMeshSegment(reader); if ((segment.TriCount * 3) > NumIndices) { Logger.Instance.Warning("GrimModelMeshData: Too many triangles in this segment, capping to the number of triangles in the mesh."); segment.TriCount = (NumIndices - segment.FirstIndex) / 3; } Segments[i] = segment; } BoundCenter = new GrimVec3(reader); BoundRadius = reader.ReadSingle(); BoundMin = new GrimVec3(reader); BoundMax = new GrimVec3(reader); }
protected override void DoRead(System.IO.BinaryReader reader) { MeshData = new GrimModelMeshData(reader); int NumBones = reader.ReadInt32(); Bones = new GrimModelBone[NumBones]; for (int i = 0; i < NumBones; i++) { Bones[i] = new GrimModelBone(reader); } EmissiveColor = new GrimVec3(reader); CastShadow = (reader.ReadByte() > 0); }
public override void ResetToDefaultParameters() { Magic = new GrimFourCC("MESH"); Version = 2; NumVertices = 0; VertexArrays = new GrimModelVertexArray[15]; Indices = null; Segments = null; BoundCenter = new GrimVec3(); BoundRadius = 0.0f; BoundMin = new GrimVec3(); BoundMax = new GrimVec3(); for (int i = 0; i < VertexArrays.Length; i++) { VertexArrays[i] = new GrimModelVertexArray(this); } }
public GrimVec3[] getVertexDataAsVec3Array() { if (DataType != DataTypeFloat || Dim != 3) { return(null); } MemoryStream memoryStream = new MemoryStream(RawVertexData); BinaryReader binaryReader = new BinaryReader(memoryStream); GrimVec3[] result = new GrimVec3[ParentMeshData.NumVertices]; for (int i = 0; i < ParentMeshData.NumVertices; i++) { result[i] = new GrimVec3(binaryReader); } return(result); }
public static float Dot(GrimVec3 left, GrimVec3 right) { return((left.X * right.X) + (left.Y * right.Y) + (left.Z * right.Z)); }
/// <summary> /// Calculate tangents and bitangents for each vertex in order using the method described at /// http://www.terathon.com/code/tangent.html /// </summary> public void CalculateTangentsAndBitangents() { GrimModelVertexArray vertexArray = VertexArrays[VERTEX_ARRAY_POSITION]; GrimModelVertexArray texArray = VertexArrays[VERTEX_ARRAY_TEXCOORD0]; GrimModelVertexArray normalArray = VertexArrays[VERTEX_ARRAY_NORMAL]; float[][] vertexData = vertexArray.getVertexDataAsFloatArray(); float[][] texData = texArray.getVertexDataAsFloatArray(); GrimVec3[] normalData = normalArray.getVertexDataAsVec3Array(); if (vertexData == null || texData == null || normalData == null) { Logger.Instance.Error("Need position, normal and texture data in existing mesh to calculate tangents."); return; } List <GrimVec3>[] vertexTangents = new List <GrimVec3> [vertexData.Length]; List <GrimVec3>[] vertexBitangents = new List <GrimVec3> [vertexData.Length]; GrimVec3[] tangentData = new GrimVec3[vertexData.Length]; GrimVec3[] bitangentData = new GrimVec3[vertexData.Length]; foreach (GrimModelMeshSegment segment in Segments) { // Reset all of the values for this segment for (int i = 0; i < vertexData.Length; i++) { vertexTangents[i] = new List <GrimVec3>(); vertexBitangents[i] = new List <GrimVec3>(); } // Calculate the range of indices we are working with int firstIndex = segment.FirstIndex; int lastIndex = firstIndex + segment.TriCount * 3; // Go over each triangle in this segment and calculate tangent / bitangent data for the related vertices for (int i = firstIndex; i < lastIndex; i += 3) { uint[] triIndices = new uint[] { Indices[i], Indices[i + 1], Indices[i + 2] }; GrimVec3[] triVerts = new GrimVec3[] { new GrimVec3(vertexData[triIndices[0]]), new GrimVec3(vertexData[triIndices[1]]), new GrimVec3(vertexData[triIndices[2]]) }; float[][] triUVs = new float[][] { texData[triIndices[0]], texData[triIndices[1]], texData[triIndices[2]] }; GrimVec3 side0 = triVerts[1] - triVerts[0]; GrimVec3 side1 = triVerts[2] - triVerts[0]; float dU0 = triUVs[1][0] - triUVs[0][0]; float dU1 = triUVs[2][0] - triUVs[0][0]; float dV0 = triUVs[1][1] - triUVs[0][1]; float dV1 = triUVs[2][1] - triUVs[0][1]; GrimVec3 tangent = dV1 * side0 - dV0 * side1; GrimVec3 bitangent = dU1 * side0 - dU0 * side1; GrimVec3 tangentCross = GrimVec3.Cross(tangent, bitangent); // Normalize at the end now // tangent.Normalize(); // bitangent.Normalize(); //wind the tangent into the other direction if necassary; means: if the UVs are mirrored //http://www.opentk.com/node/2520 /* * if (GrimVec3.Dot(surfaceNormal, tangentCross) < 0.0f) * { * biTangent *= -1.0f; * tangent *= -1.0f; * } */ for (int j = 0; j < 3; j++) { vertexTangents[triIndices[j]].Add(tangent); vertexBitangents[triIndices[j]].Add(bitangent); } } // Go over each vertex, see if we have created 1+ tangents for that vertex and do some maths if yes. for (int i = 0; i < vertexData.Length; i++) { List <GrimVec3> t = vertexTangents[i]; List <GrimVec3> b = vertexBitangents[i]; if (t.Count != b.Count || t.Count == 0) { continue; } tangentData[i] = new GrimVec3(); bitangentData[i] = new GrimVec3(); for (int j = 0; j < t.Count; j++) { tangentData[i] = tangentData[i] + t[j]; bitangentData[i] = bitangentData[i] + b[j]; } tangentData[i] = (tangentData[i] - (normalData[i] * GrimVec3.Dot(normalData[i], tangentData[i]))); bitangentData[i] = (bitangentData[i] - (normalData[i] * GrimVec3.Dot(normalData[i], bitangentData[i]))); tangentData[i].Normalize(); bitangentData[i].Normalize(); } } VertexArrays[VERTEX_ARRAY_TANGENT].putVertexDataAsVec3Array(tangentData); VertexArrays[VERTEX_ARRAY_BITANGENT].putVertexDataAsVec3Array(bitangentData); }
/// <summary> /// Destroy the normal data for this mesh and recalculate them using a simple vertex averaging system. /// </summary> public void CalculateAverageVertexNormals(bool simpleWeighting = true) { GrimModelVertexArray vertexArray = VertexArrays[VERTEX_ARRAY_POSITION]; float[][] vertexData = vertexArray.getVertexDataAsFloatArray(); if (vertexData == null) { Logger.Instance.Error("No position vertex data in existing mesh."); return; } List <GrimVec3>[] vertexValues = new List <GrimVec3> [vertexData.Length]; float[][] normalData = new float[vertexData.Length][]; // Initialise all of the normals incase we don't compute any (the data needs to be the right size) for (int i = 0; i < vertexData.Length; i++) { normalData[i] = new float[3]; } // Calculate the normal for each triangle and store that value for each vertex of that face (some vertices will have multiple values in a list). // We set each Normal Pt index to the same index as the vertex, as we are making these normals from scratch - we might as well make them parallel. foreach (GrimModelMeshSegment segment in Segments) { // Reset all of the values for this segment for (int i = 0; i < vertexData.Length; i++) { vertexValues[i] = new List <GrimVec3>(); } // Calculate the range of indices we are working with int firstIndex = segment.FirstIndex; int lastIndex = firstIndex + segment.TriCount * 3; // Iterate over each vertex and calculate a normal at that point for each face it is used in for (int i = firstIndex; i < lastIndex; i += 3) { uint[] triIndices = new uint[] { Indices[i], Indices[i + 1], Indices[i + 2] }; GrimVec3[] verts = new GrimVec3[] { new GrimVec3(vertexData[triIndices[0]]), new GrimVec3(vertexData[triIndices[1]]), new GrimVec3(vertexData[triIndices[2]]) }; GrimVec3 normal = GrimVec3.Cross((verts[1] - verts[0]), (verts[2] - verts[0])); // Apply Weighting if (simpleWeighting) { for (int j = 0; j < 3; j++) { GrimVec3 a = verts[(j + 1) % 3] - verts[j]; GrimVec3 b = verts[(j + 2) % 3] - verts[j]; float weight = (float)Math.Acos(GrimVec3.Dot(a, b) / (a.Length() * b.Length())); normal *= weight; } } vertexValues[triIndices[0]].Add(normal); vertexValues[triIndices[1]].Add(normal); vertexValues[triIndices[2]].Add(normal); } for (int i = 0; i < vertexValues.Length; i++) { List <GrimVec3> vertexNormals = vertexValues[i]; if (vertexNormals.Count == 0) { continue; } GrimVec3 normal = new GrimVec3(); for (int j = 0; j < vertexNormals.Count; j++) { normal = normal + vertexNormals[j]; } normal.Normalize(); normalData[i] = normal.ToFloatArray(); } } VertexArrays[VERTEX_ARRAY_NORMAL].putVertexDataAsFloatArray(normalData); }
protected override void DoRead(System.IO.BinaryReader reader) { Position = new GrimVec3(reader); Rotation = new GrimQuaternion(reader); Scale = new GrimVec3(reader); }
public override void ResetToDefaultParameters() { Position = new GrimVec3(); Rotation = new GrimQuaternion(); Scale = new GrimVec3(); }
public GrimAnimationKeyFrame(GrimVec3 pos, GrimQuaternion rot, GrimVec3 scale) { Position = pos; Rotation = rot; Scale = scale; }