public ReplicatorImpl(IStorageBasedDataObjectAccessor <TDataType> accessor, IStore target) { _info = GetAccessorInfo(accessor.GetType(), new Lazy <Expression>(() => accessor.GetSource().Expression)); _accessor = accessor; _target = target; }
private Mesh CreateGltfMesh(string meshName, VMesh vmesh, ModelRoot model) { ProgressDialog.SetProgress($"Creating mesh: {meshName}"); var data = vmesh.GetData(); var vbib = vmesh.VBIB; var mesh = model.CreateMesh(meshName); mesh.Name = meshName; foreach (var sceneObject in data.GetArray("m_sceneObjects")) { foreach (var drawCall in sceneObject.GetArray("m_drawCalls")) { var vertexBufferInfo = drawCall.GetArray("m_vertexBuffers")[0]; // In what situation can we have more than 1 vertex buffer per draw call? var vertexBufferIndex = (int)vertexBufferInfo.GetIntegerProperty("m_hBuffer"); var vertexBuffer = vbib.VertexBuffers[vertexBufferIndex]; var indexBufferInfo = drawCall.GetSubCollection("m_indexBuffer"); var indexBufferIndex = (int)indexBufferInfo.GetIntegerProperty("m_hBuffer"); var indexBuffer = vbib.IndexBuffers[indexBufferIndex]; // Create one primitive per draw call var primitive = mesh.CreatePrimitive(); // Avoid duplicate attribute names var uniqueAttributes = vertexBuffer.Attributes.GroupBy(a => a.Name).Select(g => g.First()); // Set vertex attributes foreach (var attribute in uniqueAttributes) { if (AccessorInfo.TryGetValue(attribute.Name, out var accessorInfo)) { var buffer = ReadAttributeBuffer(vbib, vertexBuffer, attribute); if (accessorInfo.NumComponents == 4) { var vectors = ToVector4Array(buffer); primitive.WithVertexAccessor(accessorInfo.GltfAccessorName, vectors); } else if (attribute.Name == "NORMAL" && DrawCall.IsCompressedNormalTangent(drawCall)) { var vectors = ToVector4Array(buffer); var(normals, tangents) = DecompressNormalTangents(vectors); primitive.WithVertexAccessor("NORMAL", normals); primitive.WithVertexAccessor("TANGENT", tangents); } else if (accessorInfo.NumComponents == 3) { var vectors = ToVector3Array(buffer, true, accessorInfo.Resize); primitive.WithVertexAccessor(accessorInfo.GltfAccessorName, vectors); } else if (accessorInfo.NumComponents == 2) { var vectors = ToVector2Array(buffer); primitive.WithVertexAccessor(accessorInfo.GltfAccessorName, vectors); } } } // Set index buffer var indices = ReadIndices(indexBuffer); // For triangle primitives, the front face has to be in counter-clockwise (CCW) winding order. for (var i = 0; i < indices.Length; i += 3) { var b = indices[i + 2]; indices[i + 2] = indices[i + 1]; indices[i + 1] = b; } primitive.WithIndicesAccessor(PrimitiveType.TRIANGLES, indices); // Add material var materialPath = drawCall.GetProperty <string>("m_material"); ProgressDialog.SetProgress($"Loading material: {materialPath}"); var materialResource = GuiContext.LoadFileByAnyMeansNecessary(materialPath + "_c"); if (materialResource == null) { continue; } var renderMaterial = (VMaterial)materialResource.DataBlock; var materialNameTrimmed = Path.GetFileNameWithoutExtension(materialPath); var bestMaterial = GenerateGLTFMaterialFromRenderMaterial(renderMaterial, model, materialNameTrimmed); primitive.WithMaterial(bestMaterial); } } return(mesh); }