示例#1
0
        private void SetupNodeMetadata(Model model, aiNode nd)
        {
            var props = model.Props;
            var unparsedProperties = props.GetUnparsedProperties();

            // create metadata on node
            int numStaticMetaData = 2;
            var data = nd.MetaData;
            data.NumProperties = unparsedProperties.Count + numStaticMetaData;
            data.Keys = new string[data.NumProperties];
            data.Values = new AssimpSharp.MetadataEntry[data.NumProperties];
            int index = 0;

            // find user defined properties (3ds Max)
            data.Set<string>(index++, "UserProperties", PropertyHelper.PropertyGet<string>(props, "UDP3DSMAX", ""));
            unparsedProperties.Remove("UDP3DSMAX");
            data.Set(index++, "IsNull", model.IsNull ? true : false);

            foreach (var prop in unparsedProperties)
            {
                var interpreted = prop.Value.As<TypedProperty<bool>>();
                if (interpreted != null)
                {
                    data.Set(index++, prop.Key, interpreted.Value);
                }

            }
        }
示例#2
0
 private void ConvertCamera(Model model, Camera cam)
 {
     var camera = new AssimpSharp.Camera()
     {
         Name = FixNodeName(model.Name),
         Aspect = cam.AspectWidth.Value / cam.AspectHeight.Value,
         Position = cam.Position.Value,
         LookAt = cam.InterestPosition.Value - cam.Position.Value,
         HorizontalFOV = SharpDX.MathUtil.DegreesToRadians(cam.FieldOfView.Value)
     };
     Cameras.Add(camera);
 }
示例#3
0
        private int ConvertMeshSingleMaterial(MeshGeometry mesh, Model model, Matrix nodeGlobalTransform)
        {
            var mindices = mesh.MaterialIndices;
            var outMesh = SetupEmptyMesh(mesh);

            var vertices = mesh.Vertices;
            var faces = mesh.FaceIndexCounts;

            // copy vertices
            outMesh.NumVertices = vertices.Count;
            outMesh.Vertices = new Vector3[vertices.Count];
            vertices.CopyTo(outMesh.Vertices);

            // generate dummy faces
            outMesh.NumFaces = faces.Count;
            var fac = outMesh.Faces = new AssimpSharp.Face[faces.Count];
            for(int i=0; i<faces.Count; i++)
            {
                fac[i] = new AssimpSharp.Face();
            }

            int cursor = 0;
            var facIndex = 0;
            foreach(var pcount in faces)
            {
                var f = fac[facIndex++];
                f.Indices = new int[pcount];
                switch(pcount)
                {
                    case 1:
                        outMesh.PrimitiveTypes |= AssimpSharp.PrimitiveType.Point;
                        break;
                    case 2:
                        outMesh.PrimitiveTypes |= AssimpSharp.PrimitiveType.Line;
                        break;
                    case 3:
                        outMesh.PrimitiveTypes |= AssimpSharp.PrimitiveType.Triangle;
                        break;
                    default:
                        outMesh.PrimitiveTypes |= AssimpSharp.PrimitiveType.Polygon;
                        break;
                }
                for(int i=0; i<pcount; ++i)
                {
                    f.Indices[i] = cursor++;
                }
            }

            // copy normals
            var normals = mesh.Normals;
            if (normals.Count > 0)
            {
                Debug.Assert(normals.Count == vertices.Count);
                outMesh.Normals = new Vector3[vertices.Count];
                normals.CopyTo(outMesh.Normals);
            }

            // copy tangents - assimp requires both tangents and bitangents (binormals)
            // to be present, or neither of them. Compute binormals from normals
            // and tangents if needed.
            var tangents = mesh.Tangents;
            var binormals = mesh.Binormals;
            if (tangents.Count > 0)
            {
                var tempBinormals = new List<Vector3>();
                if (binormals.Count == 0)
                {
                    if (normals.Count > 0)
                    {
                        tempBinormals = new List<Vector3>(normals.Count);
                        for(int i=0; i<tangents.Count; i++)
                        {
                            tempBinormals.Add(Vector3.Cross(normals[i], tangents[i]));
                        }
                        binormals.Clear();
                        for(int i=0; i<tempBinormals.Count; i++)
                        {
                            binormals.Add(tempBinormals[i]);
                        }
                    }
                    else
                    {
                        binormals = null;
                    }
                }
                if (binormals != null)
                {
                    Debug.Assert(tangents.Count == vertices.Count);
                    Debug.Assert(binormals.Count == vertices.Count);

                    outMesh.Tangents = new Vector3[vertices.Count];
                    tangents.CopyTo(outMesh.Tangents);

                    outMesh.Bitangents = new Vector3[vertices.Count];
                    binormals.CopyTo(outMesh.Bitangents);
                }
            }

            // copy texture coords
            for (int i=0; i<Mesh.AI_MAX_NUMBER_OF_TEXTURECOORDS; i++)
            {
                var uvs = mesh.GetTextureCoords(i);
                if (uvs.Count == 0)
                {
                    break;
                }

                var outUv = outMesh.TextureCoords[i] = new Vector3[vertices.Count];
                for(int j=0; j<uvs.Count; j++)
                {
                    outUv[j] = new Vector3(uvs[j].X, uvs[j].Y, 0);
                }
            }

            // copy vertex colors
            for (int i = 0; i < aiMesh.AI_MAX_NUMBER_OF_COLOR_SETS; ++i)
            {
                var colors = mesh.GetVertexColors(i);
                if (colors.Count == 0)
                {
                    break;
                }
                outMesh.Colors[i] = new Color4[vertices.Count];
                colors.CopyTo(outMesh.Colors[i]);
            }

            if (!Doc.Settings.ReadMaterials || mindices.Count == 0)
            {
                //FBXImporter.LogError("no material assigned to mesh, setting default material");
                outMesh.MaterialIndex = GetDefaultMaterial();
            }
            else
            {
                ConvertMaterialForMesh(outMesh, model, mesh, mindices[0]);
            }

            if (Doc.Settings.ReadWeights && mesh.DeformerSkin != null)
            {
                ConvertWeights(outMesh, model, mesh, nodeGlobalTransform, NO_MATERIAL_SEPARATION);
            }

            return Meshes.Count - 1;
        }
示例#4
0
        private void ConvertTransformOrder_TRStoSRT(
            AssimpSharp.QuatKey[] outQuat,
            AssimpSharp.VectorKey[] outScale,
            AssimpSharp.VectorKey[] outTranslation,
            KeyFrameListList scaling,
            KeyFrameListList translation,
            KeyFrameListList rotation,
            KeyTimeList times,
            ref double maxTime,
            ref double minTime,
            Model.RotOrder order,
            Vector3 defScasle,
            Vector3 defTranslate,
            Quaternion defRotation)
        {
            if (rotation.Count > 0)
            {
                InterpolateKeys(outQuat, times, rotation, false, ref maxTime, ref minTime, order);
            }
            else
            {
                for (int i = 0; i < times.Count; i++)
                {
                    outQuat[i].Time = CONVERT_FBX_TIME(times[i]) * AnimFps;
                    outQuat[i].Value = defRotation;
                }
            }

            if (scaling.Count > 0)
            {
                InterpolateKeys(outScale, times, scaling, true, ref maxTime, ref minTime);
            }
            else
            {
                for (int i = 0; i < times.Count; i++)
                {
                    outScale[i].Time = CONVERT_FBX_TIME(times[i]) * AnimFps;
                    outScale[i].Value = defScasle;
                }
            }

            if (translation.Count > 0)
            {
                InterpolateKeys(outTranslation, times, translation, false, ref maxTime, ref minTime);
            }
            else
            {
                for (int i = 0; i < times.Count; i++)
                {
                    outTranslation[i].Time = CONVERT_FBX_TIME(times[i]) * AnimFps;
                    outTranslation[i].Value = defTranslate;
                }
            }

            var count = times.Count;
            for (int i = 0; i < count; i++)
            {
                var r = outQuat[i].Value;
                var s = outScale[i].Value;
                var t = outTranslation[i].Value;

                Matrix mat;

                Matrix.Translation(ref t, out mat);
                mat *= Matrix.RotationQuaternion(r);
                mat *= Matrix.Scaling(s);
                mat.Decompose(out s, out r, out t);
                outQuat[i].Value = r;
                outScale[i].Value = s;
                outTranslation[i].Value = t;
            }
        }
示例#5
0
        private void ConvertMaterialForMesh(aiMesh result, Model model, MeshGeometry geo, int materialIndex)
        {
            // locate source materials for this mesh
            var mats = model.Materials;
            if (materialIndex >= mats.Count || materialIndex < 0)
            {
                FBXImporter.LogError("material index out of bounds, setting default material");
                result.MaterialIndex = GetDefaultMaterial();
                return;
            }

            var mat = mats[materialIndex];
            int it;
            if (MaterialsConverted.TryGetValue(mat, out it))
            {
                result.MaterialIndex = it;
                return;
            }

            result.MaterialIndex = ConvertMaterial(mat, geo);
            this.MaterialsConverted[mat] = result.MaterialIndex;
        }
示例#6
0
        private List<int> ConvertMeshMultiMaterial(MeshGeometry mesh, Model model, Matrix nodeGlobalTransform)
        {
            var mindices = mesh.MaterialIndices;
            Debug.Assert(mindices.Count > 0);

            var had = new HashSet<int>();
            var indices = new List<int>();

            foreach (var index in mindices)
            {
                if (!had.Contains(index))
                {
                    indices.Add(ConvertMeshMultiMaterial(mesh, model, index, nodeGlobalTransform));
                    had.Add(index);
                }
            }
            return indices;
        }
示例#7
0
        /// <remarks>
        /// memory for output_nodes will be managed by the caller
        /// </remarks>
        private void GenerateTransformationNodeChain(Model model, out List<aiNode> outputNodes)
        {
            outputNodes = new List<aiNode>();
            var props = model.Props;
            var rot = model.RotationOrder.Value;
            bool ok;
            var chain = new Matrix[Enum.GetValues(typeof(TransformationComp)).Length];
            for(int i=0; i<chain.Length; i++)
            {
                chain[i] = Matrix.Identity;
            }
            float zeroEpsilon = 1e-6f;
            bool isComplex = false;

            Vector3 preRotation = PropertyHelper.PropertyGet<Vector3>(props, "PreRotation", out ok);
            if (ok && preRotation.LengthSquared() > zeroEpsilon)
            {
                isComplex = true;
                GetRotationMatrix(rot, preRotation, out chain[(int)TransformationComp.PreRotation]);
            }

            Vector3 postRotation = PropertyHelper.PropertyGet<Vector3>(props, "PostRotation", out ok);
            if (ok && postRotation.LengthSquared() > zeroEpsilon)
            {
                isComplex = true;
                GetRotationMatrix(rot, postRotation, out chain[(int)TransformationComp.PostRotation]);
            }

            Vector3 RotationPivot = PropertyHelper.PropertyGet<Vector3>(props, "RotationPivot", out ok);
            if (ok && RotationPivot.LengthSquared() > zeroEpsilon)
            {
                isComplex = true;
                Matrix.Translation(ref RotationPivot, out chain[(int)TransformationComp.RotationPivot]);
                chain[(int)TransformationComp.RotationPivotInverse] = Matrix.Translation(-RotationPivot);
            }

            Vector3 RotationOffset = PropertyHelper.PropertyGet<Vector3>(props, "RotationOffset", out ok);
            if (ok && RotationOffset.LengthSquared() > zeroEpsilon)
            {
                isComplex = true;
                Matrix.Translation(ref RotationOffset, out chain[(int)TransformationComp.RotationOffset]);
            }

            Vector3 ScalingOffset = PropertyHelper.PropertyGet<Vector3>(props, "ScalingOffset", out ok);
            if (ok && ScalingOffset.LengthSquared() > zeroEpsilon)
            {
                isComplex = true;
                Matrix.Translation(ref ScalingOffset, out chain[(int)TransformationComp.ScalingOffset]);
            }

            Vector3 ScalingPivot = PropertyHelper.PropertyGet<Vector3>(props, "ScalingPivot", out ok);
            if (ok && ScalingPivot.LengthSquared() > zeroEpsilon)
            {
                isComplex = true;
                chain[(int)TransformationComp.ScalingPivot] = Matrix.Translation(ScalingPivot);
                chain[(int)TransformationComp.ScalingPivotInverse] = Matrix.Translation(-ScalingPivot);
            }

            Vector3 Translation = PropertyHelper.PropertyGet<Vector3>(props, "Lcl Translation", out ok);
            if (ok && Translation.LengthSquared() > zeroEpsilon)
            {
                Matrix.Translation(ref Translation, out chain[(int)TransformationComp.Translation]);
            }

            Vector3 Scaling = PropertyHelper.PropertyGet<Vector3>(props, "Lcl Scaling", out ok);
            if (ok && Math.Abs(Scaling.LengthSquared() - 1.0f) > zeroEpsilon)
            {
                Matrix.Scaling(ref Scaling, out chain[(int)TransformationComp.Scaling]);
            }

            Vector3 Rotation = PropertyHelper.PropertyGet<Vector3>(props, "Lcl Rotation", out ok);
            if (ok && Rotation.LengthSquared() > zeroEpsilon)
            {
                GetRotationMatrix(rot, Rotation, out chain[(int)TransformationComp.Rotation]);
            }

            Vector3 GeometricScaling = PropertyHelper.PropertyGet<Vector3>(props, "GeometricScaling", out ok);
            if (ok && Math.Abs(GeometricScaling.LengthSquared() - 1.0f) > zeroEpsilon)
            {
                Matrix.Scaling(ref GeometricScaling, out chain[(int)TransformationComp.GeometricScaling]);
            }

            Vector3 GeometricRotation = PropertyHelper.PropertyGet<Vector3>(props, "GeometricRotation", out ok);
            if (ok && GeometricRotation.LengthSquared() > zeroEpsilon)
            {
                GetRotationMatrix(rot, GeometricRotation, out chain[(int)TransformationComp.GeometricRotation]);
            }

            Vector3 GeometricTranslation = PropertyHelper.PropertyGet<Vector3>(props, "GeometricTranslation", out ok);
            if (ok && GeometricTranslation.LengthSquared() > zeroEpsilon)
            {
                Matrix.Translation(ref GeometricTranslation, out chain[(int)TransformationComp.GeometricTranslation]);
            }

            // is_complex needs to be consistent with NeedsComplexTransformationChain()
            // or the interplay between this code and the animation converter would
            // not be guaranteed.
            Debug.Assert(NeedsComplexTransformationChain(model) == isComplex);

            string name = FixNodeName(model.Name);

            // now, if we have more than just Translation, Scaling and Rotation,
            // we need to generate a full node chain to accommodate for assimp's
            // lack to express pivots and offsets.
            if (isComplex && this.Doc.Settings.PreservePivots)
            {
                FBXImporter.LogInfo("generating full transformation chain for node: " + name);

                // query the anim_chain_bits dictionary to find out which chain elements
                // have associated node animation channels. These can not be dropped
                // even if they have identity transform in bind pose.
                uint animChainBitmask;
                if (!NodeAnimChainBits.TryGetValue(name, out animChainBitmask))
                {
                    animChainBitmask = 0;
                }

                uint bit = 0x1;
                for (int i = 0; i < Enum.GetValues(typeof(TransformationComp)).Length; ++i, bit <<= 1)
                {
                    TransformationComp comp = (TransformationComp)i;

                    if (chain[i].IsIdentity && (animChainBitmask & bit) == 0)
                    {
                        continue;
                    }

                    aiNode nd = new aiNode();
                    outputNodes.Add(nd);

                    nd.Name = NameTransformationChainNode(name, comp);
                    nd.Transformation = chain[i];
                }
                Debug.Assert(outputNodes.Count > 0);
                return;
            }

            // else, we can just multiply the matrices together
            aiNode nd_ = new aiNode();
            outputNodes.Add(nd_);

            nd_.Name = name;

            nd_.Transformation = Matrix.Identity;
            for (int i = 0; i < Enum.GetValues(typeof(TransformationComp)).Length; ++i)
            {
                nd_.Transformation = nd_.Transformation * chain[i];
            }
        }
示例#8
0
        private void ConvertLight(Model model, Light light)
        {
            var outLight = new AssimpSharp.Light();
            Lights.Add(outLight);
            outLight.Name = FixNodeName(model.Name);
            float intensity = light.Intensity.Value;
            Vector3 col = light.Color.Value;
            outLight.ColorDiffuse = new SharpDX.Vector3(col.X, col.Y, col.Z);
            outLight.ColorDiffuse.X *= intensity;
            outLight.ColorDiffuse.Y *= intensity;
            outLight.ColorDiffuse.Z *= intensity;
            outLight.ColorSpecular = outLight.ColorDiffuse;

            switch (light.LightType.Value)
            {
                case Light.Type.Point:
                    outLight.Type = AssimpSharp.LightSourceType.Point;
                    break;
                case Light.Type.Directional:
                    outLight.Type = AssimpSharp.LightSourceType.Directional;
                    break;
                case Light.Type.Spot:
                    outLight.Type = AssimpSharp.LightSourceType.Spot;
                    outLight.AngleOuterCone = SharpDX.MathUtil.DegreesToRadians(light.OuterAngle.Value);
                    outLight.AngleInnerCone = SharpDX.MathUtil.DegreesToRadians(light.InnerAngle.Value);
                    break;
                case Light.Type.Area:
                    outLight.Type = AssimpSharp.LightSourceType.Undefined;
                    break;
                case Light.Type.Volume:
                    outLight.Type = AssimpSharp.LightSourceType.Undefined;
                    break;
                default:
                    System.Diagnostics.Debug.Assert(false);
                    break;
            }
            switch (light.DecayType.Value)
            {
                case Light.Decay.None:
                    outLight.AttenuationConstant = 1.0f;
                    break;
                case Light.Decay.Linear:
                    outLight.AttenuationLinear = 1.0f;
                    break;
                case Light.Decay.Quadratic:
                    outLight.AttenuationQuadratic = 1.0f;
                    break;
                case Light.Decay.Cubic:
                    Debug.WriteLine("cannot represent cubic attenuation, set to Quadratic");
                    outLight.AttenuationQuadratic = 1.0f;
                    break;
            }
        }
示例#9
0
        private AssimpSharp.NodeAnim GenerateScalingNodeAnim(string name, Model target, List<AnimationCurveNode> curves, LayerMap layerMap,
            long start, long stop,
            double maxTime, double minTime)
        {
            var na = new AssimpSharp.NodeAnim();
            na.NodeName = name;

            ConvertScaleKeys(na, curves, layerMap, start, stop, ref maxTime, ref minTime);

            // dummy rotation key
            na.RotationKeys = new AssimpSharp.QuatKey[1];
            na.RotationKeys[0] = new AssimpSharp.QuatKey(0, new Quaternion());

            // dummy position key
            na.PositionKeys = new AssimpSharp.VectorKey[1];
            na.PositionKeys[0] = new AssimpSharp.VectorKey(0, new Vector3());

            return na;
        }
示例#10
0
        /// <summary>
        /// generate node anim, extracting only Rotation, Scaling and Translation from the given chain
        /// </summary>
        private AssimpSharp.NodeAnim GenerateSimpleNodeAnim(string name,
            Model target,
            List<AnimationCurveNode>[] chain,
            LayerMap layerMap,
            long start,
            long stop,
            ref double maxTime,
            ref double minTime,
            bool reverseOrder = false)
        {
            var na = new AssimpSharp.NodeAnim();
            na.NodeName = name;
            var props = target.Props;

            // need to convert from TRS order to SRT?
            if (reverseOrder)
            {
                var defScale = Vector3.Zero;
                var defTranslate = Vector3.Zero;
                var defRot = Quaternion.Identity;
                var scaling = new KeyFrameListList();
                var translation = new KeyFrameListList();
                var rotation = new KeyFrameListList();
                if (chain[(int)TransformationComp.Scaling] != null)
                {
                    scaling = GetKeyframeList(chain[(int)TransformationComp.Scaling], start, stop);
                }
                else
                {
                    defScale = PropertyHelper.PropertyGet(props, "Lcl Scaling", new Vector3(1, 1, 1));
                }
                if (chain[(int)TransformationComp.Translation] != null)
                {
                    translation = GetKeyframeList(chain[(int)TransformationComp.Translation], start, stop);
                }
                else
                {
                    defTranslate = PropertyHelper.PropertyGet(props, "Lcl Translation", new Vector3(0, 0, 0));
                }
                if (chain[(int)TransformationComp.Rotation] != null)
                {
                    rotation = GetKeyframeList(chain[(int)TransformationComp.Rotation], start, stop);
                }
                else
                {
                    defRot = EulerToQuaternion(PropertyHelper.PropertyGet(props, "Lcl Rotation", new Vector3(0, 0, 0)), target.RotationOrder.Value);
                }

                var joined = new KeyFrameListList();
                joined.AddRange(scaling);
                joined.AddRange(translation);
                joined.AddRange(rotation);

                var times = GetKeyTimeList(joined);

                var outQuat = new AssimpSharp.QuatKey[times.Count];
                var outScale = new AssimpSharp.VectorKey[times.Count];
                var outTranslation = new AssimpSharp.VectorKey[times.Count];

                if (times.Count > 0)
                {
                    ConvertTransformOrder_TRStoSRT(outQuat, outScale, outTranslation,
                        scaling, translation, rotation, times, ref maxTime, ref minTime, target.RotationOrder.Value, defScale, defTranslate, defRot);
                }

                // XXX remove duplicates / redundant keys which this operation did
                // likely produce if not all three channels were equally dense.

                na.ScalingKeys = outScale;
                na.RotationKeys = outQuat;
                na.PositionKeys = outTranslation;
            }
            else
            {
                // if a particular transformation is not given, grab it from
                // the corresponding node to meet the semantics of aiNodeAnim,
                // which requires all of rotation, scaling and translation
                // to be set.

                if (chain[(int)TransformationComp.Scaling] != null)
                {
                    ConvertScaleKeys(na, chain[(int)TransformationComp.Scaling],
                        layerMap, start, stop, ref maxTime, ref minTime);
                }
                else
                {
                    na.ScalingKeys = new AssimpSharp.VectorKey[1];
                    na.ScalingKeys[0].Time = 0;
                    na.ScalingKeys[0].Value = PropertyHelper.PropertyGet(props, "Lcl Scaling", new Vector3(1, 1, 1));
                }
                if (chain[(int)TransformationComp.Rotation] != null)
                {
                    ConvertRotationKeys(na, chain[(int)TransformationComp.Rotation],
                        layerMap, start, stop, ref maxTime, ref minTime, target.RotationOrder.Value);
                }
                else
                {
                    na.RotationKeys = new AssimpSharp.QuatKey[1];
                    na.RotationKeys[0].Time = 0;
                    na.RotationKeys[0].Value = EulerToQuaternion(PropertyHelper.PropertyGet(props, "Lcl Rotation", new Vector3(0, 0, 0)), target.RotationOrder.Value);
                }
                if (chain[(int)TransformationComp.Translation] != null)
                {
                    ConvertTranslationKeys(na, chain[(int)TransformationComp.Translation],
                        layerMap, start, stop, ref maxTime, ref minTime);
                }
                else
                {
                    na.PositionKeys = new AssimpSharp.VectorKey[1];
                    na.PositionKeys[0].Time = 0;
                    na.PositionKeys[0].Value = PropertyHelper.PropertyGet(props, "Lcl Translation", new Vector3(0, 0, 0));
                }
            }

            return na;
        }
示例#11
0
        private AssimpSharp.NodeAnim GenerateRotationNodeAnim(string name, Model target, List<AnimationCurveNode> curves, LayerMap layerMap, long start, long stop, ref double maxTime, ref double minTime)
        {
            var na = new AssimpSharp.NodeAnim();
            na.NodeName = name;

            ConvertRotationKeys(na, curves, layerMap, start, stop, ref maxTime, ref minTime, target.RotationOrder.Value);

            // dummy scaling key
            na.ScalingKeys = new AssimpSharp.VectorKey[1];

            na.ScalingKeys[0].Time = 0;
            na.ScalingKeys[0].Value = new Vector3(1.0f, 1.0f, 1.0f);

            // dummy position key
            na.PositionKeys = new AssimpSharp.VectorKey[1];

            na.PositionKeys[0].Time = 0;
            na.PositionKeys[0].Value = new Vector3();

            return na;
        }
示例#12
0
 private Quaternion EulerToQuaternion(Vector3 rot, Model.RotOrder order)
 {
     Matrix m;
     GetRotationMatrix(order, rot, out m);
     return Quaternion.RotationMatrix(m);
 }
示例#13
0
        private void ConvertWeights(aiMesh result, Model model, MeshGeometry geo, Matrix nodeGlobalTransform, int materialIndex = FbxConverter.NO_MATERIAL_SEPARATION, int[] outputVertStartIndices = null)
        {
            Debug.Assert(geo.DeformerSkin != null);
            var outIndices = new List<int>();
            var indexOutIndices = new List<int>();
            var countOutIndices = new List<int>();

            var sk = geo.DeformerSkin;

            var bones = new List<aiBone>(sk.Clusters.Count);

            var noMatCheck = (materialIndex == FbxConverter.NO_MATERIAL_SEPARATION);
            Debug.Assert(noMatCheck || outputVertStartIndices != null);

            try
            {
                foreach (var cluster in sk.Clusters)
                {
                    Debug.Assert(cluster != null);

                    var indices = cluster.Indices;

                    if (indices.Count == 0)
                    {
                        continue;
                    }

                    var mats = geo.MaterialIndices;

                    var ok = false;

                    int noIndexSentine = int.MaxValue;

                    countOutIndices.Clear();
                    indexOutIndices.Clear();
                    outIndices.Clear();

                    foreach (var index in indices)
                    {
                        var outIdx = geo.ToOutputVertexIndex((uint)index);
                        var count = outIdx.Count;
                        // ToOutputVertexIndex only returns NULL if index is out of bounds
                        // which should never happen
                        Debug.Assert(outIdx.Count > 0);

                        indexOutIndices.Add(noIndexSentine);
                        countOutIndices.Add(0);

                        for (int i = 0; i < count; i++)
                        {
                            if (noMatCheck || mats[(int)geo.FaceForVertexIndex((uint)outIdx.Array[i+outIdx.Offset])] == materialIndex)
                            {
                                if (indexOutIndices[indexOutIndices.Count] == noIndexSentine)
                                {
                                    indexOutIndices[indexOutIndices.Count] = outIndices.Count;
                                }
                                if (noMatCheck)
                                {
                                    outIndices.Add((int)outIdx.Array[i+outIdx.Offset]);
                                }
                                else
                                {
                                    int it;
                                    for (it = 0; it < outputVertStartIndices.Length; it++)
                                    {
                                        if (outIdx.Array[i+outIdx.Offset] == outputVertStartIndices[it])
                                        {
                                            break;
                                        }
                                    }
                                    outIndices.Add(it);
                                }
                                countOutIndices[countOutIndices.Count] += 1;
                                ok = true;
                            }
                        }
                    }

                    // if we found at least one, generate the output bones
                    // XXX this could be heavily simplified by collecting the bone
                    // data in a single step.
                    if (ok)
                    {
                        ConvertCluster(bones, model, cluster, outIndices.ToArray(), indexOutIndices.ToArray(),
                            countOutIndices.ToArray(), nodeGlobalTransform);
                    }
                }
            }
            catch (Exception e)
            {
                bones.Clear();
                throw (e);
            }
            if (bones.Count == 0)
            {
                return;
            }

            result.Bones = bones.ToArray();
            result.NumBones = bones.Count;
        }
示例#14
0
 private void ConvertCameras(Model model)
 {
     var nodeAttrs = model.Attributes;
     foreach (var attr in nodeAttrs)
     {
         var camera = attr as Camera;
         if (camera != null)
         {
             ConvertCamera(model, camera);
         }
     }
 }
示例#15
0
        private AssimpSharp.NodeAnim GenerateTranslationNodeAnim(string name, Model target, List<AnimationCurveNode> curves, LayerMap layerMap,
            long start, long stop, double maxTime, double minTime, bool inverse = false)
        {
            var na = new AssimpSharp.NodeAnim();
            na.NodeName = name;

            ConvertRotationKeys(na, curves, layerMap, start, stop, ref maxTime, ref minTime, target.RotationOrder.Value);

            if (inverse)
            {
                for (int i = 0; i < na.PositionKeys.Length; i++)
                {
                    na.PositionKeys[i].Value *= -1.0f;
                }
            }

            // dummy scaling key
            na.ScalingKeys = new AssimpSharp.VectorKey[1];
            na.ScalingKeys[0].Time = 0;
            na.ScalingKeys[0].Value = new Vector3(1, 1, 1);

            // dummy rotation key
            na.RotationKeys = new AssimpSharp.QuatKey[1];
            na.RotationKeys[0].Time = 0;
            na.RotationKeys[0].Value = Quaternion.Identity;

            return na;
        }
示例#16
0
        private void ConvertCluster(List<aiBone> bones, Model model, Cluster cl, int[] outIndices, int[] indexOutIndices, int[] countOutIndices, Matrix nodeGlobalTransform)
        {
            var bone = new aiBone();
            bones.Add(bone);

            bone.Name = FixNodeName(cl.TargetNode.Name);

            bone.OffsetMatrix = cl.TransformLink;
            bone.OffsetMatrix.Invert();

            bone.OffsetMatrix = bone.OffsetMatrix * nodeGlobalTransform;

            bone.NumWeights = outIndices.Length;
            var cursor = bone.Weights = new aiVertexWeight[outIndices.Length];
            int cursor_index = 0;

            int noIndexSentinel = int.MaxValue;
            var weights = cl.Weights;

            int c = indexOutIndices.Length;
            for (int i = 0; i < c; i++)
            {
                int indexIndex = indexOutIndices[i];
                if (indexIndex == noIndexSentinel)
                {
                    continue;
                }
                int cc = countOutIndices[i];
                for (int j = 0; j < cc; j++)
                {
                    cursor[cursor_index].VertexId = outIndices[indexIndex + j];
                    cursor[cursor_index].Weight = weights[i];
                    j++;
                }
            }
        }
示例#17
0
        private void GetRotationMatrix(Model.RotOrder mode, Vector3 rotation, out Matrix result)
        {
            if (mode == Model.RotOrder.SphericXYZ)
            {
                FBXImporter.LogError("Unsupported RotationMode: SphericXYZ");
                result = new Matrix();
                return;
            }
            const float angleEpsilon = 1e-6f;
            result = Matrix.Identity;
            var isId = new bool[3] { true, true, true };
            var temp = new Matrix[3];
            if (Math.Abs(rotation.Z) > angleEpsilon)
            {
                Matrix.RotationZ(MathUtil.DegreesToRadians(rotation.Z), out temp[2]);
                isId[2] = false;
            }
            if (Math.Abs(rotation.Y) > angleEpsilon)
            {
                Matrix.RotationY(MathUtil.DegreesToRadians(rotation.Y), out temp[1]);
                isId[1] = false;
            }
            if (Math.Abs(rotation.X) > angleEpsilon)
            {
                Matrix.RotationX(MathUtil.DegreesToRadians(rotation.X), out temp[0]);
                isId[0] = false;
            }
            var order = new int[3] { -1, -1, -1 };
            switch (mode)
            {
                case Model.RotOrder.EulerXYZ:
                    order[0] = 2;
                    order[1] = 1;
                    order[2] = 0;
                    break;

                case Model.RotOrder.EulerXZY:
                    order[0] = 1;
                    order[1] = 2;
                    order[2] = 0;
                    break;

                case Model.RotOrder.EulerYZX:
                    order[0] = 0;
                    order[1] = 2;
                    order[2] = 1;
                    break;

                case Model.RotOrder.EulerYXZ:
                    order[0] = 2;
                    order[1] = 0;
                    order[2] = 1;
                    break;

                case Model.RotOrder.EulerZXY:
                    order[0] = 1;
                    order[1] = 0;
                    order[2] = 2;
                    break;

                case Model.RotOrder.EulerZYX:
                    order[0] = 0;
                    order[1] = 1;
                    order[2] = 2;
                    break;
                default:
                    Debug.Assert(false);
                    break;
            }

            Debug.Assert((order[0] >= 0) && (order[0] <= 2));
            Debug.Assert((order[1] >= 0) && (order[1] <= 2));
            Debug.Assert((order[2] >= 0) && (order[2] <= 2));
            if (!isId[order[0]])
            {
                result = temp[order[0]];
            }
            if (!isId[order[1]])
            {
                result = result * temp[order[1]];
            }
            if (!isId[order[2]])
            {
                result = result * temp[order[2]];
            }
        }
示例#18
0
 private void ConvertLights(Model model)
 {
     var nodeAttrs = model.Attributes;
     foreach (var attr in nodeAttrs)
     {
         var light = attr as Light;
         if (light != null)
         {
             ConvertLight(model, light);
         }
     }
 }
示例#19
0
        private void InterpolateKeys(AssimpSharp.QuatKey[] valOut, KeyTimeList keys, KeyFrameListList inputs,
            bool geom, ref double maxTime, ref double minTime, Model.RotOrder order)
        {
            Debug.Assert(keys.Count > 0);
            Debug.Assert(valOut != null);

            var temp = new AssimpSharp.VectorKey[keys.Count];
            InterpolateKeys(temp, keys, inputs, geom, ref maxTime, ref minTime);

            Matrix m;
            Quaternion lastq = Quaternion.Identity;
            for (int i = 0; i < keys.Count; i++)
            {
                valOut[i].Time = temp[i].Time;
                GetRotationMatrix(order, temp[i].Value, out m);
                var quat = Quaternion.RotationMatrix(m);
                if (Quaternion.Dot(quat, lastq) < 0)
                {
                    quat = -quat;
                }
                lastq = quat;
                valOut[i].Value = quat;
            }
        }
示例#20
0
        private int[] ConvertMesh(MeshGeometry mesh, Model model,
            Matrix nodeGlobalTransform)
        {
            List<int> temp;
            if (MeshesConverted.TryGetValue(mesh, out temp))
            {
                return temp.ToArray();
            }
            else
            {
                temp = new List<int>();
            }

            var vertices = mesh.Vertices;
            var faces = mesh.FaceIndexCounts;
            if (vertices.Count == 0 || faces.Count == 0)
            {
                Debug.WriteLine("ignore empty geometry: " + mesh.Name);
                return temp.ToArray();
            }

            var mindices = mesh.MaterialIndices;
            if (Doc.Settings.ReadMaterials && !(mindices.Count == 0))
            {
                var b = mindices[0];
                foreach (var index in mindices)
                {
                    if (index != b)
                    {
                        return ConvertMeshMultiMaterial(mesh, model, nodeGlobalTransform).ToArray();
                    }
                }
            }

            temp.Add(ConvertMeshSingleMaterial(mesh, model, nodeGlobalTransform));
            return temp.ToArray();
        }
示例#21
0
        private bool IsRedundantAnimationData(Model target, TransformationComp comp, List<AnimationCurveNode> curves)
        {
            Debug.Assert(curves.Count > 0);

            // look for animation nodes with
            //  * sub channels for all relevant components set
            //  * one key/value pair per component
            //  * combined values match up the corresponding value in the bind pose node transformation
            // only such nodes are 'redundant' for this function.

            if (curves.Count > 1)
            {
                return false;
            }

            var nd = curves[0];
            var subCurves = nd.Curves;

            AnimationCurve dx;
            AnimationCurve dy;
            AnimationCurve dz;

            subCurves.TryGetValue("d|X", out dx);
            subCurves.TryGetValue("d|Y", out dy);
            subCurves.TryGetValue("d|Z", out dz);

            if (dx == null || dy == null || dz == null)
            {
                return false;
            }

            var vx = dx.Values;
            var vy = dy.Values;
            var vz = dz.Values;

            if (vx.Count != 1 || vy.Count != 1 || vz.Count != 1)
            {
                return false;
            }

            var dynVal = new Vector3(vx[0], vy[0], vz[0]);
            var staticVal = PropertyHelper.PropertyGet<Vector3>(target.Props,
                NameTransformationCompProperty(comp),
                TransformationCompDefaultValue(comp));

            const float epsilon = 1e-6f;
            return (dynVal - staticVal).LengthSquared() < epsilon;
        }
示例#22
0
        private int ConvertMeshMultiMaterial(MeshGeometry mesh, Model model, int index, Matrix nodeGlobalTransform)
        {
            var outMesh = SetupEmptyMesh(mesh);
            var mindices = mesh.MaterialIndices;
            var vertices = mesh.Vertices;
            var faces = mesh.FaceIndexCounts;
            var processWeights = Doc.Settings.ReadWeights && (mesh.DeformerSkin != null);

            int countFaces = 0;
            int countVertices = 0;

            // count faces
            var itf = faces.GetEnumerator();
            foreach(var it in mindices)
            {
                itf.MoveNext();
                if (it != index)
                {
                    continue;
                }
                ++countFaces;
                countVertices += (int)itf.Current;
            }

            Debug.Assert(countFaces > 0);
            Debug.Assert(countVertices > 0);

            // mapping from output indices to DOM indexing, needed to resolve weights
            var reverseMappigng = new int[0];
            if (processWeights)
            {
                reverseMappigng = new int[countVertices];
            }

            // allocate output data arrays, but don't fill them yet
            outMesh.Vertices = new Vector3[countVertices];
            var fac = outMesh.Faces = new AssimpSharp.Face[countFaces];

            // allocate normals
            var normals = mesh.Normals;
            if (normals.Count > 0)
            {
                Debug.Assert(normals.Count == vertices.Count);
                outMesh.Normals = new Vector3[vertices.Count];
            }

            // allocate tangents, binormals.
            var tangets = mesh.Tangents;
            var binormals = mesh.Binormals;
            if (tangets.Count > 0)
            {
                Vector3[] tempBinormals = new Vector3[0];
                if (binormals.Count == 0)
                {
                    if (normals.Count > 0)
                    {
                        // XXX this computes the binormals for the entire mesh, not only
                        // the part for which we need them.
                        tempBinormals = new Vector3[normals.Count];
                        for (int i = 0; i < tangets.Count; i++)
                        {
                            tempBinormals[i] = Vector3.Cross(normals[i], tangets[i]);
                        }
                        binormals.Clear();
                        for (int i = 0; i < tempBinormals.Length; i++)
                        {
                            binormals.Add(tempBinormals[i]);
                        }
                    }
                    else
                    {
                        binormals = null;
                    }
                }

                if (binormals.Count > 0)
                {
                    Debug.Assert(tangets.Count == vertices.Count);
                    Debug.Assert(binormals.Count == vertices.Count);

                    outMesh.Tangents = new Vector3[vertices.Count];
                    outMesh.Bitangents = new Vector3[vertices.Count];
                }
            }

            // allocate texture coords
            int numUvs = 0;
            for (int i = 0; i < AssimpSharp.Mesh.AI_MAX_NUMBER_OF_TEXTURECOORDS; i++, numUvs++)
            {
                var uvs = mesh.GetTextureCoords(i);
                if (uvs.Count == 0)
                {
                    break;
                }
                outMesh.TextureCoords[i] = new Vector3[vertices.Count];
                outMesh.NumUVComponents[i] = 2;
            }

            // allocate vertex colors
            int numVcs = 0;
            for (int i = 0; i < AssimpSharp.Mesh.AI_MAX_NUMBER_OF_COLOR_SETS; i++, numVcs++)
            {
                var colors = mesh.GetVertexColors(i);
                if (colors.Count == 0)
                {
                    break;
                }
                outMesh.Colors[i] = new Color4[vertices.Count];
            }

            int cursor = 0;
            int inCursor = 0;

            int facesIndex = 0;
            int facIndex = 0;
            foreach (var it in mindices)
            {
                int pcount = (int)faces[facesIndex];
                if (it != index)
                {
                    inCursor += pcount;
                    continue;
                }

                var f = fac[facIndex++] = new Face();
                f.Indices = new int[pcount];
                switch (pcount)
                {
                    case 1:
                        outMesh.PrimitiveTypes |= AssimpSharp.PrimitiveType.Point;
                        break;
                    case 2:
                        outMesh.PrimitiveTypes |= AssimpSharp.PrimitiveType.Line;
                        break;
                    case 3:
                        outMesh.PrimitiveTypes |= AssimpSharp.PrimitiveType.Triangle;
                        break;
                    default:
                        outMesh.PrimitiveTypes |= AssimpSharp.PrimitiveType.Polygon;
                        break;
                }
                for (int i = 0; i < pcount; ++i, ++cursor, ++inCursor)
                {
                    f.Indices[i] = cursor;
                    if (reverseMappigng.Length > 0)
                    {
                        reverseMappigng[cursor] = inCursor;
                    }
                    outMesh.Vertices[cursor] = vertices[inCursor];
                    if (outMesh.Normals.Length > 0)
                    {
                        outMesh.Normals[cursor] = normals[inCursor];
                    }
                    if (outMesh.Tangents.Length > 0)
                    {
                        outMesh.Tangents[cursor] = tangets[inCursor];
                        outMesh.Bitangents[cursor] = binormals[inCursor];
                    }
                    for (int j = 0; j < numUvs; j++)
                    {
                        var uvs = mesh.GetTextureCoords(j);
                        outMesh.TextureCoords[j][cursor] = new Vector3(uvs[inCursor], 0.0f);
                    }
                    for (int j = 0; j < numVcs; j++)
                    {
                        var cols = mesh.GetVertexColors(j);
                        outMesh.Colors[j][cursor] = cols[inCursor];
                    }
                }
            }

            ConvertMaterialForMesh(outMesh, model, mesh, index);

            if (processWeights)
            {
                ConvertWeights(outMesh, model, mesh, nodeGlobalTransform, index, reverseMappigng);
            }
            return Meshes.Count - 1;
        }
示例#23
0
 private bool NeedsComplexTransformationChain(Model model)
 {
     var props = model.Props;
     var zeroEpsilon = 1e-6f;
     bool ok = false;
     foreach (var i in Enum.GetValues(typeof(TransformationComp)))
     {
         var comp = (TransformationComp)i;
         if (comp == TransformationComp.Rotation || comp == TransformationComp.Scaling || comp == TransformationComp.Translation ||
         comp == TransformationComp.GeometricScaling || comp == TransformationComp.GeometricRotation || comp == TransformationComp.GeometricTranslation)
         {
             continue;
         }
         Vector3 v = PropertyHelper.PropertyGet<Vector3>(props, NameTransformationCompProperty(comp), out ok);
         if (ok && v.LengthSquared() > zeroEpsilon)
         {
             return true;
         }
     }
     return false;
 }
示例#24
0
        private void ConvertModel(Model model, aiNode nd, Matrix nodeGlobalTransform)
        {
            var geos = model.Geometry;

            var meshes = new List<int>(geos.Count);
            foreach (var geo in geos)
            {
                var mesh = geo as MeshGeometry;
                if (mesh != null)
                {
                    var indices = ConvertMesh(mesh, model, nodeGlobalTransform);
                    meshes.AddRange(indices);
                }
                else
                {
                    Debug.WriteLine("ignoring unrecognized geometry: " + geo.Name);
                }
            }
            if (meshes.Count > 0)
            {
                nd.Meshes.AddRange(meshes);
            }
        }
示例#25
0
 private void ConvertRotationKeys(AssimpSharp.NodeAnim na, List<AnimationCurveNode> nodes, LayerMap layers,
     long start, long stop, ref double maxTime, ref double minTime, Model.RotOrder order)
 {
     Debug.Assert(nodes.Count > 0);
     var inputs = GetKeyframeList(nodes, start, stop);
     var keys = GetKeyTimeList(inputs);
     na.RotationKeys = new AssimpSharp.QuatKey[keys.Count];
     InterpolateKeys(na.RotationKeys, keys, inputs, false, ref maxTime, ref minTime, order);
 }