#include <stdio.h>
#include <string>
+#include <gmath/gmath.h>
+
#include "mesh.h"
#include "hair.h"
+#include "object.h"
-#define MAX_NUM_SPAWNS 4
+#define MAX_NUM_SPAWNS 400
#define THRESH 0.5
static bool init();
static void display();
static void reshape(int x, int y);
static void keydown(unsigned char key, int x, int y);
+static void keyup(unsigned char key, int x, int y);
static void mouse(int bn, int st, int x, int y);
static void motion(int x, int y);
+static void idle();
static std::vector<Mesh*> meshes;
static Mesh *mesh_head;
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 */
int main(int argc, char **argv)
{
glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
glutCreateWindow("hair test");
+ /* for the keydown, keyup functions to work */
+ glutSetKeyRepeat(GLUT_KEY_REPEAT_OFF);
+
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keydown);
+ glutKeyboardUpFunc(keyup);
glutMouseFunc(mouse);
glutMotionFunc(motion);
+ glutIdleFunc(idle);
if(!init()) {
return 1;
return false;
}
+ 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);
+
return true;
}
static void display()
{
+ static unsigned long prev_time;
+ unsigned long msec = glutGet(GLUT_ELAPSED_TIME);
+ float dt = (float)(msec - prev_time) / 1000.0;
+ prev_time = msec;
+
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));
+
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0, 0, -cam_dist);
glRotatef(cam_phi, 1, 0, 0);
glRotatef(cam_theta, 0, 1, 0);
-
+ /* multiplying with the head rot matrix */
+ glPushMatrix();
+ glMultMatrixf(head_xform[0]);
+ glPushAttrib(GL_LINE_BIT);
+ glLineWidth(1);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
for(size_t i=0; i<meshes.size(); i++) {
meshes[i]->draw();
}
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ glPopAttrib();
+ glPopMatrix();
+
+ hair.set_transform(head_xform);
+ hair.update(dt);
hair.draw();
+/*
+ glPushAttrib(GL_ENABLE_BIT);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_LIGHTING);
+ glBegin(GL_POINTS);
+ for (int i=0; i<500; i++) {
+ Vec3 p;
+ p.x = (float)rand() / RAND_MAX * 8 - 4;
+ p.y = (float)rand() / RAND_MAX * 4;
+ p.z = 0;
+
+ Vec3 tmp = inverse(head_xform) * p;
+ if(coll_sphere.contains(tmp)) {
+ glColor3f(1, 0, 0);
+ }
+ else glColor3f(0, 1, 0);
+
+ glVertex3f(p.x, p.y, p.z);
+ }
+ glEnd();
+ glPopAttrib();
+ */
+
glutSwapBuffers();
assert(glGetError() == GL_NO_ERROR);
}
gluPerspective(50.0, (float)x / (float)y, 0.5, 500.0);
}
+static bool hpressed;
static void keydown(unsigned char key, int /*x*/, int /*y*/)
{
switch(key) {
+ case 'h':
+ case 'H':
+ hpressed = true;
+ break;
case 27:
exit(0);
+ default:
+ break;
+ }
+}
+
+static void keyup(unsigned char key, int /*x*/, int /*y*/)
+{
+ switch(key) {
+ case 'h':
+ case 'H':
+ hpressed = false;
+ break;
+ default:
+ break;
}
}
if(!dx && !dy) return;
- if(bnstate[0]) {
- cam_theta += dx * 0.5;
- cam_phi += dy * 0.5;
+ if(hpressed) {
+ if(bnstate[0]) {
+ head_rz += dx * 0.5;
+ head_rx += dy * 0.5;
+
+ if(head_rx < -45) head_rx = -45;
+ if(head_rx > 45) head_rx = 45;
- if(cam_phi < -90) cam_phi = -90;
- if(cam_phi > 90) cam_phi = 90;
- glutPostRedisplay();
+ if(head_rz < -90) head_rz = -90;
+ if(head_rz > 90) head_rz = 30;
+ }
}
- if(bnstate[2]) {
- cam_dist += dy * 0.1;
- if(cam_dist < 0) cam_dist = 0;
- glutPostRedisplay();
+ else {
+ if(bnstate[0]) {
+ cam_theta += dx * 0.5;
+ cam_phi += dy * 0.5;
+
+ if(cam_phi < -90) cam_phi = -90;
+ if(cam_phi > 90) cam_phi = 90;
+ }
+ if(bnstate[2]) {
+ cam_dist += dy * 0.1;
+ if(cam_dist < 0) cam_dist = 0;
+ }
}
}
+
+static void idle()
+{
+ glutPostRedisplay();
+}