diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/application.cc | 3 | ||||
-rw-r--r-- | src/core/cvar.cc | 3 | ||||
-rw-r--r-- | src/core/cvar.h | 3 | ||||
-rw-r--r-- | src/core/entity.cc | 14 | ||||
-rw-r--r-- | src/core/entity.h | 2 | ||||
-rw-r--r-- | src/core/gameconnection.cc | 24 | ||||
-rw-r--r-- | src/core/gameinterface.cc | 9 | ||||
-rw-r--r-- | src/core/parser.cc | 7 | ||||
-rw-r--r-- | src/core/physics.cc | 16 | ||||
-rw-r--r-- | src/core/physics.h | 3 | ||||
-rw-r--r-- | src/core/player.cc | 12 | ||||
-rw-r--r-- | src/core/player.h | 28 | ||||
-rw-r--r-- | src/model/Makefile.am | 2 | ||||
-rw-r--r-- | src/model/collisionmesh.cc | 76 | ||||
-rw-r--r-- | src/model/collisionmesh.h | 102 | ||||
-rw-r--r-- | src/model/mapfile.cc | 146 | ||||
-rw-r--r-- | src/model/mapfile.h | 2 | ||||
-rw-r--r-- | src/model/material.cc | 9 | ||||
-rw-r--r-- | src/model/material.h | 2 | ||||
-rw-r--r-- | src/model/model.cc | 9 | ||||
-rw-r--r-- | src/model/model.h | 9 | ||||
-rw-r--r-- | src/model/vertexarray.cc | 50 | ||||
-rw-r--r-- | src/model/vertexarray.h | 35 |
23 files changed, 447 insertions, 119 deletions
diff --git a/src/core/application.cc b/src/core/application.cc index 15179c9..dc08595 100644 --- a/src/core/application.cc +++ b/src/core/application.cc @@ -149,6 +149,9 @@ void Application::init(int count, char **arguments) Cvar::net_framerate = Cvar::get("net_framerate", "25"); Cvar::net_framerate->set_info("[int] network framerate in frames/sec"); + + Cvar::mem_vertex = core::Cvar::get("mem_vertex", "64" , core::Cvar::Archive); + Cvar::mem_vertex->set_info("[int] amount of video memory reserved for model geometry, in megabytes"); #ifdef _WIN32 Cvar::con_ansi = Cvar::get("con_ansi", "0", Cvar::Archive); diff --git a/src/core/cvar.cc b/src/core/cvar.cc index bbdf395..100f31f 100644 --- a/src/core/cvar.cc +++ b/src/core/cvar.cc @@ -24,7 +24,6 @@ Cvar *Cvar::sv_framerate = 0; Cvar *Cvar::sv_name = 0; Cvar *Cvar::sv_description = 0; Cvar *Cvar::sv_password = 0; -Cvar *Cvar::sv_arraysize = 0; Cvar *Cvar::sv_keepalive = 0; Cvar *Cvar::net_host = 0; @@ -33,6 +32,8 @@ Cvar *Cvar::net_maxclients = 0; Cvar *Cvar::net_timeout = 0; Cvar *Cvar::net_framerate = 0; +Cvar *Cvar::mem_vertex = 0; + Cvar::Registry Cvar::cvar_registry; Cvar::Cvar(const char* name, const unsigned int flags) : cvar_name(name), cvar_info(), cvar_str() diff --git a/src/core/cvar.h b/src/core/cvar.h index 2487adc..4c55fad 100644 --- a/src/core/cvar.h +++ b/src/core/cvar.h @@ -155,7 +155,6 @@ public: static Cvar *sv_name; // server name static Cvar *sv_description; // server description static Cvar *sv_password; // server rcon password - static Cvar *sv_arraysize; // vertex array size in MegaBytes static Cvar *sv_keepalive; // entity keepalive timeout static Cvar *con_ansi; // console ANSI colors @@ -167,6 +166,8 @@ public: static Cvar *net_timeout; // network timeout in seconds static Cvar *net_framerate; // client network send framerate + static Cvar *mem_vertex; // amount of video memory reserved for model geometry, in megabytes + private: std::string cvar_name; std::string cvar_info; diff --git a/src/core/entity.cc b/src/core/entity.cc index 4c7b0da..9275477 100644 --- a/src/core/entity.cc +++ b/src/core/entity.cc @@ -508,7 +508,19 @@ void Entity::reset() // create collision shape if (model() && model()->radius()) { const float modelscale = radius() / model()->radius(); - entity_collision_shape = new btBoxShape(to_btVector3(model()->box().max() * modelscale)); + + if (flag_is_set(Complex) && model()->collisionmesh()) { + // use collision mesh + btBvhTriangleMeshShape *mesh = new btBvhTriangleMeshShape(model()->collisionmesh()->triangles(), true, true); + entity_collision_shape = mesh; + + btVector3 modelscalevec(modelscale, modelscale, modelscale); + mesh->setLocalScaling(modelscalevec); + + } else { + // use bounding box + entity_collision_shape = new btBoxShape(to_btVector3(model()->box().max() * modelscale)); + } } else { entity_collision_shape = new btSphereShape(radius()); } diff --git a/src/core/entity.h b/src/core/entity.h index 2d79132..378a71a 100644 --- a/src/core/entity.h +++ b/src/core/entity.h @@ -44,7 +44,7 @@ public: /** * @brief entity flags */ - enum Flags {NonSolid = 2, Bright = 4, Dockable = 8, ShowOnMap = 16, KeepAlive = 32}; + enum Flags {NonSolid = 2, Bright = 4, Dockable = 8, ShowOnMap = 16, KeepAlive = 32, Complex = 64}; /// Entity type constants enum Type {Default = 0, Dynamic = 1, Controlable = 2, Globe = 3}; diff --git a/src/core/gameconnection.cc b/src/core/gameconnection.cc index ba18bd5..982ac7d 100644 --- a/src/core/gameconnection.cc +++ b/src/core/gameconnection.cc @@ -8,6 +8,7 @@ #include <sstream> #include "sys/sys.h" +#include "filesystem/filesystem.h" #include "core/cvar.h" #include "core/gameconnection.h" #include "core/net.h" @@ -62,7 +63,28 @@ GameConnection::GameConnection(std::string const &connectionstr) game_players.push_back(localplayer()); set_playerlist_timestamp(timestamp()); - + + // generate player GUID + // we do it here because offline play doesn't require it + if (!localplayer()->guid().size()) { + + // read keys.ini + + // write keys.ini + std::string filename(filesystem::homedir()); + filename.append("keys.ini"); + + std::ofstream ofs(filename.c_str()); + if (!ofs.is_open()) { + con_warn << "Could not write " << filename << std::endl; + } else { + ofs << "; keys.ini - osirion client identification" << std::endl; + ofs << "; DO NOT EDIT OR DELETE THIS FILE" << std::endl; + ofs << "; If you do you will not be able to use existing characters on a remote server" << std::endl; + ofs.close(); + } + } + connection_running = true; } diff --git a/src/core/gameinterface.cc b/src/core/gameinterface.cc index 23018d3..0a485bc 100644 --- a/src/core/gameinterface.cc +++ b/src/core/gameinterface.cc @@ -70,18 +70,13 @@ GameInterface::GameInterface() Func *func = Func::add("list_players", func_list_players); func->set_info("get the local list of connected players"); - // size of the vertex array in megabytes - Cvar::sv_arraysize = core::Cvar::get("sv_arraysize", 128.0f , core::Cvar::Archive); - Cvar::sv_arraysize->set_info("[int] size of the vertex array in megabyte"); - - size_t mb = (size_t) Cvar::sv_arraysize->value(); + size_t mb = (size_t) Cvar::mem_vertex->value(); if (mb < 4 * sizeof(float)) mb = 4 * sizeof(float); if (mb > 512) mb = 512; - (*Cvar::sv_arraysize) = (float) mb; + (*Cvar::mem_vertex) = (float) mb; game_vertexarray = new model::VertexArray(mb); - } GameInterface::~GameInterface() diff --git a/src/core/parser.cc b/src/core/parser.cc index aa159bc..b210cdd 100644 --- a/src/core/parser.cc +++ b/src/core/parser.cc @@ -72,6 +72,13 @@ bool Parser::got_entity_key(filesystem::IniFile &inifile, core::Entity *entity) entity->unset_flag(Entity::ShowOnMap); return true; + } else if (inifile.got_key_bool("complex", blnval)) { + if (blnval) + entity->set_flag(Entity::Complex); + else + entity->unset_flag(Entity::Complex); + return true; + } else if (inifile.got_key_bool("nonsolid", blnval)) { if (blnval) entity->set_flag(Entity::NonSolid); diff --git a/src/core/physics.cc b/src/core/physics.cc index 4dadf07..6969b06 100644 --- a/src/core/physics.cc +++ b/src/core/physics.cc @@ -4,19 +4,22 @@ the terms and conditions of the GNU General Public License version 2 */ +#include "model/collisionmesh.h" #include "core/physics.h" #include "core/zone.h" namespace core { -btDefaultCollisionConfiguration *Physics::physics_configuration; -btCollisionDispatcher *Physics::physics_dispatcher; -btSequentialImpulseConstraintSolver *Physics::physics_solver; -unsigned long Physics::physics_timestamp; +btDefaultCollisionConfiguration *Physics::physics_configuration = 0; +btCollisionDispatcher *Physics::physics_dispatcher = 0; +btSequentialImpulseConstraintSolver *Physics::physics_solver = 0; +unsigned long Physics::physics_timestamp = 0; void Physics::init() { con_print << "^BInitializing physics engine..." << std::endl; + + model::CollisionMesh::init(); physics_configuration = new btDefaultCollisionConfiguration(); physics_dispatcher = new btCollisionDispatcher(physics_configuration); @@ -27,7 +30,10 @@ void Physics::init() void Physics::done() { - con_print << "^Bshutting down physics engine..." << std::endl; + con_print << "^BShutting down physics engine..." << std::endl; + + model::CollisionMesh::shutdown(); + delete physics_solver; delete physics_dispatcher; delete physics_configuration; diff --git a/src/core/physics.h b/src/core/physics.h index ecceb67..3237c3a 100644 --- a/src/core/physics.h +++ b/src/core/physics.h @@ -10,6 +10,8 @@ #include "sys/sys.h" #include "math/vector3f.h" #include "math/axis.h" +#include "core/cvar.h" +#include "model/collisionmesh.h" #include "btBulletDynamicsCommon.h" #include "BulletCollision/CollisionShapes/btTriangleMesh.h" @@ -46,6 +48,7 @@ private: static btSequentialImpulseConstraintSolver *physics_solver; static unsigned long physics_timestamp; + }; } // namespace core diff --git a/src/core/player.cc b/src/core/player.cc index e048b91..f183a4c 100644 --- a/src/core/player.cc +++ b/src/core/player.cc @@ -42,6 +42,8 @@ void Player::clear() player_ping = 0; player_level = 1; player_warningtime = 0; + + player_admin_level = 0; } @@ -136,6 +138,16 @@ void Player::set_level(const int level) player_level = level; } +void Player::set_admin_level(const int admin_level) +{ + player_admin_level = admin_level; +} + +void Player::set_guid(const std::string & guid) +{ + player_guid.assign(guid); +} + void Player::update_info() { Cvar *cl_name = Cvar::find("cl_name"); diff --git a/src/core/player.h b/src/core/player.h index 20a3b2d..dbcc161 100644 --- a/src/core/player.h +++ b/src/core/player.h @@ -117,6 +117,16 @@ public: const int level() const { return player_level; } + + /// player admin level + const int admin_level() const { + return player_admin_level; + } + + /// player global unique id + const std::string & guid() const { + return player_guid; + } /*----- messages -------------------------------------------------- */ @@ -140,7 +150,6 @@ public: return player_warningtime; } - /*----- mutators -------------------------------------------------- */ /// serialize player info to a stream @@ -208,7 +217,12 @@ public: /// set the player level void set_level(const int level); - + + /// set the admin level + void set_admin_level(const int admin_level); + + void set_guid(const std::string & guid); + /// set the dirty bit inline void set_dirty(const bool dirty = true) { player_dirty = dirty; @@ -252,10 +266,16 @@ private: Zone *player_zone; long player_credits; + // in-game level + int player_level; + long player_ping; std::string player_rconpassword; - int player_level; - + int player_admin_level; + + // global unique id + std::string player_guid; + // dirty bit bool player_dirty; // bit to indicate zone has changed diff --git a/src/model/Makefile.am b/src/model/Makefile.am index 3d9d7c0..cba5c48 100644 --- a/src/model/Makefile.am +++ b/src/model/Makefile.am @@ -5,6 +5,7 @@ INCLUDES = -I$(top_srcdir)/src noinst_LTLIBRARIES = libmodel.la noinst_HEADERS = \ asefile.h \ + collisionmesh.h \ face.h \ fragment.h \ mapfile.h \ @@ -18,6 +19,7 @@ noinst_HEADERS = \ libmodel_la_SOURCES = \ asefile.cc \ + collisionmesh.cc \ face.cc \ fragment.cc \ mapfile.cc \ diff --git a/src/model/collisionmesh.cc b/src/model/collisionmesh.cc new file mode 100644 index 0000000..616ee0d --- /dev/null +++ b/src/model/collisionmesh.cc @@ -0,0 +1,76 @@ +/* + model/collisionmesh.cc + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#include "sys/sys.h" +#include "model/collisionmesh.h" + +namespace model { + +CollisionMesh::Registry CollisionMesh::collisionmesh_registry; +bool CollisionMesh::collisionmesh_initialized = false; + +void CollisionMesh::init() +{ + clear(); + collisionmesh_initialized = true; +} + +void CollisionMesh::shutdown() +{ + clear(); + collisionmesh_initialized = false; +} + +void CollisionMesh::add(CollisionMesh *collisionmesh) +{ + collisionmesh_registry[collisionmesh->name()] = collisionmesh; +} + +void CollisionMesh::clear() +{ + con_debug << " clearing collision meshes" << std::endl; + + for (Registry::iterator i = collisionmesh_registry.begin(); i != collisionmesh_registry.end(); ++i) { + delete(*i).second; + } + + collisionmesh_registry.clear(); +} + +CollisionMesh *CollisionMesh::find(const std::string &name) +{ + for (Registry::iterator i = collisionmesh_registry.begin(); i != collisionmesh_registry.end(); ++i) { + if ((*i).first.compare(name) == 0) + return (*i).second; + } + + return 0; +} + +CollisionMesh::CollisionMesh(const std::string &name) : + collisionmesh_name(name) +{ + collisionmesh_size = 0; + // btTriangleMesh (bool use32bitIndices=true, bool use4componentVertices=true) + collisionmesh_triangles = new btTriangleMesh(true, false); +} + +CollisionMesh::~CollisionMesh() +{ + delete collisionmesh_triangles; +} + +void CollisionMesh::add_triangle(const math::Vector3f & v0, const math::Vector3f & v1, const math::Vector3f & v2) +{ + collisionmesh_triangles->addTriangle( + to_btVector3(v0), + to_btVector3(v1), + to_btVector3(v1) + ); + collisionmesh_size += 1; +} + +} // namespace model diff --git a/src/model/collisionmesh.h b/src/model/collisionmesh.h new file mode 100644 index 0000000..9efd21a --- /dev/null +++ b/src/model/collisionmesh.h @@ -0,0 +1,102 @@ +/* + model/collisionmesh.h + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#ifndef __INCLUDED_MODEL_COLLISIONMESH_H__ +#define __INCLUDED_MODEL_COLLISIONMESH_H__ + +#include "math/mathlib.h" + +#include "BulletCollision/CollisionShapes/btTriangleMesh.h" + +#include <string> +#include <map> + +namespace model +{ + +class CollisionMesh +{ +public: + + /// type definition for the material registry + typedef std::map<std::string, CollisionMesh *> Registry; + + CollisionMesh(const std::string &name); + + ~CollisionMesh(); + + /* ---- inspectors ----------------------------------------- */ + + inline const std::string &name() const { + return collisionmesh_name; + } + + /** + * @brief the number of triangles in the collision mesh + */ + inline size_t size() const { + return collisionmesh_size; + } + + static bool initialized() { + return collisionmesh_initialized; + } + + /** + * @brief the bullet triangle mesh object + */ + inline btTriangleMesh *triangles() { + return collisionmesh_triangles; + } + + /* ---- mutators ------------------------------------------- */ + + /** + * @brief add a triangle to the collision mesh + */ + void add_triangle(const math::Vector3f & v0, const math::Vector3f & v1, const math::Vector3f & v2); + + /* ---- static ----------------------------------------------------- */ + + /** + * @brief initialize collisionmesh registry + */ + static void init(); + + /** + * @brief shutdown collisionmesh registry + */ + static void shutdown(); + + /** + * @brief clear collisionmesh registry + */ + static void clear(); + + /** + * @brief find a collisionmesh in the registry + */ + static CollisionMesh *find(const std::string &name); + + /** + * @brief add a collisionmesh to the registry + */ + static void add(CollisionMesh *collisionmesh); + +private: + + /// the materials registry + static Registry collisionmesh_registry; + static bool collisionmesh_initialized; + + std::string collisionmesh_name; + size_t collisionmesh_size; + btTriangleMesh *collisionmesh_triangles; +}; + +} // namespace model + +#endif // __INCLUDED_MODEL_COLLISIONMESH_H__ diff --git a/src/model/mapfile.cc b/src/model/mapfile.cc index 5e18a0d..bfe19c0 100644 --- a/src/model/mapfile.cc +++ b/src/model/mapfile.cc @@ -7,6 +7,7 @@ #include "auxiliary/functions.h" #include "filesystem/filesystem.h" #include "math/mathlib.h" +#include "model/collisionmesh.h" #include "model/mapfile.h" #include "model/material.h" #include "model/model.h" @@ -147,6 +148,8 @@ MapFile::MapFile() map_brushes = 0; map_faces = 0; map_faces_detail = 0; + + map_load_clip = false; in_patchdef = false; warning_q2brush = false; @@ -924,32 +927,36 @@ void MapFile::make_brushface(Face *face) Vector3f face_normal(face->normal()* -1); face_normal.normalize(); - // split polygon into quads - while (vl.size() > 3) { - std::vector<Vector3f *>::iterator v0 = vl.begin(); - std::vector<Vector3f *>::reverse_iterator vn = vl.rbegin(); - std::vector<Vector3f *>::reverse_iterator vn1 = vl.rbegin(); - ++vn1; - std::vector<Vector3f *>::reverse_iterator vn2 = vl.rbegin(); - ++vn2; - ++vn2; - - Quad *quad = new Quad(*(*vn2) * SCALE, *(*vn1) * SCALE, *(*vn) * SCALE, *(*v0) * SCALE, face_normal, face->detail()); - primitives->add_quad(quad); + // clip faces have to be triangulated and can not be split into quads + if (!(face->material()->flags() & Material::Clip)) { + + // split polygon into quads + while (vl.size() > 3) { + std::vector<Vector3f *>::iterator v0 = vl.begin(); + std::vector<Vector3f *>::reverse_iterator vn = vl.rbegin(); + std::vector<Vector3f *>::reverse_iterator vn1 = vl.rbegin(); + ++vn1; + std::vector<Vector3f *>::reverse_iterator vn2 = vl.rbegin(); + ++vn2; + ++vn2; + + Quad *quad = new Quad(*(*vn2) * SCALE, *(*vn1) * SCALE, *(*vn) * SCALE, *(*v0) * SCALE, face_normal, face->detail()); + primitives->add_quad(quad); + + if (face->material()->flags() & Material::Texture) { + quad->t0().assign(map_texture_coords(face, *(*vn2))); + quad->t1().assign(map_texture_coords(face, *(*vn1))); + quad->t2().assign(map_texture_coords(face, *(*vn))); + quad->t3().assign(map_texture_coords(face, *(*v0))); + } - if (face->material()->flags() & Material::Texture) { - quad->t0().assign(map_texture_coords(face, *(*vn2))); - quad->t1().assign(map_texture_coords(face, *(*vn1))); - quad->t2().assign(map_texture_coords(face, *(*vn))); - quad->t3().assign(map_texture_coords(face, *(*v0))); + delete(*vn); + delete(*vn1); + vl.pop_back(); + vl.pop_back(); } - - delete(*vn); - delete(*vn1); - vl.pop_back(); - vl.pop_back(); } - + // split polygon into triangles while (vl.size() > 2) { std::vector<Vector3f *>::iterator v0 = vl.begin(); @@ -965,11 +972,12 @@ void MapFile::make_brushface(Face *face) triangle->t1().assign(map_texture_coords(face, *(*vn))); triangle->t2().assign(map_texture_coords(face, *(*v0))); } + delete(*vn); vl.pop_back(); } } else { - con_warn << name() << " unresolved face at line " << line() << std::endl; + con_warn << name() << " unresolved brush face at line " << line() << std::endl; } // clean up the vertex list @@ -1170,38 +1178,47 @@ void MapFile::load_fragmentgroup(Model *model, const FragmentGroup::Type class_t // store triangles if (primitives->triangles().size()) { - Fragment *fragment = new Fragment(Fragment::Triangles, primitives->material()); - - // add structural triangles to the fragment - for (Primitives::Triangles::iterator tris_it = primitives->triangles().begin(); tris_it != primitives->triangles().end(); tris_it++) { - Triangle *triangle = (*tris_it); - if (!triangle->detail()) { - size_t count = 0; - count += fragment->add_vertex(triangle->v0() - translation, triangle->normal(), triangle->t0(), false); - count += fragment->add_vertex(triangle->v1() - translation, triangle->normal(), triangle->t1(), false); - count += fragment->add_vertex(triangle->v2() - translation, triangle->normal(), triangle->t2(), false); - if (count == 3) - model->model_tris_count++; + if (!(primitives->material()->flags() & Material::Clip)) { + Fragment *fragment = new Fragment(Fragment::Triangles, primitives->material()); + + // add structural triangles to the fragment + for (Primitives::Triangles::iterator tris_it = primitives->triangles().begin(); tris_it != primitives->triangles().end(); tris_it++) { + Triangle *triangle = (*tris_it); + if (!triangle->detail()) { + size_t count = 0; + count += fragment->add_vertex(triangle->v0() - translation, triangle->normal(), triangle->t0(), false); + count += fragment->add_vertex(triangle->v1() - translation, triangle->normal(), triangle->t1(), false); + count += fragment->add_vertex(triangle->v2() - translation, triangle->normal(), triangle->t2(), false); + if (count == 3) + model->model_tris_count++; + } } - } - // add detail triangles to the fragment - for (Primitives::Triangles::iterator tris_it = primitives->triangles().begin(); tris_it != primitives->triangles().end(); tris_it++) { - Triangle *triangle = (*tris_it); - if (triangle->detail()) { - size_t count = 0; - count += fragment->add_vertex(triangle->v0() - translation, triangle->normal(), triangle->t0(), true); - count += fragment->add_vertex(triangle->v1() - translation, triangle->normal(), triangle->t1(), true); - count += fragment->add_vertex(triangle->v2() - translation, triangle->normal(), triangle->t2(), true); - if (count == 3) { - model->model_tris_count++; - model->model_tris_detail_count++; + // add detail triangles to the fragment + for (Primitives::Triangles::iterator tris_it = primitives->triangles().begin(); tris_it != primitives->triangles().end(); tris_it++) { + Triangle *triangle = (*tris_it); + if (triangle->detail()) { + size_t count = 0; + count += fragment->add_vertex(triangle->v0() - translation, triangle->normal(), triangle->t0(), true); + count += fragment->add_vertex(triangle->v1() - translation, triangle->normal(), triangle->t1(), true); + count += fragment->add_vertex(triangle->v2() - translation, triangle->normal(), triangle->t2(), true); + if (count == 3) { + model->model_tris_count++; + model->model_tris_detail_count++; + } } } - } - // add the fragment to the group - group->add_fragment(fragment); + // add the fragment to the group + group->add_fragment(fragment); + + } else if (map_load_clip) { + // clip materials are loaded into the CollisionArray + for (Primitives::Triangles::iterator tris_it = primitives->triangles().begin(); tris_it != primitives->triangles().end(); tris_it++) { + Triangle *triangle = (*tris_it); + model->collisionmesh()->add_triangle(triangle->v0(), triangle->v1(), triangle->v2()); + } + } } // store quads @@ -1309,9 +1326,23 @@ Model * MapFile::load(std::string const &name) unsigned int u; float r, s; std::string str; + + // load clip into collision mesh + // if the model has been loaded before (e.g. on r_restart), the collision mesh won't be reloaded + // submodel clip will not be imported + model->set_collisionmesh(CollisionMesh::find(name)); + + if (CollisionMesh::initialized() && !model->collisionmesh()) { + mapfile.map_load_clip = true; + + // create a collision mesh instance for the model + model->set_collisionmesh(new CollisionMesh(name)); + + } else { + mapfile.map_load_clip = false; + } while (mapfile.getline()) { - if (mapfile.got_classname("worldspawn")) { mapfile.clear_bbox(); @@ -1861,6 +1892,17 @@ Model * MapFile::load(std::string const &name) model->model_tris_detail_count << "/" << model->model_tris_count << " detail/tris " << model->model_quad_detail_count << "/" << model->model_quad_count << " detail/quads" << std::endl; + if (mapfile.map_load_clip) { + if (!model->collisionmesh()->size()) { + // delete empty collision meshes + delete model->collisionmesh(); + model->set_collisionmesh(0); + } else { + // add the collision mesh to the registry + CollisionMesh::add(model->collisionmesh()); + con_debug << " " << mapfile.name() << " " << model->collisionmesh()->size() << " collision triangles" << std::endl; + } + } return model; } diff --git a/src/model/mapfile.h b/src/model/mapfile.h index 5e4bfd8..ed63ad2 100644 --- a/src/model/mapfile.h +++ b/src/model/mapfile.h @@ -181,6 +181,8 @@ private: bool last_read_was_key; bool last_read_was_classname; bool last_read_was_classend; + + bool map_load_clip; unsigned int map_brushes; unsigned int map_faces; diff --git a/src/model/material.cc b/src/model/material.cc index 6baf4f9..2cacf42 100644 --- a/src/model/material.cc +++ b/src/model/material.cc @@ -188,15 +188,20 @@ void Material::load_shader(const std::string &shadername) material->set_flags(Tertiary); } else if (firstword.compare("ignore") == 0) { material->set_flags(Ignore); + } else if (firstword.compare("clip") == 0) { + material->set_flags(Clip); } else if (firstword.compare("qer_editorimage") == 0) { + // keyword qer_editorimage is ignored continue; } else if (firstword.compare("qer_trans") == 0) { + // keyword qer_trans is ignored + continue; + } else if (firstword.compare("surfaceparm") == 0) { + // keyword surfaceparm is ignored continue; } else if (firstword.compare("texture") == 0) { - // texture name should not contain spaces if (linestream >> firstword) { - // remove extension if (firstword[firstword.size()-4] == '.') { firstword.erase(firstword.size() - 4); diff --git a/src/model/material.h b/src/model/material.h index 44470e5..3c0ccf1 100644 --- a/src/model/material.h +++ b/src/model/material.h @@ -24,7 +24,7 @@ public: typedef void(* LoaderFuncPtr)(Material *); /// surface flags - enum SurfaceFlags { None = 0, Primary = 1, Secondary = 2, Tertiary = 3, Bright = 4, Engine = 8, Environment = 16, Texture = 32, Ignore = 64}; + enum SurfaceFlags { None = 0, Primary = 1, Secondary = 2, Tertiary = 3, Bright = 4, Engine = 8, Environment = 16, Texture = 32, Ignore = 64, Clip = 128}; /// type definition for the material registry typedef std::map<std::string, Material *> Registry; diff --git a/src/model/model.cc b/src/model/model.cc index fb33bd0..d1805df 100644 --- a/src/model/model.cc +++ b/src/model/model.cc @@ -1,5 +1,5 @@ /* - render/model.h + render/model.cc This file is part of the Osirion project and is distributed under the terms of the GNU General Public License version 2 */ @@ -29,6 +29,8 @@ Model::Model(const std::string & name) : model_tris_count = 0; model_quad_detail_count = 0; model_quad_count = 0; + + model_collisionmesh = 0; } Model::~Model() @@ -70,6 +72,11 @@ Model::~Model() model_sounds.clear(); } +void Model::set_collisionmesh(CollisionMesh *collisionmesh) +{ model_collisionmesh = collisionmesh; + +} + void Model::set_origin(const math::Vector3f &origin) { model_origin.assign(origin); diff --git a/src/model/model.h b/src/model/model.h index d3973c9..8e3d82d 100644 --- a/src/model/model.h +++ b/src/model/model.h @@ -13,6 +13,7 @@ #include "math/mathlib.h" +#include "model/collisionmesh.h" #include "model/tags.h" #include "model/fragment.h" @@ -75,6 +76,10 @@ public: return model_groups; } + inline CollisionMesh *collisionmesh() { + return model_collisionmesh; + } + /// list of model light tags inline Lights & lights() { return model_lights; @@ -145,6 +150,9 @@ public: /// set model radius void set_radius(const float radius); + /// set model collision mesh + void set_collisionmesh(CollisionMesh *collisionmesh); + /// set model origin void set_origin(const math::Vector3f &origin); @@ -198,6 +206,7 @@ private: Groups model_groups; float model_radius; static Registry model_registry; + CollisionMesh *model_collisionmesh; }; } diff --git a/src/model/vertexarray.cc b/src/model/vertexarray.cc index d06b976..881e266 100644 --- a/src/model/vertexarray.cc +++ b/src/model/vertexarray.cc @@ -14,37 +14,39 @@ namespace model { -VertexArray *VertexArray::vertex_instance = 0 ; +VertexArray *VertexArray::vertexarray_instance = 0 ; VertexArray::VertexArray(size_t size) { - vertex_instance = this; + assert(size > 0); + + vertexarray_instance = this; - vertex_size = size * 1024 * 1024; // megabytes - vertex_size = vertex_size / sizeof(float); // sizeof float + vertexarray_size = size * 1024 * 1024; // megabytes + vertexarray_size = vertexarray_size / sizeof(float); // sizeof float - vertex_data = (float *) malloc(vertex_size * sizeof(float)); + vertexarray_data = (float *) malloc(vertexarray_size * sizeof(float)); con_print << "^BInitializing vertex array..." << std::endl; - con_print << " " << (vertex_size * sizeof(float)) / (1024 * 1024) << " Mb allocated" << std::endl; + con_print << " " << (vertexarray_size * sizeof(float)) / (1024 * 1024) << " Mb allocated" << std::endl; clear(); } VertexArray::~VertexArray() { - free(vertex_data); + free(vertexarray_data); - vertex_instance = 0 ; + vertexarray_instance = 0 ; } void VertexArray::clear() { - vertex_dirty = true; - vertex_index = 0; - vertex_overflow = false; + vertexarray_dirty = true; + vertexarray_index = 0; + vertexarray_overflow = false; - memset(vertex_data, 0, sizeof(vertex_data)); + memset(vertexarray_data, 0, sizeof(vertexarray_data)); add_sphere(); } @@ -106,10 +108,10 @@ void VertexArray::add_sphere() size_t VertexArray::add_vertex(math::Vector3f const &v, math::Vector3f const &n, float tex_x, float tex_y) { - if (vertex_index + 8 >= vertex_size) { - if (!vertex_overflow) { + if (vertexarray_index + 8 >= vertexarray_size) { + if (!vertexarray_overflow) { con_warn << "VertexArray overflow!" << std::endl; - vertex_overflow = true; + vertexarray_overflow = true; } return 0; } @@ -117,19 +119,19 @@ size_t VertexArray::add_vertex(math::Vector3f const &v, math::Vector3f const &n, // GL_T2F_N3F_V3F // texture coordinates - vertex_data[vertex_index] = tex_x; - vertex_data[vertex_index+1] = tex_y; + vertexarray_data[vertexarray_index] = tex_x; + vertexarray_data[vertexarray_index+1] = tex_y; for (int i = 0; i < 3; i ++) { // normal - vertex_data[vertex_index+2+i] = n[i]; + vertexarray_data[vertexarray_index+2+i] = n[i]; // vertex coordinates - vertex_data[vertex_index+5+i] = v[i]; + vertexarray_data[vertexarray_index+5+i] = v[i]; } - vertex_index += 8; + vertexarray_index += 8; - vertex_dirty = true; + vertexarray_dirty = true; return 1; } @@ -138,9 +140,9 @@ void VertexArray::info() { const size_t mbfl = 1024 * 1024 / sizeof(float); con_print << " vertex array " - << vertex_index / mbfl << "/" << vertex_size / mbfl << "Mib " - << vertex_index / 8 << "/" << vertex_size / 8 << " verts " - << "^B" << vertex_index * 100 / vertex_size << "%^N used" << std::endl; + << vertexarray_index / mbfl << "/" << vertexarray_size / mbfl << "Mib " + << vertexarray_index / 8 << "/" << vertexarray_size / 8 << " verts " + << "^B" << vertexarray_index * 100 / vertexarray_size << "%^N used" << std::endl; } } diff --git a/src/model/vertexarray.h b/src/model/vertexarray.h index 9a71811..1474c67 100644 --- a/src/model/vertexarray.h +++ b/src/model/vertexarray.h @@ -15,7 +15,7 @@ namespace model // number of segments in a sphere circle, must be uneven const int SPHERESEGMENTS = 65; -/// global vertex array +/// global geometry vertex array /** a VertexArray acts like a stack of model vertices, it has no knowledge of what it is holding */ class VertexArray @@ -35,51 +35,50 @@ public: /// true when the array is full inline bool overflow() const { - return vertex_overflow; + return vertexarray_overflow; } /// return true if the vertex data has changed and needs to uploaded to video memory inline bool dirty() const { - return vertex_dirty; + return vertexarray_dirty; } /// pointer to model vertices, sequential in GL_T2F_N3F_V3F format inline const float *ptr() const { - return vertex_data; + return vertexarray_data; } /// size of the vertex array in number of floats (for a single array) inline size_t size() const { - return vertex_size; + return vertexarray_size; } /// number of allocated floats inline size_t index() const { - return vertex_index; + return vertexarray_index; } inline void set_dirty(const bool dirty = true) { - vertex_dirty = dirty; + vertexarray_dirty = dirty; } static inline VertexArray *instance() { - return vertex_instance; + return vertexarray_instance; } private: - /// model vertices, sequential in GL_T2F_N3F_V3F format - float *vertex_data; - - size_t vertex_index; - size_t vertex_size; - void add_sphere(); + + size_t vertexarray_index; + size_t vertexarray_size; + + /// model vertices, sequential in GL_T2F_N3F_V3F format + float *vertexarray_data; - static VertexArray *vertex_instance; - - bool vertex_overflow; + bool vertexarray_overflow; + bool vertexarray_dirty; - bool vertex_dirty; + static VertexArray *vertexarray_instance; }; } |