xref: /haiku/src/apps/haiku3d/MeshInstance.cpp (revision 25a7b01d15612846f332751841da3579db313082)
1bee3c7a9SAlexandre Deckner /*
2bee3c7a9SAlexandre Deckner  * Copyright 2008, Haiku Inc. All rights reserved.
3bee3c7a9SAlexandre Deckner  * Distributed under the terms of the MIT License.
4bee3c7a9SAlexandre Deckner  *
5bee3c7a9SAlexandre Deckner  * Authors:
6bee3c7a9SAlexandre Deckner  * 		Alexandre Deckner <alex@zappotek.com>
7bee3c7a9SAlexandre Deckner  */
8bee3c7a9SAlexandre Deckner 
9bee3c7a9SAlexandre Deckner #include "MeshInstance.h"
10bee3c7a9SAlexandre Deckner #include "MathUtils.h"
11*8e4cdaaeSAlexander von Gluck IV #include <GL/gl.h>
12bee3c7a9SAlexandre Deckner 
13bee3c7a9SAlexandre Deckner //#include <stdio.h> // debug
14bee3c7a9SAlexandre Deckner 
15bee3c7a9SAlexandre Deckner 
MeshInstance(Mesh * mesh,Texture * texture,const Vector3 & position,const Quaternion & orientation,float animOffset)16bee3c7a9SAlexandre Deckner MeshInstance::MeshInstance(Mesh* mesh, Texture* texture,
17bee3c7a9SAlexandre Deckner 	const Vector3& position, const Quaternion& orientation, float animOffset)
18bee3c7a9SAlexandre Deckner 	:
19bee3c7a9SAlexandre Deckner 	fMeshReference(mesh),
20bee3c7a9SAlexandre Deckner 	fTextureReference(texture),
21bee3c7a9SAlexandre Deckner 	fPosition(position),
22bee3c7a9SAlexandre Deckner 	fOrientation(orientation),
23bee3c7a9SAlexandre Deckner 	fScale(1.0f),
24bee3c7a9SAlexandre Deckner 	fTime(0.0f),
25bee3c7a9SAlexandre Deckner 	fAnimOffset(animOffset),
26bee3c7a9SAlexandre Deckner 	fDoubleSided(true),
27bee3c7a9SAlexandre Deckner 	fDrawNormals(false)
28bee3c7a9SAlexandre Deckner {
29bee3c7a9SAlexandre Deckner }
30bee3c7a9SAlexandre Deckner 
31bee3c7a9SAlexandre Deckner 
~MeshInstance()32bee3c7a9SAlexandre Deckner MeshInstance::~MeshInstance()
33bee3c7a9SAlexandre Deckner {
34bee3c7a9SAlexandre Deckner }
35bee3c7a9SAlexandre Deckner 
36bee3c7a9SAlexandre Deckner 
37bee3c7a9SAlexandre Deckner void
Update(float dt)38bee3c7a9SAlexandre Deckner MeshInstance::Update(float dt)
39bee3c7a9SAlexandre Deckner {
40bee3c7a9SAlexandre Deckner 	fTextureReference->Update(dt);
41bee3c7a9SAlexandre Deckner 
42bee3c7a9SAlexandre Deckner 	float animDuration = 4.0f;
43bee3c7a9SAlexandre Deckner 
44bee3c7a9SAlexandre Deckner 	fTime += dt;
45bee3c7a9SAlexandre Deckner 	if (fTime >= fAnimOffset) {
46bee3c7a9SAlexandre Deckner 		float animTime = (fTime - fAnimOffset);
47bee3c7a9SAlexandre Deckner 
48bee3c7a9SAlexandre Deckner 		float rotAngle = MathUtils::EaseInOutQuart(animTime, 0,
49bee3c7a9SAlexandre Deckner 			3 * 2 * 3.14159, animDuration);
50bee3c7a9SAlexandre Deckner 
51bee3c7a9SAlexandre Deckner 		fOrientation = Quaternion(Vector3(0.0f, 1.0f, 0.0f), rotAngle);
52bee3c7a9SAlexandre Deckner 	}
53bee3c7a9SAlexandre Deckner 
54bee3c7a9SAlexandre Deckner 	if (fTime >= fAnimOffset + animDuration) {
55bee3c7a9SAlexandre Deckner 		fOrientation = Quaternion(Vector3(0.0f, 1.0f, 0.0f), 0.0);
56bee3c7a9SAlexandre Deckner 	}
57bee3c7a9SAlexandre Deckner 
58bee3c7a9SAlexandre Deckner 	if (fTime >= animDuration * 6) {
59bee3c7a9SAlexandre Deckner 		fTime = 0.0;
60bee3c7a9SAlexandre Deckner 	}
61bee3c7a9SAlexandre Deckner }
62bee3c7a9SAlexandre Deckner 
63bee3c7a9SAlexandre Deckner 
64bee3c7a9SAlexandre Deckner void
Render()65bee3c7a9SAlexandre Deckner MeshInstance::Render()
66bee3c7a9SAlexandre Deckner {
67bee3c7a9SAlexandre Deckner 	if (fMeshReference->FaceCount() == 0)
68bee3c7a9SAlexandre Deckner 		return;
69bee3c7a9SAlexandre Deckner 
70bee3c7a9SAlexandre Deckner 	glPushMatrix();
71bee3c7a9SAlexandre Deckner 	glTranslatef(fPosition.x(), fPosition.y(), fPosition.z());
72bee3c7a9SAlexandre Deckner 	float mat[4][4];
73bee3c7a9SAlexandre Deckner 	fOrientation.toOpenGLMatrix(mat);
74bee3c7a9SAlexandre Deckner 	glMultMatrixf((GLfloat*) mat);
75bee3c7a9SAlexandre Deckner 	glScalef(fScale, fScale, fScale);
76bee3c7a9SAlexandre Deckner 	glBindTexture(GL_TEXTURE_2D, fTextureReference->Id());
77bee3c7a9SAlexandre Deckner 
78bee3c7a9SAlexandre Deckner 	int lastVertexCount = 0;
79bee3c7a9SAlexandre Deckner 
80bee3c7a9SAlexandre Deckner 	for (uint32 i = 0; i < fMeshReference->FaceCount(); i++) {
81bee3c7a9SAlexandre Deckner 
82bee3c7a9SAlexandre Deckner 		const Face& face = fMeshReference->GetFace(i);
83bee3c7a9SAlexandre Deckner 
84bee3c7a9SAlexandre Deckner 		// switch face mode
85bee3c7a9SAlexandre Deckner 		if (face.vertexCount != lastVertexCount) {
86bee3c7a9SAlexandre Deckner 			if (lastVertexCount != 0)
87bee3c7a9SAlexandre Deckner 				glEnd();
88bee3c7a9SAlexandre Deckner 
89bee3c7a9SAlexandre Deckner 			if (face.vertexCount == 3)
90bee3c7a9SAlexandre Deckner 				glBegin(GL_TRIANGLES);
91bee3c7a9SAlexandre Deckner 			else
92bee3c7a9SAlexandre Deckner 				glBegin(GL_QUADS);
93bee3c7a9SAlexandre Deckner 		}
94bee3c7a9SAlexandre Deckner 
95bee3c7a9SAlexandre Deckner 		// calculate normal
96bee3c7a9SAlexandre Deckner 		Vector3 lu(face.v[0].p - face.v[1].p);
97bee3c7a9SAlexandre Deckner 		Vector3 lv(face.v[1].p - face.v[2].p);
98bee3c7a9SAlexandre Deckner 		Vector3 normal(lu.cross(lv));
99bee3c7a9SAlexandre Deckner 		if (normal.length() <= 0.000001)
100bee3c7a9SAlexandre Deckner 			normal.setValue(0, 0, -1.0);
101bee3c7a9SAlexandre Deckner 		normal.normalize();
102bee3c7a9SAlexandre Deckner 
103bee3c7a9SAlexandre Deckner 		// draw face
104bee3c7a9SAlexandre Deckner 		glNormal3f(normal.x(), normal.y(),  normal.z());
105bee3c7a9SAlexandre Deckner 		glTexCoord2f(face.v[0].u, face.v[0].v);
106bee3c7a9SAlexandre Deckner 		glVertex3f(face.v[0].p.x(), face.v[0].p.y(), face.v[0].p.z());
107bee3c7a9SAlexandre Deckner 
108bee3c7a9SAlexandre Deckner 		glNormal3f(normal.x(), normal.y(),  normal.z());
109bee3c7a9SAlexandre Deckner 		glTexCoord2f(face.v[1].u, face.v[1].v);
110bee3c7a9SAlexandre Deckner 		glVertex3f(face.v[1].p.x(), face.v[1].p.y(), face.v[1].p.z());
111bee3c7a9SAlexandre Deckner 
112bee3c7a9SAlexandre Deckner 		glNormal3f(normal.x(), normal.y(),  normal.z());
113bee3c7a9SAlexandre Deckner 		glTexCoord2f(face.v[2].u, face.v[2].v);
114bee3c7a9SAlexandre Deckner 		glVertex3f(face.v[2].p.x(), face.v[2].p.y(), face.v[2].p.z());
115bee3c7a9SAlexandre Deckner 
116bee3c7a9SAlexandre Deckner 		if (face.vertexCount == 4) {
117bee3c7a9SAlexandre Deckner 			glNormal3f(normal.x(), normal.y(), normal.z());
118bee3c7a9SAlexandre Deckner 			glTexCoord2f(face.v[3].u, face.v[3].v);
119bee3c7a9SAlexandre Deckner 			glVertex3f(face.v[3].p.x(), face.v[3].p.y(), face.v[3].p.z());
120bee3c7a9SAlexandre Deckner 		}
121bee3c7a9SAlexandre Deckner 
122bee3c7a9SAlexandre Deckner 		if (fDoubleSided) {
123bee3c7a9SAlexandre Deckner 			if (face.vertexCount == 4) {
124bee3c7a9SAlexandre Deckner 				glNormal3f(-normal.x(), -normal.y(), -normal.z());
125bee3c7a9SAlexandre Deckner 				glTexCoord2f(face.v[3].u, face.v[3].v);
126bee3c7a9SAlexandre Deckner 				glVertex3f(face.v[3].p.x(), face.v[3].p.y(), face.v[3].p.z());
127bee3c7a9SAlexandre Deckner 			}
128bee3c7a9SAlexandre Deckner 
129bee3c7a9SAlexandre Deckner 			glNormal3f(-normal.x(), -normal.y(), -normal.z());
130bee3c7a9SAlexandre Deckner 			glTexCoord2f(face.v[2].u, face.v[2].v);
131bee3c7a9SAlexandre Deckner 			glVertex3f(face.v[2].p.x(), face.v[2].p.y(), face.v[2].p.z());
132bee3c7a9SAlexandre Deckner 
133bee3c7a9SAlexandre Deckner 			glNormal3f(-normal.x(), -normal.y(), -normal.z());
134bee3c7a9SAlexandre Deckner 			glTexCoord2f(face.v[1].u, face.v[1].v);
135bee3c7a9SAlexandre Deckner 			glVertex3f(face.v[1].p.x(), face.v[1].p.y(), face.v[1].p.z());
136bee3c7a9SAlexandre Deckner 
137bee3c7a9SAlexandre Deckner 			glNormal3f(-normal.x(), -normal.y(), -normal.z());
138bee3c7a9SAlexandre Deckner 			glTexCoord2f(face.v[0].u, face.v[0].v);
139bee3c7a9SAlexandre Deckner 			glVertex3f(face.v[0].p.x(), face.v[0].p.y(), face.v[0].p.z());
140bee3c7a9SAlexandre Deckner 		}
141bee3c7a9SAlexandre Deckner 		lastVertexCount = face.vertexCount;
142bee3c7a9SAlexandre Deckner 	}
143bee3c7a9SAlexandre Deckner 	glEnd();
144bee3c7a9SAlexandre Deckner 
145bee3c7a9SAlexandre Deckner 	if (fDrawNormals) {
146bee3c7a9SAlexandre Deckner 		glBegin(GL_LINES);
147bee3c7a9SAlexandre Deckner 		for (uint32 i = 0; i < fMeshReference->FaceCount(); i++) {
148bee3c7a9SAlexandre Deckner 
149bee3c7a9SAlexandre Deckner 			const Face& face = fMeshReference->GetFace(i);
150bee3c7a9SAlexandre Deckner 
151bee3c7a9SAlexandre Deckner 			if (face.vertexCount == 4) {
152bee3c7a9SAlexandre Deckner 
153bee3c7a9SAlexandre Deckner 				// calculate normal
154bee3c7a9SAlexandre Deckner 				Vector3 lu(face.v[0].p - face.v[1].p);
155bee3c7a9SAlexandre Deckner 				Vector3 lv(face.v[1].p - face.v[2].p);
156bee3c7a9SAlexandre Deckner 				Vector3 normal(lu.cross(lv));
157bee3c7a9SAlexandre Deckner 				if (normal.length() <= 0.000001)
158bee3c7a9SAlexandre Deckner 					normal.setValue(0, 0, -1.0);
159bee3c7a9SAlexandre Deckner 				normal.normalize();
160bee3c7a9SAlexandre Deckner 
161bee3c7a9SAlexandre Deckner 				// center of the face
162bee3c7a9SAlexandre Deckner 				Vector3 g;
163bee3c7a9SAlexandre Deckner 				if (face.vertexCount == 4)
164bee3c7a9SAlexandre Deckner 					g = (face.v[0].p + face.v[1].p + face.v[2].p + face.v[3].p)
165bee3c7a9SAlexandre Deckner 						/ 4.0;
166bee3c7a9SAlexandre Deckner 				else
167bee3c7a9SAlexandre Deckner 					g = (face.v[0].p + face.v[1].p + face.v[2].p) / 3.0;
168bee3c7a9SAlexandre Deckner 
169bee3c7a9SAlexandre Deckner 				Vector3 h(g + normal);
170bee3c7a9SAlexandre Deckner 
171bee3c7a9SAlexandre Deckner 				glVertex3f(g.x(), g.y(), g.z());
172bee3c7a9SAlexandre Deckner 				glVertex3f(h.x(), h.y(), h.z());
173bee3c7a9SAlexandre Deckner 			}
174bee3c7a9SAlexandre Deckner 		}
175bee3c7a9SAlexandre Deckner 		glEnd();
176bee3c7a9SAlexandre Deckner 	}
177bee3c7a9SAlexandre Deckner 
178bee3c7a9SAlexandre Deckner 	glPopMatrix();
179bee3c7a9SAlexandre Deckner }
180