ld33_umonster

changeset 7:92d662deb66e

capsule distance seems broken
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 25 Aug 2015 00:38:00 +0300
parents 3b4460b34d43
children bed39534d471
files Makefile sdr/shadow.v.glsl src/dragon.cc src/dragon.h src/game.cc src/geom.cc src/geom.h
diffstat 7 files changed, 291 insertions(+), 43 deletions(-) [+]
line diff
     1.1 --- a/Makefile	Sun Aug 23 05:37:09 2015 +0300
     1.2 +++ b/Makefile	Tue Aug 25 00:38:00 2015 +0300
     1.3 @@ -9,11 +9,11 @@
     1.4  
     1.5  warn = -pedantic -Wall -Wno-format-extra-args
     1.6  dbg = -g
     1.7 -opt = -O0
     1.8 +opt = -O3
     1.9  
    1.10  CFLAGS = $(warn) $(dbg) $(opt)
    1.11  CXXFLAGS = $(CFLAGS)
    1.12 -LDFLAGS = $(libgl) -lvmath -limago -lpsys -lanim -lm
    1.13 +LDFLAGS = $(libgl) -lvmath -limago -lpsys -lanim -lm -lmetasurf
    1.14  
    1.15  ifeq ($(sys), Darwin)
    1.16  	libgl = -framework OpenGL -framework GLUT -lGLEW
     2.1 --- a/sdr/shadow.v.glsl	Sun Aug 23 05:37:09 2015 +0300
     2.2 +++ b/sdr/shadow.v.glsl	Tue Aug 25 00:38:00 2015 +0300
     2.3 @@ -6,7 +6,7 @@
     2.4  	gl_Position = ftransform();
     2.5  
     2.6  	vec3 vpos = (gl_ModelViewMatrix * gl_Vertex).xyz;
     2.7 -	normal = gl_NormalMatrix * gl_Normal;
     2.8 +	normal = normalize(gl_NormalMatrix * gl_Normal);
     2.9  	vdir = -vpos;
    2.10  	ldir = gl_LightSource[0].position.xyz - vpos;
    2.11  	gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
     3.1 --- a/src/dragon.cc	Sun Aug 23 05:37:09 2015 +0300
     3.2 +++ b/src/dragon.cc	Tue Aug 25 00:38:00 2015 +0300
     3.3 @@ -1,15 +1,60 @@
     3.4  #include <algorithm>
     3.5  #include "opengl.h"
     3.6  #include "dragon.h"
     3.7 +#include "metasurf.h"
     3.8 +#include "geom.h"
     3.9 +#include "game.h"
    3.10 +#include "shadow.h"
    3.11 +
    3.12 +#define VOXEL_PAD		1.0f
    3.13 +#define DYN_FCOUNT		64
    3.14 +#define DYN_VCOUNT		(DYN_FCOUNT * 3)
    3.15 +
    3.16 +#define NUM_NECK_SEG	8
    3.17 +static const float nseg_sizes[NUM_NECK_SEG][2] = {
    3.18 +	{1.0, 3.0}, {1.0, 1.5}, {1.5, 2.0}, {2.0, 2.5}, {2.5, 3.0}, {3.0, 3.5}
    3.19 +};
    3.20 +
    3.21 +static Vector3 bezier(const Vector3 &a, const Vector3 &b, const Vector3 &c, const Vector3 &d, float t);
    3.22 +static float mseval(struct metasurface *ms, float x, float y, float z);
    3.23 +static void msvertex(struct metasurface *ms, float x, float y, float z);
    3.24 +
    3.25  
    3.26  Dragon::Dragon()
    3.27  	: pos(0, 0, 0), dir(0, 0, -1), head_pos(0, 0, -1), target(0, 0, -2)
    3.28  {
    3.29  	set_head_limits(-1, 1, -1, 1);
    3.30 +
    3.31 +	glGenBuffers(1, &dyn_vbo);
    3.32 +	glBindBuffer(GL_ARRAY_BUFFER, dyn_vbo);
    3.33 +	glBufferData(GL_ARRAY_BUFFER, DYN_VCOUNT * sizeof(DynVertex), 0, GL_STREAM_DRAW);
    3.34 +	glBindBuffer(GL_ARRAY_BUFFER, 0);
    3.35 +
    3.36 +	dyn_varr = new DynVertex[DYN_VCOUNT];
    3.37 +
    3.38 +	neck_seg_count = NUM_NECK_SEG;
    3.39 +	neck_seg = new Capsule[neck_seg_count];
    3.40 +
    3.41 +	for(int i=0; i<neck_seg_count; i++) {
    3.42 +		neck_seg[i].w[0] = nseg_sizes[i][0];
    3.43 +		neck_seg[i].w[1] = nseg_sizes[i][1];
    3.44 +	}
    3.45 +
    3.46 +	msurf = msurf_create();
    3.47 +	msurf_set_user_data(msurf, this);
    3.48 +	msurf_set_resolution(msurf, 36, 36, 36);
    3.49 +	msurf_set_threshold(msurf, 1.0);
    3.50 +	msurf_eval_func(msurf, mseval);
    3.51 +	msurf_vertex_func(msurf, msvertex);
    3.52  }
    3.53  
    3.54  Dragon::~Dragon()
    3.55  {
    3.56 +	delete [] neck_seg;
    3.57 +	msurf_free(msurf);
    3.58 +
    3.59 +	delete [] dyn_varr;
    3.60 +	glDeleteBuffers(1, &dyn_vbo);
    3.61  }
    3.62  
    3.63  void Dragon::set_position(const Vector3 &p)
    3.64 @@ -71,8 +116,120 @@
    3.65  
    3.66  void Dragon::update()
    3.67  {
    3.68 +	Vector3 bdir = breath_dir();
    3.69 +	Vector3 bezcp[] = { pos, pos + dir * 6.0, head_pos - bdir * 8.0, head_pos };
    3.70 +
    3.71 +	float t = 0.0, dt = 1.0 / (float)(neck_seg_count + 1);
    3.72 +	Vector3 p = bezier(bezcp[0], bezcp[1], bezcp[2], bezcp[3], t);
    3.73 +
    3.74 +	for(int i=0; i<neck_seg_count; i++) {
    3.75 +		t += dt;
    3.76 +		Vector3 pnext = bezier(bezcp[0], bezcp[1], bezcp[2], bezcp[3], t);
    3.77 +
    3.78 +		neck_seg[i].p[0] = p;
    3.79 +		neck_seg[i].p[1] = pnext;
    3.80 +
    3.81 +		p = pnext;
    3.82 +	}
    3.83  }
    3.84  
    3.85 +void Dragon::draw() const
    3.86 +{
    3.87 +	static float bmin[] = { head_xlim[0] - VOXEL_PAD * 0.9, head_ylim[0] - VOXEL_PAD, head_pos.z };
    3.88 +	static float bmax[] = { head_xlim[1] + VOXEL_PAD * 0.9, head_ylim[1] + VOXEL_PAD * 2.1f, pos.z + VOXEL_PAD };
    3.89 +	msurf_set_bounds(msurf, bmin[0], bmin[1], bmin[2], bmax[0], bmax[1], bmax[2]);
    3.90 +
    3.91 +
    3.92 +	if(!shadow_pass) {
    3.93 +
    3.94 +		if(dbg_wireframe) {
    3.95 +			glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    3.96 +		}
    3.97 +
    3.98 +		dyn_vidx = 0;
    3.99 +		msurf_polygonize(msurf);
   3.100 +		flush_dynvbo();
   3.101 +
   3.102 +		if(dbg_wireframe) {
   3.103 +			glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
   3.104 +		}
   3.105 +
   3.106 +		int cur_sdr;
   3.107 +		glGetIntegerv(GL_CURRENT_PROGRAM, &cur_sdr);
   3.108 +		glUseProgram(0);
   3.109 +
   3.110 +		glPushAttrib(GL_ENABLE_BIT);
   3.111 +		glDisable(GL_LIGHTING);
   3.112 +
   3.113 +		// bounds
   3.114 +		glColor3f(1, 0, 0);
   3.115 +		glBegin(GL_LINE_LOOP);
   3.116 +		glVertex3f(bmin[0], bmin[1], bmin[2]);
   3.117 +		glVertex3f(bmax[0], bmin[1], bmin[2]);
   3.118 +		glVertex3f(bmax[0], bmax[1], bmin[2]);
   3.119 +		glVertex3f(bmin[0], bmax[1], bmin[2]);
   3.120 +		glEnd();
   3.121 +		glBegin(GL_LINE_LOOP);
   3.122 +		glVertex3f(bmin[0], bmin[1], bmax[2]);
   3.123 +		glVertex3f(bmax[0], bmin[1], bmax[2]);
   3.124 +		glVertex3f(bmax[0], bmax[1], bmax[2]);
   3.125 +		glVertex3f(bmin[0], bmax[1], bmax[2]);
   3.126 +		glEnd();
   3.127 +		glBegin(GL_LINE_LOOP);
   3.128 +		glVertex3f(bmin[0], bmax[1], bmin[2]);
   3.129 +		glVertex3f(bmax[0], bmax[1], bmin[2]);
   3.130 +		glVertex3f(bmax[0], bmax[1], bmax[2]);
   3.131 +		glVertex3f(bmin[0], bmax[1], bmax[2]);
   3.132 +		glEnd();
   3.133 +		glBegin(GL_LINE_LOOP);
   3.134 +		glVertex3f(bmin[0], bmin[1], bmin[2]);
   3.135 +		glVertex3f(bmax[0], bmin[1], bmin[2]);
   3.136 +		glVertex3f(bmax[0], bmin[1], bmax[2]);
   3.137 +		glVertex3f(bmin[0], bmin[1], bmax[2]);
   3.138 +		glEnd();
   3.139 +
   3.140 +		// foo
   3.141 +		glDisable(GL_DEPTH_TEST);
   3.142 +		glEnable(GL_BLEND);
   3.143 +		glBlendFunc(GL_ONE, GL_ONE);
   3.144 +		glLineWidth(2.0);
   3.145 +		glColor3f(0, 0, 1);
   3.146 +
   3.147 +		glBegin(GL_LINES);
   3.148 +		for(int i=0; i<neck_seg_count; i++) {
   3.149 +			glVertex3f(neck_seg[i].p[0].x, neck_seg[i].p[0].y, neck_seg[i].p[0].z);
   3.150 +			glVertex3f(neck_seg[i].p[1].x, neck_seg[i].p[1].y, neck_seg[i].p[1].z);
   3.151 +		}
   3.152 +		glEnd();
   3.153 +		glLineWidth(1);
   3.154 +
   3.155 +		// done debug drawing
   3.156 +		glPopAttrib();
   3.157 +		if(cur_sdr) glUseProgram(cur_sdr);
   3.158 +	}
   3.159 +}
   3.160 +
   3.161 +void Dragon::flush_dynvbo() const
   3.162 +{
   3.163 +	if(!dyn_vidx) return;
   3.164 +
   3.165 +	glBindBuffer(GL_ARRAY_BUFFER, dyn_vbo);
   3.166 +	glBufferSubData(GL_ARRAY_BUFFER, 0, dyn_vidx * sizeof(DynVertex), dyn_varr);
   3.167 +
   3.168 +	glEnableClientState(GL_VERTEX_ARRAY);
   3.169 +	glVertexPointer(3, GL_FLOAT, sizeof(DynVertex), (void*)offsetof(DynVertex, x));
   3.170 +	glEnableClientState(GL_NORMAL_ARRAY);
   3.171 +	glNormalPointer(GL_FLOAT, sizeof(DynVertex), (void*)offsetof(DynVertex, nx));
   3.172 +	glBindBuffer(GL_ARRAY_BUFFER, 0);
   3.173 +
   3.174 +	glDrawArrays(GL_TRIANGLES, 0, dyn_vidx);
   3.175 +
   3.176 +	glDisableClientState(GL_VERTEX_ARRAY);
   3.177 +	glDisableClientState(GL_NORMAL_ARRAY);
   3.178 +	dyn_vidx = 0;
   3.179 +}
   3.180 +
   3.181 +
   3.182  static Vector3 bezier(const Vector3 &a, const Vector3 &b, const Vector3 &c, const Vector3 &d, float t)
   3.183  {
   3.184  	float x = bezier(a.x, b.x, c.x, d.x, t);
   3.185 @@ -81,40 +238,48 @@
   3.186  	return Vector3(x, y, z);
   3.187  }
   3.188  
   3.189 -void Dragon::draw() const
   3.190 +static float mseval(struct metasurface *ms, float x, float y, float z)
   3.191  {
   3.192 -	Vector3 bdir = breath_dir();
   3.193 -	Vector3 bezcp[] = { pos, pos + dir * 6.0, head_pos - bdir * 8.0, head_pos };
   3.194 +	Dragon *dragon = (Dragon*)msurf_get_user_data(ms);
   3.195  
   3.196 -	int cur_sdr;
   3.197 -	glGetIntegerv(GL_CURRENT_PROGRAM, &cur_sdr);
   3.198 -	glUseProgram(0);
   3.199 +	Vector3 pt = Vector3(x, y, z);
   3.200 +	Capsule *seg = dragon->neck_seg;
   3.201  
   3.202 -	glPushAttrib(GL_ENABLE_BIT);
   3.203 -	glDisable(GL_LIGHTING);
   3.204 +	//printf("eval(%g %g %g)\n", x, y, z);
   3.205  
   3.206 -	glLineWidth(2.0);
   3.207 -	glColor3f(0, 0, 1);
   3.208 +	float sum = 0.0f;
   3.209 +	for(int i=0; i<dragon->neck_seg_count; i++) {
   3.210 +		float dist = capsule_distance(seg[i].p[0], seg[i].w[0], seg[i].p[1], seg[i].w[1], pt);
   3.211 +		//float dist = sphere_distance(seg[i].p[0], 1.0, pt);
   3.212 +		if(dist < 1e-4) dist = 1e-4;
   3.213 +		float energy = 0.0001 / (dist * dist);
   3.214 +		/*float dx = x - seg[i].p[0].x;
   3.215 +		float dy = y - seg[i].p[0].y;
   3.216 +		float dz = z - seg[i].p[0].z;
   3.217 +		float energy = 0.5 / (dx * dx + dy * dy + dz * dz);*/
   3.218 +		sum += energy;
   3.219 +	}
   3.220 +	return sum;
   3.221 +}
   3.222  
   3.223 -	glBegin(GL_LINE_STRIP);
   3.224 -	for(int i=0; i<10; i++) {
   3.225 -		float t = (float)i / 10.0f;
   3.226 -		Vector3 p = bezier(bezcp[0], bezcp[1], bezcp[2], bezcp[3], t);
   3.227 -		glVertex3f(p.x, p.y, p.z);
   3.228 +static void msvertex(struct metasurface *ms, float x, float y, float z)
   3.229 +{
   3.230 +	Dragon *dragon = (Dragon*)msurf_get_user_data(ms);
   3.231 +
   3.232 +	const float dt = 0.001;
   3.233 +	float dfdx = mseval(ms, x - dt, y, z) - mseval(ms, x + dt, y, z);
   3.234 +	float dfdy = mseval(ms, x, y - dt, z) - mseval(ms, x, y + dt, z);
   3.235 +	float dfdz = mseval(ms, x, y, z - dt) - mseval(ms, x, y, z + dt);
   3.236 +
   3.237 +	DynVertex *vptr = dragon->dyn_varr + dragon->dyn_vidx++;
   3.238 +	vptr->x = x;
   3.239 +	vptr->y = y;
   3.240 +	vptr->z = z;
   3.241 +	vptr->nx = dfdx;
   3.242 +	vptr->ny = dfdy;
   3.243 +	vptr->nz = dfdz;
   3.244 +
   3.245 +	if(dragon->dyn_vidx >= DYN_VCOUNT) {
   3.246 +		dragon->flush_dynvbo();
   3.247  	}
   3.248 -	glEnd();
   3.249 -	glLineWidth(1);
   3.250 -
   3.251 -	glPointSize(5.0);
   3.252 -	glColor3f(0, 1, 0);
   3.253 -
   3.254 -	glBegin(GL_POINTS);
   3.255 -	for(int i=0; i<4; i++) {
   3.256 -		glVertex3f(bezcp[i].x, bezcp[i].y, bezcp[i].z);
   3.257 -	}
   3.258 -	glEnd();
   3.259 -
   3.260 -	glPopAttrib();
   3.261 -
   3.262 -	glUseProgram(cur_sdr);
   3.263  }
     4.1 --- a/src/dragon.h	Sun Aug 23 05:37:09 2015 +0300
     4.2 +++ b/src/dragon.h	Tue Aug 25 00:38:00 2015 +0300
     4.3 @@ -2,6 +2,18 @@
     4.4  #define DRAGON_H_
     4.5  
     4.6  #include "vmath/vmath.h"
     4.7 +#include "mesh.h"
     4.8 +#include "metasurf.h"
     4.9 +
    4.10 +struct Capsule {
    4.11 +	Vector3 p[2];
    4.12 +	float w[2];
    4.13 +};
    4.14 +
    4.15 +struct DynVertex {
    4.16 +	float x, y, z;
    4.17 +	float nx, ny, nz;
    4.18 +};
    4.19  
    4.20  class Dragon {
    4.21  private:
    4.22 @@ -9,6 +21,8 @@
    4.23  	Vector3 head_pos, target;
    4.24  	float head_xlim[2], head_ylim[2];
    4.25  
    4.26 +	struct metasurface *msurf;
    4.27 +
    4.28  public:
    4.29  	Dragon();
    4.30  	~Dragon();
    4.31 @@ -25,6 +39,15 @@
    4.32  
    4.33  	void update();
    4.34  	void draw() const;
    4.35 +
    4.36 +	// implementation details, must be public for the msurf callbacks
    4.37 +	Capsule *neck_seg;
    4.38 +	int neck_seg_count;
    4.39 +	DynVertex *dyn_varr;
    4.40 +	mutable int dyn_vidx;
    4.41 +	unsigned int dyn_vbo;
    4.42 +
    4.43 +	void flush_dynvbo() const;
    4.44  };
    4.45  
    4.46  #endif	// DRAGON_H_
     5.1 --- a/src/game.cc	Sun Aug 23 05:37:09 2015 +0300
     5.2 +++ b/src/game.cc	Tue Aug 25 00:38:00 2015 +0300
     5.3 @@ -29,7 +29,7 @@
     5.4  static unsigned int modkeys;
     5.5  
     5.6  
     5.7 -static Dragon dragon;
     5.8 +static Dragon *dragon;
     5.9  
    5.10  
    5.11  bool game_init()
    5.12 @@ -71,11 +71,12 @@
    5.13  		return false;
    5.14  	}
    5.15  
    5.16 -	dragon.set_position(Vector3(0, 5, 20));
    5.17 -	dragon.set_direction(Vector3(0, 0, -1));
    5.18 -	dragon.set_target(Vector3(0, 3, 0));
    5.19 -	dragon.move_head(Vector3(0, 6, 10));
    5.20 -	dragon.set_head_limits(-ROOM_WIDTH * 0.2, ROOM_WIDTH * 0.2, 1, ROOM_HEIGHT - 3);
    5.21 +	dragon = new Dragon;
    5.22 +	dragon->set_position(Vector3(0, 5, 20));
    5.23 +	dragon->set_direction(Vector3(0, 0, -1));
    5.24 +	dragon->set_target(Vector3(0, 3, 0));
    5.25 +	dragon->move_head(Vector3(0, 6, 10));
    5.26 +	dragon->set_head_limits(-ROOM_WIDTH * 0.2, ROOM_WIDTH * 0.2, 1, ROOM_HEIGHT - 3);
    5.27  
    5.28  	Mesh::use_custom_sdr_attr = false;
    5.29  
    5.30 @@ -85,6 +86,7 @@
    5.31  
    5.32  void game_cleanup()
    5.33  {
    5.34 +	delete dragon;
    5.35  	cleanup_room();
    5.36  }
    5.37  
    5.38 @@ -92,7 +94,7 @@
    5.39  {
    5.40  	cur_time = time_msec;
    5.41  
    5.42 -	dragon.update();
    5.43 +	dragon->update();
    5.44  }
    5.45  
    5.46  void game_display()
    5.47 @@ -158,7 +160,7 @@
    5.48  
    5.49  	glPopMatrix();
    5.50  
    5.51 -	dragon.draw();
    5.52 +	dragon->draw();
    5.53  }
    5.54  
    5.55  
    5.56 @@ -231,7 +233,7 @@
    5.57  	prev_y = y;
    5.58  
    5.59  	if(gamectl) {
    5.60 -		dragon.move_head(dx * 0.1, -dy * 0.1);
    5.61 +		dragon->move_head(dx * 0.1, -dy * 0.1);
    5.62  	}
    5.63  
    5.64  	if(modkeys) {
     6.1 --- a/src/geom.cc	Sun Aug 23 05:37:09 2015 +0300
     6.2 +++ b/src/geom.cc	Tue Aug 25 00:38:00 2015 +0300
     6.3 @@ -1,5 +1,6 @@
     6.4 +#include <assert.h>
     6.5 +#include <float.h>
     6.6  #include <algorithm>
     6.7 -#include <float.h>
     6.8  #include "geom.h"
     6.9  
    6.10  GeomObject::~GeomObject()
    6.11 @@ -249,3 +250,57 @@
    6.12  	}
    6.13  	return true;
    6.14  }
    6.15 +
    6.16 +float sphere_distance(const Vector3 &cent, float rad, const Vector3 &pt)
    6.17 +{
    6.18 +	return (pt - cent).length() - rad;
    6.19 +}
    6.20 +
    6.21 +float capsule_distance(const Vector3 &a, float ra, const Vector3 &b, float rb, const Vector3 &pt)
    6.22 +{
    6.23 +	Vector3 ab_dir = b - a;
    6.24 +
    6.25 +	if(fabs(ab_dir.length_sq()) < 1e-5) {
    6.26 +		// if a == b, the capsule is a sphere with radius the maximum of the capsule radii
    6.27 +		return sphere_distance(a, std::max(ra, rb), pt);
    6.28 +	}
    6.29 +	float ab_len = ab_dir.length();
    6.30 +
    6.31 +	Vector3 ap_dir = pt - a;
    6.32 +	Vector3 rotaxis = cross_product(ab_dir, ap_dir).normalized();
    6.33 +
    6.34 +	Matrix4x4 rmat;
    6.35 +	rmat.set_rotation(rotaxis, M_PI / 2.0);
    6.36 +	Vector3 right = ab_dir.transformed(rmat) / ab_len;
    6.37 +
    6.38 +	// XXX I think this check is redundant, always false, due to the cross product order
    6.39 +	//assert(dot_product(right, ab_dir) >= 0.0);
    6.40 +	if(dot_product(right, ab_dir) < 0.0) {
    6.41 +		right = -right;
    6.42 +	}
    6.43 +	Vector3 aa = a + right * ra;
    6.44 +	Vector3 bb = b + right * rb;
    6.45 +
    6.46 +	// project pt to the line segment bb-aa, see if the projection lies within the interval [0, 1)
    6.47 +	Vector3 aabb_dir = bb - aa;
    6.48 +	float aabb_len = aabb_dir.length();
    6.49 +	Vector3 aap_dir = pt - aa;
    6.50 +
    6.51 +	float t = dot_product(aap_dir, aabb_dir / aabb_len) / aabb_len;
    6.52 +	if(t < 0.0) {
    6.53 +		return sphere_distance(a, ra, pt);
    6.54 +	}
    6.55 +	if(t >= 1.0) {
    6.56 +		return sphere_distance(b, rb, pt);
    6.57 +	}
    6.58 +
    6.59 +	Vector3 ppt = aa + aabb_dir * t;
    6.60 +	Vector3 norm = ppt - pt;
    6.61 +	float dist = norm.length();
    6.62 +
    6.63 +	if(dot_product(norm, right) < 0.0) {
    6.64 +		// inside the cone
    6.65 +		dist = -dist;
    6.66 +	}
    6.67 +	return dist;
    6.68 +}
     7.1 --- a/src/geom.h	Sun Aug 23 05:37:09 2015 +0300
     7.2 +++ b/src/geom.h	Tue Aug 25 00:38:00 2015 +0300
     7.3 @@ -67,4 +67,7 @@
     7.4  	bool intersect(const Ray &ray, HitPoint *hit = 0) const;
     7.5  };
     7.6  
     7.7 +float sphere_distance(const Vector3 &cent, float rad, const Vector3 &pt);
     7.8 +float capsule_distance(const Vector3 &a, float ra, const Vector3 &b, float rb, const Vector3 &pt);
     7.9 +
    7.10  #endif	// GEOMOBJ_H_