Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/model/Makefile.am8
-rw-r--r--src/model/fragment.cc34
-rw-r--r--src/model/fragment.h51
-rw-r--r--src/model/map.cc668
-rw-r--r--src/model/map.h114
-rw-r--r--src/model/mapfile.cc562
-rw-r--r--src/model/mapfile.h133
-rw-r--r--src/model/material.h21
-rw-r--r--src/model/primitives.h44
-rw-r--r--src/model/quad.cc28
-rw-r--r--src/model/quad.h60
-rw-r--r--src/model/triangle.cc (renamed from src/model/tirangle.cc)12
-rw-r--r--src/model/triangle.h17
-rw-r--r--src/model/vertexarray.cc66
-rw-r--r--src/model/vertexarray.h12
-rw-r--r--src/model/vertexdata.h0
16 files changed, 1032 insertions, 798 deletions
diff --git a/src/model/Makefile.am b/src/model/Makefile.am
index ba8c38b..4a5e4e6 100644
--- a/src/model/Makefile.am
+++ b/src/model/Makefile.am
@@ -1,11 +1,11 @@
METASOURCES = AUTO
-libmodel_la_SOURCES = engine.cc flare.cc light.cc map.cc mapfile.cc model.cc \
- plane.cc tirangle.cc vertexarray.cc
+libmodel_la_SOURCES = engine.cc flare.cc fragment.cc light.cc map.cc model.cc \
+ plane.cc quad.cc triangle.cc vertexarray.cc
libmodel_la_LDFLAGS = -avoid-version -no-undefined -lm
noinst_LTLIBRARIES = libmodel.la
-noinst_HEADERS = engine.h flare.h light.h map.h mapfile.h model.h plane.h \
- triangle.h vertexarray.h
+noinst_HEADERS = engine.h flare.h fragment.h light.h map.h material.h model.h \
+ plane.h primitives.h quad.h triangle.h vertexarray.h
INCLUDES = -I$(top_srcdir)/src
diff --git a/src/model/fragment.cc b/src/model/fragment.cc
new file mode 100644
index 0000000..38990d5
--- /dev/null
+++ b/src/model/fragment.cc
@@ -0,0 +1,34 @@
+/*
+ model/fragment.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/fragment.h"
+#include "model/vertexarray.h"
+
+namespace model
+{
+
+Fragment::Fragment(Type type, unsigned int material)
+{
+ fragment_type = type;
+ fragment_start = VertexArray::instance()->index();
+ fragment_material = material;
+ fragment_structural_size = 0;
+ fragment_detail_size = 0;
+}
+
+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;
+ return n;
+}
+
+}
+
diff --git a/src/model/fragment.h b/src/model/fragment.h
new file mode 100644
index 0000000..ba4eaf9
--- /dev/null
+++ b/src/model/fragment.h
@@ -0,0 +1,51 @@
+/*
+ model/fragment.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_FRAGMENT_H__
+#define __INCLUDED_MODEL_FRAGMENT_H__
+
+#include "math/vector3f.h"
+#include "math/color.h"
+
+namespace model
+{
+
+/// a fragment of a model, a pointer into a continuues part of the VertexArray containt Tris or Quad data
+class Fragment
+{
+public:
+ /// fragment primitive type: triangles or quads
+ enum Type {Triangles, Quads};
+
+ /// create a new fragment
+ 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);
+
+ /// VertexArray index of the start of the fragment
+ inline size_t start() const { return fragment_start; }
+
+ /// number of structural vertices in the fragment
+ 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; }
+
+ /// material flags
+ inline unsigned int material() { return fragment_material; }
+
+private:
+ Type fragment_type;
+ size_t fragment_start;
+ size_t fragment_structural_size;
+ size_t fragment_detail_size;
+ unsigned int fragment_material;
+};
+
+}
+
+#endif // __INCLUDED_MODEL_FRAGMENT_H__
diff --git a/src/model/map.cc b/src/model/map.cc
index 192814c..220c723 100644
--- a/src/model/map.cc
+++ b/src/model/map.cc
@@ -1,17 +1,21 @@
/*
- model/map.cc
+ filesystem/map.cc
This file is part of the Osirion project and is distributed under
the terms of the GNU General Public License version 2
*/
+#include "filesystem/filesystem.h"
+#include "math/mathlib.h"
#include "model/engine.h"
#include "model/light.h"
#include "model/map.h"
-#include "model/mapfile.h"
+#include "model/material.h"
#include "model/vertexarray.h"
-
#include "sys/sys.h"
+#include <sstream>
+#include <string>
+
namespace model {
// function to test spawnflags
@@ -19,10 +23,13 @@ inline bool spawnflag_isset(unsigned int spawnflags, unsigned int flag) {
return ((spawnflags & flag) == flag);
}
+const float MAX_BOUNDS = 16384;
+const float MIN_DELTA = 10e-10;
+
Model * Map::load(std::string const &name)
{
// open the .map file
- MapFile mapfile;
+ Map mapfile;
if (!mapfile.open(name)) {
return 0;
@@ -157,108 +164,680 @@ Model * Map::load(std::string const &name)
mapfile.close();
+ mapfile.load_fragments(model);
+
+ return model;
+}
+
+Map::Map() {}
+
+Map::~Map() {}
+
+bool Map::open(std::string const & name) {
+
+ last_read_was_classname = false;
+ last_read_was_key = false;
+ key_current = "";
+ value_current = "";
+ classname_current = "";
+ line_number = 0;
+ parse_level = 0;
+ brushes = 0;
+
+ mapfile_name.assign("maps/");
+ mapfile_name.append(name);
+ mapfile_name.append(".map");
+
+ filesystem::File *f = filesystem::open(mapfile_name.c_str());
+ if (!f) {
+ con_warn << "Could not open " << mapfile_name << std::endl;
+ return false;
+ }
+
+ std::string fn = f->path();
+ fn.append(f->name());
+ filesystem::close(f);
+
+ mapfile_ifs.open(fn.c_str());
+ if (!mapfile_ifs.is_open()) {
+ con_warn << "Could not stream " << fn << "!\n";
+ return false;
+ }
+
+ return true;
+}
+
+
+bool Map::got_classname() const {
+ return last_read_was_classname;
+}
+
+bool Map::got_classname(const char * classnamelabel) const {
+ return (last_read_was_classname && (classname_current.compare(classnamelabel) == 0));
+}
+
+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);
+ std::string firstword;
+
+ 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
+ if (VertexArray::instance()) {
+ // for every face
+ 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++;
+ }
+ 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);
+ classname_current.erase(classname_current.size()-1, 1);
+ last_read_was_classname = true;
+ } else {
+ 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()) {
+ Vector3f p1, p2, p3;
+ std::string tmp;
+ std::string texture;
+ int n = 0;
+
+ linestream >> p1;
+ linestream >> tmp; // )
+ linestream >> tmp; // (
+ linestream >> p2;
+ linestream >> tmp; // )
+ linestream >> tmp; // (
+ linestream >> p3;
+ linestream >> tmp; // )
+ linestream >> texture;
+
+ // 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();
+ }
+ }
+ }
+ } else {
+
+ return false;
+ }
+
+ return true;
+}
+
+void Map::make_brushface(Plane *face)
+{
+ using math::Vector3f;
+
+ // ignore caulk
+ if (face->texture() == "common/caulk") {
+ return;
+ }
+
+ // FIXME clip should be parsed as collision blocks
+ if (face->texture() == "common/clip") {
+ return;
+ }
+
+ // using suggestions from
+ // http://www.flipcode.com/archives/Level_Editing.shtml
+
+ // vertex list
+ std::vector<math::Vector3f *> vl;
+
+ // calculate initial vertices on the bounding box
+
+ // 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));
+ vl.push_back(new math::Vector3f(0, MAX_BOUNDS, MAX_BOUNDS));
+ vl.push_back(new math::Vector3f(0, MAX_BOUNDS, -MAX_BOUNDS));
+ } else {
+ vl.push_back(new math::Vector3f(0, MAX_BOUNDS, -MAX_BOUNDS));
+ vl.push_back(new math::Vector3f(0, MAX_BOUNDS, MAX_BOUNDS));
+ vl.push_back(new math::Vector3f(0, -MAX_BOUNDS, MAX_BOUNDS));
+ vl.push_back(new math::Vector3f(0, -MAX_BOUNDS, -MAX_BOUNDS));
+ }
+ // calculate the x coordinate of each face vertex
+ for (std::vector<Vector3f *>::iterator it = vl.begin(); it != vl.end(); it++) {
+ (*it)->x = (-face->d() -
+ face->normal().z * (*it)->z -
+ face->normal().y * (*it)->y) /
+ face->normal().x;
+ }
+ }
+
+ // 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));
+ vl.push_back(new Vector3f(-MAX_BOUNDS, 0, MAX_BOUNDS));
+ vl.push_back(new Vector3f(-MAX_BOUNDS, 0, -MAX_BOUNDS));
+ } else {
+ vl.push_back(new Vector3f(-MAX_BOUNDS, 0, -MAX_BOUNDS));
+ vl.push_back(new Vector3f(-MAX_BOUNDS, 0, MAX_BOUNDS));
+ vl.push_back(new Vector3f(MAX_BOUNDS, 0, MAX_BOUNDS));
+ vl.push_back(new Vector3f(MAX_BOUNDS, 0, -MAX_BOUNDS));
+ }
+
+ // calculate the x coordinate of each face vertex
+ for (std::vector<Vector3f *>::iterator it = vl.begin(); it != vl.end(); it++) {
+ (*it)->y = (-face->d() -
+ face->normal().z * (*it)->z -
+ face->normal().x * (*it)->x) /
+ face->normal().y;
+ }
+ }
+
+ // 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));
+ vl.push_back(new Vector3f(MAX_BOUNDS, MAX_BOUNDS, 0));
+ vl.push_back(new Vector3f(MAX_BOUNDS, -MAX_BOUNDS, 0));
+ } else {
+ vl.push_back(new Vector3f(MAX_BOUNDS, -MAX_BOUNDS, 0));
+ vl.push_back(new Vector3f(MAX_BOUNDS, MAX_BOUNDS, 0));
+ vl.push_back(new Vector3f(-MAX_BOUNDS, MAX_BOUNDS, 0));
+ vl.push_back(new Vector3f(-MAX_BOUNDS, -MAX_BOUNDS, 0));
+ }
+
+ // calculate the x coordinate of each face vertex
+ for (std::vector<Vector3f *>::iterator it = vl.begin(); it != vl.end(); it++) {
+ (*it)->z = (-face->d() -
+ face->normal().x * (*it)->x -
+ face->normal().y * (*it)->y) /
+ face->normal().z;
+ }
+ }
+
+
+ // intersect the face with every plane
+ for (std::vector<Plane *>::iterator pit = planes.begin(); pit != planes.end(); pit++) {
+ Plane *plane = (*pit);
+ if (plane == face) {
+ continue;
+ }
+
+ Vector3f fn = crossproduct(face->point(1)-face->point(0), face->point(2)-face->point(0));
+ Vector3f pn = crossproduct(plane->point(1)-plane->point(0), plane->point(2)-plane->point(0));
+
+ Vector3f t = crossproduct(fn, pn);
+ if ((t.x == 0) && (t.y == 0) && (t.z == 0)) {
+ continue;
+ }
+
+ // intersect face with plane
+ 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);
+ } else {
+ next = *vl.front();
+ }
+
+ Vector3f prev;
+ if (i > 0) {
+ prev = *vl.at(i-1);
+ } else {
+ prev = *vl.back();
+ }
+
+ if ((v.x*plane->normal().x + v.y*plane->normal().y + v.z*plane->normal().z +plane->d()) < MIN_DELTA) {
+
+ // find current
+ std::vector<Vector3f *>::iterator vit = vl.begin();
+ while ((*vit) != vl.at(i)) {
+ vit++;
+ }
+
+ // check if prev - v intersects with plane
+ if ((prev.x*plane->normal().x + prev.y*plane->normal().y + prev.z*plane->normal().z + plane->d()) > -MIN_DELTA) {
+
+ // calculate intersection
+ float t1 = -plane->normal().x * prev.x - plane->normal().y * prev.y - plane->normal().z * prev.z -plane->d();
+ 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) {
+ *s = v;
+ } else {
+ for (int j = 0; j < 3; j++)
+ (*s)[j] = prev [j] + t1 * (v[j] - prev[j]) / t2;
+ }
+
+ vit = vl.insert(vit,s);
+ vit++;
+ i++;
+ }
+
+ // 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 +
+ plane->normal().y * next.y - plane->normal().y * v.y +
+ plane->normal().z * next.z - plane->normal().z * v.z);
+ //cout << "next t2 " << t2 << std::endl;
+ Vector3f *s = new Vector3f;
+
+ if (t2 == 0) {
+ *s = v;
+ } else {
+ for (int j = 0; j < 3; j++)
+ (*s)[j] = v [j] + t1 * (next[j] - v[j]) / t2;
+ }
+
+ vit = vl.insert(vit,s);
+ vit++;
+ i++;
+ }
+
+ // erase
+ delete *vit;
+ vl.erase(vit);
+ i--;
+ }
+
+ }
+ }
+
+ if (vl.size() > 2) {
+
+ // 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") {
+ color.assign(1.0f);
+ } else if (face->texture() == "colors/grey90") {
+ color.assign(0.9f);
+ } else if (face->texture() == "colors/grey75") {
+ color.assign(0.75f);
+ } else if (face->texture() == "colors/grey50") {
+ color.assign(0.5f);
+ } else if (face->texture() == "colors/grey25") {
+ color.assign(0.25f);
+ } else if (face->texture() == "colors/black") {
+ color.assign(0.0f);
+ } else if (face->texture() == "colors/red") {
+ color.assign(1, 0, 0);
+ } else if (face->texture() == "colors/green") {
+ color.assign(0, 1, 0);
+ } else if (face->texture() == "colors/blue") {
+ color.assign(0, 0, 1);
+
+ } else if ((face->texture() == "common/entity") || (face->texture() == "common/primary")) {
+ material |= Material::Primary;
+ } else if (face->texture() == "common/primary_dark") {
+ material |= Material::Primary;
+ material |= Material::Dark;
+
+ } else if (face->texture() == "common/secundary") {
+ material |= Material::Secondary;
+ } else if (face->texture() == "common/secundary_dark") {
+ material |= Material::Secondary;
+ material |= Material::Dark;
+
+ } else if (face->texture() == "common/tertiary") {
+ material |= Material::Tertiary;
+ } else if (face->texture() == "common/tertiary_dark") {
+ material |= Material::Tertiary;
+ material |= Material::Dark;
+ }
+
+ // translate surface flags to materials
+
+ // surface flag 1 light
+ if ((face->surface_flags() & 1) == 1) {
+ material |= Material::Light;
+ }
+
+ // calculate bounding box
+ 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 ) {
+ std::vector<Vector3f *>::iterator v0 = vl.begin();
+ std::vector<Vector3f *>::reverse_iterator vn = vl.rbegin();
+ std::vector<Vector3f *>::reverse_iterator vn1 = vl.rbegin();
+ ++vn1;
+
+ 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);
+ vl.pop_back();
+ }
+ } else {
+ con_debug << "Unresolved face!\n";
+ }
+
+ // clean up the vertex list
+ for (std::vector<Vector3f *>::iterator it = vl.begin(); it != vl.end(); it++) {
+ delete(*it);
+ }
+
+ vl.clear();
+}
+
+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 {
+ return false;
+ }
+}
+
+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();
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+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;
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool Map::got_key_int(const char * keylabel, unsigned int & u)
+{
+ if (last_read_was_key && (key_current.compare(keylabel) == 0 )) {
+ std::istringstream is(value_current);
+ if (!(is >> u)) {
+ u = 0;
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+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 )) {
+ std::istringstream is(value_current);
+ if ((is >> f)) {
+ f = math::degrees360f(f);
+ } else {
+ f = 0;
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+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;
+ }
+ color = math::Color(r, g, b);
+ } else {
+ color = math::Color();
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void Map::close()
+{
+ mapfile_ifs.close();
+}
+
+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 (VertexArray::instance() && !VertexArray::instance()->overflow() && ((mapfile.class_tris.size() + mapfile.class_etris.size() + mapfile.class_ltris.size()) > 0)) {
+ if ((class_tris.size() + class_etris.size() + class_ltris.size()) > 0) {
- math::Vector3f center = (mapfile.class_minbbox + mapfile.class_maxbbox) / 2;
+ math::Vector3f center = (class_minbbox + class_maxbbox) / 2;
- model->model_minbbox = mapfile.class_minbbox - center;
- model->model_maxbbox = mapfile.class_maxbbox - center;
+ 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 = mapfile.class_tris.begin(); it != mapfile.class_tris.end() && !VertexArray::instance()->overflow(); it++) {
+ 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->triangle_v0-center, triangle->normal(), triangle->color() );
- count += VertexArray::instance()->add_vertex(triangle->triangle_v1-center, triangle->normal(), triangle->color() );
- count += VertexArray::instance()->add_vertex(triangle->triangle_v2-center, triangle->normal(), triangle->color() );
+ 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;
}
}
// detail triangles
- for (std::list<Triangle *>::iterator it = mapfile.class_tris.begin(); it != mapfile.class_tris.end() && !VertexArray::instance()->overflow(); it++) {
+ 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->triangle_v0-center, triangle->normal(), triangle->color() );
- count += VertexArray::instance()->add_vertex(triangle->triangle_v1-center, triangle->normal(), triangle->color() );
- count += VertexArray::instance()->add_vertex(triangle->triangle_v2-center, triangle->normal(), triangle->color() );
+ 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;
}
delete triangle;
}
- mapfile.class_tris.clear();
+ class_tris.clear();
// structural etriangles
model->model_first_evertex = VertexArray::instance()->index()/3;
- for (std::list<Triangle *>::iterator it = mapfile.class_etris.begin(); it != mapfile.class_etris.end() && !VertexArray::instance()->overflow(); it++) {
+ 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->triangle_v0-center, triangle->normal(), triangle->color() );
- count += VertexArray::instance()->add_vertex(triangle->triangle_v1-center, triangle->normal(), triangle->color() );
- count += VertexArray::instance()->add_vertex(triangle->triangle_v2-center, triangle->normal(), triangle->color() );
+ 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;
}
}
// detail etriangles
- for (std::list<Triangle *>::iterator it = mapfile.class_etris.begin(); it != mapfile.class_etris.end() && !VertexArray::instance()->overflow(); it++) {
+ 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->triangle_v0-center, triangle->normal(), triangle->color() );
- count += VertexArray::instance()->add_vertex(triangle->triangle_v1-center, triangle->normal(), triangle->color() );
- count += VertexArray::instance()->add_vertex(triangle->triangle_v2-center, triangle->normal(), triangle->color() );
+ 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;
}
delete triangle;
}
- mapfile.class_etris.clear();
+ class_etris.clear();
// structural ltriangles
model->model_first_lvertex = VertexArray::instance()->index()/3;
- for (std::list<Triangle *>::iterator it = mapfile.class_ltris.begin(); it != mapfile.class_ltris.end() && !VertexArray::instance()->overflow(); it++) {
+ 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->triangle_v0-center, triangle->normal(), triangle->color() );
- count += VertexArray::instance()->add_vertex(triangle->triangle_v1-center, triangle->normal(), triangle->color() );
- count += VertexArray::instance()->add_vertex(triangle->triangle_v2-center, triangle->normal(), triangle->color() );
+ 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;
}
}
// detail ltriangles
- for (std::list<Triangle *>::iterator it = mapfile.class_ltris.begin(); it != mapfile.class_ltris.end() && !VertexArray::instance()->overflow(); it++) {
+ 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->triangle_v0-center, triangle->normal(), triangle->color() );
- count += VertexArray::instance()->add_vertex(triangle->triangle_v1-center, triangle->normal(), triangle->color() );
- count += VertexArray::instance()->add_vertex(triangle->triangle_v2-center, triangle->normal(), triangle->color() );
+ 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;
}
delete triangle;
}
- mapfile.class_ltris.clear();
+ class_ltris.clear();
- // reposition light and engines
- for (std::list<Engine *>::iterator eit = model->model_engine.begin(); eit != model->model_engine.end(); eit++) {
- (*eit)->engine_location -= center;
- }
-
+ // 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;
}
@@ -267,12 +846,13 @@ Model * Map::load(std::string const &name)
(*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 " << mapfile.brushes << " brushes " << model->tris()
- << " tris (" << model->details() << " detail)" << std::endl;
-
- return model;
+ con_print << " maps/" << model->name() << ".map " << brushes << " brushes " << model->tris() << " tris (" << model->details() << " detail)" << std::endl;
}
}
+
diff --git a/src/model/map.h b/src/model/map.h
index 2db4075..e5b5308 100644
--- a/src/model/map.h
+++ b/src/model/map.h
@@ -7,19 +7,125 @@
#ifndef __INCLUDED_MODEL_MAP_H__
#define __INCLUDED_MODEL_MAP_H__
+#include <fstream>
+#include <string>
+#include <vector>
+
#include "model/model.h"
+#include "model/plane.h"
+#include "model/triangle.h"
namespace model {
-/// class to load .map files into models
+/// class to parse the .map file structure and load geometry data into a model
class Map {
public:
- /// load a MAP file from disk
- /** @param name name of the model to be loaded
+ /// 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:
+ Map();
+ ~Map();
+
+ /// 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 {
+ return classname_current;
+ }
+
+ /// current key
+ inline std::string key() const {
+ return key_current;
+ }
+
+ /// current value
+ 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 {
+ 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 {
+ return line_number;
+ }
+
+ /// return true of the ini file is open for reading
+ inline bool is_open() { return mapfile_ifs.is_open(); }
+
+ /// current filename
+ 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
+ void load_fragments(Model *model);
+
+ /// 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 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;
};
}
diff --git a/src/model/mapfile.cc b/src/model/mapfile.cc
deleted file mode 100644
index 585f13b..0000000
--- a/src/model/mapfile.cc
+++ /dev/null
@@ -1,562 +0,0 @@
-/*
- filesystem/mapfile.cc
- This file is part of the Osirion project and is distributed under
- the terms of the GNU General Public License version 2
-*/
-
-#include "filesystem/filesystem.h"
-#include "math/mathlib.h"
-#include "model/mapfile.h"
-#include "model/vertexarray.h"
-#include "sys/sys.h"
-
-#include <sstream>
-#include <string>
-
-namespace model {
-
-const float MAX_BOUNDS = 16384;
-const float MIN_DELTA = 10e-10;
-
-MapFile::MapFile() {}
-
-MapFile::~MapFile() {}
-
-bool MapFile::open(std::string const & name) {
-
- last_read_was_classname = false;
- last_read_was_key = false;
- key_current = "";
- value_current = "";
- classname_current = "";
- line_number = 0;
- parse_level = 0;
- brushes = 0;
-
- mapfile_name.assign("maps/");
- mapfile_name.append(name);
- mapfile_name.append(".map");
-
- filesystem::File *f = filesystem::open(mapfile_name.c_str());
- if (!f) {
- con_warn << "Could not open " << mapfile_name << std::endl;
- return false;
- }
-
- std::string fn = f->path();
- fn.append(f->name());
- filesystem::close(f);
-
- mapfile_ifs.open(fn.c_str());
- if (!mapfile_ifs.is_open()) {
- con_warn << "Could not stream " << fn << "!\n";
- return false;
- }
-
- return true;
-}
-
-
-bool MapFile::got_classname() const {
- return last_read_was_classname;
-}
-
-bool MapFile::got_classname(const char * classnamelabel) const {
- return (last_read_was_classname && (classname_current.compare(classnamelabel) == 0));
-}
-
-bool MapFile::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);
- std::string firstword;
-
- 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
- if (VertexArray::instance()) {
- // for every face
- 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++;
- }
- 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);
- classname_current.erase(classname_current.size()-1, 1);
- last_read_was_classname = true;
- } else {
- 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()) {
- Vector3f p1, p2, p3;
- std::string tmp;
- std::string texture;
- int n = 0;
-
- linestream >> p1;
- linestream >> tmp; // )
- linestream >> tmp; // (
- linestream >> p2;
- linestream >> tmp; // )
- linestream >> tmp; // (
- linestream >> p3;
- linestream >> tmp; // )
- linestream >> texture;
-
- // 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();
- }
- }
- }
- } else {
-
- return false;
- }
-
- return true;
-}
-
-void MapFile::make_brushface(Plane *face)
-{
- using math::Vector3f;
-
- // ignore caulk
- if (face->texture() == "common/caulk") {
- return;
- }
-
- // FIXME clip should be parsed as collision blocks
- if (face->texture() == "common/clip") {
- return;
- }
-
- // using suggestions from
- // http://www.flipcode.com/archives/Level_Editing.shtml
-
- // vertex list
- std::vector<math::Vector3f *> vl;
-
- // calculate initial vertices on the bounding box
-
- // 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));
- vl.push_back(new math::Vector3f(0, MAX_BOUNDS, MAX_BOUNDS));
- vl.push_back(new math::Vector3f(0, MAX_BOUNDS, -MAX_BOUNDS));
- } else {
- vl.push_back(new math::Vector3f(0, MAX_BOUNDS, -MAX_BOUNDS));
- vl.push_back(new math::Vector3f(0, MAX_BOUNDS, MAX_BOUNDS));
- vl.push_back(new math::Vector3f(0, -MAX_BOUNDS, MAX_BOUNDS));
- vl.push_back(new math::Vector3f(0, -MAX_BOUNDS, -MAX_BOUNDS));
- }
- // calculate the x coordinate of each face vertex
- for (std::vector<Vector3f *>::iterator it = vl.begin(); it != vl.end(); it++) {
- (*it)->x = (-face->d() -
- face->normal().z * (*it)->z -
- face->normal().y * (*it)->y) /
- face->normal().x;
- }
- }
-
- // 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));
- vl.push_back(new Vector3f(-MAX_BOUNDS, 0, MAX_BOUNDS));
- vl.push_back(new Vector3f(-MAX_BOUNDS, 0, -MAX_BOUNDS));
- } else {
- vl.push_back(new Vector3f(-MAX_BOUNDS, 0, -MAX_BOUNDS));
- vl.push_back(new Vector3f(-MAX_BOUNDS, 0, MAX_BOUNDS));
- vl.push_back(new Vector3f(MAX_BOUNDS, 0, MAX_BOUNDS));
- vl.push_back(new Vector3f(MAX_BOUNDS, 0, -MAX_BOUNDS));
- }
-
- // calculate the x coordinate of each face vertex
- for (std::vector<Vector3f *>::iterator it = vl.begin(); it != vl.end(); it++) {
- (*it)->y = (-face->d() -
- face->normal().z * (*it)->z -
- face->normal().x * (*it)->x) /
- face->normal().y;
- }
- }
-
- // 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));
- vl.push_back(new Vector3f(MAX_BOUNDS, MAX_BOUNDS, 0));
- vl.push_back(new Vector3f(MAX_BOUNDS, -MAX_BOUNDS, 0));
- } else {
- vl.push_back(new Vector3f(MAX_BOUNDS, -MAX_BOUNDS, 0));
- vl.push_back(new Vector3f(MAX_BOUNDS, MAX_BOUNDS, 0));
- vl.push_back(new Vector3f(-MAX_BOUNDS, MAX_BOUNDS, 0));
- vl.push_back(new Vector3f(-MAX_BOUNDS, -MAX_BOUNDS, 0));
- }
-
- // calculate the x coordinate of each face vertex
- for (std::vector<Vector3f *>::iterator it = vl.begin(); it != vl.end(); it++) {
- (*it)->z = (-face->d() -
- face->normal().x * (*it)->x -
- face->normal().y * (*it)->y) /
- face->normal().z;
- }
- }
-
-
- // intersect the face with every plane
- for (std::vector<Plane *>::iterator pit = planes.begin(); pit != planes.end(); pit++) {
- Plane *plane = (*pit);
- if (plane == face) {
- continue;
- }
-
- Vector3f fn = crossproduct(face->point(1)-face->point(0), face->point(2)-face->point(0));
- Vector3f pn = crossproduct(plane->point(1)-plane->point(0), plane->point(2)-plane->point(0));
-
- Vector3f t = crossproduct(fn, pn);
- if ((t.x == 0) && (t.y == 0) && (t.z == 0)) {
- continue;
- }
-
- // intersect face with plane
- 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);
- } else {
- next = *vl.front();
- }
-
- Vector3f prev;
- if (i > 0) {
- prev = *vl.at(i-1);
- } else {
- prev = *vl.back();
- }
-
- if ((v.x*plane->normal().x + v.y*plane->normal().y + v.z*plane->normal().z +plane->d()) < MIN_DELTA) {
-
- // find current
- std::vector<Vector3f *>::iterator vit = vl.begin();
- while ((*vit) != vl.at(i)) {
- vit++;
- }
-
- // check if prev - v intersects with plane
- if ((prev.x*plane->normal().x + prev.y*plane->normal().y + prev.z*plane->normal().z + plane->d()) > -MIN_DELTA) {
-
- // calculate intersection
- float t1 = -plane->normal().x * prev.x - plane->normal().y * prev.y - plane->normal().z * prev.z -plane->d();
- 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) {
- *s = v;
- } else {
- for (int j = 0; j < 3; j++)
- (*s)[j] = prev [j] + t1 * (v[j] - prev[j]) / t2;
- }
-
- vit = vl.insert(vit,s);
- vit++;
- i++;
- }
-
- // 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 +
- plane->normal().y * next.y - plane->normal().y * v.y +
- plane->normal().z * next.z - plane->normal().z * v.z);
- //cout << "next t2 " << t2 << std::endl;
- Vector3f *s = new Vector3f;
-
- if (t2 == 0) {
- *s = v;
- } else {
- for (int j = 0; j < 3; j++)
- (*s)[j] = v [j] + t1 * (next[j] - v[j]) / t2;
- }
-
- vit = vl.insert(vit,s);
- vit++;
- i++;
- }
-
- // erase
- delete *vit;
- vl.erase(vit);
- i--;
- }
-
- }
- }
-
- if (vl.size() > 2) {
-
- math::Color *color = 0;
- if (face->texture() == "colors/white") {
- color = new math::Color(1, 1, 1);
- } else if (face->texture() == "colors/grey90") {
- color = new math::Color(0.9, 0.9, 0.9);
- } else if (face->texture() == "colors/grey75") {
- color = new math::Color(0.75, 0.75, 0.75);
- } else if (face->texture() == "colors/grey50") {
- color = new math::Color(0.5, 0.5, 0.5);
- } else if (face->texture() == "colors/grey25") {
- color = new math::Color(0.25, 0.25, 0.25);
- } else if (face->texture() == "colors/black") {
- color = new math::Color(0, 0, 0);
- } else if (face->texture() == "colors/red") {
- color = new math::Color(1, 0, 0);
- } else if (face->texture() == "colors/green") {
- color = new math::Color(0, 1, 0);
- } else if (face->texture() == "colors/blue") {
- color = new math::Color(0, 0, 1);
- } else if (face->texture() == "common/entity") {
- color = 0;
- } else
- // unknown textures get hot pink
- color = new math::Color(1.0f, 0.0, 1.0f);
-
- // calculate bounding box
- 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 ) {
- std::vector<Vector3f *>::iterator v0 = vl.begin();
- std::vector<Vector3f *>::reverse_iterator vn = vl.rbegin();
- std::vector<Vector3f *>::reverse_iterator vn1 = vl.rbegin();
- ++vn1;
-
- Vector3f n(face->normal()*-1);
- n.normalize();
-
- if (!color) {
- // 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 ((face->surface_flags() & 1) == 1 ) {
- // 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);
- vl.pop_back();
- }
- if (color) delete color;
- } else {
- con_debug << "Unresolved face!\n";
- }
-
- // clean up the vertex list
- for (std::vector<Vector3f *>::iterator it = vl.begin(); it != vl.end(); it++) {
- delete(*it);
- }
-
- vl.clear();
-}
-
-bool MapFile::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 {
- return false;
- }
-}
-
-bool MapFile::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();
- }
- return true;
- } else {
- return false;
- }
-}
-
-bool MapFile::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;
- }
- return true;
- } else {
- return false;
- }
-}
-
-bool MapFile::got_key_int(const char * keylabel, unsigned int & u)
-{
- if (last_read_was_key && (key_current.compare(keylabel) == 0 )) {
- std::istringstream is(value_current);
- if (!(is >> u)) {
- u = 0;
- }
- return true;
- } else {
- return false;
- }
-}
-
-bool MapFile::got_key(const char * keylabel) {
- return (last_read_was_key && (key_current.compare(keylabel) == 0 ));
-}
-
-bool MapFile::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);
- } else {
- f = 0;
- }
- return true;
- } else {
- return false;
- }
-}
-
-bool MapFile::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;
- }
- color = math::Color(r, g, b);
- } else {
- color = math::Color();
- }
- return true;
- } else {
- return false;
- }
-}
-
-void MapFile::close()
-{
- mapfile_ifs.close();
-}
-
-} // namespace filesystem
-
diff --git a/src/model/mapfile.h b/src/model/mapfile.h
deleted file mode 100644
index e599ec0..0000000
--- a/src/model/mapfile.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- model/mapfile.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_MAPFILE_H__
-#define __INCLUDED_MODEL_MAPFILE_H__
-
-#include <fstream>
-#include <string>
-#include <vector>
-
-#include "model/model.h"
-#include "model/plane.h"
-#include "model/triangle.h"
-
-namespace model {
-
-/// class to parse .map files
-class MapFile {
-
-public:
- MapFile();
- ~MapFile();
-
- /// 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 {
- return classname_current;
- }
-
- /// current key
- inline std::string key() const {
- return key_current;
- }
-
- /// current value
- 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 {
- 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 {
- return line_number;
- }
-
- /// return true of the ini file is open for reading
- inline bool is_open() { return mapfile_ifs.is_open(); }
-
- /// current filename
- inline std::string const & name() const {return mapfile_name; }
-
- /// close the file
- void close();
-
- /// tmp lists with triangles
- std::list<Triangle *> class_tris;
-
- /// tmp lists with light triangles
- std::list<Triangle *> class_ltris;
-
- /// tmp lists with entity color triangles
- std::list<Triangle *> class_etris;
-
- math::Vector3f class_maxbbox;
-
- math::Vector3f class_minbbox;
-
- unsigned int brushes;
-
-protected:
- /// generate triangles for one plane in the plane list
- void make_brushface(Plane *face);
-
- /// list of planes for the current brush
- std::vector<Plane *> planes;
-
-private:
- std::string classname_current;
- std::string key_current;
- std::string value_current;
-
- bool last_read_was_key;
- bool last_read_was_classname;
-
- unsigned int parse_level;
- unsigned int line_number;
- std::ifstream mapfile_ifs;
- std::string mapfile_name;
-};
-
-}
-
-#endif // __INCLUDED_MODEL_MAPFILE_H__
diff --git a/src/model/material.h b/src/model/material.h
new file mode 100644
index 0000000..02ae58f
--- /dev/null
+++ b/src/model/material.h
@@ -0,0 +1,21 @@
+/*
+ model/material.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_MATERIAL_H__
+#define __INCLUDED_MODEL_MATERIAL_H__
+
+namespace model
+{
+
+class Material
+{
+public:
+ enum Flags { None=0, Primary=1, Secondary=2, Tertiary=3, Dark=4, Light=8, Reflective=16 };
+};
+
+}
+
+#endif // __INCLUDED_MODEL_MATERIAL_H__
diff --git a/src/model/primitives.h b/src/model/primitives.h
new file mode 100644
index 0000000..28da706
--- /dev/null
+++ b/src/model/primitives.h
@@ -0,0 +1,44 @@
+/*
+ model/primitives.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_PRIMITIVES_H__
+#define __INCLUDED_MODEL_PRIMITIVES_H__
+
+#include "math/vector3f.h"
+#include "math/color.h"
+#include "model/triangle.h"
+#include "model/quad.h"
+
+namespace model
+{
+
+/// a list of Triangle and Quad primitives that have to be rendered using the same material, to be parsed into fragments
+class Primitives
+{
+public:
+ Primitives(unsigned int material);
+ ~Primitives();
+
+ /// the material to be used for these primitives
+ inline unsigned int material() const { return primitives_material; }
+
+ /// 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);
+
+ /// 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);
+
+private:
+ std::list<Triangle *> primitives_triangles;
+ std::list<Quad *> primitives_quads;
+
+ unsigned int primitives_material;
+};
+
+}
+#endif
diff --git a/src/model/quad.cc b/src/model/quad.cc
new file mode 100644
index 0000000..e216532
--- /dev/null
+++ b/src/model/quad.cc
@@ -0,0 +1,28 @@
+/*
+ model/quad.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/quad.h"
+
+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)
+{
+ quad_detail = detail;
+}
+
+Quad::~Quad()
+{
+}
+
+}
diff --git a/src/model/quad.h b/src/model/quad.h
new file mode 100644
index 0000000..d2215f2
--- /dev/null
+++ b/src/model/quad.h
@@ -0,0 +1,60 @@
+/*
+ model/quad.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_QUAD_H__
+#define __INCLUDED_MODEL_QUAD_H__
+
+#include "math/color.h"
+#include "math/vector3f.h"
+
+namespace model
+{
+
+/// a model quad
+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);
+ /// 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;}
+
+ /// indidcates if this quad was generated from a detail brush
+ inline bool detail() const { return quad_detail; }
+
+ /// quad vertex 0
+ inline math::Vector3f & v0() { return quad_v0; }
+
+ /// quad vertex 1
+ inline math::Vector3f & v1() { return quad_v1; }
+
+ /// quad vertex 2
+ inline math::Vector3f & v2() { return quad_v2; }
+
+ /// quad vertex 3
+ 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;
+};
+
+}
+
+#endif // __INCLUDED_MODEL_QUAD_H__
diff --git a/src/model/tirangle.cc b/src/model/triangle.cc
index fd8ad1a..7c36615 100644
--- a/src/model/tirangle.cc
+++ b/src/model/triangle.cc
@@ -9,18 +9,14 @@
namespace model
{
-Triangle::Triangle(math::Vector3f const &v0, math::Vector3f const &v1, math::Vector3f const &v2, math::Vector3f const &n, math::Color *color, bool detail) :
+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(n)
+ triangle_normal(normal),
+ triangle_color(color)
{
-
- if (color)
- triangle_color = *color;
- else
- math::Color(1.0f, 1.0f, 1.0f);
-
triangle_detail = detail;
}
diff --git a/src/model/triangle.h b/src/model/triangle.h
index 58e25e4..9d775c4 100644
--- a/src/model/triangle.h
+++ b/src/model/triangle.h
@@ -18,25 +18,36 @@ 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 *color=0, bool detail=false);
+ Triangle(math::Vector3f const &v0, math::Vector3f const &v1, math::Vector3f const &v2,
+ math::Vector3f const &n, 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;}
+
/// indidcates if this triangle was generated from a detail brush
inline bool detail() const { return triangle_detail; }
/// triangle vertex 0
+ inline math::Vector3f & v0() { return triangle_v0; }
+
+ /// triangle vertex 1
+ inline math::Vector3f & v1() { return triangle_v1; }
+
+ /// triangle vertex 2
+ 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;
-private:
math::Vector3f triangle_normal;
math::Color triangle_color;
bool triangle_detail;
diff --git a/src/model/vertexarray.cc b/src/model/vertexarray.cc
index 27124fa..6a635eb 100644
--- a/src/model/vertexarray.cc
+++ b/src/model/vertexarray.cc
@@ -75,8 +75,9 @@ void VertexArray::add_sphere()
math::Color white(1.0f, 1.0f, 1.0f);
math::Vector3f v;
math::Vector3f n;
- math::Vector3f tex;
- int count;
+ float texx, texy;
+
+ int quad_count = 0;
// add sphere
for (int j=0; j < (SPHERESEGMENTS-1) / 2; j++) {
@@ -88,18 +89,22 @@ void VertexArray::add_sphere()
v = math::Vector3f(r*costable[i], r*sintable[i], costable[j]);
n = v;
n.normalize();
- tex.assign((float)i/(float)(SPHERESEGMENTS-1), -costable[j]/2 + 0.5f , 0);
- add_vertex(v, n, white, tex);
+ texx = (float)i/(float)(SPHERESEGMENTS-1);
+ texy = -costable[j]/2 + 0.5f;
+ add_vertex(v, n, white, texx, texy);
v = math::Vector3f(r1*costable[i], r1*sintable[i], costable[j+1]);
n = v;
n.normalize();
- tex.assign((float)i/(float)(SPHERESEGMENTS-1), -costable[j+1]/2 + 0.5f, 0);
- add_vertex(v, n, white, tex);
- count +=2;
+ 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++) {
@@ -112,15 +117,16 @@ void VertexArray::add_sphere()
v = math::Vector3f(r*costable[i], r*sintable[i], costable[j]);
n = v;
n.normalize();
- tex.assign(1-(float)i/(float)(SPHERESEGMENTS-1), -costable[j]/2 + 0.5f , 0);
- add_vertex(v, n, white, tex);
+ texx = 1-(float)i/(float)(SPHERESEGMENTS-1);
+ texy = -costable[j]/2 + 0.5f;
+ add_vertex(v, n, white, texx, texy);
v = math::Vector3f(r1*costable[i], r1*sintable[i], costable[j+1]);
n = v;
n.normalize();
- tex.assign(1-(float)i/(float)(SPHERESEGMENTS-1), -costable[j+1]/2 + 0.5f, 0);
- add_vertex(v, n, white, tex);
- count +=2;
+ texx = 1-(float)i/(float)(SPHERESEGMENTS-1);
+ texy = -costable[j+1]/2 + 0.5f;
+ add_vertex(v, n, white, texx, texy);
}
}
@@ -129,10 +135,13 @@ void VertexArray::add_sphere()
delete[] costable;
}
-size_t VertexArray::add_vertex(math::Vector3f const &v, math::Vector3f const &n, math::Color const &color) {
+size_t VertexArray::add_vertex(math::Vector3f const &v, math::Vector3f const &n, math::Color const &color, float tex_x, float tex_y)
+{
if (vertex_index + 3 >= vertex_size) {
- con_warn << "VertexArray overflow!" << std::endl;
- vertex_overflow = true;
+ if (!vertex_overflow) {
+ con_warn << "VertexArray overflow!" << std::endl;
+ vertex_overflow = true;
+ }
return 0;
}
@@ -145,31 +154,16 @@ size_t VertexArray::add_vertex(math::Vector3f const &v, math::Vector3f const &n,
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;
}
-size_t VertexArray::add_vertex(math::Vector3f const &v, math::Vector3f const &n, math::Color const &color, math::Vector3f const &tex) {
- if (vertex_index + 3 >= vertex_size) {
- con_warn << "VertexArray overflow!" << std::endl;
- vertex_overflow = true;
- return 0;
- }
-
- for (int i = 0; i < 3; i ++) {
- vertex_vertex[vertex_index+i] = v[i];
- vertex_normal[vertex_index+i] = n[i];
- vertex_texture[vertex_index+i] = tex[i];
- }
-
- vertex_color[vertex_index] = color.r;
- vertex_color[vertex_index+1] = color.g;
- vertex_color[vertex_index+2] = color.b;
-
- vertex_index += 3;
- return 1;
-}
}
diff --git a/src/model/vertexarray.h b/src/model/vertexarray.h
index 26d2514..6330d8c 100644
--- a/src/model/vertexarray.h
+++ b/src/model/vertexarray.h
@@ -15,6 +15,8 @@ namespace model {
const int SPHERESEGMENTS=65;
/// global vertex array
+/** a VertexArray acts like a stack of model vertices, it has no knowledge of what it is holding
+ */
class VertexArray
{
public:
@@ -24,9 +26,8 @@ public:
void clear();
- size_t add_vertex(math::Vector3f const &v, math::Vector3f const &n, math::Color const &color);
- size_t add_vertex(math::Vector3f const &v, math::Vector3f const &n, math::Color const &color, math::Vector3f const &tex);
-
+ 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; }
@@ -34,7 +35,10 @@ public:
inline bool overflow() const { return vertex_overflow; }
+ /// number of allocated floats
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; }
@@ -48,7 +52,7 @@ private:
size_t vertex_index;
size_t vertex_size;
-
+
void add_sphere();
static VertexArray *vertex_instance;
diff --git a/src/model/vertexdata.h b/src/model/vertexdata.h
deleted file mode 100644
index e69de29..0000000
--- a/src/model/vertexdata.h
+++ /dev/null