コード例 #1
0
        public void Load(Stream source_stream)
        {
            NiHeader header = GetHeader(source_stream);

            header.Dump();

            int bt_NiTriShapeData           = header.GetBlockTypeIdxByName("NiTriShapeData");
            int bt_BSLightingShaderProperty = header.GetBlockTypeIdxByName("BSLightingShaderProperty");
            int bt_BSShaderTextureSet       = header.GetBlockTypeIdxByName("BSShaderTextureSet");
            int bt_NiSkinInstance           = header.GetBlockTypeIdxByName("NiSkinInstance");
            int bt_NiSkinPartition          = header.GetBlockTypeIdxByName("NiSkinPartition");

            int num_blocks = header.blocks.Length;

            for (int i = 0; i < num_blocks; i++)
            {
                if (header.blocks[i].type == bt_NiTriShapeData)
                {
                    NiTriShapeData triShapeData = GetObject <NiTriShapeData>(header, i);
                    triShapeData.Dump();
                }
                if (header.blocks[i].type == bt_BSLightingShaderProperty)
                {
                    BSLightingShaderProperty lightingShaderProperty = GetObject <BSLightingShaderProperty>(header, i);
                    lightingShaderProperty.Dump();
                }
                if (header.blocks[i].type == bt_BSShaderTextureSet)
                {
                    BSShaderTextureSet shaderTextureSet = GetObject <BSShaderTextureSet>(header, i);
                    shaderTextureSet.Dump();
                }
                if (header.blocks[i].type == bt_NiSkinInstance)
                {
                    NiSkinInstance skinInstance = GetObject <NiSkinInstance>(header, i);
                    skinInstance.Dump();
                    foreach (ObjectRef boneref in skinInstance.bones)
                    {
                        NiNode node = GetObject <NiNode>(header, boneref);
                        System.Console.WriteLine(header.strings[node.name]);
                    }
                }
                if (header.blocks[i].type == bt_NiSkinPartition)
                {
                    NiSkinPartition skinPartition = GetObject <NiSkinPartition>(header, i);
                    skinPartition.Dump();
                }
            }
        }
コード例 #2
0
ファイル: NifRuntime.cs プロジェクト: Wincent01/UnityNiDotNet
        private void BuildRig(NiSkinInstance skinInstance, GameObject holder)
        {
            var mesh = holder.GetComponent <MeshFilter>().sharedMesh;

            var partitions = skinInstance.SkinPartition.Object;

            var oldRenderer = holder.GetComponent <MeshRenderer>();
            var mat         = oldRenderer.sharedMaterial;

            Object.DestroyImmediate(oldRenderer);

            var renderer = holder.AddComponent <SkinnedMeshRenderer>();

            renderer.sharedMaterial = mat;
            renderer.sharedMesh     = mesh;
            renderer.rootBone       = _unityObjects[skinInstance.Root.Object].transform;

            var boneWeights = new BoneWeight[mesh.vertices.Length];

            //
            //    Loop through all the skin partitions to build the final rig.
            //    Currently there are skinned meshes where weird parts are stuck to root create awful rigs.
            //

            foreach (var partition in partitions.SkinPartitions)
            {
                for (var i = 0; i < partition.VertexMap.Length; i++)
                {
                    var index  = partition.VertexMap[i];
                    var weight = new BoneWeight();

                    for (var j = 0; j < partition.WeightsPerVertex; j++)
                    {
                        var value = partition.BoneIndices[i, j];

                        switch (j)
                        {
                        case 0:
                            weight.boneIndex0 = value;
                            break;

                        case 1:
                            weight.boneIndex1 = value;
                            break;

                        case 2:
                            weight.boneIndex2 = value;
                            break;

                        case 3:
                            weight.boneIndex3 = value;
                            break;

                        default:
                            throw new ArgumentOutOfRangeException(
                                      $"{_assetPath} has a skinned mesh with more than 4 weights/vertex. This is not supported.");
                        }

                        var vertexWeight = partition.VertexWeights[i, j];
                        switch (j)
                        {
                        case 0:
                            weight.weight0 = vertexWeight;
                            break;

                        case 1:
                            weight.weight1 = vertexWeight;
                            break;

                        case 2:
                            weight.weight2 = vertexWeight;
                            break;

                        case 3:
                            weight.weight3 = vertexWeight;
                            break;

                        default:
                            throw new ArgumentOutOfRangeException(
                                      $"{_assetPath} has a skinned mesh with more than 4 weights/vertex. This is not supported.");
                        }
                    }

                    boneWeights[index] = weight;
                }
            }

            mesh.boneWeights = boneWeights;

            var bones = new Transform[skinInstance.BonesCount];
            var poses = new Matrix4x4[skinInstance.BonesCount];

            for (var index = 0; index < skinInstance.BonesCount; index++)
            {
                var bone = skinInstance.SkinningData.Object.BoneList[index].Transform;

                var boneData    = skinInstance.Bones[index];
                var unityObject = _unityObjects[boneData].transform;
                bones[index] = unityObject;

                //
                //    I have no clue how to properly bind the skin to the bones.
                //    bone.Position & bone.Rotation is suppose to be offsets with the description of:
                //    "Offset of the skin from this bone in bind position."
                //    But I'm having a hard type parsing that.
                //

                var transform = unityObject;

                var pos = transform.position;
                var rot = transform.eulerAngles;

                Debug.Log($"{(Vector3) bone.Position} | {MatrixToEulerAngles(bone.Rotation)} | {bone.Scale} | {unityObject.name}");

                //transform.position = bone.Position;
                //transform.eulerAngles = renderer.rootBone.eulerAngles + MatrixToEulerAngles(bone.Rotation);

                poses[index] = unityObject.worldToLocalMatrix * renderer.rootBone.localToWorldMatrix;

                //transform.position = pos;
                //transform.eulerAngles = rot;
            }

            mesh.bindposes = poses;
            renderer.bones = bones;
        }