Example #1
0
        public TgcFrustum()
        {
            FrustumPlanes = new TGCPlane[6];

            Color = Color.Green;
            AlphaBlendingValue = 0.7f;
        }
Example #2
0
 override protected void UpdateValues()
 {
     base.UpdateValues();
     directionPlane = TGCPlane.FromPointNormal(GetPosition(), -GetVectorCostadoIzquierda());
     planoCostado   = TGCPlane.FromPointNormal(GetPosition(), GetVectorAdelante());
     radarSphere.setValues(this.GetPosition(), radarSphere.Radius);
 }
        /// <summary>
        ///     Separa los objetos en dos listas, segun el testo contra el plano de corte
        /// </summary>
        private void splitByPlane(TGCPlane cutPlane, List <StaticObject> objetos,
                                  List <StaticObject> possitiveList, List <StaticObject> negativeList)
        {
            TgcCollisionUtils.PlaneBoxResult c;
            foreach (var objeto in objetos)
            {
                c = TgcCollisionUtils.classifyPlaneAABB(cutPlane, objeto.Meshes[0].BoundingBox); // TODO CALCULAR BOUNDING BOX DEL GAMEOBJECT

                //possitive side
                if (c == TgcCollisionUtils.PlaneBoxResult.IN_FRONT_OF)
                {
                    possitiveList.Add(objeto);
                }

                //negative side
                else if (c == TgcCollisionUtils.PlaneBoxResult.BEHIND)
                {
                    negativeList.Add(objeto);
                }

                //both sides
                else
                {
                    possitiveList.Add(objeto);
                    negativeList.Add(objeto);
                }
            }
        }
        /// <summary>
        ///     Obtiene el mejor plano de corte recto, en el volumen dado, en la direccion dada
        /// </summary>
        private TGCPlane getCutPlane(List <TgcMesh> modelos, TGCVector3 n, float pMin, float pMax, ref float cutValue)
        {
            var vueltas     = (int)((pMax - pMin) / D_DESPLAZAMIENTO);
            var bestBalance = int.MaxValue;
            var bestPlane   = TGCPlane.Zero;

            cutValue = 0;

            for (var i = 0; i < vueltas; i++)
            {
                //crear plano de corte
                var currentCutValue = pMin + D_DESPLAZAMIENTO * i;
                var p = new TGCPlane(n.X, n.Y, n.Z, -currentCutValue);

                //clasificar todos los modelos contra ese plano
                var possitiveList = new List <TgcMesh>();
                var negativeList  = new List <TgcMesh>();
                splitByPlane(p, modelos, possitiveList, negativeList);

                //calcular balance
                var balance = Math.Abs(possitiveList.Count - negativeList.Count);

                //guardar mejor
                if (balance < bestBalance)
                {
                    bestBalance = balance;
                    bestPlane   = p;
                    cutValue    = currentCutValue;
                }
            }

            return(bestPlane);
        }
        /// <summary>
        ///     Separa los modelos en dos listas, segun el testo contra el plano de corte
        /// </summary>
        private void splitByPlane(TGCPlane cutPlane, List <TgcMesh> modelos,
                                  List <TgcMesh> possitiveList, List <TgcMesh> negativeList)
        {
            TgcCollisionUtils.PlaneBoxResult c;
            foreach (var modelo in modelos)
            {
                c = TgcCollisionUtils.classifyPlaneAABB(cutPlane, modelo.BoundingBox);

                //possitive side
                if (c == TgcCollisionUtils.PlaneBoxResult.IN_FRONT_OF)
                {
                    possitiveList.Add(modelo);
                }

                //negative side
                else if (c == TgcCollisionUtils.PlaneBoxResult.BEHIND)
                {
                    negativeList.Add(modelo);
                }

                //both sides
                else
                {
                    possitiveList.Add(modelo);
                    negativeList.Add(modelo);
                }
            }
        }
Example #6
0
        /// <summary>
        ///     Actualiza la visibilidad de todos los modelos de las celdas.
        ///     Las modelos visibles se cargan como Enable = true, mientras que el
        ///     resto se deshabilita.
        /// </summary>
        /// <param name="cameraPos">Posición de la cámara</param>
        public void updateVisibility(TGCVector3 cameraPos, TgcFrustum frustum)
        {
            //Armar Frustum para uso internor, en base al Frustum actual
            var currentFrustumPlanes = new TGCPlane[6];

            currentFrustumPlanes    = new TGCPlane[6];
            currentFrustumPlanes[0] = frustum.NearPlane;
            currentFrustumPlanes[1] = frustum.FarPlane;
            currentFrustumPlanes[2] = frustum.LeftPlane;
            currentFrustumPlanes[3] = frustum.RightPlane;
            currentFrustumPlanes[4] = frustum.BottomPlane;
            currentFrustumPlanes[5] = frustum.TopPlane;

            //Deshabilitar todas las celdas
            foreach (var cell in Cells)
            {
                cell.Visited = false;
                foreach (var connection in cell.Connections)
                {
                    connection.Portal.Visited = false;
                }
            }

            //Buscar la celda actual en la que se encuentra la cámara
            var currentCell = findCellFromPoint(cameraPos);

            if (currentCell == null)
            {
                return;
            }

            //Recorrer grafo de celdas desde la celda actual
            currentCell.Visited = true;
            traverseCellGraph(cameraPos, currentFrustumPlanes, currentCell);
        }
Example #7
0
        /// <summary>
        ///     Crear un nuevo Frustum acotado usando como base el portal recorado.
        ///     La cantidad de planos del nuevo Frustum no tiene por qué ser 6.
        ///     Depende de la forma que haya quedado en el portal recortado.
        /// </summary>
        private TGCPlane[] createFrustumPlanes(TGCVector3 cameraPos, TGCPlane[] currentFrustumPlanes, TGCVector3[] portalVerts,
                                               TGCPlane portalPlane)
        {
            //Hay un plano por cada vértice del polígono + 2 por el near y far plane
            var frustumPlanes = new TGCPlane[2 + portalVerts.Length];

            //Cargar near y far plane originales
            //TODO: habria que usar el portalPlane para acercar el NearPlane hasta el portal
            frustumPlanes[0] = currentFrustumPlanes[0];
            frustumPlanes[1] = currentFrustumPlanes[1];

            //Generar los planos laterales en base al polígono remanente del portal
            //Vamos tomando de a dos puntos del polígono + la posición de la cámara y creamos un plano
            var lastP = portalVerts[portalVerts.Length - 1];

            for (var i = 0; i < portalVerts.Length; i++)
            {
                var nextP = portalVerts[i];

                //Armar el plano para que la normal apunte hacia adentro del Frustum
                var a     = lastP - cameraPos;
                var b     = nextP - cameraPos;
                var plane = TGCPlane.FromPointNormal(cameraPos, TGCVector3.Cross(b, a));

                //Guardar después del near y far plane
                frustumPlanes[i + 2] = plane;

                lastP = nextP;
            }

            return(frustumPlanes);
        }
 /// <summary>
 ///     Crear triangulo.
 ///     Calcula su plano y BoundingSphere
 /// </summary>
 public Triangle(TGCVector3 a, TGCVector3 b, TGCVector3 c)
 {
     A              = a;
     B              = b;
     C              = c;
     Plane          = TGCPlane.FromPoints(a, b, c);
     BoundingSphere = TgcBoundingSphere.computeFromPoints(new[] { a, b, c }).toClass();
 }
Example #9
0
 public TgcPortalRenderingConnection(TgcPortalRenderingPortal portal, TgcPortalRenderingCell nextCell,
                                     TgcConvexPolygon polygon, TGCPlane plane)
 {
     Portal   = portal;
     NextCell = nextCell;
     Polygon  = polygon;
     Plane    = plane;
 }
 /// <summary>
 ///     Crear triangulo.
 ///     Calcula su plano
 /// </summary>
 public Triangle(TGCVector3 a, TGCVector3 b, TGCVector3 c, TgcBoundingSphere sphere)
 {
     A              = a;
     B              = b;
     C              = c;
     Plane          = TGCPlane.FromPoints(a, b, c);
     BoundingSphere = sphere;
 }
Example #11
0
        public bool IntersectsWithObject(TGCPlane objectPlane, float distance)
        {
            pickingRay.updateRay();

            bool intersected = TgcCollisionUtils.intersectRayPlane(pickingRay.Ray, objectPlane, out _, out TGCVector3 collisionPoint);
            bool inSight     = Math.Sqrt(TGCVector3.LengthSq(pickingRay.Ray.Origin, collisionPoint)) < distance;

            return(intersected && inSight);
        }
Example #12
0
        /// <summary>
        ///     Corte de plano Z
        /// </summary>
        private void doSectorOctreeZ(OctreeNode parent, TGCVector3 center, TGCVector3 size, int step,
                                     List <TgcMesh> meshes, int childIndex)
        {
            var z = center.Z;

            //Crear listas para realizar corte
            var possitiveList = new List <TgcMesh>();
            var negativeList  = new List <TgcMesh>();

            //Z-cut
            var zCutPlane = new TGCPlane(0, 0, 1, -z);

            splitByPlane(zCutPlane, meshes, possitiveList, negativeList);

            //obtener lista de children del parent, con iniciacion lazy
            if (parent.children == null)
            {
                parent.children = new OctreeNode[8];
            }

            //crear nodo positivo en parent, segun childIndex
            var posNode = new OctreeNode();

            parent.children[childIndex] = posNode;

            //cargar nodo negativo en parent, segun childIndex
            var negNode = new OctreeNode();

            parent.children[childIndex + 1] = negNode;

            //condicion de corte
            if (step >= MAX_SECTOR_OCTREE_RECURSION || meshes.Count <= MIN_MESH_PER_LEAVE_THRESHOLD)
            {
                //cargar hijos de nodo positivo
                posNode.models = possitiveList.ToArray();

                //cargar hijos de nodo negativo
                negNode.models = negativeList.ToArray();

                //seguir recursividad
            }
            else
            {
                step++;

                //recursividad de positivos con plano X, usando resultados positivos
                doSectorOctreeX(posNode, new TGCVector3(center.X, center.Y, z + size.Z / 2),
                                new TGCVector3(size.X, size.Y, size.Z / 2),
                                step, possitiveList);

                //recursividad de negativos con plano Y, usando resultados negativos
                doSectorOctreeX(negNode, new TGCVector3(center.X, center.Y, z - size.Z / 2),
                                new TGCVector3(size.X, size.Y, size.Z / 2),
                                step, negativeList);
            }
        }
 public Plane(TGCVector3 minPoint, TGCVector3 maxPoint, TGCVector3 orientation, string fileName, float UCoordinate, float VCoordinate)
 {
     orientation.Normalize();
     this.plane = new TgcPlane(new TGCVector3(0, 0, 0), new TGCVector3(0, 0, 0), this.GetPlaneOrientation(orientation), TgcTexture.createTexture(GlobalConcepts.GetInstance().GetMediaDir() + "MeshCreator\\Meshes\\" + fileName), UCoordinate, VCoordinate);
     this.plane.setExtremes(minPoint, maxPoint);
     this.plane.updateValues();
     this.mesh          = this.plane.toMesh("plane");
     mesh.AutoTransform = false;
     //negrada atomica
     InvertNormals(orientation);
     this.realPlane = TGCPlane.FromPointNormal(minPoint, orientation);
     mesh.Effect    = TgcShaders.Instance.TgcMeshPointLightShader;
     mesh.Technique = "DIFFUSE_MAP";
 }
Example #14
0
        protected bool IsReallyTheFloor(Collidable element)
        {
            TGCVector3 directionOfCollision = new TGCVector3(0, -1f, 0);
            TgcRay     ray = new TgcRay();

            ray.Origin    = this.auto.GetLastPosition();
            ray.Direction = directionOfCollision;
            TGCPlane   plane  = element.GetPlaneOfCollision(ray, this.auto);
            TGCVector3 normal = new TGCVector3(0, 1, 0);

            if (normal != new TGCVector3(0, 1, 0))
            {
                return(false);
            }
            return(true);
        }
Example #15
0
        /// <summary>
        ///     Actualiza los planos que conforman el volumen del Frustum.
        ///     Los planos se calculan con las normales apuntando hacia adentro
        /// </summary>
        /// <param name="viewMatrix">View matrix</param>
        /// <param name="projectionMatrix">Projection matrix</param>
        public void updateVolume(TGCMatrix viewMatrix, TGCMatrix projectionMatrix)
        {
            var viewProjection = viewMatrix * projectionMatrix;

            //Left plane
            FrustumPlanes[0].A = viewProjection.M14 + viewProjection.M11;
            FrustumPlanes[0].B = viewProjection.M24 + viewProjection.M21;
            FrustumPlanes[0].C = viewProjection.M34 + viewProjection.M31;
            FrustumPlanes[0].D = viewProjection.M44 + viewProjection.M41;

            //Right plane
            FrustumPlanes[1].A = viewProjection.M14 - viewProjection.M11;
            FrustumPlanes[1].B = viewProjection.M24 - viewProjection.M21;
            FrustumPlanes[1].C = viewProjection.M34 - viewProjection.M31;
            FrustumPlanes[1].D = viewProjection.M44 - viewProjection.M41;

            //Top plane
            FrustumPlanes[2].A = viewProjection.M14 - viewProjection.M12;
            FrustumPlanes[2].B = viewProjection.M24 - viewProjection.M22;
            FrustumPlanes[2].C = viewProjection.M34 - viewProjection.M32;
            FrustumPlanes[2].D = viewProjection.M44 - viewProjection.M42;

            //Bottom plane
            FrustumPlanes[3].A = viewProjection.M14 + viewProjection.M12;
            FrustumPlanes[3].B = viewProjection.M24 + viewProjection.M22;
            FrustumPlanes[3].C = viewProjection.M34 + viewProjection.M32;
            FrustumPlanes[3].D = viewProjection.M44 + viewProjection.M42;

            //Near plane
            FrustumPlanes[4].A = viewProjection.M13;
            FrustumPlanes[4].B = viewProjection.M23;
            FrustumPlanes[4].C = viewProjection.M33;
            FrustumPlanes[4].D = viewProjection.M43;

            //Far plane
            FrustumPlanes[5].A = viewProjection.M14 - viewProjection.M13;
            FrustumPlanes[5].B = viewProjection.M24 - viewProjection.M23;
            FrustumPlanes[5].C = viewProjection.M34 - viewProjection.M33;
            FrustumPlanes[5].D = viewProjection.M44 - viewProjection.M43;

            //Normalize planes
            for (var i = 0; i < 6; i++)
            {
                FrustumPlanes[i] = TGCPlane.Normalize(FrustumPlanes[i]);
            }
        }
Example #16
0
        /// <summary>
        ///     Corte con plano X
        /// </summary>
        private void doSectorOctreeX(OctreeNode parent, TGCVector3 center, TGCVector3 size,
                                     int step, List <TgcMesh> meshes)
        {
            var x = center.X;

            //Crear listas para realizar corte
            var possitiveList = new List <TgcMesh>();
            var negativeList  = new List <TgcMesh>();

            //X-cut
            var xCutPlane = new TGCPlane(1, 0, 0, -x);

            splitByPlane(xCutPlane, meshes, possitiveList, negativeList);

            //recursividad de positivos con plano Y, usando resultados positivos y childIndex 0
            doSectorOctreeY(parent, new TGCVector3(x + size.X / 2, center.Y, center.Z),
                            new TGCVector3(size.X / 2, size.Y, size.Z),
                            step, possitiveList, 0);

            //recursividad de negativos con plano Y, usando resultados negativos y childIndex 4
            doSectorOctreeY(parent, new TGCVector3(x - size.X / 2, center.Y, center.Z),
                            new TGCVector3(size.X / 2, size.Y, size.Z),
                            step, negativeList, 4);
        }
Example #17
0
        /// <summary>
        ///     Corte con plano Y
        /// </summary>
        private void doSectorOctreeY(OctreeNode parent, TGCVector3 center, TGCVector3 size, int step,
                                     List <TgcMesh> meshes, int childIndex)
        {
            var y = center.Y;

            //Crear listas para realizar corte
            var possitiveList = new List <TgcMesh>();
            var negativeList  = new List <TgcMesh>();

            //Y-cut
            var yCutPlane = new TGCPlane(0, 1, 0, -y);

            splitByPlane(yCutPlane, meshes, possitiveList, negativeList);

            //recursividad de positivos con plano Z, usando resultados positivos y childIndex 0
            doSectorOctreeZ(parent, new TGCVector3(center.X, y + size.Y / 2, center.Z),
                            new TGCVector3(size.X, size.Y / 2, size.Z),
                            step, possitiveList, childIndex + 0);

            //recursividad de negativos con plano Z, usando plano X negativo y childIndex 2
            doSectorOctreeZ(parent, new TGCVector3(center.X, y - size.Y / 2, center.Z),
                            new TGCVector3(size.X, size.Y / 2, size.Z),
                            step, negativeList, childIndex + 2);
        }
Example #18
0
        private void Collide(TgcMesh elemento, Vehicle car)
        {
            //direccion a la que estoy yendo antes de chocar
            TGCVector3 directionOfCollision = car.GetDirectionOfCollision();
            TgcRay     ray = new TgcRay();

            ray.Origin    = car.GetLastPosition();
            ray.Direction = directionOfCollision;
            //interseco el rayo con el aabb, para conocer un punto del plano con el que colisione
            TgcBoundingAxisAlignBox.Face[] faces;
            faces = elemento.BoundingBox.computeFaces();
            TGCPlane   plane  = this.CreatePlane(ray, faces, car.GetLastPosition());
            TGCVector3 normal = GlobalConcepts.GetInstance().GetNormalPlane(plane);
            TGCVector3 output = normal + directionOfCollision * 2;
            float      angle  = car.SetDirection(output, normal);

            car.Crash(angle);

            while (TgcCollisionUtils.testObbAABB(car.GetTGCBoundingOrientedBox(), elemento.BoundingBox))
            {
                car.Translate(TGCMatrix.Translation(normal));
                car.Transform();
            }
        }
        public override void Init()
        {
            //Cargar un mesh
            var loader = new TgcSceneLoader();
            var scene  = loader.loadSceneFromFile(MediaDir + "MeshCreator\\Meshes\\Cimientos\\PilarEgipcio\\PilarEgipcio-TgcScene.xml");

            mesh = scene.Meshes[0];

            //Obtener los vértices del mesh (esta operacion es lenta, copia de la GPU a la CPU, no hacer a cada rato)
            var vertices = mesh.getVertexPositions();

            //Iterar sobre todos los vertices y construir triangulos, normales y planos
            var triCount = vertices.Length / 3;

            triangles = new List <TgcTriangle>(triCount);
            normals   = new List <TgcArrow>();
            planes    = new List <TGCQuad>();
            for (var i = 0; i < triCount; i++)
            {
                //Obtenemos los 3 vertices del triangulo, es importante saber como esta estructurado nuestro mesh.
                var a = vertices[i * 3];
                var b = vertices[i * 3 + 1];
                var c = vertices[i * 3 + 2];

                //Obtener normal del triangulo. El orden influye en si obtenemos el vector normal hacia adentro o hacia afuera del mesh
                var normal = TGCVector3.Cross(c - a, b - a);
                normal.Normalize();

                //Crear plano que contiene el triangulo a partir un vertice y la normal
                var plane = TGCPlane.FromPointNormal(a, normal);

                //Calcular el centro del triangulo. Hay muchos tipos de centros para un triangulo (http://www.mathopenref.com/trianglecenters.html)
                //Aca calculamos el mas simple
                var center = TGCVector3.Scale(a + b + c, 1 / 3f);

                ///////////// Creacion de elementos para poder dibujar a pantalla (propios de este ejemplo) ///////////////

                //Crear un quad (pequeno plano) con la clase TgcQuad para poder dibujar el plano que contiene al triangulo
                var quad = new TGCQuad();
                quad.Center = center;
                quad.Normal = normal;
                quad.Color  = adaptColorRandom(Color.DarkGreen);
                quad.Size   = new TGCVector2(10, 10);
                quad.updateValues();
                planes.Add(quad);

                //Creamos una flecha con la clase TgcArrow para poder dibujar la normal (la normal la estiramos un poco para que se pueda ver)
                normals.Add(TgcArrow.fromDirection(center, TGCVector3.Scale(normal, 10f)));

                //Creamos la clase TgcTriangle que es un helper para dibujar triangulos sueltos
                var t = new TgcTriangle();
                t.A     = a;
                t.B     = b;
                t.C     = c;
                t.Color = adaptColorRandom(Color.Red);
                t.updateValues();
                triangles.Add(t);
            }

            //Modifiers
            meshModifier      = AddBoolean("mesh", "mesh", true);
            trianglesModifier = AddBoolean("triangles", "triangles", true);
            normalsModifier   = AddBoolean("normals", "normals", true);
            planesModifier    = AddBoolean("planes", "planes", false);

            //Camara
            Camera = new TgcRotationalCamera(mesh.BoundingBox.calculateBoxCenter(), mesh.BoundingBox.calculateBoxRadius() * 2, Input);
        }
Example #20
0
        /// <summary>
        ///     Tomar un mesh cargar todas las estructuras internas necesarias para poder editarlo
        /// </summary>
        private void loadMesh(TgcMesh origMesh)
        {
            //Obtener vertices del mesh
            mesh = origMesh;
            mesh.AutoTransformEnable = true;
            var origVertices = getMeshOriginalVertexData(origMesh);
            var origTriCount = origVertices.Count / 3;

            //Iterar sobre los triangulos y generar data auxiliar unificada
            Vertices    = new List <EditPolyVertex>();
            Edges       = new List <EditPolyEdge>();
            Polygons    = new List <EditPolyPolygon>();
            IndexBuffer = new short[origTriCount * 3];
            var attributeBuffer = origMesh.D3dMesh.LockAttributeBufferArray(LockFlags.ReadOnly);

            origMesh.D3dMesh.UnlockAttributeBuffer(attributeBuffer);
            for (var i = 0; i < origTriCount; i++)
            {
                var v1 = origVertices[i * 3];
                var v2 = origVertices[i * 3 + 1];
                var v3 = origVertices[i * 3 + 2];

                //Agregar vertices a la lista, si es que son nuevos
                var v1Idx = EditablePolyUtils.addVertexToListIfUnique(Vertices, v1);
                var v2Idx = EditablePolyUtils.addVertexToListIfUnique(Vertices, v2);
                var v3Idx = EditablePolyUtils.addVertexToListIfUnique(Vertices, v3);
                v1 = Vertices[v1Idx];
                v2 = Vertices[v2Idx];
                v3 = Vertices[v3Idx];

                //Crear edges
                var e1 = new EditPolyEdge();
                e1.a = v1;
                e1.b = v2;
                var e2 = new EditPolyEdge();
                e2.a = v2;
                e2.b = v3;
                var e3 = new EditPolyEdge();
                e3.a = v3;
                e3.b = v1;

                //Crear poligono para este triangulo
                var p = new EditPolyPolygon();
                p.vertices = new List <EditPolyVertex>();
                p.vertices.Add(v1);
                p.vertices.Add(v2);
                p.vertices.Add(v3);
                p.edges = new List <EditPolyEdge>();
                p.edges.Add(e1);
                p.edges.Add(e2);
                p.edges.Add(e3);
                p.vbTriangles = new List <int>();
                p.vbTriangles.Add(i * 3);
                p.TGCPlane = TGCPlane.FromPoints(v1.position, v2.position, v3.position);
                p.TGCPlane.Normalize();
                p.matId = attributeBuffer[i];

                //Agregar triangulo al index buffer
                IndexBuffer[i * 3]     = (short)v1Idx;
                IndexBuffer[i * 3 + 1] = (short)v2Idx;
                IndexBuffer[i * 3 + 2] = (short)v3Idx;

                //Agregar a lista de poligonos
                Polygons.Add(p);

                /*
                 * //Buscar si hay un poligono ya existente al cual sumarnos (coplanar y que compartan una arista)
                 * EditPolyPolygon coplanarP = null;
                 * for (int j = 0; j < polygons.Count; j++)
                 * {
                 *  //Coplanares y con igual material ID
                 *  EditPolyPolygon p0 = polygons[j];
                 *  if (p0.matId == p.matId && EditablePolyUtils.sameTGCPlane(p0.TGCPlane, p.TGCPlane))
                 *  {
                 *      //Buscar si tienen una arista igual
                 *      int p0SharedEdgeIdx;
                 *      int pSharedEdgeIdx;
                 *      if (EditablePolyUtils.findShareEdgeBetweenPolygons(p0, p, out p0SharedEdgeIdx, out pSharedEdgeIdx))
                 *      {
                 *          //Obtener el tercer vertice del triangulo que no es parte de la arista compartida
                 *          EditPolyEdge sharedEdge = p0.edges[p0SharedEdgeIdx];
                 *          EditPolyVertex thirdVert;
                 *          if (p.vertices[0] != sharedEdge.a && p.vertices[0] != sharedEdge.b)
                 *              thirdVert = p.vertices[0];
                 *          else if (p.vertices[1] != sharedEdge.a && p.vertices[1] != sharedEdge.b)
                 *              thirdVert = p.vertices[1];
                 *          else
                 *              thirdVert = p.vertices[2];
                 *
                 *          //Agregar el tercer vertice al poligno existente
                 *          EditablePolyUtils.addVertexToPolygon(p0, sharedEdge, thirdVert);
                 *
                 *          //Quitar arista compartida
                 *          p0.edges.Remove(sharedEdge);
                 *
                 *          //Agregar al poligono dos nuevas aristas que conectar los extremos de la arista compartida hacia el tercer vertice
                 *          EditPolyEdge newPolEdge1 = new EditPolyEdge();
                 *          newPolEdge1.a = sharedEdge.a;
                 *          newPolEdge1.b = thirdVert;
                 *          p0.edges.Add(newPolEdge1);
                 *
                 *          EditPolyEdge newPolEdge2 = new EditPolyEdge();
                 *          newPolEdge2.a = thirdVert;
                 *          newPolEdge2.b = sharedEdge.b;
                 *          p0.edges.Add(newPolEdge2);
                 *
                 *          //Agregar indice de triangulo del vertexBuffer que se sumo al poligono
                 *          p0.vbTriangles.Add(p.vbTriangles[0]);
                 *
                 *          coplanarP = p0;
                 *      }
                 *  }
                 * }
                 * //Es un nuevo poligono, agregarlo
                 * if (coplanarP == null)
                 * {
                 *  polygons.Add(p);
                 * }
                 */
            }

            //Unificar aristas de los poligonos
            foreach (var p in Polygons)
            {
                for (var i = 0; i < p.edges.Count; i++)
                {
                    bool newEdgeAdded;
                    var  eIdx = EditablePolyUtils.addEdgeToListIfUnique(Edges, p.edges[i], out newEdgeAdded);
                    var  e    = Edges[eIdx];

                    //Nueva arista incorporada a la lista
                    if (newEdgeAdded)
                    {
                        e.faces = new List <EditPolyPolygon>();

                        //Agregar referencia a vertices que usan la arista
                        e.a.edges.Add(e);
                        e.b.edges.Add(e);
                    }
                    //Se usa arista existente de la lista
                    else
                    {
                        //Reemplazar en poligono por la nueva
                        p.edges[i] = e;
                    }

                    //Indicar a la arista que pertenece al poligono actual
                    e.faces.Add(p);
                }
            }

            setDirtyValues(false);
        }
Example #21
0
 /// <summary>
 ///     Compara si dos planos son iguales
 /// </summary>
 public static bool sameTGCPlane(TGCPlane p1, TGCPlane p2)
 {
     //TODO: comparar en ambos sentidos por las dudas
     return(equalsTGCVector3(new TGCVector3(p1.A, p1.B, p1.C), new TGCVector3(p2.A, p2.B, p2.C)) &&
            equalsFloat(p1.D, p2.D));
 }
Example #22
0
        /// <summary>
        ///     Detección de colisiones recursiva
        /// </summary>
        public void doCollideWithWorld(TgcBoundingSphere characterSphere, TGCVector3 movementVector,
                                       List <Collider> colliders, int recursionDepth, TgcBoundingSphere movementSphere, bool sliding,
                                       float slidingMinY)
        {
            //Limitar recursividad
            if (recursionDepth > 5)
            {
                return;
            }

            //Posicion deseada
            var originalSphereCenter = characterSphere.Center;
            var nextSphereCenter     = originalSphereCenter + movementVector;

            //Buscar el punto de colision mas cercano de todos los objetos candidatos
            Collision = false;
            TGCVector3 q;
            float      t;
            TGCVector3 n;
            var        minT = float.MaxValue;

            foreach (var collider in colliders)
            {
                //Colisionar Sphere en movimiento contra Collider (cada Collider resuelve la colision)
                if (collider.intersectMovingSphere(characterSphere, movementVector, movementSphere, out t, out q, out n))
                {
                    //Quedarse con el menor instante de colision
                    if (t < minT)
                    {
                        minT                = t;
                        Collision           = true;
                        LastCollisionPoint  = q;
                        LastCollisionNormal = n;
                        lastCollider        = collider;
                    }
                }
            }

            //Si nunca hubo colisión, avanzar todo lo requerido
            if (!Collision)
            {
                //Avanzar todo lo pedido
                //lastCollisionDistance = movementVector.Length();
                characterSphere.moveCenter(movementVector);
                return;
            }

            //Solo movernos si ya no estamos muy cerca
            if (minT >= EPSILON)
            {
                //Restar un poco al instante de colision, para movernos hasta casi esa distancia
                minT -= EPSILON;
                var realMovementVector = movementVector * minT;

                //Mover el BoundingSphere
                characterSphere.moveCenter(realMovementVector);

                //Quitarle al punto de colision el EPSILON restado al movimiento, para no afectar al plano de sliding
                var v = TGCVector3.Normalize(realMovementVector);
                LastCollisionPoint -= v * EPSILON;
            }

            if (sliding)
            {
                //Calcular plano de Sliding, como un plano tangete al punto de colision con la esfera, apuntando hacia el centro de la esfera
                var slidePlaneOrigin = LastCollisionPoint;
                var slidePlaneNormal = characterSphere.Center - LastCollisionPoint;
                slidePlaneNormal.Normalize();
                var slidePlane = TGCPlane.FromPointNormal(slidePlaneOrigin, slidePlaneNormal);

                //Calcular vector de movimiento para sliding, proyectando el punto de destino original sobre el plano de sliding
                var distance            = TgcCollisionUtils.distPointPlane(nextSphereCenter, slidePlane);
                var newDestinationPoint = nextSphereCenter - distance * slidePlaneNormal;
                var slideMovementVector = newDestinationPoint - LastCollisionPoint;

                //No hacer recursividad si es muy pequeño
                slideMovementVector.Scale(SlideFactor);
                if (slideMovementVector.Length() < EPSILON)
                {
                    return;
                }

                if (LastCollisionNormal.Y <= slidingMinY)
                {
                    //Recursividad para aplicar sliding
                    doCollideWithWorld(characterSphere, slideMovementVector, colliders, recursionDepth + 1,
                                       movementSphere, sliding, slidingMinY);
                }
            }
        }
        /// <summary>
        ///     Cargar información de PortalRendering
        /// </summary>
        public TgcPortalRenderingManager loadFromData(TgcScene scene, TgcPortalRenderingData portalRenderingData)
        {
            var manager = new TgcPortalRenderingManager(scene);

            //Crear dictionary de nombres de los meshes
            var meshDictionary = new Dictionary<string, TgcMesh>();
            foreach (var mesh in scene.Meshes)
            {
                meshDictionary.Add(mesh.Name, mesh);
            }

            //Cargar celdas
            foreach (var cellData in portalRenderingData.cells)
            {
                //Crear cuerpo Convexo
                var convexPoly = new TgcConvexPolyhedron();
                convexPoly.Planes = new TGCPlane[cellData.facePlanes.Length / 4];
                for (var i = 0; i < convexPoly.Planes.Length; i++)
                {
                    convexPoly.Planes[i] = new TGCPlane(
                        cellData.facePlanes[i * 4],
                        cellData.facePlanes[i * 4 + 1],
                        cellData.facePlanes[i * 4 + 2],
                        cellData.facePlanes[i * 4 + 3]
                        );
                }
                convexPoly.BoundingVertices = new TGCVector3[cellData.boundingVertices.Length / 3];
                for (var i = 0; i < convexPoly.BoundingVertices.Length; i++)
                {
                    convexPoly.BoundingVertices[i] = new TGCVector3(
                        cellData.boundingVertices[i * 3],
                        cellData.boundingVertices[i * 3 + 1],
                        cellData.boundingVertices[i * 3 + 2]
                        );
                }

                //Crear celda
                var cell = new TgcPortalRenderingCell(cellData.name, convexPoly);
                manager.Cells.Add(cell);

                //Cargar meshes en celda
                for (var i = 0; i < cellData.meshes.Length; i++)
                {
                    var mesh = meshDictionary[cellData.meshes[i]];
                    cell.Meshes.Add(mesh);
                }
            }

            //Cargar portales
            foreach (var portalData in portalRenderingData.portals)
            {
                //BoundingBox del portal
                var boundingBox = new TgcBoundingAxisAlignBox(
                    new TGCVector3(portalData.pMin[0], portalData.pMin[1], portalData.pMin[2]),
                    new TGCVector3(portalData.pMax[0], portalData.pMax[1], portalData.pMax[2])
                    );

                //Crear portal
                var portal = new TgcPortalRenderingPortal(portalData.name, boundingBox);
                manager.Portals.Add(portal);

                //Cargar conexiones para celdas A y B
                var cellA = manager.Cells[portalData.cellA];
                var cellB = manager.Cells[portalData.cellB];

                //Poligono del portal para la celda A
                var polygonA = new TgcConvexPolygon();
                polygonA.BoundingVertices = new TGCVector3[portalData.boundingVerticesA.Length / 3];
                for (var i = 0; i < polygonA.BoundingVertices.Length; i++)
                {
                    polygonA.BoundingVertices[i] = new TGCVector3(
                        portalData.boundingVerticesA[i * 3],
                        portalData.boundingVerticesA[i * 3 + 1],
                        portalData.boundingVerticesA[i * 3 + 2]
                        );
                }

                //Plano del portal para la celda A
                var planeA = TGCPlane.Float4ArrayToPlane(portalData.planeA);

                //Crear conexion A
                var connectionA = new TgcPortalRenderingConnection(portal, cellB, polygonA, planeA);
                cellA.Connections.Add(connectionA);

                //Poligono del portal para la celda B
                var polygonB = new TgcConvexPolygon();
                polygonB.BoundingVertices = new TGCVector3[portalData.boundingVerticesB.Length / 3];
                for (var i = 0; i < polygonB.BoundingVertices.Length; i++)
                {
                    polygonB.BoundingVertices[i] = new TGCVector3(
                        portalData.boundingVerticesB[i * 3],
                        portalData.boundingVerticesB[i * 3 + 1],
                        portalData.boundingVerticesB[i * 3 + 2]
                        );
                }

                //Plano del portal para la celda B
                var planeB = TGCPlane.Float4ArrayToPlane(portalData.planeB);

                //Crear conexion B
                var connectionB = new TgcPortalRenderingConnection(portal, cellA, polygonB, planeB);
                cellB.Connections.Add(connectionB);
            }

            return manager;
        }
Example #24
0
 public bool IsInFrontOf(TGCVector3 testpoint, TGCPlane plane)
 {
     return(plane.A * testpoint.X + plane.B * testpoint.Y + plane.C * testpoint.Z + plane.D >= 0);
 }
Example #25
0
 public TGCVector3 GetNormalPlane(TGCPlane plane)
 {
     return(new TGCVector3(plane.A, plane.B, plane.C));
 }
Example #26
0
        /// <summary>
        ///     Detección de colisiones recursiva
        /// </summary>
        /// <param name="eSphere">Sphere de radio 1 pasada a Elipsoid space</param>
        /// <param name="eMovementVector">Movimiento pasado a Elipsoid space</param>
        /// <param name="eRadius">Radio de la elipsoide</param>
        /// <param name="colliders">Objetos contra los cuales colisionar</param>
        /// <param name="recursionDepth">Nivel de recursividad</param>
        /// <param name="movementSphere">Esfera real que representa el movimiento abarcado</param>
        /// <param name="slidingMinY">Minimo valor de normal Y de colision para hacer sliding</param>
        /// <returns>Resultado de colision</returns>
        public CollisionResult doCollideWithWorld(TgcBoundingSphere eSphere, TGCVector3 eMovementVector, TGCVector3 eRadius,
                                                  List <Collider> colliders, int recursionDepth, TgcBoundingSphere movementSphere, float slidingMinY)
        {
            var result = new CollisionResult();

            result.collisionFound = false;

            //Limitar recursividad
            if (recursionDepth > 5)
            {
                return(result);
            }

            //Posicion deseada
            var nextSphereCenter = eSphere.Center + eMovementVector;

            //Buscar el punto de colision mas cercano de todos los objetos candidatos
            TGCVector3 q;
            float      t;
            TGCVector3 n;
            var        minT = float.MaxValue;

            foreach (var collider in colliders)
            {
                //Colisionar Sphere en movimiento contra Collider (cada Collider resuelve la colision)
                if (collider.intersectMovingElipsoid(eSphere, eMovementVector, eRadius, movementSphere, out t, out q,
                                                     out n))
                {
                    //Quedarse con el menor instante de colision
                    if (t < minT)
                    {
                        minT = t;
                        result.collisionFound  = true;
                        result.collisionPoint  = q;
                        result.collisionNormal = n;
                        result.collider        = collider;
                    }
                }
            }

            //Si nunca hubo colisión, avanzar todo lo requerido
            if (!result.collisionFound)
            {
                //Avanzar todo lo pedido
                eSphere.moveCenter(eMovementVector);
                result.realMovmentVector = eMovementVector;
                result.collisionNormal   = TGCVector3.Empty;
                result.collisionPoint    = TGCVector3.Empty;
                result.collider          = null;
                return(result);
            }

            //Solo movernos si ya no estamos muy cerca
            if (minT >= EPSILON)
            {
                //Restar un poco al instante de colision, para movernos hasta casi esa distancia
                minT -= EPSILON;
                result.realMovmentVector = eMovementVector * minT;
                eSphere.moveCenter(result.realMovmentVector);

                //Quitarle al punto de colision el EPSILON restado al movimiento, para no afectar al plano de sliding
                var v = TGCVector3.Normalize(result.realMovmentVector);
                result.collisionPoint -= v * EPSILON;
            }

            //Calcular plano de Sliding, como un plano tangete al punto de colision con la esfera, apuntando hacia el centro de la esfera
            var slidePlaneOrigin = result.collisionPoint;
            var slidePlaneNormal = eSphere.Center - result.collisionPoint;

            slidePlaneNormal.Normalize();
            var slidePlane = TGCPlane.FromPointNormal(slidePlaneOrigin, slidePlaneNormal);

            //Calcular vector de movimiento para sliding, proyectando el punto de destino original sobre el plano de sliding
            var distance            = TgcCollisionUtils.distPointPlane(nextSphereCenter, slidePlane);
            var newDestinationPoint = nextSphereCenter - distance * slidePlaneNormal;
            var slideMovementVector = newDestinationPoint - result.collisionPoint;

            //No hacer recursividad si es muy pequeño
            slideMovementVector.Scale(SlideFactor);
            if (slideMovementVector.Length() < EPSILON)
            {
                return(result);
            }

            //Ver si posee la suficiente pendiente en Y para hacer sliding
            if (result.collisionNormal.Y <= slidingMinY)
            {
                //Recursividad para aplicar sliding
                doCollideWithWorld(eSphere, slideMovementVector, eRadius, colliders, recursionDepth + 1, movementSphere,
                                   slidingMinY);
            }

            return(result);
        }
 public TGCPlane GetPlaneOfCollision(TgcRay ray, Vehicle car)
 {
     return(TGCPlane.FromPointNormal(this.GetPosition(), TGCVector3.Up));
 }
        /// <summary>
        ///     Detección de colisiones recursiva
        /// </summary>
        public void doCollideWithWorld(TgcBoundingSphere characterSphere, TGCVector3 movementVector,
                                       List <TgcBoundingAxisAlignBox> obstaculos, int recursionDepth)
        {
            //Limitar recursividad
            if (recursionDepth > 5)
            {
                return;
            }

            //Ver si la distancia a recorrer es para tener en cuenta
            var distanceToTravelSq = movementVector.LengthSq();

            if (distanceToTravelSq < EPSILON)
            {
                return;
            }

            //Posicion deseada
            var originalSphereCenter = characterSphere.Center;
            var nextSphereCenter     = originalSphereCenter + movementVector;

            //Buscar el punto de colision mas cercano de todos los objetos candidatos
            var minCollisionDistSq = float.MaxValue;
            var realMovementVector = movementVector;

            TgcBoundingAxisAlignBox.Face collisionFace     = null;
            TgcBoundingAxisAlignBox      collisionObstacle = null;
            var nearestPolygonIntersectionPoint            = TGCVector3.Empty;

            foreach (var obstaculoBB in obstaculos)
            {
                //Obtener los polígonos que conforman las 6 caras del BoundingBox
                var bbFaces = obstaculoBB.computeFaces();

                foreach (var bbFace in bbFaces)
                {
                    var pNormal = TgcCollisionUtils.getPlaneNormal(bbFace.Plane);

                    var        movementRay = new TgcRay(originalSphereCenter, movementVector);
                    float      brutePlaneDist;
                    TGCVector3 brutePlaneIntersectionPoint;
                    if (
                        !TgcCollisionUtils.intersectRayPlane(movementRay, bbFace.Plane, out brutePlaneDist,
                                                             out brutePlaneIntersectionPoint))
                    {
                        continue;
                    }

                    var movementRadiusLengthSq = TGCVector3.Multiply(movementVector, characterSphere.Radius).LengthSq();
                    if (brutePlaneDist * brutePlaneDist > movementRadiusLengthSq)
                    {
                        continue;
                    }

                    //Obtener punto de colisión en el plano, según la normal del plano
                    float      pDist;
                    TGCVector3 planeIntersectionPoint;
                    TGCVector3 sphereIntersectionPoint;
                    var        planeNormalRay = new TgcRay(originalSphereCenter, -pNormal);
                    var        embebbed       = false;
                    var        collisionFound = false;
                    if (TgcCollisionUtils.intersectRayPlane(planeNormalRay, bbFace.Plane, out pDist,
                                                            out planeIntersectionPoint))
                    {
                        //Ver si el plano está embebido en la esfera
                        if (pDist <= characterSphere.Radius)
                        {
                            embebbed = true;

                            //TODO: REVISAR ESTO, caso embebido a analizar con más detalle
                            sphereIntersectionPoint = originalSphereCenter - pNormal * characterSphere.Radius;
                        }
                        //Esta fuera de la esfera
                        else
                        {
                            //Obtener punto de colisión del contorno de la esfera según la normal del plano
                            sphereIntersectionPoint = originalSphereCenter -
                                                      TGCVector3.Multiply(pNormal, characterSphere.Radius);

                            //Disparar un rayo desde el contorno de la esfera hacia el plano, con el vector de movimiento
                            var sphereMovementRay = new TgcRay(sphereIntersectionPoint, movementVector);
                            if (
                                !TgcCollisionUtils.intersectRayPlane(sphereMovementRay, bbFace.Plane, out pDist,
                                                                     out planeIntersectionPoint))
                            {
                                //no hay colisión
                                continue;
                            }
                        }

                        //Ver si planeIntersectionPoint pertenece al polígono
                        TGCVector3 newMovementVector;
                        float      newMoveDistSq;
                        TGCVector3 polygonIntersectionPoint;
                        if (pointInBounbingBoxFace(planeIntersectionPoint, bbFace))
                        {
                            if (embebbed)
                            {
                                //TODO: REVISAR ESTO, nunca debería pasar
                                //throw new Exception("El polígono está dentro de la esfera");
                            }

                            polygonIntersectionPoint = planeIntersectionPoint;
                            collisionFound           = true;
                        }
                        else
                        {
                            //Buscar el punto mas cercano planeIntersectionPoint que tiene el polígono real de esta cara
                            polygonIntersectionPoint = TgcCollisionUtils.closestPointRectangle3d(planeIntersectionPoint,
                                                                                                 bbFace.Extremes[0], bbFace.Extremes[1], bbFace.Extremes[2]);

                            //Revertir el vector de velocidad desde el nuevo polygonIntersectionPoint para ver donde colisiona la esfera, si es que llega
                            var reversePointSeg = polygonIntersectionPoint - movementVector;
                            if (TgcCollisionUtils.intersectSegmentSphere(polygonIntersectionPoint, reversePointSeg,
                                                                         characterSphere, out pDist, out sphereIntersectionPoint))
                            {
                                collisionFound = true;
                            }
                        }

                        if (collisionFound)
                        {
                            //Nuevo vector de movimiento acotado
                            newMovementVector = polygonIntersectionPoint - sphereIntersectionPoint;
                            newMoveDistSq     = newMovementVector.LengthSq();

                            if (newMoveDistSq <= distanceToTravelSq && newMoveDistSq < minCollisionDistSq)
                            {
                                minCollisionDistSq = newMoveDistSq;
                                realMovementVector = newMovementVector;
                                nearestPolygonIntersectionPoint = polygonIntersectionPoint;
                                collisionFace     = bbFace;
                                collisionObstacle = obstaculoBB;
                            }
                        }
                    }
                }
            }

            //Si nunca hubo colisión, avanzar todo lo requerido
            if (collisionFace == null)
            {
                //Avanzar hasta muy cerca
                var movementLength = movementVector.Length();
                movementVector.Multiply((movementLength - EPSILON) / movementLength);
                characterSphere.moveCenter(movementVector);
                return;
            }

            //Solo movernos si ya no estamos muy cerca
            if (minCollisionDistSq >= EPSILON)
            {
                //Mover el BoundingSphere hasta casi la nueva posición real
                var movementLength = realMovementVector.Length();
                realMovementVector.Multiply((movementLength - EPSILON) / movementLength);
                characterSphere.moveCenter(realMovementVector);
            }

            //Calcular plano de Sliding
            var slidePlaneOrigin = nearestPolygonIntersectionPoint;
            var slidePlaneNormal = characterSphere.Center - nearestPolygonIntersectionPoint;

            slidePlaneNormal.Normalize();

            var slidePlane = TGCPlane.FromPointNormal(slidePlaneOrigin, slidePlaneNormal);

            //Proyectamos el punto original de destino en el plano de sliding
            var slideRay = new TgcRay(nearestPolygonIntersectionPoint + TGCVector3.Multiply(movementVector, SlideFactor),
                                      slidePlaneNormal);
            float      slideT;
            TGCVector3 slideDestinationPoint;

            if (TgcCollisionUtils.intersectRayPlane(slideRay, slidePlane, out slideT, out slideDestinationPoint))
            {
                //Nuevo vector de movimiento
                var slideMovementVector = slideDestinationPoint - nearestPolygonIntersectionPoint;

                if (slideMovementVector.LengthSq() < EPSILON)
                {
                    return;
                }

                //Recursividad para aplicar sliding
                doCollideWithWorld(characterSphere, slideMovementVector, obstaculos, recursionDepth + 1);
            }
        }