From 2ccff9db76166b5b2cc308e77e74972d85ad3a9f Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Mon, 2 Nov 2009 18:59:40 +0000 Subject: [PATCH] changed plane construction to accept 4 parameters to specify (a,b,c,d) directly (in addition to 6 parameter mode) git-svn-id: svn://anubis/anaglym/trunk@147 99a6e188-d820-4881-8870-2d33a10e2619 --- .todo | 1 - Engine.cc | 103 ++++++++++++++++++++++++++++++++++-------------------- ag.cc | 32 ++++++++++------- 3 files changed, 85 insertions(+), 51 deletions(-) diff --git a/.todo b/.todo index 66fc68c..e8f7001 100644 --- a/.todo +++ b/.todo @@ -1,3 +1,2 @@ -- add plane constructor taking 4 parameters for (a,b,c,d) - support loading and applying textures for managed objects - debug hooks for loading and execution to halt infinite lua loops diff --git a/Engine.cc b/Engine.cc index 02c35b7..bc01b98 100644 --- a/Engine.cc +++ b/Engine.cc @@ -31,6 +31,8 @@ using namespace std; #define WHITESPACE " \t\r\n\f" +#define FP_EQ(a,b) (fabsf(a - b) < 0.0001) + /* Global data */ Engine * g_engine; @@ -54,6 +56,13 @@ static string trim(const string & orig) return result; } +static void cross_product(dVector3 result, dVector3 first, dVector3 second) +{ + result[0] = first[1] * second[2] - first[2] * second[1]; + result[1] = first[2] * second[0] - first[0] * second[2]; + result[2] = first[0] * second[1] - first[1] * second[0]; +} + /******** Engine functions ********/ Engine::Engine(const string & path, Video & video) @@ -725,7 +734,7 @@ void Engine::Object::createManagedObject() m_ode_object->addSphere(m_args); break; case OdeWorld::PLANE: - while (m_args->size() < 6) + while (m_args->size() < 4 || m_args->size() == 5) m_args->push_back(0); m_ode_object->addPlane(m_args); break; @@ -745,29 +754,9 @@ void Engine::Object::createManagedObject() } /* render a managed object */ +/* prerequisite: m_args->size() is big enough */ void Engine::Object::render() { - bool valid = false; - switch (m_geom_type) - { - case OdeWorld::BOX: - if (m_args->size() >= 3) valid = true; - break; - case OdeWorld::SPHERE: - if (m_args->size() >= 1) valid = true; - break; - case OdeWorld::PLANE: - if (m_args->size() >= 6) valid = true; - break; - case OdeWorld::CYLINDER: - if (m_args->size() >= 2) valid = true; - break; - case OdeWorld::CCYLINDER: - if (m_args->size() >= 2) valid = true; - break; - } - if (!valid) - return; if (m_display_list <= 0) m_display_list = glGenLists(1); glNewList(m_display_list, GL_COMPILE); @@ -813,30 +802,70 @@ void Engine::Object::render() gluSphere(quad, (*m_args)[0], 16, 8); break; case OdeWorld::PLANE: { - dMatrix3 r; - dRFromEulerAngles(r, (*m_args)[3], (*m_args)[4], (*m_args)[5]); - dVector3 default_plane_direction = {0, 0, 1, 0}; - dVector3 default_x = {1, 0, 0, 0}; - dVector3 default_y = {0, 1, 0, 0}; - dVector3 rotated_plane_direction; + dVector3 normal; dVector3 rotated_x; dVector3 rotated_y; - dMultiply0(rotated_plane_direction, default_plane_direction, - r, 1, 3, 3); - dMultiply0(rotated_x, default_x, r, 1, 3, 3); - dMultiply0(rotated_y, default_y, r, 1, 3, 3); + float x_o, y_o, z_o; + if (m_args->size() == 6) + { + dMatrix3 r; + dRFromEulerAngles(r, (*m_args)[3], (*m_args)[4], (*m_args)[5]); + dVector3 default_plane_direction = {0, 0, 1, 0}; + dVector3 default_x = {1, 0, 0, 0}; + dVector3 default_y = {0, 1, 0, 0}; + dMultiply0(normal, default_plane_direction, + r, 1, 3, 3); + dMultiply0(rotated_x, default_x, r, 1, 3, 3); + dMultiply0(rotated_y, default_y, r, 1, 3, 3); + x_o = (*m_args)[0]; + y_o = (*m_args)[1]; + z_o = (*m_args)[2]; + } + else + { + normal[0] = (*m_args)[0]; + normal[1] = (*m_args)[1]; + normal[2] = (*m_args)[2]; + float d = (*m_args)[3]; + float len = normal[0] * normal[0] + + normal[1] * normal[1] + + normal[2] * normal[2]; + if (! FP_EQ(len, 1.0)) /* normalize if necessary */ + { + len = sqrtf(len); + normal[0] /= len; + normal[1] /= len; + normal[2] /= len; + d /= len; + } + int min_component = 0; + float comp = 10000.0f; + for (int i = 0; i < 3; i++) + { + if (normal[i] < comp) + { + min_component = i; + comp = normal[i]; + } + } + dVector3 cross_vec; + for (int i = 0; i < 3; i++) + cross_vec[i] = (i == min_component) ? 1 : 0; + cross_product(rotated_x, normal, cross_vec); + cross_product(rotated_y, normal, rotated_x); + x_o = normal[0] * d; + y_o = normal[1] * d; + z_o = normal[2] * d; + } /* plane equation: ax + by + cz = d, plane normal: (a, b, c) */ const int num_sections = 10; const float section_size = 100.0f; - float x_o = (*m_args)[0]; - float y_o = (*m_args)[1]; - float z_o = (*m_args)[2]; #ifdef dSINGLE - glNormal3fv(rotated_plane_direction); + glNormal3fv(normal); #else - glNormal3dv(rotated_plane_direction); + glNormal3dv(normal); #endif for (int x = 0; x < num_sections; x++) { diff --git a/ag.cc b/ag.cc index 11ed01b..7965755 100644 --- a/ag.cc +++ b/ag.cc @@ -378,21 +378,27 @@ namespace ag static int createPlaneSpecify(lua_State * L, bool is_static) { int argc = lua_gettop(L); - if (argc == 6 && - lua_isnumber(L, 1) && - lua_isnumber(L, 2) && - lua_isnumber(L, 3) && - lua_isnumber(L, 4) && - lua_isnumber(L, 5) && - lua_isnumber(L, 6)) + if (argc == 4 || argc == 6) { - refptr< vector > args = new vector(); - for (int i = 1; i <= 6; i++) - args->push_back(lua_tonumber(L, i)); - addManagedObject(L, is_static, OdeWorld::PLANE, args); + bool valid = true; + for (int i = 0; i < argc; i++) + { + if (!lua_isnumber(L, i)) + { + valid = false; + break; + } + } + if (valid) + { + refptr< vector > args = new vector(); + for (int i = 1; i <= 6; i++) + args->push_back(lua_tonumber(L, i)); + addManagedObject(L, is_static, OdeWorld::PLANE, args); + return 1; + } } - else - lua_pushnil(L); + lua_pushnil(L); return 1; }