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