/* * Copyright 2008, Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: * Alexandre Deckner */ #include "MeshInstance.h" #include "MathUtils.h" #include //#include // debug MeshInstance::MeshInstance(Mesh* mesh, Texture* texture, const Vector3& position, const Quaternion& orientation, float animOffset) : fMeshReference(mesh), fTextureReference(texture), fPosition(position), fOrientation(orientation), fScale(1.0f), fTime(0.0f), fAnimOffset(animOffset), fDoubleSided(true), fDrawNormals(false) { } MeshInstance::~MeshInstance() { } void MeshInstance::Update(float dt) { fTextureReference->Update(dt); float animDuration = 4.0f; fTime += dt; if (fTime >= fAnimOffset) { float animTime = (fTime - fAnimOffset); float rotAngle = MathUtils::EaseInOutQuart(animTime, 0, 3 * 2 * 3.14159, animDuration); fOrientation = Quaternion(Vector3(0.0f, 1.0f, 0.0f), rotAngle); } if (fTime >= fAnimOffset + animDuration) { fOrientation = Quaternion(Vector3(0.0f, 1.0f, 0.0f), 0.0); } if (fTime >= animDuration * 6) { fTime = 0.0; } } void MeshInstance::Render() { if (fMeshReference->FaceCount() == 0) return; glPushMatrix(); glTranslatef(fPosition.x(), fPosition.y(), fPosition.z()); float mat[4][4]; fOrientation.toOpenGLMatrix(mat); glMultMatrixf((GLfloat*) mat); glScalef(fScale, fScale, fScale); glBindTexture(GL_TEXTURE_2D, fTextureReference->Id()); int lastVertexCount = 0; for (uint32 i = 0; i < fMeshReference->FaceCount(); i++) { const Face& face = fMeshReference->GetFace(i); // switch face mode if (face.vertexCount != lastVertexCount) { if (lastVertexCount != 0) glEnd(); if (face.vertexCount == 3) glBegin(GL_TRIANGLES); else glBegin(GL_QUADS); } // calculate normal Vector3 lu(face.v[0].p - face.v[1].p); Vector3 lv(face.v[1].p - face.v[2].p); Vector3 normal(lu.cross(lv)); if (normal.length() <= 0.000001) normal.setValue(0, 0, -1.0); normal.normalize(); // draw face glNormal3f(normal.x(), normal.y(), normal.z()); glTexCoord2f(face.v[0].u, face.v[0].v); glVertex3f(face.v[0].p.x(), face.v[0].p.y(), face.v[0].p.z()); glNormal3f(normal.x(), normal.y(), normal.z()); glTexCoord2f(face.v[1].u, face.v[1].v); glVertex3f(face.v[1].p.x(), face.v[1].p.y(), face.v[1].p.z()); glNormal3f(normal.x(), normal.y(), normal.z()); glTexCoord2f(face.v[2].u, face.v[2].v); glVertex3f(face.v[2].p.x(), face.v[2].p.y(), face.v[2].p.z()); if (face.vertexCount == 4) { glNormal3f(normal.x(), normal.y(), normal.z()); glTexCoord2f(face.v[3].u, face.v[3].v); glVertex3f(face.v[3].p.x(), face.v[3].p.y(), face.v[3].p.z()); } if (fDoubleSided) { if (face.vertexCount == 4) { glNormal3f(-normal.x(), -normal.y(), -normal.z()); glTexCoord2f(face.v[3].u, face.v[3].v); glVertex3f(face.v[3].p.x(), face.v[3].p.y(), face.v[3].p.z()); } glNormal3f(-normal.x(), -normal.y(), -normal.z()); glTexCoord2f(face.v[2].u, face.v[2].v); glVertex3f(face.v[2].p.x(), face.v[2].p.y(), face.v[2].p.z()); glNormal3f(-normal.x(), -normal.y(), -normal.z()); glTexCoord2f(face.v[1].u, face.v[1].v); glVertex3f(face.v[1].p.x(), face.v[1].p.y(), face.v[1].p.z()); glNormal3f(-normal.x(), -normal.y(), -normal.z()); glTexCoord2f(face.v[0].u, face.v[0].v); glVertex3f(face.v[0].p.x(), face.v[0].p.y(), face.v[0].p.z()); } lastVertexCount = face.vertexCount; } glEnd(); if (fDrawNormals) { glBegin(GL_LINES); for (uint32 i = 0; i < fMeshReference->FaceCount(); i++) { const Face& face = fMeshReference->GetFace(i); if (face.vertexCount == 4) { // calculate normal Vector3 lu(face.v[0].p - face.v[1].p); Vector3 lv(face.v[1].p - face.v[2].p); Vector3 normal(lu.cross(lv)); if (normal.length() <= 0.000001) normal.setValue(0, 0, -1.0); normal.normalize(); // center of the face Vector3 g; if (face.vertexCount == 4) g = (face.v[0].p + face.v[1].p + face.v[2].p + face.v[3].p) / 4.0; else g = (face.v[0].p + face.v[1].p + face.v[2].p) / 3.0; Vector3 h(g + normal); glVertex3f(g.x(), g.y(), g.z()); glVertex3f(h.x(), h.y(), h.z()); } } glEnd(); } glPopMatrix(); }