Example #1
0
    /// <summary>
    /// Method for checking if element can be assigned as flat - checking surface area ratio
    /// </summary>
    /// <param name="element"></param>
    /// <returns></returns>
    private bool CheckIfElementIsFlat(GameObject element)
    {
        Vector3      size        = GetSizeOfGameObject(element);
        ModelSurface mainSurface = GetMainSurfaceOfGameObject(element);

        float mainSurfaceArea = 0.0f;
        float auxSurfaceArea0 = 0.0f;
        float auxSurfaceArea1 = 0.0f;

        if (mainSurface == ModelSurface.XY)
        {
            mainSurfaceArea = Math.Abs(size.x * size.y);
            auxSurfaceArea0 = Math.Abs(size.z * size.y);
            auxSurfaceArea1 = Math.Abs(size.z * size.x);
        }
        else if (mainSurface == ModelSurface.XZ)
        {
            mainSurfaceArea = Math.Abs(size.x * size.z);
            auxSurfaceArea0 = Math.Abs(size.y * size.z);
            auxSurfaceArea1 = Math.Abs(size.y * size.x);
        }
        else if (mainSurface == ModelSurface.YZ)
        {
            mainSurfaceArea = Math.Abs(size.y * size.z);
            auxSurfaceArea0 = Math.Abs(size.x * size.y);
            auxSurfaceArea1 = Math.Abs(size.x * size.z);
        }
        else
        {
            return(false);
        }

        //If main surface area is 0 return false;
        if (mainSurfaceArea == 0)
        {
            return(false);
        }

        //Checking first aux surface area
        if (auxSurfaceArea0 / mainSurfaceArea > MinFlatSurfaceRatio)
        {
            return(false);
        }

        //Checking second aux surface area
        if (auxSurfaceArea1 / mainSurfaceArea > MinFlatSurfaceRatio)
        {
            return(false);
        }

        //Main surface is big enough - element is flat
        return(true);
    }
Example #2
0
        // used for initial loads, reloadModel, and reloading the data of purged models Upon exit, the model will absolutely be valid, but possibly as a default model
        public override void LoadModel()
        {
            int   version, i, num;
            Lexer parser = new(LEXFL.ALLOWPATHNAMES | LEXFL.NOSTRINGESCAPECHARS);

            if (!purged)
            {
                PurgeModel();
            }
            purged = false;

            if (!parser.LoadFile(name))
            {
                MakeDefaultModel(); return;
            }

            parser.ExpectTokenString(ModelX.MD5_VERSION_STRING); version = parser.ParseInt();
            if (version != ModelX.MD5_VERSION)
            {
                parser.Error($"Invalid version {version}.  Should be version {ModelX.MD5_VERSION}\n");
            }

            // skip commandline
            parser.ExpectTokenString("commandline"); parser.ReadToken(out var token);

            // parse num joints
            parser.ExpectTokenString("numJoints"); num = parser.ParseInt();
            joints      = new MD5Joint[num];
            defaultPose = new JointQuat[num];
            var poseMat3 = stackalloc JointMat[num + JointMat.ALLOC16]; poseMat3 = _alloca16T(poseMat3);

            // parse num meshes
            parser.ExpectTokenString("numMeshes"); num = parser.ParseInt();
            if (num < 0)
            {
                parser.Error($"Invalid size: {num}");
            }
            meshes = new MD5Mesh[num];

            // parse joints
            parser.ExpectTokenString("joints"); parser.ExpectTokenString("{");

            for (i = 0; i < joints.Length; i++)
            {
                var pose  = defaultPose[i];
                var joint = joints[i];
                ParseJoint(parser, joint, pose);
                poseMat3[i].SetRotation(pose.q.ToMat3());
                poseMat3[i].SetTranslation(pose.t);
                if (joint.parent != null)
                {
                    var parentNum = joint.parent - joints;
                    pose.q = (poseMat3[i].ToMat3() * poseMat3[parentNum].ToMat3().Transpose()).ToQuat();
                    pose.t = (poseMat3[i].ToVec3() - poseMat3[parentNum].ToVec3()) * poseMat3[parentNum].ToMat3().Transpose();
                }
            }
            parser.ExpectTokenString("}");

            //-----------------------------------------
            // create the inverse of the base pose joints to support tech6 style deformation of base pose vertexes, normals, and tangents.
            //
            // vertex * joints * inverseJoints == vertex when joints is the base pose When the joints are in another pose, it gives the animated vertex position
            //-----------------------------------------
            invertedDefaultPose = new JointMat[RenderWorldX.SIMD_ROUND_JOINTS(joints.Length)];
            for (i = 0; i < joints.Length; i++)
            {
                invertedDefaultPose[i] = poseMat3[i];
                invertedDefaultPose[i].Invert();
            }
            RenderWorldX.SIMD_INIT_LAST_JOINT(invertedDefaultPose, joints.Length);

            for (i = 0; i < meshes.Length; i++)
            {
                var isPDAmesh = false;
                parser.ExpectTokenString("mesh"); meshes[i].ParseMesh(parser, defaultPose.Length, poseMat3);

                // Koz begin: Remove hands from weapon & pda viewmodels if desired.
                var materialName = meshes[i].shader.Name;
                if (string.IsNullOrEmpty(materialName))
                {
                    meshes[i].shader = null;
                }
                // change material to _pdaImage instead of deault this allows rendering the PDA & swf menus to the model ingame. if we find this gui, we also need to add a surface to the model, so flag.
                else if (materialName == "textures/common/pda_gui" || materialName == "_pdaImage" || materialName == "_pdaimage")
                {
                    meshes[i].shader = declManager.FindMaterial("_pdaImage"); isPDAmesh = true;
                }

                if (isPDAmesh)
                {
                    common.Printf("Load pda model\n");
                    for (var ti = 0; ti < meshes[i].NumVerts; ti++)
                    {
                        common.Printf($"Numverts {meshes[i].NumVerts} Vert {ti} {meshes[i].deformInfo.verts[ti].xyz.x} {meshes[i].deformInfo.verts[ti].xyz.y} {meshes[i].deformInfo.verts[ti].xyz.z} : {meshes[i].deformInfo.verts[ti].TexCoordS} {meshes[i].deformInfo.verts[ti].TexCoordT} {meshes[i].deformInfo.verts[ti].st[0]} {meshes[i].deformInfo.verts[ti].st[1]}\n");
                    }
                    common.Printf("PDA gui found, creating gui surface for hitscan.\n");

                    var pdasurface = new ModelSurface {
                        id = 0, shader = declManager.FindMaterial("_pdaImage")
                    };
                    var pdageometry = AllocSurfaceTriangles(meshes[i].NumVerts, meshes[i].deformInfo.numIndexes);
                    Debug.Assert(pdageometry != null);

                    // infinite bounds
                    pdageometry.bounds[0].x = pdageometry.bounds[0].y = pdageometry.bounds[0].z = -99999;
                    pdageometry.bounds[1].x = pdageometry.bounds[1].y = pdageometry.bounds[1].z = 99999;
                    pdageometry.numVerts    = meshes[i].NumVerts;
                    pdageometry.numIndexes  = meshes[i].deformInfo.numIndexes;

                    for (var zz = 0; zz < pdageometry.numIndexes; zz++)
                    {
                        pdageometry.indexes[zz] = meshes[i].deformInfo.indexes[zz];
                    }
                    for (var zz = 0; zz < pdageometry.numVerts; zz++)
                    {
                        pdageometry.verts[zz].xyz = meshes[i].deformInfo.verts[zz].xyz;
                        //pdageometry.verts[zz].SetTexCoord( meshes[i].deformInfo.verts[zz].GetTexCoord() );
                        pdageometry.verts[zz].st = meshes[i].deformInfo.verts[zz].st;
                    }

                    common.Printf("verify pda model\n");
                    for (var ti = 0; ti < pdageometry.numVerts; ti++)
                    {
                        common.Printf($"Numverts {pdageometry.numVerts} Vert {ti} {pdageometry.verts[ti].xyz.x} {pdageometry.verts[ti].xyz.y} {pdageometry.verts[ti].xyz.z} : {pdageometry.verts[ti].TexCoordS} {pdageometry.verts[ti].TexCoordT} {pdageometry.verts[ti].st[0]} {pdageometry.verts[ti].st[1]}\n");
                    }
                    pdasurface.geometry = pdageometry;
                    AddSurface(pdasurface);
                }
            }

            // calculate the bounds of the model
            CalculateBounds(poseMat3);

            // set the timestamp for reloadmodels
            fileSystem.ReadFile(name, out var timeStamp);
        }
Example #3
0
        public void UpdateSurface(RenderEntity ent, JointMat[] joints, ModelSurface surf)
        {
            int i;

            tr.pc.c_deformedSurfaces++;
            tr.pc.c_deformedVerts   += deformInfo.numOutputVerts;
            tr.pc.c_deformedIndexes += deformInfo.numIndexes;

            surf.shader = shader;

            if (surf.geometry != null)
            {
                // if the number of verts and indexes are the same we can re-use the triangle surface the number of indexes must be the same to assure the correct amount of memory is allocated for the facePlanes
                if (surf.geometry.numVerts == deformInfo.numOutputVerts && surf.geometry.numIndexes == deformInfo.numIndexes)
                {
                    R_FreeStaticTriSurfVertexCaches(surf.geometry);
                }
                else
                {
                    R_FreeStaticTriSurf(surf.geometry); surf.geometry = R_AllocStaticTriSurf();
                }
            }
            else
            {
                surf.geometry = R_AllocStaticTriSurf();
            }

            var tri = surf.geometry;

            // note that some of the data is references, and should not be freed
            tri.deformedSurface      = true;
            tri.tangentsCalculated   = false;
            tri.facePlanesCalculated = false;

            tri.numIndexes       = deformInfo.numIndexes;
            tri.indexes          = deformInfo.indexes;
            tri.silIndexes       = deformInfo.silIndexes;
            tri.numMirroredVerts = deformInfo.numMirroredVerts;
            tri.mirroredVerts    = deformInfo.mirroredVerts;
            tri.numDupVerts      = deformInfo.numDupVerts;
            tri.dupVerts         = deformInfo.dupVerts;
            tri.numSilEdges      = deformInfo.numSilEdges;
            tri.silEdges         = deformInfo.silEdges;
            tri.dominantTris     = deformInfo.dominantTris;
            tri.numVerts         = deformInfo.numOutputVerts;

            if (tri.verts == null)
            {
                R_AllocStaticTriSurfVerts(tri, tri.numVerts);
                for (i = 0; i < deformInfo.numSourceVerts; i++)
                {
                    tri.verts[i].Clear(); tri.verts[i].st = texCoords[i];
                }
            }

            fixed(JointMat *jointsJ = joints)
            if (ent.shaderParms[IRenderWorld.SHADERPARM_MD5_SKINSCALE] != 0f)
            {
                TransformScaledVerts(tri.verts, jointsJ, ent.shaderParms[IRenderWorld.SHADERPARM_MD5_SKINSCALE]);
            }
            else
            {
                TransformVerts(tri.verts, jointsJ);
            }

            // replicate the mirror seam vertexes
            var base_ = deformInfo.numOutputVerts - deformInfo.numMirroredVerts;

            for (i = 0; i < deformInfo.numMirroredVerts; i++)
            {
                tri.verts[base_ + i] = tri.verts[deformInfo.mirroredVerts[i]];
            }

            R_BoundTriSurf(tri);

            // If a surface is going to be have a lighting interaction generated, it will also have to call R_DeriveTangents() to get normals, tangents, and face planes.  If it only
            // needs shadows generated, it will only have to generate face planes.  If it only has ambient drawing, or is culled, no additional work will be necessary
            if (!r_useDeferredTangents.Bool)
            {
                R_DeriveTangents(tri);                              // set face planes, vertex normals, tangents
            }
        }
Example #4
0
    /// <summary>
    /// Method for checking raycast from main surface of element and center point - in order to check whether element is inside switchboard or not
    /// </summary>
    /// <param name="element">
    /// Element to check
    /// </param>
    /// <returns>
    /// Array of raycast results - if one of them is false than element is outside the switchboard
    /// </returns>
    private bool[] CheckElementsRaycast(GameObject element)
    {
        ModelSurface mainSurface        = GetMainSurfaceOfGameObject(element);
        Vector3      elementCenterPoint = GetCenterPointOfGameObject(element);
        Vector3      elementSize        = GetSizeOfGameObject(element);

        //Two points of raycasting - raycast should be performed from center point, moved to the external surface of element
        //For every direction there is different external surface
        Vector3 raycastPoint0 = new Vector3(0, 0, 0);
        Vector3 raycastPoint1 = new Vector3(0, 0, 0);

        //Two directions of raycasting
        Vector3 raycastDirection0 = new Vector3(0, 0, 1);
        Vector3 raycastDirection1 = new Vector3(0, 0, -1);

        switch (mainSurface)
        {
        case ModelSurface.XY:
        {
            raycastDirection0 = new Vector3(0, 0, 1);
            raycastDirection1 = new Vector3(0, 0, -1);
            raycastPoint0     = elementCenterPoint + new Vector3(0, 0, elementSize.z / 2);
            raycastPoint1     = elementCenterPoint + new Vector3(0, 0, -elementSize.z / 2);
            break;
        }

        case ModelSurface.XZ:
        {
            raycastDirection0 = new Vector3(0, 1, 0);
            raycastDirection1 = new Vector3(0, -1, 0);
            raycastPoint0     = elementCenterPoint + new Vector3(0, elementSize.y / 2, 0);
            raycastPoint1     = elementCenterPoint + new Vector3(0, -elementSize.y / 2, 0);
            break;
        }

        case ModelSurface.YZ:
        {
            raycastDirection0 = new Vector3(1, 0, 0);
            raycastDirection1 = new Vector3(-1, 0, 0);
            raycastPoint0     = elementCenterPoint + new Vector3(elementSize.x / 2, 0, 0);
            raycastPoint1     = elementCenterPoint + new Vector3(-elementSize.x / 2, 0, 0);
            break;
        }
        }

        //Raycasting depening on raycast length set
        var raycast0Result = false;
        var raycast1Result = false;

        if (MaxRaycastDistance < 0)
        {
            raycast0Result = Physics.Raycast(raycastPoint0, raycastDirection0);
            raycast1Result = Physics.Raycast(raycastPoint1, raycastDirection1);
        }
        else
        {
            raycast0Result = Physics.Raycast(raycastPoint0, raycastDirection0, MaxRaycastDistance);
            raycast1Result = Physics.Raycast(raycastPoint1, raycastDirection1, MaxRaycastDistance);
        }

        return(new bool[] { raycast0Result, raycast1Result });
    }