3dphotoshoot
changeset 25:ac80210d5fbe
preparing a pc version for easier development of non-android-specifics
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 18 Jun 2015 03:12:30 +0300 |
parents | 2712c5da2e00 |
children | a460b1e5af4a |
files | Makefile sdr/color.p.glsl sdr/normvis.p.glsl sdr/vertex.glsl src/android/amain.c src/android/camera.c src/camera.h src/game.cc src/geom.cc src/geom.h src/mesh.cc src/mesh.h src/meshgen.cc src/meshgen.h src/pc/camera.c |
diffstat | 15 files changed, 2392 insertions(+), 48 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/Makefile Thu Jun 18 03:12:30 2015 +0300 1.3 @@ -0,0 +1,22 @@ 1.4 +root = . 1.5 +include $(root)/proj.mk 1.6 + 1.7 +src += $(wildcard $(root)/src/glut/*.c) 1.8 +obj = $(src:.c=.o) $(ccsrc:.cc=.o) 1.9 + 1.10 +ifeq ($(shell uname -s), Darwin) 1.11 + libgl = -framework OpenGL -framework GLUT 1.12 +else 1.13 + libgl = -lGL -lGLU -lglut 1.14 +endif 1.15 + 1.16 +CXXFLAGS = -pedantic -Wall -g $(defs) -I$(root)/src/glut $(incpaths) 1.17 +CFLAGS = $(CXXFLAGS) 1.18 +LDFLAGS = $(libpaths) $(libs) $(libgl) 1.19 + 1.20 +$(bin): $(obj) 1.21 + $(CXX) -o $@ $(obj) $(LDFLAGS) 1.22 + 1.23 +.PHONY: clean 1.24 +clean: 1.25 + rm -f $(obj) $(bin)
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/sdr/color.p.glsl Thu Jun 18 03:12:30 2015 +0300 2.3 @@ -0,0 +1,8 @@ 2.4 +precision mediump float; 2.5 + 2.6 +uniform vec4 color; 2.7 + 2.8 +void main() 2.9 +{ 2.10 + gl_FragColor = color; 2.11 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/sdr/normvis.p.glsl Thu Jun 18 03:12:30 2015 +0300 3.3 @@ -0,0 +1,10 @@ 3.4 +precision mediump float; 3.5 + 3.6 +varying vec3 normal; 3.7 + 3.8 +void main() 3.9 +{ 3.10 + vec3 ncol = normal * 0.5 + 0.5; 3.11 + gl_FragColor.rgb = ncol; 3.12 + gl_FragColor.a = 1.0; 3.13 +}
4.1 --- a/sdr/vertex.glsl Tue Jun 16 06:17:59 2015 +0300 4.2 +++ b/sdr/vertex.glsl Thu Jun 18 03:12:30 2015 +0300 4.3 @@ -1,7 +1,9 @@ 4.4 -attribute vec4 attr_vertex, attr_texcoord, attr_color; 4.5 +attribute vec4 attr_vertex, attr_normal, attr_texcoord, attr_color; 4.6 4.7 uniform mat4 matrix_modelview, matrix_projection, matrix_texture; 4.8 +uniform mat3 matrix_normal; 4.9 4.10 +varying vec3 normal; 4.11 varying vec4 tex_coords, color; 4.12 4.13 void main() 4.14 @@ -10,4 +12,5 @@ 4.15 gl_Position = mvp * attr_vertex; 4.16 tex_coords = matrix_texture * attr_texcoord; 4.17 color = attr_color; 4.18 + normal = matrix_normal * attr_normal.xyz; 4.19 }
5.1 --- a/src/android/amain.c Tue Jun 16 06:17:59 2015 +0300 5.2 +++ b/src/android/amain.c Thu Jun 18 03:12:30 2015 +0300 5.3 @@ -117,15 +117,26 @@ 5.4 switch(evid) { 5.5 case EVID_SENS_ACCEL: 5.6 if(sens_accel) { 5.7 - float accel[3]; 5.8 + static double prev_sec = -1.0; 5.9 + double sec, dt; 5.10 + double accel[3] = {0, 0, 0}; 5.11 + static double velocity[3]; 5.12 + 5.13 while(ASensorEventQueue_getEvents(sens_evq_accel, &sens_ev, 1) > 0) { 5.14 - accel[0] = sens_ev.acceleration.x; 5.15 - accel[1] = sens_ev.acceleration.y; 5.16 - accel[2] = sens_ev.acceleration.z; 5.17 + accel[0] += sens_ev.acceleration.x; 5.18 + accel[1] += sens_ev.acceleration.y; 5.19 + accel[2] += sens_ev.acceleration.z; 5.20 } 5.21 5.22 - // TODO: integrate over time 5.23 - game_6dof_translation(accel[0], accel[1], accel[2]); 5.24 + sec = get_time_sec(); 5.25 + dt = prev_sec >= 0.0 ? sec - prev_sec : 0.0; 5.26 + prev_sec = sec; 5.27 + 5.28 + velocity[0] += accel[0] * dt; 5.29 + velocity[1] += accel[1] * dt; 5.30 + velocity[2] += accel[2] * dt; 5.31 + 5.32 + game_6dof_translation(velocity[0] * dt, velocity[1] * dt, velocity[2] * dt); 5.33 } 5.34 break; 5.35
6.1 --- a/src/android/camera.c Tue Jun 16 06:17:59 2015 +0300 6.2 +++ b/src/android/camera.c Thu Jun 18 03:12:30 2015 +0300 6.3 @@ -4,6 +4,8 @@ 6.4 #include <jni.h> 6.5 #include "opengl.h" 6.6 #include "camera.h" 6.7 +#include "sdr.h" 6.8 +#include "sanegl.h" 6.9 6.10 6.11 static JavaVM *jvm; 6.12 @@ -15,6 +17,10 @@ 6.13 static jfloatArray jtex_matrix; 6.14 static int capturing; 6.15 6.16 +static unsigned int sdr_cam; 6.17 +static int aloc_vertex, aloc_texcoord; 6.18 + 6.19 + 6.20 int cam_init(void *platform_data) 6.21 { 6.22 int glerr; 6.23 @@ -26,6 +32,13 @@ 6.24 6.25 jtex_matrix = (*jni)->NewFloatArray(jni, 16); 6.26 6.27 + // load preview shader 6.28 + if(!(sdr_cam = create_program_load("sdr/vertex.glsl", "sdr/android_cam_preview.p.glsl"))) { 6.29 + return -1; 6.30 + } 6.31 + aloc_vertex = glGetAttribLocation(sdr_cam, "attr_vertex"); 6.32 + aloc_texcoord = glGetAttribLocation(sdr_cam, "attr_texcoord"); 6.33 + 6.34 // create the camera texture 6.35 assert(glGetError() == GL_NO_ERROR); 6.36 glGenTextures(1, &tex); 6.37 @@ -44,6 +57,8 @@ 6.38 glDeleteTextures(1, &tex); 6.39 tex = 0; 6.40 6.41 + free_program(sdr_cam); 6.42 + 6.43 if(jni) { 6.44 (*jni)->DeleteGlobalRef(jni, jtex_matrix); 6.45 } 6.46 @@ -171,3 +186,28 @@ 6.47 { 6.48 return -1; // TODO 6.49 } 6.50 + 6.51 +void cam_draw_preview(void) 6.52 +{ 6.53 + const float *tex_matrix = cam_texture_matrix(); 6.54 + 6.55 + gl_matrix_mode(GL_TEXTURE); 6.56 + gl_load_matrixf(tex_matrix); 6.57 + 6.58 + glUseProgram(sdr_cam); 6.59 + glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex); 6.60 + 6.61 + gl_begin(GL_QUADS); 6.62 + gl_texcoord2f(0, 0); 6.63 + gl_vertex2f(-1, -1); 6.64 + gl_texcoord2f(1, 0); 6.65 + gl_vertex2f(1, -1); 6.66 + gl_texcoord2f(1, 1); 6.67 + gl_vertex2f(1, 1); 6.68 + gl_texcoord2f(0, 1); 6.69 + gl_vertex2f(-1, 1); 6.70 + gl_end(); 6.71 + 6.72 + gl_matrix_mode(GL_TEXTURE); 6.73 + gl_load_identity(); 6.74 +}
7.1 --- a/src/camera.h Tue Jun 16 06:17:59 2015 +0300 7.2 +++ b/src/camera.h Thu Jun 18 03:12:30 2015 +0300 7.3 @@ -30,6 +30,8 @@ 7.4 7.5 int cam_take_picture(void); 7.6 7.7 +void cam_draw_preview(void); 7.8 + 7.9 #ifdef __cplusplus 7.10 } 7.11 #endif
8.1 --- a/src/game.cc Tue Jun 16 06:17:59 2015 +0300 8.2 +++ b/src/game.cc Thu Jun 18 03:12:30 2015 +0300 8.3 @@ -2,6 +2,7 @@ 8.4 #include <stdlib.h> 8.5 #include <math.h> 8.6 #include <assert.h> 8.7 +#include <algorithm> 8.8 #include "opengl.h" 8.9 #include "game.h" 8.10 #include "camera.h" 8.11 @@ -10,8 +11,12 @@ 8.12 #include "shader.h" 8.13 #include "text.h" 8.14 #include "vmath/vmath.h" 8.15 +#include "mesh.h" 8.16 +#include "meshgen.h" 8.17 8.18 static void draw_quad(float hsz, float vsz); 8.19 +static void draw_rotation_gizmo(); 8.20 +static void draw_disc_wedge(float start, float end, int subdiv); 8.21 8.22 int win_width, win_height; 8.23 8.24 @@ -20,10 +25,15 @@ 8.25 static float video_aspect; 8.26 static struct texture *test_tex; 8.27 8.28 -static SdrProg *sdr_cam, *sdr_tex; 8.29 +static SdrProg *sdr_tex, *sdr_color, *sdr_debug; 8.30 8.31 -static Quaternion qrot; 8.32 -static Vector3 trans; 8.33 +static Quaternion last_rot; 8.34 +static Vector3 last_trans; 8.35 + 8.36 +static Quaternion rot; 8.37 +static Vector3 rot_euler; 8.38 + 8.39 +static Mesh *mesh; 8.40 8.41 extern "C" int game_init(void) 8.42 { 8.43 @@ -32,10 +42,13 @@ 8.44 8.45 glClearColor(0.4, 0.4, 0.4, 1); 8.46 8.47 - if(!(sdr_cam = get_sdrprog("sdr/vertex.glsl", "sdr/android_cam_preview.p.glsl"))) { 8.48 + if(!(sdr_tex = get_sdrprog("sdr/vertex.glsl", "sdr/tex.p.glsl"))) { 8.49 return -1; 8.50 } 8.51 - if(!(sdr_tex = get_sdrprog("sdr/vertex.glsl", "sdr/tex.p.glsl"))) { 8.52 + if(!(sdr_color = get_sdrprog("sdr/vertex.glsl", "sdr/color.p.glsl"))) { 8.53 + return -1; 8.54 + } 8.55 + if(!(sdr_debug = get_sdrprog("sdr/vertex.glsl", "sdr/normvis.p.glsl"))) { 8.56 return -1; 8.57 } 8.58 8.59 @@ -43,6 +56,9 @@ 8.60 return -1; 8.61 } 8.62 8.63 + mesh = new Mesh; 8.64 + gen_cylinder(mesh, 0.2, 1.0, 16, 1); 8.65 + 8.66 cam_start_video(); 8.67 cam_video_size(&video_width, &video_height); 8.68 if(video_height) { 8.69 @@ -58,31 +74,28 @@ 8.70 extern "C" void game_shutdown(void) 8.71 { 8.72 cam_shutdown(); 8.73 - delete sdr_cam; 8.74 delete sdr_tex; 8.75 } 8.76 8.77 extern "C" void game_display(unsigned long msec) 8.78 { 8.79 unsigned int tex; 8.80 - const float *tex_matrix; 8.81 float xscale, yscale; 8.82 8.83 cam_update(); 8.84 tex = cam_texture(); 8.85 - tex_matrix = cam_texture_matrix(); 8.86 8.87 //float tsec = (float)msec / 1000.0f; 8.88 8.89 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 8.90 8.91 + // draw video preview frame 8.92 + gl_matrix_mode(GL_PROJECTION); 8.93 + gl_push_matrix(); 8.94 + gl_load_identity(); 8.95 + gl_scalef((float)win_height / (float)win_width, 1, 1); 8.96 gl_matrix_mode(GL_MODELVIEW); 8.97 gl_load_identity(); 8.98 - gl_matrix_mode(GL_TEXTURE); 8.99 - gl_load_matrixf(tex_matrix); 8.100 - 8.101 - sdr_cam->bind(); 8.102 - glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex); 8.103 8.104 if(video_aspect > win_aspect) { 8.105 xscale = 1.0; 8.106 @@ -91,34 +104,27 @@ 8.107 xscale = video_aspect; 8.108 yscale = 1.0; 8.109 } 8.110 - draw_quad(xscale, yscale); 8.111 + gl_scalef(xscale, yscale, 1); 8.112 8.113 - gl_matrix_mode(GL_TEXTURE); 8.114 - gl_load_identity(); 8.115 - gl_translatef(0, 1, 0); 8.116 - gl_scalef(1, -1, 1); 8.117 + cam_draw_preview(); 8.118 + 8.119 + gl_matrix_mode(GL_PROJECTION); 8.120 + gl_pop_matrix(); 8.121 + // done drawing preview 8.122 + 8.123 + 8.124 gl_matrix_mode(GL_MODELVIEW); 8.125 gl_load_identity(); 8.126 - gl_scalef((float)test_tex->width / (float)test_tex->height, 1, 1); 8.127 + gl_translatef(0, 0, -6); 8.128 8.129 - sdr_tex->bind(); 8.130 - glBindTexture(GL_TEXTURE_2D, test_tex->texid); 8.131 - 8.132 - glEnable(GL_BLEND); 8.133 - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 8.134 - draw_quad(0.5, 0.5); 8.135 - glDisable(GL_BLEND); 8.136 - 8.137 - gl_matrix_mode(GL_TEXTURE); 8.138 - gl_load_identity(); 8.139 - 8.140 + draw_rotation_gizmo(); 8.141 8.142 // print the rotation quaternion 8.143 text_color(1, 1, 1, 1); 8.144 text_position(0, 0); 8.145 - text_printf("translation (% .3f, % .3f, % .3f)", trans.x, trans.y, trans.z); 8.146 + text_printf("translation (% .3f, % .3f, % .3f)", last_trans.x, last_trans.y, last_trans.z); 8.147 text_position(0, 1); 8.148 - text_printf("Rotation quat ([% 1.3f, % 1.3f, % 1.3f], % 1.3f)", qrot.v.x, qrot.v.y, qrot.v.z, qrot.s); 8.149 + text_printf("Rotation quat ([% 1.3f, % 1.3f, % 1.3f], % 1.3f)", last_rot.v.x, last_rot.v.y, last_rot.v.z, last_rot.s); 8.150 } 8.151 8.152 static void draw_quad(float hsz, float vsz) 8.153 @@ -147,6 +153,65 @@ 8.154 gl_pop_matrix(); 8.155 } 8.156 8.157 +static void draw_rotation_gizmo() 8.158 +{ 8.159 + /*static const float axis[][3] = { 8.160 + {1, 0, 0}, {0, 1, 0}, {0, 0, 1} 8.161 + };*/ 8.162 + 8.163 + last_rot.normalize(); 8.164 + Matrix4x4 rmat = last_rot.get_rotation_matrix().transposed(); 8.165 + gl_matrix_mode(GL_MODELVIEW); 8.166 + gl_push_matrix(); 8.167 + gl_mult_matrixf(rmat[0]); 8.168 + gl_apply_xform(sdr_debug->get_globj()); 8.169 + 8.170 + sdr_debug->bind(); 8.171 + 8.172 + mesh->draw(); 8.173 + 8.174 + gl_pop_matrix(); 8.175 +} 8.176 + 8.177 +static void draw_disc_wedge(float start, float end, int subdiv) 8.178 +{ 8.179 + if(start > end) { 8.180 + float tmp = start; 8.181 + start = end; 8.182 + end = tmp; 8.183 + } 8.184 + 8.185 + float arc_size = end - start; 8.186 + subdiv = std::max<int>(subdiv * arc_size, 1); 8.187 + int nverts = subdiv + 2; 8.188 + 8.189 + float *varr = (float*)alloca(nverts * 3 * sizeof *varr); 8.190 + float *vptr = varr; 8.191 + 8.192 + // start with the center vertex 8.193 + vptr[0] = vptr[1] = vptr[2] = 0; 8.194 + vptr += 3; 8.195 + 8.196 + // then add the arc vertices in sequence 8.197 + float u = start; 8.198 + float du = arc_size / (float)subdiv; 8.199 + for(int i=0; i<subdiv + 1; i++) { 8.200 + float angle = u * M_PI * 2.0; 8.201 + vptr[0] = sin(angle); 8.202 + vptr[1] = cos(angle); 8.203 + vptr[2] = 0.0; 8.204 + vptr += 3; 8.205 + u += du; 8.206 + } 8.207 + 8.208 + glEnableVertexAttribArray(SDR_ATTR_VERTEX); 8.209 + glVertexAttribPointer(SDR_ATTR_VERTEX, 3, GL_FLOAT, 0, 0, varr); 8.210 + 8.211 + glDrawArrays(GL_TRIANGLE_FAN, 0, nverts); 8.212 + 8.213 + glDisableVertexAttribArray(SDR_ATTR_VERTEX); 8.214 +} 8.215 + 8.216 extern "C" void game_reshape(int x, int y) 8.217 { 8.218 win_width = x; 8.219 @@ -155,8 +220,7 @@ 8.220 glViewport(0, 0, x, y); 8.221 8.222 gl_matrix_mode(GL_PROJECTION); 8.223 - gl_load_identity(); 8.224 - gl_scalef((float)win_height / (float)win_width, 1, 1); 8.225 + glu_perspective(50.0, win_aspect, 0.5, 500.0); 8.226 } 8.227 8.228 extern "C" void game_keyboard(int key, int pressed) 8.229 @@ -223,15 +287,17 @@ 8.230 8.231 void game_6dof_translation(float dx, float dy, float dz) 8.232 { 8.233 - trans.x = dx; 8.234 - trans.y = dy; 8.235 - trans.z = dz; 8.236 + last_trans.x = dx; 8.237 + last_trans.y = dy; 8.238 + last_trans.z = dz; 8.239 } 8.240 8.241 void game_6dof_rotation(float qx, float qy, float qz, float qw) 8.242 { 8.243 - qrot.v.x = qx; 8.244 - qrot.v.y = qy; 8.245 - qrot.v.z = qz; 8.246 - qrot.s = qw; 8.247 + last_rot.v.x = qx; 8.248 + last_rot.v.y = qy; 8.249 + last_rot.v.z = qz; 8.250 + last_rot.s = qw; 8.251 + 8.252 + rot.rotate(last_rot); 8.253 }
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/src/geom.cc Thu Jun 18 03:12:30 2015 +0300 9.3 @@ -0,0 +1,251 @@ 9.4 +#include <algorithm> 9.5 +#include <float.h> 9.6 +#include "geom.h" 9.7 + 9.8 +GeomObject::~GeomObject() 9.9 +{ 9.10 +} 9.11 + 9.12 + 9.13 +Sphere::Sphere() 9.14 +{ 9.15 + radius = 1.0; 9.16 +} 9.17 + 9.18 +Sphere::Sphere(const Vector3 ¢, float radius) 9.19 + : center(cent) 9.20 +{ 9.21 + this->radius = radius; 9.22 +} 9.23 + 9.24 +void Sphere::set_union(const GeomObject *obj1, const GeomObject *obj2) 9.25 +{ 9.26 + const Sphere *sph1 = dynamic_cast<const Sphere*>(obj1); 9.27 + const Sphere *sph2 = dynamic_cast<const Sphere*>(obj2); 9.28 + 9.29 + if(!sph1 || !sph2) { 9.30 + fprintf(stderr, "Sphere::set_union: arguments must be spheres"); 9.31 + return; 9.32 + } 9.33 + 9.34 + float dist = (sph1->center - sph2->center).length(); 9.35 + float surf_dist = dist - (sph1->radius + sph2->radius); 9.36 + float d1 = sph1->radius + surf_dist / 2.0; 9.37 + float d2 = sph2->radius + surf_dist / 2.0; 9.38 + float t = d1 / (d1 + d2); 9.39 + 9.40 + if(t < 0.0) t = 0.0; 9.41 + if(t > 1.0) t = 1.0; 9.42 + 9.43 + center = sph1->center * t + sph2->center * (1.0 - t); 9.44 + radius = std::max(dist * t + sph2->radius, dist * (1.0f - t) + sph1->radius); 9.45 +} 9.46 + 9.47 +void Sphere::set_intersection(const GeomObject *obj1, const GeomObject *obj2) 9.48 +{ 9.49 + fprintf(stderr, "Sphere::intersection undefined\n"); 9.50 +} 9.51 + 9.52 +bool Sphere::intersect(const Ray &ray, HitPoint *hit) const 9.53 +{ 9.54 + float a = dot_product(ray.dir, ray.dir); 9.55 + float b = 2.0 * ray.dir.x * (ray.origin.x - center.x) + 9.56 + 2.0 * ray.dir.y * (ray.origin.y - center.y) + 9.57 + 2.0 * ray.dir.z * (ray.origin.z - center.z); 9.58 + float c = dot_product(ray.origin, ray.origin) + dot_product(center, center) - 9.59 + 2.0 * dot_product(ray.origin, center) - radius * radius; 9.60 + 9.61 + float discr = b * b - 4.0 * a * c; 9.62 + if(discr < 1e-4) { 9.63 + return false; 9.64 + } 9.65 + 9.66 + float sqrt_discr = sqrt(discr); 9.67 + float t0 = (-b + sqrt_discr) / (2.0 * a); 9.68 + float t1 = (-b - sqrt_discr) / (2.0 * a); 9.69 + 9.70 + if(t0 < 1e-4) 9.71 + t0 = t1; 9.72 + if(t1 < 1e-4) 9.73 + t1 = t0; 9.74 + 9.75 + float t = t0 < t1 ? t0 : t1; 9.76 + if(t < 1e-4) { 9.77 + return false; 9.78 + } 9.79 + 9.80 + // fill the HitPoint structure 9.81 + if(hit) { 9.82 + hit->obj = this; 9.83 + hit->dist = t; 9.84 + hit->pos = ray.origin + ray.dir * t; 9.85 + hit->normal = (hit->pos - center) / radius; 9.86 + } 9.87 + return true; 9.88 +} 9.89 + 9.90 + 9.91 +AABox::AABox() 9.92 +{ 9.93 +} 9.94 + 9.95 +AABox::AABox(const Vector3 &vmin, const Vector3 &vmax) 9.96 + : min(vmin), max(vmax) 9.97 +{ 9.98 +} 9.99 + 9.100 +void AABox::set_union(const GeomObject *obj1, const GeomObject *obj2) 9.101 +{ 9.102 + const AABox *box1 = dynamic_cast<const AABox*>(obj1); 9.103 + const AABox *box2 = dynamic_cast<const AABox*>(obj2); 9.104 + 9.105 + if(!box1 || !box2) { 9.106 + fprintf(stderr, "AABox::set_union: arguments must be AABoxes too\n"); 9.107 + return; 9.108 + } 9.109 + 9.110 + min.x = std::min(box1->min.x, box2->min.x); 9.111 + min.y = std::min(box1->min.y, box2->min.y); 9.112 + min.z = std::min(box1->min.z, box2->min.z); 9.113 + 9.114 + max.x = std::max(box1->max.x, box2->max.x); 9.115 + max.y = std::max(box1->max.y, box2->max.y); 9.116 + max.z = std::max(box1->max.z, box2->max.z); 9.117 +} 9.118 + 9.119 +void AABox::set_intersection(const GeomObject *obj1, const GeomObject *obj2) 9.120 +{ 9.121 + const AABox *box1 = dynamic_cast<const AABox*>(obj1); 9.122 + const AABox *box2 = dynamic_cast<const AABox*>(obj2); 9.123 + 9.124 + if(!box1 || !box2) { 9.125 + fprintf(stderr, "AABox::set_intersection: arguments must be AABoxes too\n"); 9.126 + return; 9.127 + } 9.128 + 9.129 + for(int i=0; i<3; i++) { 9.130 + min[i] = std::max(box1->min[i], box2->min[i]); 9.131 + max[i] = std::min(box1->max[i], box2->max[i]); 9.132 + 9.133 + if(max[i] < min[i]) { 9.134 + max[i] = min[i]; 9.135 + } 9.136 + } 9.137 +} 9.138 + 9.139 +bool AABox::intersect(const Ray &ray, HitPoint *hit) const 9.140 +{ 9.141 + Vector3 param[2] = {min, max}; 9.142 + Vector3 inv_dir(1.0 / ray.dir.x, 1.0 / ray.dir.y, 1.0 / ray.dir.z); 9.143 + int sign[3] = {inv_dir.x < 0, inv_dir.y < 0, inv_dir.z < 0}; 9.144 + 9.145 + float tmin = (param[sign[0]].x - ray.origin.x) * inv_dir.x; 9.146 + float tmax = (param[1 - sign[0]].x - ray.origin.x) * inv_dir.x; 9.147 + float tymin = (param[sign[1]].y - ray.origin.y) * inv_dir.y; 9.148 + float tymax = (param[1 - sign[1]].y - ray.origin.y) * inv_dir.y; 9.149 + 9.150 + if(tmin > tymax || tymin > tmax) { 9.151 + return false; 9.152 + } 9.153 + if(tymin > tmin) { 9.154 + tmin = tymin; 9.155 + } 9.156 + if(tymax < tmax) { 9.157 + tmax = tymax; 9.158 + } 9.159 + 9.160 + float tzmin = (param[sign[2]].z - ray.origin.z) * inv_dir.z; 9.161 + float tzmax = (param[1 - sign[2]].z - ray.origin.z) * inv_dir.z; 9.162 + 9.163 + if(tmin > tzmax || tzmin > tmax) { 9.164 + return false; 9.165 + } 9.166 + if(tzmin > tmin) { 9.167 + tmin = tzmin; 9.168 + } 9.169 + if(tzmax < tmax) { 9.170 + tmax = tzmax; 9.171 + } 9.172 + 9.173 + float t = tmin < 1e-4 ? tmax : tmin; 9.174 + if(t >= 1e-4) { 9.175 + 9.176 + if(hit) { 9.177 + hit->obj = this; 9.178 + hit->dist = t; 9.179 + hit->pos = ray.origin + ray.dir * t; 9.180 + 9.181 + float min_dist = FLT_MAX; 9.182 + Vector3 offs = min + (max - min) / 2.0; 9.183 + Vector3 local_hit = hit->pos - offs; 9.184 + 9.185 + static const Vector3 axis[] = { 9.186 + Vector3(1, 0, 0), Vector3(0, 1, 0), Vector3(0, 0, 1) 9.187 + }; 9.188 + //int tcidx[][2] = {{2, 1}, {0, 2}, {0, 1}}; 9.189 + 9.190 + for(int i=0; i<3; i++) { 9.191 + float dist = fabs((max[i] - offs[i]) - fabs(local_hit[i])); 9.192 + if(dist < min_dist) { 9.193 + min_dist = dist; 9.194 + hit->normal = axis[i] * (local_hit[i] < 0.0 ? 1.0 : -1.0); 9.195 + //hit->texcoord = Vector2(hit->pos[tcidx[i][0]], hit->pos[tcidx[i][1]]); 9.196 + } 9.197 + } 9.198 + } 9.199 + return true; 9.200 + } 9.201 + return false; 9.202 + 9.203 +} 9.204 + 9.205 +Plane::Plane() 9.206 + : normal(0.0, 1.0, 0.0) 9.207 +{ 9.208 +} 9.209 + 9.210 +Plane::Plane(const Vector3 &p, const Vector3 &norm) 9.211 + : pt(p) 9.212 +{ 9.213 + normal = norm.normalized(); 9.214 +} 9.215 + 9.216 +Plane::Plane(const Vector3 &p1, const Vector3 &p2, const Vector3 &p3) 9.217 + : pt(p1) 9.218 +{ 9.219 + normal = cross_product(p2 - p1, p3 - p1).normalized(); 9.220 +} 9.221 + 9.222 +Plane::Plane(const Vector3 &normal, float dist) 9.223 +{ 9.224 + this->normal = normal.normalized(); 9.225 + pt = this->normal * dist; 9.226 +} 9.227 + 9.228 +void Plane::set_union(const GeomObject *obj1, const GeomObject *obj2) 9.229 +{ 9.230 + fprintf(stderr, "Plane::set_union undefined\n"); 9.231 +} 9.232 + 9.233 +void Plane::set_intersection(const GeomObject *obj1, const GeomObject *obj2) 9.234 +{ 9.235 + fprintf(stderr, "Plane::set_intersection undefined\n"); 9.236 +} 9.237 + 9.238 +bool Plane::intersect(const Ray &ray, HitPoint *hit) const 9.239 +{ 9.240 + float ndotdir = dot_product(normal, ray.dir); 9.241 + if(fabs(ndotdir) < 1e-4) { 9.242 + return false; 9.243 + } 9.244 + 9.245 + if(hit) { 9.246 + Vector3 ptdir = pt - ray.origin; 9.247 + float t = dot_product(normal, ptdir) / ndotdir; 9.248 + 9.249 + hit->pos = ray.origin + ray.dir * t; 9.250 + hit->normal = normal; 9.251 + hit->obj = this; 9.252 + } 9.253 + return true; 9.254 +}
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/src/geom.h Thu Jun 18 03:12:30 2015 +0300 10.3 @@ -0,0 +1,67 @@ 10.4 +#ifndef GEOMOBJ_H_ 10.5 +#define GEOMOBJ_H_ 10.6 + 10.7 +#include "vmath/vmath.h" 10.8 + 10.9 +class GeomObject; 10.10 + 10.11 +struct HitPoint { 10.12 + float dist; //< parametric distance along the ray 10.13 + Vector3 pos; //< position of intersection (orig + dir * dist) 10.14 + Vector3 normal; //< normal at the point of intersection 10.15 + const void *obj; //< pointer to the intersected object 10.16 +}; 10.17 + 10.18 +class GeomObject { 10.19 +public: 10.20 + virtual ~GeomObject(); 10.21 + 10.22 + virtual void set_union(const GeomObject *obj1, const GeomObject *obj2) = 0; 10.23 + virtual void set_intersection(const GeomObject *obj1, const GeomObject *obj2) = 0; 10.24 + 10.25 + virtual bool intersect(const Ray &ray, HitPoint *hit = 0) const = 0; 10.26 +}; 10.27 + 10.28 +class Sphere : public GeomObject { 10.29 +public: 10.30 + Vector3 center; 10.31 + float radius; 10.32 + 10.33 + Sphere(); 10.34 + Sphere(const Vector3 ¢er, float radius); 10.35 + 10.36 + void set_union(const GeomObject *obj1, const GeomObject *obj2); 10.37 + void set_intersection(const GeomObject *obj1, const GeomObject *obj2); 10.38 + 10.39 + bool intersect(const Ray &ray, HitPoint *hit = 0) const; 10.40 +}; 10.41 + 10.42 +class AABox : public GeomObject { 10.43 +public: 10.44 + Vector3 min, max; 10.45 + 10.46 + AABox(); 10.47 + AABox(const Vector3 &min, const Vector3 &max); 10.48 + 10.49 + void set_union(const GeomObject *obj1, const GeomObject *obj2); 10.50 + void set_intersection(const GeomObject *obj1, const GeomObject *obj2); 10.51 + 10.52 + bool intersect(const Ray &ray, HitPoint *hit = 0) const; 10.53 +}; 10.54 + 10.55 +class Plane : public GeomObject { 10.56 +public: 10.57 + Vector3 pt, normal; 10.58 + 10.59 + Plane(); 10.60 + Plane(const Vector3 &pt, const Vector3 &normal); 10.61 + Plane(const Vector3 &p1, const Vector3 &p2, const Vector3 &p3); 10.62 + Plane(const Vector3 &normal, float dist); 10.63 + 10.64 + void set_union(const GeomObject *obj1, const GeomObject *obj2); 10.65 + void set_intersection(const GeomObject *obj1, const GeomObject *obj2); 10.66 + 10.67 + bool intersect(const Ray &ray, HitPoint *hit = 0) const; 10.68 +}; 10.69 + 10.70 +#endif // GEOMOBJ_H_
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/src/mesh.cc Thu Jun 18 03:12:30 2015 +0300 11.3 @@ -0,0 +1,1190 @@ 11.4 +#include <stdio.h> 11.5 +#include <stdlib.h> 11.6 +#include <float.h> 11.7 +#include <assert.h> 11.8 +#include "opengl.h" 11.9 +#include "mesh.h" 11.10 +//#include "xform_node.h" 11.11 +#include "shader.h" 11.12 + 11.13 +int Mesh::global_sdr_loc[NUM_MESH_ATTR] = { 11.14 + (int)SDR_ATTR_VERTEX, 11.15 + (int)SDR_ATTR_NORMAL, 11.16 + (int)SDR_ATTR_TANGENT, 11.17 + (int)SDR_ATTR_TEXCOORD, 11.18 + (int)SDR_ATTR_COLOR, 11.19 + -1, -1}; 11.20 +unsigned int Mesh::intersect_mode = ISECT_DEFAULT; 11.21 +float Mesh::vertex_sel_dist = 0.01; 11.22 +float Mesh::vis_vecsize = 1.0; 11.23 + 11.24 +Mesh::Mesh() 11.25 +{ 11.26 + clear(); 11.27 + 11.28 + glGenBuffers(NUM_MESH_ATTR + 1, buffer_objects); 11.29 + 11.30 + for(int i=0; i<NUM_MESH_ATTR; i++) { 11.31 + vattr[i].vbo = buffer_objects[i]; 11.32 + } 11.33 + ibo = buffer_objects[NUM_MESH_ATTR]; 11.34 + wire_ibo = 0; 11.35 +} 11.36 + 11.37 +Mesh::~Mesh() 11.38 +{ 11.39 + glDeleteBuffers(NUM_MESH_ATTR + 1, buffer_objects); 11.40 + 11.41 + if(wire_ibo) { 11.42 + glDeleteBuffers(1, &wire_ibo); 11.43 + } 11.44 +} 11.45 + 11.46 +Mesh::Mesh(const Mesh &rhs) 11.47 +{ 11.48 + clear(); 11.49 + 11.50 + glGenBuffers(NUM_MESH_ATTR + 1, buffer_objects); 11.51 + 11.52 + for(int i=0; i<NUM_MESH_ATTR; i++) { 11.53 + vattr[i].vbo = buffer_objects[i]; 11.54 + } 11.55 + ibo = buffer_objects[NUM_MESH_ATTR]; 11.56 + wire_ibo = 0; 11.57 + 11.58 + clone(rhs); 11.59 +} 11.60 + 11.61 +Mesh &Mesh::operator =(const Mesh &rhs) 11.62 +{ 11.63 + if(&rhs != this) { 11.64 + clone(rhs); 11.65 + } 11.66 + return *this; 11.67 +} 11.68 + 11.69 +bool Mesh::clone(const Mesh &m) 11.70 +{ 11.71 + clear(); 11.72 + 11.73 + for(int i=0; i<NUM_MESH_ATTR; i++) { 11.74 + if(m.has_attrib(i)) { 11.75 + m.get_attrib_data(i); // force validation of the actual data on the source mesh 11.76 + 11.77 + vattr[i].nelem = m.vattr[i].nelem; 11.78 + vattr[i].data = m.vattr[i].data; // copy the actual data 11.79 + vattr[i].data_valid = true; 11.80 + } 11.81 + } 11.82 + 11.83 + if(m.is_indexed()) { 11.84 + m.get_index_data(); // again, force validation 11.85 + 11.86 + // copy the index data 11.87 + idata = m.idata; 11.88 + idata_valid = true; 11.89 + } 11.90 + 11.91 + name = m.name; 11.92 + nverts = m.nverts; 11.93 + nfaces = m.nfaces; 11.94 + 11.95 + //bones = m.bones; 11.96 + 11.97 + memcpy(cur_val, m.cur_val, sizeof cur_val); 11.98 + 11.99 + aabb = m.aabb; 11.100 + aabb_valid = m.aabb_valid; 11.101 + bsph = m.bsph; 11.102 + bsph_valid = m.bsph_valid; 11.103 + 11.104 + hitface = m.hitface; 11.105 + hitvert = m.hitvert; 11.106 + 11.107 + intersect_mode = m.intersect_mode; 11.108 + vertex_sel_dist = m.vertex_sel_dist; 11.109 + vis_vecsize = m.vis_vecsize; 11.110 + 11.111 + return true; 11.112 +} 11.113 + 11.114 +void Mesh::set_name(const char *name) 11.115 +{ 11.116 + this->name = name; 11.117 +} 11.118 + 11.119 +const char *Mesh::get_name() const 11.120 +{ 11.121 + return name.c_str(); 11.122 +} 11.123 + 11.124 +bool Mesh::has_attrib(int attr) const 11.125 +{ 11.126 + if(attr < 0 || attr >= NUM_MESH_ATTR) { 11.127 + return false; 11.128 + } 11.129 + 11.130 + // if neither of these is valid, then nobody has set this attribute 11.131 + return vattr[attr].vbo_valid || vattr[attr].data_valid; 11.132 +} 11.133 + 11.134 +bool Mesh::is_indexed() const 11.135 +{ 11.136 + return ibo_valid || idata_valid; 11.137 +} 11.138 + 11.139 +void Mesh::clear() 11.140 +{ 11.141 + //bones.clear(); 11.142 + 11.143 + for(int i=0; i<NUM_MESH_ATTR; i++) { 11.144 + vattr[i].nelem = 0; 11.145 + vattr[i].vbo_valid = false; 11.146 + vattr[i].data_valid = false; 11.147 + //vattr[i].sdr_loc = -1; 11.148 + vattr[i].data.clear(); 11.149 + } 11.150 + ibo_valid = idata_valid = false; 11.151 + idata.clear(); 11.152 + 11.153 + wire_ibo_valid = false; 11.154 + 11.155 + nverts = nfaces = 0; 11.156 + 11.157 + bsph_valid = false; 11.158 + aabb_valid = false; 11.159 +} 11.160 + 11.161 +float *Mesh::set_attrib_data(int attrib, int nelem, unsigned int num, const float *data) 11.162 +{ 11.163 + if(attrib < 0 || attrib >= NUM_MESH_ATTR) { 11.164 + fprintf(stderr, "%s: invalid attrib: %d\n", __FUNCTION__, attrib); 11.165 + return 0; 11.166 + } 11.167 + 11.168 + if(nverts && num != nverts) { 11.169 + fprintf(stderr, "%s: attribute count missmatch (%d instead of %d)\n", __FUNCTION__, num, nverts); 11.170 + return 0; 11.171 + } 11.172 + nverts = num; 11.173 + 11.174 + vattr[attrib].data.clear(); 11.175 + vattr[attrib].nelem = nelem; 11.176 + vattr[attrib].data.resize(num * nelem); 11.177 + 11.178 + if(data) { 11.179 + memcpy(&vattr[attrib].data[0], data, num * nelem * sizeof *data); 11.180 + } 11.181 + 11.182 + vattr[attrib].data_valid = true; 11.183 + vattr[attrib].vbo_valid = false; 11.184 + return &vattr[attrib].data[0]; 11.185 +} 11.186 + 11.187 +float *Mesh::get_attrib_data(int attrib) 11.188 +{ 11.189 + if(attrib < 0 || attrib >= NUM_MESH_ATTR) { 11.190 + fprintf(stderr, "%s: invalid attrib: %d\n", __FUNCTION__, attrib); 11.191 + return 0; 11.192 + } 11.193 + 11.194 + vattr[attrib].vbo_valid = false; 11.195 + return (float*)((const Mesh*)this)->get_attrib_data(attrib); 11.196 +} 11.197 + 11.198 +const float *Mesh::get_attrib_data(int attrib) const 11.199 +{ 11.200 + if(attrib < 0 || attrib >= NUM_MESH_ATTR) { 11.201 + fprintf(stderr, "%s: invalid attrib: %d\n", __FUNCTION__, attrib); 11.202 + return 0; 11.203 + } 11.204 + 11.205 + if(!vattr[attrib].data_valid) { 11.206 +#if GL_ES_VERSION_2_0 11.207 + fprintf(stderr, "%s: can't read back attrib data on CrippledGL ES\n", __FUNCTION__); 11.208 + return 0; 11.209 +#else 11.210 + if(!vattr[attrib].vbo_valid) { 11.211 + fprintf(stderr, "%s: unavailable attrib: %d\n", __FUNCTION__, attrib); 11.212 + return 0; 11.213 + } 11.214 + 11.215 + // local data copy is unavailable, grab the data from the vbo 11.216 + Mesh *m = (Mesh*)this; 11.217 + m->vattr[attrib].data.resize(nverts * vattr[attrib].nelem); 11.218 + 11.219 + glBindBuffer(GL_ARRAY_BUFFER, vattr[attrib].vbo); 11.220 + void *data = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY); 11.221 + memcpy(&m->vattr[attrib].data[0], data, nverts * vattr[attrib].nelem * sizeof(float)); 11.222 + glUnmapBuffer(GL_ARRAY_BUFFER); 11.223 + 11.224 + vattr[attrib].data_valid = true; 11.225 +#endif 11.226 + } 11.227 + 11.228 + return &vattr[attrib].data[0]; 11.229 +} 11.230 + 11.231 +void Mesh::set_attrib(int attrib, int idx, const Vector4 &v) 11.232 +{ 11.233 + float *data = get_attrib_data(attrib); 11.234 + if(data) { 11.235 + data += idx * vattr[attrib].nelem; 11.236 + for(int i=0; i<vattr[attrib].nelem; i++) { 11.237 + data[i] = v[i]; 11.238 + } 11.239 + } 11.240 +} 11.241 + 11.242 +Vector4 Mesh::get_attrib(int attrib, int idx) const 11.243 +{ 11.244 + Vector4 v(0.0, 0.0, 0.0, 1.0); 11.245 + const float *data = get_attrib_data(attrib); 11.246 + if(data) { 11.247 + data += idx * vattr[attrib].nelem; 11.248 + for(int i=0; i<vattr[attrib].nelem; i++) { 11.249 + v[i] = data[i]; 11.250 + } 11.251 + } 11.252 + return v; 11.253 +} 11.254 + 11.255 +int Mesh::get_attrib_count(int attrib) const 11.256 +{ 11.257 + return has_attrib(attrib) ? nverts : 0; 11.258 +} 11.259 + 11.260 + 11.261 +unsigned int *Mesh::set_index_data(int num, const unsigned int *indices) 11.262 +{ 11.263 + int nidx = nfaces * 3; 11.264 + if(nidx && num != nidx) { 11.265 + fprintf(stderr, "%s: index count missmatch (%d instead of %d)\n", __FUNCTION__, num, nidx); 11.266 + return 0; 11.267 + } 11.268 + nfaces = num / 3; 11.269 + 11.270 + idata.clear(); 11.271 + idata.resize(num); 11.272 + 11.273 + if(indices) { 11.274 + memcpy(&idata[0], indices, num * sizeof *indices); 11.275 + } 11.276 + 11.277 + idata_valid = true; 11.278 + ibo_valid = false; 11.279 + 11.280 + return &idata[0]; 11.281 +} 11.282 + 11.283 +unsigned int *Mesh::get_index_data() 11.284 +{ 11.285 + ibo_valid = false; 11.286 + return (unsigned int*)((const Mesh*)this)->get_index_data(); 11.287 +} 11.288 + 11.289 +const unsigned int *Mesh::get_index_data() const 11.290 +{ 11.291 + if(!idata_valid) { 11.292 +#if GL_ES_VERSION_2_0 11.293 + fprintf(stderr, "%s: can't read back index data in CrippledGL ES\n", __FUNCTION__); 11.294 + return 0; 11.295 +#else 11.296 + if(!ibo_valid) { 11.297 + fprintf(stderr, "%s: indices unavailable\n", __FUNCTION__); 11.298 + return 0; 11.299 + } 11.300 + 11.301 + // local data copy is unavailable, gram the data from the ibo 11.302 + Mesh *m = (Mesh*)this; 11.303 + int nidx = nfaces * 3; 11.304 + m->idata.resize(nidx); 11.305 + 11.306 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 11.307 + void *data = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY); 11.308 + memcpy(&m->idata[0], data, nidx * sizeof(unsigned int)); 11.309 + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); 11.310 + 11.311 + idata_valid = true; 11.312 +#endif 11.313 + } 11.314 + 11.315 + return &idata[0]; 11.316 +} 11.317 + 11.318 +int Mesh::get_index_count() const 11.319 +{ 11.320 + return nfaces * 3; 11.321 +} 11.322 + 11.323 +void Mesh::append(const Mesh &mesh) 11.324 +{ 11.325 + unsigned int idxoffs = nverts; 11.326 + 11.327 + nverts += mesh.nverts; 11.328 + nfaces += mesh.nfaces; 11.329 + 11.330 + for(int i=0; i<NUM_MESH_ATTR; i++) { 11.331 + if(has_attrib(i) && mesh.has_attrib(i)) { 11.332 + // force validating the data arrays 11.333 + get_attrib_data(i); 11.334 + mesh.get_attrib_data(i); 11.335 + 11.336 + // append the mesh data 11.337 + vattr[i].data.insert(vattr[i].data.end(), mesh.vattr[i].data.begin(), mesh.vattr[i].data.end()); 11.338 + } 11.339 + } 11.340 + 11.341 + if(ibo_valid || idata_valid) { 11.342 + // make index arrays valid 11.343 + get_index_data(); 11.344 + mesh.get_index_data(); 11.345 + 11.346 + size_t orig_sz = idata.size(); 11.347 + 11.348 + idata.insert(idata.end(), mesh.idata.begin(), mesh.idata.end()); 11.349 + 11.350 + // fixup all the new indices 11.351 + for(size_t i=orig_sz; i<idata.size(); i++) { 11.352 + idata[i] += idxoffs; 11.353 + } 11.354 + } 11.355 + 11.356 + // fuck everything 11.357 + wire_ibo_valid = false; 11.358 + aabb_valid = false; 11.359 + bsph_valid = false; 11.360 +} 11.361 + 11.362 +// assemble a complete vertex by adding all the useful attributes 11.363 +void Mesh::vertex(float x, float y, float z) 11.364 +{ 11.365 + cur_val[MESH_ATTR_VERTEX] = Vector4(x, y, z, 1.0f); 11.366 + vattr[MESH_ATTR_VERTEX].data_valid = true; 11.367 + vattr[MESH_ATTR_VERTEX].nelem = 3; 11.368 + 11.369 + for(int i=0; i<NUM_MESH_ATTR; i++) { 11.370 + if(vattr[i].data_valid) { 11.371 + for(int j=0; j<vattr[MESH_ATTR_VERTEX].nelem; j++) { 11.372 + vattr[i].data.push_back(cur_val[i][j]); 11.373 + } 11.374 + } 11.375 + vattr[i].vbo_valid = false; 11.376 + } 11.377 + 11.378 + if(idata_valid) { 11.379 + idata.clear(); 11.380 + } 11.381 + ibo_valid = idata_valid = false; 11.382 +} 11.383 + 11.384 +void Mesh::normal(float nx, float ny, float nz) 11.385 +{ 11.386 + cur_val[MESH_ATTR_NORMAL] = Vector4(nx, ny, nz, 1.0f); 11.387 + vattr[MESH_ATTR_NORMAL].data_valid = true; 11.388 + vattr[MESH_ATTR_NORMAL].nelem = 3; 11.389 +} 11.390 + 11.391 +void Mesh::tangent(float tx, float ty, float tz) 11.392 +{ 11.393 + cur_val[MESH_ATTR_TANGENT] = Vector4(tx, ty, tz, 1.0f); 11.394 + vattr[MESH_ATTR_TANGENT].data_valid = true; 11.395 + vattr[MESH_ATTR_TANGENT].nelem = 3; 11.396 +} 11.397 + 11.398 +void Mesh::texcoord(float u, float v, float w) 11.399 +{ 11.400 + cur_val[MESH_ATTR_TEXCOORD] = Vector4(u, v, w, 1.0f); 11.401 + vattr[MESH_ATTR_TEXCOORD].data_valid = true; 11.402 + vattr[MESH_ATTR_TEXCOORD].nelem = 3; 11.403 +} 11.404 + 11.405 +void Mesh::boneweights(float w1, float w2, float w3, float w4) 11.406 +{ 11.407 + cur_val[MESH_ATTR_BONEWEIGHTS] = Vector4(w1, w2, w3, w4); 11.408 + vattr[MESH_ATTR_BONEWEIGHTS].data_valid = true; 11.409 + vattr[MESH_ATTR_BONEWEIGHTS].nelem = 4; 11.410 +} 11.411 + 11.412 +void Mesh::boneidx(int idx1, int idx2, int idx3, int idx4) 11.413 +{ 11.414 + cur_val[MESH_ATTR_BONEIDX] = Vector4(idx1, idx2, idx3, idx4); 11.415 + vattr[MESH_ATTR_BONEIDX].data_valid = true; 11.416 + vattr[MESH_ATTR_BONEIDX].nelem = 4; 11.417 +} 11.418 + 11.419 +int Mesh::get_poly_count() const 11.420 +{ 11.421 + if(nfaces) { 11.422 + return nfaces; 11.423 + } 11.424 + if(nverts) { 11.425 + return nverts / 3; 11.426 + } 11.427 + return 0; 11.428 +} 11.429 + 11.430 +/// static function 11.431 +void Mesh::set_attrib_location(int attr, int loc) 11.432 +{ 11.433 + if(attr < 0 || attr >= NUM_MESH_ATTR) { 11.434 + return; 11.435 + } 11.436 + Mesh::global_sdr_loc[attr] = loc; 11.437 +} 11.438 + 11.439 +/// static function 11.440 +int Mesh::get_attrib_location(int attr) 11.441 +{ 11.442 + if(attr < 0 || attr >= NUM_MESH_ATTR) { 11.443 + return -1; 11.444 + } 11.445 + return Mesh::global_sdr_loc[attr]; 11.446 +} 11.447 + 11.448 +/// static function 11.449 +void Mesh::clear_attrib_locations() 11.450 +{ 11.451 + for(int i=0; i<NUM_MESH_ATTR; i++) { 11.452 + Mesh::global_sdr_loc[i] = -1; 11.453 + } 11.454 +} 11.455 + 11.456 +/// static function 11.457 +void Mesh::set_vis_vecsize(float sz) 11.458 +{ 11.459 + Mesh::vis_vecsize = sz; 11.460 +} 11.461 + 11.462 +float Mesh::get_vis_vecsize() 11.463 +{ 11.464 + return Mesh::vis_vecsize; 11.465 +} 11.466 + 11.467 +void Mesh::apply_xform(const Matrix4x4 &xform) 11.468 +{ 11.469 + Matrix4x4 dir_xform = xform; 11.470 + dir_xform[0][3] = dir_xform[1][3] = dir_xform[2][3] = 0.0f; 11.471 + dir_xform[3][0] = dir_xform[3][1] = dir_xform[3][2] = 0.0f; 11.472 + dir_xform[3][3] = 1.0f; 11.473 + 11.474 + apply_xform(xform, dir_xform); 11.475 +} 11.476 + 11.477 +void Mesh::apply_xform(const Matrix4x4 &xform, const Matrix4x4 &dir_xform) 11.478 +{ 11.479 + for(unsigned int i=0; i<nverts; i++) { 11.480 + Vector4 v = get_attrib(MESH_ATTR_VERTEX, i); 11.481 + set_attrib(MESH_ATTR_VERTEX, i, v.transformed(xform)); 11.482 + 11.483 + if(has_attrib(MESH_ATTR_NORMAL)) { 11.484 + Vector3 n = get_attrib(MESH_ATTR_NORMAL, i); 11.485 + set_attrib(MESH_ATTR_NORMAL, i, n.transformed(dir_xform)); 11.486 + } 11.487 + if(has_attrib(MESH_ATTR_TANGENT)) { 11.488 + Vector3 t = get_attrib(MESH_ATTR_TANGENT, i); 11.489 + set_attrib(MESH_ATTR_TANGENT, i, t.transformed(dir_xform)); 11.490 + } 11.491 + } 11.492 +} 11.493 + 11.494 +void Mesh::flip() 11.495 +{ 11.496 + flip_faces(); 11.497 + flip_normals(); 11.498 +} 11.499 + 11.500 +void Mesh::flip_faces() 11.501 +{ 11.502 + if(is_indexed()) { 11.503 + unsigned int *indices = get_index_data(); 11.504 + if(!indices) return; 11.505 + 11.506 + int idxnum = get_index_count(); 11.507 + for(int i=0; i<idxnum; i+=3) { 11.508 + unsigned int tmp = indices[i + 2]; 11.509 + indices[i + 2] = indices[i + 1]; 11.510 + indices[i + 1] = tmp; 11.511 + } 11.512 + 11.513 + } else { 11.514 + Vector3 *verts = (Vector3*)get_attrib_data(MESH_ATTR_VERTEX); 11.515 + if(!verts) return; 11.516 + 11.517 + int vnum = get_attrib_count(MESH_ATTR_VERTEX); 11.518 + for(int i=0; i<vnum; i+=3) { 11.519 + Vector3 tmp = verts[i + 2]; 11.520 + verts[i + 2] = verts[i + 1]; 11.521 + verts[i + 1] = tmp; 11.522 + } 11.523 + } 11.524 +} 11.525 + 11.526 +void Mesh::flip_normals() 11.527 +{ 11.528 + Vector3 *normals = (Vector3*)get_attrib_data(MESH_ATTR_NORMAL); 11.529 + if(!normals) return; 11.530 + 11.531 + int num = get_attrib_count(MESH_ATTR_NORMAL); 11.532 + for(int i=0; i<num; i++) { 11.533 + normals[i] = -normals[i]; 11.534 + } 11.535 +} 11.536 + 11.537 +/* 11.538 +int Mesh::add_bone(XFormNode *bone) 11.539 +{ 11.540 + int idx = bones.size(); 11.541 + bones.push_back(bone); 11.542 + return idx; 11.543 +} 11.544 + 11.545 +const XFormNode *Mesh::get_bone(int idx) const 11.546 +{ 11.547 + if(idx < 0 || idx >= (int)bones.size()) { 11.548 + return 0; 11.549 + } 11.550 + return bones[idx]; 11.551 +} 11.552 + 11.553 +int Mesh::get_bones_count() const 11.554 +{ 11.555 + return (int)bones.size(); 11.556 +} 11.557 +*/ 11.558 + 11.559 +void Mesh::draw() const 11.560 +{ 11.561 +#ifdef GL_ES_VERSION_2_0 11.562 + if(!SdrProg::active) { 11.563 + fprintf(stderr, "%s: CrippledGL ES can't draw without a shader\n", __FUNCTION__); 11.564 + return; 11.565 + } 11.566 +#endif 11.567 + 11.568 + ((Mesh*)this)->update_buffers(); 11.569 + 11.570 + if(!vattr[MESH_ATTR_VERTEX].vbo_valid) { 11.571 + fprintf(stderr, "%s: invalid vertex buffer\n", __FUNCTION__); 11.572 + return; 11.573 + } 11.574 + 11.575 + if(SdrProg::active) { 11.576 + // rendering with shaders 11.577 + if(global_sdr_loc[MESH_ATTR_VERTEX] == -1) { 11.578 + fprintf(stderr, "%s: shader attribute location for vertices unset\n", __FUNCTION__); 11.579 + return; 11.580 + } 11.581 + 11.582 + for(int i=0; i<NUM_MESH_ATTR; i++) { 11.583 + int loc = global_sdr_loc[i]; 11.584 + if(loc >= 0 && vattr[i].vbo_valid) { 11.585 + glBindBuffer(GL_ARRAY_BUFFER, vattr[i].vbo); 11.586 + glVertexAttribPointer(loc, vattr[i].nelem, GL_FLOAT, GL_FALSE, 0, 0); 11.587 + glEnableVertexAttribArray(loc); 11.588 + } 11.589 + } 11.590 + } else { 11.591 +#ifndef GL_ES_VERSION_2_0 11.592 + // rendering with fixed-function (not available in GLES2) 11.593 + glBindBuffer(GL_ARRAY_BUFFER, vattr[MESH_ATTR_VERTEX].vbo); 11.594 + glVertexPointer(vattr[MESH_ATTR_VERTEX].nelem, GL_FLOAT, 0, 0); 11.595 + glEnableClientState(GL_VERTEX_ARRAY); 11.596 + 11.597 + if(vattr[MESH_ATTR_NORMAL].vbo_valid) { 11.598 + glBindBuffer(GL_ARRAY_BUFFER, vattr[MESH_ATTR_NORMAL].vbo); 11.599 + glNormalPointer(GL_FLOAT, 0, 0); 11.600 + glEnableClientState(GL_NORMAL_ARRAY); 11.601 + } 11.602 + if(vattr[MESH_ATTR_TEXCOORD].vbo_valid) { 11.603 + glBindBuffer(GL_ARRAY_BUFFER, vattr[MESH_ATTR_TEXCOORD].vbo); 11.604 + glTexCoordPointer(vattr[MESH_ATTR_TEXCOORD].nelem, GL_FLOAT, 0, 0); 11.605 + glEnableClientState(GL_TEXTURE_COORD_ARRAY); 11.606 + } 11.607 + if(vattr[MESH_ATTR_COLOR].vbo_valid) { 11.608 + glBindBuffer(GL_ARRAY_BUFFER, vattr[MESH_ATTR_COLOR].vbo); 11.609 + glColorPointer(vattr[MESH_ATTR_COLOR].nelem, GL_FLOAT, 0, 0); 11.610 + glEnableClientState(GL_COLOR_ARRAY); 11.611 + } 11.612 +#endif 11.613 + } 11.614 + glBindBuffer(GL_ARRAY_BUFFER, 0); 11.615 + 11.616 + if(ibo_valid) { 11.617 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 11.618 + glDrawElements(GL_TRIANGLES, nfaces * 3, GL_UNSIGNED_INT, 0); 11.619 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 11.620 + } else { 11.621 + glDrawArrays(GL_TRIANGLES, 0, nverts); 11.622 + } 11.623 + 11.624 + if(SdrProg::active) { 11.625 + // rendered with shaders 11.626 + for(int i=0; i<NUM_MESH_ATTR; i++) { 11.627 + int loc = global_sdr_loc[i]; 11.628 + if(loc >= 0 && vattr[i].vbo_valid) { 11.629 + glDisableVertexAttribArray(loc); 11.630 + } 11.631 + } 11.632 + } else { 11.633 +#ifndef GL_ES_VERSION_2_0 11.634 + // rendered with fixed-function 11.635 + glDisableClientState(GL_VERTEX_ARRAY); 11.636 + if(vattr[MESH_ATTR_NORMAL].vbo_valid) { 11.637 + glDisableClientState(GL_NORMAL_ARRAY); 11.638 + } 11.639 + if(vattr[MESH_ATTR_TEXCOORD].vbo_valid) { 11.640 + glDisableClientState(GL_TEXTURE_COORD_ARRAY); 11.641 + } 11.642 + if(vattr[MESH_ATTR_COLOR].vbo_valid) { 11.643 + glDisableClientState(GL_COLOR_ARRAY); 11.644 + } 11.645 +#endif 11.646 + } 11.647 +} 11.648 + 11.649 +void Mesh::draw_wire() const 11.650 +{ 11.651 + ((Mesh*)this)->update_wire_ibo(); 11.652 + 11.653 + if(!vattr[MESH_ATTR_VERTEX].vbo_valid || !wire_ibo_valid) { 11.654 + fprintf(stderr, "%s: invalid vertex buffer\n", __FUNCTION__); 11.655 + return; 11.656 + } 11.657 + if(global_sdr_loc[MESH_ATTR_VERTEX] == -1) { 11.658 + fprintf(stderr, "%s: shader attribute location for vertices unset\n", __FUNCTION__); 11.659 + return; 11.660 + } 11.661 + 11.662 + for(int i=0; i<NUM_MESH_ATTR; i++) { 11.663 + int loc = global_sdr_loc[i]; 11.664 + if(loc >= 0 && vattr[i].vbo_valid) { 11.665 + glBindBuffer(GL_ARRAY_BUFFER, vattr[i].vbo); 11.666 + glVertexAttribPointer(loc, vattr[i].nelem, GL_FLOAT, GL_FALSE, 0, 0); 11.667 + glEnableVertexAttribArray(loc); 11.668 + } 11.669 + } 11.670 + glBindBuffer(GL_ARRAY_BUFFER, 0); 11.671 + 11.672 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, wire_ibo); 11.673 + glDrawElements(GL_LINES, nfaces * 6, GL_UNSIGNED_INT, 0); 11.674 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 11.675 + 11.676 + for(int i=0; i<NUM_MESH_ATTR; i++) { 11.677 + int loc = global_sdr_loc[i]; 11.678 + if(loc >= 0 && vattr[i].vbo_valid) { 11.679 + glDisableVertexAttribArray(loc); 11.680 + } 11.681 + } 11.682 +} 11.683 + 11.684 +void Mesh::draw_vertices() const 11.685 +{ 11.686 + ((Mesh*)this)->update_buffers(); 11.687 + 11.688 + if(!vattr[MESH_ATTR_VERTEX].vbo_valid) { 11.689 + fprintf(stderr, "%s: invalid vertex buffer\n", __FUNCTION__); 11.690 + return; 11.691 + } 11.692 + if(global_sdr_loc[MESH_ATTR_VERTEX] == -1) { 11.693 + fprintf(stderr, "%s: shader attribute location for vertices unset\n", __FUNCTION__); 11.694 + return; 11.695 + } 11.696 + 11.697 + for(int i=0; i<NUM_MESH_ATTR; i++) { 11.698 + int loc = global_sdr_loc[i]; 11.699 + if(loc >= 0 && vattr[i].vbo_valid) { 11.700 + glBindBuffer(GL_ARRAY_BUFFER, vattr[i].vbo); 11.701 + glVertexAttribPointer(loc, vattr[i].nelem, GL_FLOAT, GL_FALSE, 0, 0); 11.702 + glEnableVertexAttribArray(loc); 11.703 + } 11.704 + } 11.705 + glBindBuffer(GL_ARRAY_BUFFER, 0); 11.706 + 11.707 + glDrawArrays(GL_POINTS, 0, nverts); 11.708 + 11.709 + for(int i=0; i<NUM_MESH_ATTR; i++) { 11.710 + int loc = global_sdr_loc[i]; 11.711 + if(loc >= 0 && vattr[i].vbo_valid) { 11.712 + glDisableVertexAttribArray(loc); 11.713 + } 11.714 + } 11.715 +} 11.716 + 11.717 +void Mesh::draw_normals() const 11.718 +{ 11.719 +#ifdef USE_OLDGL 11.720 + Vector3 *varr = (Vector3*)get_attrib_data(MESH_ATTR_VERTEX); 11.721 + Vector3 *norm = (Vector3*)get_attrib_data(MESH_ATTR_NORMAL); 11.722 + if(!varr || !norm) { 11.723 + return; 11.724 + } 11.725 + 11.726 + glBegin(GL_LINES); 11.727 + if(get_current_shader()) { 11.728 + int vert_loc = global_sdr_loc[MESH_ATTR_VERTEX]; 11.729 + if(vert_loc < 0) { 11.730 + glEnd(); 11.731 + return; 11.732 + } 11.733 + 11.734 + for(size_t i=0; i<nverts; i++) { 11.735 + glVertexAttrib3f(vert_loc, varr[i].x, varr[i].y, varr[i].z); 11.736 + Vector3 end = varr[i] + norm[i] * vis_vecsize; 11.737 + glVertexAttrib3f(vert_loc, end.x, end.y, end.z); 11.738 + } 11.739 + } else { 11.740 + for(size_t i=0; i<nverts; i++) { 11.741 + glVertex3f(varr[i].x, varr[i].y, varr[i].z); 11.742 + Vector3 end = varr[i] + norm[i] * vis_vecsize; 11.743 + glVertex3f(end.x, end.y, end.z); 11.744 + } 11.745 + } 11.746 + glEnd(); 11.747 +#endif // USE_OLDGL 11.748 +} 11.749 + 11.750 +void Mesh::draw_tangents() const 11.751 +{ 11.752 +#ifdef USE_OLDGL 11.753 + Vector3 *varr = (Vector3*)get_attrib_data(MESH_ATTR_VERTEX); 11.754 + Vector3 *tang = (Vector3*)get_attrib_data(MESH_ATTR_TANGENT); 11.755 + if(!varr || !tang) { 11.756 + return; 11.757 + } 11.758 + 11.759 + glBegin(GL_LINES); 11.760 + if(get_current_shader()) { 11.761 + int vert_loc = global_sdr_loc[MESH_ATTR_VERTEX]; 11.762 + if(vert_loc < 0) { 11.763 + glEnd(); 11.764 + return; 11.765 + } 11.766 + 11.767 + for(size_t i=0; i<nverts; i++) { 11.768 + glVertexAttrib3f(vert_loc, varr[i].x, varr[i].y, varr[i].z); 11.769 + Vector3 end = varr[i] + tang[i] * vis_vecsize; 11.770 + glVertexAttrib3f(vert_loc, end.x, end.y, end.z); 11.771 + } 11.772 + } else { 11.773 + for(size_t i=0; i<nverts; i++) { 11.774 + glVertex3f(varr[i].x, varr[i].y, varr[i].z); 11.775 + Vector3 end = varr[i] + tang[i] * vis_vecsize; 11.776 + glVertex3f(end.x, end.y, end.z); 11.777 + } 11.778 + } 11.779 + glEnd(); 11.780 +#endif // USE_OLDGL 11.781 +} 11.782 + 11.783 +void Mesh::get_aabbox(Vector3 *vmin, Vector3 *vmax) const 11.784 +{ 11.785 + if(!aabb_valid) { 11.786 + ((Mesh*)this)->calc_aabb(); 11.787 + } 11.788 + *vmin = aabb.min; 11.789 + *vmax = aabb.max; 11.790 +} 11.791 + 11.792 +const AABox &Mesh::get_aabbox() const 11.793 +{ 11.794 + if(!aabb_valid) { 11.795 + ((Mesh*)this)->calc_aabb(); 11.796 + } 11.797 + return aabb; 11.798 +} 11.799 + 11.800 +float Mesh::get_bsphere(Vector3 *center, float *rad) const 11.801 +{ 11.802 + if(!bsph_valid) { 11.803 + ((Mesh*)this)->calc_bsph(); 11.804 + } 11.805 + *center = bsph.center; 11.806 + *rad = bsph.radius; 11.807 + return bsph.radius; 11.808 +} 11.809 + 11.810 +const Sphere &Mesh::get_bsphere() const 11.811 +{ 11.812 + if(!bsph_valid) { 11.813 + ((Mesh*)this)->calc_bsph(); 11.814 + } 11.815 + return bsph; 11.816 +} 11.817 + 11.818 +/// static function 11.819 +void Mesh::set_intersect_mode(unsigned int mode) 11.820 +{ 11.821 + Mesh::intersect_mode = mode; 11.822 +} 11.823 + 11.824 +/// static function 11.825 +unsigned int Mesh::get_intersect_mode() 11.826 +{ 11.827 + return Mesh::intersect_mode; 11.828 +} 11.829 + 11.830 +/// static function 11.831 +void Mesh::set_vertex_select_distance(float dist) 11.832 +{ 11.833 + Mesh::vertex_sel_dist = dist; 11.834 +} 11.835 + 11.836 +/// static function 11.837 +float Mesh::get_vertex_select_distance() 11.838 +{ 11.839 + return Mesh::vertex_sel_dist; 11.840 +} 11.841 + 11.842 +bool Mesh::intersect(const Ray &ray, HitPoint *hit) const 11.843 +{ 11.844 + assert((Mesh::intersect_mode & (ISECT_VERTICES | ISECT_FACE)) != (ISECT_VERTICES | ISECT_FACE)); 11.845 + 11.846 + const Vector3 *varr = (Vector3*)get_attrib_data(MESH_ATTR_VERTEX); 11.847 + const Vector3 *narr = (Vector3*)get_attrib_data(MESH_ATTR_NORMAL); 11.848 + if(!varr) { 11.849 + return false; 11.850 + } 11.851 + const unsigned int *idxarr = get_index_data(); 11.852 + 11.853 + // first test with the bounding box 11.854 + AABox box; 11.855 + get_aabbox(&box.min, &box.max); 11.856 + if(!box.intersect(ray)) { 11.857 + return false; 11.858 + } 11.859 + 11.860 + HitPoint nearest_hit; 11.861 + nearest_hit.dist = FLT_MAX; 11.862 + nearest_hit.obj = 0; 11.863 + 11.864 + if(Mesh::intersect_mode & ISECT_VERTICES) { 11.865 + // we asked for "intersections" with the vertices of the mesh 11.866 + long nearest_vidx = -1; 11.867 + float thres_sq = Mesh::vertex_sel_dist * Mesh::vertex_sel_dist; 11.868 + 11.869 + for(unsigned int i=0; i<nverts; i++) { 11.870 + 11.871 + if((Mesh::intersect_mode & ISECT_FRONT) && dot_product(narr[i], ray.dir) > 0) { 11.872 + continue; 11.873 + } 11.874 + 11.875 + // project the vertex onto the ray line 11.876 + float t = dot_product(varr[i] - ray.origin, ray.dir); 11.877 + Vector3 vproj = ray.origin + ray.dir * t; 11.878 + 11.879 + float dist_sq = (vproj - varr[i]).length_sq(); 11.880 + if(dist_sq < thres_sq) { 11.881 + if(!hit) { 11.882 + return true; 11.883 + } 11.884 + if(t < nearest_hit.dist) { 11.885 + nearest_hit.dist = t; 11.886 + nearest_vidx = i; 11.887 + } 11.888 + } 11.889 + } 11.890 + 11.891 + if(nearest_vidx != -1) { 11.892 + hitvert = varr[nearest_vidx]; 11.893 + nearest_hit.obj = &hitvert; 11.894 + } 11.895 + 11.896 + } else { 11.897 + // regular intersection test with polygons 11.898 + 11.899 + for(unsigned int i=0; i<nfaces; i++) { 11.900 + Triangle face(i, varr, idxarr); 11.901 + 11.902 + // ignore back-facing polygons if the mode flags include ISECT_FRONT 11.903 + if((Mesh::intersect_mode & ISECT_FRONT) && dot_product(face.get_normal(), ray.dir) > 0) { 11.904 + continue; 11.905 + } 11.906 + 11.907 + HitPoint fhit; 11.908 + if(face.intersect(ray, hit ? &fhit : 0)) { 11.909 + if(!hit) { 11.910 + return true; 11.911 + } 11.912 + if(fhit.dist < nearest_hit.dist) { 11.913 + nearest_hit = fhit; 11.914 + hitface = face; 11.915 + } 11.916 + } 11.917 + } 11.918 + } 11.919 + 11.920 + if(nearest_hit.obj) { 11.921 + if(hit) { 11.922 + *hit = nearest_hit; 11.923 + 11.924 + // if we are interested in the mesh and not the faces set obj to this 11.925 + if(Mesh::intersect_mode & ISECT_FACE) { 11.926 + hit->obj = &hitface; 11.927 + } else if(Mesh::intersect_mode & ISECT_VERTICES) { 11.928 + hit->obj = &hitvert; 11.929 + } else { 11.930 + hit->obj = this; 11.931 + } 11.932 + } 11.933 + return true; 11.934 + } 11.935 + return false; 11.936 +} 11.937 + 11.938 + 11.939 +// ------ private member functions ------ 11.940 + 11.941 +void Mesh::calc_aabb() 11.942 +{ 11.943 + // the cast is to force calling the const version which doesn't invalidate 11.944 + if(!((const Mesh*)this)->get_attrib_data(MESH_ATTR_VERTEX)) { 11.945 + return; 11.946 + } 11.947 + 11.948 + aabb.min = Vector3(FLT_MAX, FLT_MAX, FLT_MAX); 11.949 + aabb.max = -aabb.min; 11.950 + 11.951 + for(unsigned int i=0; i<nverts; i++) { 11.952 + Vector4 v = get_attrib(MESH_ATTR_VERTEX, i); 11.953 + for(int j=0; j<3; j++) { 11.954 + if(v[j] < aabb.min[j]) { 11.955 + aabb.min[j] = v[j]; 11.956 + } 11.957 + if(v[j] > aabb.max[j]) { 11.958 + aabb.max[j] = v[j]; 11.959 + } 11.960 + } 11.961 + } 11.962 + aabb_valid = true; 11.963 +} 11.964 + 11.965 +void Mesh::calc_bsph() 11.966 +{ 11.967 + // the cast is to force calling the const version which doesn't invalidate 11.968 + if(!((const Mesh*)this)->get_attrib_data(MESH_ATTR_VERTEX)) { 11.969 + return; 11.970 + } 11.971 + 11.972 + Vector3 v; 11.973 + bsph.center = Vector3(0, 0, 0); 11.974 + 11.975 + // first find the center 11.976 + for(unsigned int i=0; i<nverts; i++) { 11.977 + v = get_attrib(MESH_ATTR_VERTEX, i); 11.978 + bsph.center += v; 11.979 + } 11.980 + bsph.center /= (float)nverts; 11.981 + 11.982 + bsph.radius = 0.0f; 11.983 + for(unsigned int i=0; i<nverts; i++) { 11.984 + v = get_attrib(MESH_ATTR_VERTEX, i); 11.985 + float dist_sq = (v - bsph.center).length_sq(); 11.986 + if(dist_sq > bsph.radius) { 11.987 + bsph.radius = dist_sq; 11.988 + } 11.989 + } 11.990 + bsph.radius = sqrt(bsph.radius); 11.991 + 11.992 + bsph_valid = true; 11.993 +} 11.994 + 11.995 +void Mesh::update_buffers() 11.996 +{ 11.997 + for(int i=0; i<NUM_MESH_ATTR; i++) { 11.998 + if(has_attrib(i) && !vattr[i].vbo_valid) { 11.999 + glBindBuffer(GL_ARRAY_BUFFER, vattr[i].vbo); 11.1000 + glBufferData(GL_ARRAY_BUFFER, nverts * vattr[i].nelem * sizeof(float), &vattr[i].data[0], GL_STATIC_DRAW); 11.1001 + vattr[i].vbo_valid = true; 11.1002 + } 11.1003 + } 11.1004 + glBindBuffer(GL_ARRAY_BUFFER, 0); 11.1005 + 11.1006 + if(idata_valid && !ibo_valid) { 11.1007 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 11.1008 + glBufferData(GL_ELEMENT_ARRAY_BUFFER, nfaces * 3 * sizeof(unsigned int), &idata[0], GL_STATIC_DRAW); 11.1009 + ibo_valid = true; 11.1010 + } 11.1011 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 11.1012 +} 11.1013 + 11.1014 +void Mesh::update_wire_ibo() 11.1015 +{ 11.1016 + update_buffers(); 11.1017 + 11.1018 + if(wire_ibo_valid) { 11.1019 + return; 11.1020 + } 11.1021 + 11.1022 + if(!wire_ibo) { 11.1023 + glGenBuffers(1, &wire_ibo); 11.1024 + } 11.1025 + 11.1026 + unsigned int *wire_idxarr = new unsigned int[nfaces * 6]; 11.1027 + unsigned int *dest = wire_idxarr; 11.1028 + 11.1029 + if(ibo_valid) { 11.1030 + // we're dealing with an indexed mesh 11.1031 + const unsigned int *idxarr = ((const Mesh*)this)->get_index_data(); 11.1032 + 11.1033 + for(unsigned int i=0; i<nfaces; i++) { 11.1034 + *dest++ = idxarr[0]; 11.1035 + *dest++ = idxarr[1]; 11.1036 + *dest++ = idxarr[1]; 11.1037 + *dest++ = idxarr[2]; 11.1038 + *dest++ = idxarr[2]; 11.1039 + *dest++ = idxarr[0]; 11.1040 + idxarr += 3; 11.1041 + } 11.1042 + } else { 11.1043 + // not an indexed mesh ... 11.1044 + for(unsigned int i=0; i<nfaces; i++) { 11.1045 + int vidx = i * 3; 11.1046 + *dest++ = vidx; 11.1047 + *dest++ = vidx + 1; 11.1048 + *dest++ = vidx + 1; 11.1049 + *dest++ = vidx + 2; 11.1050 + *dest++ = vidx + 2; 11.1051 + *dest++ = vidx; 11.1052 + } 11.1053 + } 11.1054 + 11.1055 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, wire_ibo); 11.1056 + glBufferData(GL_ELEMENT_ARRAY_BUFFER, nfaces * 6 * sizeof(unsigned int), wire_idxarr, GL_STATIC_DRAW); 11.1057 + delete [] wire_idxarr; 11.1058 + wire_ibo_valid = true; 11.1059 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 11.1060 +} 11.1061 + 11.1062 + 11.1063 +// ------ class Triangle ------ 11.1064 +Triangle::Triangle() 11.1065 +{ 11.1066 + normal_valid = false; 11.1067 + id = -1; 11.1068 +} 11.1069 + 11.1070 +Triangle::Triangle(const Vector3 &v0, const Vector3 &v1, const Vector3 &v2) 11.1071 +{ 11.1072 + v[0] = v0; 11.1073 + v[1] = v1; 11.1074 + v[2] = v2; 11.1075 + normal_valid = false; 11.1076 + id = -1; 11.1077 +} 11.1078 + 11.1079 +Triangle::Triangle(int n, const Vector3 *varr, const unsigned int *idxarr) 11.1080 +{ 11.1081 + if(idxarr) { 11.1082 + v[0] = varr[idxarr[n * 3]]; 11.1083 + v[1] = varr[idxarr[n * 3 + 1]]; 11.1084 + v[2] = varr[idxarr[n * 3 + 2]]; 11.1085 + } else { 11.1086 + v[0] = varr[n * 3]; 11.1087 + v[1] = varr[n * 3 + 1]; 11.1088 + v[2] = varr[n * 3 + 2]; 11.1089 + } 11.1090 + normal_valid = false; 11.1091 + id = n; 11.1092 +} 11.1093 + 11.1094 +void Triangle::calc_normal() 11.1095 +{ 11.1096 + normal = cross_product(v[1] - v[0], v[2] - v[0]).normalized(); 11.1097 + normal_valid = true; 11.1098 +} 11.1099 + 11.1100 +const Vector3 &Triangle::get_normal() const 11.1101 +{ 11.1102 + if(!normal_valid) { 11.1103 + ((Triangle*)this)->calc_normal(); 11.1104 + } 11.1105 + return normal; 11.1106 +} 11.1107 + 11.1108 +void Triangle::transform(const Matrix4x4 &xform) 11.1109 +{ 11.1110 + v[0].transform(xform); 11.1111 + v[1].transform(xform); 11.1112 + v[2].transform(xform); 11.1113 + normal_valid = false; 11.1114 +} 11.1115 + 11.1116 +void Triangle::draw() const 11.1117 +{ 11.1118 + Vector3 n[3]; 11.1119 + n[0] = get_normal(); 11.1120 + n[1] = get_normal(); 11.1121 + n[2] = get_normal(); 11.1122 + 11.1123 + int vloc = Mesh::get_attrib_location(MESH_ATTR_VERTEX); 11.1124 + int nloc = Mesh::get_attrib_location(MESH_ATTR_NORMAL); 11.1125 + 11.1126 + glEnableVertexAttribArray(vloc); 11.1127 + glVertexAttribPointer(vloc, 3, GL_FLOAT, GL_FALSE, 0, &v[0].x); 11.1128 + glVertexAttribPointer(nloc, 3, GL_FLOAT, GL_FALSE, 0, &n[0].x); 11.1129 + 11.1130 + glDrawArrays(GL_TRIANGLES, 0, 3); 11.1131 + 11.1132 + glDisableVertexAttribArray(vloc); 11.1133 + glDisableVertexAttribArray(nloc); 11.1134 + CHECK_GLERROR; 11.1135 +} 11.1136 + 11.1137 +void Triangle::draw_wire() const 11.1138 +{ 11.1139 + static const int idxarr[] = {0, 1, 1, 2, 2, 0}; 11.1140 + int vloc = Mesh::get_attrib_location(MESH_ATTR_VERTEX); 11.1141 + 11.1142 + glEnableVertexAttribArray(vloc); 11.1143 + glVertexAttribPointer(vloc, 3, GL_FLOAT, GL_FALSE, 0, &v[0].x); 11.1144 + 11.1145 + glDrawElements(GL_LINES, 6, GL_UNSIGNED_INT, idxarr); 11.1146 + 11.1147 + glDisableVertexAttribArray(vloc); 11.1148 + CHECK_GLERROR; 11.1149 +} 11.1150 + 11.1151 +Vector3 Triangle::calc_barycentric(const Vector3 &pos) const 11.1152 +{ 11.1153 + Vector3 norm = get_normal(); 11.1154 + 11.1155 + float area_sq = fabs(dot_product(cross_product(v[1] - v[0], v[2] - v[0]), norm)); 11.1156 + if(area_sq < 1e-5) { 11.1157 + return Vector3(0, 0, 0); 11.1158 + } 11.1159 + 11.1160 + float asq0 = fabs(dot_product(cross_product(v[1] - pos, v[2] - pos), norm)); 11.1161 + float asq1 = fabs(dot_product(cross_product(v[2] - pos, v[0] - pos), norm)); 11.1162 + float asq2 = fabs(dot_product(cross_product(v[0] - pos, v[1] - pos), norm)); 11.1163 + 11.1164 + return Vector3(asq0 / area_sq, asq1 / area_sq, asq2 / area_sq); 11.1165 +} 11.1166 + 11.1167 +bool Triangle::intersect(const Ray &ray, HitPoint *hit) const 11.1168 +{ 11.1169 + Vector3 normal = get_normal(); 11.1170 + 11.1171 + float ndotdir = dot_product(ray.dir, normal); 11.1172 + if(fabs(ndotdir) < 1e-4) { 11.1173 + return false; 11.1174 + } 11.1175 + 11.1176 + Vector3 vertdir = v[0] - ray.origin; 11.1177 + float t = dot_product(normal, vertdir) / ndotdir; 11.1178 + 11.1179 + Vector3 pos = ray.origin + ray.dir * t; 11.1180 + Vector3 bary = calc_barycentric(pos); 11.1181 + 11.1182 + if(bary.x + bary.y + bary.z > 1.00001) { 11.1183 + return false; 11.1184 + } 11.1185 + 11.1186 + if(hit) { 11.1187 + hit->dist = t; 11.1188 + hit->pos = ray.origin + ray.dir * t; 11.1189 + hit->normal = normal; 11.1190 + hit->obj = this; 11.1191 + } 11.1192 + return true; 11.1193 +}
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/src/mesh.h Thu Jun 18 03:12:30 2015 +0300 12.3 @@ -0,0 +1,225 @@ 12.4 +#ifndef MESH_H_ 12.5 +#define MESH_H_ 12.6 + 12.7 +#include <string> 12.8 +#include <vector> 12.9 +#include "vmath/vmath.h" 12.10 +#include "geom.h" 12.11 + 12.12 +enum { 12.13 + MESH_ATTR_VERTEX, 12.14 + MESH_ATTR_NORMAL, 12.15 + MESH_ATTR_TANGENT, 12.16 + MESH_ATTR_TEXCOORD, 12.17 + MESH_ATTR_COLOR, 12.18 + MESH_ATTR_BONEWEIGHTS, 12.19 + MESH_ATTR_BONEIDX, 12.20 + 12.21 + NUM_MESH_ATTR 12.22 +}; 12.23 + 12.24 +// intersection mode flags 12.25 +enum { 12.26 + ISECT_DEFAULT = 0, // default (whole mesh, all intersections) 12.27 + ISECT_FRONT = 1, // front-faces only 12.28 + ISECT_FACE = 2, // return intersected face pointer instead of mesh 12.29 + ISECT_VERTICES = 4 // return (?) TODO 12.30 +}; 12.31 + 12.32 +//class XFormNode; 12.33 + 12.34 + 12.35 +class Triangle { 12.36 +public: 12.37 + Vector3 v[3]; 12.38 + Vector3 normal; 12.39 + bool normal_valid; 12.40 + int id; 12.41 + 12.42 + Triangle(); 12.43 + Triangle(const Vector3 &v0, const Vector3 &v1, const Vector3 &v2); 12.44 + Triangle(int n, const Vector3 *varr, const unsigned int *idxarr = 0); 12.45 + 12.46 + /// calculate normal (quite expensive) 12.47 + void calc_normal(); 12.48 + const Vector3 &get_normal() const; 12.49 + 12.50 + void transform(const Matrix4x4 &xform); 12.51 + 12.52 + void draw() const; 12.53 + void draw_wire() const; 12.54 + 12.55 + /// calculate barycentric coordinates of a point 12.56 + Vector3 calc_barycentric(const Vector3 &pos) const; 12.57 + 12.58 + bool intersect(const Ray &ray, HitPoint *hit = 0) const; 12.59 +}; 12.60 + 12.61 + 12.62 +class Mesh { 12.63 +private: 12.64 + std::string name; 12.65 + unsigned int nverts, nfaces; 12.66 + 12.67 + // current value for each attribute for the immedate mode 12.68 + // interface. 12.69 + Vector4 cur_val[NUM_MESH_ATTR]; 12.70 + 12.71 + unsigned int buffer_objects[NUM_MESH_ATTR + 1]; 12.72 + 12.73 + // vertex attribute data and buffer objects 12.74 + struct { 12.75 + int nelem; // number of elements per attribute range: [1, 4] 12.76 + std::vector<float> data; 12.77 + unsigned int vbo; 12.78 + mutable bool vbo_valid; // if this is false, the vbo needs updating from the data 12.79 + mutable bool data_valid; // if this is false, the data needs to be pulled from the vbo 12.80 + //int sdr_loc; 12.81 + } vattr[NUM_MESH_ATTR]; 12.82 + 12.83 + static int global_sdr_loc[NUM_MESH_ATTR]; 12.84 + 12.85 + //std::vector<XFormNode*> bones; // bones affecting this mesh 12.86 + 12.87 + // index data and buffer object 12.88 + std::vector<unsigned int> idata; 12.89 + unsigned int ibo; 12.90 + mutable bool ibo_valid; 12.91 + mutable bool idata_valid; 12.92 + 12.93 + // index buffer object for wireframe rendering (constructed on demand) 12.94 + unsigned int wire_ibo; 12.95 + mutable bool wire_ibo_valid; 12.96 + 12.97 + // axis-aligned bounding box 12.98 + mutable AABox aabb; 12.99 + mutable bool aabb_valid; 12.100 + 12.101 + // bounding sphere 12.102 + mutable Sphere bsph; 12.103 + mutable bool bsph_valid; 12.104 + 12.105 + // keeps the last intersected face 12.106 + mutable Triangle hitface; 12.107 + // keeps the last intersected vertex position 12.108 + mutable Vector3 hitvert; 12.109 + 12.110 + void calc_aabb(); 12.111 + void calc_bsph(); 12.112 + 12.113 + static unsigned int intersect_mode; 12.114 + static float vertex_sel_dist; 12.115 + 12.116 + static float vis_vecsize; 12.117 + 12.118 + /// update the VBOs after data has changed (invalid vbo/ibo) 12.119 + void update_buffers(); 12.120 + /// construct/update the wireframe index buffer (called from draw_wire). 12.121 + void update_wire_ibo(); 12.122 + 12.123 + 12.124 +public: 12.125 + Mesh(); 12.126 + ~Mesh(); 12.127 + 12.128 + Mesh(const Mesh &rhs); 12.129 + Mesh &operator =(const Mesh &rhs); 12.130 + bool clone(const Mesh &m); 12.131 + 12.132 + void set_name(const char *name); 12.133 + const char *get_name() const; 12.134 + 12.135 + bool has_attrib(int attr) const; 12.136 + bool is_indexed() const; 12.137 + 12.138 + // clears everything about this mesh, and returns to the newly constructed state 12.139 + void clear(); 12.140 + 12.141 + // access the vertex attribute data 12.142 + // if vdata == 0, space is just allocated 12.143 + float *set_attrib_data(int attrib, int nelem, unsigned int num, const float *vdata = 0); // invalidates vbo 12.144 + float *get_attrib_data(int attrib); // invalidates vbo 12.145 + const float *get_attrib_data(int attrib) const; 12.146 + 12.147 + // simple access to any particular attribute 12.148 + void set_attrib(int attrib, int idx, const Vector4 &v); // invalidates vbo 12.149 + Vector4 get_attrib(int attrib, int idx) const; 12.150 + 12.151 + int get_attrib_count(int attrib) const; 12.152 + 12.153 + // ... same for index data 12.154 + unsigned int *set_index_data(int num, const unsigned int *indices = 0); // invalidates ibo 12.155 + unsigned int *get_index_data(); // invalidates ibo 12.156 + const unsigned int *get_index_data() const; 12.157 + 12.158 + int get_index_count() const; 12.159 + 12.160 + void append(const Mesh &mesh); 12.161 + 12.162 + // immediate-mode style mesh construction interface 12.163 + void vertex(float x, float y, float z); 12.164 + void normal(float nx, float ny, float nz); 12.165 + void tangent(float tx, float ty, float tz); 12.166 + void texcoord(float u, float v, float w); 12.167 + void boneweights(float w1, float w2, float w3, float w4); 12.168 + void boneidx(int idx1, int idx2, int idx3, int idx4); 12.169 + 12.170 + int get_poly_count() const; 12.171 + 12.172 + /* apply a transformation to the vertices and its inverse-transpose 12.173 + * to the normals and tangents. 12.174 + */ 12.175 + void apply_xform(const Matrix4x4 &xform); 12.176 + void apply_xform(const Matrix4x4 &xform, const Matrix4x4 &dir_xform); 12.177 + 12.178 + void flip(); // both faces and normals 12.179 + void flip_faces(); 12.180 + void flip_normals(); 12.181 + 12.182 + // adds a bone and returns its index 12.183 + /*int add_bone(XFormNode *bone); 12.184 + const XFormNode *get_bone(int idx) const; 12.185 + int get_bones_count() const;*/ 12.186 + 12.187 + // access the shader attribute locations 12.188 + static void set_attrib_location(int attr, int loc); 12.189 + static int get_attrib_location(int attr); 12.190 + static void clear_attrib_locations(); 12.191 + 12.192 + static void set_vis_vecsize(float sz); 12.193 + static float get_vis_vecsize(); 12.194 + 12.195 + void draw() const; 12.196 + void draw_wire() const; 12.197 + void draw_vertices() const; 12.198 + void draw_normals() const; 12.199 + void draw_tangents() const; 12.200 + 12.201 + /** get the bounding box in local space. The result will be cached, and subsequent 12.202 + * calls will return the same box. The cache gets invalidated by any functions that can affect 12.203 + * the vertex data (non-const variant of get_attrib_data(MESH_ATTR_VERTEX, ...) included). 12.204 + * @{ */ 12.205 + void get_aabbox(Vector3 *vmin, Vector3 *vmax) const; 12.206 + const AABox &get_aabbox() const; 12.207 + /// @} 12.208 + 12.209 + /** get the bounding sphere in local space. The result will be cached, and subsequent 12.210 + * calls will return the same box. The cache gets invalidated by any functions that can affect 12.211 + * the vertex data (non-const variant of get_attrib_data(MESH_ATTR_VERTEX, ...) included). 12.212 + * @{ */ 12.213 + float get_bsphere(Vector3 *center, float *rad) const; 12.214 + const Sphere &get_bsphere() const; 12.215 + 12.216 + static void set_intersect_mode(unsigned int mode); 12.217 + static unsigned int get_intersect_mode(); 12.218 + static void set_vertex_select_distance(float dist); 12.219 + static float get_vertex_select_distance(); 12.220 + 12.221 + /** Find the intersection between the mesh and a ray. 12.222 + * XXX Brute force at the moment, not intended to be used for anything other than picking in tools. 12.223 + * If you intend to use it in a speed-critical part of the code, you'll *have* to optimize it! 12.224 + */ 12.225 + bool intersect(const Ray &ray, HitPoint *hit = 0) const; 12.226 +}; 12.227 + 12.228 +#endif // MESH_H_
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/src/meshgen.cc Thu Jun 18 03:12:30 2015 +0300 13.3 @@ -0,0 +1,395 @@ 13.4 +#include <stdio.h> 13.5 +#include "meshgen.h" 13.6 +#include "mesh.h" 13.7 + 13.8 +// -------- sphere -------- 13.9 + 13.10 +#define SURAD(u) ((u) * 2.0 * M_PI) 13.11 +#define SVRAD(v) ((v) * M_PI) 13.12 + 13.13 +static Vector3 sphvec(float theta, float phi) 13.14 +{ 13.15 + return Vector3(sin(theta) * sin(phi), 13.16 + cos(phi), 13.17 + cos(theta) * sin(phi)); 13.18 +} 13.19 + 13.20 +void gen_sphere(Mesh *mesh, float rad, int usub, int vsub, float urange, float vrange) 13.21 +{ 13.22 + if(usub < 4) usub = 4; 13.23 + if(vsub < 2) vsub = 2; 13.24 + 13.25 + int uverts = usub + 1; 13.26 + int vverts = vsub + 1; 13.27 + 13.28 + int num_verts = uverts * vverts; 13.29 + int num_quads = usub * vsub; 13.30 + int num_tri = num_quads * 2; 13.31 + 13.32 + mesh->clear(); 13.33 + Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 13.34 + Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 13.35 + Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 13.36 + Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); 13.37 + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); 13.38 + 13.39 + float du = urange / (float)(uverts - 1); 13.40 + float dv = vrange / (float)(vverts - 1); 13.41 + 13.42 + float u = 0.0; 13.43 + for(int i=0; i<uverts; i++) { 13.44 + float theta = SURAD(u * urange); 13.45 + 13.46 + float v = 0.0; 13.47 + for(int j=0; j<vverts; j++) { 13.48 + float phi = SVRAD(v * vrange); 13.49 + 13.50 + Vector3 pos = sphvec(theta, phi); 13.51 + 13.52 + *varr++ = pos * rad; 13.53 + *narr++ = pos; 13.54 + *tarr++ = (sphvec(theta + 0.1f, (float)M_PI / 2.0f) - sphvec(theta - 0.1f, (float)M_PI / 2.0f)).normalized(); 13.55 + *uvarr++ = Vector2(u * urange, v * vrange); 13.56 + 13.57 + if(i < usub && j < vsub) { 13.58 + int idx = i * vverts + j; 13.59 + *idxarr++ = idx; 13.60 + *idxarr++ = idx + 1; 13.61 + *idxarr++ = idx + vverts + 1; 13.62 + 13.63 + *idxarr++ = idx; 13.64 + *idxarr++ = idx + vverts + 1; 13.65 + *idxarr++ = idx + vverts; 13.66 + } 13.67 + 13.68 + v += dv; 13.69 + } 13.70 + u += du; 13.71 + } 13.72 +} 13.73 + 13.74 + 13.75 +// -------- cylinder -------- 13.76 + 13.77 +static Vector3 cylvec(float theta, float height) 13.78 +{ 13.79 + return Vector3(sin(theta), height, cos(theta)); 13.80 +} 13.81 + 13.82 +void gen_cylinder(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub, float urange, float vrange) 13.83 +{ 13.84 + if(usub < 4) usub = 4; 13.85 + if(vsub < 1) vsub = 1; 13.86 + 13.87 + int uverts = usub + 1; 13.88 + int vverts = vsub + 1; 13.89 + 13.90 + int num_body_verts = uverts * vverts; 13.91 + int num_body_quads = usub * vsub; 13.92 + int num_body_tri = num_body_quads * 2; 13.93 + 13.94 + int capvverts = capsub ? capsub + 1 : 0; 13.95 + int num_cap_verts = uverts * capvverts; 13.96 + int num_cap_quads = usub * capsub; 13.97 + int num_cap_tri = num_cap_quads * 2; 13.98 + 13.99 + int num_verts = num_body_verts + num_cap_verts * 2; 13.100 + int num_tri = num_body_tri + num_cap_tri * 2; 13.101 + 13.102 + mesh->clear(); 13.103 + Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 13.104 + Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 13.105 + Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 13.106 + Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); 13.107 + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); 13.108 + 13.109 + float du = urange / (float)(uverts - 1); 13.110 + float dv = vrange / (float)(vverts - 1); 13.111 + 13.112 + float u = 0.0; 13.113 + for(int i=0; i<uverts; i++) { 13.114 + float theta = SURAD(u); 13.115 + 13.116 + float v = 0.0; 13.117 + for(int j=0; j<vverts; j++) { 13.118 + float y = (v - 0.5) * height; 13.119 + Vector3 pos = cylvec(theta, y); 13.120 + 13.121 + *varr++ = Vector3(pos.x * rad, pos.y, pos.z * rad); 13.122 + *narr++ = Vector3(pos.x, 0.0, pos.z); 13.123 + *tarr++ = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized(); 13.124 + *uvarr++ = Vector2(u * urange, v * vrange); 13.125 + 13.126 + if(i < usub && j < vsub) { 13.127 + int idx = i * vverts + j; 13.128 + 13.129 + *idxarr++ = idx; 13.130 + *idxarr++ = idx + vverts + 1; 13.131 + *idxarr++ = idx + 1; 13.132 + 13.133 + *idxarr++ = idx; 13.134 + *idxarr++ = idx + vverts; 13.135 + *idxarr++ = idx + vverts + 1; 13.136 + } 13.137 + 13.138 + v += dv; 13.139 + } 13.140 + u += du; 13.141 + } 13.142 + 13.143 + 13.144 + // now the cap! 13.145 + if(!capsub) { 13.146 + return; 13.147 + } 13.148 + 13.149 + dv = 1.0 / (float)(capvverts - 1); 13.150 + 13.151 + u = 0.0; 13.152 + for(int i=0; i<uverts; i++) { 13.153 + float theta = SURAD(u); 13.154 + 13.155 + float v = 0.0; 13.156 + for(int j=0; j<capvverts; j++) { 13.157 + float r = v * rad; 13.158 + 13.159 + Vector3 pos = cylvec(theta, height / 2.0) * r; 13.160 + pos.y = height / 2.0; 13.161 + Vector3 tang = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized(); 13.162 + 13.163 + *varr++ = pos; 13.164 + *narr++ = Vector3(0, 1, 0); 13.165 + *tarr++ = tang; 13.166 + *uvarr++ = Vector2(u * urange, v); 13.167 + 13.168 + pos.y = -height / 2.0; 13.169 + *varr++ = pos; 13.170 + *narr++ = Vector3(0, -1, 0); 13.171 + *tarr++ = -tang; 13.172 + *uvarr++ = Vector2(u * urange, v); 13.173 + 13.174 + if(i < usub && j < capsub) { 13.175 + unsigned int idx = num_body_verts + (i * capvverts + j) * 2; 13.176 + 13.177 + unsigned int vidx[4] = { 13.178 + idx, 13.179 + idx + capvverts * 2, 13.180 + idx + (capvverts + 1) * 2, 13.181 + idx + 2 13.182 + }; 13.183 + 13.184 + *idxarr++ = vidx[0]; 13.185 + *idxarr++ = vidx[2]; 13.186 + *idxarr++ = vidx[1]; 13.187 + *idxarr++ = vidx[0]; 13.188 + *idxarr++ = vidx[3]; 13.189 + *idxarr++ = vidx[2]; 13.190 + 13.191 + *idxarr++ = vidx[0] + 1; 13.192 + *idxarr++ = vidx[1] + 1; 13.193 + *idxarr++ = vidx[2] + 1; 13.194 + *idxarr++ = vidx[0] + 1; 13.195 + *idxarr++ = vidx[2] + 1; 13.196 + *idxarr++ = vidx[3] + 1; 13.197 + } 13.198 + 13.199 + v += dv; 13.200 + } 13.201 + u += du; 13.202 + } 13.203 +} 13.204 + 13.205 +// -------- cone -------- 13.206 + 13.207 +static Vector3 conevec(float theta, float y, float height) 13.208 +{ 13.209 + float scale = 1.0 - y / height; 13.210 + return Vector3(sin(theta) * scale, y, cos(theta) * scale); 13.211 +} 13.212 + 13.213 +void gen_cone(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub, float urange, float vrange) 13.214 +{ 13.215 + if(usub < 4) usub = 4; 13.216 + if(vsub < 1) vsub = 1; 13.217 + 13.218 + int uverts = usub + 1; 13.219 + int vverts = vsub + 1; 13.220 + 13.221 + int num_body_verts = uverts * vverts; 13.222 + int num_body_quads = usub * vsub; 13.223 + int num_body_tri = num_body_quads * 2; 13.224 + 13.225 + int capvverts = capsub ? capsub + 1 : 0; 13.226 + int num_cap_verts = uverts * capvverts; 13.227 + int num_cap_quads = usub * capsub; 13.228 + int num_cap_tri = num_cap_quads * 2; 13.229 + 13.230 + int num_verts = num_body_verts + num_cap_verts; 13.231 + int num_tri = num_body_tri + num_cap_tri; 13.232 + 13.233 + mesh->clear(); 13.234 + Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 13.235 + Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 13.236 + Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 13.237 + Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); 13.238 + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); 13.239 + 13.240 + float du = urange / (float)(uverts - 1); 13.241 + float dv = vrange / (float)(vverts - 1); 13.242 + 13.243 + float u = 0.0; 13.244 + for(int i=0; i<uverts; i++) { 13.245 + float theta = SURAD(u); 13.246 + 13.247 + float v = 0.0; 13.248 + for(int j=0; j<vverts; j++) { 13.249 + float y = v * height; 13.250 + Vector3 pos = conevec(theta, y, height); 13.251 + 13.252 + Vector3 tang = (conevec(theta + 0.1, 0.0, height) - conevec(theta - 0.1, 0.0, height)).normalized(); 13.253 + Vector3 bitang = (conevec(theta, y + 0.1, height) - pos).normalized(); 13.254 + 13.255 + *varr++ = Vector3(pos.x * rad, pos.y, pos.z * rad); 13.256 + *narr++ = cross_product(tang, bitang); 13.257 + *tarr++ = tang; 13.258 + *uvarr++ = Vector2(u * urange, v * vrange); 13.259 + 13.260 + if(i < usub && j < vsub) { 13.261 + int idx = i * vverts + j; 13.262 + 13.263 + *idxarr++ = idx; 13.264 + *idxarr++ = idx + vverts + 1; 13.265 + *idxarr++ = idx + 1; 13.266 + 13.267 + *idxarr++ = idx; 13.268 + *idxarr++ = idx + vverts; 13.269 + *idxarr++ = idx + vverts + 1; 13.270 + } 13.271 + 13.272 + v += dv; 13.273 + } 13.274 + u += du; 13.275 + } 13.276 + 13.277 + 13.278 + // now the bottom cap! 13.279 + if(!capsub) { 13.280 + return; 13.281 + } 13.282 + 13.283 + dv = 1.0 / (float)(capvverts - 1); 13.284 + 13.285 + u = 0.0; 13.286 + for(int i=0; i<uverts; i++) { 13.287 + float theta = SURAD(u); 13.288 + 13.289 + float v = 0.0; 13.290 + for(int j=0; j<capvverts; j++) { 13.291 + float r = v * rad; 13.292 + 13.293 + Vector3 pos = conevec(theta, 0.0, height) * r; 13.294 + Vector3 tang = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized(); 13.295 + 13.296 + *varr++ = pos; 13.297 + *narr++ = Vector3(0, -1, 0); 13.298 + *tarr++ = tang; 13.299 + *uvarr++ = Vector2(u * urange, v); 13.300 + 13.301 + if(i < usub && j < capsub) { 13.302 + unsigned int idx = num_body_verts + i * capvverts + j; 13.303 + 13.304 + unsigned int vidx[4] = { 13.305 + idx, 13.306 + idx + capvverts, 13.307 + idx + (capvverts + 1), 13.308 + idx + 1 13.309 + }; 13.310 + 13.311 + *idxarr++ = vidx[0]; 13.312 + *idxarr++ = vidx[1]; 13.313 + *idxarr++ = vidx[2]; 13.314 + *idxarr++ = vidx[0]; 13.315 + *idxarr++ = vidx[2]; 13.316 + *idxarr++ = vidx[3]; 13.317 + } 13.318 + 13.319 + v += dv; 13.320 + } 13.321 + u += du; 13.322 + } 13.323 +} 13.324 + 13.325 + 13.326 +// -------- plane -------- 13.327 + 13.328 +void gen_plane(Mesh *mesh, float width, float height, int usub, int vsub) 13.329 +{ 13.330 + gen_heightmap(mesh, width, height, usub, vsub, 0); 13.331 +} 13.332 + 13.333 + 13.334 +// ----- heightmap ------ 13.335 + 13.336 +void gen_heightmap(Mesh *mesh, float width, float height, int usub, int vsub, float (*hf)(float, float, void*), void *hfdata) 13.337 +{ 13.338 + if(usub < 1) usub = 1; 13.339 + if(vsub < 1) vsub = 1; 13.340 + 13.341 + mesh->clear(); 13.342 + 13.343 + int uverts = usub + 1; 13.344 + int vverts = vsub + 1; 13.345 + int num_verts = uverts * vverts; 13.346 + 13.347 + int num_quads = usub * vsub; 13.348 + int num_tri = num_quads * 2; 13.349 + 13.350 + Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 13.351 + Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 13.352 + Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 13.353 + Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); 13.354 + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); 13.355 + 13.356 + float du = 1.0 / (float)usub; 13.357 + float dv = 1.0 / (float)vsub; 13.358 + 13.359 + float u = 0.0; 13.360 + for(int i=0; i<uverts; i++) { 13.361 + float v = 0.0; 13.362 + for(int j=0; j<vverts; j++) { 13.363 + float x = (u - 0.5) * width; 13.364 + float y = (v - 0.5) * height; 13.365 + float z = hf ? hf(u, v, hfdata) : 0.0; 13.366 + 13.367 + Vector3 normal = Vector3(0, 0, 1); 13.368 + if(hf) { 13.369 + float u1z = hf(u + du, v, hfdata); 13.370 + float v1z = hf(u, v + dv, hfdata); 13.371 + 13.372 + Vector3 tang = Vector3(du * width, 0, u1z - z); 13.373 + Vector3 bitan = Vector3(0, dv * height, v1z - z); 13.374 + normal = cross_product(tang, bitan).normalized(); 13.375 + } 13.376 + 13.377 + *varr++ = Vector3(x, y, z); 13.378 + *narr++ = normal; 13.379 + *tarr++ = Vector3(1, 0, 0); 13.380 + *uvarr++ = Vector2(u, v); 13.381 + 13.382 + if(i < usub && j < vsub) { 13.383 + int idx = i * vverts + j; 13.384 + 13.385 + *idxarr++ = idx; 13.386 + *idxarr++ = idx + vverts + 1; 13.387 + *idxarr++ = idx + 1; 13.388 + 13.389 + *idxarr++ = idx; 13.390 + *idxarr++ = idx + vverts; 13.391 + *idxarr++ = idx + vverts + 1; 13.392 + } 13.393 + 13.394 + v += dv; 13.395 + } 13.396 + u += du; 13.397 + } 13.398 +}
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/src/meshgen.h Thu Jun 18 03:12:30 2015 +0300 14.3 @@ -0,0 +1,12 @@ 14.4 +#ifndef MESHGEN_H_ 14.5 +#define MESHGEN_H_ 14.6 + 14.7 +class Mesh; 14.8 + 14.9 +void gen_sphere(Mesh *mesh, float rad, int usub, int vsub, float urange = 1.0, float vrange = 1.0); 14.10 +void gen_cylinder(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub = 0, float urange = 1.0, float vrange = 1.0); 14.11 +void gen_cone(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub = 0, float urange = 1.0, float vrange = 1.0); 14.12 +void gen_plane(Mesh *mesh, float width, float height, int usub = 1, int vsub = 1); 14.13 +void gen_heightmap(Mesh *mesh, float width, float height, int usub, int vsub, float (*hf)(float, float, void*), void *hfdata = 0); 14.14 + 14.15 +#endif // MESHGEN_H_
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/src/pc/camera.c Thu Jun 18 03:12:30 2015 +0300 15.3 @@ -0,0 +1,42 @@ 15.4 +#include "camera.h" 15.5 + 15.6 +int cam_init(void *platform_data) 15.7 +{ 15.8 + return -1; 15.9 +} 15.10 + 15.11 +void cam_shutdown(void) 15.12 +{ 15.13 +} 15.14 + 15.15 +unsigned int cam_texture(void) 15.16 +{ 15.17 +} 15.18 + 15.19 +const float *cam_texture_matrix(void) 15.20 +{ 15.21 +} 15.22 + 15.23 +int cam_start_video(void) 15.24 +{ 15.25 +} 15.26 + 15.27 +int cam_stop_video(void) 15.28 +{ 15.29 +} 15.30 + 15.31 +int cam_update(void) 15.32 +{ 15.33 +} 15.34 + 15.35 +int cam_is_capturing(void) 15.36 +{ 15.37 +} 15.38 + 15.39 +int cam_video_size(int *xsz, int *ysz) 15.40 +{ 15.41 +} 15.42 + 15.43 +int cam_take_picture(void) 15.44 +{ 15.45 +}