-\r
-#include "cpicomodel.h"\r
-#include "qertypes.h"\r
-\r
-#include <map>\r
-#include <vector>\r
-\r
-#define RADIANT_ASSERT(condition, message) if(!(condition)) { Sys_Printf("ASSERTION FAILURE: " message "\n"); } else\r
-\r
-template<class key_type, class value_type>\r
-class cache_element\r
-{\r
-public:\r
- inline cache_element() : m_count(0), m_value(NULL) {}\r
- inline ~cache_element()\r
- {\r
- RADIANT_ASSERT(m_count == 0 , "destroyed a reference before it was released\n");\r
- if(m_count > 0)\r
- destroy();\r
- }\r
- inline value_type* capture(const key_type& key)\r
- {\r
- if(++m_count == 1)\r
- construct(key);\r
- return m_value;\r
- }\r
- inline void release()\r
- {\r
- RADIANT_ASSERT(!empty(), "failed to release reference - not found in cache\n");\r
- if(--m_count == 0)\r
- destroy();\r
- }\r
- inline bool empty()\r
- {\r
- return m_count == 0;\r
- }\r
- inline void refresh(const key_type& key)\r
- {\r
- m_value->refresh(key);\r
- }\r
-private:\r
- inline void construct(const key_type& key)\r
- {\r
- m_value = new value_type(key);\r
- }\r
- inline void destroy()\r
- {\r
- delete m_value;\r
- }\r
-\r
- unsigned int m_count;\r
- value_type* m_value;\r
-};\r
-\r
-class ModelCache\r
-{\r
- typedef CPicoModel value_type;\r
- \r
-public:\r
- typedef PicoModelKey key_type;\r
- typedef cache_element<key_type, value_type> elem_type;\r
- typedef map<key_type, elem_type> cache_type;\r
- \r
- value_type* capture(const key_type& key)\r
- {\r
- return m_cache[key].capture(key);\r
- }\r
- void release(const key_type& key)\r
- {\r
- m_cache[key].release();\r
- }\r
-\r
-private:\r
- cache_type m_cache;\r
-};\r
-\r
-ModelCache g_model_cache;\r
-\r
-\r
-\r
-typedef struct remap_s {\r
- char m_remapbuff[64+1024];\r
- char *original;\r
- char *remap;\r
-} remap_t;\r
-\r
-class RemapWrapper : public IRender, public ISelect\r
-{\r
- unsigned int m_refcount;\r
-public:\r
- RemapWrapper(entity_interfaces_t* model, const char* name)\r
- : m_refcount(1)\r
- {\r
- parse_namestr(name);\r
-\r
- m_model = g_model_cache.capture(ModelCache::key_type(m_name.GetBuffer(), m_frame));\r
-\r
- model->pRender = this;\r
- model->pRender->IncRef();\r
- model->pEdit = NULL;\r
- model->pSelect = this;\r
- model->pSelect->IncRef();\r
-\r
- construct_shaders();\r
- }\r
- virtual ~RemapWrapper()\r
- {\r
- g_model_cache.release(ModelCache::key_type(m_name.GetBuffer(), m_frame));\r
-\r
- for(shaders_t::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i) {\r
- (*i)->DecRef();\r
- }\r
-\r
- for(remaps_t::iterator j = m_remaps.begin(); j != m_remaps.end(); ++j)\r
- {\r
- remap_t *pRemap = (*j);\r
- delete pRemap;\r
- }\r
- m_remaps.clear();\r
- }\r
- virtual void IncRef()\r
- {\r
- ++m_refcount;\r
- }\r
- virtual void DecRef()\r
- {\r
- if(--m_refcount == 0)\r
- delete this;\r
- }\r
- virtual void Draw(int state, int rflags) const\r
- {\r
- m_model->Draw(state, m_shaders, rflags);\r
- }\r
- virtual const aabb_t *GetAABB() const \r
- {\r
- return m_model->GetAABB();\r
- }\r
- virtual bool TestRay(const ray_t *ray, vec_t *dist) const\r
- {\r
- return m_model->TestRay(ray, dist);\r
- }\r
-private:\r
- void add_remap(const char *remap)\r
- {\r
- const char *ch;\r
- remap_t *pRemap;\r
-\r
- ch = remap;\r
-\r
- while( *ch && *ch != ';' )\r
- ch++;\r
-\r
- if( *ch == '\0' ) {\r
- // bad remap\r
- Sys_FPrintf( SYS_WRN, "WARNING: Shader _remap key found in a model entity without a ; character\n" );\r
- } else {\r
- pRemap = new remap_t;\r
-\r
- strncpy( pRemap->m_remapbuff, remap, sizeof(pRemap->m_remapbuff) );\r
-\r
- pRemap->m_remapbuff[ch - remap] = '\0';\r
-\r
- pRemap->original = pRemap->m_remapbuff;\r
- pRemap->remap = pRemap->m_remapbuff + ( ch - remap ) + 1;\r
-\r
- m_remaps.push_back( pRemap );\r
- }\r
- }\r
-\r
- void parse_namestr(const char *name)\r
- {\r
- const char *ptr, *s;\r
- char buf[1024];\r
- bool hasName, hasFrame;\r
-\r
- hasName = hasFrame = false;\r
-\r
- for( s = ptr = name; *ptr; ptr++ ) {\r
- if( !hasName && *ptr == ':' ) {\r
- // model name\r
- hasName = true;\r
- strncpy( buf, s, ptr - s );\r
- buf[ptr - s] = '\0';\r
- m_name = buf;\r
- s = ptr + 1;\r
- } else if( *ptr == '?' ) {\r
- // model frame\r
- hasFrame = true;\r
- strncpy( buf, s, ptr - s );\r
- buf[ptr - s] = '\0';\r
- m_frame = atoi(buf);\r
- s = ptr + 1;\r
- } else if( *ptr == '&' ) {\r
- // a remap\r
- strncpy( buf, s, ptr - s );\r
- buf[ptr - s] = '\0';\r
- add_remap( buf );\r
- s = ptr + 1;\r
- }\r
- }\r
-\r
- if( !hasFrame ) {\r
- // model frame\r
- strncpy( buf, s, ptr - s );\r
- buf[ptr - s] = '\0';\r
- m_frame = atoi(buf);\r
- } else {\r
- // a remap\r
- strncpy( buf, s, ptr - s );\r
- buf[ptr - s] = '\0';\r
- add_remap( buf );\r
- }\r
- }\r
-\r
- void construct_shaders()\r
- {\r
- IShader* global_shader = shader_for_remap("*");\r
-\r
- unsigned int numSurfaces = m_model->GetNumSurfaces();\r
- m_shaders.reserve(numSurfaces);\r
- // now go through our surface and find our shaders, remap if needed\r
- for(unsigned int j = 0; j < numSurfaces; j++ )\r
- {\r
- const char* surfShaderName = m_model->GetShaderNameForSurface(j);\r
- IShader* shader = shader_for_remap(surfShaderName);\r
-// m_shaders.push_back((shader) ? shader : (global_shader) ? global_shader : QERApp_Shader_ForName(surfShaderName));\r
- if( shader ) {\r
- m_shaders.push_back(shader);\r
- } else if( global_shader ) {\r
- m_shaders.push_back(global_shader);\r
- } else {\r
- m_shaders.push_back(QERApp_Shader_ForName(surfShaderName));\r
- }\r
- }\r
- }\r
- \r
- inline IShader* shader_for_remap(const char* remap)\r
- {\r
- remap_t *pRemap;\r
- remaps_t::iterator i;\r
- for(i = m_remaps.begin(); i != m_remaps.end(); ++i)\r
- {\r
- pRemap = (*i);\r
- if( stricmp( remap, pRemap->original ) == 0 )\r
- break;\r
- }\r
- return (i != m_remaps.end()) ? QERApp_Shader_ForName(pRemap->remap) : NULL;\r
- }\r
-\r
- Str m_name;\r
- int m_frame;\r
- CPicoModel* m_model;\r
-\r
- typedef vector<remap_t *> remaps_t;\r
- remaps_t m_remaps;\r
- typedef vector<IShader*> shaders_t;\r
- shaders_t m_shaders;\r
-};\r
-\r
-class ModelWrapper : public IRender, public ISelect\r
-{\r
- unsigned int m_refcount;\r
-public:\r
- ModelWrapper(entity_interfaces_t* model, const char* name)\r
- : m_refcount(1), m_name(name)\r
- {\r
- m_model = g_model_cache.capture(ModelCache::key_type(m_name.GetBuffer(), 0));\r
-\r
- model->pRender = this;\r
- model->pRender->IncRef();\r
- model->pEdit = NULL;\r
- model->pSelect = this;\r
- model->pSelect->IncRef();\r
- }\r
- virtual ~ModelWrapper()\r
- {\r
- g_model_cache.release(ModelCache::key_type(m_name.GetBuffer(), 0));\r
- }\r
-\r
- virtual void IncRef()\r
- {\r
- ++m_refcount;\r
- }\r
- virtual void DecRef()\r
- {\r
- if(--m_refcount == 0)\r
- delete this;\r
- }\r
- virtual void Draw(int state, int rflags) const\r
- {\r
- m_model->Draw(state, rflags);\r
- }\r
- virtual const aabb_t *GetAABB() const \r
- {\r
- return m_model->GetAABB();\r
- }\r
- virtual bool TestRay(const ray_t *ray, vec_t *dist) const\r
- {\r
- return m_model->TestRay(ray, dist);\r
- }\r
-\r
- Str m_name;\r
- CPicoModel* m_model;\r
-};\r
-\r
-void LoadModel(entity_interfaces_t* model, const char* name)\r
-{\r
- if(strchr(name, ':') != NULL || strchr(name, '?') != NULL || strchr(name, '&') != NULL)\r
- {\r
- RemapWrapper* wrapper = new RemapWrapper(model, name);\r
- wrapper->DecRef();\r
- }\r
- else\r
- {\r
- ModelWrapper* wrapper = new ModelWrapper(model, name);\r
- wrapper->DecRef();\r
- }\r
-}\r
+
+#include "cpicomodel.h"
+#include "qertypes.h"
+
+#include <map>
+#include <vector>
+
+#define RADIANT_ASSERT(condition, message) if(!(condition)) { Sys_Printf("ASSERTION FAILURE: " message "\n"); } else
+
+template<class key_type, class value_type>
+class cache_element
+{
+public:
+ inline cache_element() : m_count(0), m_value(NULL) {}
+ inline ~cache_element()
+ {
+ RADIANT_ASSERT(m_count == 0 , "destroyed a reference before it was released\n");
+ if(m_count > 0)
+ destroy();
+ }
+ inline value_type* capture(const key_type& key)
+ {
+ if(++m_count == 1)
+ construct(key);
+ return m_value;
+ }
+ inline void release()
+ {
+ RADIANT_ASSERT(!empty(), "failed to release reference - not found in cache\n");
+ if(--m_count == 0)
+ destroy();
+ }
+ inline bool empty()
+ {
+ return m_count == 0;
+ }
+ inline void refresh(const key_type& key)
+ {
+ m_value->refresh(key);
+ }
+private:
+ inline void construct(const key_type& key)
+ {
+ m_value = new value_type(key);
+ }
+ inline void destroy()
+ {
+ delete m_value;
+ }
+
+ unsigned int m_count;
+ value_type* m_value;
+};
+
+class ModelCache
+{
+ typedef CPicoModel value_type;
+
+public:
+ typedef PicoModelKey key_type;
+ typedef cache_element<key_type, value_type> elem_type;
+ typedef map<key_type, elem_type> cache_type;
+
+ value_type* capture(const key_type& key)
+ {
+ return m_cache[key].capture(key);
+ }
+ void release(const key_type& key)
+ {
+ m_cache[key].release();
+ }
+
+private:
+ cache_type m_cache;
+};
+
+ModelCache g_model_cache;
+
+
+
+typedef struct remap_s {
+ char m_remapbuff[64+1024];
+ char *original;
+ char *remap;
+} remap_t;
+
+class RemapWrapper : public IRender, public ISelect
+{
+ unsigned int m_refcount;
+public:
+ RemapWrapper(entity_interfaces_t* model, const char* name)
+ : m_refcount(1)
+ {
+ parse_namestr(name);
+
+ m_model = g_model_cache.capture(ModelCache::key_type(m_name.GetBuffer(), m_frame));
+
+ model->pRender = this;
+ model->pRender->IncRef();
+ model->pEdit = NULL;
+ model->pSelect = this;
+ model->pSelect->IncRef();
+
+ construct_shaders();
+ }
+ virtual ~RemapWrapper()
+ {
+ g_model_cache.release(ModelCache::key_type(m_name.GetBuffer(), m_frame));
+
+ for(shaders_t::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i) {
+ (*i)->DecRef();
+ }
+
+ for(remaps_t::iterator j = m_remaps.begin(); j != m_remaps.end(); ++j)
+ {
+ remap_t *pRemap = (*j);
+ delete pRemap;
+ }
+ m_remaps.clear();
+ }
+ virtual void IncRef()
+ {
+ ++m_refcount;
+ }
+ virtual void DecRef()
+ {
+ if(--m_refcount == 0)
+ delete this;
+ }
+ virtual void Draw(int state, int rflags) const
+ {
+ m_model->Draw(state, m_shaders, rflags);
+ }
+ virtual const aabb_t *GetAABB() const
+ {
+ return m_model->GetAABB();
+ }
+ virtual bool TestRay(const ray_t *ray, vec_t *dist) const
+ {
+ return m_model->TestRay(ray, dist);
+ }
+private:
+ void add_remap(const char *remap)
+ {
+ const char *ch;
+ remap_t *pRemap;
+
+ ch = remap;
+
+ while( *ch && *ch != ';' )
+ ch++;
+
+ if( *ch == '\0' ) {
+ // bad remap
+ Sys_FPrintf( SYS_WRN, "WARNING: Shader _remap key found in a model entity without a ; character\n" );
+ } else {
+ pRemap = new remap_t;
+
+ strncpy( pRemap->m_remapbuff, remap, sizeof(pRemap->m_remapbuff) );
+
+ pRemap->m_remapbuff[ch - remap] = '\0';
+
+ pRemap->original = pRemap->m_remapbuff;
+ pRemap->remap = pRemap->m_remapbuff + ( ch - remap ) + 1;
+
+ m_remaps.push_back( pRemap );
+ }
+ }
+
+ void parse_namestr(const char *name)
+ {
+ const char *ptr, *s;
+ char buf[1024];
+ bool hasName, hasFrame;
+
+ hasName = hasFrame = false;
+
+ for( s = ptr = name; *ptr; ptr++ ) {
+ if( !hasName && *ptr == ':' ) {
+ // model name
+ hasName = true;
+ strncpy( buf, s, ptr - s );
+ buf[ptr - s] = '\0';
+ m_name = buf;
+ s = ptr + 1;
+ } else if( *ptr == '?' ) {
+ // model frame
+ hasFrame = true;
+ strncpy( buf, s, ptr - s );
+ buf[ptr - s] = '\0';
+ m_frame = atoi(buf);
+ s = ptr + 1;
+ } else if( *ptr == '&' ) {
+ // a remap
+ strncpy( buf, s, ptr - s );
+ buf[ptr - s] = '\0';
+ add_remap( buf );
+ s = ptr + 1;
+ }
+ }
+
+ if( !hasFrame ) {
+ // model frame
+ strncpy( buf, s, ptr - s );
+ buf[ptr - s] = '\0';
+ m_frame = atoi(buf);
+ } else {
+ // a remap
+ strncpy( buf, s, ptr - s );
+ buf[ptr - s] = '\0';
+ add_remap( buf );
+ }
+ }
+
+ void construct_shaders()
+ {
+ IShader* global_shader = shader_for_remap("*");
+
+ unsigned int numSurfaces = m_model->GetNumSurfaces();
+ m_shaders.reserve(numSurfaces);
+ // now go through our surface and find our shaders, remap if needed
+ for(unsigned int j = 0; j < numSurfaces; j++ )
+ {
+ const char* surfShaderName = m_model->GetShaderNameForSurface(j);
+ IShader* shader = shader_for_remap(surfShaderName);
+// m_shaders.push_back((shader) ? shader : (global_shader) ? global_shader : QERApp_Shader_ForName(surfShaderName));
+ // Determine which shader it is going to be
+ if( !shader ) {
+ if( global_shader ) {
+ shader = global_shader;
+ } else {
+ shader = QERApp_Shader_ForName(surfShaderName);
+ }
+ }
+ // Add reference
+ shader->IncRef();
+ // Done, continue
+ m_shaders.push_back( shader );
+ }
+ }
+
+ inline IShader* shader_for_remap(const char* remap)
+ {
+ remap_t *pRemap;
+ remaps_t::iterator i;
+ for(i = m_remaps.begin(); i != m_remaps.end(); ++i)
+ {
+ pRemap = (*i);
+ if( stricmp( remap, pRemap->original ) == 0 )
+ break;
+ }
+ return (i != m_remaps.end()) ? QERApp_Shader_ForName(pRemap->remap) : NULL;
+ }
+
+ Str m_name;
+ int m_frame;
+ CPicoModel* m_model;
+
+ typedef vector<remap_t *> remaps_t;
+ remaps_t m_remaps;
+ typedef vector<IShader*> shaders_t;
+ shaders_t m_shaders;
+};
+
+class ModelWrapper : public IRender, public ISelect
+{
+ unsigned int m_refcount;
+public:
+ ModelWrapper(entity_interfaces_t* model, const char* name)
+ : m_refcount(1), m_name(name)
+ {
+ m_model = g_model_cache.capture(ModelCache::key_type(m_name.GetBuffer(), 0));
+
+ model->pRender = this;
+ model->pRender->IncRef();
+ model->pEdit = NULL;
+ model->pSelect = this;
+ model->pSelect->IncRef();
+ }
+ virtual ~ModelWrapper()
+ {
+ g_model_cache.release(ModelCache::key_type(m_name.GetBuffer(), 0));
+ }
+
+ virtual void IncRef()
+ {
+ ++m_refcount;
+ }
+ virtual void DecRef()
+ {
+ if(--m_refcount == 0)
+ delete this;
+ }
+ virtual void Draw(int state, int rflags) const
+ {
+ m_model->Draw(state, rflags);
+ }
+ virtual const aabb_t *GetAABB() const
+ {
+ return m_model->GetAABB();
+ }
+ virtual bool TestRay(const ray_t *ray, vec_t *dist) const
+ {
+ return m_model->TestRay(ray, dist);
+ }
+
+ Str m_name;
+ CPicoModel* m_model;
+};
+
+void LoadModel(entity_interfaces_t* model, const char* name)
+{
+ if(strchr(name, ':') != NULL || strchr(name, '?') != NULL || strchr(name, '&') != NULL)
+ {
+ RemapWrapper* wrapper = new RemapWrapper(model, name);
+ wrapper->DecRef();
+ }
+ else
+ {
+ ModelWrapper* wrapper = new ModelWrapper(model, name);
+ wrapper->DecRef();
+ }
+}