1
0
Fork 0
blockofighter/src/mesh.cpp

368 lines
9.2 KiB
C++

#include "main.h"
#include "mesh.h"
#include "vector.h"
#include "sphere.h"
#include "collision.h"
#include "audio.h"
#include <math.h>
#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;
}