Exemplo n.º 1
0
        /// <summary>
        /// Construye la grilla
        /// </summary>
        private GrillaRegularNode[, ,] buildGrid(List<TgcMesh> modelos, TgcBoundingBox sceneBounds, Vector3 cellDim)
        {
            Vector3 sceneSize = sceneBounds.calculateSize();

            int gx = (int)FastMath.Ceiling(sceneSize.X / cellDim.X) + 1;
            int gy = (int)FastMath.Ceiling(sceneSize.Y / cellDim.Y) + 1;
            int gz = (int)FastMath.Ceiling(sceneSize.Z / cellDim.Z) + 1;

            GrillaRegularNode[, ,] grid = new GrillaRegularNode[gx, gy, gz];

            //Construir grilla
            for (int x = 0; x < gx; x++)
            {
                for (int y = 0; y < gy; y++)
                {
                    for (int z = 0; z < gz; z++)
                    {
                        //Crear celda
                        GrillaRegularNode node = new GrillaRegularNode();
                        
                        //Crear BoundingBox de celda
                        Vector3 pMin = new Vector3(sceneBounds.PMin.X + x * cellDim.X, sceneBounds.PMin.Y + y * cellDim.Y, sceneBounds.PMin.Z + z * cellDim.Z);
                        Vector3 pMax = Vector3.Add(pMin, cellDim);
                        node.BoundingBox = new TgcBoundingBox(pMin, pMax);

                        //Cargar modelos en celda
                        node.Models = new List<TgcMesh>();
                        addModelsToCell(node, modelos);

                        grid[x, y, z] = node;
                    }
                }
            }

            return grid;
        }
Exemplo n.º 2
0
        /// <summary>
        /// Indica si un Cilindro colisiona con un AABB.
        /// Solo indica si hay colision o no. No va mas en detalle.
        /// </summary>
        /// <param name="box">AABB</param>
        /// <param name="cylinder">Cilindro alineado</param>
        /// <returns>True si hay colision</returns>
        public static bool testAABBCylinder(TgcBoundingBox box, TgcFixedYBoundingCylinder cylinder)
        {
            //datos del aabb
            Vector3 boxCenter = box.calculateBoxCenter();
            Vector3 boxHalfSize = box.calculateSize() * 0.5f;

            //datos del cilindro
            Vector3 cylCenter = cylinder.Center;
            float cylHalfLength = cylinder.HalfLength;
            float cylRadius = cylinder.Radius;

            //vector de distancias
            Vector3 distances = new Vector3(
                FastMath.Abs(boxCenter.X - cylCenter.X),
                FastMath.Abs(boxCenter.Y - cylCenter.Y),
                FastMath.Abs(boxCenter.Z - cylCenter.Z));

            //si el aabb esta muy arriba o muy abajo no hay colision
            if (distances.Y > boxHalfSize.Y + cylHalfLength) return false;

            //si el aabb esta muy lejos en x o en z no hay colision
            if (distances.X > boxHalfSize.X + cylRadius) return false;
            if (distances.Z > boxHalfSize.Z + cylRadius) return false;

            //si el centro del cilindro esta dentro del aabb hay colision
            if (distances.X <= boxHalfSize.X) return true;
            if (distances.Z <= boxHalfSize.Z) return true;

            //si el cilindro toca alguno de los extremos hay colision
            float cornerDistanceSq =
                FastMath.Pow2(distances.X - boxHalfSize.X) +
                FastMath.Pow2(distances.Z - boxHalfSize.Z);
            return (cornerDistanceSq <= FastMath.Pow2(cylRadius));
        }
        /// <summary>
        /// Indica si existe colision con un AABB rapidamente, perdiendo precision.
        /// Eso se debe a que trata al cilindro como un cubo para ganar performance obviando colisiones raras.
        /// </summary>
        public bool fastThereIsCollisionCyBB(TgcBoundingBox aabb)
        {
            Vector3 boxDimensions = aabb.calculateSize() * 0.5f;
            Vector3 boxCenter = aabb.Position + boxDimensions;

            Vector3 centerToCenter = new Vector3(this.Position.X - boxCenter.X, 0, this.Position.Z - boxCenter.Z);
            Vector3 absCenterToCenter = new Vector3();
            absCenterToCenter.X = FastMath.Abs(centerToCenter.X);
            absCenterToCenter.Z = FastMath.Abs(centerToCenter.Z);

            //vemos si esta muy lejos
            if (absCenterToCenter.X > (boxDimensions.X + this.radius)) return false;
            if (absCenterToCenter.Z > (boxDimensions.Z + this.radius)) return false;

            return true;
        }
        /// <summary>
        /// Indica si existe colision con un AABB. En tal caso devuelve la normal de colision.
        /// </summary>
        public bool thereIsCollisionCyBB(TgcBoundingBox aabb, out Vector3 n)
        {
            n = Vector3.Empty;

            Vector3 boxDimensions = aabb.calculateSize() * 0.5f;
            Vector3 boxCenter = aabb.Position + boxDimensions;

            Vector3 centerToCenter = new Vector3(this.Position.X - boxCenter.X, 0, this.Position.Z - boxCenter.Z);
            Vector3 absCenterToCenter = new Vector3();
            absCenterToCenter.X = FastMath.Abs(centerToCenter.X);
            absCenterToCenter.Z = FastMath.Abs(centerToCenter.Z);

            //vemos si esta muy lejos
            if (absCenterToCenter.X > (boxDimensions.X + this.radius)) return false;
            if (absCenterToCenter.Z > (boxDimensions.Z + this.radius)) return false;

            //vemos si esta dentro del aabb
            if (absCenterToCenter.X <= boxDimensions.X) goto calculateNormal;
            if (absCenterToCenter.Z <= boxDimensions.Z) goto calculateNormal;

            //vemos si toca una esquina
            float cornerDistance = FastMath.Pow2(absCenterToCenter.X - boxDimensions.X) + FastMath.Pow2(absCenterToCenter.Z - boxDimensions.Z);
            if (cornerDistance <= FastMath.Pow2(this.radius)) goto calculateNormal;

            return false;

        calculateNormal:
            Vector2 boxDimensions2d = fromVector3(boxDimensions);
            Vector2 centerToCenter2d = fromVector3(absCenterToCenter);

            float cross = Vector2.Ccw(centerToCenter2d, boxDimensions2d);

            if (cross > 0) n = new Vector3(centerToCenter.X, 0, 0);
            else if (cross < 0) n = new Vector3(0, 0, centerToCenter.Z);
            else n = new Vector3(centerToCenter.X * boxDimensions2d.Y, 0, centerToCenter.Z * boxDimensions2d.X);
            n.Normalize();
            return true;
        }