From aad0913d91fc3b682deddb5a5f8380d1475174f5 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Sun, 21 Dec 2008 12:12:53 +0000 Subject: improved func_rotate --- doc/models.html | 30 +++++++++++++++++++++------ src/model/fragment.h | 14 ++++++++++++- src/model/map.cc | 54 +++++++++++++++++++++++++++++++++++-------------- src/model/map.h | 10 +++++++-- src/model/model.h | 3 +++ src/render/draw.cc | 13 ++++++++++-- src/render/particles.cc | 1 + 7 files changed, 99 insertions(+), 26 deletions(-) diff --git a/doc/models.html b/doc/models.html index d2f6ca7..28ba9c7 100644 --- a/doc/models.html +++ b/doc/models.html @@ -49,6 +49,7 @@
  • Lights
  • Flares
  • Particles +
  • Function groups
  • Other entities @@ -56,9 +57,9 @@ Creating models with GtkRadiant

    - All the models for the game were created with GtkRadiant 1.5.0, + All the models for the game were created with GtkRadiant 1.5, in theory any editor capable of exporting Quake 2 .map files could - be used. Support for files for GtkRadiant 1.5.0 are included in the + be used. Support for files for GtkRadiant 1.5 are included in the data distribution. Refer to the file INSTALL on where to find them and how to install them. No map compiler is necessary, the engine reads the .map files directly. @@ -183,17 +184,17 @@ to the level but to add point lights to a model. Adding a light will render a light flare texture in the corresponding location.

    - The flare value indicates what texture will be used to draw the light. + The flare value indicates what texture will be used to draw the light. The flare value is translated to a texture name, bitmaps/fx/flare??. The default flare texture is flare00.

    - The light value is used to determine the size of the flare. The engine + The light value is used to determine the size of the flare. The engine default is 100, resulting in rather large flares.

    - The default color is white, but the color can be set through radiant's + The default _color is white, but the color can be set through radiant's color menu (K key). If the entity option (spawnflag 2) is set, the color value will be ignored and the light will be rendered with the - color of the entity it is attached to. + color of the entity it is attached to.

    The strobe option (spawnflag 1) will create a blinking light. A number of options can be set to manipulate the flashing behaviour. By default @@ -241,6 +242,23 @@

    Particles will only be rendered if the model is within detail range.

    +

    + Function groups +

    +

    + Brushes can be grouped together into funcion groups. These groups can be used + to create moving parts in a model. +

    +

    + func_door will be used to create animated doors (not implemented) +

    +

    + func_group an editor utility to group brushes together. +

    +

    + func_rotate will create a rotating set of brushes. The center of the rotation + is automaticly calculated as the geometrical center of the group. +

    Other entities

    diff --git a/src/model/fragment.h b/src/model/fragment.h index fcdeca3..204a3c9 100644 --- a/src/model/fragment.h +++ b/src/model/fragment.h @@ -86,11 +86,16 @@ public: inline const Type type() const { return group_type; } + inline const size_t size() const { return group_fragments.size(); } + + inline const float angle() const { return group_angle; } + + inline const float speed() const { return group_speed; } + inline iterator begin() { return group_fragments.begin(); } inline iterator end() { return group_fragments.end(); } - inline size_t size() const { return group_fragments.size(); } inline void push_back(Fragment *fragment) { group_fragments.push_back(fragment); } @@ -98,7 +103,12 @@ public: inline void set_type(const Type type) { group_type = type; } + inline void set_angle(const float angle) { group_angle = angle; } + + inline void set_speed(const float speed) { group_speed = speed; } + void clear(); + private: /// type definition for a list of model fragments typedef std::list Fragments; @@ -108,6 +118,8 @@ private: math::Vector3f group_forward; Type group_type; + float group_angle; + float group_speed; }; } diff --git a/src/model/map.cc b/src/model/map.cc index 71b0dda..c073a4d 100644 --- a/src/model/map.cc +++ b/src/model/map.cc @@ -242,14 +242,6 @@ bool Map::getline() return true; } -void Map::clear_bbox() -{ - for (int i=0; i < 3; i++) { - class_minbbox[i] = MAX_BOUNDS; - class_maxbbox[i] = -MAX_BOUNDS; - } -} - void Map::make_brushface(Plane *face) { using math::Vector3f; @@ -678,6 +670,17 @@ void Map::close() mapfile_ifs.close(); } +void Map::clear_bbox() +{ + for (int i=0; i < 3; i++) { + class_minbbox[i] = MAX_BOUNDS; + class_maxbbox[i] = -MAX_BOUNDS; + } + + class_angle = 0; + class_speed = 0; +} + void Map::load_worldspawn(Model *model) { if (!map_materials.size()) @@ -694,7 +697,7 @@ void Map::load_worldspawn(Model *model) load_fragmentgroup(model, FragmentGroup::None); } -void Map::load_fragmentgroup(Model *model, const FragmentGroup::Type type) +void Map::load_fragmentgroup(Model *model, const FragmentGroup::Type class_type) { if (!VertexArray::instance() || VertexArray::instance()->overflow()) return; @@ -702,9 +705,18 @@ void Map::load_fragmentgroup(Model *model, const FragmentGroup::Type type) if (!map_materials.size()) return; + if (class_type == FragmentGroup::Rotate) { + if (class_speed == 0) { + // default rotation speed 45 degrees per second + class_speed = 45.0f; + } + } + FragmentGroup *group = new FragmentGroup(); - group->set_type(type); + group->set_type(class_type); group->set_location((class_minbbox + class_maxbbox) / 2.0f - map_center); + group->set_angle(class_angle); + group->set_speed(class_speed); for (Materials::iterator mit = map_materials.begin(); mit != map_materials.end(); mit++) { // split the Primitives with this material into fragments @@ -819,7 +831,7 @@ Model * Map::load(std::string const &name) mapfile.load_worldspawn(model); mapfile.clear_materials(); - } else if (mapfile.classname().compare("worldspawn") == 0) { + } else if (mapfile.in_class("worldspawn")) { // worldspawn attributes if (mapfile.got_key_int("enginesound", u)) { @@ -832,14 +844,12 @@ Model * Map::load(std::string const &name) } else if (mapfile.got_key_color("enginecolor", model->model_enginecolor)) { continue; -/* - } else if (mapfile.got_key("name")) { - continue; -*/ + } else if (mapfile.got_key()) { con_warn "Unknown key " << mapfile.classname() << ":" << mapfile.key() << std::endl; } + } else if (mapfile.got_classname("func_door")) { mapfile.clear_bbox(); @@ -847,6 +857,8 @@ Model * Map::load(std::string const &name) mapfile.load_fragmentgroup(model, FragmentGroup::Door); mapfile.clear_materials(); + } else if (mapfile.in_class("func_door")) { + } else if (mapfile.got_classname("func_group")) { mapfile.clear_bbox(); @@ -861,6 +873,18 @@ Model * Map::load(std::string const &name) mapfile.load_fragmentgroup(model, FragmentGroup::Rotate); mapfile.clear_materials(); + } else if (mapfile.in_class("func_rotate")) { + + if (mapfile.got_key_float("angle", mapfile.class_angle)) { + continue; + + } else if (mapfile.got_key_float("speed", mapfile.class_speed)) { + continue; + + } else if (mapfile.got_key()) { + con_warn "Unknown key " << mapfile.classname() << ":" << mapfile.key() << std::endl; + } + } else if (mapfile.got_classend()) { mapfile.clear_materials(); diff --git a/src/model/map.h b/src/model/map.h index 9b75f7a..f9b036f 100644 --- a/src/model/map.h +++ b/src/model/map.h @@ -64,6 +64,11 @@ private: /// true if the last read line contained a new classname bool got_classname() const; + /// true if we are inside the requested class + bool in_class(const char *name) { + return (classname_current.compare(name) == 0); + } + /// true if the last read line contained a class closing bracket inline bool got_classend() const { @@ -130,7 +135,7 @@ private: void load_worldspawn(Model *model); /// load parsed primitives into a FragmentGroup - void load_fragmentgroup(Model *model, const FragmentGroup::Type type); + void load_fragmentgroup(Model *model, const FragmentGroup::Type class_type); /// clear the current list of per-material geometry void clear_materials(); @@ -160,9 +165,10 @@ private: math::Vector3f class_maxbbox; math::Vector3f class_minbbox; + float class_angle; + float class_speed; math::Vector3f map_center; - Materials map_materials; }; diff --git a/src/model/model.h b/src/model/model.h index bdaa74a..6e9c5d8 100644 --- a/src/model/model.h +++ b/src/model/model.h @@ -23,6 +23,9 @@ namespace model const float SCALE = 1.0f / 1024.0f; const float LIGHTSCALE = 1.0f / 100.0f; +const float ANGLEUP = -1.0f; +const float ANGLEDOWN = -2.0f; + /// a 3D model contains a list of faces class Model { diff --git a/src/render/draw.cc b/src/render/draw.cc index afff831..e094a44 100644 --- a/src/render/draw.cc +++ b/src/render/draw.cc @@ -582,8 +582,17 @@ void draw_model_fragments(core::Entity *entity) if (group->type() == model::FragmentGroup::Rotate) { gl::push(); gl::translate(group->location()); - float angle = math::degrees360f(core::application()->time() * 90.0f); - gl::rotate(angle, math::Vector3f::Xaxis()); + + float rotation_angle = math::degrees360f(core::application()->time() * group->speed()); + + if (group->angle() == model::ANGLEUP) { + gl::rotate(rotation_angle, math::Vector3f::Zaxis()); + } else if (group->angle() == model::ANGLEDOWN) { + gl::rotate(-rotation_angle, math::Vector3f::Zaxis()); + } else { + gl::rotate(rotation_angle, math::Vector3f::Xaxis()); + } + gl::translate(group->location()* -1.0f); } diff --git a/src/render/particles.cc b/src/render/particles.cc index 3a9521b..71ec26b 100644 --- a/src/render/particles.cc +++ b/src/render/particles.cc @@ -201,6 +201,7 @@ ParticleSystem::ParticleSystem(ParticleScript *script, core::Entity *entity, mod if (modelclass->engine()) { color.assign(entity->model()->enginecolor()); } + particlesystem_axis.assign(modelclass->axis()); } } -- cgit v1.2.3