ld33_umonster

diff src/dragon.cc @ 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
line diff
     1.1 --- a/src/dragon.cc	Sun Aug 23 05:37:09 2015 +0300
     1.2 +++ b/src/dragon.cc	Tue Aug 25 00:38:00 2015 +0300
     1.3 @@ -1,15 +1,60 @@
     1.4  #include <algorithm>
     1.5  #include "opengl.h"
     1.6  #include "dragon.h"
     1.7 +#include "metasurf.h"
     1.8 +#include "geom.h"
     1.9 +#include "game.h"
    1.10 +#include "shadow.h"
    1.11 +
    1.12 +#define VOXEL_PAD		1.0f
    1.13 +#define DYN_FCOUNT		64
    1.14 +#define DYN_VCOUNT		(DYN_FCOUNT * 3)
    1.15 +
    1.16 +#define NUM_NECK_SEG	8
    1.17 +static const float nseg_sizes[NUM_NECK_SEG][2] = {
    1.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}
    1.19 +};
    1.20 +
    1.21 +static Vector3 bezier(const Vector3 &a, const Vector3 &b, const Vector3 &c, const Vector3 &d, float t);
    1.22 +static float mseval(struct metasurface *ms, float x, float y, float z);
    1.23 +static void msvertex(struct metasurface *ms, float x, float y, float z);
    1.24 +
    1.25  
    1.26  Dragon::Dragon()
    1.27  	: pos(0, 0, 0), dir(0, 0, -1), head_pos(0, 0, -1), target(0, 0, -2)
    1.28  {
    1.29  	set_head_limits(-1, 1, -1, 1);
    1.30 +
    1.31 +	glGenBuffers(1, &dyn_vbo);
    1.32 +	glBindBuffer(GL_ARRAY_BUFFER, dyn_vbo);
    1.33 +	glBufferData(GL_ARRAY_BUFFER, DYN_VCOUNT * sizeof(DynVertex), 0, GL_STREAM_DRAW);
    1.34 +	glBindBuffer(GL_ARRAY_BUFFER, 0);
    1.35 +
    1.36 +	dyn_varr = new DynVertex[DYN_VCOUNT];
    1.37 +
    1.38 +	neck_seg_count = NUM_NECK_SEG;
    1.39 +	neck_seg = new Capsule[neck_seg_count];
    1.40 +
    1.41 +	for(int i=0; i<neck_seg_count; i++) {
    1.42 +		neck_seg[i].w[0] = nseg_sizes[i][0];
    1.43 +		neck_seg[i].w[1] = nseg_sizes[i][1];
    1.44 +	}
    1.45 +
    1.46 +	msurf = msurf_create();
    1.47 +	msurf_set_user_data(msurf, this);
    1.48 +	msurf_set_resolution(msurf, 36, 36, 36);
    1.49 +	msurf_set_threshold(msurf, 1.0);
    1.50 +	msurf_eval_func(msurf, mseval);
    1.51 +	msurf_vertex_func(msurf, msvertex);
    1.52  }
    1.53  
    1.54  Dragon::~Dragon()
    1.55  {
    1.56 +	delete [] neck_seg;
    1.57 +	msurf_free(msurf);
    1.58 +
    1.59 +	delete [] dyn_varr;
    1.60 +	glDeleteBuffers(1, &dyn_vbo);
    1.61  }
    1.62  
    1.63  void Dragon::set_position(const Vector3 &p)
    1.64 @@ -71,8 +116,120 @@
    1.65  
    1.66  void Dragon::update()
    1.67  {
    1.68 +	Vector3 bdir = breath_dir();
    1.69 +	Vector3 bezcp[] = { pos, pos + dir * 6.0, head_pos - bdir * 8.0, head_pos };
    1.70 +
    1.71 +	float t = 0.0, dt = 1.0 / (float)(neck_seg_count + 1);
    1.72 +	Vector3 p = bezier(bezcp[0], bezcp[1], bezcp[2], bezcp[3], t);
    1.73 +
    1.74 +	for(int i=0; i<neck_seg_count; i++) {
    1.75 +		t += dt;
    1.76 +		Vector3 pnext = bezier(bezcp[0], bezcp[1], bezcp[2], bezcp[3], t);
    1.77 +
    1.78 +		neck_seg[i].p[0] = p;
    1.79 +		neck_seg[i].p[1] = pnext;
    1.80 +
    1.81 +		p = pnext;
    1.82 +	}
    1.83  }
    1.84  
    1.85 +void Dragon::draw() const
    1.86 +{
    1.87 +	static float bmin[] = { head_xlim[0] - VOXEL_PAD * 0.9, head_ylim[0] - VOXEL_PAD, head_pos.z };
    1.88 +	static float bmax[] = { head_xlim[1] + VOXEL_PAD * 0.9, head_ylim[1] + VOXEL_PAD * 2.1f, pos.z + VOXEL_PAD };
    1.89 +	msurf_set_bounds(msurf, bmin[0], bmin[1], bmin[2], bmax[0], bmax[1], bmax[2]);
    1.90 +
    1.91 +
    1.92 +	if(!shadow_pass) {
    1.93 +
    1.94 +		if(dbg_wireframe) {
    1.95 +			glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    1.96 +		}
    1.97 +
    1.98 +		dyn_vidx = 0;
    1.99 +		msurf_polygonize(msurf);
   1.100 +		flush_dynvbo();
   1.101 +
   1.102 +		if(dbg_wireframe) {
   1.103 +			glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
   1.104 +		}
   1.105 +
   1.106 +		int cur_sdr;
   1.107 +		glGetIntegerv(GL_CURRENT_PROGRAM, &cur_sdr);
   1.108 +		glUseProgram(0);
   1.109 +
   1.110 +		glPushAttrib(GL_ENABLE_BIT);
   1.111 +		glDisable(GL_LIGHTING);
   1.112 +
   1.113 +		// bounds
   1.114 +		glColor3f(1, 0, 0);
   1.115 +		glBegin(GL_LINE_LOOP);
   1.116 +		glVertex3f(bmin[0], bmin[1], bmin[2]);
   1.117 +		glVertex3f(bmax[0], bmin[1], bmin[2]);
   1.118 +		glVertex3f(bmax[0], bmax[1], bmin[2]);
   1.119 +		glVertex3f(bmin[0], bmax[1], bmin[2]);
   1.120 +		glEnd();
   1.121 +		glBegin(GL_LINE_LOOP);
   1.122 +		glVertex3f(bmin[0], bmin[1], bmax[2]);
   1.123 +		glVertex3f(bmax[0], bmin[1], bmax[2]);
   1.124 +		glVertex3f(bmax[0], bmax[1], bmax[2]);
   1.125 +		glVertex3f(bmin[0], bmax[1], bmax[2]);
   1.126 +		glEnd();
   1.127 +		glBegin(GL_LINE_LOOP);
   1.128 +		glVertex3f(bmin[0], bmax[1], bmin[2]);
   1.129 +		glVertex3f(bmax[0], bmax[1], bmin[2]);
   1.130 +		glVertex3f(bmax[0], bmax[1], bmax[2]);
   1.131 +		glVertex3f(bmin[0], bmax[1], bmax[2]);
   1.132 +		glEnd();
   1.133 +		glBegin(GL_LINE_LOOP);
   1.134 +		glVertex3f(bmin[0], bmin[1], bmin[2]);
   1.135 +		glVertex3f(bmax[0], bmin[1], bmin[2]);
   1.136 +		glVertex3f(bmax[0], bmin[1], bmax[2]);
   1.137 +		glVertex3f(bmin[0], bmin[1], bmax[2]);
   1.138 +		glEnd();
   1.139 +
   1.140 +		// foo
   1.141 +		glDisable(GL_DEPTH_TEST);
   1.142 +		glEnable(GL_BLEND);
   1.143 +		glBlendFunc(GL_ONE, GL_ONE);
   1.144 +		glLineWidth(2.0);
   1.145 +		glColor3f(0, 0, 1);
   1.146 +
   1.147 +		glBegin(GL_LINES);
   1.148 +		for(int i=0; i<neck_seg_count; i++) {
   1.149 +			glVertex3f(neck_seg[i].p[0].x, neck_seg[i].p[0].y, neck_seg[i].p[0].z);
   1.150 +			glVertex3f(neck_seg[i].p[1].x, neck_seg[i].p[1].y, neck_seg[i].p[1].z);
   1.151 +		}
   1.152 +		glEnd();
   1.153 +		glLineWidth(1);
   1.154 +
   1.155 +		// done debug drawing
   1.156 +		glPopAttrib();
   1.157 +		if(cur_sdr) glUseProgram(cur_sdr);
   1.158 +	}
   1.159 +}
   1.160 +
   1.161 +void Dragon::flush_dynvbo() const
   1.162 +{
   1.163 +	if(!dyn_vidx) return;
   1.164 +
   1.165 +	glBindBuffer(GL_ARRAY_BUFFER, dyn_vbo);
   1.166 +	glBufferSubData(GL_ARRAY_BUFFER, 0, dyn_vidx * sizeof(DynVertex), dyn_varr);
   1.167 +
   1.168 +	glEnableClientState(GL_VERTEX_ARRAY);
   1.169 +	glVertexPointer(3, GL_FLOAT, sizeof(DynVertex), (void*)offsetof(DynVertex, x));
   1.170 +	glEnableClientState(GL_NORMAL_ARRAY);
   1.171 +	glNormalPointer(GL_FLOAT, sizeof(DynVertex), (void*)offsetof(DynVertex, nx));
   1.172 +	glBindBuffer(GL_ARRAY_BUFFER, 0);
   1.173 +
   1.174 +	glDrawArrays(GL_TRIANGLES, 0, dyn_vidx);
   1.175 +
   1.176 +	glDisableClientState(GL_VERTEX_ARRAY);
   1.177 +	glDisableClientState(GL_NORMAL_ARRAY);
   1.178 +	dyn_vidx = 0;
   1.179 +}
   1.180 +
   1.181 +
   1.182  static Vector3 bezier(const Vector3 &a, const Vector3 &b, const Vector3 &c, const Vector3 &d, float t)
   1.183  {
   1.184  	float x = bezier(a.x, b.x, c.x, d.x, t);
   1.185 @@ -81,40 +238,48 @@
   1.186  	return Vector3(x, y, z);
   1.187  }
   1.188  
   1.189 -void Dragon::draw() const
   1.190 +static float mseval(struct metasurface *ms, float x, float y, float z)
   1.191  {
   1.192 -	Vector3 bdir = breath_dir();
   1.193 -	Vector3 bezcp[] = { pos, pos + dir * 6.0, head_pos - bdir * 8.0, head_pos };
   1.194 +	Dragon *dragon = (Dragon*)msurf_get_user_data(ms);
   1.195  
   1.196 -	int cur_sdr;
   1.197 -	glGetIntegerv(GL_CURRENT_PROGRAM, &cur_sdr);
   1.198 -	glUseProgram(0);
   1.199 +	Vector3 pt = Vector3(x, y, z);
   1.200 +	Capsule *seg = dragon->neck_seg;
   1.201  
   1.202 -	glPushAttrib(GL_ENABLE_BIT);
   1.203 -	glDisable(GL_LIGHTING);
   1.204 +	//printf("eval(%g %g %g)\n", x, y, z);
   1.205  
   1.206 -	glLineWidth(2.0);
   1.207 -	glColor3f(0, 0, 1);
   1.208 +	float sum = 0.0f;
   1.209 +	for(int i=0; i<dragon->neck_seg_count; i++) {
   1.210 +		float dist = capsule_distance(seg[i].p[0], seg[i].w[0], seg[i].p[1], seg[i].w[1], pt);
   1.211 +		//float dist = sphere_distance(seg[i].p[0], 1.0, pt);
   1.212 +		if(dist < 1e-4) dist = 1e-4;
   1.213 +		float energy = 0.0001 / (dist * dist);
   1.214 +		/*float dx = x - seg[i].p[0].x;
   1.215 +		float dy = y - seg[i].p[0].y;
   1.216 +		float dz = z - seg[i].p[0].z;
   1.217 +		float energy = 0.5 / (dx * dx + dy * dy + dz * dz);*/
   1.218 +		sum += energy;
   1.219 +	}
   1.220 +	return sum;
   1.221 +}
   1.222  
   1.223 -	glBegin(GL_LINE_STRIP);
   1.224 -	for(int i=0; i<10; i++) {
   1.225 -		float t = (float)i / 10.0f;
   1.226 -		Vector3 p = bezier(bezcp[0], bezcp[1], bezcp[2], bezcp[3], t);
   1.227 -		glVertex3f(p.x, p.y, p.z);
   1.228 +static void msvertex(struct metasurface *ms, float x, float y, float z)
   1.229 +{
   1.230 +	Dragon *dragon = (Dragon*)msurf_get_user_data(ms);
   1.231 +
   1.232 +	const float dt = 0.001;
   1.233 +	float dfdx = mseval(ms, x - dt, y, z) - mseval(ms, x + dt, y, z);
   1.234 +	float dfdy = mseval(ms, x, y - dt, z) - mseval(ms, x, y + dt, z);
   1.235 +	float dfdz = mseval(ms, x, y, z - dt) - mseval(ms, x, y, z + dt);
   1.236 +
   1.237 +	DynVertex *vptr = dragon->dyn_varr + dragon->dyn_vidx++;
   1.238 +	vptr->x = x;
   1.239 +	vptr->y = y;
   1.240 +	vptr->z = z;
   1.241 +	vptr->nx = dfdx;
   1.242 +	vptr->ny = dfdy;
   1.243 +	vptr->nz = dfdz;
   1.244 +
   1.245 +	if(dragon->dyn_vidx >= DYN_VCOUNT) {
   1.246 +		dragon->flush_dynvbo();
   1.247  	}
   1.248 -	glEnd();
   1.249 -	glLineWidth(1);
   1.250 -
   1.251 -	glPointSize(5.0);
   1.252 -	glColor3f(0, 1, 0);
   1.253 -
   1.254 -	glBegin(GL_POINTS);
   1.255 -	for(int i=0; i<4; i++) {
   1.256 -		glVertex3f(bezcp[i].x, bezcp[i].y, bezcp[i].z);
   1.257 -	}
   1.258 -	glEnd();
   1.259 -
   1.260 -	glPopAttrib();
   1.261 -
   1.262 -	glUseProgram(cur_sdr);
   1.263  }