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>2008-07-23 19:51:06 +0000
committerStijn Buys <ingar@osirion.org>2008-07-23 19:51:06 +0000
commit5c96b74c76b881b1533432a75d1a8cc42ecc5bda (patch)
treea1500e0149ba03d017dd5fdb169a6538a7a06a61 /src
parent1cf82068a2adff7c401fe0aba73466f045e460d3 (diff)
fragment renderer
Diffstat (limited to 'src')
-rw-r--r--src/math/color.cc9
-rw-r--r--src/math/color.h3
-rw-r--r--src/model/Makefile.am2
-rw-r--r--src/model/engine.cc5
-rw-r--r--src/model/engine.h40
-rw-r--r--src/model/flare.cc9
-rw-r--r--src/model/flare.h15
-rw-r--r--src/model/fragment.cc17
-rw-r--r--src/model/fragment.h44
-rw-r--r--src/model/light.cc9
-rw-r--r--src/model/light.h77
-rw-r--r--src/model/map.cc705
-rw-r--r--src/model/map.h112
-rw-r--r--src/model/model.cc103
-rw-r--r--src/model/model.h179
-rw-r--r--src/model/plane.cc16
-rw-r--r--src/model/plane.h55
-rw-r--r--src/model/primitives.cc44
-rw-r--r--src/model/primitives.h45
-rw-r--r--src/model/quad.cc17
-rw-r--r--src/model/quad.h57
-rw-r--r--src/model/triangle.cc17
-rw-r--r--src/model/triangle.h52
-rw-r--r--src/model/vertexarray.cc55
-rw-r--r--src/model/vertexarray.h67
-rw-r--r--src/render/draw.cc175
26 files changed, 1123 insertions, 806 deletions
diff --git a/src/math/color.cc b/src/math/color.cc
index 1e52ec5..0cf2ea8 100644
--- a/src/math/color.cc
+++ b/src/math/color.cc
@@ -123,6 +123,15 @@ Color const operator*(float scalar, Color const & color)
{
return color * scalar;
}
+
+Color & Color::operator*=(const float scalar)
+{
+ for (int i=0; i < 3; i++)
+ rgba_data[i] *= scalar;
+ return (*this);
+}
+
+
std::ostream &operator<<(std::ostream &os, Color const & color)
{
os << color.red() << " " << color.green() << " " << color.blue(); // << " " << c.alpha();
diff --git a/src/math/color.h b/src/math/color.h
index ea6fe1c..4f3df16 100644
--- a/src/math/color.h
+++ b/src/math/color.h
@@ -46,6 +46,9 @@ public:
/// multiply rgb values with scalar value.
Color operator*(const float scalar) const;
+ /// multiply rgb values with scalar value.
+ Color & operator*=(const float scalar);
+
inline float operator[](size_t index) const { return rgba_data[index]; }
/// pointer to the internal data
diff --git a/src/model/Makefile.am b/src/model/Makefile.am
index 4a5e4e6..a6e8a99 100644
--- a/src/model/Makefile.am
+++ b/src/model/Makefile.am
@@ -1,7 +1,7 @@
METASOURCES = AUTO
libmodel_la_SOURCES = engine.cc flare.cc fragment.cc light.cc map.cc model.cc \
- plane.cc quad.cc triangle.cc vertexarray.cc
+ plane.cc primitives.cc quad.cc triangle.cc vertexarray.cc
libmodel_la_LDFLAGS = -avoid-version -no-undefined -lm
noinst_LTLIBRARIES = libmodel.la
diff --git a/src/model/engine.cc b/src/model/engine.cc
index 7c8d117..eb4198a 100644
--- a/src/model/engine.cc
+++ b/src/model/engine.cc
@@ -7,13 +7,14 @@
#include "model/engine.h"
-namespace model {
+namespace model
+{
/* ---------- core::Engine ------------------------------------------ */
Engine::Engine() :
- engine_location()
+ engine_location()
{
engine_radius = 1.0f;
engine_flare = 0;
diff --git a/src/model/engine.h b/src/model/engine.h
index 569eb4e..c3e6064 100644
--- a/src/model/engine.h
+++ b/src/model/engine.h
@@ -10,32 +10,48 @@
#include "math/vector3f.h"
#include "math/color.h"
-namespace model {
+namespace model
+{
/// a spacecraft engine
class Engine
{
public:
Engine();
-
+
Engine(math::Vector3f const & location);
~Engine();
- inline math::Vector3f const & location() const { return engine_location; }
-
- inline math::Color const & color() const { return engine_color; }
-
- inline float radius() const { return engine_radius; }
-
- inline unsigned int flare() const { return engine_flare; }
-
- inline unsigned int texture() const { return render_texture; }
+ inline math::Vector3f const & location() const
+ {
+ return engine_location;
+ }
+
+ inline math::Color const & color() const
+ {
+ return engine_color;
+ }
+
+ inline float radius() const
+ {
+ return engine_radius;
+ }
+
+ inline unsigned int flare() const
+ {
+ return engine_flare;
+ }
+
+ inline unsigned int texture() const
+ {
+ return render_texture;
+ }
math::Vector3f engine_location;
float engine_radius;
math::Color engine_color;
unsigned int engine_flare;
-
+
unsigned int render_texture;
};
diff --git a/src/model/flare.cc b/src/model/flare.cc
index fcd36f1..0669a49 100644
--- a/src/model/flare.cc
+++ b/src/model/flare.cc
@@ -6,14 +6,15 @@
#include "model/flare.h"
-namespace model {
+namespace model
+{
-Flare::Flare() : Light() {
+Flare::Flare() : Light()
+{
flare_angle = 0;
}
Flare::~Flare()
-{
-}
+{}
}
diff --git a/src/model/flare.h b/src/model/flare.h
index 3cd192c..6f96d8c 100644
--- a/src/model/flare.h
+++ b/src/model/flare.h
@@ -9,16 +9,21 @@
#include "model/light.h"
-namespace model {
+namespace model
+{
/// a flare is a directional light
-class Flare : public Light {
+class Flare : public Light
+{
public:
Flare();
~Flare();
-
- inline float angle() const { return flare_angle; }
-
+
+ inline float angle() const
+ {
+ return flare_angle;
+ }
+
float flare_angle;
};
diff --git a/src/model/fragment.cc b/src/model/fragment.cc
index 38990d5..b655807 100644
--- a/src/model/fragment.cc
+++ b/src/model/fragment.cc
@@ -10,10 +10,14 @@
namespace model
{
+/*
+ Triangles: the number of triangles is size/3
+ Quads: the number of Quads is size/4
+*/
Fragment::Fragment(Type type, unsigned int material)
{
fragment_type = type;
- fragment_start = VertexArray::instance()->index();
+ fragment_index = VertexArray::instance()->index() / 3;
fragment_material = material;
fragment_structural_size = 0;
fragment_detail_size = 0;
@@ -22,11 +26,12 @@ Fragment::Fragment(Type type, unsigned int material)
size_t Fragment::add_vertex(math::Vector3f const & vertex, math::Vector3f const &normal, math::Color const & color, bool detail)
{
size_t n = VertexArray::instance()->add_vertex(vertex, normal, color);
-
- if (detail)
- fragment_detail_size += n;
- else
- fragment_structural_size += n;
+ if (n) {
+ if (detail)
+ fragment_detail_size += n;
+ else
+ fragment_structural_size += n;
+ }
return n;
}
diff --git a/src/model/fragment.h b/src/model/fragment.h
index ba4eaf9..0df1b79 100644
--- a/src/model/fragment.h
+++ b/src/model/fragment.h
@@ -19,28 +19,46 @@ class Fragment
public:
/// fragment primitive type: triangles or quads
enum Type {Triangles, Quads};
-
+
/// create a new fragment
- Fragment (Type type, unsigned int material);
-
+ Fragment(Type type, unsigned int material);
+
/// add a vertex to the fragment
size_t add_vertex(math::Vector3f const & vertex, math::Vector3f const &normal, math::Color const & color, bool detail);
-
+
+ /// the type of primitives this fragment consists of
+ inline Type type() const
+ {
+ return fragment_type;
+ }
+
/// VertexArray index of the start of the fragment
- inline size_t start() const { return fragment_start; }
-
+ inline size_t index() const
+ {
+ return fragment_index;
+ }
+
/// number of structural vertices in the fragment
- inline size_t structural_size() const { return fragment_structural_size; }
-
+ inline size_t structural_size() const
+ {
+ return fragment_structural_size;
+ }
+
/// number of detail vertices in the fragment
- inline size_t detail_size() const { return fragment_detail_size; }
-
+ inline size_t detail_size() const
+ {
+ return fragment_detail_size;
+ }
+
/// material flags
- inline unsigned int material() { return fragment_material; }
-
+ inline unsigned int material()
+ {
+ return fragment_material;
+ }
+
private:
Type fragment_type;
- size_t fragment_start;
+ size_t fragment_index;
size_t fragment_structural_size;
size_t fragment_detail_size;
unsigned int fragment_material;
diff --git a/src/model/light.cc b/src/model/light.cc
index 426e7fd..01ddf96 100644
--- a/src/model/light.cc
+++ b/src/model/light.cc
@@ -6,11 +6,12 @@
#include "model/light.h"
-namespace model {
+namespace model
+{
-Light::Light() :
- light_location(),
- light_color(1.0f, 1.0f, 1.0f)
+Light::Light() :
+ light_location(),
+ light_color(1.0f, 1.0f, 1.0f)
{
light_entity = false;
light_strobe = false;
diff --git a/src/model/light.h b/src/model/light.h
index b834623..00587f3 100644
--- a/src/model/light.h
+++ b/src/model/light.h
@@ -10,45 +10,76 @@
#include "math/vector3f.h"
#include "math/color.h"
-namespace model {
+namespace model
+{
/// an exterior light
class Light
{
public:
Light();
-
+
Light(math::Vector3f const & location, math::Color const & color, bool strobe=false);
-
+
~Light();
- inline math::Vector3f const & location() const { return light_location; }
-
- inline math::Color const & color() const { return light_color; };
-
+ inline math::Vector3f const & location() const
+ {
+ return light_location;
+ }
+
+ inline math::Color const & color() const
+ {
+ return light_color;
+ };
+
/// true if this is a strobe light
- inline bool strobe() const { return light_strobe; }
-
+ inline bool strobe() const
+ {
+ return light_strobe;
+ }
+
/// true if this light has entity color
- inline bool entity() const { return light_entity; }
-
+ inline bool entity() const
+ {
+ return light_entity;
+ }
+
/// size if the light, default is 1.0f
- inline float radius() const { return light_radius; }
+ inline float radius() const
+ {
+ return light_radius;
+ }
/// strobe time offset, in seconds
- inline float offset() const { return light_offset; }
-
+ inline float offset() const
+ {
+ return light_offset;
+ }
+
/// frequency in strobes per second
- inline float frequency() const { return light_frequency; }
-
+ inline float frequency() const
+ {
+ return light_frequency;
+ }
+
/// fraction a strobe light will be on, default is 0.5f
- inline float time() const { return light_time; }
-
+ inline float time() const
+ {
+ return light_time;
+ }
+
/// flare texture number
- inline unsigned int flare() const { return light_flare; }
-
+ inline unsigned int flare() const
+ {
+ return light_flare;
+ }
+
/// render texture number
- inline size_t texture() const { return render_texture; }
+ inline size_t texture() const
+ {
+ return render_texture;
+ }
math::Vector3f light_location;
math::Color light_color;
@@ -58,9 +89,9 @@ public:
float light_frequency;
float light_offset;
float light_time;
-
+
unsigned int light_flare;
-
+
size_t render_texture;
};
diff --git a/src/model/map.cc b/src/model/map.cc
index 220c723..8260f10 100644
--- a/src/model/map.cc
+++ b/src/model/map.cc
@@ -10,170 +10,55 @@
#include "model/light.h"
#include "model/map.h"
#include "model/material.h"
+#include "model/model.h"
#include "model/vertexarray.h"
#include "sys/sys.h"
#include <sstream>
#include <string>
-namespace model {
+namespace model
+{
// function to test spawnflags
-inline bool spawnflag_isset(unsigned int spawnflags, unsigned int flag) {
+inline bool spawnflag_isset(unsigned int spawnflags, unsigned int flag)
+{
return ((spawnflags & flag) == flag);
}
+// max geometry bounds
const float MAX_BOUNDS = 16384;
-const float MIN_DELTA = 10e-10;
-
-Model * Map::load(std::string const &name)
-{
- // open the .map file
- Map mapfile;
-
- if (!mapfile.open(name)) {
- return 0;
- }
-
- Model *model = new Model(name);
- Light *light = 0;
- Flare *flare = 0;
- Engine *engine = 0;
-
- unsigned int u;
-
- while (mapfile.getline()) {
-
- if (mapfile.got_classname("worldspawn")) {
-
- // new wordspawn
-
- } else if (mapfile.classname().compare("worldspawn") == 0 ) {
-
- // worldspawn attributes
- if (mapfile.got_key_int("enginesound", u)) {
- model->model_enginesound = u;
- continue;
- }
-
- } else if (mapfile.got_classname("light")) {
-
- // new light
- light = new Light();
- model->add_light(light);
-
- } else if (mapfile.classname().compare("light") == 0 ) {
-
- // light attributes
- if (mapfile.got_key_vector3f("origin", light->light_location)) {
- light->light_location *= SCALE;
- continue;
-
- } else if (mapfile.got_key_color("_color", light->light_color)) {
- continue;
-
- } else if (mapfile.got_key_int("spawnflags", u)) {
- light->light_strobe = spawnflag_isset(u, 1);
- light->light_entity = spawnflag_isset(u, 2);
-
- } else if (mapfile.got_key_float("light", light->light_radius)) {
- light->light_radius /= 100.0f;
- } else if (mapfile.got_key_float("frequency", light->light_frequency)) {
- continue;
-
- } else if (mapfile.got_key_float("offset", light->light_offset)) {
- continue;
-
- } else if (mapfile.got_key_float("time", light->light_time)) {
- continue;
-
- } else if (mapfile.got_key_int("flare", light->light_flare)) {
- continue;
-
- }
-
- } else if (mapfile.got_classname("target_flare")) {
-
- // new flare
- flare = new Flare();
- model->add_flare(flare);
-
- } else if (mapfile.classname().compare("target_flare") == 0 ) {
-
- // flare attributes
- if (mapfile.got_key_vector3f("origin", flare->light_location)) {
- flare->light_location *= SCALE;
- continue;
-
- } else if (mapfile.got_key_color("_color", flare->light_color)) {
- continue;
-
- } else if (mapfile.got_key_int("spawnflags", u)) {
- flare->light_strobe = spawnflag_isset(u, 1);
- flare->light_entity = spawnflag_isset(u, 2);
-
- } else if (mapfile.got_key_float("radius", flare->light_radius)) {
- flare->light_radius /= 100.0f;
-
- } else if (mapfile.got_key_float("frequency", flare->light_frequency)) {
- continue;
+// scaling factor when loading .map geometry
+const float SCALE = 1.0f / 1024.0f;
- } else if (mapfile.got_key_float("offset", flare->light_offset)) {
- continue;
-
- } else if (mapfile.got_key_float("time", flare->light_time)) {
- continue;
-
- } else if (mapfile.got_key_int("flare", flare->light_flare)) {
- continue;
-
- } else if (mapfile.got_key_float("angle", flare->flare_angle)) {
- flare->flare_angle = math::degrees360f(flare->flare_angle);
- continue;
-
- }
-
- } else if (mapfile.got_classname("target_engine")) {
- // new engine
- engine = new Engine();
- model->add_engine(engine);
-
- } else if (mapfile.classname().compare("target_engine") == 0 ) {
- // engine attributes
-
- if (mapfile.got_key_vector3f("origin", engine->engine_location)) {
- engine->engine_location *= SCALE;
- continue;
-
- } else if (mapfile.got_key_color("_color", engine->engine_color)) {
- continue;
+const float MIN_DELTA = 10e-10;
- } else if (mapfile.got_key_float("radius", engine->engine_radius)) {
- engine->engine_radius /= 100.0f;
- continue;
+Map::Map()
+{
+ mapfile_name.clear();
+}
- } else if (mapfile.got_key_int("flare", engine->engine_flare)) {
- continue;
+Map::~Map()
+{
+ clear_materials();
+}
- } else if (mapfile.got_key_color("_color", engine->engine_color)) {
- continue;
- }
- }
+void Map::clear_materials()
+{
+ for (Materials::iterator mit = map_materials.begin(); mit != map_materials.end(); mit++) {
+ // delete list of primitives
+ delete(*mit).second;
}
-
- mapfile.close();
-
- mapfile.load_fragments(model);
-
- return model;
+ map_materials.clear();
+
+ map_brushes = 0;
+ map_faces = 0;
+ map_faces_detail = 0;
}
-Map::Map() {}
-
-Map::~Map() {}
-
-bool Map::open(std::string const & name) {
+bool Map::open(std::string const & name)
+{
last_read_was_classname = false;
last_read_was_key = false;
@@ -182,13 +67,14 @@ bool Map::open(std::string const & name) {
classname_current = "";
line_number = 0;
parse_level = 0;
- brushes = 0;
-
+
+ clear_materials();
+
mapfile_name.assign("maps/");
mapfile_name.append(name);
mapfile_name.append(".map");
- filesystem::File *f = filesystem::open(mapfile_name.c_str());
+ filesystem::File *f = filesystem::open(mapfile_name.c_str());
if (!f) {
con_warn << "Could not open " << mapfile_name << std::endl;
return false;
@@ -203,33 +89,36 @@ bool Map::open(std::string const & name) {
con_warn << "Could not stream " << fn << "!\n";
return false;
}
-
+
return true;
}
-bool Map::got_classname() const {
+bool Map::got_classname() const
+{
return last_read_was_classname;
}
-bool Map::got_classname(const char * classnamelabel) const {
+bool Map::got_classname(const char * classnamelabel) const
+{
return (last_read_was_classname && (classname_current.compare(classnamelabel) == 0));
}
-bool Map::getline() {
+bool Map::getline()
+{
using math::Vector3f;
-
+
char data[1024];
-
+
last_read_was_classname = false;
last_read_was_key = false;
-
+
key_current = "";
value_current = "";
-
+
if (!mapfile_ifs.is_open())
return false;
-
+
if (mapfile_ifs.getline(data, 1023)) {
line_number++;
std::istringstream linestream(data);
@@ -238,13 +127,13 @@ bool Map::getline() {
if (linestream >> firstword) {
if (!firstword.size()) {
return true;
-
+
} else if (firstword == "//") {
return true;
-
+
} else if (firstword == "{") {
parse_level++;
-
+
} else if (firstword == "}") {
if ((parse_level == 2) && (classname_current == "worldspawn")) {
// brush
@@ -253,24 +142,24 @@ bool Map::getline() {
for (std::vector<Plane *>::iterator face = planes.begin(); face != planes.end(); face++) {
make_brushface((*face));
}
-
+
// clean planes
for (std::vector<Plane *>::iterator it = planes.begin(); it != planes.end(); it++) {
delete(*it);
}
planes.clear();
-
- brushes++;
+
+ map_brushes++;
}
value_current.clear();
}
parse_level--;
-
+
} else if (parse_level == 1) {
-
+
if (firstword == "\"classname\"") {
classname_current.clear();
-
+
if (linestream >> classname_current) {
if (classname_current.size() > 2) {
classname_current.erase(0,1);
@@ -280,24 +169,24 @@ bool Map::getline() {
classname_current.clear();
}
}
-
+
} else if ((firstword.size() > 2) && (firstword[0] == '\"') && (firstword[firstword.size()-1] == '\"')) {
-
+
key_current.assign(firstword);
key_current.erase(0,1);
key_current.erase(key_current.size()-1, 1);
-
+
value_current.clear();
char c;
while ((linestream.get(c)) && (c != '"'));
while ((linestream.get(c)) && (c != '"'))
value_current += c;
-
+
last_read_was_key = true;
}
} else if (parse_level == 2) {
-
+
if ((firstword == "(") && (classname_current == "worldspawn")) {
// brush plane
if (VertexArray::instance()) {
@@ -319,21 +208,21 @@ bool Map::getline() {
// 5 numbers (texture alignment?)
for (int i=0; i < 5; i++)
linestream >> tmp;
-
+
// content flags ?
if (!(linestream >> n))
n = 0;
-
+
Plane *plane = new Plane(p1, p2, p3);
plane->texture() = texture;
if (n > 0)
plane->detail() = true;
-
+
// surface flags
if (!(linestream >> n))
n = 0;
plane->surface_flags() = n;
-
+
planes.push_back(plane);
}
value_current.clear();
@@ -341,10 +230,10 @@ bool Map::getline() {
}
}
} else {
-
+
return false;
}
-
+
return true;
}
@@ -361,7 +250,13 @@ void Map::make_brushface(Plane *face)
if (face->texture() == "common/clip") {
return;
}
-
+
+ // statistics
+ map_faces++;
+ if (face->detail()) {
+ map_faces_detail++;
+ }
+
// using suggestions from
// http://www.flipcode.com/archives/Level_Editing.shtml
@@ -372,7 +267,7 @@ void Map::make_brushface(Plane *face)
// check if the face is x-axis oriented
if ((fabsf(face->normal().x) >= fabsf(face->normal().y)) && (fabsf(face->normal().x) >= fabsf(face->normal().z))) {
-
+
if (face->normal().x >= 0) {
vl.push_back(new math::Vector3f(0, -MAX_BOUNDS, -MAX_BOUNDS));
vl.push_back(new math::Vector3f(0, -MAX_BOUNDS, MAX_BOUNDS));
@@ -395,7 +290,7 @@ void Map::make_brushface(Plane *face)
// check if the face is y-axis oriented
else if ((fabsf(face->normal().y) >= fabsf(face->normal().x)) && (fabsf(face->normal().y) >= fabsf(face->normal().z))) {
-
+
if (face->normal().y >= 0) {
vl.push_back(new Vector3f(MAX_BOUNDS, 0, -MAX_BOUNDS));
vl.push_back(new Vector3f(MAX_BOUNDS, 0, MAX_BOUNDS));
@@ -419,7 +314,7 @@ void Map::make_brushface(Plane *face)
// face must be z-axis oriented
else {
-
+
if (face->normal().z >= 0) {
vl.push_back(new Vector3f(-MAX_BOUNDS, -MAX_BOUNDS, 0));
vl.push_back(new Vector3f(-MAX_BOUNDS, MAX_BOUNDS, 0));
@@ -461,7 +356,7 @@ void Map::make_brushface(Plane *face)
for (int i=0; vl.size() - i > 0; i++) {
Vector3f v(*vl.at(i));
-
+
Vector3f next;
if (vl.size() - i > 1) {
next = *vl.at(i+1);
@@ -492,7 +387,7 @@ void Map::make_brushface(Plane *face)
float t2 = (plane->normal().x * v.x - plane->normal().x * prev.x +
plane->normal().y * v.y - plane->normal().y * prev.y +
plane->normal().z * v.z - plane->normal().z * prev.z);
-
+
Vector3f *s = new Vector3f;
if (t2 == 0) {
@@ -509,7 +404,7 @@ void Map::make_brushface(Plane *face)
// check if next - v intersects with plane
if ((next.x*plane->normal().x + next.y*plane->normal().y + next.z*plane->normal().z + plane->d()) > -MIN_DELTA) {
-
+
// calculate intersection
float t1 = -plane->normal().x * v.x - plane->normal().y * v.y - plane->normal().z * v.z -plane->d();
float t2 = (plane->normal().x * next.x - plane->normal().x * v.x +
@@ -543,72 +438,84 @@ void Map::make_brushface(Plane *face)
// default material is none
unsigned int material = 0;
-
+
// default color makrs unknown textures hot pink
math::Color color(1.0f, 0.0, 1.0f, 1.0f);
-
+
// translate texture names to color and material
- if (face->texture() == "colors/white") {
+ if (face->texture().compare("colors/white") == 0) {
color.assign(1.0f);
- } else if (face->texture() == "colors/grey90") {
+ } else if (face->texture().compare("colors/grey90") == 0) {
color.assign(0.9f);
- } else if (face->texture() == "colors/grey75") {
+ } else if (face->texture().compare("colors/grey75") == 0) {
color.assign(0.75f);
- } else if (face->texture() == "colors/grey50") {
+ } else if (face->texture().compare("colors/grey50") == 0) {
color.assign(0.5f);
- } else if (face->texture() == "colors/grey25") {
+ } else if (face->texture().compare("colors/grey25") == 0) {
color.assign(0.25f);
- } else if (face->texture() == "colors/black") {
+ } else if (face->texture().compare("colors/black") == 0) {
color.assign(0.0f);
- } else if (face->texture() == "colors/red") {
+ } else if (face->texture().compare("colors/red") == 0) {
color.assign(1, 0, 0);
- } else if (face->texture() == "colors/green") {
+ } else if (face->texture().compare("colors/green") == 0) {
color.assign(0, 1, 0);
- } else if (face->texture() == "colors/blue") {
+ } else if (face->texture().compare("colors/blue") == 0) {
color.assign(0, 0, 1);
-
- } else if ((face->texture() == "common/entity") || (face->texture() == "common/primary")) {
+
+ } else if ((face->texture().compare("common/entity") == 0) || (face->texture().compare("common/primary") == 0)) {
material |= Material::Primary;
- } else if (face->texture() == "common/primary_dark") {
+ } else if (face->texture().compare("common/primary_dark") == 0) {
material |= Material::Primary;
material |= Material::Dark;
-
- } else if (face->texture() == "common/secundary") {
+
+ } else if (face->texture().compare("common/secundary") == 0) {
material |= Material::Secondary;
- } else if (face->texture() == "common/secundary_dark") {
+ } else if (face->texture().compare("common/secundary_dark") == 0) {
material |= Material::Secondary;
material |= Material::Dark;
-
- } else if (face->texture() == "common/tertiary") {
+
+ } else if (face->texture().compare("common/tertiary") == 0) {
material |= Material::Tertiary;
- } else if (face->texture() == "common/tertiary_dark") {
+ } else if (face->texture().compare("common/tertiary_dark") == 0) {
material |= Material::Tertiary;
material |= Material::Dark;
}
-
+
// translate surface flags to materials
-
+
// surface flag 1 light
if ((face->surface_flags() & 1) == 1) {
material |= Material::Light;
}
-
+
+ // find the list if primitives for the current material, allocate a new one if necessary
+ Primitives *primitives = 0;
+
+ Materials::iterator mit = map_materials.find(material);
+ if (mit == map_materials.end()) {
+ primitives = new Primitives(material);
+ map_materials[material] = primitives;
+ } else {
+ primitives = (*mit).second;
+ }
+
// calculate bounding box
- for (std::vector<Vector3f *>::iterator it = vl.begin(); it != vl.end(); it++) {
-
+ for (std::vector<Vector3f *>::iterator it = vl.begin(); it != vl.end(); it++) {
+
*(*it) *= SCALE;
-
+
for (int i=0; i < 3; i++) {
if (class_maxbbox[i] < (*(*it))[i])
class_maxbbox[i] = (*(*it))[i];
-
+
if (class_minbbox[i] > (*(*it))[i])
class_minbbox[i] = (*(*it))[i];
}
}
-
+
// split face into triangles
- while (vl.size() >2 ) {
+ // FIXME split off quads
+ while (vl.size() >2) {
std::vector<Vector3f *>::iterator v0 = vl.begin();
std::vector<Vector3f *>::reverse_iterator vn = vl.rbegin();
std::vector<Vector3f *>::reverse_iterator vn1 = vl.rbegin();
@@ -616,21 +523,9 @@ void Map::make_brushface(Plane *face)
Vector3f n(face->normal()*-1);
n.normalize();
-
- if (material & Material::Primary) {
- // evertices will be added to the VertexArray after normal vertices
- Triangle *triangle = new Triangle(*(*vn1), *(*vn), *(*v0), n, 0, face->detail());
- class_etris.push_back(triangle);
- } else if (material & Material::Light) {
- // lvertices
- Triangle *triangle = new Triangle(*(*vn1), *(*vn), *(*v0), n, color, face->detail());
- class_ltris.push_back(triangle);
- } else {
- Triangle *triangle = new Triangle(*(*vn1), *(*vn), *(*v0), n, color, face->detail());
- class_tris.push_back(triangle);
- }
-
- delete (*vn);
+
+ primitives->add_triangle(*(*vn1), *(*vn), *(*v0), n, color, face->detail());
+ delete(*vn);
vl.pop_back();
}
} else {
@@ -645,8 +540,9 @@ void Map::make_brushface(Plane *face)
vl.clear();
}
-bool Map::got_key_string(const char * keylabel, std::string & valuestring) {
- if (last_read_was_key && (key_current.compare(keylabel) == 0 )) {
+bool Map::got_key_string(const char * keylabel, std::string & valuestring)
+{
+ if (last_read_was_key && (key_current.compare(keylabel) == 0)) {
valuestring.assign(value_current);
return true;
} else {
@@ -654,14 +550,15 @@ bool Map::got_key_string(const char * keylabel, std::string & valuestring) {
}
}
-bool Map::got_key_vector3f(const char * keylabel, math::Vector3f & v) {
- if (last_read_was_key && (key_current.compare(keylabel) == 0 )) {
+bool Map::got_key_vector3f(const char * keylabel, math::Vector3f & v)
+{
+ if (last_read_was_key && (key_current.compare(keylabel) == 0)) {
std::istringstream is(value_current);
float x, y, z;
if ((is >> x) && (is >> y) && (is >> z)) {
v = math::Vector3f(x,y,z);
} else {
- v= math::Vector3f();
+ v= math::Vector3f();
}
return true;
} else {
@@ -669,8 +566,9 @@ bool Map::got_key_vector3f(const char * keylabel, math::Vector3f & v) {
}
}
-bool Map::got_key_float(const char * keylabel, float & f) {
- if (last_read_was_key && (key_current.compare(keylabel) == 0 )) {
+bool Map::got_key_float(const char * keylabel, float & f)
+{
+ if (last_read_was_key && (key_current.compare(keylabel) == 0)) {
std::istringstream is(value_current);
if (!(is >> f)) {
f = 0;
@@ -683,7 +581,7 @@ bool Map::got_key_float(const char * keylabel, float & f) {
bool Map::got_key_int(const char * keylabel, unsigned int & u)
{
- if (last_read_was_key && (key_current.compare(keylabel) == 0 )) {
+ if (last_read_was_key && (key_current.compare(keylabel) == 0)) {
std::istringstream is(value_current);
if (!(is >> u)) {
u = 0;
@@ -694,12 +592,14 @@ bool Map::got_key_int(const char * keylabel, unsigned int & u)
}
}
-bool Map::got_key(const char * keylabel) {
- return (last_read_was_key && (key_current.compare(keylabel) == 0 ));
+bool Map::got_key(const char * keylabel)
+{
+ return (last_read_was_key && (key_current.compare(keylabel) == 0));
}
-bool Map::got_key_angle(const char * keylabel, float & f) {
- if (last_read_was_key && (key_current.compare(keylabel) == 0 )) {
+bool Map::got_key_angle(const char * keylabel, float & f)
+{
+ if (last_read_was_key && (key_current.compare(keylabel) == 0)) {
std::istringstream is(value_current);
if ((is >> f)) {
f = math::degrees360f(f);
@@ -712,13 +612,16 @@ bool Map::got_key_angle(const char * keylabel, float & f) {
}
}
-bool Map::got_key_color(const char * keylabel, math::Color & color) {
- if (last_read_was_key && (key_current.compare(keylabel) == 0 )) {
+bool Map::got_key_color(const char * keylabel, math::Color & color)
+{
+ if (last_read_was_key && (key_current.compare(keylabel) == 0)) {
std::istringstream is(value_current);
float r, g, b;
if ((is >> r) && (is >> g) && (is >> b)) {
if ((r > 1) || (g > 1) || (b > 1)) {
- r /= 255; g /= 255; b /= 255;
+ r /= 255;
+ g /= 255;
+ b /= 255;
}
color = math::Color(r, g, b);
} else {
@@ -739,119 +642,231 @@ void Map::load_fragments(Model *model)
{
if (!VertexArray::instance() || VertexArray::instance()->overflow())
return;
-
- // process the triangles calculated by the mapfile and add them to the vertex array
- if ((class_tris.size() + class_etris.size() + class_ltris.size()) > 0) {
-
- math::Vector3f center = (class_minbbox + class_maxbbox) / 2;
-
- model->model_minbbox = class_minbbox - center;
- model->model_maxbbox = class_maxbbox - center;
-
- model->model_radius = model->model_maxbbox.length();
-
- // structural triangles
- model->model_first_vertex = VertexArray::instance()->index()/3;
- for (std::list<Triangle *>::iterator it = class_tris.begin(); it != class_tris.end(); it++) {
- Triangle *triangle = (*it);
- if (!triangle->detail()) {
- size_t count = 0;
- count += VertexArray::instance()->add_vertex(triangle->v0()-center, triangle->normal(), triangle->color() );
- count += VertexArray::instance()->add_vertex(triangle->v1()-center, triangle->normal(), triangle->color() );
- count += VertexArray::instance()->add_vertex(triangle->v2()-center, triangle->normal(), triangle->color() );
- if (count == 3)
- model->model_vertex_count += count;
+
+ if (!map_materials.size())
+ return;
+
+ // FIXME center in maps without brushes
+ math::Vector3f center = (class_minbbox + class_maxbbox) / 2;
+
+ model->model_minbbox = class_minbbox - center;
+ model->model_maxbbox = class_maxbbox - center;
+
+ model->model_radius = model->model_maxbbox.length();
+
+ // reposition lights, flares and engines
+ for (Model::Lights::iterator lit = model->lights().begin(); lit != model->lights().end(); lit++) {
+ (*lit)->light_location -= center;
+ }
+
+ for (Model::Flares::iterator flit = model->flares().begin(); flit != model->flares().end(); flit++) {
+ (*flit)->light_location -= center;
+ }
+
+ for (Model::Engines::iterator eit = model->engines().begin(); eit != model->engines().end(); eit++) {
+ (*eit)->engine_location -= center;
+ }
+
+ for (Materials::iterator mit = map_materials.begin(); mit != map_materials.end(); mit++) {
+ // split the Primitives with this material into fragments
+ Primitives *primitives = (*mit).second;
+
+ // 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()-center, triangle->normal(), triangle->color(), false);
+ count += fragment->add_vertex(triangle->v1()-center, triangle->normal(), triangle->color(), false);
+ count += fragment->add_vertex(triangle->v2()-center, triangle->normal(), triangle->color(), false);
+ if (count == 3)
+ model->model_tris_count++;
+ }
}
- }
-
- // detail triangles
- for (std::list<Triangle *>::iterator it = class_tris.begin(); it != class_tris.end(); it++) {
- Triangle *triangle = (*it);
- if (triangle->detail()) {
- size_t count = 0;
- count += VertexArray::instance()->add_vertex(triangle->v0()-center, triangle->normal(), triangle->color() );
- count += VertexArray::instance()->add_vertex(triangle->v1()-center, triangle->normal(), triangle->color() );
- count += VertexArray::instance()->add_vertex(triangle->v2()-center, triangle->normal(), triangle->color() );
- if (count == 3)
- model->model_vertex_countdetail += 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()-center, triangle->normal(), triangle->color(), true);
+ count += fragment->add_vertex(triangle->v1()-center, triangle->normal(), triangle->color(), true);
+ count += fragment->add_vertex(triangle->v2()-center, triangle->normal(), triangle->color(), true);
+ if (count == 3) {
+ model->model_tris_count++;
+ model->model_tris_detail_count++;
+ }
+ }
}
- delete triangle;
+
+ // add the fragment to the model
+ model->fragments().push_back(fragment);
}
- class_tris.clear();
- // structural etriangles
- model->model_first_evertex = VertexArray::instance()->index()/3;
- for (std::list<Triangle *>::iterator it = class_etris.begin(); it != class_etris.end(); it++) {
- Triangle *triangle = (*it);
- if (!triangle->detail()) {
- size_t count = 0;
- count += VertexArray::instance()->add_vertex(triangle->v0()-center, triangle->normal(), triangle->color());
- count += VertexArray::instance()->add_vertex(triangle->v1()-center, triangle->normal(), triangle->color());
- count += VertexArray::instance()->add_vertex(triangle->v2()-center, triangle->normal(), triangle->color());
- if (count == 3)
- model->model_evertex_count += count;
- }
- }
+ }
+
+ if (model->model_tris_count + model->model_quad_count > 0) {
+
+ }
+
+}
- // detail etriangles
- for (std::list<Triangle *>::iterator it = class_etris.begin(); it != class_etris.end(); it++) {
- Triangle *triangle = (*it);
- if (triangle->detail()) {
- size_t count = 0;
- count += VertexArray::instance()->add_vertex(triangle->v0()-center, triangle->normal(), triangle->color());
- count += VertexArray::instance()->add_vertex(triangle->v1()-center, triangle->normal(), triangle->color());
- count += VertexArray::instance()->add_vertex(triangle->v2()-center, triangle->normal(), triangle->color());
- if (count == 3)
- model->model_evertex_countdetail += count;
+Model * Map::load(std::string const &name)
+{
+ // open the .map file
+ Map mapfile;
+
+ if (!mapfile.open(name)) {
+ return 0;
+ }
+
+ Model *model = new Model(name);
+ Light *light = 0;
+ Flare *flare = 0;
+ Engine *engine = 0;
+
+ unsigned int u;
+
+ while (mapfile.getline()) {
+
+ if (mapfile.got_classname("worldspawn")) {
+
+ // new wordspawn
+
+ } else if (mapfile.classname().compare("worldspawn") == 0) {
+
+ // worldspawn attributes
+ if (mapfile.got_key_int("enginesound", u)) {
+ model->model_enginesound = u;
+ continue;
}
- delete triangle;
- }
- class_etris.clear();
-
- // structural ltriangles
- model->model_first_lvertex = VertexArray::instance()->index()/3;
- for (std::list<Triangle *>::iterator it = class_ltris.begin(); it != class_ltris.end(); it++) {
- Triangle *triangle = (*it);
- if (!triangle->detail()) {
- size_t count = 0;
- count += VertexArray::instance()->add_vertex(triangle->v0()-center, triangle->normal(), triangle->color());
- count += VertexArray::instance()->add_vertex(triangle->v1()-center, triangle->normal(), triangle->color());
- count += VertexArray::instance()->add_vertex(triangle->v2()-center, triangle->normal(), triangle->color());
- if (count == 3)
- model->model_lvertex_count += count;
+
+ } else if (mapfile.got_classname("light")) {
+
+ // new light
+ light = new Light();
+ model->add_light(light);
+
+ } else if (mapfile.classname().compare("light") == 0) {
+
+ // light attributes
+ if (mapfile.got_key_vector3f("origin", light->light_location)) {
+ light->light_location *= SCALE;
+ continue;
+
+ } else if (mapfile.got_key_color("_color", light->light_color)) {
+ continue;
+
+ } else if (mapfile.got_key_int("spawnflags", u)) {
+ light->light_strobe = spawnflag_isset(u, 1);
+ light->light_entity = spawnflag_isset(u, 2);
+
+ } else if (mapfile.got_key_float("light", light->light_radius)) {
+ light->light_radius /= 100.0f;
+
+ } else if (mapfile.got_key_float("frequency", light->light_frequency)) {
+ continue;
+
+ } else if (mapfile.got_key_float("offset", light->light_offset)) {
+ continue;
+
+ } else if (mapfile.got_key_float("time", light->light_time)) {
+ continue;
+
+ } else if (mapfile.got_key_int("flare", light->light_flare)) {
+ continue;
+
}
- }
-
- // detail ltriangles
- for (std::list<Triangle *>::iterator it = class_ltris.begin(); it != class_ltris.end(); it++) {
- Triangle *triangle = (*it);
- if (triangle->detail()) {
- size_t count = 0;
- count += VertexArray::instance()->add_vertex(triangle->v0()-center, triangle->normal(), triangle->color() );
- count += VertexArray::instance()->add_vertex(triangle->v1()-center, triangle->normal(), triangle->color() );
- count += VertexArray::instance()->add_vertex(triangle->v2()-center, triangle->normal(), triangle->color() );
- if (count == 3)
- model->model_lvertex_countdetail += count;
+
+ } else if (mapfile.got_classname("target_flare")) {
+
+ // new flare
+ flare = new Flare();
+ model->add_flare(flare);
+
+ } else if (mapfile.classname().compare("target_flare") == 0) {
+
+ // flare attributes
+ if (mapfile.got_key_vector3f("origin", flare->light_location)) {
+ flare->light_location *= SCALE;
+ continue;
+
+ } else if (mapfile.got_key_color("_color", flare->light_color)) {
+ continue;
+
+ } else if (mapfile.got_key_int("spawnflags", u)) {
+ flare->light_strobe = spawnflag_isset(u, 1);
+ flare->light_entity = spawnflag_isset(u, 2);
+
+ } else if (mapfile.got_key_float("radius", flare->light_radius)) {
+ flare->light_radius /= 100.0f;
+
+ } else if (mapfile.got_key_float("frequency", flare->light_frequency)) {
+ continue;
+
+ } else if (mapfile.got_key_float("offset", flare->light_offset)) {
+ continue;
+
+ } else if (mapfile.got_key_float("time", flare->light_time)) {
+ continue;
+
+ } else if (mapfile.got_key_int("flare", flare->light_flare)) {
+ continue;
+
+ } else if (mapfile.got_key_float("angle", flare->flare_angle)) {
+ flare->flare_angle = math::degrees360f(flare->flare_angle);
+ continue;
+
+ }
+
+ } else if (mapfile.got_classname("target_engine")) {
+ // new engine
+ engine = new Engine();
+ model->add_engine(engine);
+
+ } else if (mapfile.classname().compare("target_engine") == 0) {
+ // engine attributes
+
+ if (mapfile.got_key_vector3f("origin", engine->engine_location)) {
+ engine->engine_location *= SCALE;
+ continue;
+
+ } else if (mapfile.got_key_color("_color", engine->engine_color)) {
+ continue;
+
+ } else if (mapfile.got_key_float("radius", engine->engine_radius)) {
+ engine->engine_radius /= 100.0f;
+ continue;
+
+ } else if (mapfile.got_key_int("flare", engine->engine_flare)) {
+ continue;
+
+ } else if (mapfile.got_key_color("_color", engine->engine_color)) {
+ continue;
}
- delete triangle;
- }
- class_ltris.clear();
-
- // reposition lights, flares and engines
- for (std::list<Light *>::iterator lit = model->model_light.begin(); lit != model->model_light.end(); lit++) {
- (*lit)->light_location -= center;
- }
-
- for (std::list<Flare *>::iterator flit = model->model_flare.begin(); flit != model->model_flare.end(); flit++) {
- (*flit)->light_location -= center;
- }
-
- for (std::list<Engine *>::iterator eit = model->model_engine.begin(); eit != model->model_engine.end(); eit++) {
- (*eit)->engine_location -= center;
}
}
-
- con_print << " maps/" << model->name() << ".map " << brushes << " brushes " << model->tris() << " tris (" << model->details() << " detail)" << std::endl;
+
+ mapfile.close();
+ /*
+ con_print << " " << mapfile.name() << " " << mapfile.map_materials.size() << " mat" <<
+ mapfile.map_brushes << " brushes " <<
+ mapfile.map_faces << "/" << mapfile.map_faces_detail << " faces/detail " << std::endl;
+ */
+ mapfile.load_fragments(model);
+
+ con_print << " " << mapfile.name() << " " <<
+ model->model_tris_count << "/" << model->model_tris_detail_count << " tris/detail " <<
+ model->model_quad_count << "/" << model->model_quad_detail_count << " quads/detail " <<
+ model->fragments().size() << " frags " <<std::endl;
+
+ mapfile.clear_materials();
+
+ return model;
}
}
diff --git a/src/model/map.h b/src/model/map.h
index e5b5308..afe925b 100644
--- a/src/model/map.h
+++ b/src/model/map.h
@@ -13,119 +13,139 @@
#include "model/model.h"
#include "model/plane.h"
-#include "model/triangle.h"
+#include "model/primitives.h"
-namespace model {
+namespace model
+{
/// class to parse the .map file structure and load geometry data into a model
-class Map {
+class Map
+{
public:
/// load a .map file into a Model
/** @param name name of the model to be loaded, without .map extension or maps/ prefix
*/
static Model *load(std::string const &name);
-
-protected:
+
+private:
Map();
~Map();
-
+
+ /// tpye definition for a per-material list of Primitives
+ typedef std::map<unsigned int, Primitives *> Materials;
+
/// open the file for reading
/** the filename will get the "maps/" prefix and ".map" suffix
*/
bool open(std::string const & name);
-
+
/// parse one line, returns false on end-of-file
bool getline();
-
+
/// current classname
- inline std::string classname() const {
+ inline std::string classname() const
+ {
return classname_current;
}
-
+
/// current key
- inline std::string key() const {
+ inline std::string key() const
+ {
return key_current;
}
-
+
/// current value
- inline std::string value() const {
+ inline std::string value() const
+ {
return value_current;
}
-
+
/// true if the last read line contained a new classname
bool got_classname() const;
-
+
/// true if the last read line contained a new classname
bool got_classname(const char*) const;
-
+
/// true if the last read statement was a key=value pair
- inline bool got_key() const {
+ inline bool got_key() const
+ {
return last_read_was_key;
}
-
+
bool got_key(const char * keylabel);
-
+
/// check if the last read key=value pair matches keylabel and store the value in valuestring
bool got_key_string(const char * keylabel, std::string & valuestring);
-
+
/// check if the last read key=value pair matches keylabel and store the value in color
bool got_key_color(const char * keylabel, math::Color & color);
-
+
/// check if the last read key=value pair matches keylabel and store the value in f
bool got_key_float(const char * keylabel, float & f);
-
+
/// check if the last read key=value pair matches keylabel and store the value in f
bool got_key_int(const char * keylabel, unsigned int & u);
-
+
/// check if the last read key=value pair matches keylabel and store the value in valuestring
bool got_key_angle(const char * keylabel, float & f);
-
+
bool got_key_vector3f(const char * keylabel, math::Vector3f & v);
-
-
+
+
/// return the number of lines read so far
- inline unsigned int line() const {
+ inline unsigned int line() const
+ {
return line_number;
}
-
+
/// return true of the ini file is open for reading
- inline bool is_open() { return mapfile_ifs.is_open(); }
-
+ inline bool is_open()
+ {
+ return mapfile_ifs.is_open();
+ }
+
/// current filename
- inline std::string const & name() const {return mapfile_name; }
-
+ inline std::string const & name() const
+ {
+ return mapfile_name;
+ }
+
/// close the file
void close();
-
+
/// generate triangles for one plane in the plane list
void make_brushface(Plane *face);
-
- /// load parsed primitives into map fragments
+
+ /// load parsed primitives into Model Fragments
void load_fragments(Model *model);
-
+
+ /// clear the current list of per-material geometry
+ void clear_materials();
+
/// list of planes for the current brush
std::vector<Plane *> planes;
-
+
std::string classname_current;
std::string key_current;
std::string value_current;
-
+
bool last_read_was_key;
bool last_read_was_classname;
-
- unsigned int brushes;
+
+ unsigned int map_brushes;
+ unsigned int map_faces;
+ unsigned int map_faces_detail;
+
unsigned int parse_level;
unsigned int line_number;
std::ifstream mapfile_ifs;
std::string mapfile_name;
-
- std::list<Triangle *> class_tris; // normal triangles
- std::list<Triangle *> class_etris; // entity color triangles
- std::list<Triangle *> class_ltris; // light triangles
-
+
math::Vector3f class_maxbbox;
- math::Vector3f class_minbbox;
+ math::Vector3f class_minbbox;
+
+ Materials map_materials;
};
}
diff --git a/src/model/model.cc b/src/model/model.cc
index 2e9f0ba..5becc82 100644
--- a/src/model/model.cc
+++ b/src/model/model.cc
@@ -12,78 +12,67 @@
namespace model
{
-std::map<std::string, Model*> Model::registry;
+// static model registry
+Model::Registry Model::model_registry;
Model::Model(std::string const & name) :
model_name(name)
{
- model_first_vertex = 0;
- model_first_evertex = 0;
- model_first_lvertex = 0;
-
- model_vertex_count = 0;
- model_vertex_countdetail = 0;
- model_evertex_count = 0;
- model_evertex_countdetail = 0;
- model_lvertex_count = 0;
- model_lvertex_countdetail = 0;
-
model_radius = 0.5f;
model_enginesound = 0;
+
+ model_tris_detail_count = 0;
+ model_tris_count = 0;
+ model_quad_detail_count = 0;
+ model_quad_count = 0;
}
Model::~Model()
{
+ // delete all fragments
+ for (Fragments::iterator fragit = model_fragments.begin(); fragit != model_fragments.end(); fragit++) {
+ delete(*fragit);
+ }
+ model_fragments.clear();
+
// delete all engines
- for (std::list<Engine *>::iterator eit = model_engine.begin(); eit != model_engine.end(); eit++) {
+ for (Engines::iterator eit = model_engines.begin(); eit != model_engines.end(); eit++) {
delete(*eit);
}
- model_engine.clear();
+ model_engines.clear();
// delete all lights
- for (std::list<Light *>::iterator lit = model_light.begin(); lit != model_light.end(); lit++) {
- delete (*lit);
+ for (Lights::iterator lit = model_lights.begin(); lit != model_lights.end(); lit++) {
+ delete(*lit);
}
- model_light.clear();
-
+ model_lights.clear();
+
// delete all flares
- for (std::list<Flare *>::iterator flit = model_flare.begin(); flit != model_flare.end(); flit++) {
- delete (*flit);
+ for (Flares::iterator flit = model_flares.begin(); flit != model_flares.end(); flit++) {
+ delete(*flit);
}
- model_flare.clear();
-}
-
-size_t Model::tris() const
-{
- return ((model_vertex_count + model_vertex_countdetail +
- model_evertex_count + model_evertex_countdetail +
- model_lvertex_count + model_lvertex_countdetail)/3);
-}
-
-size_t Model::details() const
-{
- return ((model_vertex_countdetail + model_evertex_countdetail + model_lvertex_countdetail)/3);
+ model_flares.clear();
}
void Model::add_engine(Engine *engine)
{
- model_engine.push_back(engine);
+ model_engines.push_back(engine);
}
void Model::add_light(Light *light)
{
- model_light.push_back(light);
+ model_lights.push_back(light);
}
void Model::add_flare(Flare *flare)
{
- model_flare.push_back(flare);
+ model_flares.push_back(flare);
}
Model *Model::find(std::string const & name)
{
- std::map<std::string, Model*>::iterator it = registry.find(name);
- if (it == registry.end())
+ Registry::iterator it = model_registry.find(name);
+ if (it == model_registry.end())
return 0;
else
return (*it).second;
@@ -94,40 +83,46 @@ Model *Model::load(std::string const & name)
Model *model = find(name);
if (!model) {
model = Map::load(name);
- if (model)
- registry[model->name()] = model;
+ if (model) {
+ model_registry[model->name()] = model;
+ }
}
-
+
return model;
}
void Model::clear()
{
// delete all models in the registry
- for (std::map<std::string, Model*>::iterator mit = registry.begin(); mit != registry.end(); mit++) {
+ for (Registry::iterator mit = model_registry.begin(); mit != model_registry.end(); mit++) {
delete(*mit).second;
}
- registry.clear();
-
+ model_registry.clear();
+
// clear the vertex array
if (VertexArray::instance())
VertexArray::instance()->clear();
}
+void Model::list_model(Model *model)
+{
+ con_print << " " << model->name() << " " <<
+ model->model_tris_count << "/" << model->model_tris_detail_count << " tris/detail " <<
+ model->model_quad_count << "/" << model->model_quad_detail_count << " quads/detail "
+ << model->fragments().size() << " frags "<< std::endl;
+}
+
void Model::list()
{
- for (std::map<std::string, Model*>::iterator mit = registry.begin(); mit != registry.end(); mit++) {
- con_print << " " << (*mit).second->name() << " "
- << (*mit).second->tris() << " triangles ("
- << (*mit).second->details() << " detail) "
- << (*mit).second->model_engine.size() << " engines "
- << (*mit).second->model_light.size() << " lights "
- << (*mit).second->model_flare.size() << " flares ";
+ for (Registry::iterator mit = model_registry.begin(); mit != model_registry.end(); mit++) {
+ list_model((*mit).second);
+
}
- con_print << registry.size() << " registered models" << std::endl;
+
+ con_print << model_registry.size() << " registered models" << std::endl;
if (VertexArray::instance())
- con_print << "vertex array " << (VertexArray::instance()->index() * 100 / VertexArray::instance()->size())
- << "% used" << std::endl;
+ con_print << "vertex array " << (VertexArray::instance()->index() * 100 / VertexArray::instance()->size())
+ << "% of " << VertexArray::instance()->size() << " used" << std::endl;
}
}
diff --git a/src/model/model.h b/src/model/model.h
index d2b7d65..552d7dd 100644
--- a/src/model/model.h
+++ b/src/model/model.h
@@ -13,6 +13,7 @@
#include "math/mathlib.h"
#include "model/engine.h"
+#include "model/fragment.h"
#include "model/light.h"
#include "model/flare.h"
@@ -20,15 +21,29 @@
namespace model
{
-/// scaling factor when loading .map geometry
-const float SCALE = 1.0f / 1024.0f;
-
/// a 3D model contains a list of faces
class Model
{
public:
- /// load a model from disk
+ /// type definition for the model registry
+ typedef std::map<std::string, Model*> Registry;
+
+ /// type definition for a list of model fragments
+ typedef std::list<Fragment *> Fragments;
+
+ /// type definition for a list of model lights
+ typedef std::list<Light *> Lights;
+
+ /// type definition for a list of model flares
+ typedef std::list<Flare *> Flares;
+
+ /// type definition for a list of model engines
+ typedef std::list<Engine *> Engines;
+
+ /// create a model with a name
Model(std::string const & name);
+
+ /// delete the model, and all fragments, lights, etc
~Model();
/// the name of the model
@@ -36,95 +51,79 @@ public:
{
return model_name;
}
-
+
+ /// radius
+ inline float radius() const
+ {
+ return model_radius;
+ }
+
+ /// list of fragments
+ inline Fragments & fragments()
+ {
+ return model_fragments;
+ }
+
+ /// list of lights
+ inline Lights & lights()
+ {
+ return model_lights;
+ }
+
+ /// list of flares
+ inline Flares & flares()
+ {
+ return model_flares;
+ }
+
+ /// list of engines
+ inline Engines & engines()
+ {
+ return model_engines;
+ }
+
/// maximum values of the bounding box
- inline math::Vector3f const & maxbbox() const { return model_maxbbox; }
+ inline math::Vector3f const & maxbbox() const
+ {
+ return model_maxbbox;
+ }
/// minimum values of the bounding box
- inline math::Vector3f const & minbbox() const { return model_minbbox; }
-
- /// first vertex in the global VertexArray
- inline size_t first_vertex() const { return model_first_vertex; }
-
- /// number of structural vertices in this model
- inline size_t vertex_structural() const { return model_vertex_count; }
-
- /// number of detail vertices
- inline size_t vertex_detail() const { return model_vertex_countdetail; }
-
- /// first evertex in the global VertexArray
- inline size_t first_evertex() const { return model_first_evertex; }
-
- /// number of structural evertices in this model
- inline size_t evertex_structural() const { return model_evertex_count; }
-
- /// number of detail evertices in this model
- inline size_t evertex_detail() const { return model_evertex_countdetail; }
-
- /// first lvertex in the global VertexArray
- inline size_t first_lvertex() const { return model_first_lvertex; }
-
- /// number of structural lvertices in this model
- inline size_t lvertex_structural() const { return model_lvertex_count; }
-
- /// number of detail evertices in this model
- inline size_t lvertex_detail() const { return model_lvertex_countdetail; }
-
+ inline math::Vector3f const & minbbox() const
+ {
+ return model_minbbox;
+ }
+
/// engine sound loop for this model
- inline unsigned int enginesound() const { return model_enginesound; }
-
- /// total number of triangles in this model
- size_t tris() const;
-
- /// number of detail triangles in this model
- size_t details() const;
-
- /// radius
- inline float radius() const { return model_radius; }
-
- /// list of Engines
- std::list<Engine *> model_engine;
-
- /// add an engine to the model
- void add_engine(Engine *engine);
-
- /// list of Lights
- std::list<Light *> model_light;
-
+ inline unsigned int & enginesound()
+ {
+ return model_enginesound;
+ }
+
/// add a light to the model
void add_light(Light *light);
-
- /// list of flares
- std::list<Flare *> model_flare;
-
+
+ /// add an engine to the model
+ void add_engine(Engine *engine);
+
/// add a flare to the model
void add_flare(Flare *flare);
- std::string model_name;
float model_radius;
-
+
math::Vector3f model_maxbbox;
math::Vector3f model_minbbox;
-
- size_t model_first_vertex;
- size_t model_vertex_count;
- size_t model_vertex_countdetail;
-
- size_t model_first_evertex;
- size_t model_evertex_count;
- size_t model_evertex_countdetail;
-
- size_t model_first_lvertex;
- size_t model_lvertex_count;
- size_t model_lvertex_countdetail;
-
+
unsigned int model_enginesound;
-
+
/* ---- static functions for the Model registry -------------------- */
-
- /// the Model registry
- static std::map<std::string, Model*> registry;
-
+
+ /// the model registry
+ static inline Registry & registry()
+ {
+ return model_registry;
+ }
+
/// get name model, returns 0 if not found
static Model *find(std::string const & name);
@@ -136,6 +135,28 @@ public:
/// list the content of the model registry
static void list();
+
+ /// list one model
+ static void list_model(Model *model);
+
+ /// total number of triangles
+ size_t model_tris_count;
+ /// number of detail triangles
+ size_t model_tris_detail_count;
+ /// total number of quads
+ size_t model_quad_count;
+ /// number of detail quads
+ size_t model_quad_detail_count;
+
+private:
+ static Registry model_registry;
+
+ std::string model_name;
+
+ Fragments model_fragments;
+ Flares model_flares;
+ Engines model_engines;
+ Lights model_lights;
};
}
diff --git a/src/model/plane.cc b/src/model/plane.cc
index a637b75..6d80df6 100644
--- a/src/model/plane.cc
+++ b/src/model/plane.cc
@@ -17,25 +17,25 @@ using math::Vector3f;
* x*a() + y*b() + z*c() + d() = 0
*/
-Plane::Plane(Vector3f const & point0, Vector3f const &point1, Vector3f const &point2)
+Plane::Plane(Vector3f const & point0, Vector3f const &point1, Vector3f const &point2)
{
plane_detail = false;
plane_surface_flags = 0;
-
+
plane_point[0] = point0;
plane_point[1] = point1;
plane_point[2] = point2;
-
- plane_normal = crossproduct((plane_point[1] - plane_point[0]) , (plane_point[2] - plane_point[0]) );
+
+ plane_normal = crossproduct((plane_point[1] - plane_point[0]) , (plane_point[2] - plane_point[0]));
pd = -1 * (plane_normal.x * plane_point[0].x + plane_normal.y * plane_point[0].y + plane_normal.z * plane_point[0].z);
}
-Plane::Plane(Plane const & other)
+Plane::Plane(Plane const & other)
{
- for (size_t i=0; i < 3; i++)
+ for (size_t i=0; i < 3; i++)
this->plane_point[i] = other.plane_point[i];
-
- plane_normal = crossproduct((plane_point[1] - plane_point[0]) , (plane_point[2] - plane_point[0]) );
+
+ plane_normal = crossproduct((plane_point[1] - plane_point[0]) , (plane_point[2] - plane_point[0]));
pd = -1 * (plane_normal.x * plane_point[0].x + plane_normal.y * plane_point[0].y + plane_normal.z * plane_point[0].z);
}
diff --git a/src/model/plane.h b/src/model/plane.h
index 5a8e6b6..6c19a5a 100644
--- a/src/model/plane.h
+++ b/src/model/plane.h
@@ -25,28 +25,55 @@ public:
Plane(math::Vector3f const & point0, math::Vector3f const &point1, math::Vector3f const &point2);
/// copy constructor
Plane(Plane const & other);
-
+
/// normal of the plane, not normalized to lenght 1
- inline math::Vector3f const & normal() const { return plane_normal; }
- /// the points defining the plane.
+ inline math::Vector3f const & normal() const
+ {
+ return plane_normal;
+ }
+ /// the points defining the plane.
/// @param i 0 <= i < 3
- inline math::Vector3f const & point(size_t i) const { return plane_point[i]; }
- /// plane texture
- inline std::string & texture() { return plane_texture; }
+ inline math::Vector3f const & point(size_t i) const
+ {
+ return plane_point[i];
+ }
+ /// plane texture
+ inline std::string & texture()
+ {
+ return plane_texture;
+ }
/// first parameter of the general equation
- inline float a() const { return plane_normal[0]; }
+ inline float a() const
+ {
+ return plane_normal[0];
+ }
/// second parameter of the general equation
- inline float b() const { return plane_normal[1]; }
+ inline float b() const
+ {
+ return plane_normal[1];
+ }
/// third param of the general equation
- inline float c() const { return plane_normal[2]; }
+ inline float c() const
+ {
+ return plane_normal[2];
+ }
/// fourth parameter of the general equation
- inline float d() const { return pd; }
+ inline float d() const
+ {
+ return pd;
+ }
/// indidcates if this plane was generated from a detail brush
- inline bool & detail() { return plane_detail; }
+ inline bool & detail()
+ {
+ return plane_detail;
+ }
/// surface flags
- inline unsigned int & surface_flags() { return plane_surface_flags; }
-
-
+ inline unsigned int & surface_flags()
+ {
+ return plane_surface_flags;
+ }
+
+
private:
math::Vector3f plane_point[3];
math::Vector3f plane_normal;
diff --git a/src/model/primitives.cc b/src/model/primitives.cc
new file mode 100644
index 0000000..1b9d216
--- /dev/null
+++ b/src/model/primitives.cc
@@ -0,0 +1,44 @@
+/*
+ model/primitives.cc
+ This file is part of the Osirion project and is distributed under
+ the terms of the GNU General Public License version 2
+*/
+
+#include "model/primitives.h"
+
+namespace model
+{
+
+Primitives::Primitives(unsigned int material)
+{
+ primitives_material = material;
+}
+
+Primitives::~Primitives()
+{
+ // clear list of triangles
+ for (std::list<Triangle *>::iterator tris_it = primitives_triangles.begin(); tris_it != primitives_triangles.end(); tris_it++)
+ delete(*tris_it);
+ primitives_triangles.clear();
+
+ // clear list of quads
+ for (std::list<Quad *>::iterator quad_it = primitives_quads.begin(); quad_it != primitives_quads.end(); quad_it++)
+ delete(*quad_it);
+ primitives_quads.clear();
+}
+
+void Primitives::add_triangle(math::Vector3f const &v0, math::Vector3f const &v1, math::Vector3f const &v2,
+ math::Vector3f const &normal, math::Color const &color, bool detail)
+{
+ Triangle *triangle = new Triangle(v0, v1, v2, normal, color, detail);
+ primitives_triangles.push_back(triangle);
+}
+
+void Primitives::add_quad(math::Vector3f const &v0, math::Vector3f const &v1, math::Vector3f const &v2, math::Vector3f const &v3,
+ math::Vector3f const &normal, math::Color const &color, bool detail)
+{
+ Quad *quad = new Quad(v0, v1, v2, v3, normal, color, detail);
+ primitives_quads.push_back(quad);
+}
+
+}
diff --git a/src/model/primitives.h b/src/model/primitives.h
index 28da706..d11ac61 100644
--- a/src/model/primitives.h
+++ b/src/model/primitives.h
@@ -7,6 +7,8 @@
#ifndef __INCLUDED_MODEL_PRIMITIVES_H__
#define __INCLUDED_MODEL_PRIMITIVES_H__
+#include <list>
+
#include "math/vector3f.h"
#include "math/color.h"
#include "model/triangle.h"
@@ -15,28 +17,49 @@
namespace model
{
-/// a list of Triangle and Quad primitives that have to be rendered using the same material, to be parsed into fragments
+/// a list of Triangle and Quad primitives with the same material, to be parsed into fragments
class Primitives
{
public:
+ /// type definition for a list of triangles
+ typedef std::list<Triangle *> Triangles;
+
+ /// type definition for a list of quads
+ typedef std::list<Quad *> Quads;
+
Primitives(unsigned int material);
~Primitives();
-
+
/// the material to be used for these primitives
- inline unsigned int material() const { return primitives_material; }
-
+ inline unsigned int material() const
+ {
+ return primitives_material;
+ }
+
+ /// list of triangles
+ inline Triangles & triangles()
+ {
+ return primitives_triangles;
+ }
+
+ /// list of quads
+ inline Quads & quads()
+ {
+ return primitives_quads;
+ }
+
/// add a Triangle primitive
void add_triangle(math::Vector3f const &v0, math::Vector3f const &v1, math::Vector3f const &v2,
- math::Vector3f const &normal, math::Color const &color, bool detail);
-
+ math::Vector3f const &normal, math::Color const &color, bool detail);
+
/// add a Quad primitive
void add_quad(math::Vector3f const &v0, math::Vector3f const &v1, math::Vector3f const &v2, math::Vector3f const &v3,
- math::Vector3f const &normal, math::Color const &color, bool detail);
-
+ math::Vector3f const &normal, math::Color const &color, bool detail);
+
private:
- std::list<Triangle *> primitives_triangles;
- std::list<Quad *> primitives_quads;
-
+ Triangles primitives_triangles;
+ Quads primitives_quads;
+
unsigned int primitives_material;
};
diff --git a/src/model/quad.cc b/src/model/quad.cc
index e216532..0b8b208 100644
--- a/src/model/quad.cc
+++ b/src/model/quad.cc
@@ -10,19 +10,18 @@ namespace model
{
Quad::Quad(math::Vector3f const &v0, math::Vector3f const &v1, math::Vector3f const &v2, math::Vector3f const &v3,
- math::Vector3f const &normal, math::Color const &color, bool detail) :
- quad_v0(v0),
- quad_v1(v1),
- quad_v2(v2),
- quad_v3(v3),
- quad_normal(normal),
- quad_color(color)
+ math::Vector3f const &normal, math::Color const &color, bool detail) :
+ quad_v0(v0),
+ quad_v1(v1),
+ quad_v2(v2),
+ quad_v3(v3),
+ quad_normal(normal),
+ quad_color(color)
{
quad_detail = detail;
}
Quad::~Quad()
-{
-}
+{}
}
diff --git a/src/model/quad.h b/src/model/quad.h
index d2215f2..42832d0 100644
--- a/src/model/quad.h
+++ b/src/model/quad.h
@@ -19,37 +19,58 @@ class Quad
public:
/// a new quad with 4 vertices, a normal, color and a detail flag
Quad(math::Vector3f const &v0, math::Vector3f const &v1, math::Vector3f const &v2, math::Vector3f const &v3,
- math::Vector3f const &n, math::Color const & color, bool detail);
+ math::Vector3f const &normal, math::Color const & color, bool detail);
/// delete quad
~Quad();
-
+
/// normal of the quad
- inline math::Vector3f const & normal() const { return quad_normal; }
-
- /// color of the quad
- inline math::Color const & color() const { return quad_color;}
-
+ inline math::Vector3f const & normal() const
+ {
+ return quad_normal;
+ }
+
+ /// color of the quad
+ inline math::Color const & color() const
+ {
+ return quad_color;
+ }
+
/// indidcates if this quad was generated from a detail brush
- inline bool detail() const { return quad_detail; }
-
+ inline bool detail() const
+ {
+ return quad_detail;
+ }
+
/// quad vertex 0
- inline math::Vector3f & v0() { return quad_v0; }
-
+ inline math::Vector3f & v0()
+ {
+ return quad_v0;
+ }
+
/// quad vertex 1
- inline math::Vector3f & v1() { return quad_v1; }
-
+ inline math::Vector3f & v1()
+ {
+ return quad_v1;
+ }
+
/// quad vertex 2
- inline math::Vector3f & v2() { return quad_v2; }
-
+ inline math::Vector3f & v2()
+ {
+ return quad_v2;
+ }
+
/// quad vertex 3
- inline math::Vector3f & v3() { return quad_v3; }
+ inline math::Vector3f & v3()
+ {
+ return quad_v3;
+ }
private:
-
+
math::Vector3f quad_v0;
math::Vector3f quad_v1;
math::Vector3f quad_v2;
math::Vector3f quad_v3;
-
+
math::Vector3f quad_normal;
math::Color quad_color;
bool quad_detail;
diff --git a/src/model/triangle.cc b/src/model/triangle.cc
index 7c36615..807d536 100644
--- a/src/model/triangle.cc
+++ b/src/model/triangle.cc
@@ -9,19 +9,18 @@
namespace model
{
-Triangle::Triangle(math::Vector3f const &v0, math::Vector3f const &v1, math::Vector3f const &v2,
- math::Vector3f const &normal, math::Color const &color, bool detail) :
- triangle_v0(v0),
- triangle_v1(v1),
- triangle_v2(v2),
- triangle_normal(normal),
- triangle_color(color)
+Triangle::Triangle(math::Vector3f const &v0, math::Vector3f const &v1, math::Vector3f const &v2,
+ math::Vector3f const &normal, math::Color const &color, bool detail) :
+ triangle_v0(v0),
+ triangle_v1(v1),
+ triangle_v2(v2),
+ triangle_normal(normal),
+ triangle_color(color)
{
triangle_detail = detail;
}
Triangle::~Triangle()
-{
-}
+{}
}
diff --git a/src/model/triangle.h b/src/model/triangle.h
index 9d775c4..8f4a6a5 100644
--- a/src/model/triangle.h
+++ b/src/model/triangle.h
@@ -19,35 +19,51 @@ class Triangle
public:
/// a new triangle with 3 vertices, a normal, color and a detail flag
Triangle(math::Vector3f const &v0, math::Vector3f const &v1, math::Vector3f const &v2,
- math::Vector3f const &n, math::Color const & color, bool detail);
+ math::Vector3f const &normal, math::Color const & color, bool detail);
/// delete triangle
~Triangle();
-
+
/// normal of the triangle
- inline math::Vector3f const & normal() const { return triangle_normal; }
-
- /// color of the triangle
- inline math::Color const & color() const { return triangle_color;}
-
+ inline math::Vector3f const & normal() const
+ {
+ return triangle_normal;
+ }
+
+ /// color of the triangle
+ inline math::Color const & color() const
+ {
+ return triangle_color;
+ }
+
/// indidcates if this triangle was generated from a detail brush
- inline bool detail() const { return triangle_detail; }
-
+ inline bool detail() const
+ {
+ return triangle_detail;
+ }
+
/// triangle vertex 0
- inline math::Vector3f & v0() { return triangle_v0; }
-
+ inline math::Vector3f & v0()
+ {
+ return triangle_v0;
+ }
+
/// triangle vertex 1
- inline math::Vector3f & v1() { return triangle_v1; }
-
+ inline math::Vector3f & v1()
+ {
+ return triangle_v1;
+ }
+
/// triangle vertex 2
- inline math::Vector3f & v2() { return triangle_v2; }
+ inline math::Vector3f & v2()
+ {
+ return triangle_v2;
+ }
private:
-
+
math::Vector3f triangle_v0;
- /// triangle vertex 1
math::Vector3f triangle_v1;
- /// triangle vertex 2
math::Vector3f triangle_v2;
-
+
math::Vector3f triangle_normal;
math::Color triangle_color;
bool triangle_detail;
diff --git a/src/model/vertexarray.cc b/src/model/vertexarray.cc
index 6a635eb..0562bea 100644
--- a/src/model/vertexarray.cc
+++ b/src/model/vertexarray.cc
@@ -9,7 +9,8 @@
#include "model/vertexarray.h"
#include "sys/sys.h"
-namespace model {
+namespace model
+{
VertexArray *VertexArray::vertex_instance = 0 ;
@@ -24,10 +25,10 @@ VertexArray::VertexArray(size_t size)
vertex_color = (float *) malloc(vertex_size * sizeof(float));
vertex_normal = (float *) malloc(vertex_size * sizeof(float));
vertex_texture = (float *) malloc(vertex_size * sizeof(float));
-
+
con_print << "^BInitializing vertex array..." << std::endl;
con_print << " " << size << " Mb allocated" << std::endl;
-
+
clear();
}
@@ -45,46 +46,46 @@ void VertexArray::clear()
{
vertex_index = 0;
vertex_overflow = false;
-
+
memset(vertex_vertex, 0, sizeof(vertex_vertex));
memset(vertex_color, 0, sizeof(vertex_color));
memset(vertex_normal, 0, sizeof(vertex_normal));
memset(vertex_texture, 0, sizeof(vertex_texture));
-
+
add_sphere();
}
void VertexArray::add_sphere()
{
// load sphere vertices into the VertexArray
-
+
// build sin/cos table
float *sintable;
float *costable;
-
+
sintable = new float[SPHERESEGMENTS];
costable = new float[SPHERESEGMENTS];
float d = 2 * M_PI / (SPHERESEGMENTS-1);
-
+
for (int i=0; i < SPHERESEGMENTS; i++) {
- sintable[i] = sin( d * (float) i );
- costable[i] = cos ( d * (float) i );
+ sintable[i] = sin(d * (float) i);
+ costable[i] = cos(d * (float) i);
}
-
+
// draw body
math::Color white(1.0f, 1.0f, 1.0f);
math::Vector3f v;
math::Vector3f n;
float texx, texy;
-
+
int quad_count = 0;
-
+
// add sphere
for (int j=0; j < (SPHERESEGMENTS-1) / 2; j++) {
-
+
float r = sintable[j];
float r1 = sintable[j+1];
-
+
for (int i = 0; i < SPHERESEGMENTS; i++) {
v = math::Vector3f(r*costable[i], r*sintable[i], costable[j]);
n = v;
@@ -95,23 +96,23 @@ void VertexArray::add_sphere()
v = math::Vector3f(r1*costable[i], r1*sintable[i], costable[j+1]);
n = v;
- n.normalize();
+ n.normalize();
texx = (float)i/(float)(SPHERESEGMENTS-1);
texy = -costable[j+1]/2 + 0.5f;
add_vertex(v, n, white, texx, texy);
-
+
quad_count++;
}
quad_count--;
}
-
+
// add inside-out sphere
for (int j=0; j < (SPHERESEGMENTS-1) / 2; j++) {
-
+
float r = sintable[j];
float r1 = sintable[j+1];
-
+
for (int i = SPHERESEGMENTS -1 ; i >= 0; i--) {
v = math::Vector3f(r*costable[i], r*sintable[i], costable[j]);
@@ -123,14 +124,14 @@ void VertexArray::add_sphere()
v = math::Vector3f(r1*costable[i], r1*sintable[i], costable[j+1]);
n = v;
- n.normalize();
+ n.normalize();
texx = 1-(float)i/(float)(SPHERESEGMENTS-1);
texy = -costable[j+1]/2 + 0.5f;
add_vertex(v, n, white, texx, texy);
}
}
-
+
delete[] sintable;
delete[] costable;
}
@@ -144,23 +145,23 @@ size_t VertexArray::add_vertex(math::Vector3f const &v, math::Vector3f const &n,
}
return 0;
}
-
+
for (int i = 0; i < 3; i ++) {
vertex_vertex[vertex_index+i] = v[i];
vertex_normal[vertex_index+i] = n[i];
}
-
+
vertex_color[vertex_index] = color.r;
vertex_color[vertex_index+1] = color.g;
vertex_color[vertex_index+2] = color.b;
-
+
vertex_texture[vertex_index] = tex_x;
vertex_texture[vertex_index+1] = tex_y;
// reserved
vertex_texture[vertex_index+2] = 0;
-
+
vertex_index += 3;
-
+
return 1;
}
diff --git a/src/model/vertexarray.h b/src/model/vertexarray.h
index 6330d8c..37f2be9 100644
--- a/src/model/vertexarray.h
+++ b/src/model/vertexarray.h
@@ -10,7 +10,8 @@
#include "math/color.h"
#include "math/vector3f.h"
-namespace model {
+namespace model
+{
const int SPHERESEGMENTS=65;
@@ -23,40 +24,64 @@ public:
/// create a new VertexArray with size in Mb
VertexArray(size_t size);
~VertexArray();
-
+
void clear();
-
+
size_t add_vertex(math::Vector3f const &v, math::Vector3f const &n, math::Color const &color, float tex_x=0.0f, float tex_y=0.0f);
-
- inline float *vertex() { return vertex_vertex; }
- inline float *color() { return vertex_color; }
- inline float *normal() { return vertex_normal; }
- inline float *texture() { return vertex_texture; }
-
- inline bool overflow() const { return vertex_overflow; }
-
+
+ inline float *vertex()
+ {
+ return vertex_vertex;
+ }
+ inline float *color()
+ {
+ return vertex_color;
+ }
+ inline float *normal()
+ {
+ return vertex_normal;
+ }
+ inline float *texture()
+ {
+ return vertex_texture;
+ }
+
+ inline bool overflow() const
+ {
+ return vertex_overflow;
+ }
+
/// number of allocated floats
- inline size_t size() const { return vertex_size; }
-
+ inline size_t size() const
+ {
+ return vertex_size;
+ }
+
/// index to the top of the stack
- inline size_t index() const { return vertex_index; }
-
- static inline VertexArray *instance() { return vertex_instance; }
-
+ inline size_t index() const
+ {
+ return vertex_index;
+ }
+
+ static inline VertexArray *instance()
+ {
+ return vertex_instance;
+ }
+
private:
/// model vertices
float *vertex_vertex;
float *vertex_color;
float *vertex_normal;
float *vertex_texture;
-
+
size_t vertex_index;
size_t vertex_size;
-
+
void add_sphere();
-
+
static VertexArray *vertex_instance;
-
+
bool vertex_overflow;
};
diff --git a/src/render/draw.cc b/src/render/draw.cc
index 17dbdda..54a56a0 100644
--- a/src/render/draw.cc
+++ b/src/render/draw.cc
@@ -8,6 +8,8 @@
#include <iomanip>
#include "core/core.h"
+#include "model/fragment.h"
+#include "model/material.h"
#include "model/model.h"
#include "render/render.h"
#include "render/textures.h"
@@ -245,50 +247,91 @@ void draw_entity_axis(core::Entity *entity)
gl::end();
}
-/* ----- Entity models --------------------------------------------- */
+/* ----- model fragments ------------------------------------------- */
-void draw_model_vertex(core::Entity *entity)
+void draw_fragment(model::Fragment *fragment, bool draw_details)
{
- size_t count = entity->model()->vertex_structural();
- if (entity->state()->detailvisible())
- count += entity->model()->vertex_detail();
-
- // draw model vertices
- if (count) {
- size_t index = entity->model()->first_vertex();
- glDrawArrays(gl::Triangles, index, count);
- Stats::tris += count/3;
+ size_t index = fragment->index();
+
+ size_t vertex_count = fragment->structural_size();
+ if (draw_details)
+ vertex_count += fragment->detail_size();
+
+ switch (fragment->type()) {
+ case model::Fragment::Triangles:
+ glDrawArrays(gl::Triangles, index, vertex_count);
+ Stats::tris += vertex_count / 3;
+ break;
+
+ case model::Fragment::Quads:
+ glDrawArrays(gl::Quads, index, vertex_count);
+ Stats::quads += vertex_count / 4;
+ break;
}
}
-void draw_model_lvertex(core::Entity *entity)
+void draw_model_fragments(core::Entity *entity)
{
- size_t count = entity->model()->lvertex_structural();
- if (entity->state()->detailvisible())
- count += entity->model()->lvertex_detail();
-
- // draw model lvertices
- if (count) {
- gl::disable(GL_LIGHTING);
- size_t index = entity->model()->first_lvertex();
- glDrawArrays(gl::Triangles, index, count);
- Stats::tris += count/3;
+ using namespace model;
+
+ Model *model = entity->model();
+ if (!model)
+ return;
+
+ // default material, lighted and geometry color
+ unsigned int material = Material::None;
+
+ bool use_color_array = true; // glEnableClientState(GL_COLOR_ARRAY) is set
+ bool use_light = true; // gl::disable(GL_LIGHTING) is set
+
+ for (Model::Fragments::iterator fit = model->fragments().begin(); fit != model->fragments().end(); fit++) {
+
+ Fragment *fragment = (*fit);
+
+ if (fragment->material() != material) {
+ material = fragment->material();
+
+ if (material & Material::Tertiary) {
+ if (use_color_array) {
+ use_color_array = false;
+ glDisableClientState(GL_COLOR_ARRAY);
+ }
+ // FIXME Primary, Secondary Tertiary color
+ math::Color color(entity->color());
+
+ if (material & Material::Dark)
+ color *= 0.5f;
+ gl::color(color);
+
+ } else {
+ if (!use_color_array) {
+ glEnableClientState(GL_COLOR_ARRAY);
+ use_color_array = true;
+ }
+ }
+
+ if (material & Material::Light) {
+ if (use_light) {
+ gl::disable(GL_LIGHTING);
+ use_light = false;
+ }
+ } else {
+ if (!use_light) {
+ gl::enable(GL_LIGHTING);
+ use_light = true;
+ }
+ }
+ }
+
+ draw_fragment(fragment, entity->state()->detailvisible());
+ }
+
+ if (!use_light) {
gl::enable(GL_LIGHTING);
}
-}
-void draw_model_evertex(core::Entity *entity)
-{
- size_t count = entity->model()->evertex_structural();
- if (entity->state()->detailvisible())
- count += entity->model()->evertex_detail();
-
- // draw model evertices
- if (count) {
- size_t index = entity->model()->first_evertex();
- render::gl::color(entity->color());
- glDrawArrays(gl::Triangles, index, count);
- Stats::tris += count/3;
+ if (!use_color_array) {
+ glEnableClientState(GL_COLOR_ARRAY);
}
}
@@ -298,6 +341,8 @@ void draw_model_evertex(core::Entity *entity)
/* calculate entity visibility */
void pass_prepare(float seconds)
{
+ using namespace model;
+
// reset light state
gl::disable(GL_LIGHT1);
@@ -317,7 +362,7 @@ void pass_prepare(float seconds)
// load entity models and light flare textures
if (!entity->model() && entity->modelname().size()) {
- entity->entity_model = model::Model::load(entity->modelname());
+ entity->entity_model = Model::load(entity->modelname());
if (!entity->model()) {
entity->entity_modelname.clear();
@@ -326,8 +371,8 @@ void pass_prepare(float seconds)
// set entity radius to model radius
entity->entity_radius = entity->entity_model->radius();
- for (std::list<model::Light *>::iterator lit = entity->model()->model_light.begin(); lit != entity->model()->model_light.end(); lit++) {
- model::Light *light = (*lit);
+ for (Model::Lights::iterator lit = entity->model()->lights().begin(); lit != entity->model()->lights().end(); lit++) {
+ Light *light = (*lit);
// load light texture
// FIXME optimize
@@ -336,8 +381,8 @@ void pass_prepare(float seconds)
light->render_texture = Textures::load(flarename.str());
}
- for(std::list<model::Engine*>::iterator eit = entity->model()->model_engine.begin(); eit != entity->model()->model_engine.end(); eit++) {
- model::Engine *engine = (*eit);
+ for(Model::Engines::iterator eit = entity->model()->engines().begin(); eit != entity->model()->engines().end(); eit++) {
+ Engine *engine = (*eit);
if (!engine->flare()) engine->engine_flare = 1;
@@ -348,8 +393,8 @@ void pass_prepare(float seconds)
engine->render_texture = Textures::load(flarename.str());
}
- for (std::list<model::Flare *>::iterator flit = entity->model()->model_flare.begin(); flit != entity->model()->model_flare.end(); flit++) {
- model::Flare *flare = (*flit);
+ for (Model::Flares::iterator flit = entity->model()->flares().begin(); flit != entity->model()->flares().end(); flit++) {
+ Flare *flare = (*flit);
// load flare texture
// FIXME optimize
@@ -530,40 +575,19 @@ void draw_pass_default()
}
}
-/* Draw model vertices*/
-void draw_pass_model_vertex()
-{
- std::map<unsigned int, core::Entity *>::iterator it;
- for (it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) {
-
- core::Entity *entity = (*it).second;
- if (entity->model() && entity->state()->visible()) {
- gl::push();
- gl::translate(entity->state()->location());
- gl::multmatrix(entity->state()->axis());
-
- draw_model_vertex(entity);
- draw_model_lvertex(entity);
-
- gl::pop();
- }
- }
-}
-
-/* Draw entites with model evertices */
-void draw_pass_model_evertex()
+/* draw model geometry fragments */
+void draw_pass_model_fragments()
{
std::map<unsigned int, core::Entity *>::iterator it;
for (it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) {
core::Entity *entity = (*it).second;
-
if (entity->model() && entity->state()->visible()) {
gl::push();
gl::translate(entity->state()->location());
gl::multmatrix(entity->state()->axis());
- draw_model_evertex(entity);
+ draw_model_fragments(entity);
gl::pop();
}
@@ -587,7 +611,7 @@ void draw_pass_model_fx()
if (entity->model() && entity->state()->detailvisible()) {
// draw model lights
- for (std::list<model::Light *>::iterator lit = entity->model()->model_light.begin(); lit != entity->model()->model_light.end(); lit++) {
+ for (model::Model::Lights::iterator lit = entity->model()->lights().begin(); lit != entity->model()->lights().end(); lit++) {
// strobe frequency
t = 1.0f;
@@ -630,7 +654,7 @@ void draw_pass_model_fx()
}
// draw flares
- for (std::list<model::Flare *>::iterator flit = entity->model()->model_flare.begin(); flit != entity->model()->model_flare.end(); flit++) {
+ for (model::Model::Flares::iterator flit = entity->model()->flares().begin(); flit != entity->model()->flares().end(); flit++) {
model::Flare *flare = (*flit);
@@ -681,11 +705,11 @@ void draw_pass_model_fx()
}
// draw model engines for Controlable entities
- if (entity->type() == core::Entity::Controlable && entity->model()->model_engine.size()) {
+ if (entity->type() == core::Entity::Controlable && entity->model()->engines().size()) {
float u = static_cast<core::EntityControlable *>(entity)->thrust();
- for(std::list<model::Engine*>::iterator eit = entity->model()->model_engine.begin(); eit != entity->model()->model_engine.end(); eit++) {
+ for(model::Model::Engines::iterator eit = entity->model()->engines().begin(); eit != entity->model()->engines().end(); eit++) {
model::Engine *engine = (*eit);
@@ -857,17 +881,14 @@ void draw(float seconds)
glEnableClientState(GL_COLOR_ARRAY);
- draw_pass_model_vertex(); // draw entities with model
+ draw_pass_model_fragments();
glDisableClientState(GL_COLOR_ARRAY);
-
- draw_pass_model_evertex(); // draw entities with model, vertices with entity color
-
- gl::enable(GL_BLEND);
gl::disable(GL_LIGHTING);
-
+
+ gl::enable(GL_BLEND);
+
draw_pass_spacegrid(); // draw the blue spacegrid
-
Dust::draw(); // draw spacedust
draw_pass_model_fx(); // draw entity lights and engines