]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - plugins/md3model/model.h
my own uncrustify run
[xonotic/netradiant.git] / plugins / md3model / model.h
1 /*
2    Copyright (C) 2001-2006, William Joseph.
3    All Rights Reserved.
4
5    This file is part of GtkRadiant.
6
7    GtkRadiant is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    GtkRadiant is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GtkRadiant; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 #if !defined( INCLUDED_MODEL_H )
23 #define INCLUDED_MODEL_H
24
25 #include "cullable.h"
26 #include "renderable.h"
27 #include "selectable.h"
28 #include "modelskin.h"
29
30 #include "math/frustum.h"
31 #include "string/string.h"
32 #include "generic/static.h"
33 #include "stream/stringstream.h"
34 #include "os/path.h"
35 #include "scenelib.h"
36 #include "instancelib.h"
37 #include "transformlib.h"
38 #include "traverselib.h"
39 #include "render.h"
40
41 class VectorLightList : public LightList
42 {
43 typedef std::vector<const RendererLight*> Lights;
44 Lights m_lights;
45 public:
46 void addLight( const RendererLight& light ){
47         m_lights.push_back( &light );
48 }
49 void clear(){
50         m_lights.clear();
51 }
52 void evaluateLights() const {
53 }
54 void lightsChanged() const {
55 }
56 void forEachLight( const RendererLightCallback& callback ) const {
57         for ( Lights::const_iterator i = m_lights.begin(); i != m_lights.end(); ++i )
58         {
59                 callback( *( *i ) );
60         }
61 }
62 };
63
64 inline VertexPointer vertexpointer_arbitrarymeshvertex( const ArbitraryMeshVertex* array ){
65         return VertexPointer( VertexPointer::pointer( &array->vertex ), sizeof( ArbitraryMeshVertex ) );
66 }
67
68 inline void parseTextureName( CopiedString& name, const char* token ){
69         StringOutputStream cleaned( 256 );
70         cleaned << PathCleaned( token );
71         name = StringRange( cleaned.c_str(), path_get_filename_base_end( cleaned.c_str() ) ); // remove extension
72 }
73
74 // generic renderable triangle surface
75 class Surface :
76         public OpenGLRenderable
77 {
78 public:
79 typedef VertexBuffer<ArbitraryMeshVertex> vertices_t;
80 typedef IndexBuffer indices_t;
81 private:
82
83 AABB m_aabb_local;
84 CopiedString m_shader;
85 Shader* m_state;
86
87 vertices_t m_vertices;
88 indices_t m_indices;
89
90 void CaptureShader(){
91         m_state = GlobalShaderCache().capture( m_shader.c_str() );
92 }
93 void ReleaseShader(){
94         GlobalShaderCache().release( m_shader.c_str() );
95 }
96
97 public:
98
99 Surface()
100         : m_shader( "" ), m_state( 0 ){
101         CaptureShader();
102 }
103 ~Surface(){
104         ReleaseShader();
105 }
106
107 vertices_t& vertices(){
108         return m_vertices;
109 }
110 indices_t& indices(){
111         return m_indices;
112 }
113
114 void setShader( const char* name ){
115         ReleaseShader();
116         parseTextureName( m_shader, name );
117         CaptureShader();
118 }
119 const char* getShader() const {
120         return m_shader.c_str();
121 }
122 Shader* getState() const {
123         return m_state;
124 }
125 void updateAABB(){
126         m_aabb_local = AABB();
127         for ( vertices_t::iterator i = m_vertices.begin(); i != m_vertices.end(); ++i )
128                 aabb_extend_by_point_safe( m_aabb_local, reinterpret_cast<const Vector3&>( ( *i ).vertex ) );
129
130
131
132         for ( Surface::indices_t::iterator i = m_indices.begin(); i != m_indices.end(); i += 3 )
133         {
134                 ArbitraryMeshVertex& a = m_vertices[*( i + 0 )];
135                 ArbitraryMeshVertex& b = m_vertices[*( i + 1 )];
136                 ArbitraryMeshVertex& c = m_vertices[*( i + 2 )];
137
138                 ArbitraryMeshTriangle_sumTangents( a, b, c );
139         }
140
141         for ( Surface::vertices_t::iterator i = m_vertices.begin(); i != m_vertices.end(); ++i )
142         {
143                 vector3_normalise( reinterpret_cast<Vector3&>( ( *i ).tangent ) );
144                 vector3_normalise( reinterpret_cast<Vector3&>( ( *i ).bitangent ) );
145         }
146 }
147
148 void render( RenderStateFlags state ) const {
149 #if 1
150         if ( ( state & RENDER_BUMP ) != 0 ) {
151                 if ( GlobalShaderCache().useShaderLanguage() ) {
152                         glNormalPointer( GL_FLOAT, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->normal );
153                         glVertexAttribPointerARB( c_attr_TexCoord0, 2, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->texcoord );
154                         glVertexAttribPointerARB( c_attr_Tangent, 3, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->tangent );
155                         glVertexAttribPointerARB( c_attr_Binormal, 3, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->bitangent );
156                 }
157                 else
158                 {
159                         glVertexAttribPointerARB( 11, 3, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->normal );
160                         glVertexAttribPointerARB( 8, 2, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->texcoord );
161                         glVertexAttribPointerARB( 9, 3, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->tangent );
162                         glVertexAttribPointerARB( 10, 3, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->bitangent );
163                 }
164         }
165         else
166         {
167                 glNormalPointer( GL_FLOAT, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->normal );
168                 glTexCoordPointer( 2, GL_FLOAT, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->texcoord );
169         }
170         glVertexPointer( 3, GL_FLOAT, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->vertex );
171         glDrawElements( GL_TRIANGLES, GLsizei( m_indices.size() ), RenderIndexTypeID, m_indices.data() );
172 #else
173         glBegin( GL_TRIANGLES );
174         for ( unsigned int i = 0; i < m_indices.size(); ++i )
175         {
176                 glTexCoord2fv( &m_vertices[m_indices[i]].texcoord.s );
177                 glNormal3fv( &m_vertices[m_indices[i]].normal.x );
178                 glVertex3fv( &m_vertices[m_indices[i]].vertex.x );
179         }
180         glEnd();
181 #endif
182
183 #if defined( _DEBUG )
184         glBegin( GL_LINES );
185
186         for ( VertexBuffer<ArbitraryMeshVertex>::const_iterator i = m_vertices.begin(); i != m_vertices.end(); ++i )
187         {
188                 Vector3 normal = vector3_added( vertex3f_to_vector3( ( *i ).vertex ), vector3_scaled( normal3f_to_vector3( ( *i ).normal ), 8 ) );
189                 glVertex3fv( vertex3f_to_array( ( *i ).vertex ) );
190                 glVertex3fv( vector3_to_array( normal ) );
191         }
192         glEnd();
193 #endif
194 }
195
196 VolumeIntersectionValue intersectVolume( const VolumeTest& test, const Matrix4& localToWorld ) const {
197         return test.TestAABB( m_aabb_local, localToWorld );
198 }
199
200 const AABB& localAABB() const {
201         return m_aabb_local;
202 }
203
204 void render( Renderer& renderer, const Matrix4& localToWorld, Shader* state ) const {
205         renderer.SetState( state, Renderer::eFullMaterials );
206         renderer.addRenderable( *this, localToWorld );
207 }
208
209 void render( Renderer& renderer, const Matrix4& localToWorld ) const {
210         render( renderer, localToWorld, m_state );
211 }
212
213 void testSelect( Selector& selector, SelectionTest& test, const Matrix4& localToWorld ){
214         test.BeginMesh( localToWorld );
215
216         SelectionIntersection best;
217         test.TestTriangles(
218                 vertexpointer_arbitrarymeshvertex( m_vertices.data() ),
219                 IndexPointer( m_indices.data(), IndexPointer::index_type( m_indices.size() ) ),
220                 best
221                 );
222         if ( best.valid() ) {
223                 selector.addIntersection( best );
224         }
225 }
226 };
227
228 // generic model node
229 class Model :
230         public Cullable,
231         public Bounded
232 {
233 typedef std::vector<Surface*> surfaces_t;
234 surfaces_t m_surfaces;
235
236 AABB m_aabb_local;
237 public:
238 Callback m_lightsChanged;
239
240 ~Model(){
241         for ( surfaces_t::iterator i = m_surfaces.begin(); i != m_surfaces.end(); ++i )
242         {
243                 delete *i;
244         }
245 }
246
247 typedef surfaces_t::const_iterator const_iterator;
248
249 const_iterator begin() const {
250         return m_surfaces.begin();
251 }
252 const_iterator end() const {
253         return m_surfaces.end();
254 }
255 std::size_t size() const {
256         return m_surfaces.size();
257 }
258
259 Surface& newSurface(){
260         m_surfaces.push_back( new Surface );
261         return *m_surfaces.back();
262 }
263 void updateAABB(){
264         m_aabb_local = AABB();
265         for ( surfaces_t::iterator i = m_surfaces.begin(); i != m_surfaces.end(); ++i )
266         {
267                 aabb_extend_by_aabb_safe( m_aabb_local, ( *i )->localAABB() );
268         }
269 }
270
271 VolumeIntersectionValue intersectVolume( const VolumeTest& test, const Matrix4& localToWorld ) const {
272         return test.TestAABB( m_aabb_local, localToWorld );
273 }
274
275 virtual const AABB& localAABB() const {
276         return m_aabb_local;
277 }
278
279 void testSelect( Selector& selector, SelectionTest& test, const Matrix4& localToWorld ){
280         for ( surfaces_t::iterator i = m_surfaces.begin(); i != m_surfaces.end(); ++i )
281         {
282                 if ( ( *i )->intersectVolume( test.getVolume(), localToWorld ) != c_volumeOutside ) {
283                         ( *i )->testSelect( selector, test, localToWorld );
284                 }
285         }
286 }
287 };
288
289 inline void Surface_addLight( const Surface& surface, VectorLightList& lights, const Matrix4& localToWorld, const RendererLight& light ){
290         if ( light.testAABB( aabb_for_oriented_aabb( surface.localAABB(), localToWorld ) ) ) {
291                 lights.addLight( light );
292         }
293 }
294
295 class ModelInstance :
296         public scene::Instance,
297         public Renderable,
298         public SelectionTestable,
299         public LightCullable,
300         public SkinnedModel
301 {
302 class TypeCasts
303 {
304 InstanceTypeCastTable m_casts;
305 public:
306 TypeCasts(){
307         InstanceContainedCast<ModelInstance, Bounded>::install( m_casts );
308         InstanceContainedCast<ModelInstance, Cullable>::install( m_casts );
309         InstanceStaticCast<ModelInstance, Renderable>::install( m_casts );
310         InstanceStaticCast<ModelInstance, SelectionTestable>::install( m_casts );
311         InstanceStaticCast<ModelInstance, SkinnedModel>::install( m_casts );
312 }
313 InstanceTypeCastTable& get(){
314         return m_casts;
315 }
316 };
317
318 Model& m_model;
319
320 const LightList* m_lightList;
321 typedef Array<VectorLightList> SurfaceLightLists;
322 SurfaceLightLists m_surfaceLightLists;
323
324 class Remap
325 {
326 public:
327 CopiedString first;
328 Shader* second;
329 Remap() : second( 0 ){
330 }
331 };
332 typedef Array<Remap> SurfaceRemaps;
333 SurfaceRemaps m_skins;
334 public:
335
336 typedef LazyStatic<TypeCasts> StaticTypeCasts;
337
338 Bounded& get( NullType<Bounded>){
339         return m_model;
340 }
341 Cullable& get( NullType<Cullable>){
342         return m_model;
343 }
344
345 void lightsChanged(){
346         m_lightList->lightsChanged();
347 }
348 typedef MemberCaller<ModelInstance, &ModelInstance::lightsChanged> LightsChangedCaller;
349
350 void constructRemaps(){
351         ModelSkin* skin = NodeTypeCast<ModelSkin>::cast( path().parent() );
352         if ( skin != 0 && skin->realised() ) {
353                 SurfaceRemaps::iterator j = m_skins.begin();
354                 for ( Model::const_iterator i = m_model.begin(); i != m_model.end(); ++i, ++j )
355                 {
356                         const char* remap = skin->getRemap( ( *i )->getShader() );
357                         if ( !string_empty( remap ) ) {
358                                 ( *j ).first = remap;
359                                 ( *j ).second = GlobalShaderCache().capture( remap );
360                         }
361                         else
362                         {
363                                 ( *j ).second = 0;
364                         }
365                 }
366                 SceneChangeNotify();
367         }
368 }
369 void destroyRemaps(){
370         for ( SurfaceRemaps::iterator i = m_skins.begin(); i != m_skins.end(); ++i )
371         {
372                 if ( ( *i ).second != 0 ) {
373                         GlobalShaderCache().release( ( *i ).first.c_str() );
374                         ( *i ).second = 0;
375                 }
376         }
377 }
378 void skinChanged(){
379         ASSERT_MESSAGE( m_skins.size() == m_model.size(), "ERROR" );
380         destroyRemaps();
381         constructRemaps();
382 }
383
384 ModelInstance( const scene::Path& path, scene::Instance* parent, Model& model ) :
385         Instance( path, parent, this, StaticTypeCasts::instance().get() ),
386         m_model( model ),
387         m_surfaceLightLists( m_model.size() ),
388         m_skins( m_model.size() ){
389         m_lightList = &GlobalShaderCache().attach( *this );
390         m_model.m_lightsChanged = LightsChangedCaller( *this );
391
392         Instance::setTransformChangedCallback( LightsChangedCaller( *this ) );
393
394         constructRemaps();
395 }
396 ~ModelInstance(){
397         destroyRemaps();
398
399         Instance::setTransformChangedCallback( Callback() );
400
401         m_model.m_lightsChanged = Callback();
402         GlobalShaderCache().detach( *this );
403 }
404
405 void render( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const {
406         SurfaceLightLists::const_iterator j = m_surfaceLightLists.begin();
407         SurfaceRemaps::const_iterator k = m_skins.begin();
408         for ( Model::const_iterator i = m_model.begin(); i != m_model.end(); ++i, ++j, ++k )
409         {
410                 if ( ( *i )->intersectVolume( volume, localToWorld ) != c_volumeOutside ) {
411                         renderer.setLights( *j );
412                         ( *i )->render( renderer, localToWorld, ( *k ).second != 0 ? ( *k ).second : ( *i )->getState() );
413                 }
414         }
415 }
416
417 void renderSolid( Renderer& renderer, const VolumeTest& volume ) const {
418         m_lightList->evaluateLights();
419
420         render( renderer, volume, Instance::localToWorld() );
421 }
422 void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const {
423         renderSolid( renderer, volume );
424 }
425
426 void testSelect( Selector& selector, SelectionTest& test ){
427         m_model.testSelect( selector, test, Instance::localToWorld() );
428 }
429
430 bool testLight( const RendererLight& light ) const {
431         return light.testAABB( worldAABB() );
432 }
433 void insertLight( const RendererLight& light ){
434         const Matrix4& localToWorld = Instance::localToWorld();
435         SurfaceLightLists::iterator j = m_surfaceLightLists.begin();
436         for ( Model::const_iterator i = m_model.begin(); i != m_model.end(); ++i )
437         {
438                 Surface_addLight( *( *i ), *j++, localToWorld, light );
439         }
440 }
441 void clearLights(){
442         for ( SurfaceLightLists::iterator i = m_surfaceLightLists.begin(); i != m_surfaceLightLists.end(); ++i )
443         {
444                 ( *i ).clear();
445         }
446 }
447 };
448
449 class ModelNode : public scene::Node::Symbiot, public scene::Instantiable
450 {
451 class TypeCasts
452 {
453 NodeTypeCastTable m_casts;
454 public:
455 TypeCasts(){
456         NodeStaticCast<ModelNode, scene::Instantiable>::install( m_casts );
457 }
458 NodeTypeCastTable& get(){
459         return m_casts;
460 }
461 };
462
463
464 scene::Node m_node;
465 InstanceSet m_instances;
466 Model m_model;
467 public:
468
469 typedef LazyStatic<TypeCasts> StaticTypeCasts;
470
471 ModelNode() : m_node( this, this, StaticTypeCasts::instance().get() ){
472 }
473
474 Model& model(){
475         return m_model;
476 }
477
478 void release(){
479         delete this;
480 }
481 scene::Node& node(){
482         return m_node;
483 }
484
485 scene::Instance* create( const scene::Path& path, scene::Instance* parent ){
486         return new ModelInstance( path, parent, m_model );
487 }
488 void forEachInstance( const scene::Instantiable::Visitor& visitor ){
489         m_instances.forEachInstance( visitor );
490 }
491 void insert( scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance ){
492         m_instances.insert( observer, path, instance );
493 }
494 scene::Instance* erase( scene::Instantiable::Observer* observer, const scene::Path& path ){
495         return m_instances.erase( observer, path );
496 }
497 };
498
499
500 inline void Surface_constructQuad( Surface& surface, const Vector3& a, const Vector3& b, const Vector3& c, const Vector3& d, const Vector3& normal ){
501         surface.vertices().push_back(
502                 ArbitraryMeshVertex(
503                         vertex3f_for_vector3( a ),
504                         normal3f_for_vector3( normal ),
505                         texcoord2f_from_array( aabb_texcoord_topleft )
506                         )
507                 );
508         surface.vertices().push_back(
509                 ArbitraryMeshVertex(
510                         vertex3f_for_vector3( b ),
511                         normal3f_for_vector3( normal ),
512                         texcoord2f_from_array( aabb_texcoord_topright )
513                         )
514                 );
515         surface.vertices().push_back(
516                 ArbitraryMeshVertex(
517                         vertex3f_for_vector3( c ),
518                         normal3f_for_vector3( normal ),
519                         texcoord2f_from_array( aabb_texcoord_botright )
520                         )
521                 );
522         surface.vertices().push_back(
523                 ArbitraryMeshVertex(
524                         vertex3f_for_vector3( d ),
525                         normal3f_for_vector3( normal ),
526                         texcoord2f_from_array( aabb_texcoord_botleft )
527                         )
528                 );
529 }
530
531 inline void Model_constructNull( Model& model ){
532         Surface& surface = model.newSurface();
533
534         AABB aabb( Vector3( 0, 0, 0 ), Vector3( 8, 8, 8 ) );
535
536         Vector3 points[8];
537         aabb_corners( aabb, points );
538
539         surface.vertices().reserve( 24 );
540
541         Surface_constructQuad( surface, points[2], points[1], points[5], points[6], aabb_normals[0] );
542         Surface_constructQuad( surface, points[1], points[0], points[4], points[5], aabb_normals[1] );
543         Surface_constructQuad( surface, points[0], points[1], points[2], points[3], aabb_normals[2] );
544         Surface_constructQuad( surface, points[0], points[3], points[7], points[4], aabb_normals[3] );
545         Surface_constructQuad( surface, points[3], points[2], points[6], points[7], aabb_normals[4] );
546         Surface_constructQuad( surface, points[7], points[6], points[5], points[4], aabb_normals[5] );
547
548         surface.indices().reserve( 36 );
549
550         RenderIndex indices[36] = {
551                 0,  1,  2,  0,  2,  3,
552                 4,  5,  6,  4,  6,  7,
553                 8,  9, 10,  8, 10, 11,
554                 12, 13, 14, 12, 14, 15,
555                 16, 17, 18, 16, 18, 19,
556                 20, 21, 22, 10, 22, 23,
557         };
558
559         for ( RenderIndex* i = indices; i != indices + ( sizeof( indices ) / sizeof( RenderIndex ) ); ++i )
560         {
561                 surface.indices().insert( *i );
562         }
563
564         surface.setShader( "" );
565
566         surface.updateAABB();
567
568         model.updateAABB();
569 }
570
571 #endif