Пример #1
0
        public OglVertexArray Init(Action <InitOption> option, Action <VertexDataBuilder> builder)
        {
            if (option != null)
            {
                var initOption = new InitOption(this);
                option(initOption);
                //data = initOption.databytes;
                vao = 0;
                vbo = 0;
            }

            if (builder != null)
            {
                var vartexDataBuilder = new VertexDataBuilder(this);
                builder(vartexDataBuilder);
                data = vartexDataBuilder.buildResult.ToArray();
            }
            InitBuffer();
            return(this);
        }
Пример #2
0
        public unsafe override ProcessedModel ProcessT(Stream stream, string extension)
        {
            AssimpContext ac    = new AssimpContext();
            Scene         scene = ac.ImportFileFromStream(
                stream,
                PostProcessSteps.FlipWindingOrder | PostProcessSteps.GenerateNormals | PostProcessSteps.FlipUVs,
                extension);
            aiMatrix4x4 rootNodeInverseTransform = scene.RootNode.Transform;

            rootNodeInverseTransform.Inverse();

            List <ProcessedMeshPart>  parts      = new List <ProcessedMeshPart>();
            List <ProcessedAnimation> animations = new List <ProcessedAnimation>();

            HashSet <string> encounteredNames = new HashSet <string>();

            for (int meshIndex = 0; meshIndex < scene.MeshCount; meshIndex++)
            {
                Mesh   mesh     = scene.Meshes[meshIndex];
                string meshName = mesh.Name;
                if (string.IsNullOrEmpty(meshName))
                {
                    meshName = $"mesh_{meshIndex}";
                }
                int counter = 1;
                while (!encounteredNames.Add(meshName))
                {
                    meshName = mesh.Name + "_" + counter.ToString();
                    counter += 1;
                }
                int vertexCount = mesh.VertexCount;

                int positionOffset    = 0;
                int normalOffset      = 12;
                int texCoordsOffset   = -1;
                int boneWeightOffset  = -1;
                int boneIndicesOffset = -1;

                List <VertexElementDescription> elementDescs = new List <VertexElementDescription>();
                elementDescs.Add(new VertexElementDescription("Position", VertexElementSemantic.Position, VertexElementFormat.Float3));
                elementDescs.Add(new VertexElementDescription("Normal", VertexElementSemantic.Normal, VertexElementFormat.Float3));
                normalOffset = 12;

                int vertexSize = 24;

                bool hasTexCoords = mesh.HasTextureCoords(0);
                elementDescs.Add(new VertexElementDescription("TexCoords", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float2));
                texCoordsOffset = vertexSize;
                vertexSize     += 8;

                bool hasBones = mesh.HasBones;
                if (hasBones)
                {
                    elementDescs.Add(new VertexElementDescription("BoneWeights", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float4));
                    elementDescs.Add(new VertexElementDescription("BoneIndices", VertexElementSemantic.TextureCoordinate, VertexElementFormat.UInt4));

                    boneWeightOffset = vertexSize;
                    vertexSize      += 16;

                    boneIndicesOffset = vertexSize;
                    vertexSize       += 16;
                }

                byte[]            vertexData = new byte[vertexCount * vertexSize];
                VertexDataBuilder builder    = new VertexDataBuilder(vertexData, vertexSize);
                Vector3           min        = vertexCount > 0 ? mesh.Vertices[0].ToSystemVector3() : Vector3.Zero;
                Vector3           max        = vertexCount > 0 ? mesh.Vertices[0].ToSystemVector3() : Vector3.Zero;

                for (int i = 0; i < vertexCount; i++)
                {
                    Vector3 position = mesh.Vertices[i].ToSystemVector3();
                    min = Vector3.Min(min, position);
                    max = Vector3.Max(max, position);

                    builder.WriteVertexElement(
                        i,
                        positionOffset,
                        position);

                    Vector3 normal = mesh.Normals[i].ToSystemVector3();
                    builder.WriteVertexElement(i, normalOffset, normal);

                    if (mesh.HasTextureCoords(0))
                    {
                        builder.WriteVertexElement(
                            i,
                            texCoordsOffset,
                            new Vector2(mesh.TextureCoordinateChannels[0][i].X, mesh.TextureCoordinateChannels[0][i].Y));
                    }
                    else
                    {
                        builder.WriteVertexElement(
                            i,
                            texCoordsOffset,
                            new Vector2());
                    }
                }

                List <int> indices = new List <int>();
                foreach (Face face in mesh.Faces)
                {
                    if (face.IndexCount == 3)
                    {
                        indices.Add(face.Indices[0]);
                        indices.Add(face.Indices[1]);
                        indices.Add(face.Indices[2]);
                    }
                }

                Dictionary <string, uint>   boneIDsByName = new Dictionary <string, uint>();
                System.Numerics.Matrix4x4[] boneOffsets   = new System.Numerics.Matrix4x4[mesh.BoneCount];

                if (hasBones)
                {
                    Dictionary <int, int> assignedBoneWeights = new Dictionary <int, int>();
                    for (uint boneID = 0; boneID < mesh.BoneCount; boneID++)
                    {
                        Bone   bone     = mesh.Bones[(int)boneID];
                        string boneName = bone.Name;
                        int    suffix   = 1;
                        while (boneIDsByName.ContainsKey(boneName))
                        {
                            boneName = bone.Name + "_" + suffix.ToString();
                            suffix  += 1;
                        }

                        boneIDsByName.Add(boneName, boneID);
                        foreach (VertexWeight weight in bone.VertexWeights)
                        {
                            int relativeBoneIndex = GetAndIncrementRelativeBoneIndex(assignedBoneWeights, weight.VertexID);
                            builder.WriteVertexElement(weight.VertexID, boneIndicesOffset + (relativeBoneIndex * sizeof(uint)), boneID);
                            builder.WriteVertexElement(weight.VertexID, boneWeightOffset + (relativeBoneIndex * sizeof(float)), weight.Weight);
                        }

                        System.Numerics.Matrix4x4 offsetMat = bone.OffsetMatrix.ToSystemMatrixTransposed();
                        System.Numerics.Matrix4x4.Decompose(offsetMat, out var scale, out var rot, out var trans);
                        offsetMat = System.Numerics.Matrix4x4.CreateScale(scale)
                                    * System.Numerics.Matrix4x4.CreateFromQuaternion(rot)
                                    * System.Numerics.Matrix4x4.CreateTranslation(trans);

                        boneOffsets[boneID] = offsetMat;
                    }
                }
                builder.FreeGCHandle();

                uint indexCount = (uint)indices.Count;

                int[]  int32Indices = indices.ToArray();
                byte[] indexData    = new byte[indices.Count * sizeof(uint)];
                fixed(byte *indexDataPtr = indexData)
                {
                    fixed(int *int32Ptr = int32Indices)
                    {
                        Buffer.MemoryCopy(int32Ptr, indexDataPtr, indexData.Length, indexData.Length);
                    }
                }

                ProcessedMeshPart part = new ProcessedMeshPart(
                    vertexData,
                    elementDescs.ToArray(),
                    indexData,
                    IndexFormat.UInt32,
                    (uint)indices.Count,
                    boneIDsByName,
                    boneOffsets);
                parts.Add(part);
            }

            // Nodes
            Node rootNode = scene.RootNode;
            List <ProcessedNode> processedNodes = new List <ProcessedNode>();

            ConvertNode(rootNode, -1, processedNodes);

            ProcessedNodeSet nodes = new ProcessedNodeSet(processedNodes.ToArray(), 0, rootNodeInverseTransform.ToSystemMatrixTransposed());

            for (int animIndex = 0; animIndex < scene.AnimationCount; animIndex++)
            {
                Animation animation = scene.Animations[animIndex];
                Dictionary <string, ProcessedAnimationChannel> channels = new Dictionary <string, ProcessedAnimationChannel>();
                for (int channelIndex = 0; channelIndex < animation.NodeAnimationChannelCount; channelIndex++)
                {
                    NodeAnimationChannel nac = animation.NodeAnimationChannels[channelIndex];
                    channels[nac.NodeName] = ConvertChannel(nac);
                }

                string baseAnimName = animation.Name;
                if (string.IsNullOrEmpty(baseAnimName))
                {
                    baseAnimName = "anim_" + animIndex;
                }

                string animationName = baseAnimName;


                int counter = 1;
                while (!encounteredNames.Add(animationName))
                {
                    animationName = baseAnimName + "_" + counter.ToString();
                    counter      += 1;
                }
            }

            return(new ProcessedModel()
            {
                MeshParts = parts.ToArray(),
                Animations = animations.ToArray(),
                Nodes = nodes
            });
        }