Updating the changelog in the VERSION file, and version_sync.
[shapes.git] / source / zbufto2D.cc
blob86a7706c3cc17e3e8030572e547d38dc972c11b8
1 /* This file is part of Shapes.
3 * Shapes is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * any later version.
8 * Shapes is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with Shapes. If not, see <http://www.gnu.org/licenses/>.
16 * Copyright 2008 Henrik Tidefelt
19 #include <cmath>
21 #include "shapestypes.h"
22 #include "shapesexceptions.h"
23 #include "astexpr.h"
24 #include "consts.h"
25 #include "angleselect.h"
26 #include "astvar.h"
27 #include "astclass.h"
28 #include "statetypes.h"
29 #include "lighttypes.h"
30 #include "shadingtypes.h"
31 #include "globals.h"
33 #include <ctype.h>
34 #include <list>
35 #include <algorithm>
37 using namespace Shapes;
39 #define SPLICEDEBUG( code ) // code
42 RefCountPtr< const Lang::Drawable2D >
43 Lang::ZBuf::typed_to2D( const Kernel::PassedDyn & dyn, const Lang::Transform3D & tf, const RefCountPtr< const Lang::Drawable3D > & self ) const
45 Concrete::Length eyez = dyn->getEyeZ( );
47 std::list< RefCountPtr< const Lang::LightSource > > commonLights;
48 std::list< RefCountPtr< const Lang::LightSource > > allShadowLights;
51 typedef typeof *lightPile_ PileType;
52 for( PileType::const_iterator src = lightPile_->begin( ); src != lightPile_->end( ); ++src )
54 if( (*src)->shadows( ) )
56 allShadowLights.push_back( (*src)->typed_transformed( tf ) );
58 else
60 commonLights.push_back( (*src)->typed_transformed( tf ) );
65 if( ! allShadowLights.empty( ) )
67 throw Exceptions::NotImplemented( "Shadow lights in ZBuf::typed_to2D" );
70 size_t debugCounter = 0;
72 // There is one queue per original object. This structure will be where all the
73 // triangles resides at the beginning of the treatment of each shadow light or the
74 // view occlusion computation.
76 // We begin by initializing these queues.
77 std::list< std::list< Computation::ZBufTriangle > * > triangleQueues;
79 typedef typeof *pile_ PileType;
80 for( PileType::const_iterator src = pile_->begin( ); src != pile_->end( ); ++src )
82 std::list< Computation::ZBufTriangle > * triangleQueue = new std::list< Computation::ZBufTriangle >;
83 (*src)->push_zBufTriangles( tf, eyez, triangleQueue );
84 triangleQueues.push_back( triangleQueue );
88 // The vectors triangleQueue and disjointTriangles share indices in the sense that same indices points to
89 // triangles with the same origin.
90 std::list< std::list< Computation::ZBufTriangle > * > disjointTriangles;
91 std::list< std::list< Computation::ZBufTriangle > * > occludedTriangles;
93 for( std::list< std::list< Computation::ZBufTriangle > * >::iterator src = triangleQueues.begin( );
94 src != triangleQueues.end( ); ++src )
96 std::list< Computation::ZBufTriangle > * triangleQueue = *src;
98 std::list< Computation::ZBufTriangle > * currentDisjoint = new std::list< Computation::ZBufTriangle >;
99 std::list< Computation::ZBufTriangle > * currentOccluded = new std::list< Computation::ZBufTriangle >;
101 while( ! triangleQueue->empty( ) )
103 SPLICEDEBUG( std::cerr << "====( Debug step number " << debugCounter << " )====" << std::endl );
104 Computation::ZBufTriangle current = triangleQueue->front( );
105 triangleQueue->pop_front( );
107 typedef typeof disjointTriangles ListType;
108 bool foundOverlap = false;
109 ListType::iterator iOccluded = occludedTriangles.begin( );
110 for( ListType::iterator iDisjoint = disjointTriangles.begin( ); iDisjoint != disjointTriangles.end( );
111 ++iDisjoint, ++iOccluded )
113 typedef typeof **iDisjoint SubListType;
114 for( SubListType::iterator j = (*iDisjoint)->begin( ); j != (*iDisjoint)->end( ); ++j )
116 if( current.overlaps( *j ) )
118 Computation::ZBufTriangle tOld( *j );
119 (*iDisjoint)->erase( j );
120 Computation::ZBufTriangle::splice( tOld, current,
121 *iDisjoint, *iOccluded,
122 currentDisjoint, currentOccluded,
123 triangleQueue );
124 mergeTriangles( *iDisjoint );
125 recombineTriangles( *iOccluded );
126 foundOverlap = true;
127 goto doublebreak;
131 doublebreak:
132 if( ! foundOverlap )
134 currentDisjoint->push_back( current );
138 mergeTriangles( currentDisjoint );
139 recombineTriangles( currentDisjoint );
140 disjointTriangles.push_back( currentDisjoint );
142 mergeTriangles( currentOccluded );
143 recombineTriangles( currentOccluded );
144 occludedTriangles.push_back( currentOccluded );
146 ++debugCounter;
147 if( debugCounter >= Interaction::debugStep )
149 // break;
154 size_t sum = 0;
155 typedef typeof disjointTriangles ListType;
156 for( ListType::const_iterator i = disjointTriangles.begin( ); i != disjointTriangles.end( ); ++i )
158 sum += (*i)->size( );
162 // It is now time to take care of the lines.
163 // The first thing we shall do is to remove what is occluded by triangles.
164 // Note that triangles will be drawn before the lines, and that is the only way lines
165 // can occlude triangles.
166 // Then, we make sure that the lines are drawn in back-to-front order, clipping occluded lines
167 // behind the line occluding them to avoid cyclic locking.
169 std::list< const Computation::ZBufLine * > lineQueue;
171 typedef typeof *linePile_ PileType;
172 for( PileType::const_iterator src = linePile_->begin( ); src != linePile_->end( ); ++src )
174 (*src)->push_zBufLine( tf, eyez, & lineQueue );
178 std::list< const Computation::ZBufLine * > disjointLines;
179 while( ! lineQueue.empty( ) )
182 std::list< const Computation::ZBufLine * > queue1;
183 std::list< const Computation::ZBufLine * > queue2;
185 std::list< const Computation::ZBufLine * > * currentQueue = & queue1;
186 std::list< const Computation::ZBufLine * > * otherQueue = & queue2;
188 currentQueue->push_back( lineQueue.front( ) );
189 lineQueue.pop_front( );
191 typedef typeof disjointTriangles ListType;
192 for( ListType::const_iterator i = disjointTriangles.begin( ); i != disjointTriangles.end( ); ++i )
194 typedef typeof **i SubListType;
195 for( SubListType::iterator j = (*i)->begin( ); j != (*i)->end( ); ++j )
197 while( ! currentQueue->empty( ) )
199 const Computation::ZBufLine * currentLine = currentQueue->front( );
200 currentQueue->pop_front( );
201 if( currentLine->overlaps( *j ) )
203 currentLine->splice( *j, otherQueue );
204 delete currentLine;
206 else
208 otherQueue->push_back( currentLine );
213 // swap the queues
214 std::list< const Computation::ZBufLine * > * tmp = currentQueue;
215 currentQueue = otherQueue;
216 otherQueue = tmp;
221 // When we reach here the line segments are in currentQueue.
222 // These segments are ready to be inserted in the line z buffer.
224 // The algorithm below is inefficient, because it will generally make the overlap comparison
225 // several times for any overlaping pair of line segments.
226 while( ! currentQueue->empty( ) )
228 const Computation::ZBufLine * current = currentQueue->front( );
229 currentQueue->pop_front( );
231 bool foundOverlap = false;
232 typedef typeof disjointLines ListType;
233 for( ListType::iterator i = disjointLines.begin( ); i != disjointLines.end( );
234 ++i )
236 if( current->overlaps( **i ) )
238 disjointLines.erase( i );
239 // Note that splice is responsible for deleting that of *i and current which is not used.
240 Computation::ZBufLine::splice( *i, current,
241 & disjointLines,
242 currentQueue );
243 foundOverlap = true;
244 break;
247 if( ! foundOverlap )
249 disjointLines.push_back( current );
255 RefCountPtr< const Lang::Group2D > res = Lang::THE_NULL2D;
257 const bool SHOW_TRIXELS = false;
258 if( SHOW_TRIXELS )
260 // This is a debug mode
262 typedef typeof disjointTriangles ListType;
263 for( ListType::const_iterator i = disjointTriangles.begin( ); i != disjointTriangles.end( ); ++i )
265 typedef typeof **i SubListType;
266 for( SubListType::iterator j = (*i)->begin( ); j != (*i)->end( ); ++j )
268 res = RefCountPtr< const Lang::Group2D >( new Lang::GroupPair2D( j->debugFrame( ),
269 res,
270 metaState_ ) );
274 else
276 // This is the standard mode
278 size_t commonLightCount = commonLights.size( );
280 typedef typeof disjointTriangles ListType;
281 for( ListType::iterator i = disjointTriangles.begin( ); i != disjointTriangles.end( ); ++i )
283 if( (*i)->empty( ) )
285 continue;
287 typedef std::list< RefCountPtr< const Lang::LightSource > > ShadowLightListType;
288 const ShadowLightListType & shadowLights = (*i)->front( ).shadowLights_;
289 for( ShadowLightListType::const_iterator l = shadowLights.begin( ); l != shadowLights.end( ); ++l )
291 commonLights.push_back( *l );
293 RefCountPtr< const Lang::PaintedPolygon2D > tmp = (*i)->front( ).painter_->polygon_to2D( dyn, tf, commonLights );
294 while( commonLights.size( ) > commonLightCount )
296 commonLights.pop_back( );
299 // The following statement will consume the objects in the list pointed to by *i
300 res = RefCountPtr< const Lang::Group2D >( new Lang::GroupPair2D( tmp->clip( *i, tmp ),
301 res,
302 metaState_ ) );
307 while( ! disjointTriangles.empty ( ) )
309 delete disjointTriangles.back( );
310 disjointTriangles.pop_back( );
312 delete occludedTriangles.back( );
313 occludedTriangles.pop_back( );
316 while( ! triangleQueues.empty( ) )
318 delete triangleQueues.back( );
319 triangleQueues.pop_back( );
323 // Finally we draw the lines.
324 while( ! disjointLines.empty( ) )
326 const Computation::ZBufLine * current = disjointLines.front( );
327 disjointLines.pop_front( );
328 res = RefCountPtr< const Lang::Group2D >( new Lang::GroupPair2D( current->stroke2D( ),
329 res,
330 metaState_ ) );
331 delete current;
335 return res;