xref: /haiku/src/apps/haiku3d/MeshInstance.cpp (revision d25503d3dbd8e3f526fd0a9bdd884b8e43c1b794)
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 <opengl/GL/gl.h>
12 
13 //#include <stdio.h> // debug
14 
15 
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 
32 MeshInstance::~MeshInstance()
33 {
34 }
35 
36 
37 void
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
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 	//int batchCount = 0;
80 
81 	for(uint32 i = 0; i < fMeshReference->FaceCount(); i++) {
82 
83 		const Face& face = fMeshReference->GetFace(i);
84 
85 		// switch face mode
86 		if (face.vertexCount != lastVertexCount) {
87 			if (lastVertexCount != 0)
88 				glEnd();
89 
90 			if (face.vertexCount == 3)
91 				glBegin(GL_TRIANGLES);
92 			else
93 				glBegin(GL_QUADS);
94 
95 			//batchCount++;
96 		}
97 
98 		// calculate normal
99 		Vector3 lu(face.v[0].p - face.v[1].p);
100 		Vector3 lv(face.v[1].p - face.v[2].p);
101 		Vector3 normal(lu.cross(lv));
102 		if (normal.length() <= 0.000001)
103 			normal.setValue(0, 0, -1.0);
104 		normal.normalize();
105 
106 		// draw face
107 		glNormal3f(normal.x(), normal.y(),  normal.z());
108 		glTexCoord2f(face.v[0].u, face.v[0].v);
109 		glVertex3f(face.v[0].p.x(), face.v[0].p.y(), face.v[0].p.z());
110 
111 		glNormal3f(normal.x(), normal.y(),  normal.z());
112 		glTexCoord2f(face.v[1].u, face.v[1].v);
113 		glVertex3f(face.v[1].p.x(), face.v[1].p.y(), face.v[1].p.z());
114 
115 		glNormal3f(normal.x(), normal.y(),  normal.z());
116 		glTexCoord2f(face.v[2].u, face.v[2].v);
117 		glVertex3f(face.v[2].p.x(), face.v[2].p.y(), face.v[2].p.z());
118 
119 		if (face.vertexCount == 4) {
120 			glNormal3f(normal.x(), normal.y(), normal.z());
121 			glTexCoord2f(face.v[3].u, face.v[3].v);
122 			glVertex3f(face.v[3].p.x(), face.v[3].p.y(), face.v[3].p.z());
123 		}
124 
125 		if (fDoubleSided) {
126 			if (face.vertexCount == 4) {
127 				glNormal3f(-normal.x(), -normal.y(), -normal.z());
128 				glTexCoord2f(face.v[3].u, face.v[3].v);
129 				glVertex3f(face.v[3].p.x(), face.v[3].p.y(), face.v[3].p.z());
130 			}
131 
132 			glNormal3f(-normal.x(), -normal.y(), -normal.z());
133 			glTexCoord2f(face.v[2].u, face.v[2].v);
134 			glVertex3f(face.v[2].p.x(), face.v[2].p.y(), face.v[2].p.z());
135 
136 			glNormal3f(-normal.x(), -normal.y(), -normal.z());
137 			glTexCoord2f(face.v[1].u, face.v[1].v);
138 			glVertex3f(face.v[1].p.x(), face.v[1].p.y(), face.v[1].p.z());
139 
140 			glNormal3f(-normal.x(), -normal.y(), -normal.z());
141 			glTexCoord2f(face.v[0].u, face.v[0].v);
142 			glVertex3f(face.v[0].p.x(), face.v[0].p.y(), face.v[0].p.z());
143 		}
144 		lastVertexCount = face.vertexCount;
145 	}
146 	glEnd();
147 	//printf("batchCount %d\n", batchCount);
148 
149 	if (fDrawNormals) {
150 		glBegin(GL_LINES);
151 		for(uint32 i = 0; i < fMeshReference->FaceCount(); i++) {
152 
153 			const Face& face = fMeshReference->GetFace(i);
154 
155 			if (face.vertexCount == 4) {
156 
157 				// calculate normal
158 				Vector3 lu(face.v[0].p - face.v[1].p);
159 				Vector3 lv(face.v[1].p - face.v[2].p);
160 				Vector3 normal(lu.cross(lv));
161 				if (normal.length() <= 0.000001)
162 					normal.setValue(0, 0, -1.0);
163 				normal.normalize();
164 
165 				// center of the face
166 				Vector3 g;
167 				if (face.vertexCount == 4)
168 					g = (face.v[0].p + face.v[1].p + face.v[2].p + face.v[3].p)
169 						/ 4.0;
170 				else
171 					g = (face.v[0].p + face.v[1].p + face.v[2].p) / 3.0;
172 
173 				Vector3 h(g + normal);
174 
175 				glVertex3f(g.x(), g.y(), g.z());
176 				glVertex3f(h.x(), h.y(), h.z());
177 	    	}
178 		}
179 		glEnd();
180 	}
181 
182 	glPopMatrix();
183 }
184