180 lines
4.2 KiB
C++
180 lines
4.2 KiB
C++
/*
|
|
* Copyright 2008, Haiku Inc. All rights reserved.
|
|
* Distributed under the terms of the MIT License.
|
|
*
|
|
* Authors:
|
|
* Alexandre Deckner <alex@zappotek.com>
|
|
*/
|
|
|
|
#include "MeshInstance.h"
|
|
#include "MathUtils.h"
|
|
#include <GL/gl.h>
|
|
|
|
//#include <stdio.h> // 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();
|
|
}
|