Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorStijn Buys <ingar@osirion.org>2011-01-21 14:41:35 +0000
committerStijn Buys <ingar@osirion.org>2011-01-21 14:41:35 +0000
commit035653e94a3d74b8f18c993034199d7cd08a895a (patch)
tree6acc56c14a86b499657b6e7faaf50f9e6f7ff57d /src
parent4af61dca099d2b7010d4fa83833ceeeef01b0b0f (diff)
Support structures for complex entity collision,
renamed sv_arrysize cvar to mem_vertex.
Diffstat (limited to 'src')
-rw-r--r--src/core/application.cc3
-rw-r--r--src/core/cvar.cc3
-rw-r--r--src/core/cvar.h3
-rw-r--r--src/core/entity.cc14
-rw-r--r--src/core/entity.h2
-rw-r--r--src/core/gameconnection.cc24
-rw-r--r--src/core/gameinterface.cc9
-rw-r--r--src/core/parser.cc7
-rw-r--r--src/core/physics.cc16
-rw-r--r--src/core/physics.h3
-rw-r--r--src/core/player.cc12
-rw-r--r--src/core/player.h28
-rw-r--r--src/model/Makefile.am2
-rw-r--r--src/model/collisionmesh.cc76
-rw-r--r--src/model/collisionmesh.h102
-rw-r--r--src/model/mapfile.cc146
-rw-r--r--src/model/mapfile.h2
-rw-r--r--src/model/material.cc9
-rw-r--r--src/model/material.h2
-rw-r--r--src/model/model.cc9
-rw-r--r--src/model/model.h9
-rw-r--r--src/model/vertexarray.cc50
-rw-r--r--src/model/vertexarray.h35
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;
};
}