예제 #1
0
        /// <summary>
        /// Load the bone information for each vertex
        /// </summary>
        /// <param name="assimpMesh"> mesh that contains the information to be processed </param>
        /// <param name="mesh"> customized mesh that stores information for later use </param>
        protected void LoadBoneWeights(Mesh assimpMesh, ClientMesh mesh)
        {
            // create a new data structures to store the bones
            mesh.VertexBoneDatas = new List <VertexBoneData>(mesh.CountVertices);
            for (int i = 0; i < mesh.CountVertices; i++)
            {
                mesh.VertexBoneDatas.Add(new VertexBoneData());
            }

            // copy bone weights from the meshes for each vertex
            for (int boneIndex = 0; boneIndex < assimpMesh.BoneCount; boneIndex++)
            {
                Bone currBone = assimpMesh.Bones[boneIndex];

                for (int weighti = 0; weighti < currBone.VertexWeightCount; weighti++)
                {
                    VertexWeight vertexWeight = currBone.VertexWeights[weighti];
                    mesh.VertexBoneDatas[vertexWeight.VertexID].AddBoneData(_allBoneMappings[currBone.Name], vertexWeight.Weight);
                }
            }

            // create new datastream so that we can stream them to the VBOs
            mesh.boneIDSize     = sizeof(int) * VertexBoneData.MAX_BONES_PER_VERTEX * mesh.CountVertices;
            mesh.boneWeightSize = sizeof(float) * VertexBoneData.MAX_BONES_PER_VERTEX * mesh.CountVertices;
            mesh.DSBoneIDs      = new DataStream(mesh.boneIDSize, true, true);
            mesh.DSBoneWeights  = new DataStream(mesh.boneWeightSize, true, true);

            // for each vertex, write the vertex buffer datastreams
            for (int i = 0; i < mesh.CountVertices; i++)
            {
                // normalize bone weights
                //mesh.VertexBoneDatas[i].NormalizeBoneData();

                // write the data into datastreams
                for (int bonei = 0; bonei < VertexBoneData.MAX_BONES_PER_VERTEX; bonei++)
                {
                    mesh.DSBoneIDs.Write(mesh.VertexBoneDatas[i].BoneIndices[bonei]);
                    mesh.DSBoneWeights.Write(mesh.VertexBoneDatas[i].BoneWeights[bonei]);
                }
            }

            mesh.DSBoneWeights.Position = 0;
            mesh.DSBoneIDs.Position     = 0;

            // create the datastreams
            mesh.VBOBoneIDs     = new Buffer(GraphicsRenderer.Device, mesh.DSBoneIDs, mesh.boneIDSize, ResourceUsage.Default, BindFlags.VertexBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);
            mesh.VBOBoneWeights = new Buffer(GraphicsRenderer.Device, mesh.DSBoneWeights, mesh.boneWeightSize, ResourceUsage.Default, BindFlags.VertexBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);
        }
예제 #2
0
        /// <summary>
        /// Draw a model by using the modelmatrix it is assigned to
        /// </summary>
        /// <param name="modelMatrix"> describes how the object is viewed in the world space </param>
        /// <param name="shader"> the shader that is used to draw the geometry </param>
        public void Draw(Matrix modelMatrix, Shader shader)
        {
            shader.ShaderEffect.GetVariableByName("gWorld").AsMatrix().SetMatrix(modelMatrix);
            shader.ShaderEffect.GetVariableByName("gView").AsMatrix()
            .SetMatrix(GraphicsManager.ActiveCamera.m_ViewMatrix);
            shader.ShaderEffect.GetVariableByName("gProj").AsMatrix().SetMatrix(GraphicsRenderer.ProjectionMatrix);

            GraphicsManager.ActiveLightSystem.UpdateShader(shader, modelMatrix);
            shader.ShaderEffect.GetVariableByName("CamPosObj").AsVector().Set(
                Vector4.Transform(new Vector4(GraphicsManager.ActiveCamera.CameraPosition, 1.0f), Matrix.Invert(modelMatrix)));


            if (CurrentAnimationIndex != -1)
            {
                //shader.ShaderEffect.GetVariableByName("boneTransforms")
                //    .SetRawValue(_boneTransformStream, MAX_BONES_PER_GEO * sizeof(float) * 16);
                shader.ShaderEffect.GetVariableByName("boneTransforms").AsMatrix().SetMatrixArray(_boneTransformList.ToArray());
            }

            for (int i = 0; i < scene.MeshCount; i++)
            {
                ClientMesh mesh = allMeshes[i];

                // pass vertices, normals, and indices into the shader
                GraphicsRenderer.Device.ImmediateContext.InputAssembler.SetVertexBuffers(VertexLoc,
                                                                                         new VertexBufferBinding(mesh.VBOPositions, Vector3.SizeInBytes, 0));
                GraphicsRenderer.Device.ImmediateContext.InputAssembler.SetVertexBuffers(NormalLoc,
                                                                                         new VertexBufferBinding(mesh.VBONormals, Vector3.SizeInBytes, 0));

                GraphicsRenderer.Device.ImmediateContext.InputAssembler.SetIndexBuffer(mesh.EBO, Format.R32_UInt, 0);

                // pass texture coordinates into the shader if applicable
                if (mesh.Materials.texCount > 0)
                {
                    // note that the raw parsed tex coords are in vec3, we just need the first 2 elements of the vector
                    GraphicsRenderer.Device.ImmediateContext.InputAssembler.SetVertexBuffers(TexLoc,
                                                                                             new VertexBufferBinding(mesh.VBOTexCoords, Vector3.SizeInBytes, 0));
                }

                // pass bone IDs and weights if applicable
                shader.ShaderEffect.GetVariableByName("animationIndex").AsScalar().Set(CurrentAnimationIndex);
                if (CurrentAnimationIndex != -1)
                {
                    shader.ShaderEffect.GetVariableByName("meshTransform").AsMatrix().SetMatrix(_allBones[0].GlobalAnimatedTransform);
                    GraphicsRenderer.Device.ImmediateContext.InputAssembler.SetVertexBuffers(BoneIdLoc,
                                                                                             new VertexBufferBinding(mesh.VBOBoneIDs, sizeof(int) * VertexBoneData.MAX_BONES_PER_VERTEX, 0));

                    GraphicsRenderer.Device.ImmediateContext.InputAssembler.SetVertexBuffers(BoneWeightLoc,
                                                                                             new VertexBufferBinding(mesh.VBOBoneWeights, sizeof(float) * VertexBoneData.MAX_BONES_PER_VERTEX, 0));
                }

                // pass texture resource into the shader if applicable
                if (mesh.Materials.texSRV != null)
                {
                    shader.ShaderEffect.GetVariableByName("tex_diffuse").AsResource().SetResource(mesh.Materials.texSRV);
                }

                // pass material properties into the shader
                if (!useAltColor || mesh.Materials.texCount > 0)
                {
                    shader.ShaderEffect.GetVariableByName("Diffuse").AsVector().Set(mesh.Materials.diffuse);
                }
                else
                {
                    shader.ShaderEffect.GetVariableByName("Diffuse").AsVector().Set(mesh.Materials.diffuse.ScalarMultiply(altDiffuseColor));
                }

                shader.ShaderEffect.GetVariableByName("Specular").AsVector().Set(mesh.Materials.specular);
                shader.ShaderEffect.GetVariableByName("Ambient").AsVector().Set(mesh.Materials.ambient);
                shader.ShaderEffect.GetVariableByName("Emissive").AsVector().Set(mesh.Materials.emissive);
                shader.ShaderEffect.GetVariableByName("Shininess").AsScalar().Set(mesh.Materials.shininess);
                shader.ShaderEffect.GetVariableByName("Opacity").AsScalar().Set(mesh.Materials.opacity);
                shader.ShaderEffect.GetVariableByName("texCount").AsScalar().Set(mesh.Materials.texCount);

                // Draw the object using the indices
                shader.ShaderPass.Apply(GraphicsRenderer.Device.ImmediateContext);
                GraphicsRenderer.Device.ImmediateContext.DrawIndexed(mesh.faceSize / sizeof(int), 0, 0);
            }
        }
예제 #3
0
        /// <summary>
        /// Create a new geometry given filename
        /// </summary>
        /// <param name="fileName"> filepath to the 3D model file </param>
        public Geometry(string fileName, bool enableRigging = false)
        {
            RiggingEnabled = enableRigging;
            sourceFileName = fileName;

            //Create new importer.
            importer = new AssimpContext();

            //import the file
            scene = importer.ImportFile(fileName,
                                        PostProcessSteps.CalculateTangentSpace | PostProcessSteps.Triangulate |
                                        PostProcessSteps.JoinIdenticalVertices | PostProcessSteps.SortByPrimitiveType |
                                        PostProcessSteps.GenerateUVCoords | PostProcessSteps.FlipUVs |
                                        PostProcessSteps.LimitBoneWeights | PostProcessSteps.ValidateDataStructure);

            //make sure scene not null
            if (scene == null)
            {
                throw new FileNotFoundException();
            }

            //loop through sizes and count them.
            allMeshes = new List <ClientMesh>(scene.MeshCount);

            //loop through and store sizes
            for (int idx = 0; idx < scene.MeshCount; idx++)
            {
                ClientMesh mesh = new ClientMesh();
                allMeshes.Add(mesh);

                mesh.CountVertices = scene.Meshes[idx].VertexCount;

                mesh.vertSize = scene.Meshes[idx].VertexCount * Vector3.SizeInBytes;
                mesh.normSize = scene.Meshes[idx].Normals.Count * Vector3.SizeInBytes;
                mesh.faceSize = scene.Meshes[idx].FaceCount * scene.Meshes[idx].Faces[0].IndexCount * sizeof(int);
                if (scene.Meshes[idx].HasTextureCoords(0))
                {
                    mesh.texSize = scene.Meshes[idx].TextureCoordinateChannels[0].Count * Vector3.SizeInBytes;
                }
            }

            diffuseTextureSRV = new Dictionary <string, ShaderResourceView>();

            // do all the processing that rigging is required to have
            if (enableRigging)
            {
                _allBones        = new List <ClientBone>();
                _allBoneMappings = new Dictionary <string, int>();
                _allBoneLookup   = new Dictionary <string, ClientBone>();

                // set the animation related lookup tables
                AnimationIndices = new Dictionary <string, int>();
                _animationNodes  = new List <Dictionary <string, ClientAnimationNode> >(scene.AnimationCount);
                for (int i = 0; i < scene.AnimationCount; i++)
                {
                    AnimationIndices[scene.Animations[i].Name] = i;
                    _animationNodes.Add(new Dictionary <string, ClientAnimationNode>());

                    for (int j = 0; j < scene.Animations[i].NodeAnimationChannelCount; j++)
                    {
                        NodeAnimationChannel ch     = scene.Animations[i].NodeAnimationChannels[j];
                        ClientAnimationNode  myNode = new ClientAnimationNode(ch.NodeName);

                        _animationNodes[i][ch.NodeName] = myNode;
                        myNode.Translations             = new List <Vector3>();
                        myNode.TranslationTime          = new List <double>();
                        myNode.Rotations    = new List <Quaternion>();
                        myNode.RotationTime = new List <double>();
                        myNode.Scalings     = new List <Vector3>();
                        myNode.ScalingTime  = new List <double>();

                        // copy over all the necessary information in the animation channels
                        for (int k = 0; k < ch.PositionKeyCount; k++)
                        {
                            myNode.Translations.Add(ch.PositionKeys[k].Value.ToVector3());
                            myNode.TranslationTime.Add(ch.PositionKeys[k].Time);
                        }

                        for (int k = 0; k < ch.RotationKeyCount; k++)
                        {
                            myNode.Rotations.Add(ch.RotationKeys[k].Value.ToQuaternion());
                            myNode.RotationTime.Add(ch.RotationKeys[k].Time);
                        }

                        for (int k = 0; k < ch.ScalingKeyCount; k++)
                        {
                            myNode.Scalings.Add(ch.ScalingKeys[k].Value.ToVector3());
                            myNode.ScalingTime.Add(ch.ScalingKeys[k].Time);
                        }
                    }
                }

                // create and store the big scene tree
                _rootBone = CreateBoneTree(scene.RootNode, null);

                // set each bone offset
                foreach (var sceneMesh in scene.Meshes)
                {
                    foreach (var rawBone in sceneMesh.Bones)
                    {
                        ClientBone found;
                        if (!_allBoneLookup.TryGetValue(rawBone.Name, out found))
                        {
                            Console.WriteLine("Cannot find bone: " + rawBone.Name);
                            continue;
                        }

                        found.BoneOffset = rawBone.OffsetMatrix.ToMatrix();
                        _allBones.Add(found);
                        _allBoneMappings[found.BoneName] = _allBones.IndexOf(found);
                    }
                }

                // for bones not inside the meshes...? jasdkl;fja;lskdjkfl
                foreach (var boneName in _allBoneLookup.Keys.Where(b =>
                                                                   _allBones.All(b1 => b1.BoneName != b) && b.StartsWith("Bone")))
                {
                    _allBoneLookup[boneName].BoneOffset = _allBoneLookup[boneName].Parent.BoneOffset.Clone();
                    _allBones.Add(_allBoneLookup[boneName]);
                    _allBoneMappings[boneName] = _allBones.IndexOf(_allBoneLookup[boneName]);
                }

                // load the bone weights
                for (int idx = 0; idx < scene.MeshCount; idx++)
                {
                    LoadBoneWeights(scene.Meshes[idx], allMeshes[idx]);
                }

                //_boneTransformStream = new DataStream(MAX_BONES_PER_GEO * sizeof(float) * 16, true, true);
                _boneTransformList = new List <Matrix>(MAX_BONES_PER_GEO);
                for (int i = 0; i < MAX_BONES_PER_GEO; i++)
                {
                    _boneTransformList.Add(Matrix.Identity);
                }
            }

            // main loading loop; copy cover the scene content into the datastreams and then to the buffers
            for (int idx = 0; idx < scene.MeshCount; idx++)
            {
                ClientMesh mesh = allMeshes[idx];

                //create new datastreams.
                mesh.Vertices = new DataStream(mesh.vertSize, true, true);
                mesh.Normals  = new DataStream(mesh.normSize, true, true);
                mesh.Faces    = new DataStream(mesh.faceSize, true, true);

                // create a new material
                mesh.Materials = new ClientMaterial();

                //min and max bounds
                var min = new Vector3(float.MaxValue);
                var max = new Vector3(float.MinValue);
                // copy the buffers
                scene.Meshes[idx].Vertices.ForEach(vertex =>
                {
                    mesh.Vertices.Write(vertex.ToVector3());

                    //keep track of min and max for obj boundaries.
                    min = Vector3.Minimize(min, vertex.ToVector3());
                    max = Vector3.Maximize(max, vertex.ToVector3());
                });
                BoundingBoxes.Add(new BoundingBox(min, max));


                scene.Meshes[idx].Normals.ForEach(normal =>
                {
                    mesh.Normals.Write(normal.ToVector3());
                });
                scene.Meshes[idx].Faces.ForEach(face =>
                {
                    mesh.Faces.WriteRange(face.Indices.ToArray());
                });

                // check if the mesh has texture coordinates
                if (scene.Meshes[idx].HasTextureCoords(0))
                {
                    mesh.TexCoords = new DataStream(mesh.texSize, true, true);
                    scene.Meshes[idx].TextureCoordinateChannels[0].ForEach(texture => {
                        mesh.TexCoords.Write(texture);
                    });

                    mesh.TexCoords.Position = 0;
                }

                // Parse material properties
                ApplyMaterial(scene.Materials[scene.Meshes[idx].MaterialIndex], mesh.Materials);

                // reset datastream positions
                mesh.Vertices.Position = 0;
                mesh.Normals.Position  = 0;
                mesh.Faces.Position    = 0;

                //create vertex vbo and faces ebo.
                mesh.VBOPositions = new Buffer(GraphicsRenderer.Device, mesh.Vertices, mesh.vertSize, ResourceUsage.Default, BindFlags.VertexBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);
                mesh.VBONormals   = new Buffer(GraphicsRenderer.Device, mesh.Normals, mesh.normSize, ResourceUsage.Default, BindFlags.VertexBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);
                if (scene.Meshes[idx].HasTextureCoords(0))
                {
                    mesh.VBOTexCoords = new Buffer(GraphicsRenderer.Device, mesh.TexCoords, mesh.texSize, ResourceUsage.Default, BindFlags.VertexBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);
                }

                // buffer creation flags
                var ibd = new BufferDescription(
                    mesh.faceSize,
                    ResourceUsage.Immutable,
                    BindFlags.IndexBuffer,
                    CpuAccessFlags.None,
                    ResourceOptionFlags.None,
                    0);

                mesh.EBO = new Buffer(GraphicsRenderer.Device, mesh.Faces, ibd);
            }

            _inverseGlobalTransform = Matrix.Invert(scene.RootNode.Transform.ToMatrix());
        }