Exemplo n.º 1
0
        public void deformarMesh(TgcObb obbColisionable, float velocidad)
        {
            object vertexBuffer = null;
            Type   tipo;
            float  distanciaMinima;
            float  factorChoque = Math.Abs(velocidad) * this.masa * 0.001F;

            switch (this.mesh.RenderType)
            {
            case TgcMesh.MeshRenderType.VERTEX_COLOR:
                vertexBuffer = (TgcSceneLoader.VertexColorVertex[]) this.mesh.D3dMesh.LockVertexBuffer(
                    typeof(TgcSceneLoader.VertexColorVertex), LockFlags.ReadOnly, this.mesh.D3dMesh.NumberVertices);

                break;

            case TgcMesh.MeshRenderType.DIFFUSE_MAP:
                vertexBuffer = (TgcSceneLoader.DiffuseMapVertex[]) this.mesh.D3dMesh.LockVertexBuffer(
                    typeof(TgcSceneLoader.DiffuseMapVertex), LockFlags.ReadOnly, this.mesh.D3dMesh.NumberVertices);

                break;

            case TgcMesh.MeshRenderType.DIFFUSE_MAP_AND_LIGHTMAP:
                vertexBuffer = (TgcSceneLoader.DiffuseMapAndLightmapVertex[]) this.mesh.D3dMesh.LockVertexBuffer(
                    typeof(TgcSceneLoader.DiffuseMapAndLightmapVertex), LockFlags.ReadOnly, this.mesh.D3dMesh.NumberVertices);

                break;
            }
            tipo = vertexBuffer.GetType();
            System.Reflection.MethodInfo dameValorPorIndice    = tipo.GetMethod("GetValue", new Type[] { typeof(int) });
            System.Reflection.MethodInfo insertaValorPorIndice = tipo.GetMethod("SetValue", new Type[] { typeof(object), typeof(int) });
            int cantidadDeVertices = (int)tipo.GetProperty("Length").GetValue(vertexBuffer, null);


            //Calculo la distancia minima entre el centro del OBB colisionado y todos los vertices del mesh
            //...parto con la distancia entre centros
            distanciaMinima  = (this.obb.Extents.Length() + obbColisionable.Extents.Length()) * 6;
            this.puntoChoque = this.obb.Center;


            Vector3[] cornersObbCoche  = computeCorners(this.obb);
            Vector3[] cornersObstaculo = computeCorners(obbColisionable);
            int       idPuntoChoque    = 0;

            for (int j = 0; j < 8; j++)
            {
                for (int i = 0; i < 8; i++)
                {
                    if (distanciaMinimaAlPlano(cornersObbCoche[i], cornersObstaculo[j]) < distanciaMinima)
                    {
                        distanciaMinima  = distanciaMinimaAlPlano(cornersObbCoche[i], cornersObstaculo[j]);
                        this.puntoChoque = cornersObbCoche[i]; // acá es donde se genera el choque!!! (es un corner del obb)
                        idPuntoChoque    = i;
                    }
                }
            }


            if (Shared.debugMode)
            {
                // ya sé donde se genera el choque... ahí voy a crear una esfera para verlo en el DebugMode
                moon.Position = this.puntoChoque;
            }

            //Armo un obb auxiliar para rotarlo a la orientación original (porque el VertexBuffer me carga los vértices sin rotar!!!)
            TgcObb obbAuxiliar = this.obb;

            obbAuxiliar.setRotation(rotacionInicial);
            Vector3[] nuevosCorners = computeCorners(obbAuxiliar);

            Vector3 puntoChoqueDeformacion = nuevosCorners[idPuntoChoque];

            // APLICO DEFORMACIÓN EN MALLA
            /// .... mientras, aprovecho para buscar al verdadero punto de choque (el otro es un corner del obb)
            distanciaMinima = (this.obb.Extents.Length() + obbColisionable.Extents.Length()) * 6;
            Vector3 verdaderoPuntoDeChoque = puntoChoque;  // lo voy a usar para las chispas!

            for (int i = 0; i < cantidadDeVertices; i++)
            {
                object  vertice          = dameValorPorIndice.Invoke(vertexBuffer, new object[] { i });
                Vector3 unVerticeDelMesh = (Vector3)vertice.GetType().GetField("Position").GetValue(vertice);
                unVerticeDelMesh += this.obb.Position;

                if (Math.Abs(distancePointPoint(unVerticeDelMesh, puntoChoqueDeformacion)) < distanciaMinima)
                {
                    distanciaMinima        = Math.Abs(distancePointPoint(unVerticeDelMesh, puntoChoqueDeformacion));
                    verdaderoPuntoDeChoque = unVerticeDelMesh;
                }

                /// voy tirando los vertices al centro del mesh
                if (Math.Abs(distancePointPoint(unVerticeDelMesh, puntoChoqueDeformacion)) < factorChoque)
                {
                    float   factorDeformacion       = factorChoque * 0.1f;
                    Vector3 vectorDondeMoverElPunto = unVerticeDelMesh - puntoChoqueDeformacion;
                    //vectorDondeMoverElPunto.Z = unVerticeDelMesh.Z; // fuerzo al plano Z para que no pasen cosas raras
                    //corro de lugar el vértice del mesh, usando el versor del vector
                    unVerticeDelMesh += factorDeformacion * Vector3.Normalize(vectorDondeMoverElPunto);

                    //restauro como estaba antes, sino guardo cqcosa
                    unVerticeDelMesh -= this.obb.Position;
                    vertice.GetType().GetField("Position").SetValue(vertice, unVerticeDelMesh);
                    insertaValorPorIndice.Invoke(vertexBuffer, new object[] { vertice, i });
                }
            }
            this.mesh.D3dMesh.SetVertexBufferData(vertexBuffer, LockFlags.None);
            this.mesh.D3dMesh.UnlockVertexBuffer();
            // FIN DEFORMACIÓN

            //Mientras más se deforma, más se reduce su velocidad máxima
            this.velocidadMaxima -= factorChoque * 0.5f;

            //Ahora vienen las CHISPAS
            int k   = 0;
            int cte = chispas.Count * 4;

            foreach (Chispa chispa in this.chispas)
            {
                chispa.mesh.Position = verdaderoPuntoDeChoque;
                chispa.asignarDireccion(puntoChoque, verdaderoPuntoDeChoque, new Vector3(k * cte, k * cte, k * cte));
                chispa.tiempoChispas = factorChoque * 5;
                k++;
            }
        }