Beispiel #1
0
        private AABB_s GetAABB2(YmapEntityDef ent)
        {
            var arch   = ent.Archetype;
            var ori    = ent.Orientation;
            var pos    = ent.Position;
            var sca    = ent.Scale;
            var mat    = Matrix.Transformation(Vector3.Zero, Quaternion.Identity, sca, Vector3.Zero, ori, pos);
            var matabs = mat;

            matabs.Column1 = mat.Column1.Abs();
            matabs.Column2 = mat.Column2.Abs();
            matabs.Column3 = mat.Column3.Abs();
            matabs.Column4 = mat.Column4.Abs();
            Vector3 bbmin = pos - ent.BSRadius; //sphere
            Vector3 bbmax = pos + ent.BSRadius;

            if (arch != null)
            {
                var bbcenter = (arch.BBMax + arch.BBMin) * 0.5f;
                var bbextent = (arch.BBMax - arch.BBMin) * 0.5f;
                var ncenter  = Vector3.TransformCoordinate(bbcenter, mat);
                var nextent  = Vector3.TransformNormal(bbextent, matabs);
                bbmin = ncenter - nextent;
                bbmax = ncenter + nextent;
            }
            AABB_s b = new AABB_s();

            b.Min = new Vector4(bbmin, 0f);
            b.Max = new Vector4(bbmax, 0f);
            return(b);
        }
Beispiel #2
0
        private AABB_s GetAABB(YmapEntityDef ent)
        {
            var     arch  = ent.Archetype;
            var     ori   = ent.Orientation;
            Vector3 bbmin = ent.Position - ent.BSRadius; //sphere
            Vector3 bbmax = ent.Position + ent.BSRadius;

            if (arch != null)
            {
                Vector3[] c     = new Vector3[8];
                Vector3   abmin = arch.BBMin * ent.Scale; //entity box
                Vector3   abmax = arch.BBMax * ent.Scale;
                c[0]  = abmin;
                c[1]  = new Vector3(abmin.X, abmin.Y, abmax.Z);
                c[2]  = new Vector3(abmin.X, abmax.Y, abmin.Z);
                c[3]  = new Vector3(abmin.X, abmax.Y, abmax.Z);
                c[4]  = new Vector3(abmax.X, abmin.Y, abmin.Z);
                c[5]  = new Vector3(abmax.X, abmin.Y, abmax.Z);
                c[6]  = new Vector3(abmax.X, abmax.Y, abmin.Z);
                c[7]  = abmax;
                bbmin = new Vector3(float.MaxValue);
                bbmax = new Vector3(float.MinValue);
                for (int j = 0; j < 8; j++)
                {
                    Vector3 corn = ori.Multiply(c[j]) + ent.Position;
                    bbmin = Vector3.Min(bbmin, corn);
                    bbmax = Vector3.Max(bbmax, corn);
                }
            }
            AABB_s b = new AABB_s();

            b.Min = new Vector4(bbmin, 0f);
            b.Max = new Vector4(bbmax, 0f);
            return(b);
        }
Beispiel #3
0
        private DrawableGeometry TryConvertGeometry(List <FbxPolygon> fPolys, FbxNode matNode, out AABB_s aabb)
        {
            aabb = new AABB_s();

            if (matNode == null)
            {
                return(null);
            }
            if (fPolys == null)
            {
                return(null);
            }
            if (fPolys.Count == 0)
            {
                return(null);
            }


            var dShader   = TryConvertMaterial(matNode);
            var dVertDecl = GetVertexDeclaration(dShader);

            var vDict = new Dictionary <FbxVertex, ushort>();
            var vList = new List <FbxVertex>();
            var iList = new List <ushort>();

            foreach (var fPoly in fPolys)
            {
                if (fPoly.Vertices == null)
                {
                    continue;
                }
                if (vList.Count >= 65535)
                {
                    break;     //too many vertices in this geometry!!
                }
                ushort i0 = 0; //first generated index
                ushort iP = 0; //previous generated index
                ushort iN = 0; //current index
                for (int v = 0; v < fPoly.Vertices.Length; v++)
                {
                    var vert = fPoly.Vertices[v];
                    vert.GenVertexBytes(dVertDecl);

                    if (!vDict.TryGetValue(vert, out iN))
                    {
                        iN          = (ushort)vList.Count;
                        vDict[vert] = iN;
                        vList.Add(vert);
                    }
                    else
                    {
                    }  //found identical vertex, use its index
                    if (v == 0)
                    {
                        i0 = iN;
                    }
                    if (v < 3) //first triangle
                    {
                        iList.Add(iN);
                    }
                    else //for each extra vertex, make triangle from v0, vN-1, vN - assumes convex polygon!!
                    {
                        iList.Add(i0);
                        iList.Add(iP);
                        iList.Add(iN);
                    }
                    iP = iN;
                }
            }


            var vStride = dVertDecl.Stride;
            var vBytes  = new byte[vList.Count * vStride];

            for (int i = 0; i < vList.Count; i++)
            {
                var v = vList[i].Bytes;
                var o = i * vStride;
                for (int j = 0; j < vStride; j++)
                {
                    vBytes[o + j] = v[j];
                }
            }

            if (vList.Count > 0)
            {
                aabb.Min = new Vector4(float.MaxValue);
                aabb.Max = new Vector4(float.MinValue);
                foreach (var vert in vList)
                {
                    var v = new Vector4(vert.Position, vert.Position.X);
                    aabb.Min = Vector4.Min(aabb.Min, v);
                    aabb.Max = Vector4.Max(aabb.Max, v);
                }
            }


            var vData = new VertexData();

            vData.Info         = dVertDecl;
            vData.VertexType   = (VertexType)dVertDecl.Flags;
            vData.VertexStride = dVertDecl.Stride;
            vData.VertexCount  = vList.Count;
            vData.VertexBytes  = vBytes;

            var vBuff = new VertexBuffer();

            vBuff.Data1        = vData;
            vBuff.Data2        = vData;
            vBuff.Info         = dVertDecl;
            vBuff.VertexCount  = (uint)vList.Count;
            vBuff.VertexStride = vStride;
            vBuff.VFT          = 1080153064;//is this needed?
            vBuff.Unknown_4h   = 1;

            var iBuff = new IndexBuffer();

            iBuff.IndicesCount = (uint)iList.Count;
            iBuff.Indices      = iList.ToArray();
            iBuff.VFT          = 1080111576;//is this needed?
            iBuff.Unknown_4h   = 1;


            var dGeom = new DrawableGeometry();

            dGeom.Shader         = dShader;
            dGeom.VertexData     = vData;
            dGeom.VertexBuffer   = vBuff;
            dGeom.IndexBuffer    = iBuff;
            dGeom.VFT            = 1080133736;//is this needed?
            dGeom.Unknown_4h     = 1;
            dGeom.IndicesCount   = (uint)iList.Count;
            dGeom.TrianglesCount = (uint)iList.Count / 3;
            dGeom.VerticesCount  = (ushort)vList.Count;
            dGeom.Unknown_62h    = 3; //indices per triangle..?
            dGeom.VertexStride   = vStride;
            dGeom.BoneIdsCount   = 0; //todo: bones


            return(dGeom);
        }
Beispiel #4
0
        private FbxModel TryConvertModel(FbxNode mnode)
        {
            FbxNode geonode  = null;
            var     matnodes = new List <FbxNode>();

            foreach (var cnode in mnode.Connections)
            {
                if (cnode == null)
                {
                    continue;
                }
                switch (cnode.Name)
                {
                case "Geometry":
                    geonode = cnode;
                    break;

                case "Material":
                    matnodes.Add(cnode);
                    break;
                }
            }

            if (geonode == null)
            {
                return(null);
            }
            if (matnodes.Count == 0)
            {
                return(null);                                 //need atleast one material...
            }
            var fnEdges   = geonode["Edges"]?.Value as int[]; //do we need this? maybe for collision/navmesh
            var fnVerts   = geonode["Vertices"]?.Value as double[];
            var fnIndices = geonode["PolygonVertexIndex"]?.Value as int[];

            if ((fnVerts == null) || (fnIndices == null))
            {
                return(null);
            }                //no mesh data.. abort!

            var fnNormals   = new List <FbxNode>();
            var fnBinormals = new List <FbxNode>();
            var fnTangents  = new List <FbxNode>();
            var fnTexcoords = new List <FbxNode>();
            var fnColours   = new List <FbxNode>();
            var fnMaterials = new List <FbxNode>();

            foreach (var cnode in geonode.Nodes)
            {
                if (cnode == null)
                {
                    continue;
                }
                switch (cnode.Name)
                {
                case "LayerElementNormal": fnNormals.Add(cnode); break;

                case "LayerElementBinormal": fnBinormals.Add(cnode); break;

                case "LayerElementTangent": fnTangents.Add(cnode); break;

                case "LayerElementUV": fnTexcoords.Add(cnode); break;

                case "LayerElementColor": fnColours.Add(cnode); break;

                case "LayerElementMaterial": fnMaterials.Add(cnode); break;

                case "LayerElementSmoothing": break; //ignore currently

                case "Layer": break;                 //ignore- merge all layers data instead
                }
            }

            var nNormals   = fnNormals.Count;
            var nBinormals = fnBinormals.Count;
            var nTangents  = fnTangents.Count;
            var nTexcoords = fnTexcoords.Count;
            var nColours   = fnColours.Count;
            var nMaterials = fnMaterials.Count;

            var fPolys      = new List <FbxPolygon>();
            var fPolyVerts  = new List <FbxVertex>();
            var fPolysByMat = new List <FbxPolygon> [matnodes.Count];

            foreach (var fnIndex in fnIndices) //build the polygons.
            {
                var pVert = new FbxVertex();
                pVert.Position  = GetVector3FromDoubleArray(fnVerts, (fnIndex < 0) ? (-fnIndex - 1) : fnIndex);
                pVert.Normals   = nNormals > 0 ? new Vector3[nNormals] : null;
                pVert.Binormals = nBinormals > 0 ? new Vector3[nBinormals] : null;
                pVert.Tangents  = nTangents > 0 ? new Vector3[nTangents] : null;
                pVert.Texcoords = nTexcoords > 0 ? new Vector2[nTexcoords] : null;
                pVert.Colours   = nColours > 0 ? new Vector4[nColours] : null;
                fPolyVerts.Add(pVert);
                if (fnIndex < 0) //yeah because negative index means end of polygon...
                {
                    var fPoly = new FbxPolygon();
                    fPoly.Vertices  = fPolyVerts.ToArray();
                    fPoly.Materials = nMaterials > 0 ? new FbxNode[nMaterials] : null;
                    fPolyVerts.Clear();
                    fPolys.Add(fPoly);
                    if (fPoly.Vertices.Length > 3)
                    {
                    }   //more than 3 vertices in this poly! will need to split it into triangles!! but do it later since all poly verts are needed for next steps
                }
            }

            for (int i = 0; i < nNormals; i++)
            {
                var fnNorms = fnNormals[i];
                var arNorms = fnNorms["Normals"]?.Value as double[];
                var aiNorms = fnNorms["NormalIndex"]?.Value as int[];
                if (!IsByPolygonVertexMapType(fnNorms))
                {
                    continue;
                }
                var indexed = IsIndexToDirectRefType(fnNorms);
                if (indexed && (aiNorms == null))
                {
                    continue;
                }             //need the index array if it's IndexToDirect!
                int j = 0;
                foreach (var fPoly in fPolys)
                {
                    foreach (var fVert in fPoly.Vertices)
                    {
                        var ai = indexed ? aiNorms[j] : j;
                        fVert.Normals[i] = GetVector3FromDoubleArray(arNorms, ai);
                        j++;
                    }
                }
            }
            for (int i = 0; i < nBinormals; i++)
            {
                var fnBinorms = fnBinormals[i];
                var arBinorms = fnBinorms["Binormals"]?.Value as double[];
                var aiBinorms = fnBinorms["BinormalIndex"]?.Value as int[];
                if (!IsByPolygonVertexMapType(fnBinorms))
                {
                    continue;
                }
                var indexed = IsIndexToDirectRefType(fnBinorms);
                if (indexed && (aiBinorms == null))
                {
                    continue;
                }             //need the index array if it's IndexToDirect!
                int j = 0;
                foreach (var fPoly in fPolys)
                {
                    foreach (var fVert in fPoly.Vertices)
                    {
                        var ai = indexed ? aiBinorms[j] : j;
                        fVert.Binormals[i] = GetVector3FromDoubleArray(arBinorms, ai);
                        j++;
                    }
                }
            }
            for (int i = 0; i < nTangents; i++)
            {
                var fnTangs = fnTangents[i];
                var arTangs = fnTangs["Tangents"]?.Value as double[];
                var aiTangs = fnTangs["TangentIndex"]?.Value as int[];
                if (!IsByPolygonVertexMapType(fnTangs))
                {
                    continue;
                }
                var indexed = IsIndexToDirectRefType(fnTangs);
                if (indexed && (aiTangs == null))
                {
                    continue;
                }             //need the index array if it's IndexToDirect!
                int j = 0;
                foreach (var fPoly in fPolys)
                {
                    foreach (var fVert in fPoly.Vertices)
                    {
                        var ai = indexed ? aiTangs[j] : j;
                        fVert.Tangents[i] = GetVector3FromDoubleArray(arTangs, ai);
                        j++;
                    }
                }
            }
            for (int i = 0; i < nTexcoords; i++)
            {
                var fnTexcs = fnTexcoords[i];
                var arTexcs = fnTexcs["UV"]?.Value as double[];
                var aiTexcs = fnTexcs["UVIndex"]?.Value as int[];
                if (!IsByPolygonVertexMapType(fnTexcs))
                {
                    continue;
                }
                var indexed = IsIndexToDirectRefType(fnTexcs);
                if (indexed && (aiTexcs == null))
                {
                    continue;
                }             //need the index array if it's IndexToDirect!
                int j = 0;
                foreach (var fPoly in fPolys)
                {
                    foreach (var fVert in fPoly.Vertices)
                    {
                        var ai = indexed ? aiTexcs[j] : j;
                        var tc = GetVector2FromDoubleArray(arTexcs, ai);
                        fVert.Texcoords[i] = InvertTexcoordV ? new Vector2(tc.X, -tc.Y) : tc;//whyyyy
                        j++;
                    }
                }
            }
            for (int i = 0; i < nColours; i++)
            {
                var fnCols = fnColours[i];
                var arCols = fnCols["Colors"]?.Value as double[];
                var aiCols = fnCols["ColorIndex"]?.Value as int[];
                if (!IsByPolygonVertexMapType(fnCols))
                {
                    continue;
                }
                var indexed = IsIndexToDirectRefType(fnCols);
                if (indexed && (aiCols == null))
                {
                    continue;
                }             //need the index array if it's IndexToDirect!
                int j = 0;
                foreach (var fPoly in fPolys)
                {
                    foreach (var fVert in fPoly.Vertices)
                    {
                        var ai = indexed ? aiCols[j] : j;
                        fVert.Colours[i] = GetVector4FromDoubleArray(arCols, ai);
                        j++;
                    }
                }
            }
            for (int i = 0; i < nMaterials; i++)
            {
                var fnMats  = fnMaterials[i];
                var arMats  = fnMats["Materials"]?.Value as int[];
                var mapType = fnMats["MappingInformationType"]?.Value as string;
                var refType = fnMats["ReferenceInformationType"]?.Value as string;
                var allSame = false;
                switch (mapType)
                {
                case "ByPolygon": break;

                case "AllSame": allSame = true; break;

                default:
                    continue;
                }
                switch (refType)
                {
                case "IndexToDirect": break;

                default:
                    continue;
                }
                for (int j = 0; j < fPolys.Count; j++)
                {
                    var fPoly = fPolys[j];
                    var iMat  = allSame ? arMats[0] : arMats[j];
                    fPoly.Materials[i] = matnodes[iMat];

                    //group all the polygons by material...
                    var matPolys = fPolysByMat[iMat];
                    if (matPolys == null)
                    {
                        matPolys          = new List <FbxPolygon>();
                        fPolysByMat[iMat] = matPolys;
                    }
                    matPolys.Add(fPoly);
                }
            }



            var dModel = new DrawableModel();

            var dGeoms     = new List <DrawableGeometry>();
            var dGeomAABBs = new List <AABB_s>();
            var dModelAABB = new AABB_s();

            for (int i = 0; i < fPolysByMat.Length; i++)
            {
                AABB_s dGeomAABB;
                var    dGeom = TryConvertGeometry(fPolysByMat[i], matnodes[i], out dGeomAABB);
                if (dGeom != null)
                {
                    dGeoms.Add(dGeom);
                    dGeomAABBs.Add(dGeomAABB);
                }
            }
            if (dGeomAABBs.Count > 1)//need to include whole model AABB first, if more than one geometry..
            {
                var dGeomAABBs2 = new List <AABB_s>();
                dModelAABB.Min = new Vector4(float.MaxValue);
                dModelAABB.Max = new Vector4(float.MinValue);
                foreach (var aabb in dGeomAABBs)
                {
                    dModelAABB.Min = Vector4.Min(dModelAABB.Min, aabb.Min);
                    dModelAABB.Max = Vector4.Max(dModelAABB.Max, aabb.Max);
                }
                dGeomAABBs2.Add(dModelAABB);
                dGeomAABBs2.AddRange(dGeomAABBs);
                dGeomAABBs = dGeomAABBs2;
            }


            dModel.VFT              = 1080101496; //is this needed?
            dModel.Unknown_4h       = 1;
            dModel.RenderMaskFlags  = 0x00FF;     //GIMS "Mask"
            dModel.Geometries       = dGeoms.ToArray();
            dModel.GeometriesCount1 = (ushort)dGeoms.Count;
            dModel.GeometriesCount2 = (ushort)dGeoms.Count;
            dModel.GeometriesCount3 = (ushort)dGeoms.Count;
            dModel.BoundsData       = dGeomAABBs.ToArray();
            //shader mappings array will be added when adding models to drawable.



            var fModel = new FbxModel();

            fModel.Name  = (mnode.Properties.Count > 1) ? (mnode.Properties[1] as string)?.Replace("Model::", "") : null;
            fModel.Node  = mnode;
            fModel.Model = dModel;

            return(fModel);
        }