merge branch work back into trunk
[xonotic/netradiant.git] / plugins / model / cpicosurface.cpp
1 /*
2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
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 #include "cpicosurface.h"
23
24 // public
25
26 CPicoSurface::CPicoSurface(picoSurface_t *pSurface)
27 {
28   refCount = 1;
29
30   m_pSurface = pSurface;
31
32   // PicoFixSurfaceNormals( pSurface );
33         
34   AccumulateBBox();
35
36   m_shader = QERApp_Shader_ForName(GetShaderName());
37 }
38
39 CPicoSurface::~CPicoSurface()
40 {
41   m_shader->DecRef();
42 }
43
44 void CPicoSurface::Draw(int state, int rflags)
45 {
46   Draw(state, m_shader, rflags);
47 }
48
49 void CPicoSurface::Draw(int state, IShader *pShader, int rflags)
50 {
51   int j;
52
53   if( !(rflags & (DRAW_RF_SEL_OUTLINE|DRAW_RF_SEL_FILL|DRAW_RF_XY)) )
54   {
55     if(state & DRAW_GL_TEXTURE_2D)
56     {
57       g_QglTable.m_pfn_qglBindTexture(GL_TEXTURE_2D, pShader->getTexture()->texture_number);
58       if( (rflags & DRAW_RF_CAM) && (pShader->getFlags() & QER_ALPHAFUNC) ) {
59         int nFunc = 0;
60         float fRef = 0.f;
61
62         g_QglTable.m_pfn_qglColor4f( 1.f, 1.f, 1.f, 1.f ); // identity
63
64         g_QglTable.m_pfn_qglEnable( GL_ALPHA_TEST );
65
66         pShader->getAlphaFunc( &nFunc, &fRef );
67               g_QglTable.m_pfn_qglAlphaFunc( nFunc, fRef );
68       }
69     }
70     else
71     {
72       //g_QglTable.m_pfn_qglColor3fv( pShader->getTexture()->color );
73 /*      g_QglTable.m_pfn_qglEnableClientState(GL_COLOR_ARRAY);*/
74     }
75
76     if( !(state & DRAW_GL_WIRE) && (pShader->getFlags() & QER_CULL) )
77     {
78       if( pShader->getCull() == 2 )
79       {
80         g_QglTable.m_pfn_qglDisable( GL_CULL_FACE );
81         g_QglTable.m_pfn_qglPolygonMode (GL_FRONT, GL_FILL);
82       }
83       else // is 1
84       {
85         g_QglTable.m_pfn_qglCullFace( GL_BACK );
86       }
87     }
88   }
89
90   switch( PicoGetSurfaceType(m_pSurface) )
91   {
92   case PICO_TRIANGLES:  g_QglTable.m_pfn_qglBegin(GL_TRIANGLES);
93                         for (j=0; j<PicoGetSurfaceNumIndexes(m_pSurface); j++)
94                         {
95                               g_QglTable.m_pfn_qglNormal3fv(PicoGetSurfaceNormal(m_pSurface,PicoGetSurfaceIndex(m_pSurface,j)));
96                                                         
97                                                   if( !(rflags & (DRAW_RF_SEL_OUTLINE|DRAW_RF_SEL_FILL|DRAW_RF_XY)) ) {
98                             if(state & DRAW_GL_TEXTURE_2D) {
99                               g_QglTable.m_pfn_qglTexCoord2fv(PicoGetSurfaceST(m_pSurface,0,PicoGetSurfaceIndex(m_pSurface,j)));
100                                                         } else {
101                               picoByte_t *vertexColor = PicoGetSurfaceColor(m_pSurface,0,PicoGetSurfaceIndex(m_pSurface,j));
102                               //% g_QglTable.m_pfn_qglColor4f( vertexColor[ 0 ] / 255.f,
103                               //%                              vertexColor[ 1 ] / 255.f,
104                               //%                              vertexColor[ 2 ] / 255.f,
105                               //%                              vertexColor[ 3 ] / 255.f );
106                               g_QglTable.m_pfn_qglColor4ubv( vertexColor );
107                             }
108                                                   }
109                           g_QglTable.m_pfn_qglVertex3fv( PicoGetSurfaceXYZ( m_pSurface, PicoGetSurfaceIndex( m_pSurface, j ) ) );
110                         }
111                         g_QglTable.m_pfn_qglEnd();
112                         /*g_QglTable.m_pfn_qglVertexPointer( 3, GL_FLOAT, 0, PicoGetSurfaceXYZ( m_pSurface, 0 ) );
113                                                 g_QglTable.m_pfn_qglNormalPointer( GL_FLOAT, 0, PicoGetSurfaceNormal( m_pSurface, 0 ) );
114                                                 if( !(rflags & (DRAW_RF_SEL_OUTLINE|DRAW_RF_SEL_FILL|DRAW_RF_XY)) ) {
115                           if( state & DRAW_GL_TEXTURE_2D ) {
116                                                     g_QglTable.m_pfn_qglTexCoordPointer( 2, GL_FLOAT, 0, PicoGetSurfaceST( m_pSurface, 0, 0 ) );                            
117                                                   } else {
118                             g_QglTable.m_pfn_qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, PicoGetSurfaceColor( m_pSurface, 0, 0 ) );
119                                                   }
120                                                 }
121                                                 g_QglTable.m_pfn_qglDrawElements( GL_TRIANGLES, PicoGetSurfaceNumIndexes( m_pSurface ), GL_UNSIGNED_INT, PicoGetSurfaceIndexes( m_pSurface, 0 ) );*/
122
123                         /*g_QglTable.m_pfn_qglColor3f( 0.f, .5f, 1.f );
124                                                 g_QglTable.m_pfn_qglBegin( GL_LINES );
125                                                 for( int i = 0; i < PicoGetSurfaceNumIndexes( m_pSurface ); i++ ) {
126                                                   vec3_t outerpoint;
127                                                   VectorMA( PicoGetSurfaceXYZ( m_pSurface, PicoGetSurfaceIndex( m_pSurface, i ) ), .3f, PicoGetSurfaceNormal( m_pSurface, PicoGetSurfaceIndex( m_pSurface, i ) ), outerpoint );
128                                                   g_QglTable.m_pfn_qglVertex3fv( PicoGetSurfaceXYZ( m_pSurface, PicoGetSurfaceIndex( m_pSurface, i ) ) );
129                                                   g_QglTable.m_pfn_qglVertex3fv( outerpoint );
130                                                 }
131                                                 g_QglTable.m_pfn_qglEnd();*/
132
133                         break;
134   default:              Sys_Printf( "ERROR: Unsupported Pico Surface Type: %i", PicoGetSurfaceType(m_pSurface) );
135                         break;
136   }
137
138   if( !(rflags & (DRAW_RF_SEL_OUTLINE|DRAW_RF_SEL_FILL|DRAW_RF_XY)) )
139   {
140     if( (state & DRAW_GL_TEXTURE_2D) && (rflags & DRAW_RF_CAM) && (pShader->getFlags() & QER_ALPHAFUNC) ) {
141       g_QglTable.m_pfn_qglDisable( GL_ALPHA_TEST );
142     }
143
144 /*      if(!(state & DRAW_GL_TEXTURE_2D)) {
145       g_QglTable.m_pfn_qglDisableClientState(GL_COLOR_ARRAY);
146         }*/
147
148     if( !(state & DRAW_GL_WIRE) && (pShader->getFlags() & QER_CULL) )
149     {
150       if( pShader->getCull() == 2 )
151       {
152         g_QglTable.m_pfn_qglPolygonMode (GL_FRONT, GL_LINE);
153         g_QglTable.m_pfn_qglEnable( GL_CULL_FACE );
154       }
155       else // is 1
156       {
157         g_QglTable.m_pfn_qglCullFace( GL_FRONT );
158       }
159     }
160   }
161 }
162
163 // private
164
165 void CPicoSurface::AccumulateBBox()
166 {
167   int i;
168   picoVec_t *p;
169   aabb_clear(&m_BBox);
170   for (i=0; i<PicoGetSurfaceNumVertexes(m_pSurface); i++)
171   {
172     p=PicoGetSurfaceXYZ(m_pSurface,i);
173     aabb_extend_by_point(&m_BBox, p);
174   }
175   aabb_update_radius(&m_BBox);
176 }
177
178 bool CPicoSurface::TestRay (const ray_t *ray, vec_t *dist) const
179 {
180   int i;
181   vec_t start_dist = *dist;
182   vec_t local_dist = *dist;
183   if (aabb_intersect_ray(&m_BBox, ray, &local_dist))
184   {
185     switch( PicoGetSurfaceType(m_pSurface) )
186     {
187     case PICO_TRIANGLES:
188       for (i=0; i<PicoGetSurfaceNumIndexes(m_pSurface); i+=3)
189       {
190                     local_dist = ray_intersect_triangle(ray, true, PicoGetSurfaceXYZ(m_pSurface,PicoGetSurfaceIndex(m_pSurface,i+2)),
191                                               PicoGetSurfaceXYZ(m_pSurface,PicoGetSurfaceIndex(m_pSurface,i+1)),
192                                               PicoGetSurfaceXYZ(m_pSurface,PicoGetSurfaceIndex(m_pSurface,i)));
193                     if (local_dist < *dist)
194           *dist = local_dist;
195       }
196       break;
197     default:
198       Sys_Printf( "ERROR: Unsupported Pico Surface Type: %i", PicoGetSurfaceType(m_pSurface) );
199       break;
200     }
201   }
202         return (*dist < start_dist);
203 }