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++; } }