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