Пример #1
0
        unsafe private void FillVerticesUV2(FLVER0.Mesh mesh, Span <Vector3> pickingVerts, IntPtr vertBuffer)
        {
            Span <FlverLayoutUV2> verts = new Span <FlverLayoutUV2>(vertBuffer.ToPointer(), mesh.Vertices.Count);

            for (int i = 0; i < mesh.Vertices.Count; i++)
            {
                var vert = mesh.Vertices[i];

                verts[i]        = new FlverLayoutUV2();
                pickingVerts[i] = new Vector3(vert.Position.X, vert.Position.Y, vert.Position.Z);
                fixed(FlverLayoutUV2 *v = &verts[i])
                {
                    FillVertex(ref (*v).Position, ref vert);
                    FillNormalSNorm8((*v).Normal, ref vert);
                    FillUVShort((*v).Uv1, ref vert, 0);
                    FillUVShort((*v).Uv2, ref vert, 1);
                    if (vert.TangentCount > 0)
                    {
                        FillBinormalBitangentSNorm8((*v).Binormal, (*v).Bitangent, ref vert, 0);
                    }
                    else
                    {
                        FillBinormalBitangentSNorm8Zero((*v).Binormal, (*v).Bitangent);
                    }
                }
            }
        }
Пример #2
0
        unsafe private void FillVerticesNormalOnly(FLVER0.Mesh mesh, Span <Vector3> pickingVerts, IntPtr vertBuffer)
        {
            Span <FlverLayoutSky> verts = new Span <FlverLayoutSky>(vertBuffer.ToPointer(), mesh.Vertices.Count);

            for (int i = 0; i < mesh.Vertices.Count; i++)
            {
                var vert = mesh.Vertices[i];

                verts[i]        = new FlverLayoutSky();
                pickingVerts[i] = new Vector3(vert.Position.X, vert.Position.Y, vert.Position.Z);
                fixed(FlverLayoutSky *v = &verts[i])
                {
                    FillVertex(ref (*v).Position, ref vert);
                    FillNormalSNorm8((*v).Normal, ref vert);
                }
            }
        }
Пример #3
0
        unsafe private void ProcessMesh(FLVER0.Mesh mesh, FlverSubmesh dest)
        {
            var factory = Scene.Renderer.Factory;

            dest.Material = GPUMaterials[mesh.MaterialIndex];

            //var MeshVertices = VerticesPool.Rent(mesh.VertexCount);
            var vSize        = dest.Material.VertexSize;
            var meshVertices = Marshal.AllocHGlobal(mesh.Vertices.Count * (int)vSize);

            dest.PickingVertices = Marshal.AllocHGlobal(mesh.Vertices.Count * sizeof(Vector3));
            var pvhandle = new Span <Vector3>(dest.PickingVertices.ToPointer(), mesh.Vertices.Count);

            if (dest.Material.LayoutType == MeshLayoutType.LayoutSky)
            {
                FillVerticesNormalOnly(mesh, pvhandle, meshVertices);
            }
            else if (dest.Material.LayoutType == MeshLayoutType.LayoutUV2)
            {
                FillVerticesUV2(mesh, pvhandle, meshVertices);
            }
            else
            {
                FillVerticesStandard(mesh, pvhandle, meshVertices);
            }

            dest.VertexCount = mesh.Vertices.Count;

            dest.MeshFacesets = new List <FlverSubmesh.FlverSubmeshFaceSet>();

            bool is32bit      = false;//FlverDeS.Version > 0x20005 && mesh.Vertices.Count > 65535;
            int  indicesTotal = 0;

            ushort[] fs16 = null;
            int[]    fs32 = null;

            int idxoffset = 0;

            if (mesh.VertexIndices.Count != 0)
            {
                var  indices    = mesh.Triangulate(FlverDeS.Version).ToArray();
                uint buffersize = (uint)indices.Length * (is32bit ? 4u : 2u);

                indicesTotal = indices.Length;
                if (is32bit)
                {
                    fs32 = new int[indicesTotal];
                }
                else
                {
                    fs16 = new ushort[indicesTotal];
                }

                var newFaceSet = new FlverSubmesh.FlverSubmeshFaceSet()
                {
                    BackfaceCulling = true,
                    IsTriangleStrip = false,
                    //IndexBuffer = factory.CreateBuffer(new BufferDescription(buffersize, BufferUsage.IndexBuffer)),
                    IndexOffset = idxoffset,

                    IndexCount          = indices.Length,
                    Is32Bit             = is32bit,
                    PickingIndicesCount = indices.Length,
                    //PickingIndices = Marshal.AllocHGlobal(indices.Length * 4),
                };
                fixed(void *iptr = indices)
                {
                    //Unsafe.CopyBlock(newFaceSet.PickingIndices.ToPointer(), iptr, (uint)indices.Length * 4);
                }

                if (is32bit)
                {
                    for (int i = 0; i < indices.Length; i++)
                    {
                        if (indices[i] == 0xFFFF && indices[i] > mesh.Vertices.Count)
                        {
                            fs32[newFaceSet.IndexOffset + i] = -1;
                        }
                        else
                        {
                            fs32[newFaceSet.IndexOffset + i] = indices[i];
                        }
                    }
                }
                else
                {
                    for (int i = 0; i < indices.Length; i++)
                    {
                        if (indices[i] == 0xFFFF && indices[i] > mesh.Vertices.Count)
                        {
                            fs16[newFaceSet.IndexOffset + i] = 0xFFFF;
                        }
                        else
                        {
                            fs16[newFaceSet.IndexOffset + i] = (ushort)indices[i];
                        }
                    }
                }

                dest.MeshFacesets.Add(newFaceSet);
            }

            dest.Bounds = BoundingBox.CreateFromPoints((Vector3 *)dest.PickingVertices.ToPointer(), dest.VertexCount, 12, Quaternion.Identity, Vector3.Zero, Vector3.One);

            uint vbuffersize = (uint)mesh.Vertices.Count * (uint)vSize;

            dest.GeomBuffer = Scene.Renderer.GeometryBufferAllocator.Allocate(vbuffersize, (uint)indicesTotal * (is32bit ? 4u : 2u), (int)vSize, 4, (h) =>
            {
                h.FillVBuffer(meshVertices, vSize * (uint)mesh.Vertices.Count, () =>
                {
                    Marshal.FreeHGlobal(meshVertices);
                });
                if (is32bit)
                {
                    h.FillIBuffer(fs32);
                }
                else
                {
                    h.FillIBuffer(fs16);
                }
            });

            if (CaptureMaterialLayouts)
            {
                lock (_matLayoutLock)
                {
                    if (!MaterialLayouts.ContainsKey(dest.Material.MaterialName))
                    {
                        MaterialLayouts.Add(dest.Material.MaterialName, Flver.BufferLayouts[mesh.LayoutIndex]);
                    }
                }
            }
        }
Пример #4
0
        public FlverSubmeshRenderer(Model parent, FLVER0 flvr, FLVER0.Mesh mesh)
        {
            Parent = parent;

            MaterialName = flvr.Materials[mesh.MaterialIndex].Name;

            var shortMaterialName = MiscUtil.GetFileNameWithoutDirectoryOrExtension(flvr.Materials[mesh.MaterialIndex].MTD);

            if (shortMaterialName.EndsWith("_Alp") ||
                shortMaterialName.Contains("_Edge") ||
                shortMaterialName.Contains("_Decal") ||
                shortMaterialName.Contains("_Cloth") ||
                shortMaterialName.Contains("_al") ||
                shortMaterialName.Contains("BlendOpacity"))
            {
                DrawStep = GFXDrawStep.AlphaEdge;
            }
            else
            {
                DrawStep = GFXDrawStep.Opaque;
            }

            bool hasLightmap = false;

            foreach (var matParam in flvr.Materials[mesh.MaterialIndex].Textures)
            {
                if (matParam == null || matParam.Type == null)
                {
                    break;
                }
                var paramNameCheck = matParam.Type.ToUpper();
                // DS3/BB
                if (paramNameCheck == "G_DIFFUSETEXTURE")
                {
                    TexNameDiffuse = matParam.Path;
                }
                else if (paramNameCheck == "G_SPECULARTEXTURE")
                {
                    TexNameSpecular = matParam.Path;
                }
                else if (paramNameCheck == "G_BUMPMAPTEXTURE")
                {
                    TexNameNormal = matParam.Path;
                }
                else if (paramNameCheck == "G_DOLTEXTURE1")
                {
                    TexNameDOL1 = matParam.Path;
                }
                else if (paramNameCheck == "G_DOLTEXTURE2")
                {
                    TexNameDOL2 = matParam.Path;
                }
                // DS1 params
                else if (paramNameCheck == "G_DIFFUSE")
                {
                    TexNameDiffuse = matParam.Path;
                }
                else if (paramNameCheck == "G_SPECULAR")
                {
                    TexNameSpecular = matParam.Path;
                }
                else if (paramNameCheck == "G_BUMPMAP")
                {
                    TexNameNormal = matParam.Path;
                }
                else if (paramNameCheck == "G_LIGHTMAP")
                {
                    TexNameDOL1 = matParam.Path;
                    hasLightmap = true;
                }
            }

            // MTD lookup
            MTD mtd = null;// InterrootLoader.GetMTD(flvr.Materials[mesh.MaterialIndex].MTD);

            var MeshVertices = new VertexPositionColorNormalTangentTexture[mesh.Vertices.Count];

            for (int i = 0; i < mesh.Vertices.Count; i++)
            {
                var vert = mesh.Vertices[i];
                MeshVertices[i] = new VertexPositionColorNormalTangentTexture();

                MeshVertices[i].Position = new Vector3(vert.Position.X, vert.Position.Y, vert.Position.Z);

                if (vert.Normal != null && vert.Tangents != null && vert.Tangents.Count > 0)
                {
                    MeshVertices[i].Normal   = Vector3.Normalize(new Vector3(vert.Normal.X, vert.Normal.Y, vert.Normal.Z));
                    MeshVertices[i].Binormal = Vector3.Normalize(new Vector3(vert.Bitangent.X, vert.Bitangent.Y, vert.Bitangent.Z));
                    MeshVertices[i].Tangent  = Vector3.Normalize(new Vector3(vert.Tangents[0].X, vert.Tangents[0].Y, vert.Tangents[0].Z));
                }

                if (vert.UVs.Count > 0)
                {
                    MeshVertices[i].TextureCoordinate = new Vector2(vert.UVs[0].X, vert.UVs[0].Y);
                    if (vert.UVs.Count > 1 && hasLightmap)
                    {
                        if (mtd == null)
                        {
                            // Really stupid heuristic to determine light map UVs without reading mtd files or something
                            if (vert.UVs.Count > 2 && flvr.Materials[mesh.MaterialIndex].Textures.Count > 11)
                            {
                                MeshVertices[i].TextureCoordinate2 = new Vector2(vert.UVs[2].X, vert.UVs[2].Y);
                            }
                            else
                            {
                                MeshVertices[i].TextureCoordinate2 = new Vector2(vert.UVs[1].X, vert.UVs[1].Y);
                            }
                        }
                        else
                        {
                            // Better heuristic with MTDs
                            int uvindex  = mtd.Textures.Find(tex => tex.Type.ToUpper() == "G_LIGHTMAP" || tex.Type.ToUpper() == "G_DOLTEXTURE1").UVNumber;
                            int uvoffset = 1;
                            for (int j = 1; j < uvindex; j++)
                            {
                                if (!mtd.Textures.Any(t => (t.UVNumber == j)))
                                {
                                    uvoffset++;
                                }
                            }
                            uvindex -= uvoffset;
                            if (vert.UVs.Count > uvindex)
                            {
                                MeshVertices[i].TextureCoordinate2 = new Vector2(vert.UVs[uvindex].X, vert.UVs[uvindex].Y);
                            }
                            else
                            {
                                MeshVertices[i].TextureCoordinate2 = new Vector2(vert.UVs[1].X, vert.UVs[1].Y);
                            }
                        }
                    }
                    else
                    {
                        MeshVertices[i].TextureCoordinate2 = Vector2.Zero;
                    }
                }
                else
                {
                    MeshVertices[i].TextureCoordinate  = Vector2.Zero;
                    MeshVertices[i].TextureCoordinate2 = Vector2.Zero;
                }
            }

            VertexCount = MeshVertices.Length;

            MeshFacesets = new List <FlverSubmeshRendererFaceSet>();

            var tlist      = mesh.ToTriangleList();
            var newFaceSet = new FlverSubmeshRendererFaceSet()
            {
                BackfaceCulling = true,
                IsTriangleStrip = false,
                IndexBuffer     = new IndexBuffer(
                    GFX.Device,
                    IndexElementSize.SixteenBits,
                    tlist.Length,
                    BufferUsage.WriteOnly),
                IndexCount = tlist.Length,
            };

            newFaceSet.IndexBuffer.SetData(tlist);

            MeshFacesets.Add(newFaceSet);

            Bounds = BoundingBox.CreateFromPoints(MeshVertices.Select(x => x.Position));

            VertBuffer = new VertexBuffer(GFX.Device,
                                          typeof(VertexPositionColorNormalTangentTexture), MeshVertices.Length, BufferUsage.WriteOnly);
            VertBuffer.SetData(MeshVertices);

            VertBufferBinding = new VertexBufferBinding(VertBuffer, 0, 0);

            TryToLoadTextures();
        }