コード例 #1
0
        /// <summary>
        /// Dibujar el esqueleto de la malla
        /// </summary>
        protected void renderSkeletonMesh()
        {
            Device  device  = GuiController.Instance.D3dDevice;
            Vector3 ceroVec = new Vector3(0, 0, 0);

            //Dibujar huesos y joints
            for (int i = 0; i < bones.Length; i++)
            {
                TgcSkeletalBone bone = bones[i];

                //Renderizar Joint
                TgcBox jointBox = skeletonRenderJoints[i];
                jointBox.Transform = bone.MatFinal * this.transform;
                jointBox.render();

                //Modificar línea del bone
                if (bone.ParentBone != null)
                {
                    TgcLine boneLine = skeletonRenderBones[i];

                    boneLine.PStart = TgcVectorUtils.transform(ceroVec, bone.MatFinal * this.transform);
                    boneLine.PEnd   = TgcVectorUtils.transform(ceroVec, bone.ParentBone.MatFinal * this.transform);
                    boneLine.updateValues();
                }
            }

            //Dibujar bones
            foreach (TgcLine boneLine in skeletonRenderBones)
            {
                if (boneLine != null)
                {
                    boneLine.render();
                }
            }
        }
コード例 #2
0
        public static Vector3[] computeCorners(Auto auto)
        {
            TgcObb obbAuto = auto.obb;

            Vector3[] corners = new Vector3[8];
            Vector3   extents;

            Vector3[] orientation = obbAuto.Orientation;
            Vector3   center      = obbAuto.Center;

            extents = auto.mesh.BoundingBox.calculateAxisRadius();
            extents = TgcVectorUtils.abs(extents);

            Vector3 eX = extents.X * orientation[0];
            Vector3 eY = extents.Y * orientation[1];
            Vector3 eZ = extents.Z * orientation[2];

            corners[0] = center - eX - eY - eZ;
            corners[1] = center - eX - eY + eZ;

            corners[2] = center - eX + eY - eZ;
            corners[3] = center - eX + eY + eZ;

            corners[4] = center + eX - eY - eZ;
            corners[5] = center + eX - eY + eZ;

            corners[6] = center + eX + eY - eZ;
            corners[7] = center + eX + eY + eZ;

            return(corners);
        }
コード例 #3
0
        /// <summary>
        ///     Dibujar el esqueleto de la malla
        /// </summary>
        protected void renderSkeletonMesh()
        {
            var ceroVec = new Vector3(0, 0, 0);

            //Dibujar huesos y joints
            for (var i = 0; i < bones.Length; i++)
            {
                var bone = bones[i];

                //Renderizar Joint
                var jointBox = skeletonRenderJoints[i];
                jointBox.Transform = bone.MatFinal * transform;
                jointBox.render();

                //Modificar línea del bone
                if (bone.ParentBone != null)
                {
                    var boneLine = skeletonRenderBones[i];

                    boneLine.PStart = TgcVectorUtils.transform(ceroVec, bone.MatFinal * transform);
                    boneLine.PEnd   = TgcVectorUtils.transform(ceroVec, bone.ParentBone.MatFinal * transform);
                    boneLine.updateValues();
                }
            }

            //Dibujar bones
            foreach (var boneLine in skeletonRenderBones)
            {
                if (boneLine != null)
                {
                    boneLine.render();
                }
            }
        }
コード例 #4
0
ファイル: MeshPrimitive.cs プロジェクト: nicoschtein/TGC2014
        /// <summary>
        /// Transformar fisicamente los vertices del mesh segun su transformacion actual
        /// </summary>
        private void applyMeshTransformToVertices(TgcMesh m)
        {
            //Transformacion actual
            Matrix transform = Matrix.Scaling(m.Scale)
                               * Matrix.RotationYawPitchRoll(m.Rotation.Y, m.Rotation.X, m.Rotation.Z)
                               * Matrix.Translation(m.Position);

            switch (m.RenderType)
            {
            case TgcMesh.MeshRenderType.VERTEX_COLOR:
                TgcSceneLoader.VertexColorVertex[] verts1 = (TgcSceneLoader.VertexColorVertex[])m.D3dMesh.LockVertexBuffer(
                    typeof(TgcSceneLoader.VertexColorVertex), LockFlags.ReadOnly, m.D3dMesh.NumberVertices);
                for (int i = 0; i < verts1.Length; i++)
                {
                    verts1[i].Position = TgcVectorUtils.transform(verts1[i].Position, transform);
                }
                m.D3dMesh.SetVertexBufferData(verts1, LockFlags.None);
                m.D3dMesh.UnlockVertexBuffer();
                break;

            case TgcMesh.MeshRenderType.DIFFUSE_MAP:
                TgcSceneLoader.DiffuseMapVertex[] verts2 = (TgcSceneLoader.DiffuseMapVertex[])m.D3dMesh.LockVertexBuffer(
                    typeof(TgcSceneLoader.DiffuseMapVertex), LockFlags.ReadOnly, m.D3dMesh.NumberVertices);
                for (int i = 0; i < verts2.Length; i++)
                {
                    verts2[i].Position = TgcVectorUtils.transform(verts2[i].Position, transform);
                }
                m.D3dMesh.SetVertexBufferData(verts2, LockFlags.None);
                m.D3dMesh.UnlockVertexBuffer();
                break;

            case TgcMesh.MeshRenderType.DIFFUSE_MAP_AND_LIGHTMAP:
                TgcSceneLoader.DiffuseMapAndLightmapVertex[] verts3 = (TgcSceneLoader.DiffuseMapAndLightmapVertex[])m.D3dMesh.LockVertexBuffer(
                    typeof(TgcSceneLoader.DiffuseMapAndLightmapVertex), LockFlags.ReadOnly, m.D3dMesh.NumberVertices);
                for (int i = 0; i < verts3.Length; i++)
                {
                    verts3[i].Position = TgcVectorUtils.transform(verts3[i].Position, transform);
                }
                m.D3dMesh.SetVertexBufferData(verts3, LockFlags.None);
                m.D3dMesh.UnlockVertexBuffer();
                break;
            }

            //Quitar movimientos del mesh
            m.Position            = new Vector3(0, 0, 0);
            m.Scale               = new Vector3(1, 1, 1);
            m.Rotation            = new Vector3(0, 0, 0);
            m.Transform           = Matrix.Identity;
            m.AutoTransformEnable = true;

            //Calcular nuevo bounding box
            m.createBoundingBox();
        }
コード例 #5
0
        /// <summary>
        ///     Colisiona un Elipsoide en movimiento contra un conjunto de triangulos.
        ///     Si hay colision devuelve el instante t de colision, el punto q de colision y el vector normal n de la superficie
        ///     contra la que
        ///     se colisiona.
        ///     Todo se devuelve en Elipsoid space.
        ///     Pasa cada triangulo a Elipsoid space para hacer el testeo.
        /// </summary>
        /// <param name="eSphere">BoundingSphere de radio 1 en Elipsoid space</param>
        /// <param name="eMovementVector">movimiento en Elipsoid space</param>
        /// <param name="eRadius">radio del Elipsoide</param>
        /// <param name="movementSphere">
        ///     BoundingSphere que abarca el sphere en su punto de origen mas el sphere en su punto final
        ///     deseado
        /// </param>
        /// <param name="minT">Menor instante de colision, en Elipsoid space</param>
        /// <param name="minQ">Punto mas cercano de colision, en Elipsoid space</param>
        /// <param name="n">Vector normal de la superficie contra la que se colisiona</param>
        /// <returns>True si hay colision</returns>
        public override bool intersectMovingElipsoid(TgcBoundingSphere eSphere, Vector3 eMovementVector, Vector3 eRadius,
                                                     TgcBoundingSphere movementSphere, out float minT, out Vector3 minQ, out Vector3 n)
        {
            minQ = Vector3.Empty;
            minT = float.MaxValue;
            n    = Vector3.Empty;
            var collisionPlane = Plane.Empty;

            //Colision contra cada triangulo del collider, quedarse con el menor
            Vector3 q;
            float   t;

            for (var i = 0; i < Triangles.Length; i++)
            {
                var triangle = Triangles[i];

                //Primero hacer un Sphere-Sphere test
                if (TgcCollisionUtils.testSphereSphere(movementSphere, triangle.BoundingSphere))
                {
                    //Pasar triangle a Elipsoid Space
                    var eTriangle = new Triangle(
                        TgcVectorUtils.div(triangle.A, eRadius),
                        TgcVectorUtils.div(triangle.B, eRadius),
                        TgcVectorUtils.div(triangle.C, eRadius),
                        null
                        );

                    //Interseccion Moving Sphere-Triangle
                    if (intersectMovingSphereTriangle(eSphere, eMovementVector, eTriangle, out t, out q))
                    {
                        if (t < minT)
                        {
                            minT           = t;
                            minQ           = q;
                            collisionPlane = triangle.Plane;
                        }
                    }
                }
            }

            if (minT != float.MaxValue)
            {
                n = TgcCollisionUtils.getPlaneNormal(collisionPlane);
                return(true);
            }

            return(false);
        }
コード例 #6
0
        /// <summary>
        ///     Mover Elipsoide con detección de colisiones, sliding y gravedad.
        ///     Se actualiza la posición del centro del Elipsoide
        /// </summary>
        /// <param name="characterElipsoid">Elipsoide del cuerpo a mover</param>
        /// <param name="movementVector">Movimiento a realizar</param>
        /// <param name="colliders">Obstáculos contra los cuales se puede colisionar</param>
        /// <returns>Desplazamiento relativo final efecutado al Elipsoide</returns>
        public Vector3 moveCharacter(TgcBoundingElipsoid characterElipsoid, Vector3 movementVector, List <Collider> colliders)
        {
            //Guardar posicion original del Elipsoide
            var originalElipsoidCenter = characterElipsoid.Center;

            //Pasar elipsoid space
            var eCenter         = TgcVectorUtils.div(characterElipsoid.Center, characterElipsoid.Radius);
            var eMovementVector = TgcVectorUtils.div(movementVector, characterElipsoid.Radius);

            eSphere.setValues(eCenter, 1);
            var eOrigCenter = eSphere.Center;

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

            if (distanceToTravelSq >= EPSILON)
            {
                //Mover la distancia pedida
                selectPotentialColliders(characterElipsoid, movementVector, colliders);
                result = doCollideWithWorld(eSphere, eMovementVector, characterElipsoid.Radius, objetosCandidatos, 0,
                                            movementSphere, 1);
            }

            //Aplicar gravedad
            if (GravityEnabled)
            {
                //Mover con gravedad
                var eGravity = TgcVectorUtils.div(GravityForce, characterElipsoid.Radius);
                selectPotentialColliders(characterElipsoid, eGravity, colliders);
                result = doCollideWithWorld(eSphere, eGravity, characterElipsoid.Radius, objetosCandidatos, 0,
                                            movementSphere, OnGroundMinDotValue);
            }

            //Mover Elipsoid pasando valores de colision a R3
            var movement = TgcVectorUtils.mul(eSphere.Center - eOrigCenter, characterElipsoid.Radius);

            characterElipsoid.moveCenter(movement);

            //Ajustar resultados
            result.realMovmentVector = TgcVectorUtils.mul(result.realMovmentVector, characterElipsoid.Radius);
            result.collisionPoint    = TgcVectorUtils.mul(result.collisionPoint, characterElipsoid.Radius);

            return(movement);
        }
コード例 #7
0
        /// <summary>
        ///     Transforma el BondingBox en base a una matriz de transformación.
        ///     Esto implica escalar, rotar y trasladar.
        ///     El procedimiento es mas costoso que solo hacer scaleTranslate().
        ///     Se construye un nuevo BoundingBox en base a los puntos extremos del original
        ///     más la transformación pedida.
        ///     Si el BoundingBox se transformó y luego se llama a scaleTranslate(), se respeta
        ///     la traslación y la escala, pero la rotación se va a perder.
        /// </summary>
        /// <param name="transform"></param>
        public void transform(Matrix transform)
        {
            //Transformar vertices extremos originales
            var corners    = computeCorners(pMinOriginal, pMaxOriginal);
            var newCorners = new Vector3[corners.Length];

            for (var i = 0; i < corners.Length; i++)
            {
                newCorners[i] = TgcVectorUtils.transform(corners[i], transform);
            }

            //Calcular nuevo BoundingBox en base a extremos transformados
            var newBB = computeFromPoints(newCorners);

            //actualizar solo pMin y pMax, pMinOriginal y pMaxOriginal quedan sin ser transformados
            pMin = newBB.pMin;
            pMax = newBB.pMax;

            dirtyValues = true;
        }
コード例 #8
0
        /// <summary>
        /// Crea mallas a modo Debug para visualizar la configuración del esqueleto
        /// </summary>
        public void buildSkletonMesh()
        {
            //Crear array para dibujar los huesos y joints
            Color   jointsColor = Color.Violet;
            Color   bonesColor  = Color.Yellow;
            Vector3 jointsSize  = new Vector3(2, 2, 2);
            Vector3 ceroVec     = new Vector3(0, 0, 0);

            skeletonRenderJoints = new TgcBox[bones.Length];
            skeletonRenderBones  = new TgcLine[bones.Length];
            int boneColor = Color.Yellow.ToArgb();

            //Actualizar jerarquia
            for (int i = 0; i < bones.Length; i++)
            {
                TgcSkeletalBone bone = bones[i];

                //Es hijo o padre
                if (bone.ParentBone == null)
                {
                    skeletonRenderBones[i] = null;
                }
                else
                {
                    //Crear linea de hueso para renderziar esqueleto
                    TgcLine boneLine = new TgcLine();
                    boneLine.PStart        = TgcVectorUtils.transform(ceroVec, bone.MatFinal);
                    boneLine.PEnd          = TgcVectorUtils.transform(ceroVec, bone.ParentBone.MatFinal);
                    boneLine.Color         = bonesColor;
                    skeletonRenderBones[i] = boneLine;
                }
                //Crear malla de Joint para renderizar el esqueleto
                TgcBox jointBox = TgcBox.fromSize(jointsSize, jointsColor);
                jointBox.AutoTransformEnable = false;
                skeletonRenderJoints[i]      = jointBox;
            }
        }
コード例 #9
0
ファイル: NaveEnemiga.cs プロジェクト: nicoschtein/TGC2014
        public void MoverHaciaObjetivo(float tiempoRenderizado, Vector3 posicionObjetivo)
        {
            if (this.Modelo.Enabled)
            {
                //Resto los dos vectores para hallar el vector distancia
                Vector3 Distancia = Vector3.Subtract(posicionObjetivo, this.Modelo.Position);

                //Otro vector, con valores absolutos para hallar la componente maxima
                Vector3 DistanciaAbs = TgcVectorUtils.abs(Distancia);

                //Calculo matriz de rotacion
                Vector3 DireccionObjetivo = Vector3.Normalize(posicionObjetivo - this.Modelo.Position);
                float   angulo            = FastMath.Acos(Vector3.Dot(RotacionOriginal, DireccionObjetivo));
                Vector3 axisRotation      = Vector3.Cross(this.Modelo.Rotation, DireccionObjetivo);
                MatrizRotacion = Matrix.RotationAxis(axisRotation, angulo);

                float cantidadDeMovimiento = this.VelocidadMovimiento * tiempoRenderizado;
                float giro = this.Modelo.Rotation.Y - angulo;
                if (giro < -0.1)
                {
                    this.Modelo.rotateY(Geometry.DegreeToRadian(-giro * 100 * tiempoRenderizado));
                    return;
                }
                else if (giro > 0.1)
                {
                    this.Modelo.rotateY(Geometry.DegreeToRadian(-giro * 100 * tiempoRenderizado));
                    return;
                }
                if (DistanciaAbs.X + DistanciaAbs.Y + DistanciaAbs.Z > 700f)
                {
                    //Hallo la componente de mayor valor y me muevo en esa direccion. VER SENTIDO.
                    if (DistanciaAbs.X >= DistanciaAbs.Y)
                    {
                        if (DistanciaAbs.X >= DistanciaAbs.Z)
                        {
                            // MOVER EN X
                            if (Distancia.X > cantidadDeMovimiento)
                            {
                                this.Modelo.move(cantidadDeMovimiento, 0, 0);
                            }
                            else
                            {
                                this.Modelo.move(cantidadDeMovimiento * -1, 0, 0);
                            }
                        }
                        else
                        {
                            // MOVER EN Z
                            if (Distancia.Z > 0)
                            {
                                this.Modelo.move(0, 0, cantidadDeMovimiento);
                            }
                            else
                            {
                                this.Modelo.move(0, 0, cantidadDeMovimiento * -1);
                            }
                        }
                    }
                    else
                    {
                        if (DistanciaAbs.Y >= DistanciaAbs.Z)
                        {
                            // MOVER EN Y
                            if (Distancia.Y > 0)
                            {
                                this.Modelo.move(0, cantidadDeMovimiento, 0);
                            }
                            else
                            {
                                this.Modelo.move(0, cantidadDeMovimiento * -1, 0);
                            }
                        }
                        else
                        {
                            // MOVER EN Z
                            if (Distancia.Z > 0)
                            {
                                this.Modelo.move(0, 0, cantidadDeMovimiento);
                            }
                            else
                            {
                                this.Modelo.move(0, 0, cantidadDeMovimiento * -1);
                            }
                        }
                    }
                }
                else
                {
                    //Disparar. Tambien deberia rotar para que el disparo vaya bien

                    if (TiempoParado == 0 || TiempoParado >= TiempoRecarga)
                    {
                        Disparo disparo = new Disparo(this.Modelo, MatrizRotacion);
                        Disparos.Add(disparo);
                        TiempoParado = 0f;
                    }
                    TiempoParado = TiempoParado + tiempoRenderizado * 4;
                }
            }
        }
コード例 #10
0
        /// <summary>
        ///     Colisiona un Elipsoide en movimiento contra el BoundingBox.
        ///     Si hay colision devuelve el instante t de colision, el punto q de colision y el vector normal n de la superficie
        ///     contra la que
        ///     se colisiona.
        ///     Todo se devuelve en Elipsoid space.
        ///     El BoundingBox se pasa a Elipsoid space para comparar.
        /// </summary>
        /// <param name="eSphere">BoundingSphere de radio 1 en Elipsoid space</param>
        /// <param name="eMovementVector">movimiento en Elipsoid space</param>
        /// <param name="eRadius">radio del Elipsoide</param>
        /// <param name="movementSphere">
        ///     BoundingSphere que abarca el sphere en su punto de origen mas el sphere en su punto final
        ///     deseado
        /// </param>
        /// <param name="t">Menor instante de colision, en Elipsoid space</param>
        /// <param name="q">Punto mas cercano de colision, en Elipsoid space</param>
        /// <param name="n">Vector normal de la superficie contra la que se colisiona</param>
        /// <returns>True si hay colision</returns>
        public override bool intersectMovingElipsoid(TgcBoundingSphere eSphere, Vector3 eMovementVector, Vector3 eRadius,
                                                     TgcBoundingSphere movementSphere, out float t, out Vector3 q, out Vector3 n)
        {
            //Pasar AABB a Elipsoid Space
            eAABB.setExtremes(
                TgcVectorUtils.div(Aabb.PMin, eRadius),
                TgcVectorUtils.div(Aabb.PMax, eRadius)
                );

            t = -1f;
            q = Vector3.Empty;
            n = Vector3.Empty;

            // Compute the AABB resulting from expanding b by sphere radius r
            var e = eAABB.toStruct();

            e.min.X -= eSphere.Radius;
            e.min.Y -= eSphere.Radius;
            e.min.Z -= eSphere.Radius;
            e.max.X += eSphere.Radius;
            e.max.Y += eSphere.Radius;
            e.max.Z += eSphere.Radius;

            // Intersect ray against expanded AABB e. Exit with no intersection if ray
            // misses e, else get intersection point p and time t as result
            Vector3 p;
            var     ray = new TgcRay.RayStruct();

            ray.origin    = eSphere.Center;
            ray.direction = eMovementVector;
            if (!intersectRayAABB(ray, e, out t, out p) || t > 1.0f)
            {
                return(false);
            }

            // Compute which min and max faces of b the intersection point p lies
            // outside of. Note, u and v cannot have the same bits set and
            // they must have at least one bit set among them
            var i    = 0;
            var sign = new int[3];

            if (p.X < eAABB.PMin.X)
            {
                sign[0] = -1;
                i++;
            }
            if (p.X > eAABB.PMax.X)
            {
                sign[0] = 1;
                i++;
            }
            if (p.Y < eAABB.PMin.Y)
            {
                sign[1] = -1;
                i++;
            }
            if (p.Y > eAABB.PMax.Y)
            {
                sign[1] = 1;
                i++;
            }
            if (p.Z < eAABB.PMin.Z)
            {
                sign[2] = -1;
                i++;
            }
            if (p.Z > eAABB.PMax.Z)
            {
                sign[2] = 1;
                i++;
            }

            //Face
            if (i == 1)
            {
                n = new Vector3(sign[0], sign[1], sign[2]);
                q = eSphere.Center + t * eMovementVector - eSphere.Radius * n;
                return(true);
            }

            // Define line segment [c, c+d] specified by the sphere movement
            var seg = new Segment(eSphere.Center, eSphere.Center + eMovementVector);

            //Box extent and center
            var extent = eAABB.calculateAxisRadius();
            var center = eAABB.PMin + extent;

            //Edge
            if (i == 2)
            {
                //Generar los dos puntos extremos del Edge
                float[] extentDir = { sign[0], sign[1], sign[2] };
                var     zeroIndex = sign[0] == 0 ? 0 : (sign[1] == 0 ? 1 : 2);
                extentDir[zeroIndex] = 1;
                var capsuleA = center + new Vector3(extent.X * extentDir[0], extent.Y * extentDir[1], extent.Z * extentDir[2]);
                extentDir[zeroIndex] = -1;
                var capsuleB = center + new Vector3(extent.X * extentDir[0], extent.Y * extentDir[1], extent.Z * extentDir[2]);

                //Colision contra el Edge hecho Capsula
                if (intersectSegmentCapsule(seg, new Capsule(capsuleA, capsuleB, eSphere.Radius), out t))
                {
                    n = new Vector3(sign[0], sign[1], sign[2]);
                    n.Normalize();
                    q = eSphere.Center + t * eMovementVector - eSphere.Radius * n;
                    return(true);
                }
            }

            //Vertex
            if (i == 3)
            {
                var     tmin     = float.MaxValue;
                var     capsuleA = center + new Vector3(extent.X * sign[0], extent.Y * sign[1], extent.Z * sign[2]);
                Vector3 capsuleB;

                capsuleB = center + new Vector3(extent.X * -sign[0], extent.Y * sign[1], extent.Z * sign[2]);
                if (intersectSegmentCapsule(seg, new Capsule(capsuleA, capsuleB, eSphere.Radius), out t))
                {
                    tmin = TgcCollisionUtils.min(t, tmin);
                }

                capsuleB = center + new Vector3(extent.X * sign[0], extent.Y * -sign[1], extent.Z * sign[2]);
                if (intersectSegmentCapsule(seg, new Capsule(capsuleA, capsuleB, eSphere.Radius), out t))
                {
                    tmin = TgcCollisionUtils.min(t, tmin);
                }

                capsuleB = center + new Vector3(extent.X * sign[0], extent.Y * sign[1], extent.Z * -sign[2]);
                if (intersectSegmentCapsule(seg, new Capsule(capsuleA, capsuleB, eSphere.Radius), out t))
                {
                    tmin = TgcCollisionUtils.min(t, tmin);
                }

                if (tmin == float.MaxValue)
                {
                    return(false);                        // No intersection
                }
                t = tmin;
                n = new Vector3(sign[0], sign[1], sign[2]);
                n.Normalize();
                q = eSphere.Center + t * eMovementVector - eSphere.Radius * n;
                return(true); // Intersection at time t == tmin
            }

            return(false);
        }
コード例 #11
0
        /// <summary>
        ///     Calcular OBB a partir de un conjunto de puntos.
        ///     Prueba todas las orientaciones entre initValues y endValues, saltando de angulo en cada intervalo segun step
        ///     Continua recursivamente hasta llegar a un step menor a 0.01f
        /// </summary>
        /// <returns></returns>
        private static OBBStruct computeFromPointsRecursive(Vector3[] points, Vector3 initValues, Vector3 endValues,
                                                            float step)
        {
            var   minObb = new OBBStruct();
            var   minVolume = float.MaxValue;
            var   minInitValues = Vector3.Empty;
            var   minEndValues = Vector3.Empty;
            var   transformedPoints = new Vector3[points.Length];
            float x, y, z;

            x = initValues.X;
            while (x <= endValues.X)
            {
                y = initValues.Y;
                var rotX = FastMath.ToRad(x);
                while (y <= endValues.Y)
                {
                    z = initValues.Z;
                    var rotY = FastMath.ToRad(y);
                    while (z <= endValues.Z)
                    {
                        //Matriz de rotacion
                        var       rotZ        = FastMath.ToRad(z);
                        var       rotM        = Matrix.RotationYawPitchRoll(rotY, rotX, rotZ);
                        Vector3[] orientation =
                        {
                            new Vector3(rotM.M11, rotM.M12, rotM.M13),
                            new Vector3(rotM.M21, rotM.M22, rotM.M23),
                            new Vector3(rotM.M31, rotM.M32, rotM.M33)
                        };

                        //Transformar todos los puntos a OBB-space
                        for (var i = 0; i < transformedPoints.Length; i++)
                        {
                            transformedPoints[i].X = Vector3.Dot(points[i], orientation[0]);
                            transformedPoints[i].Y = Vector3.Dot(points[i], orientation[1]);
                            transformedPoints[i].Z = Vector3.Dot(points[i], orientation[2]);
                        }

                        //Obtener el AABB de todos los puntos transformados
                        var aabb = TgcBoundingBox.computeFromPoints(transformedPoints);

                        //Calcular volumen del AABB
                        var extents = aabb.calculateAxisRadius();
                        extents = TgcVectorUtils.abs(extents);
                        var volume = extents.X * 2 * extents.Y * 2 * extents.Z * 2;

                        //Buscar menor volumen
                        if (volume < minVolume)
                        {
                            minVolume     = volume;
                            minInitValues = new Vector3(x, y, z);
                            minEndValues  = new Vector3(x + step, y + step, z + step);

                            //Volver centro del AABB a World-space
                            var center = aabb.calculateBoxCenter();
                            center = center.X * orientation[0] + center.Y * orientation[1] + center.Z * orientation[2];

                            //Crear OBB
                            minObb.center      = center;
                            minObb.extents     = extents;
                            minObb.orientation = orientation;
                        }

                        z += step;
                    }
                    y += step;
                }
                x += step;
            }

            //Recursividad en mejor intervalo encontrado
            if (step > 0.01f)
            {
                minObb = computeFromPointsRecursive(points, minInitValues, minEndValues, step / 10f);
            }

            return(minObb);
        }