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
16MeshInstance::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
32MeshInstance::~MeshInstance()
33{
34}
35
36
37void
38MeshInstance::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
64void
65MeshInstance::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