# HG changeset patch # User John Tsiombikas # Date 1440297429 -10800 # Node ID 3b4460b34d432a74d82eef6b37c83f08d172ef11 # Parent 1e8d90aeae34d1b63caf143462f3b1547a72d397 progress diff -r 1e8d90aeae34 -r 3b4460b34d43 src/dragon.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dragon.cc Sun Aug 23 05:37:09 2015 +0300 @@ -0,0 +1,120 @@ +#include +#include "opengl.h" +#include "dragon.h" + +Dragon::Dragon() + : pos(0, 0, 0), dir(0, 0, -1), head_pos(0, 0, -1), target(0, 0, -2) +{ + set_head_limits(-1, 1, -1, 1); +} + +Dragon::~Dragon() +{ +} + +void Dragon::set_position(const Vector3 &p) +{ + pos = p; +} + +void Dragon::set_direction(const Vector3 &dir) +{ + this->dir = dir.normalized(); +} + +void Dragon::set_target(const Vector3 &p) +{ + target = p; +} + +void Dragon::set_head_limits(float xmin, float xmax, float ymin, float ymax) +{ + head_xlim[0] = std::min(xmin, xmax); + head_xlim[1] = std::max(xmin, xmax); + head_ylim[0] = std::min(ymin, ymax); + head_ylim[1] = std::max(ymin, ymax); +} + +void Dragon::move_head(const Vector3 &p) +{ + head_pos = p; +} + +static float clamp(float x, float low, float high) +{ + return x < low ? low : (x > high ? high : x); +} + +void Dragon::move_head(float dx, float dy) +{ + float newx = clamp(head_pos.x + dx, head_xlim[0], head_xlim[1]); + float newy = clamp(head_pos.y + dy, head_ylim[0], head_ylim[1]); + + dx = newx - head_pos.x; + dy = newy - head_pos.y; + head_pos.x = newx; + head_pos.y = newy; + + target.x += dx * 0.7; + target.y += dy * 0.5; +} + +const Vector3 &Dragon::head_position() const +{ + return head_pos; +} + +Vector3 Dragon::breath_dir() const +{ + return (target - head_pos).normalized(); +} + +void Dragon::update() +{ +} + +static Vector3 bezier(const Vector3 &a, const Vector3 &b, const Vector3 &c, const Vector3 &d, float t) +{ + float x = bezier(a.x, b.x, c.x, d.x, t); + float y = bezier(a.y, b.y, c.y, d.y, t); + float z = bezier(a.z, b.z, c.z, d.z, t); + return Vector3(x, y, z); +} + +void Dragon::draw() const +{ + Vector3 bdir = breath_dir(); + Vector3 bezcp[] = { pos, pos + dir * 6.0, head_pos - bdir * 8.0, head_pos }; + + int cur_sdr; + glGetIntegerv(GL_CURRENT_PROGRAM, &cur_sdr); + glUseProgram(0); + + glPushAttrib(GL_ENABLE_BIT); + glDisable(GL_LIGHTING); + + glLineWidth(2.0); + glColor3f(0, 0, 1); + + glBegin(GL_LINE_STRIP); + for(int i=0; i<10; i++) { + float t = (float)i / 10.0f; + Vector3 p = bezier(bezcp[0], bezcp[1], bezcp[2], bezcp[3], t); + glVertex3f(p.x, p.y, p.z); + } + glEnd(); + glLineWidth(1); + + glPointSize(5.0); + glColor3f(0, 1, 0); + + glBegin(GL_POINTS); + for(int i=0; i<4; i++) { + glVertex3f(bezcp[i].x, bezcp[i].y, bezcp[i].z); + } + glEnd(); + + glPopAttrib(); + + glUseProgram(cur_sdr); +} diff -r 1e8d90aeae34 -r 3b4460b34d43 src/dragon.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dragon.h Sun Aug 23 05:37:09 2015 +0300 @@ -0,0 +1,30 @@ +#ifndef DRAGON_H_ +#define DRAGON_H_ + +#include "vmath/vmath.h" + +class Dragon { +private: + Vector3 pos, dir; + Vector3 head_pos, target; + float head_xlim[2], head_ylim[2]; + +public: + Dragon(); + ~Dragon(); + + void set_position(const Vector3 &p); + void set_direction(const Vector3 &dir); + void set_target(const Vector3 &p); + + void set_head_limits(float xmin, float xmax, float ymin, float ymax); + void move_head(const Vector3 &p); + void move_head(float dx, float dy); + const Vector3 &head_position() const; + Vector3 breath_dir() const; + + void update(); + void draw() const; +}; + +#endif // DRAGON_H_ diff -r 1e8d90aeae34 -r 3b4460b34d43 src/game.cc --- a/src/game.cc Sun Aug 23 04:45:24 2015 +0300 +++ b/src/game.cc Sun Aug 23 05:37:09 2015 +0300 @@ -9,6 +9,7 @@ #include "mesh.h" #include "room.h" +#include "dragon.h" static void draw_scene(); @@ -19,13 +20,18 @@ unsigned int sdr_shadow, sdr_shadow_notex; -static float cam_theta, cam_phi = 25, cam_dist = 8; +static float cam_theta, cam_phi = 23, cam_dist = 26; +static float cam_x, cam_y, cam_z = 9; static bool bnstate[8]; static int prev_x, prev_y; +static bool gamectl = false; static unsigned int modkeys; +static Dragon dragon; + + bool game_init() { if(init_opengl() == -1) { @@ -65,6 +71,12 @@ return false; } + dragon.set_position(Vector3(0, 5, 20)); + dragon.set_direction(Vector3(0, 0, -1)); + dragon.set_target(Vector3(0, 3, 0)); + dragon.move_head(Vector3(0, 6, 10)); + dragon.set_head_limits(-ROOM_WIDTH * 0.2, ROOM_WIDTH * 0.2, 1, ROOM_HEIGHT - 3); + Mesh::use_custom_sdr_attr = false; assert(glGetError() == GL_NO_ERROR); @@ -79,6 +91,8 @@ void game_update(unsigned long time_msec) { cur_time = time_msec; + + dragon.update(); } void game_display() @@ -90,12 +104,13 @@ glTranslatef(0, 0.1, -cam_dist); glRotatef(cam_phi, 1, 0, 0); glRotatef(cam_theta, 0, 1, 0); + glTranslatef(-cam_x, -cam_y, -cam_z); - float lpos[] = {-5, 15, 10, 1}; + float lpos[] = {0, 10, 24, 1}; glLightfv(GL_LIGHT0, GL_POSITION, lpos); if(opt.shadows && sdr_shadow) { - begin_shadow_pass(Vector3(lpos[0], lpos[1], lpos[2]), Vector3(0, 0, 0), 10); + begin_shadow_pass(Vector3(lpos[0], lpos[1], lpos[2]), Vector3(0, 0, 0), 45); draw_scene(); end_shadow_pass(); @@ -142,6 +157,8 @@ draw_teapot(); glPopMatrix(); + + dragon.draw(); } @@ -161,6 +178,10 @@ case 27: quit(); + case ' ': + gamectl = !gamectl; + break; + case 'w': dbg_wireframe = !dbg_wireframe; redisplay(); @@ -170,6 +191,11 @@ opt.shadows = !opt.shadows; redisplay(); break; + + case 'p': + printf("camera pos(%g %g %g) rot(%g %g) d(%g)\n", + cam_x, cam_y, cam_z, cam_theta, cam_phi, cam_dist); + break; } } } @@ -204,6 +230,10 @@ prev_x = x; prev_y = y; + if(gamectl) { + dragon.move_head(dx * 0.1, -dy * 0.1); + } + if(modkeys) { if(bnstate[0]) { cam_theta += dx * 0.5; @@ -212,6 +242,19 @@ if(cam_phi < -90) cam_phi = -90; if(cam_phi > 90) cam_phi = 90; } + if(bnstate[1]) { + float theta = DEG_TO_RAD(cam_theta); + + float dxp = dx * 0.1; + float dyp = dy * 0.1; + + cam_x += cos(theta) * dxp - sin(theta) * dyp; + if(modkeys & (1 << MOD_SHIFT)) { + cam_y -= sin(theta) * dxp + cos(theta) * dyp; + } else { + cam_z += sin(theta) * dxp + cos(theta) * dyp; + } + } if(bnstate[2]) { cam_dist += dy * 0.1; if(cam_dist < 0.0) cam_dist = 0.0; diff -r 1e8d90aeae34 -r 3b4460b34d43 src/revol.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/revol.cc Sun Aug 23 05:37:09 2015 +0300 @@ -0,0 +1,44 @@ +#include +#include "revol.h" + +Vector2 bezier_revol(float u, float v, void *cls) +{ + BezCurve *curve = (BezCurve*)cls; + int nseg = (curve->numcp - 1) / 2; + + if(v >= 1.0) v = 1.0 - 1e-6; + int cidx = std::min((int)(v * nseg), nseg - 1); + float t = fmod(v * (float)nseg, 1.0); + + const vec2_t *cp = curve->cp + cidx * 2; + + float resx = bezier(cp[0].x, cp[1].x, cp[1].x, cp[2].x, t); + float resy = bezier(cp[0].y, cp[1].y, cp[1].y, cp[2].y, t); + return Vector2(resx * curve->scale, resy * curve->scale); +} + +Vector2 bezier_revol_normal(float u, float v, void *cls) +{ + BezCurve *curve = (BezCurve*)cls; + int nseg = (curve->numcp - 1) / 2; + + if(v >= 1.0) v = 1.0 - 1e-6; + int cidx = std::min((int)(v * nseg), nseg - 1); + float t = fmod(v * (float)nseg, 1.0); + + const vec2_t *cp = curve->cp + cidx * 2; + Vector2 cp0 = cp[0]; + Vector2 cp1 = cp[1]; + Vector2 cp2 = cp[2]; + + Vector2 pprev, pnext; + for(int i=0; i<2; i++) { + pprev[i] = bezier(cp0[i], cp1[i], cp1[i], cp2[i], t - 0.05); + pnext[i] = bezier(cp0[i], cp1[i], cp1[i], cp2[i], t + 0.05); + } + + float tx = pnext.x - pprev.x; + float ty = pnext.y - pprev.y; + + return Vector2(-ty, tx); +} diff -r 1e8d90aeae34 -r 3b4460b34d43 src/revol.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/revol.h Sun Aug 23 05:37:09 2015 +0300 @@ -0,0 +1,15 @@ +#ifndef REVOL_H_ +#define REVOL_H_ + +#include "vmath/vmath.h" + +struct BezCurve { + int numcp; + vec2_t *cp; + float scale; +}; + +Vector2 bezier_revol(float u, float v, void *cls); +Vector2 bezier_revol_normal(float u, float v, void *cls); + +#endif // REVOL_H_ diff -r 1e8d90aeae34 -r 3b4460b34d43 src/room.cc --- a/src/room.cc Sun Aug 23 04:45:24 2015 +0300 +++ b/src/room.cc Sun Aug 23 05:37:09 2015 +0300 @@ -5,25 +5,60 @@ #include "object.h" #include "scene.h" #include "meshgen.h" +#include "revol.h" static Scene scn; +static const vec2_t pillar_cp[] = { + {0.8, 10}, + {1.2, 5.5}, + {1, 0} +}; +static const BezCurve pillar_curve = { + sizeof pillar_cp / sizeof *pillar_cp, + (vec2_t*)pillar_cp, 1.0 +}; + bool init_room() { Matrix4x4 xform; // generate room Mesh *mroom = new Mesh; - gen_box(mroom, 50, 25, 50); - xform.set_translation(Vector3(0, 12.5, 0)); + gen_box(mroom, ROOM_WIDTH, ROOM_HEIGHT, ROOM_LENGTH); + xform.set_translation(Vector3(0, ROOM_HEIGHT / 2.0, 0)); mroom->apply_xform(xform); mroom->flip(); Object *oroom = new Object; oroom->set_mesh(mroom); + oroom->mtl.diffuse = Vector3(0.5, 0.5, 0.5); oroom->rop.cast_shadows = false; + scn.add_object(oroom); - scn.add_object(oroom); + for(int i=0; i<8; i++) { + float x = (i < 4 ? -1.0 : 1.0) * ROOM_WIDTH * 0.3; + float z = (float)(i % 4) * 12.5 - 12.5; + + Mesh *mpillar = new Mesh; + gen_revol(mpillar, 16, 3, bezier_revol, bezier_revol_normal, (void*)&pillar_curve); + + Mesh mtorus; + gen_torus(&mtorus, 1.0, 0.25, 16, 8); + Matrix4x4 xform; + xform.set_translation(Vector3(0, 0.1, 0)); + mtorus.apply_xform(xform, Matrix4x4::identity); + mpillar->append(mtorus); + + mpillar->texcoord_gen_cylinder(); + + Object *opillar = new Object; + opillar->set_mesh(mpillar); + opillar->mtl.diffuse = Vector3(0.6, 0.6, 0.6); + opillar->xform().set_translation(Vector3(x, 0.0, z)); + + scn.add_object(opillar); + } return true; } diff -r 1e8d90aeae34 -r 3b4460b34d43 src/room.h --- a/src/room.h Sun Aug 23 04:45:24 2015 +0300 +++ b/src/room.h Sun Aug 23 05:37:09 2015 +0300 @@ -1,6 +1,12 @@ #ifndef ROOM_H_ #define ROOM_H_ + +#define ROOM_WIDTH 30.0f +#define ROOM_HEIGHT 10.0f +#define ROOM_LENGTH 50.0f + + bool init_room(); void cleanup_room(); void draw_room(); diff -r 1e8d90aeae34 -r 3b4460b34d43 src/shadow.cc --- a/src/shadow.cc Sun Aug 23 04:45:24 2015 +0300 +++ b/src/shadow.cc Sun Aug 23 05:37:09 2015 +0300 @@ -90,7 +90,7 @@ glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glPolygonOffset(1.1, 4.0); + glPolygonOffset(2.0, 4.0); glEnable(GL_POLYGON_OFFSET_FILL); glClear(GL_DEPTH_BUFFER_BIT);