private static unsafe bool getMeshOutputs(Xenko.Rendering.Mesh modelMesh, out List <Vector3> positions, out List <int> indicies) { if (modelMesh.Draw is StagedMeshDraw) { StagedMeshDraw smd = modelMesh.Draw as StagedMeshDraw; object verts = smd.Verticies; if (verts is VertexPositionNormalColor[]) { VertexPositionNormalColor[] vpnc = verts as VertexPositionNormalColor[]; positions = new List <Vector3>(vpnc.Length); for (int k = 0; k < vpnc.Length; k++) { positions[k] = vpnc[k].Position; } } else if (verts is VertexPositionNormalTexture[]) { VertexPositionNormalTexture[] vpnc = verts as VertexPositionNormalTexture[]; positions = new List <Vector3>(vpnc.Length); for (int k = 0; k < vpnc.Length; k++) { positions[k] = vpnc[k].Position; } } else if (verts is VertexPositionNormalTextureTangent[]) { VertexPositionNormalTextureTangent[] vpnc = verts as VertexPositionNormalTextureTangent[]; positions = new List <Vector3>(vpnc.Length); for (int k = 0; k < vpnc.Length; k++) { positions[k] = vpnc[k].Position; } } else { positions = null; indicies = null; return(false); } // take care of indicies indicies = new List <int>((int[])(object)smd.Indicies); } else { Xenko.Graphics.Buffer buf = modelMesh.Draw?.VertexBuffers[0].Buffer; Xenko.Graphics.Buffer ibuf = modelMesh.Draw?.IndexBuffer.Buffer; if (buf == null || buf.VertIndexData == null || ibuf == null || ibuf.VertIndexData == null) { positions = null; indicies = null; return(false); } if (ModelBatcher.UnpackRawVertData(buf.VertIndexData, modelMesh.Draw.VertexBuffers[0].Declaration, out Vector3[] arraypositions, out Core.Mathematics.Vector3[] normals, out Core.Mathematics.Vector2[] uvs,
private static unsafe bool getMeshOutputs(Xenko.Rendering.Mesh modelMesh, out List <Vector3> positions, out List <int> indicies) { if (modelMesh.Draw is StagedMeshDraw) { StagedMeshDraw smd = modelMesh.Draw as StagedMeshDraw; object verts = smd.Verticies; if (verts is VertexPositionNormalColor[]) { VertexPositionNormalColor[] vpnc = verts as VertexPositionNormalColor[]; positions = new List <Vector3>(vpnc.Length); for (int k = 0; k < vpnc.Length; k++) { positions.Add(vpnc[k].Position); } } else if (verts is VertexPositionNormalTexture[]) { VertexPositionNormalTexture[] vpnc = verts as VertexPositionNormalTexture[]; positions = new List <Vector3>(vpnc.Length); for (int k = 0; k < vpnc.Length; k++) { positions.Add(vpnc[k].Position); } } else if (verts is VertexPositionNormalTextureTangent[]) { VertexPositionNormalTextureTangent[] vpnc = verts as VertexPositionNormalTextureTangent[]; positions = new List <Vector3>(vpnc.Length); for (int k = 0; k < vpnc.Length; k++) { positions.Add(vpnc[k].Position); } } else { throw new ArgumentException("Couldn't get StageMeshDraw mesh, unknown vert type for " + modelMesh.Name); } // take care of indicies indicies = new List <int>(smd.Indicies.Length); for (int i = 0; i < smd.Indicies.Length; i++) { indicies.Add((int)smd.Indicies[i]); } } else { Xenko.Graphics.Buffer buf = modelMesh.Draw?.VertexBuffers[0].Buffer; Xenko.Graphics.Buffer ibuf = modelMesh.Draw?.IndexBuffer.Buffer; if (buf == null || buf.VertIndexData == null || ibuf == null || ibuf.VertIndexData == null) { throw new ArgumentException("Couldn't get mesh for " + modelMesh.Name + ", buffer wasn't stored probably. Try Xenko.Graphics.Buffer.CaptureAllModelBuffers to true."); } if (ModelBatcher.UnpackRawVertData(buf.VertIndexData, modelMesh.Draw.VertexBuffers[0].Declaration, out Vector3[] arraypositions, out Core.Mathematics.Vector3[] normals, out Core.Mathematics.Vector2[] uvs,
protected override void EndDraw(bool present) { base.EndDraw(present); // handle any VR flushing if (VRDeviceSystem.Device != null) { VRDeviceSystem.Device.Flush(); } // have any staged mesh draws to clear out? StagedMeshDraw.FlushTrash(); }
private static unsafe void ProcessMaterial(List <BatchingChunk> chunks, MaterialInstance material, Model prefabModel, HashSet <Entity> unbatched = null) { //actually create the mesh List <VertexPositionNormalTextureTangent> vertsNT = null; List <VertexPositionNormalColor> vertsNC = null; List <uint> indiciesList = new List <uint>(); BoundingBox bb = new BoundingBox(new Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity), new Vector3(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity)); uint indexOffset = 0; for (int i = 0; i < chunks.Count; i++) { BatchingChunk chunk = chunks[i]; if (unbatched != null && unbatched.Contains(chunk.Entity)) { continue; // don't try batching other things in this entity if some failed } if (chunk.Entity != null) { chunk.Entity.Transform.UpdateLocalMatrix(); chunk.Entity.Transform.UpdateWorldMatrixInternal(true, false); } Matrix worldMatrix = chunk.Entity == null ? (chunk.Transform ?? Matrix.Identity) : chunk.Entity.Transform.WorldMatrix; Matrix rot; if (worldMatrix != Matrix.Identity) { worldMatrix.GetRotationMatrix(out rot); } else { rot = Matrix.Identity; } for (int j = 0; j < chunk.Model.Meshes.Count; j++) { Mesh modelMesh = chunk.Model.Meshes[j]; //process only right material if (modelMesh.MaterialIndex == chunk.MaterialIndex) { Vector3[] positions = null, normals = null; Vector4[] tangents = null; Vector2[] uvs = null; Color4[] colors = null; //vertexes if (CachedModelData.TryGet(modelMesh, out var information)) { // clone positions and normals, since they may change positions = (Vector3[])information.positions.Clone(); normals = (Vector3[])information.normals.Clone(); tangents = information.tangents; uvs = information.uvs; colors = information.colors; for (int k = 0; k < information.indicies.Length; k++) { indiciesList.Add(information.indicies[k] + indexOffset); } } else if (modelMesh.Draw is StagedMeshDraw) { StagedMeshDraw smd = modelMesh.Draw as StagedMeshDraw; object verts = smd.Verticies; if (verts is VertexPositionNormalColor[]) { VertexPositionNormalColor[] vpnc = verts as VertexPositionNormalColor[]; positions = new Vector3[vpnc.Length]; normals = new Vector3[vpnc.Length]; colors = new Color4[vpnc.Length]; for (int k = 0; k < vpnc.Length; k++) { positions[k] = vpnc[k].Position; normals[k] = vpnc[k].Normal; colors[k] = vpnc[k].Color; } } else if (verts is VertexPositionNormalTexture[]) { VertexPositionNormalTexture[] vpnc = verts as VertexPositionNormalTexture[]; positions = new Vector3[vpnc.Length]; normals = new Vector3[vpnc.Length]; uvs = new Vector2[vpnc.Length]; for (int k = 0; k < vpnc.Length; k++) { positions[k] = vpnc[k].Position; normals[k] = vpnc[k].Normal; uvs[k] = vpnc[k].TextureCoordinate; } } else if (verts is VertexPositionNormalTextureTangent[]) { VertexPositionNormalTextureTangent[] vpnc = verts as VertexPositionNormalTextureTangent[]; positions = new Vector3[vpnc.Length]; normals = new Vector3[vpnc.Length]; uvs = new Vector2[vpnc.Length]; tangents = new Vector4[vpnc.Length]; for (int k = 0; k < vpnc.Length; k++) { positions[k] = vpnc[k].Position; normals[k] = vpnc[k].Normal; uvs[k] = vpnc[k].TextureCoordinate; tangents[k] = vpnc[k].Tangent; } } else { // unsupported StagedMeshDraw if (unbatched != null) { unbatched.Add(chunk.Entity); } continue; } // take care of indicies for (int k = 0; k < smd.Indicies.Length; k++) { indiciesList.Add(smd.Indicies[k] + indexOffset); } // cache this for later CachedModelData.Add(modelMesh, new CachedData() { colors = colors, indicies = smd.Indicies, normals = (Vector3[])normals.Clone(), positions = (Vector3[])positions.Clone(), tangents = tangents, uvs = uvs } ); } else { Xenko.Graphics.Buffer buf = modelMesh.Draw?.VertexBuffers[0].Buffer; Xenko.Graphics.Buffer ibuf = modelMesh.Draw?.IndexBuffer.Buffer; if (buf == null || buf.VertIndexData == null || ibuf == null || ibuf.VertIndexData == null) { if (unbatched != null) { unbatched.Add(chunk.Entity); } continue; } if (UnpackRawVertData(buf.VertIndexData, modelMesh.Draw.VertexBuffers[0].Declaration, out positions, out normals, out uvs, out colors, out tangents) == false) { if (unbatched != null) { unbatched.Add(chunk.Entity); } continue; } CachedData cmd = new CachedData() { colors = colors, positions = (Vector3[])positions.Clone(), normals = (Vector3[])normals.Clone(), uvs = uvs, tangents = tangents }; // indicies fixed(byte *pdst = ibuf.VertIndexData) { int numIndices = modelMesh.Draw.IndexBuffer.Count; cmd.indicies = new uint[numIndices]; if (modelMesh.Draw.IndexBuffer.Is32Bit) { var dst = (uint *)(pdst + modelMesh.Draw.IndexBuffer.Offset); for (var k = 0; k < numIndices; k++) { // Offset indices cmd.indicies[k] = dst[k]; indiciesList.Add(dst[k] + indexOffset); } } else { var dst = (ushort *)(pdst + modelMesh.Draw.IndexBuffer.Offset); for (var k = 0; k < numIndices; k++) { // Offset indices cmd.indicies[k] = dst[k]; indiciesList.Add(dst[k] + indexOffset); } } } CachedModelData.Add(modelMesh, cmd); } // what kind of structure will we be making, if we haven't picked one already? if (vertsNT == null && vertsNC == null) { if (uvs != null) { vertsNT = new List <VertexPositionNormalTextureTangent>(positions.Length); } else { vertsNC = new List <VertexPositionNormalColor>(positions.Length); } } // bounding box/finish list bool needmatrix = worldMatrix != Matrix.Identity; for (int k = 0; k < positions.Length; k++) { if (needmatrix) { Vector3.Transform(ref positions[k], ref worldMatrix, out positions[k]); if (normals != null) { Vector3.TransformNormal(ref normals[k], ref rot, out normals[k]); } } // update bounding box? Vector3 pos = positions[k]; if (pos.X > bb.Maximum.X) { bb.Maximum.X = pos.X; } if (pos.Y > bb.Maximum.Y) { bb.Maximum.Y = pos.Y; } if (pos.Z > bb.Maximum.Z) { bb.Maximum.Z = pos.Z; } if (pos.X < bb.Minimum.X) { bb.Minimum.X = pos.X; } if (pos.Y < bb.Minimum.Y) { bb.Minimum.Y = pos.Y; } if (pos.Z < bb.Minimum.Z) { bb.Minimum.Z = pos.Z; } if (vertsNT != null) { vertsNT.Add(new VertexPositionNormalTextureTangent { Position = positions[k], Normal = normals != null ? normals[k] : Vector3.UnitY, TextureCoordinate = uvs[k], Tangent = tangents != null ? tangents[k] : Vector4.UnitW }); } else { vertsNC.Add(new VertexPositionNormalColor { Position = positions[k], Normal = normals != null ? normals[k] : Vector3.UnitY, Color = colors != null ? colors[k] : Color4.White }); } } indexOffset += (uint)positions.Length; } } } if (indiciesList.Count <= 0) { return; } uint[] indicies = indiciesList.ToArray(); // make stagedmesh with verts StagedMeshDraw md; if (vertsNT != null) { var vertsNTa = vertsNT.ToArray(); md = StagedMeshDraw.MakeStagedMeshDraw <VertexPositionNormalTextureTangent>(ref indicies, ref vertsNTa, VertexPositionNormalTextureTangent.Layout); } else if (vertsNC != null) { var vertsNCa = vertsNC.ToArray(); md = StagedMeshDraw.MakeStagedMeshDraw <VertexPositionNormalColor>(ref indicies, ref vertsNCa, VertexPositionNormalColor.Layout); } else { return; } Mesh m = new Mesh { Draw = md, BoundingBox = bb, MaterialIndex = prefabModel.Materials.Count }; prefabModel.Add(m); if (material != null) { prefabModel.Add(material); } }