2 #include "cpicomodel.h"
\r
3 #include "qertypes.h"
\r
8 #define RADIANT_ASSERT(condition, message) if(!(condition)) { Sys_Printf("ASSERTION FAILURE: " message "\n"); } else
\r
10 template<class key_type, class value_type>
\r
14 inline cache_element() : m_count(0), m_value(NULL) {}
\r
15 inline ~cache_element()
\r
17 RADIANT_ASSERT(m_count == 0 , "destroyed a reference before it was released\n");
\r
21 inline value_type* capture(const key_type& key)
\r
27 inline void release()
\r
29 RADIANT_ASSERT(!empty(), "failed to release reference - not found in cache\n");
\r
35 return m_count == 0;
\r
37 inline void refresh(const key_type& key)
\r
39 m_value->refresh(key);
\r
42 inline void construct(const key_type& key)
\r
44 m_value = new value_type(key);
\r
46 inline void destroy()
\r
51 unsigned int m_count;
\r
52 value_type* m_value;
\r
57 typedef CPicoModel value_type;
\r
60 typedef PicoModelKey key_type;
\r
61 typedef cache_element<key_type, value_type> elem_type;
\r
62 typedef map<key_type, elem_type> cache_type;
\r
64 value_type* capture(const key_type& key)
\r
66 return m_cache[key].capture(key);
\r
68 void release(const key_type& key)
\r
70 m_cache[key].release();
\r
77 ModelCache g_model_cache;
\r
81 typedef struct remap_s {
\r
82 char m_remapbuff[64+1024];
\r
87 class RemapWrapper : public IRender, public ISelect
\r
89 unsigned int m_refcount;
\r
91 RemapWrapper(entity_interfaces_t* model, const char* name)
\r
94 parse_namestr(name);
\r
96 m_model = g_model_cache.capture(ModelCache::key_type(m_name.GetBuffer(), m_frame));
\r
98 model->pRender = this;
\r
99 model->pRender->IncRef();
\r
100 model->pEdit = NULL;
\r
101 model->pSelect = this;
\r
102 model->pSelect->IncRef();
\r
104 construct_shaders();
\r
106 virtual ~RemapWrapper()
\r
108 g_model_cache.release(ModelCache::key_type(m_name.GetBuffer(), m_frame));
\r
110 for(shaders_t::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i) {
\r
114 for(remaps_t::iterator j = m_remaps.begin(); j != m_remaps.end(); ++j)
\r
116 remap_t *pRemap = (*j);
\r
121 virtual void IncRef()
\r
125 virtual void DecRef()
\r
127 if(--m_refcount == 0)
\r
130 virtual void Draw(int state, int rflags) const
\r
132 m_model->Draw(state, m_shaders, rflags);
\r
134 virtual const aabb_t *GetAABB() const
\r
136 return m_model->GetAABB();
\r
138 virtual bool TestRay(const ray_t *ray, vec_t *dist) const
\r
140 return m_model->TestRay(ray, dist);
\r
143 void add_remap(const char *remap)
\r
150 while( *ch && *ch != ';' )
\r
153 if( *ch == '\0' ) {
\r
155 Sys_FPrintf( SYS_WRN, "WARNING: Shader _remap key found in a model entity without a ; character\n" );
\r
157 pRemap = new remap_t;
\r
159 strncpy( pRemap->m_remapbuff, remap, sizeof(pRemap->m_remapbuff) );
\r
161 pRemap->m_remapbuff[ch - remap] = '\0';
\r
163 pRemap->original = pRemap->m_remapbuff;
\r
164 pRemap->remap = pRemap->m_remapbuff + ( ch - remap ) + 1;
\r
166 m_remaps.push_back( pRemap );
\r
170 void parse_namestr(const char *name)
\r
172 const char *ptr, *s;
\r
174 bool hasName, hasFrame;
\r
176 hasName = hasFrame = false;
\r
178 for( s = ptr = name; *ptr; ptr++ ) {
\r
179 if( !hasName && *ptr == ':' ) {
\r
182 strncpy( buf, s, ptr - s );
\r
183 buf[ptr - s] = '\0';
\r
186 } else if( *ptr == '?' ) {
\r
189 strncpy( buf, s, ptr - s );
\r
190 buf[ptr - s] = '\0';
\r
191 m_frame = atoi(buf);
\r
193 } else if( *ptr == '&' ) {
\r
195 strncpy( buf, s, ptr - s );
\r
196 buf[ptr - s] = '\0';
\r
204 strncpy( buf, s, ptr - s );
\r
205 buf[ptr - s] = '\0';
\r
206 m_frame = atoi(buf);
\r
209 strncpy( buf, s, ptr - s );
\r
210 buf[ptr - s] = '\0';
\r
215 void construct_shaders()
\r
217 IShader* global_shader = shader_for_remap("*");
\r
219 unsigned int numSurfaces = m_model->GetNumSurfaces();
\r
220 m_shaders.reserve(numSurfaces);
\r
221 // now go through our surface and find our shaders, remap if needed
\r
222 for(unsigned int j = 0; j < numSurfaces; j++ )
\r
224 const char* surfShaderName = m_model->GetShaderNameForSurface(j);
\r
225 IShader* shader = shader_for_remap(surfShaderName);
\r
226 // m_shaders.push_back((shader) ? shader : (global_shader) ? global_shader : QERApp_Shader_ForName(surfShaderName));
\r
228 m_shaders.push_back(shader);
\r
229 } else if( global_shader ) {
\r
230 m_shaders.push_back(global_shader);
\r
232 m_shaders.push_back(QERApp_Shader_ForName(surfShaderName));
\r
237 inline IShader* shader_for_remap(const char* remap)
\r
240 remaps_t::iterator i;
\r
241 for(i = m_remaps.begin(); i != m_remaps.end(); ++i)
\r
244 if( stricmp( remap, pRemap->original ) == 0 )
\r
247 return (i != m_remaps.end()) ? QERApp_Shader_ForName(pRemap->remap) : NULL;
\r
252 CPicoModel* m_model;
\r
254 typedef vector<remap_t *> remaps_t;
\r
256 typedef vector<IShader*> shaders_t;
\r
257 shaders_t m_shaders;
\r
260 class ModelWrapper : public IRender, public ISelect
\r
262 unsigned int m_refcount;
\r
264 ModelWrapper(entity_interfaces_t* model, const char* name)
\r
265 : m_refcount(1), m_name(name)
\r
267 m_model = g_model_cache.capture(ModelCache::key_type(m_name.GetBuffer(), 0));
\r
269 model->pRender = this;
\r
270 model->pRender->IncRef();
\r
271 model->pEdit = NULL;
\r
272 model->pSelect = this;
\r
273 model->pSelect->IncRef();
\r
275 virtual ~ModelWrapper()
\r
277 g_model_cache.release(ModelCache::key_type(m_name.GetBuffer(), 0));
\r
280 virtual void IncRef()
\r
284 virtual void DecRef()
\r
286 if(--m_refcount == 0)
\r
289 virtual void Draw(int state, int rflags) const
\r
291 m_model->Draw(state, rflags);
\r
293 virtual const aabb_t *GetAABB() const
\r
295 return m_model->GetAABB();
\r
297 virtual bool TestRay(const ray_t *ray, vec_t *dist) const
\r
299 return m_model->TestRay(ray, dist);
\r
303 CPicoModel* m_model;
\r
306 void LoadModel(entity_interfaces_t* model, const char* name)
\r
308 if(strchr(name, ':') != NULL || strchr(name, '?') != NULL || strchr(name, '&') != NULL)
\r
310 RemapWrapper* wrapper = new RemapWrapper(model, name);
\r
315 ModelWrapper* wrapper = new ModelWrapper(model, name);
\r