/* * $Id: mesh.cpp,v 1.14 2002/07/19 20:08:28 msell Exp $ * * * $Log: mesh.cpp,v $ * Revision 1.14 2002/07/19 20:08:28 msell * Linux-porttausta * * Revision 1.13 2002/07/15 15:22:08 msell * Parantelua * * Revision 1.12 2002/07/14 21:40:43 msell * Conflictit pois, liikkumiset (hyppy, kävely, lyönti), uusi areena * * Revision 1.11 2002/07/14 21:22:39 jkaarlas * skybox ja ukkojen säätö * * Revision 1.10 2002/07/10 22:22:53 msell * Cartoon-rendaus * * Revision 1.9 2002/07/10 22:10:32 jkaarlas * skaalatut ja käännellyt ruumiinosat * * Revision 1.8 2002/07/10 17:13:44 msell * Törmäystarkastelun parantelua * * Revision 1.7 2002/07/07 17:53:21 msell * Legoukon alku * * Revision 1.6 2002/07/07 15:29:07 msell * Törmäyksien parantelua * * Revision 1.5 2002/07/04 21:05:41 msell * Se toimii!! =) * Törmäystarkistukset siis * * Revision 1.4 2002/06/30 16:05:04 msell * Törmäyksien parantelua, transformaatioita mukana * * Revision 1.3 2002/06/26 22:30:29 jkaarlas * lisätty Vertexiin tekstuurikoordinaatit * * Revision 1.2 2002/06/24 14:12:15 msell * Nyt toimii sphere -> mesh -törmäykset, ihan tosi * * Revision 1.1 2002/06/20 22:50:12 msell * Meshit * * * * $Date: 2002/07/19 20:08:28 $ * */ #include "main.h" #include "mesh.h" #include "vector.h" #include "sphere.h" #include "collision.h" #include "audio.h" #include #include "glapi.h" Vertex::Vertex(void){ vectorSet(position, 0, 0, 0); vectorSet(normal, 0, 0, 0); } Vertex::Vertex(float x, float y, float z){ vectorSet(position, x, y, z); vectorSet(normal, x, y, z); vectorNormalize(normal); } Vertex::Vertex(float x, float y, float z, float nx, float ny, float nz){ vectorSet(position, x, y, z); vectorSet(normal, nx, ny, nz); } void Vertex::setTexCoords(float u, float v){ this->texcoords[0] = u; this->texcoords[1] = v; } Polygon::Polygon(void){ vertexcount = 0; edgecount = 0; smooth = false; realsmooth = false; } Mesh::Mesh(void){ vertexcount = 0; polygoncount = 0; edgecount = 0; } Mesh::~Mesh(void){ delete [] polygons; delete [] vertices; } void Mesh::createPlanes(void){ int i; for (i = 0; i < polygoncount; i++){ class Polygon *polygon = &this->polygons[i]; if (polygon->vertexcount >= 3){ float v1[3], v2[3]; vectorSub(v1, polygon->vertices[1]->position, polygon->vertices[0]->position); vectorSub(v2, polygon->vertices[2]->position, polygon->vertices[0]->position); vectorCross(polygon->planenormal, v1, v2); vectorNormalize(polygon->planenormal); polygon->planedistance = -vectorDot(polygon->vertices[0]->position, polygon->planenormal); } } } void Mesh::createVertexnormals(void){ int i, j, ii; bool connect; float normal[3]; for (i = 0; i < vertexcount; i++){ bool found = false; vectorSet(normal, 0, 0, 0); for (j = 0; j < polygoncount; j++){ connect = false; class Polygon *polygon = &polygons[j]; for (ii = 0;ii < polygon->vertexcount; ii++){ if (polygons[j].vertices[ii] == &(vertices[i])){ connect = true; } } if (connect){ vectorAdd(normal, polygon->planenormal); found = true; } } if (found){ vectorNormalize(vertices[i].normal, normal); } } for (j = 0; j < polygoncount; j++){ class Polygon *polygon = &polygons[j]; if (!polygon->realsmooth) polygon->smooth = true; } } void Mesh::createEdges(void){ int maxedgecount = 0; int i; for (i = 0; i < polygoncount; i++){ class Polygon *polygon = &polygons[i]; maxedgecount += polygon->vertexcount; } edgecount = 0; int j, k; Edge *edges = new Edge[maxedgecount]; for (i = 0; i < polygoncount; i++){ class Polygon *polygon = &polygons[i]; polygon->edges = new Edge *[polygon->vertexcount]; for (j = 1; j <= polygon->vertexcount; j++){ Vertex *v1 = polygon->vertices[j-1]; Vertex *v2 = polygon->vertices[j%polygon->vertexcount]; bool found = false; for (k = 0; k < edgecount; k++){ if (edges[k].v2 == v1 && edges[k].v1 == v2){ found = true; edges[k].p2 = polygon; break; } } if (!found){ edges[edgecount].v1 = v1; edges[edgecount].v2 = v2; edges[edgecount].p1 = polygon; edges[edgecount].p2 = NULL; edgecount++; } } } this->edges = new Edge[edgecount]; //printf("%i\n", edgecount); for (i = 0; i < edgecount; i++){ this->edges[i].v1 = edges[i].v1; this->edges[i].v2 = edges[i].v2; this->edges[i].p1 = edges[i].p1; this->edges[i].p2 = edges[i].p2; class Polygon *p; p = edges[i].p1; p->edges[p->edgecount++] = &this->edges[i]; p = edges[i].p2; p->edges[p->edgecount++] = &this->edges[i]; //printf("%p, %p\n", edges[i].p1, edges[i].p2); } delete[] edges; } float Mesh::calculateScale(float targetLength, int axis){ float min = 0.0; float max = 0.0; for (int i=0; i < this->vertexcount; i++){ if (this->vertices->position[axis] > max){ max = this->vertices->position[axis]; } if (this->vertices->position[axis] < min){ min = this->vertices->position[axis]; } } return fabs(targetLength / (max - min)); } /* ei toimi kunnolla kaikille objekteille (kädet ok, jalat ja torso ei) */ void Mesh::scale(float targetLength, int axis){ float newscale = this->calculateScale(targetLength, axis); this->scale(newscale); } /* ei toimi kunnolla kaikille objekteille (kädet ok, jalat ja torso ei)*/ void Mesh::scale(float scale){ for (int i=0; i < this->vertexcount; i++){ this->vertices->position[0] *= scale; this->vertices->position[1] *= scale; this->vertices->position[2] *= scale; } this->createVertexnormals(); this->createPlanes(); } MeshObject::MeshObject(Mesh *mesh){ this->mesh = mesh; this->appearance = new MeshAppearance(mesh); this->geometry = new MeshShape(this); } MeshAppearance::MeshAppearance(Mesh *mesh){ this->mesh = mesh; } void MeshAppearance::draw(void){ //glDisable(GL_CULL_FACE); glColor4fv(this->material.getColor()); this->material.enable(); int i, j; for (i = 0; i < mesh->polygoncount; i++){ class Polygon *polygon = &mesh->polygons[i]; glBegin(GL_TRIANGLE_FAN); if (!polygon->smooth) glNormal3fv(polygon->planenormal); for (j = 0; j < polygon->vertexcount; j++){ Vertex *vertex = polygon->vertices[j]; if (polygon->smooth) glNormal3fv(vertex->normal); glVertex3fv(vertex->position); } glEnd(); } glDisable(GL_DEPTH); glDisable(GL_LIGHTING); glLineWidth(5.0); glBegin(GL_LINES); for (i = 0; i < mesh->edgecount; i++){ glColor3f(0, 0, 0); glVertex3fv(mesh->edges[i].v1->position); glVertex3fv(mesh->edges[i].v2->position); } glEnd(); glEnable(GL_LIGHTING); glEnable(GL_DEPTH); this->material.disable(); //glEnable(GL_CULL_FACE); } MeshShape::MeshShape(MeshObject *object) : Shape(object){ mesh = object->mesh; } MeshShape::MeshShape(Object *object, Mesh *mesh) : Shape(object){ this->mesh = mesh; } bool MeshShape::checkCollision(Object *target){ return target->geometry->checkCollisionPeer(this); } float MeshShape::calculateMomentOfInertia(float *rotationvector){ if (vectorDot(rotationvector, rotationvector) < EPSILON) return 0; int i; float j = 0; for (i = 0; i < mesh->vertexcount; i++){ float proj[3]; vectorProject(proj, mesh->vertices[i].position, rotationvector); vectorSub(proj, mesh->vertices[i].position, proj); //float r = vectorLength(proj); float r2 = vectorDot(proj, proj); j += r2; } return j / i; } bool MeshShape::checkCollisionPeer(SphereShape *target){ float position[3] = {0, 0, 0}; target->object->transformPoint(position, position); object->unTransformPoint(position, position); float normal[3]; float contactpoint[3]; float r = target->getRadius(); if (checkSphereMeshCollision(position, r, mesh, normal, contactpoint)){ vectorScale(normal, -1); object->transformVector(normal, normal); object->transformPoint(contactpoint, contactpoint); addCollision(object, target->object, normal, contactpoint); //vectorAdd(contactnormal, normal); return true; } return false; } //extern Sound *shotsound; bool MeshShape::checkCollisionPeer(MeshShape *target){ float normal[3]; float contactpoint[3]; bool collided = false; int i; Mesh *sourcemesh, *targetmesh; sourcemesh = this->mesh; targetmesh = target->mesh; for (i = 0; i < sourcemesh->vertexcount; i++){ Vertex *vertex = &sourcemesh->vertices[i]; float vertexposition[3]; object->transformPoint(vertexposition, vertex->position); target->object->unTransformPoint(vertexposition, vertexposition); if (checkPointMeshCollision(vertexposition, targetmesh, normal, contactpoint)){ target->object->transformVector(normal, normal); target->object->transformPoint(contactpoint, contactpoint); if (vectorIsZero(contactpoint)){ vectorSet(contactpoint, 0, 0, 0); } addCollision(object, target->object, normal, contactpoint); collided = true; } } sourcemesh = target->mesh; targetmesh = this->mesh; for (i = 0; i < sourcemesh->vertexcount; i++){ Vertex *vertex = &sourcemesh->vertices[i]; float vertexposition[3]; target->object->transformPoint(vertexposition, vertex->position); object->unTransformPoint(vertexposition, vertexposition); if (checkPointMeshCollision(vertexposition, targetmesh, normal, contactpoint)){ object->transformVector(normal, normal); object->transformPoint(contactpoint, contactpoint); addCollision(target->object, object, normal, contactpoint); collided = true; } } sourcemesh = this->mesh; targetmesh = target->mesh; for (i = 0; i < sourcemesh->edgecount; i++){ Edge *edge = &sourcemesh->edges[i]; float v1[3], v2[3]; object->transformPoint(v1, edge->v1->position); target->object->unTransformPoint(v1, v1); object->transformPoint(v2, edge->v2->position); target->object->unTransformPoint(v2, v2); if (checkEdgeMeshCollision(v1, v2, targetmesh, normal, contactpoint)){ target->object->transformVector(normal, normal); target->object->transformPoint(contactpoint, contactpoint); addCollision(object, target->object, normal, contactpoint); collided = true; } } return collided; }