private static void WriteSkinnedMeshJson(SkinnedMeshRenderer skinnedRenderer, WebGLBone[] bones, Stream outStream, Dictionary <Material, WebGLModel> materialModels) { Mesh mesh = skinnedRenderer.sharedMesh; int i; // Map the bones used by each sub-mesh foreach (WebGLModel model in materialModels.Values) { for (i = 0; i < model.meshes.Count; ++i) { WebGLMesh subMesh = model.meshes[i]; // Eventually this will have to change, but for now let's just keep things simple: subMesh.boneOffset = 0; subMesh.boneCount = bones.Length; model.meshes[i] = subMesh; } } StringTemplateGroup templateGroup = new StringTemplateGroup("MG", templatePath, typeof(DefaultTemplateLexer)); StringTemplate modelTemplate = templateGroup.GetInstanceOf("WebGLModel"); modelTemplate.SetAttribute("name", mesh.name); modelTemplate.SetAttribute("models", materialModels.Values); modelTemplate.SetAttribute("bones", bones); string content = modelTemplate.ToString(); Byte[] bytes = new UTF8Encoding(true).GetBytes(CleanJSON(content)); outStream.Write(bytes, 0, bytes.Length); }
private static void WriteMeshBinary(Mesh mesh, VertexFormat vertexFormat, Material[] materials, int[] boneIdLookup, Stream outStream, out Dictionary <Material, WebGLModel> models) { int i, j; Dictionary <string, MemoryStream> lumps = new Dictionary <string, MemoryStream>(); Vector3[] verts = mesh.vertices; Vector2[] uv = mesh.uv; Vector2[] uv2 = mesh.uv2; Vector3[] normals = mesh.normals; Vector4[] tangents = mesh.tangents; Color[] colors = mesh.colors; BoneWeight[] boneWeights = mesh.boneWeights; // Check for some attributes that may not be present. Remove them from the mask if they have no data if (uv2.Length == 0 && (vertexFormat & VertexFormat.UV2) == VertexFormat.UV2) { vertexFormat &= ~VertexFormat.UV2; } if (colors.Length == 0 && (vertexFormat & VertexFormat.Color) == VertexFormat.Color) { vertexFormat &= ~VertexFormat.Color; } if (boneWeights.Length == 0 && (vertexFormat & VertexFormat.BoneWeights) == VertexFormat.BoneWeights) { vertexFormat &= ~VertexFormat.BoneWeights; } // Build the vertex buffer UInt32 vertStride = 0; if ((vertexFormat & VertexFormat.Position) == VertexFormat.Position) { vertStride += 12; } if ((vertexFormat & VertexFormat.UV) == VertexFormat.UV) { vertStride += 8; } if ((vertexFormat & VertexFormat.UV2) == VertexFormat.UV2) { vertStride += 8; } if ((vertexFormat & VertexFormat.Normal) == VertexFormat.Normal) { vertStride += 12; } if ((vertexFormat & VertexFormat.Tangent) == VertexFormat.Tangent) { vertStride += 16; } if ((vertexFormat & VertexFormat.Color) == VertexFormat.Color) { vertStride += 4; } if ((vertexFormat & VertexFormat.BoneWeights) == VertexFormat.BoneWeights) { vertStride += 24; } MemoryStream vertStream = new MemoryStream(); BinaryWriter vertBuf = new BinaryWriter(vertStream); vertBuf.Write((UInt32)vertexFormat); vertBuf.Write(vertStride); for (i = 0; i < verts.Length; ++i) { if ((vertexFormat & VertexFormat.Position) == VertexFormat.Position) { vertBuf.Write(verts[i].x); // Apparently Unity does it's X axis "backwards" from most other apps vertBuf.Write(verts[i].y); vertBuf.Write(verts[i].z); } if ((vertexFormat & VertexFormat.UV) == VertexFormat.UV) { vertBuf.Write(uv[i].x); vertBuf.Write(uv[i].y); } if ((vertexFormat & VertexFormat.UV2) == VertexFormat.UV2) { vertBuf.Write(uv2[i].x); vertBuf.Write(uv2[i].y); } if ((vertexFormat & VertexFormat.Normal) == VertexFormat.Normal) { vertBuf.Write(-normals[i].x); vertBuf.Write(normals[i].y); vertBuf.Write(normals[i].z); } if ((vertexFormat & VertexFormat.Tangent) == VertexFormat.Tangent) { vertBuf.Write(tangents[i].x); vertBuf.Write(tangents[i].y); vertBuf.Write(tangents[i].z); vertBuf.Write(tangents[i].w); } if ((vertexFormat & VertexFormat.Color) == VertexFormat.Color) { vertBuf.Write((Byte)(colors[i].r * 255.0)); vertBuf.Write((Byte)(colors[i].g * 255.0)); vertBuf.Write((Byte)(colors[i].b * 255.0)); vertBuf.Write((Byte)(colors[i].a * 255.0)); } if ((vertexFormat & VertexFormat.BoneWeights) == VertexFormat.BoneWeights) { // We're only going to be tracking 3 bones per vertex, so we need to find // the lowest weight and average the other weights out across it int lowestWeightId = 0; float lowestWeight = boneWeights[i].weight0; if (boneWeights[i].weight1 < lowestWeight) { lowestWeightId = 1; lowestWeight = boneWeights[i].weight1; } if (boneWeights[i].weight2 < lowestWeight) { lowestWeightId = 2; lowestWeight = boneWeights[i].weight2; } if (boneWeights[i].weight3 < lowestWeight) { lowestWeightId = 3; lowestWeight = boneWeights[i].weight3; } float weightAdjustment = 1.0f + lowestWeight; if (lowestWeightId != 0) { vertBuf.Write(boneWeights[i].weight0 * weightAdjustment); } if (lowestWeightId != 1) { vertBuf.Write(boneWeights[i].weight1 * weightAdjustment); } if (lowestWeightId != 2) { vertBuf.Write(boneWeights[i].weight2 * weightAdjustment); } if (lowestWeightId != 3) { vertBuf.Write(boneWeights[i].weight3 * weightAdjustment); } if (lowestWeightId != 0) { vertBuf.Write((float)boneIdLookup[boneWeights[i].boneIndex0]); } if (lowestWeightId != 1) { vertBuf.Write((float)boneIdLookup[boneWeights[i].boneIndex1]); } if (lowestWeightId != 2) { vertBuf.Write((float)boneIdLookup[boneWeights[i].boneIndex2]); } if (lowestWeightId != 3) { vertBuf.Write((float)boneIdLookup[boneWeights[i].boneIndex3]); } } } lumps.Add("vert", vertStream); // Build the index buffer UInt32 indexCount = 0; models = new Dictionary <Material, WebGLModel>(); MemoryStream indexStream = new MemoryStream(); BinaryWriter indexBuf = new BinaryWriter(indexStream); for (i = 0; i < mesh.subMeshCount; ++i) { int[] triangles = mesh.GetTriangles(i); Material material = materials[i]; WebGLModel model; if (!models.TryGetValue(material, out model)) { model = new WebGLModel(); model.meshes = new List <WebGLMesh>(); model.material = material; if (material.mainTexture) { model.defaultTexture = CreateWebTexture(material.mainTexture as Texture2D); } models[material] = model; } WebGLMesh webGLMesh = new WebGLMesh(); webGLMesh.indexOffset = (UInt16)indexCount; webGLMesh.indexCount = (UInt16)triangles.Length; indexCount += webGLMesh.indexCount; model.meshes.Add(webGLMesh); for (j = 0; j < triangles.Length; ++j) { indexBuf.Write((UInt16)triangles[j]); } } lumps.Add("indx", indexStream); WriteLumpFile(vertBinaryVersion, "wglv", lumps, outStream); }