goat3dgfx

diff src/object.cc @ 0:1873dfd13f2d

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