2 #include "cpicomodel.h"
8 #define RADIANT_ASSERT( condition, message ) if ( !( condition ) ) { Sys_Printf( "ASSERTION FAILURE: " message "\n" ); } else
10 template<class key_type, class value_type>
14 inline cache_element() : m_count( 0 ), m_value( NULL ) {}
15 inline ~cache_element(){
16 RADIANT_ASSERT( m_count == 0, "destroyed a reference before it was released\n" );
21 inline value_type* capture( const key_type& key ){
22 if ( ++m_count == 1 ) {
27 inline void release(){
28 RADIANT_ASSERT( !empty(), "failed to release reference - not found in cache\n" );
29 if ( --m_count == 0 ) {
36 inline void refresh( const key_type& key ){
37 m_value->refresh( key );
40 inline void construct( const key_type& key ){
41 m_value = new value_type( key );
43 inline void destroy(){
53 typedef CPicoModel value_type;
56 typedef PicoModelKey key_type;
57 typedef cache_element<key_type, value_type> elem_type;
58 typedef map<key_type, elem_type> cache_type;
60 value_type* capture( const key_type& key ){
61 return m_cache[key].capture( key );
63 void release( const key_type& key ){
64 m_cache[key].release();
71 ModelCache g_model_cache;
75 typedef struct remap_s {
76 char m_remapbuff[64 + 1024];
81 class RemapWrapper : public IRender, public ISelect
83 unsigned int m_refcount;
85 RemapWrapper( entity_interfaces_t* model, const char* name )
87 parse_namestr( name );
89 m_model = g_model_cache.capture( ModelCache::key_type( m_name.GetBuffer(), m_frame ) );
91 model->pRender = this;
92 model->pRender->IncRef();
94 model->pSelect = this;
95 model->pSelect->IncRef();
99 virtual ~RemapWrapper(){
100 g_model_cache.release( ModelCache::key_type( m_name.GetBuffer(), m_frame ) );
102 for ( shaders_t::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i ) {
106 for ( remaps_t::iterator j = m_remaps.begin(); j != m_remaps.end(); ++j )
108 remap_t *pRemap = ( *j );
113 virtual void IncRef(){
116 virtual void DecRef(){
117 if ( --m_refcount == 0 ) {
121 virtual void Draw( int state, int rflags ) const {
122 m_model->Draw( state, m_shaders, rflags );
124 virtual const aabb_t *GetAABB() const {
125 return m_model->GetAABB();
127 virtual bool TestRay( const ray_t *ray, vec_t *dist ) const {
128 return m_model->TestRay( ray, dist );
131 void add_remap( const char *remap ){
137 while ( *ch && *ch != ';' )
142 Sys_FPrintf( SYS_WRN, "WARNING: Shader _remap key found in a model entity without a ; character\n" );
145 pRemap = new remap_t;
147 strncpy( pRemap->m_remapbuff, remap, sizeof( pRemap->m_remapbuff ) );
149 pRemap->m_remapbuff[ch - remap] = '\0';
151 pRemap->original = pRemap->m_remapbuff;
152 pRemap->remap = pRemap->m_remapbuff + ( ch - remap ) + 1;
154 m_remaps.push_back( pRemap );
158 void parse_namestr( const char *name ){
161 bool hasName, hasFrame;
163 hasName = hasFrame = false;
165 for ( s = ptr = name; *ptr; ptr++ ) {
166 if ( !hasName && *ptr == ':' ) {
169 strncpy( buf, s, ptr - s );
174 else if ( *ptr == '?' ) {
177 strncpy( buf, s, ptr - s );
179 m_frame = atoi( buf );
182 else if ( *ptr == '&' ) {
184 strncpy( buf, s, ptr - s );
193 strncpy( buf, s, ptr - s );
195 m_frame = atoi( buf );
199 strncpy( buf, s, ptr - s );
205 void construct_shaders(){
206 IShader* global_shader = shader_for_remap( "*" );
208 unsigned int numSurfaces = m_model->GetNumSurfaces();
209 m_shaders.reserve( numSurfaces );
210 // now go through our surface and find our shaders, remap if needed
211 for ( unsigned int j = 0; j < numSurfaces; j++ )
213 const char* surfShaderName = m_model->GetShaderNameForSurface( j );
214 IShader* shader = shader_for_remap( surfShaderName );
215 // Determine which shader it is going to be
217 if ( global_shader ) {
218 shader = global_shader;
221 shader = QERApp_Shader_ForName( surfShaderName );
227 m_shaders.push_back( shader );
231 inline IShader* shader_for_remap( const char* remap ){
233 remaps_t::iterator i;
234 for ( i = m_remaps.begin(); i != m_remaps.end(); ++i )
237 if ( stricmp( remap, pRemap->original ) == 0 ) {
241 return ( i != m_remaps.end() ) ? QERApp_Shader_ForName( pRemap->remap ) : NULL;
248 typedef vector<remap_t *> remaps_t;
250 typedef vector<IShader*> shaders_t;
254 class ModelWrapper : public IRender, public ISelect
256 unsigned int m_refcount;
258 ModelWrapper( entity_interfaces_t* model, const char* name )
259 : m_refcount( 1 ), m_name( name ){
260 m_model = g_model_cache.capture( ModelCache::key_type( m_name.GetBuffer(), 0 ) );
262 model->pRender = this;
263 model->pRender->IncRef();
265 model->pSelect = this;
266 model->pSelect->IncRef();
268 virtual ~ModelWrapper(){
269 g_model_cache.release( ModelCache::key_type( m_name.GetBuffer(), 0 ) );
272 virtual void IncRef(){
275 virtual void DecRef(){
276 if ( --m_refcount == 0 ) {
280 virtual void Draw( int state, int rflags ) const {
281 m_model->Draw( state, rflags );
283 virtual const aabb_t *GetAABB() const {
284 return m_model->GetAABB();
286 virtual bool TestRay( const ray_t *ray, vec_t *dist ) const {
287 return m_model->TestRay( ray, dist );
294 void LoadModel( entity_interfaces_t* model, const char* name ){
295 if ( strchr( name, ':' ) != NULL || strchr( name, '?' ) != NULL || strchr( name, '&' ) != NULL ) {
296 RemapWrapper* wrapper = new RemapWrapper( model, name );
301 ModelWrapper* wrapper = new ModelWrapper( model, name );