data/
.clang_complete
*.suo
+*.user
*sdf
+*.dll
+*.exe
Debug/
Release/
dep = $(obj:.o=.d)
bin = demo
-opt = -O3 -ffast-math
+#opt = -O3 -ffast-math
dbg = -g
incpath = -Isrc -Isrc/machine -I/usr/local/include `pkg-config --cflags sdl2`
CFLAGS = $(warn) $(opt) $(dbg) $(incpath)
CXXFLAGS = -std=c++11 $(warn) $(opt) $(dbg) $(incpath)
-LDFLAGS = $(libpath) $(libgl_$(sys)) -lm -lgmath -lvmath -limago -lresman \
- -lpthread -lassimp -ltreestore -ldrawtext -loptcfg -lgoatvr `pkg-config --libs sdl2`
+LDFLAGS = $(libpath) -ldrawtext $(libgl_$(sys)) -lm -lgmath -lvmath -limago \
+ -lresman -lpthread -lassimp -ltreestore -lgoatvr \
+ -lz -lpng -ljpeg `pkg-config --libs sdl2 freetype2`
sys = $(shell uname -s | sed 's/MINGW.*/mingw/')
libgl_Linux = -lGL -lGLU -lGLEW
libgl_Darwin = -framework OpenGL -lGLEW
libgl_mingw = -lopengl32 -lglu32 -lglew32
+#libgl_mingw = -lglu32 -Wl,-Bstatic -lglew32 -Wl,-Bdynamic -lopengl32
ifeq ($(sys), mingw)
bin = demo.exe
+ #CFLAGS += -DGLEW_STATIC
+ #CXXFLAGS += -DGLEW_STATIC
endif
$(bin): .clang_complete $(obj)
<ProjectGuid>{71A6DAF0-CBF6-4135-BE23-B3999E432EF6}</ProjectGuid>\r
<Keyword>Win32Proj</Keyword>\r
<RootNamespace>laserbrain_demo</RootNamespace>\r
+ <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>\r
</PropertyGroup>\r
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
<ConfigurationType>Application</ConfigurationType>\r
<UseDebugLibraries>true</UseDebugLibraries>\r
<PlatformToolset>v141</PlatformToolset>\r
- <CharacterSet>MultiByte</CharacterSet>\r
+ <CharacterSet>NotSet</CharacterSet>\r
</PropertyGroup>\r
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
<ConfigurationType>Application</ConfigurationType>\r
<UseDebugLibraries>false</UseDebugLibraries>\r
<PlatformToolset>v141</PlatformToolset>\r
- <WholeProgramOptimization>true</WholeProgramOptimization>\r
- <CharacterSet>MultiByte</CharacterSet>\r
+ <WholeProgramOptimization>false</WholeProgramOptimization>\r
+ <CharacterSet>NotSet</CharacterSet>\r
</PropertyGroup>\r
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
<ImportGroup Label="ExtensionSettings">\r
<ClCompile Include="src\blob_exhibit.cc" />\r
<ClCompile Include="src\datamap.cc" />\r
<ClCompile Include="src\exhibit.cc" />\r
+ <ClCompile Include="src\exman.cc" />\r
<ClCompile Include="src\geom.cc" />\r
<ClCompile Include="src\image.cc" />\r
<ClCompile Include="src\logger.cc" />\r
<ClCompile Include="src\opt.cc" />\r
<ClCompile Include="src\optcfg.c" />\r
<ClCompile Include="src\post.cc" />\r
+ <ClCompile Include="src\renderer.cc" />\r
+ <ClCompile Include="src\rend_cubemap.cc" />\r
<ClCompile Include="src\scene.cc" />\r
<ClCompile Include="src\sceneload.cc" />\r
<ClCompile Include="src\sdr.c" />\r
+ <ClCompile Include="src\sdrman.cc" />\r
<ClCompile Include="src\shader.cc" />\r
<ClCompile Include="src\shadow.cc" />\r
<ClCompile Include="src\snode.cc" />\r
<ClInclude Include="src\datamap.h" />\r
<ClInclude Include="src\dataset.h" />\r
<ClInclude Include="src\exhibit.h" />\r
+ <ClInclude Include="src\exman.h" />\r
<ClInclude Include="src\geom.h" />\r
<ClInclude Include="src\image.h" />\r
<ClInclude Include="src\logger.h" />\r
<ClInclude Include="src\opt.h" />\r
<ClInclude Include="src\optcfg.h" />\r
<ClInclude Include="src\post.h" />\r
+ <ClInclude Include="src\renderer.h" />\r
+ <ClInclude Include="src\rend_cubemap.h" />\r
<ClInclude Include="src\scene.h" />\r
<ClInclude Include="src\sceneload.h" />\r
<ClInclude Include="src\sdr.h" />\r
+ <ClInclude Include="src\sdrman.h" />\r
<ClInclude Include="src\shader.h" />\r
<ClInclude Include="src\shadow.h" />\r
<ClInclude Include="src\snode.h" />\r
<ClCompile Include="src\optcfg.c">\r
<Filter>src</Filter>\r
</ClCompile>\r
+ <ClCompile Include="src\exman.cc">\r
+ <Filter>src</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="src\rend_cubemap.cc">\r
+ <Filter>src</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="src\renderer.cc">\r
+ <Filter>src</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="src\sdrman.cc">\r
+ <Filter>src</Filter>\r
+ </ClCompile>\r
</ItemGroup>\r
<ItemGroup>\r
<ClInclude Include="src\app.h">\r
<ClInclude Include="src\optcfg.h">\r
<Filter>src</Filter>\r
</ClInclude>\r
+ <ClInclude Include="src\exman.h">\r
+ <Filter>src</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="src\rend_cubemap.h">\r
+ <Filter>src</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="src\renderer.h">\r
+ <Filter>src</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="src\sdrman.h">\r
+ <Filter>src</Filter>\r
+ </ClInclude>\r
</ItemGroup>\r
<ItemGroup>\r
<None Include="src\dataset.inl">\r
#include "opt.h"
#include "post.h"
#include "renderer.h"
+#include "exman.h"
#include "blob_exhibit.h"
#define NEAR_CLIP 5.0
static long prev_msec;
+static ExhibitManager *exman;
static BlobExhibit *blobs;
static bool show_blobs;
dir.y = 0;
cam_theta = rad_to_deg(acos(dot(dir, Vec3(0, 0, 1))));
+ exman = new ExhibitManager;
+ if(!exman->load(mscn, "data/exhibits")) {
+ //return false;
+ }
+
blobs = new BlobExhibit;
blobs->node = new SceneNode;
blobs->init();
blobs->node->set_scaling(Vec3(28, 28, 28));
blobs->node->update(0);
+ exman->add(blobs);
+
if(!(sdr_ltmap_notex = create_program_load("sdr/lightmap.v.glsl", "sdr/lightmap-notex.p.glsl"))) {
return false;
}
delete rend;
- blobs->destroy();
- delete blobs->node;
- delete blobs;
+ delete exman;
texman.clear();
sceneman.clear();
sceneman.update();
mscn->update(dt);
- if(show_blobs) {
- blobs->update(dt);
- }
+ exman->update(dt);
float speed = walk_speed * dt;
Vec3 dir;
BlobExhibit::~BlobExhibit()
{
+ destroy();
delete priv;
}
void BlobExhibit::destroy()
{
- msurf_free(priv->msurf);
- priv->msurf = 0;
+ if(priv->msurf) {
+ msurf_free(priv->msurf);
+ priv->msurf = 0;
+ }
}
void BlobExhibit::update(float dt)
#include <algorithm>
#include "datamap.h"
-#ifdef WIN32
+#if defined(WIN32) || defined(__WIN32__)
#include <malloc.h>
#else
#include <alloca.h>
#include "exhibit.h"
#include "snode.h"
+#include "scene.h"
class ExhibitPriv {
+public:
Vec3 orig_pos;
Quat orig_rot;
SceneNode *orig_node;
+
+ ExhibitPriv();
};
ExSelection::ExSelection(Exhibit *ex)
return ex != 0;
}
+ExhibitPriv::ExhibitPriv()
+{
+ orig_node = 0;
+}
+
Exhibit::Exhibit()
{
priv = new ExhibitPriv;
- priv->orig_node = 0;
}
Exhibit::~Exhibit()
delete priv;
}
+void Exhibit::set_node(SceneNode *node)
+{
+ this->node = priv->orig_node = node;
+ priv->orig_pos = node->get_position();
+ priv->orig_rot = node->get_rotation();
+}
+
ExSelection Exhibit::select(const Ray &ray) const
{
return ExSelection(0);
class Exhibit;
class ExhibitPriv;
+class Scene;
enum {
EXSEL_RAY = 1,
Exhibit(const Exhibit&) = delete;
Exhibit &operator =(const Exhibit &) = delete;
+ virtual void set_node(SceneNode *node);
+
virtual ExSelection select(const Ray &ray) const;
virtual ExSelection select(const Sphere &sph) const;
+#include <algorithm>
#include "exman.h"
#include "exhibit.h"
#include "blob_exhibit.h"
+#include "treestore.h"
static Exhibit *create_exhibit(const char *type);
items.clear();
}
-bool ExhibitManager::load(const MetaScene *mscn, const char *fname)
+void ExhibitManager::add(Exhibit *ex)
+{
+ std::vector<Exhibit*>::iterator it = std::find(items.begin(), items.end(), ex);
+ if(it == items.end()) {
+ items.push_back(ex);
+ }
+}
+
+bool ExhibitManager::remove(Exhibit *ex)
+{
+ std::vector<Exhibit*>::iterator it = std::find(items.begin(), items.end(), ex);
+ if(it != items.end()) {
+ items.erase(it);
+ return true;
+ }
+ return false;
+}
+
+bool ExhibitManager::load(MetaScene *mscn, const char *fname)
{
struct ts_node *root = ts_load(fname);
if(!root || strcmp(root->name, "exhibits") != 0) {
return false;
}
+ struct ts_node *iter = root->child_list;
+ while(iter) {
+ struct ts_node *node = iter;
+ iter = iter->next;
+
+ if(strcmp(node->name, "item") == 0) {
+ SceneNode *snode;
+
+ const char *amatch = ts_get_attr_str(node, "match_node");
+ if(!amatch || !(snode = mscn->match_node(amatch))) {
+ error_log("regexp \"%s\" didn't match any nodes\n", amatch ? amatch : "");
+ continue;
+ }
+
+ Exhibit *ex;
+ const char *atype = ts_get_attr_str(node, "type");
+ if(!atype || !(ex = create_exhibit(atype))) {
+ error_log("failed to create exhibit of type: %s\n", atype);
+ continue;
+ }
+
+ ex->set_node(snode);
+ items.push_back(ex);
+ }
+ }
+
ts_free_tree(root);
return true;
}
+void ExhibitManager::update(float dt)
+{
+ int num = items.size();
+ for(int i=0; i<num; i++) {
+ items[i]->update(dt);
+ }
+}
static Exhibit *create_exhibit(const char *type)
{
} else if(strcmp(type, "blobs") == 0) {
return new BlobExhibit;
}
+ error_log("unknown exhibit type: %s\n", type);
return 0;
}
ExhibitManager();
~ExhibitManager();
- bool load(const MetaScene *mscn, const char *fname);
+ void add(Exhibit *ex);
+ bool remove(Exhibit *ex);
+
+ bool load(MetaScene *mscn, const char *fname);
ExSelection select(const Ray &ray) const;
ExSelection select(const Sphere &sph) const;
+
+ void update(float dt = 0.0f);
};
#endif // EXMAN_H_
#include <string.h>
-#ifndef _MSC_VER
-#include <alloca.h>
-#else
+#if defined(WIN32) || defined(__WIN32__)
#include <malloc.h>
+#else
+#include <alloca.h>
#endif
#include "imago2.h"
#include "logger.h"
#include "app.h"
-#ifdef WIN32
+#if defined(WIN32) || defined(__WIN32__)
#include <malloc.h>
#else
#include <alloca.h>
}
}
+SceneNode *MetaScene::find_node(const char *name) const
+{
+ int num = scenes.size();
+ for(int i=0; i<num; i++) {
+ SceneNode *n = scenes[i]->find_node(name);
+ if(n) return n;
+ }
+ return 0;
+}
+
+SceneNode *MetaScene::match_node(const char *qstr) const
+{
+ int num = scenes.size();
+ for(int i=0; i<num; i++) {
+ SceneNode *n = scenes[i]->match_node(qstr);
+ if(n) return n;
+ }
+ return 0;
+}
+
+std::list<SceneNode*> MetaScene::match_nodes(const char *qstr) const
+{
+ std::list<SceneNode*> res;
+ int num = scenes.size();
+ for(int i=0; i<num; i++) {
+ std::list<SceneNode*> tmp = scenes[i]->match_nodes(qstr);
+ if(!tmp.empty()) {
+ res.splice(res.end(), tmp);
+ }
+ }
+ return std::move(res);
+}
+
+Scene *MetaScene::extract_nodes(const char *qstr)
+{
+ Scene *scn = 0;
+ int nscn = scenes.size();
+ for(int i=0; i<nscn; i++) {
+ Scene *tmp = scenes[i]->extract_nodes(qstr);
+ if(tmp) {
+ if(!scn) {
+ scn = tmp;
+ } else {
+ scn->merge(tmp);
+ delete tmp;
+ }
+ }
+ }
+ return scn;
+}
+
static bool proc_node(MetaScene *mscn, struct ts_node *node)
{
struct ts_node *c = node->child_list;
void update(float dt);
void draw() const;
+
+ /* helper functions which end up calling the corresponding Scene functions
+ * for every scene
+ */
+ SceneNode *find_node(const char *name) const;
+ SceneNode *match_node(const char *qstr) const;
+ std::list<SceneNode*> match_nodes(const char *qstr) const;
+
+ Scene *extract_nodes(const char *qstr);
};
#endif // METASCENE_H_
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
-#ifdef _MSC_VER
+#if defined(WIN32) || defined(__WIN32__)
#include <malloc.h>
#else
#include <alloca.h>
return n->scene == this;
}
+/* traverse scene graph and find node by name */
+static SceneNode *find_node_rec(SceneNode *tree, const char *name)
+{
+ if(strcmp(tree->get_name(), name) == 0) {
+ return tree;
+ }
+
+ int num = tree->get_num_children();
+ for(int i=0; i<num; i++) {
+ SceneNode *n = find_node_rec(tree->get_child(i), name);
+ if(n) return n;
+ }
+ return 0;
+}
+
+static SceneNode *find_node_rec(SceneNode *tree, const std::regex &re)
+{
+ if(std::regex_match(tree->get_name(), re)) {
+ return tree;
+ }
+ debug_log("no match: \"%s\"\n", tree->get_name());
+
+ int num = tree->get_num_children();
+ for(int i=0; i<num; i++) {
+ SceneNode *n = find_node_rec(tree, re);
+ if(n) return n;
+ }
+ return 0;
+}
+
static void find_nodes_rec(std::list<SceneNode*> *res, SceneNode *tree, const std::regex &re)
{
if(std::regex_match(tree->get_name(), re)) {
}
}
+SceneNode *Scene::find_node(const char *name) const
+{
+ if(!nodes) return 0;
+ return find_node_rec(nodes, name);
+}
+
+SceneNode *Scene::match_node(const char *qstr) const
+{
+ if(!nodes) return 0;
+
+ std::regex re{qstr};
+ return find_node_rec(nodes, re);
+}
+
+std::list<SceneNode*> Scene::match_nodes(const char *qstr) const
+{
+ std::list<SceneNode*> res;
+ if(nodes) {
+ std::regex re{qstr};
+ find_nodes_rec(&res, nodes, re);
+ }
+ return std::move(res);
+}
+
Scene *Scene::extract_nodes(const char *qstr)
{
if(!nodes) return 0;
bool remove_node(SceneNode *n);
bool have_node(SceneNode *n) const;
+ // find node by name
+ SceneNode *find_node(const char *name) const;
+ // match nodes with regexp and return the first that matches
+ SceneNode *match_node(const char *qstr) const;
+ // match nodes with regexp and return a list of matches
+ std::list<SceneNode*> match_nodes(const char *qstr) const;
+
/* find and remove all nodes whose names match the regexp
* XXX at the moment this has the effect of flattening the hierarchy in the
* result scene. If we ever need verbatim extraction of whole subtrees we'll