vrshoot

diff src/object.cc @ 0:b2f14e535253

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 01 Feb 2014 19:58:19 +0200
parents
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/object.cc	Sat Feb 01 19:58:19 2014 +0200
     1.3 @@ -0,0 +1,332 @@
     1.4 +#include <float.h>
     1.5 +#include "object.h"
     1.6 +#include "opengl.h"
     1.7 +#include "shader.h"
     1.8 +#include "unistate.h"
     1.9 +#include "logger.h"
    1.10 +
    1.11 +static void destroy_all_rec(XFormNode *node);
    1.12 +static void get_all_meshes_rec(XFormNode *node, std::list<Mesh*> *reslist);
    1.13 +
    1.14 +DrawMode Object::draw_mode = DRAW_DEFAULT;
    1.15 +
    1.16 +Object::Object()
    1.17 +{
    1.18 +	type = NODE_OBJECT;
    1.19 +	mesh = 0;
    1.20 +}
    1.21 +
    1.22 +void Object::destroy_all()
    1.23 +{
    1.24 +	destroy_all_rec(this);
    1.25 +}
    1.26 +
    1.27 +static void destroy_all_rec(XFormNode *node)
    1.28 +{
    1.29 +	if(!node) {
    1.30 +		return;
    1.31 +	}
    1.32 +
    1.33 +	for(int i=0; i<node->get_children_count(); i++) {
    1.34 +		destroy_all_rec(node->get_child(i));
    1.35 +	}
    1.36 +	delete node;
    1.37 +}
    1.38 +
    1.39 +void Object::set_mesh(Mesh *m)
    1.40 +{
    1.41 +	mesh = m;
    1.42 +}
    1.43 +
    1.44 +Mesh *Object::get_mesh()
    1.45 +{
    1.46 +	return mesh;
    1.47 +}
    1.48 +
    1.49 +const Mesh *Object::get_mesh() const
    1.50 +{
    1.51 +	return mesh;
    1.52 +}
    1.53 +
    1.54 +std::list<Mesh*> Object::get_all_meshes()
    1.55 +{
    1.56 +	std::list<Mesh*> meshes;
    1.57 +	get_all_meshes_rec(this, &meshes);
    1.58 +	return meshes;
    1.59 +}
    1.60 +
    1.61 +std::list<const Mesh*> Object::get_all_meshes() const
    1.62 +{
    1.63 +	std::list<const Mesh*> meshes;
    1.64 +	get_all_meshes_rec((Object*)this, (std::list<Mesh*>*)&meshes);
    1.65 +	return meshes;
    1.66 +}
    1.67 +
    1.68 +static void get_all_meshes_rec(XFormNode *node, std::list<Mesh*> *reslist)
    1.69 +{
    1.70 +	if(!node) {
    1.71 +		return;
    1.72 +	}
    1.73 +
    1.74 +	if(node->get_type() == NODE_OBJECT) {
    1.75 +		Object *obj = (Object*)node;
    1.76 +		if(obj) {
    1.77 +			Mesh *mesh = obj->get_mesh();
    1.78 +			if(mesh) {
    1.79 +				reslist->push_back(mesh);
    1.80 +			}
    1.81 +		}
    1.82 +	}
    1.83 +
    1.84 +	for(int i=0; i<node->get_children_count(); i++) {
    1.85 +		get_all_meshes_rec(node->get_child(i), reslist);
    1.86 +	}
    1.87 +}
    1.88 +
    1.89 +long Object::count_polys() const
    1.90 +{
    1.91 +	long poly_count = mesh ? mesh->get_poly_count() : 0;
    1.92 +
    1.93 +	int nchildren = get_children_count();
    1.94 +	for(int i=0; i<nchildren; i++) {
    1.95 +		const XFormNode *child = get_child(i);
    1.96 +		if(child->get_type() == NODE_OBJECT) {
    1.97 +			poly_count += ((const Object*)child)->count_polys();
    1.98 +		}
    1.99 +	}
   1.100 +	return poly_count;
   1.101 +}
   1.102 +
   1.103 +AABox Object::get_aabbox() const
   1.104 +{
   1.105 +	AABox box;
   1.106 +
   1.107 +	if(mesh) {
   1.108 +		box = mesh->get_aabbox();
   1.109 +	} else {
   1.110 +		box.min = Vector3(FLT_MAX, FLT_MAX, FLT_MAX);
   1.111 +		box.max = -box.min;
   1.112 +	}
   1.113 +
   1.114 +	int num_children = get_children_count();
   1.115 +	for(int i=0; i<num_children; i++) {
   1.116 +		const Object *obj = dynamic_cast<const Object*>(get_child(i));
   1.117 +		if(obj) {
   1.118 +			AABox child_box = obj->get_aabbox();
   1.119 +			box.set_union(&box, &child_box);
   1.120 +		}
   1.121 +	}
   1.122 +	return box;
   1.123 +}
   1.124 +
   1.125 +Sphere Object::get_bsphere() const
   1.126 +{
   1.127 +	Sphere sph;
   1.128 +	bool valid = false;
   1.129 +
   1.130 +	if(mesh) {
   1.131 +		sph = mesh->get_bsphere();
   1.132 +		valid = true;
   1.133 +	} else {
   1.134 +		sph.radius = 0.0;
   1.135 +	}
   1.136 +
   1.137 +	int num_children = get_children_count();
   1.138 +	for(int i=0; i<num_children; i++) {
   1.139 +		// TODO: this is wrong
   1.140 +		const Object *obj = dynamic_cast<const Object*>(get_child(i));
   1.141 +		if(obj) {
   1.142 +			Sphere child_sph = obj->get_bsphere();
   1.143 +			if(valid) {
   1.144 +				sph.set_union(&sph, &child_sph);
   1.145 +			} else {
   1.146 +				sph = child_sph;
   1.147 +				valid = true;
   1.148 +			}
   1.149 +		}
   1.150 +	}
   1.151 +
   1.152 +	return sph;
   1.153 +}
   1.154 +
   1.155 +void Object::apply_xform(long msec)
   1.156 +{
   1.157 +	std::list<XFormNode*> nodelist = get_all_nodes(NODE_OBJECT);
   1.158 +
   1.159 +	std::list<XFormNode*>::iterator it = nodelist.begin();
   1.160 +	while(it != nodelist.end()) {
   1.161 +		Object *obj = (Object*)*it++;
   1.162 +
   1.163 +		Mesh *mesh = obj->get_mesh();
   1.164 +		if(mesh) {
   1.165 +			Matrix4x4 xform;
   1.166 +			obj->get_xform(msec, &xform);
   1.167 +			mesh->apply_xform(xform);
   1.168 +		}
   1.169 +	}
   1.170 +
   1.171 +	// go through the list a second time and clear the transformations
   1.172 +	it = nodelist.begin();
   1.173 +	while(it != nodelist.end()) {
   1.174 +		Object *obj = (Object*)*it++;
   1.175 +
   1.176 +		obj->clear_xform();
   1.177 +	}
   1.178 +}
   1.179 +
   1.180 +/*static const char *attr_name[] = {
   1.181 +	"attr_vertex",
   1.182 +	"attr_normal",
   1.183 +	"attr_tangent",
   1.184 +	"attr_texcoord",
   1.185 +	"attr_boneweights",
   1.186 +	"attr_boneidx"
   1.187 +};*/
   1.188 +
   1.189 +void Object::draw(long msec) const
   1.190 +{
   1.191 +	Matrix4x4 xform;
   1.192 +	get_xform(msec, &xform);
   1.193 +
   1.194 +	set_world_matrix(xform);
   1.195 +
   1.196 +	if(mesh) {
   1.197 +		/*unsigned int prog = sdrprog;
   1.198 +
   1.199 +		if(mesh->get_bones_count() > 0) {
   1.200 +			prog = sdrprog_skin;
   1.201 +		}
   1.202 +
   1.203 +		glUseProgram(prog);
   1.204 +		// get all the attribute locations
   1.205 +		for(int i=0; i<NUM_MESH_ATTR; i++) {
   1.206 +			int loc = glGetAttribLocation(prog, attr_name[i]);
   1.207 +			if(loc != -1) {
   1.208 +				Mesh::set_attrib_location(i, loc);
   1.209 +			}
   1.210 +		}
   1.211 +
   1.212 +		setup_bones(msec);
   1.213 +
   1.214 +		glUseProgram(prog);*/
   1.215 +
   1.216 +#ifndef GL_ES_VERSION_2_0
   1.217 +		if(!get_current_shader()) {
   1.218 +			setup_gl_matrices();
   1.219 +		}
   1.220 +#endif
   1.221 +
   1.222 +		material.setup();
   1.223 +		setup_unistate();	// set all state uniforms
   1.224 +
   1.225 +		switch(Object::draw_mode) {
   1.226 +		case DRAW_WIREFRAME:
   1.227 +			mesh->draw_wire();
   1.228 +			break;
   1.229 +
   1.230 +		case DRAW_VERTICES:
   1.231 +			mesh->draw_vertices();
   1.232 +			break;
   1.233 +
   1.234 +		case DRAW_DEFAULT:
   1.235 +		default:
   1.236 +			mesh->draw();
   1.237 +		}
   1.238 +	}
   1.239 +
   1.240 +	int num_children = get_children_count();
   1.241 +	for(int i=0; i<num_children; i++) {
   1.242 +		const XFormNode *c = get_child(i);
   1.243 +		c->draw(msec);
   1.244 +	}
   1.245 +}
   1.246 +
   1.247 +
   1.248 +bool Object::intersect(const Ray &inray, HitPoint *hit) const
   1.249 +{
   1.250 +	Ray ray = inray;
   1.251 +	Matrix4x4 xform, inv_xform;
   1.252 +	get_xform(ray.time, &xform/*, &inv_xform*/);
   1.253 +	ray.transform(xform.inverse());	// TODO find out what's wrong with get_xform's inv_xform and use that
   1.254 +
   1.255 +	HitPoint nearest_hit;
   1.256 +	nearest_hit.dist = FLT_MAX;
   1.257 +	nearest_hit.obj = 0;
   1.258 +
   1.259 +	if(mesh) {
   1.260 +		if(mesh->intersect(ray, hit ? &nearest_hit : 0)) {
   1.261 +			if(!hit) {
   1.262 +				return true;
   1.263 +			}
   1.264 +
   1.265 +			if(Mesh::get_intersect_mode() & ISECT_FACE) {
   1.266 +				Triangle *face = (Triangle*)nearest_hit.obj;
   1.267 +				face->transform(xform);
   1.268 +			} else if(Mesh::get_intersect_mode() & ISECT_VERTICES) {
   1.269 +				Vector3 *v = (Vector3*)nearest_hit.obj;
   1.270 +				v->transform(xform);
   1.271 +			} else {
   1.272 +				nearest_hit.obj = this;
   1.273 +			}
   1.274 +		}
   1.275 +	}
   1.276 +
   1.277 +	int num_children = get_children_count();
   1.278 +	for(int i=0; i<num_children; i++) {
   1.279 +		const Object *obj = dynamic_cast<const Object*>(get_child(i));
   1.280 +
   1.281 +		HitPoint chit;
   1.282 +		if(obj && obj->intersect(inray, hit ? &chit : 0)) {
   1.283 +			if(!hit) {
   1.284 +				return true;
   1.285 +			}
   1.286 +
   1.287 +			if(chit.dist < nearest_hit.dist) {
   1.288 +				nearest_hit = chit;
   1.289 +			}
   1.290 +		}
   1.291 +	}
   1.292 +
   1.293 +	if(nearest_hit.obj) {
   1.294 +		if(hit) {
   1.295 +			*hit = nearest_hit;
   1.296 +		}
   1.297 +		return true;
   1.298 +	}
   1.299 +	return false;
   1.300 +}
   1.301 +
   1.302 +
   1.303 +bool Object::setup_bones(long msec) const
   1.304 +{
   1.305 +	int num_bones;
   1.306 +	if(!mesh || !(num_bones = mesh->get_bones_count())) {
   1.307 +		return false;
   1.308 +	}
   1.309 +
   1.310 +	/*char uniname[32];
   1.311 +
   1.312 +	for(int i=0; i<num_bones; i++) {
   1.313 +		const XFormNode *bone = mesh->get_bone(i);
   1.314 +
   1.315 +		Matrix4x4 xform;
   1.316 +		bone->get_xform(msec, &xform);
   1.317 +
   1.318 +		xform = xform * bone->get_bone_matrix();
   1.319 +
   1.320 +		sprintf(uniname, "bone_xform[%d]", i);
   1.321 +		int loc = glGetUniformLocation(sdrprog_skin, uniname);
   1.322 +		if(loc == -1) {
   1.323 +			return false;
   1.324 +		}
   1.325 +		glUniformMatrix4fv(loc, 1, GL_TRUE, xform[0]);
   1.326 +	}*/
   1.327 +	return true;
   1.328 +}
   1.329 +
   1.330 +DrawMode Object::set_draw_mode(DrawMode mode)
   1.331 +{
   1.332 +	DrawMode prev = Object::draw_mode;
   1.333 +	Object::draw_mode = mode;
   1.334 +	return prev;
   1.335 +}