#include "hair.h"
#include "object.h"
-#define MAX_NUM_SPAWNS 400
+#define MAX_NUM_SPAWNS 1600
#define THRESH 0.5
static bool init();
static void mouse(int bn, int st, int x, int y);
static void motion(int x, int y);
static void idle();
+static void sball_motion(int x, int y, int z);
+static void sball_rotate(int x, int y, int z);
+static void sball_button(int bn, int st);
+
+static unsigned int gen_grad_tex(int sz, const Vec3 &c0, const Vec3 &c1);
+static void draw_text(const char *text, int x, int y, float sz, const Vec3 &color);
+static void update_sball_matrix();
static std::vector<Mesh*> meshes;
static Mesh *mesh_head;
static Hair hair;
+static unsigned int grad_tex;
+
static int win_width, win_height;
static float cam_theta, cam_phi = 25, cam_dist = 8;
static float head_rz, head_rx; /* rot angles x, z axis */
static Mat4 head_xform;
-static CollSphere coll_sphere; /* sphere used for collision detection */
+//static CollSphere coll_sphere; /* sphere used for collision detection */
+
+// spaceball (6dof control) state
+static Vec3 sball_pos;
+static Quat sball_rot;
+static Mat4 sball_xform;
+static bool sball_update_pending;
+
int main(int argc, char **argv)
{
glutMouseFunc(mouse);
glutMotionFunc(motion);
glutIdleFunc(idle);
+ glutSpaceballMotionFunc(sball_motion);
+ glutSpaceballRotateFunc(sball_rotate);
+ glutSpaceballButtonFunc(sball_button);
if(!init()) {
return 1;
{
glewInit();
+ grad_tex = gen_grad_tex(32, Vec3(0, 0, 1), Vec3(0, 1, 0));
+
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
- glEnable(GL_COLOR_MATERIAL);
+// glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
return false;
}
- coll_sphere.radius = 1.0;
- coll_sphere.center = Vec3(0, 0.6, 0.53);
+// coll_sphere.radius = 1.0;
+// coll_sphere.center = Vec3(0, 0.6, 0.53);
if(!hair.init(mesh_head, MAX_NUM_SPAWNS, THRESH)) {
fprintf(stderr, "Failed to initialize hair\n");
return false;
}
- hair.add_collider(&coll_sphere);
+// hair.add_collider(&coll_sphere);
return true;
}
for(size_t i=0; i<meshes.size(); i++) {
delete meshes[i];
}
+ glDeleteTextures(1, &grad_tex);
}
static void display()
float dt = (float)(msec - prev_time) / 1000.0;
prev_time = msec;
+ if(sball_update_pending) {
+ update_sball_matrix();
+ sball_update_pending = false;
+ }
+
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
head_xform = Mat4::identity;
head_xform.rotate_x(gph::deg_to_rad(head_rx));
head_xform.rotate_z(-gph::deg_to_rad(head_rz));
+ head_xform *= sball_xform;
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
*/
for(size_t i=0; i<meshes.size(); i++) {
- meshes[i]->draw();
+ if(!meshes[i]->mtl.tex || meshes[i]->mtl.tex_opaque)
+ meshes[i]->draw();
+ }
+ for(size_t i=0; i<meshes.size(); i++) {
+ if(meshes[i]->mtl.tex && !meshes[i]->mtl.tex_opaque)
+ meshes[i]->draw();
}
/*
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnd();
glPopAttrib();
*/
+ float plane[4] = {
+ 0, 0, 0.5 / 350, 0.5
+ };
+
+ glPushMatrix();
+ glRotatef(90, 1, 0, 0);
+
+ glPushAttrib(GL_ENABLE_BIT);
+ glDisable(GL_LIGHTING);
+ glEnable(GL_TEXTURE_1D);
+ glBindTexture(GL_TEXTURE_1D, grad_tex);
+ glFrontFace(GL_CW);
+ glEnable(GL_TEXTURE_GEN_S);
+ glTexGenfv(GL_S, GL_OBJECT_PLANE, plane);
+ glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+ glColor3f(1, 1, 1);
+
+ glDepthMask(0);
+
+ glutSolidSphere(350, 16, 8);
+ glDisable(GL_TEXTURE_1D);
+
+ glColor3f(0.2, 0.2, 0.2);
+ glutWireSphere(350, 32, 16);
+
+ glDepthMask(1);
+ glFrontFace(GL_CCW);
+ glPopAttrib();
+
+ glPopMatrix();
+
+ draw_text("Hold h to move the head with the mouse!", 15, 15, 0.0015 * win_width, Vec3(0, 0, 0));
+ draw_text("Hold h to move the head with the mouse!", 12, 17, 0.0015 * win_width, Vec3(0.8, 0.5, 0.7));
glutSwapBuffers();
assert(glGetError() == GL_NO_ERROR);
{
glutPostRedisplay();
}
+
+static void sball_motion(int x, int y, int z)
+{
+ sball_pos.x += (float)x * 0.001;
+ sball_pos.y += (float)y * 0.001;
+ sball_pos.z -= (float)z * 0.001;
+ sball_update_pending = true;
+}
+
+static void sball_rotate(int x, int y, int z)
+{
+ Vec3 axis = Vec3(x, y, -z);
+ float axis_len = length(axis);
+ if(axis_len > 0.0f) {
+ Quat q;
+ q.set_rotation(axis / axis_len, axis_len * 0.001);
+ sball_rot = q * sball_rot;
+ sball_update_pending = true;
+ }
+}
+
+static void sball_button(int bn, int st)
+{
+ if(st != GLUT_DOWN) return;
+
+ sball_pos = Vec3(0, 0, 0);
+ sball_rot = Quat::identity;
+ sball_xform = Mat4::identity;
+}
+
+static unsigned int gen_grad_tex(int sz, const Vec3 &c0, const Vec3 &c1)
+{
+ unsigned char *pixels = new unsigned char[sz * 3];
+ for(int i=0; i<sz; i++) {
+ float t = (float)i / (float)(sz - 1);
+ Vec3 color = c0 + (c1 - c0) * t;
+ pixels[i * 3] = color.x * 255;
+ pixels[i * 3 + 1] = color.y * 255;
+ pixels[i * 3 + 2] = color.z * 255;
+ }
+
+ unsigned int tex;
+ glGenTextures(1, &tex);
+ glBindTexture(GL_TEXTURE_1D, tex);
+
+ glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+
+ glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, sz, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels);
+
+ delete [] pixels;
+
+ return tex;
+}
+
+static void draw_text(const char *text, int x, int y, float sz, const Vec3 &color)
+{
+ glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT | GL_POINT_BIT);
+
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_LIGHTING);
+ glLineWidth(3);
+ glPointSize(3);
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ glOrtho(0, win_width, 0, win_height, -1, 1);
+
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+ glTranslatef(x, y, 0);
+ glScalef(0.1 * sz, 0.1 * sz, 1);
+
+ glColor3f(color.x, color.y, color.z);
+ while(*text != '\0') {
+ glutStrokeCharacter(GLUT_STROKE_MONO_ROMAN, *text);
+ text++;
+ }
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+
+ glPopAttrib();
+}
+
+static void update_sball_matrix()
+{
+ Mat4 rot = sball_rot.calc_matrix();
+ //rot.transpose();
+
+ Mat4 trans;
+ trans.translation(sball_pos);
+
+ sball_xform = rot * trans;
+}