# HG changeset patch # User John Tsiombikas # Date 1440452280 -10800 # Node ID 92d662deb66e5ede39e03c9831fc1bff7a31062a # Parent 3b4460b34d432a74d82eef6b37c83f08d172ef11 capsule distance seems broken diff -r 3b4460b34d43 -r 92d662deb66e Makefile --- a/Makefile Sun Aug 23 05:37:09 2015 +0300 +++ b/Makefile Tue Aug 25 00:38:00 2015 +0300 @@ -9,11 +9,11 @@ warn = -pedantic -Wall -Wno-format-extra-args dbg = -g -opt = -O0 +opt = -O3 CFLAGS = $(warn) $(dbg) $(opt) CXXFLAGS = $(CFLAGS) -LDFLAGS = $(libgl) -lvmath -limago -lpsys -lanim -lm +LDFLAGS = $(libgl) -lvmath -limago -lpsys -lanim -lm -lmetasurf ifeq ($(sys), Darwin) libgl = -framework OpenGL -framework GLUT -lGLEW diff -r 3b4460b34d43 -r 92d662deb66e sdr/shadow.v.glsl --- a/sdr/shadow.v.glsl Sun Aug 23 05:37:09 2015 +0300 +++ b/sdr/shadow.v.glsl Tue Aug 25 00:38:00 2015 +0300 @@ -6,7 +6,7 @@ gl_Position = ftransform(); vec3 vpos = (gl_ModelViewMatrix * gl_Vertex).xyz; - normal = gl_NormalMatrix * gl_Normal; + normal = normalize(gl_NormalMatrix * gl_Normal); vdir = -vpos; ldir = gl_LightSource[0].position.xyz - vpos; gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; diff -r 3b4460b34d43 -r 92d662deb66e src/dragon.cc --- a/src/dragon.cc Sun Aug 23 05:37:09 2015 +0300 +++ b/src/dragon.cc Tue Aug 25 00:38:00 2015 +0300 @@ -1,15 +1,60 @@ #include #include "opengl.h" #include "dragon.h" +#include "metasurf.h" +#include "geom.h" +#include "game.h" +#include "shadow.h" + +#define VOXEL_PAD 1.0f +#define DYN_FCOUNT 64 +#define DYN_VCOUNT (DYN_FCOUNT * 3) + +#define NUM_NECK_SEG 8 +static const float nseg_sizes[NUM_NECK_SEG][2] = { + {1.0, 3.0}, {1.0, 1.5}, {1.5, 2.0}, {2.0, 2.5}, {2.5, 3.0}, {3.0, 3.5} +}; + +static Vector3 bezier(const Vector3 &a, const Vector3 &b, const Vector3 &c, const Vector3 &d, float t); +static float mseval(struct metasurface *ms, float x, float y, float z); +static void msvertex(struct metasurface *ms, float x, float y, float z); + 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); + + glGenBuffers(1, &dyn_vbo); + glBindBuffer(GL_ARRAY_BUFFER, dyn_vbo); + glBufferData(GL_ARRAY_BUFFER, DYN_VCOUNT * sizeof(DynVertex), 0, GL_STREAM_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + dyn_varr = new DynVertex[DYN_VCOUNT]; + + neck_seg_count = NUM_NECK_SEG; + neck_seg = new Capsule[neck_seg_count]; + + for(int i=0; ineck_seg; - glPushAttrib(GL_ENABLE_BIT); - glDisable(GL_LIGHTING); + //printf("eval(%g %g %g)\n", x, y, z); - glLineWidth(2.0); - glColor3f(0, 0, 1); + float sum = 0.0f; + for(int i=0; ineck_seg_count; i++) { + float dist = capsule_distance(seg[i].p[0], seg[i].w[0], seg[i].p[1], seg[i].w[1], pt); + //float dist = sphere_distance(seg[i].p[0], 1.0, pt); + if(dist < 1e-4) dist = 1e-4; + float energy = 0.0001 / (dist * dist); + /*float dx = x - seg[i].p[0].x; + float dy = y - seg[i].p[0].y; + float dz = z - seg[i].p[0].z; + float energy = 0.5 / (dx * dx + dy * dy + dz * dz);*/ + sum += energy; + } + return sum; +} - 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); +static void msvertex(struct metasurface *ms, float x, float y, float z) +{ + Dragon *dragon = (Dragon*)msurf_get_user_data(ms); + + const float dt = 0.001; + float dfdx = mseval(ms, x - dt, y, z) - mseval(ms, x + dt, y, z); + float dfdy = mseval(ms, x, y - dt, z) - mseval(ms, x, y + dt, z); + float dfdz = mseval(ms, x, y, z - dt) - mseval(ms, x, y, z + dt); + + DynVertex *vptr = dragon->dyn_varr + dragon->dyn_vidx++; + vptr->x = x; + vptr->y = y; + vptr->z = z; + vptr->nx = dfdx; + vptr->ny = dfdy; + vptr->nz = dfdz; + + if(dragon->dyn_vidx >= DYN_VCOUNT) { + dragon->flush_dynvbo(); } - 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 3b4460b34d43 -r 92d662deb66e src/dragon.h --- a/src/dragon.h Sun Aug 23 05:37:09 2015 +0300 +++ b/src/dragon.h Tue Aug 25 00:38:00 2015 +0300 @@ -2,6 +2,18 @@ #define DRAGON_H_ #include "vmath/vmath.h" +#include "mesh.h" +#include "metasurf.h" + +struct Capsule { + Vector3 p[2]; + float w[2]; +}; + +struct DynVertex { + float x, y, z; + float nx, ny, nz; +}; class Dragon { private: @@ -9,6 +21,8 @@ Vector3 head_pos, target; float head_xlim[2], head_ylim[2]; + struct metasurface *msurf; + public: Dragon(); ~Dragon(); @@ -25,6 +39,15 @@ void update(); void draw() const; + + // implementation details, must be public for the msurf callbacks + Capsule *neck_seg; + int neck_seg_count; + DynVertex *dyn_varr; + mutable int dyn_vidx; + unsigned int dyn_vbo; + + void flush_dynvbo() const; }; #endif // DRAGON_H_ diff -r 3b4460b34d43 -r 92d662deb66e src/game.cc --- a/src/game.cc Sun Aug 23 05:37:09 2015 +0300 +++ b/src/game.cc Tue Aug 25 00:38:00 2015 +0300 @@ -29,7 +29,7 @@ static unsigned int modkeys; -static Dragon dragon; +static Dragon *dragon; bool game_init() @@ -71,11 +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); + dragon = new Dragon; + 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; @@ -85,6 +86,7 @@ void game_cleanup() { + delete dragon; cleanup_room(); } @@ -92,7 +94,7 @@ { cur_time = time_msec; - dragon.update(); + dragon->update(); } void game_display() @@ -158,7 +160,7 @@ glPopMatrix(); - dragon.draw(); + dragon->draw(); } @@ -231,7 +233,7 @@ prev_y = y; if(gamectl) { - dragon.move_head(dx * 0.1, -dy * 0.1); + dragon->move_head(dx * 0.1, -dy * 0.1); } if(modkeys) { diff -r 3b4460b34d43 -r 92d662deb66e src/geom.cc --- a/src/geom.cc Sun Aug 23 05:37:09 2015 +0300 +++ b/src/geom.cc Tue Aug 25 00:38:00 2015 +0300 @@ -1,5 +1,6 @@ +#include +#include #include -#include #include "geom.h" GeomObject::~GeomObject() @@ -249,3 +250,57 @@ } return true; } + +float sphere_distance(const Vector3 ¢, float rad, const Vector3 &pt) +{ + return (pt - cent).length() - rad; +} + +float capsule_distance(const Vector3 &a, float ra, const Vector3 &b, float rb, const Vector3 &pt) +{ + Vector3 ab_dir = b - a; + + if(fabs(ab_dir.length_sq()) < 1e-5) { + // if a == b, the capsule is a sphere with radius the maximum of the capsule radii + return sphere_distance(a, std::max(ra, rb), pt); + } + float ab_len = ab_dir.length(); + + Vector3 ap_dir = pt - a; + Vector3 rotaxis = cross_product(ab_dir, ap_dir).normalized(); + + Matrix4x4 rmat; + rmat.set_rotation(rotaxis, M_PI / 2.0); + Vector3 right = ab_dir.transformed(rmat) / ab_len; + + // XXX I think this check is redundant, always false, due to the cross product order + //assert(dot_product(right, ab_dir) >= 0.0); + if(dot_product(right, ab_dir) < 0.0) { + right = -right; + } + Vector3 aa = a + right * ra; + Vector3 bb = b + right * rb; + + // project pt to the line segment bb-aa, see if the projection lies within the interval [0, 1) + Vector3 aabb_dir = bb - aa; + float aabb_len = aabb_dir.length(); + Vector3 aap_dir = pt - aa; + + float t = dot_product(aap_dir, aabb_dir / aabb_len) / aabb_len; + if(t < 0.0) { + return sphere_distance(a, ra, pt); + } + if(t >= 1.0) { + return sphere_distance(b, rb, pt); + } + + Vector3 ppt = aa + aabb_dir * t; + Vector3 norm = ppt - pt; + float dist = norm.length(); + + if(dot_product(norm, right) < 0.0) { + // inside the cone + dist = -dist; + } + return dist; +} diff -r 3b4460b34d43 -r 92d662deb66e src/geom.h --- a/src/geom.h Sun Aug 23 05:37:09 2015 +0300 +++ b/src/geom.h Tue Aug 25 00:38:00 2015 +0300 @@ -67,4 +67,7 @@ bool intersect(const Ray &ray, HitPoint *hit = 0) const; }; +float sphere_distance(const Vector3 ¢, float rad, const Vector3 &pt); +float capsule_distance(const Vector3 &a, float ra, const Vector3 &b, float rb, const Vector3 &pt); + #endif // GEOMOBJ_H_