// ----------------------------------------- // DumpBufferInfoFromMesh // ----------------------------------------- void DumpBufferInfoFromMesh(Mesh _mesh, BufferInfo _bufInfo) { int vertexBytes = 0; byte[] vertexData; List <byte[]> indexDataList = new List <byte[]>(); byte[] bindposesData; Vector3[] vertices = _mesh.vertices; Vector3[] normals = _mesh.normals; Vector4[] tangents = _mesh.tangents; Color[] colors = _mesh.colors; Vector2[] uv = _mesh.uv; Vector2[] uv2 = _mesh.uv2; Vector2[] uv3 = _mesh.uv3; Vector2[] uv4 = _mesh.uv4; BoneWeight[] boneWeights = _mesh.boneWeights; int offsetNormal = 0; int offsetTangent = 0; int offsetColor = 0; int offsetUV = 0; int offsetUV2 = 0; int offsetUV3 = 0; int offsetUV4 = 0; int offsetJoint = 0; int offsetWeight = 0; int offsetBuffer = _bufInfo.data.Length; Vector3 minPos = Vector3.zero; Vector3 maxPos = Vector3.zero; Vector3 minNormal = Vector3.zero; Vector3 maxNormal = Vector3.zero; Vector4 minTangent = Vector4.zero; Vector4 maxTangent = Vector4.zero; if (vertices.Length > 0) { minPos = maxPos = vertices[0]; vertexBytes += 12; // float32 * 3 } if (normals.Length > 0) { offsetNormal = vertexBytes; vertexBytes += 12; // float32 * 3 } if (tangents.Length > 0) { offsetTangent = vertexBytes; vertexBytes += 16; // float32 * 4 } if (colors.Length > 0) { offsetColor = vertexBytes; vertexBytes += 16; // float32 * 4 } if (uv.Length > 0) { offsetUV = vertexBytes; vertexBytes += 8; // float32 * 2 } if (uv2.Length > 0) { offsetUV2 = vertexBytes; vertexBytes += 8; // float32 * 2 } if (uv3.Length > 0) { offsetUV3 = vertexBytes; vertexBytes += 8; // float32 * 2 } if (uv4.Length > 0) { offsetUV4 = vertexBytes; vertexBytes += 8; // float32 * 2 } if (boneWeights.Length > 0) { offsetJoint = vertexBytes; vertexBytes += 8; // uint16 * 4 offsetWeight = vertexBytes; vertexBytes += 16; // float32 * 4 } // vertexData using (MemoryStream stream = new MemoryStream(vertexBytes * _mesh.vertexCount)) { using (BinaryWriter writer = new BinaryWriter(stream)) { for (int i = 0; i < _mesh.vertexCount; ++i) { if (vertices.Length > 0) { Vector3 vert = vertices[i]; // NOTE: convert LH to RH vert.z = -vert.z; writer.Write(vert.x); writer.Write(vert.y); writer.Write(vert.z); if (vert.x < minPos.x) { minPos.x = vert.x; } if (vert.y < minPos.y) { minPos.y = vert.y; } if (vert.z < minPos.z) { minPos.z = vert.z; } if (vert.x > maxPos.x) { maxPos.x = vert.x; } if (vert.y > maxPos.y) { maxPos.y = vert.y; } if (vert.z > maxPos.z) { maxPos.z = vert.z; } } if (normals.Length > 0) { Vector3 normal = normals[i]; // NOTE: convert LH to RH normal.z = -normal.z; writer.Write(normal.x); writer.Write(normal.y); writer.Write(normal.z); if (normal.x < minNormal.x) { minNormal.x = normal.x; } if (normal.y < minNormal.y) { minNormal.y = normal.y; } if (normal.z < minNormal.z) { minNormal.z = normal.z; } if (normal.x > maxNormal.x) { maxNormal.x = normal.x; } if (normal.y > maxNormal.y) { maxNormal.y = normal.y; } if (normal.z > maxNormal.z) { maxNormal.z = normal.z; } } if (tangents.Length > 0) { Vector4 tangent = tangents[i]; // NOTE: convert LH to RH tangent.z = -tangent.z; writer.Write(tangent.x); writer.Write(tangent.y); writer.Write(tangent.z); writer.Write(tangent.w); if (tangent.x < minTangent.x) { minTangent.x = tangent.x; } if (tangent.y < minTangent.y) { minTangent.y = tangent.y; } if (tangent.z < minTangent.z) { minTangent.z = tangent.z; } if (tangent.w < minTangent.w) { minTangent.w = tangent.w; } if (tangent.x > maxTangent.x) { maxTangent.x = tangent.x; } if (tangent.y > maxTangent.y) { maxTangent.y = tangent.y; } if (tangent.z > maxTangent.z) { maxTangent.z = tangent.z; } if (tangent.w > maxTangent.w) { maxTangent.w = tangent.w; } } if (colors.Length > 0) { writer.Write(colors[i].r); writer.Write(colors[i].g); writer.Write(colors[i].b); writer.Write(colors[i].a); } if (uv.Length > 0) { writer.Write(uv[i].x); writer.Write(uv[i].y); } if (uv2.Length > 0) { writer.Write(uv2[i].x); writer.Write(uv2[i].y); } if (uv3.Length > 0) { writer.Write(uv3[i].x); writer.Write(uv3[i].y); } if (uv4.Length > 0) { writer.Write(uv4[i].x); writer.Write(uv4[i].y); } if (boneWeights.Length > 0) { writer.Write((ushort)boneWeights[i].boneIndex0); writer.Write((ushort)boneWeights[i].boneIndex1); writer.Write((ushort)boneWeights[i].boneIndex2); writer.Write((ushort)boneWeights[i].boneIndex3); writer.Write(boneWeights[i].weight0); writer.Write(boneWeights[i].weight1); writer.Write(boneWeights[i].weight2); writer.Write(boneWeights[i].weight3); } } } vertexData = stream.ToArray(); } // indexDataList for (int i = 0; i < _mesh.subMeshCount; ++i) { int[] subTriangles = _mesh.GetTriangles(i); if (subTriangles.Length > 0) { using (MemoryStream stream = new MemoryStream(2 * subTriangles.Length)) { using (BinaryWriter writer = new BinaryWriter(stream)) { // DISABLE // for ( int ii = 0; ii < subTriangles.Length; ++ii ) { // writer.Write((ushort)subTriangles[ii]); // } // NOTE: convert mesh winding order from CW (Unity3D's) to CCW (most webgl programs) for (int ii = 0; ii < subTriangles.Length / 3; ++ii) { writer.Write((ushort)subTriangles[3 * ii]); writer.Write((ushort)subTriangles[3 * ii + 2]); writer.Write((ushort)subTriangles[3 * ii + 1]); } } indexDataList.Add(stream.ToArray()); } } } // bindposesData using (MemoryStream stream = new MemoryStream(4 * 16 * _mesh.bindposes.Length)) { using (BinaryWriter writer = new BinaryWriter(stream)) { for (int i = 0; i < _mesh.bindposes.Length; ++i) { Matrix4x4 bindpose = _mesh.bindposes[i]; // NOTE: convert LH to RH writer.Write(bindpose[0]); writer.Write(bindpose[1]); writer.Write(-bindpose[2]); // a02 writer.Write(bindpose[3]); writer.Write(bindpose[4]); writer.Write(bindpose[5]); writer.Write(-bindpose[6]); // a12 writer.Write(bindpose[7]); writer.Write(-bindpose[8]); // a20 writer.Write(-bindpose[9]); // a21 writer.Write(bindpose[10]); writer.Write(bindpose[11]); writer.Write(bindpose[12]); writer.Write(bindpose[13]); writer.Write(-bindpose[14]); // b2 writer.Write(bindpose[15]); } } bindposesData = stream.ToArray(); } // bufferViews List <BufferViewInfo> bufferViews = new List <BufferViewInfo>(); // vbView BufferViewInfo vbView = new BufferViewInfo { name = "vb@" + _mesh.name, offset = offsetBuffer, length = vertexData.Length, stride = vertexBytes, type = BufferType.VERTEX, accessors = new List <AccessorInfo>(), }; if (vertices.Length > 0) { AccessorInfo acc = new AccessorInfo { name = "position@" + _mesh.name, offset = 0, count = _mesh.vertexCount, compType = ComponentType.FLOAT32, attrType = AttrType.VEC3, min = new object[3] { minPos.x, minPos.y, minPos.z }, max = new object[3] { maxPos.x, maxPos.y, maxPos.z }, }; vbView.accessors.Add(acc); } if (normals.Length > 0) { AccessorInfo acc = new AccessorInfo { name = "normal@" + _mesh.name, offset = offsetNormal, count = _mesh.vertexCount, compType = ComponentType.FLOAT32, attrType = AttrType.VEC3, min = new object[3] { minNormal.x, minNormal.y, minNormal.z }, max = new object[3] { maxNormal.x, maxNormal.y, maxNormal.z }, }; vbView.accessors.Add(acc); } if (tangents.Length > 0) { AccessorInfo acc = new AccessorInfo { name = "tangent@" + _mesh.name, offset = offsetTangent, count = _mesh.vertexCount, compType = ComponentType.FLOAT32, attrType = AttrType.VEC4, min = new object[4] { minTangent.x, minTangent.y, minTangent.z, minTangent.w }, max = new object[4] { maxTangent.x, maxTangent.y, maxTangent.z, maxTangent.w }, }; vbView.accessors.Add(acc); } if (colors.Length > 0) { AccessorInfo acc = new AccessorInfo { name = "color@" + _mesh.name, offset = offsetColor, count = _mesh.vertexCount, compType = ComponentType.FLOAT32, attrType = AttrType.VEC4, // TODO: min, max }; vbView.accessors.Add(acc); } if (uv.Length > 0) { AccessorInfo acc = new AccessorInfo { name = "uv0@" + _mesh.name, offset = offsetUV, count = _mesh.vertexCount, compType = ComponentType.FLOAT32, attrType = AttrType.VEC2, // TODO: min, max }; vbView.accessors.Add(acc); } if (uv2.Length > 0) { AccessorInfo acc = new AccessorInfo { name = "uv1@" + _mesh.name, offset = offsetUV2, count = _mesh.vertexCount, compType = ComponentType.FLOAT32, attrType = AttrType.VEC2, // TODO: min, max }; vbView.accessors.Add(acc); } if (uv3.Length > 0) { AccessorInfo acc = new AccessorInfo { name = "uv2@" + _mesh.name, offset = offsetUV3, count = _mesh.vertexCount, compType = ComponentType.FLOAT32, attrType = AttrType.VEC2, // TODO: min, max }; vbView.accessors.Add(acc); } if (uv4.Length > 0) { AccessorInfo acc = new AccessorInfo { name = "uv3@" + _mesh.name, offset = offsetUV4, count = _mesh.vertexCount, compType = ComponentType.FLOAT32, attrType = AttrType.VEC2, // TODO: min, max }; vbView.accessors.Add(acc); } if (boneWeights.Length > 0) { AccessorInfo acc = new AccessorInfo { name = "joints@" + _mesh.name, offset = offsetJoint, count = _mesh.vertexCount, compType = ComponentType.UINT16, attrType = AttrType.VEC4, // TODO: min, max }; vbView.accessors.Add(acc); acc = new AccessorInfo { name = "weights@" + _mesh.name, offset = offsetWeight, count = _mesh.vertexCount, compType = ComponentType.FLOAT32, attrType = AttrType.VEC4, // TODO: min, max }; vbView.accessors.Add(acc); } // bufferViews.Add(vbView); offsetBuffer += Utils.Align(vbView.length, 4); // ibView for (int i = 0; i < indexDataList.Count; ++i) { byte[] indexData = indexDataList[i]; BufferViewInfo ibView = new BufferViewInfo { name = "ib" + i + "@" + _mesh.name, offset = offsetBuffer, length = indexData.Length, type = BufferType.INDEX, accessors = new List <AccessorInfo>(), }; AccessorInfo acc = new AccessorInfo { name = "indices" + i + "@" + _mesh.name, offset = 0, count = indexData.Length / 2, compType = ComponentType.UINT16, attrType = AttrType.SCALAR, }; ibView.accessors.Add(acc); bufferViews.Add(ibView); offsetBuffer += Utils.Align(ibView.length, 4); } // bpView if (bindposesData.Length > 0) { BufferViewInfo bpView = new BufferViewInfo { name = "bp@" + _mesh.name, offset = offsetBuffer, length = bindposesData.Length, type = BufferType.NONE, accessors = new List <AccessorInfo>(), }; AccessorInfo acc = new AccessorInfo { name = "bindposes@" + _mesh.name, offset = 0, count = bindposesData.Length / (4 * 16), compType = ComponentType.FLOAT32, attrType = AttrType.MAT4, }; bpView.accessors.Add(acc); bufferViews.Add(bpView); offsetBuffer += Utils.Align(bpView.length, 4); } // data byte[] data = new byte[offsetBuffer]; int offset = 0; System.Buffer.BlockCopy(_bufInfo.data, 0, data, offset, _bufInfo.data.Length); offset += _bufInfo.data.Length; System.Buffer.BlockCopy(vertexData, 0, data, offset, vertexData.Length); offset += Utils.Align(vertexData.Length, 4); for (int i = 0; i < indexDataList.Count; ++i) { System.Buffer.BlockCopy(indexDataList[i], 0, data, offset, indexDataList[i].Length); offset += Utils.Align(indexDataList[i].Length, 4); } System.Buffer.BlockCopy(bindposesData, 0, data, offset, bindposesData.Length); offset += Utils.Align(bindposesData.Length, 4); // _bufInfo.data = data; _bufInfo.bufferViews.AddRange(bufferViews); }
// ----------------------------------------- // DumpBufferInfoFromAnimData // ----------------------------------------- void DumpBufferInfoFromAnimData(AnimData _animData, BufferInfo _bufInfo) { List <AccessorInfo> accessors = new List <AccessorInfo>(); // calculate total length of animation-data int length = 0; AccessorInfo acc; // time0 acc = new AccessorInfo { name = "time0@" + _animData.name, offset = length, count = 1, compType = ComponentType.FLOAT32, attrType = AttrType.SCALAR }; accessors.Add(acc); length += 4; // times acc = new AccessorInfo { name = "times@" + _animData.name, offset = length, count = _animData.times.Count, compType = ComponentType.FLOAT32, attrType = AttrType.SCALAR }; accessors.Add(acc); length += _animData.times.Count * 4; // frames foreach (var entry in _animData.nameToFrames) { NodeFrames frames = entry.Value; if (frames.tlist.Count > 0) { acc = new AccessorInfo { name = frames.node.name + "_T@" + _animData.name, offset = length, count = frames.tlist.Count, compType = ComponentType.FLOAT32, attrType = AttrType.VEC3 }; accessors.Add(acc); length += frames.tlist.Count * 12; } if (frames.slist.Count > 0) { acc = new AccessorInfo { name = frames.node.name + "_S@" + _animData.name, offset = length, count = frames.slist.Count, compType = ComponentType.FLOAT32, attrType = AttrType.VEC3 }; accessors.Add(acc); length += frames.slist.Count * 12; } if (frames.rlist.Count > 0) { acc = new AccessorInfo { name = frames.node.name + "_R@" + _animData.name, offset = length, count = frames.rlist.Count, compType = ComponentType.FLOAT32, attrType = AttrType.VEC4 }; accessors.Add(acc); length += frames.rlist.Count * 16; } } // write data byte[] clipData; using (MemoryStream stream = new MemoryStream(length)) { using (BinaryWriter writer = new BinaryWriter(stream)) { // time0 writer.Write(0.0f); // times for (int i = 0; i < _animData.times.Count; ++i) { writer.Write(_animData.times[i]); } foreach (var entry in _animData.nameToFrames) { NodeFrames frames = entry.Value; if (frames.tlist.Count > 0) { for (int i = 0; i < frames.tlist.Count; ++i) { // NOTE: convert LH to RH writer.Write(frames.tlist[i].x); writer.Write(frames.tlist[i].y); writer.Write(-frames.tlist[i].z); } } if (frames.slist.Count > 0) { for (int i = 0; i < frames.slist.Count; ++i) { writer.Write(frames.slist[i].x); writer.Write(frames.slist[i].y); writer.Write(frames.slist[i].z); } } if (frames.rlist.Count > 0) { for (int i = 0; i < frames.rlist.Count; ++i) { // NOTE: convert LH to RH writer.Write(-frames.rlist[i].x); writer.Write(-frames.rlist[i].y); writer.Write(frames.rlist[i].z); writer.Write(frames.rlist[i].w); } } } } clipData = stream.ToArray(); } // buffer view BufferViewInfo bufView = new BufferViewInfo { name = _animData.name, offset = _bufInfo.data.Length, length = clipData.Length, type = BufferType.NONE, accessors = accessors }; // byte[] data = new byte[_bufInfo.data.Length + clipData.Length]; int offset = 0; System.Buffer.BlockCopy(_bufInfo.data, 0, data, offset, _bufInfo.data.Length); offset += _bufInfo.data.Length; System.Buffer.BlockCopy(clipData, 0, data, offset, clipData.Length); offset += clipData.Length; // _bufInfo.data = data; _bufInfo.bufferViews.Add(bufView); }