Updating the changelog in the VERSION file, and version_sync.
[shapes.git] / source / singlesidedpolygons.cc
blobe2a654e9c327ff5e6c0a938d3db322479d2bfca8
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 "astvar.h"
26 #include "astclass.h"
27 #include "statetypes.h"
28 #include "lighttypes.h"
29 #include "shadingtypes.h"
30 #include "globals.h"
31 #include "trianglefunctions.h"
33 #include <list>
34 #include <algorithm>
36 using namespace Shapes;
39 std::string
40 binaryFormat( unsigned int value, size_t bits )
42 std::ostringstream oss;
43 for( int i = bits - 1; i >= 0; --i )
45 oss << ( ( ( ( value >> i ) & (size_t)( 1 ) ) != 0 ) ? '1' : 'o' ) ;
47 return oss.str( );
51 Computation::SingleSidedPolygon3DGray::SingleSidedPolygon3DGray( const RefCountPtr< const Computation::FacetInterpolatorGray > & interpolator,
52 bool singleSided,
53 const Concrete::UnitFloatTriple & polygonUnitNormal,
54 Concrete::Length m,
55 Concrete::Length tiebreaker,
56 Concrete::Length viewResolution,
57 Computation::FacetShadeOrder shadeOrder )
58 : Computation::PaintedPolygon3D( singleSided, polygonUnitNormal, m, tiebreaker ),
59 interpolator_( interpolator ),
60 viewResolution_( viewResolution ),
61 shadeOrder_( shadeOrder )
62 { }
64 Computation::SingleSidedPolygon3DGray::~SingleSidedPolygon3DGray( )
65 { }
67 RefCountPtr< const Lang::PaintedPolygon2D >
68 Computation::SingleSidedPolygon3DGray::polygon_to2D( const Kernel::PassedDyn & dyn, const Lang::Transform3D & tf, const std::list< RefCountPtr< const Lang::LightSource > > & lights ) const
70 // In the current implementation, the color is only computed at one point. Later, this
71 // shall be extended to nice shadings.
73 Concrete::Length eyez = dyn->getEyeZ( );
75 if( viewResolution_ == Concrete::HUGE_LENGTH &&
76 shadeOrder_ == 0 )
78 return simple_polygon_to2D( eyez, tf, lights );
81 PtrOwner_back_Access< std::list< const FacetLatticeVertex * > > vertexMem;
82 PtrOwner_back_Access< std::list< const FacetLatticeEdge * > > edgeMem;
83 PtrOwner_back_Access< std::list< const Computation::FacetLatticeTriangle * > > lattice;
85 makeLattice( & lattice, & edgeMem, & vertexMem, viewResolution_, eyez, tf );
87 switch( shadeOrder_ )
89 case 0:
90 return render0( eyez, tf, lights, & lattice );
91 case 1:
93 const SimplePDF::PDF_Version::Version SHADE_VERSION = SimplePDF::PDF_Version::PDF_1_3;
94 if( Kernel::the_PDF_version.greaterOrEqual( SHADE_VERSION ) )
96 return render1( eyez, tf, lights, & lattice );
98 else
100 Kernel::the_PDF_version.message( SHADE_VERSION, "Replacing shade order 1 by 0." );
101 return render0( eyez, tf, lights, & lattice );
104 case 2:
106 const SimplePDF::PDF_Version::Version SHADE_VERSION = SimplePDF::PDF_Version::PDF_1_3;
107 if( Kernel::the_PDF_version.greaterOrEqual( SHADE_VERSION ) )
109 return render2( eyez, tf, lights, & lattice, vertexMem );
111 else
113 Kernel::the_PDF_version.message( SHADE_VERSION, "Replacing shade order 2 by 0." );
114 return render0( eyez, tf, lights, & lattice );
117 default:
118 throw Exceptions::InternalError( "SingleSidedPolygon3DGray::polygon_to2D: shadeOrder_ out of range." );
122 RefCountPtr< const Lang::PaintedPolygon2D >
123 Computation::SingleSidedPolygon3DGray::simple_polygon_to2D( const Concrete::Length eyez, const Lang::Transform3D & tf, const std::list< RefCountPtr< const Lang::LightSource > > & lights ) const
125 Kernel::GraphicsState * metaStatePtr = new Kernel::GraphicsState( true );
127 metaStatePtr->nonStrokingColor_ = interpolator_->compute( tf, lights, computeMean( ).transformed( tf ), eyez );
129 RefCountPtr< const Kernel::GraphicsState > metaState( metaStatePtr );
131 RefCountPtr< Lang::ElementaryPath2D > path = RefCountPtr< Lang::ElementaryPath2D >( new Lang::ElementaryPath2D( ) );
132 path->close( );
133 if( tf.isIdentity( ) )
135 typedef typeof points_ ListType;
136 for( ListType::const_iterator i = points_.begin( ); i != points_.end( ); ++i )
138 path->push_back( new Concrete::PathPoint2D( i->make2D( eyez ) ) );
141 else
143 typedef typeof points_ ListType;
144 for( ListType::const_iterator i = points_.begin( ); i != points_.end( ); ++i )
146 path->push_back( new Concrete::PathPoint2D( i->transformed( tf ).make2D( eyez ) ) );
150 return RefCountPtr< const Lang::PaintedPolygon2D >( new Lang::PaintedPolygon2D( metaState, path ) );
153 RefCountPtr< const Lang::PaintedPolygon2D >
154 Computation::SingleSidedPolygon3DGray::render0( const Concrete::Length eyez, const Lang::Transform3D & tf, const std::list< RefCountPtr< const Lang::LightSource > > & lights, PtrOwner_back_Access< std::list< const Computation::FacetLatticeTriangle * > > * lattice ) const
156 RefCountPtr< const Lang::Group2D > contents = Lang::THE_NULL2D;
158 while( ! lattice->empty( ) )
160 const Computation::FacetLatticeTriangle * triangle = lattice->back( );
161 contents = RefCountPtr< const Lang::Group2D >( new Lang::GroupPair2D( triangle->paint( interpolator_, lights, eyez ),
162 contents,
163 Kernel::THE_DEFAULT_STATE ) );
164 delete triangle;
165 lattice->pop_back( );
168 RefCountPtr< Lang::ElementaryPath2D > path = RefCountPtr< Lang::ElementaryPath2D >( new Lang::ElementaryPath2D( ) );
169 path->close( );
170 if( tf.isIdentity( ) )
172 typedef typeof points_ ListType;
173 for( ListType::const_iterator i = points_.begin( ); i != points_.end( ); ++i )
175 path->push_back( new Concrete::PathPoint2D( i->make2D( eyez ) ) );
178 else
180 typedef typeof points_ ListType;
181 for( ListType::const_iterator i = points_.begin( ); i != points_.end( ); ++i )
183 path->push_back( new Concrete::PathPoint2D( i->transformed( tf ).make2D( eyez ) ) );
187 return RefCountPtr< const Lang::PaintedPolygon2D >( new Lang::BBoxed2D( contents, path ) );
190 RefCountPtr< const Lang::PaintedPolygon2D >
191 Computation::SingleSidedPolygon3DGray::render1( const Concrete::Length eyez, const Lang::Transform3D & tf, const std::list< RefCountPtr< const Lang::LightSource > > & lights, PtrOwner_back_Access< std::list< const Computation::FacetLatticeTriangle * > > * lattice ) const
193 throw Exceptions::NotImplemented( "SingleSidedPolygon3DGray::render1" );
196 RefCountPtr< const Lang::PaintedPolygon2D >
197 Computation::SingleSidedPolygon3DGray::render2( const Concrete::Length eyez, const Lang::Transform3D & tf, const std::list< RefCountPtr< const Lang::LightSource > > & lights, PtrOwner_back_Access< std::list< const Computation::FacetLatticeTriangle * > > * lattice, const PtrOwner_back_Access< std::list< const FacetLatticeVertex * > > & vertexMem ) const
199 RefCountPtr< Lang::ElementaryPath2D > bbox = RefCountPtr< Lang::ElementaryPath2D >( new Lang::ElementaryPath2D( ) );
200 bbox->close( );
201 if( tf.isIdentity( ) )
203 typedef typeof points_ ListType;
204 for( ListType::const_iterator i = points_.begin( ); i != points_.end( ); ++i )
206 bbox->push_back( new Concrete::PathPoint2D( i->make2D( eyez ) ) );
209 else
211 typedef typeof points_ ListType;
212 for( ListType::const_iterator i = points_.begin( ); i != points_.end( ); ++i )
214 bbox->push_back( new Concrete::PathPoint2D( i->transformed( tf ).make2D( eyez ) ) );
219 std::vector< RefCountPtr< const Lang::Gray > > vertexColors;
221 vertexColors.reserve( vertexMem.size( ) );
222 typedef typeof vertexMem ListType;
223 for( ListType::const_iterator i = vertexMem.begin( ); i != vertexMem.end( ); ++i )
225 vertexColors.push_back( interpolator_->compute( tf, lights, (*i)->p3D_.transformed( tf ), eyez ) );
229 RefCountPtr< const Lang::ColorSpace > colorSpace = Lang::THE_COLOR_SPACE_DEVICE_GRAY;
231 RefCountPtr< SimplePDF::PDF_Stream_out > form;
233 RefCountPtr< SimplePDF::PDF_Object > indirection = SimplePDF::indirect( form, & Kernel::theIndirectObjectCount );
235 (*form)[ "Subtype" ] = SimplePDF::newName( "Shading" );
236 (*form)[ "ShadingType" ] = SimplePDF::newInt( 4 );
237 (*form)[ "ColorSpace" ] = colorSpace->name( );
238 // (*form)[ "BBox" ] =
239 // (*form)[ "AntiAlias" ] =
241 const size_t BITS_PER_COORDINATE = 32;
242 const size_t BITS_PER_COMPONENT = 12;
243 const size_t BITS_PER_FLAG = 4;
244 const size_t NUMBER_OF_COMPONENTS = colorSpace->numberOfComponents( );
245 const size_t NUMBER_OF_COORDINATES = 2; // don't change!
247 if( ( NUMBER_OF_COORDINATES * BITS_PER_COORDINATE + NUMBER_OF_COMPONENTS* BITS_PER_COMPONENT + BITS_PER_FLAG ) % 8 != 0 )
249 throw Exceptions::InternalError( "The sizes of thins don't add upp to a whole number of bytes!" );
252 (*form)[ "BitsPerCoordinate" ] = SimplePDF::newInt( BITS_PER_COORDINATE );
253 (*form)[ "BitsPerComponent" ] = SimplePDF::newInt( BITS_PER_COMPONENT );
254 (*form)[ "BitsPerFlag" ] = SimplePDF::newInt( BITS_PER_FLAG );
256 Concrete::Coords2D x0y0( 0, 0 );
257 Concrete::Coords2D x1y1( 0, 0 );
259 if( ! bbox->boundingRectangle( & x0y0, & x1y1 ) )
261 throw Exceptions::InternalError( "SingleSidedPolygon3DGray::render2: Polygon without bounding box!" );
263 Concrete::Length bboxWidth = x1y1.x_ - x0y0.x_;
264 Concrete::Length bboxHeight = x1y1.y_ - x0y0.y_;
266 RefCountPtr< SimplePDF::PDF_Vector > decodeArray = RefCountPtr< SimplePDF::PDF_Vector >( new SimplePDF::PDF_Vector( ) );
268 (*form)[ "Decode" ] = decodeArray;
270 decodeArray->vec.push_back( SimplePDF::newFloat( Concrete::Length::offtype( x0y0.x_ ) ) );
271 decodeArray->vec.push_back( SimplePDF::newFloat( Concrete::Length::offtype( x1y1.x_ ) ) );
272 decodeArray->vec.push_back( SimplePDF::newFloat( Concrete::Length::offtype( x0y0.y_ ) ) );
273 decodeArray->vec.push_back( SimplePDF::newFloat( Concrete::Length::offtype( x1y1.y_ ) ) );
274 for( size_t i = 0; i < NUMBER_OF_COMPONENTS; ++i )
276 decodeArray->vec.push_back( SimplePDF::newFloat( 0. ) );
277 decodeArray->vec.push_back( SimplePDF::newFloat( 1. ) );
280 const Computation::FacetLatticeVertex * va = 0;
281 const Computation::FacetLatticeVertex * vb = 0;
282 const Computation::FacetLatticeVertex * vc = 0;
285 // The first triangle is chosen at random. We have no previous vertexes to consider.
286 const Computation::FacetLatticeTriangle * current = lattice->front( );
287 lattice->pop_front( );
288 current->getVertexes( & va, & vb, & vc );
289 delete current;
291 writePacked( form->data,
292 BITS_PER_COORDINATE, BITS_PER_COMPONENT, BITS_PER_FLAG,
293 ( va->p2D_.x_ - x0y0.x_ ) / bboxWidth,
294 ( va->p2D_.y_ - x0y0.y_ ) / bboxHeight,
295 vertexColors[ va->i_ ]->components( ), 0 );
296 writePacked( form->data,
297 BITS_PER_COORDINATE, BITS_PER_COMPONENT, BITS_PER_FLAG,
298 ( vb->p2D_.x_ - x0y0.x_ ) / bboxWidth,
299 ( vb->p2D_.y_ - x0y0.y_ ) / bboxHeight,
300 vertexColors[ vb->i_ ]->components( ), 0 );
301 writePacked( form->data,
302 BITS_PER_COORDINATE, BITS_PER_COMPONENT, BITS_PER_FLAG,
303 ( vc->p2D_.x_ - x0y0.x_ ) / bboxWidth,
304 ( vc->p2D_.y_ - x0y0.y_ ) / bboxHeight,
305 vertexColors[ vc->i_ ]->components( ), 0 );
308 while( ! lattice->empty( ) )
310 typedef typeof *lattice ListType;
311 bool found = false;
312 for( ListType::iterator i = lattice->begin( ); i != lattice->end( ); ++i ) // we could almost have used a const_iterator here,
313 // but since the last thing we do is erase at i, a non-const iterator must be used.
315 const Computation::FacetLatticeTriangle * current = *i;
316 unsigned char flag = current->extendLattice( & va, & vb, & vc );
317 if( flag != 3 )
319 found = true;
321 lattice->erase( i );
323 writePacked( form->data,
324 BITS_PER_COORDINATE, BITS_PER_COMPONENT, BITS_PER_FLAG,
325 ( vc->p2D_.x_ - x0y0.x_ ) / bboxWidth,
326 ( vc->p2D_.y_ - x0y0.y_ ) / bboxHeight,
327 vertexColors[ vc->i_ ]->components( ), flag );
329 delete current;
330 break;
334 if( ! found )
336 // The first triangle is chosen at random. We have no previous vertexes to consider.
337 const Computation::FacetLatticeTriangle * current = lattice->front( );
338 lattice->pop_front( );
339 current->getVertexes( & va, & vb, & vc );
340 delete current;
342 writePacked( form->data,
343 BITS_PER_COORDINATE, BITS_PER_COMPONENT, BITS_PER_FLAG,
344 ( va->p2D_.x_ - x0y0.x_ ) / bboxWidth,
345 ( va->p2D_.y_ - x0y0.y_ ) / bboxHeight,
346 vertexColors[ va->i_ ]->components( ), 0 );
347 writePacked( form->data,
348 BITS_PER_COORDINATE, BITS_PER_COMPONENT, BITS_PER_FLAG,
349 ( vb->p2D_.x_ - x0y0.x_ ) / bboxWidth,
350 ( vb->p2D_.y_ - x0y0.y_ ) / bboxHeight,
351 vertexColors[ vb->i_ ]->components( ), 0 );
352 writePacked( form->data,
353 BITS_PER_COORDINATE, BITS_PER_COMPONENT, BITS_PER_FLAG,
354 ( vc->p2D_.x_ - x0y0.x_ ) / bboxWidth,
355 ( vc->p2D_.y_ - x0y0.y_ ) / bboxHeight,
356 vertexColors[ vc->i_ ]->components( ), 0 );
360 RefCountPtr< const Lang::Type4Shading > contents
361 = RefCountPtr< const Lang::Type4Shading >( new Lang::Type4Shading( indirection, bbox ) );
363 return RefCountPtr< const Lang::PaintedPolygon2D >( new Lang::BBoxed2D( contents, bbox ) );
367 void
368 Computation::SingleSidedPolygon3DGray::writePacked( std::ostream & os,
369 const size_t BITS_PER_COORDINATE, const size_t BITS_PER_COMPONENT, const size_t BITS_PER_FLAG,
370 const double x, const double y, const Concrete::Gray & color, const unsigned char flag )
372 char rest = 0; // Unused bits must be zero!
373 size_t restAvail = 8; // Number of unused bits in <rest>.
376 size_t BITS = BITS_PER_FLAG;
377 writePackedValue( os, & rest, & restAvail, flag, BITS );
381 size_t BITS = BITS_PER_COORDINATE;
382 unsigned int MAX = UINT_MAX >> ( 8 * sizeof( unsigned int ) - BITS ) ;
383 writePackedValue( os, & rest, & restAvail, (unsigned int)( x * MAX ), BITS );
384 writePackedValue( os, & rest, & restAvail, (unsigned int)( y * MAX ), BITS );
388 size_t BITS = BITS_PER_COMPONENT;
389 unsigned int MAX = UINT_MAX >> ( 8 * sizeof( unsigned int ) - BITS ) ;
390 writePackedValue( os, & rest, & restAvail, (unsigned int)( color.gr_ * MAX ), BITS );
393 if( restAvail < 8 )
395 os.write( & rest, 1 );
400 void
401 Computation::SingleSidedPolygon3DGray::writePackedValue( std::ostream & os, char * rest, size_t * restAvail,
402 unsigned int val, size_t bits )
404 if( bits >= *restAvail )
406 char tmp = ( val >> ( bits - *restAvail ) );
407 *rest |= tmp;
409 val %= ( 1 << ( bits - *restAvail ) );
410 bits -= *restAvail;
412 os.write( rest, 1 );
413 *rest = 0;
414 *restAvail = 8;
416 while( bits >= 8 )
418 char tmp = ( val >> ( bits - 8 ) );
419 os.write( & tmp, 1 );
420 val %= ( 1 << ( bits - 8 ) );
422 bits -= 8;
426 // By now we know that bits <= 7
427 if( bits > *restAvail )
429 char tmp = ( val >> ( bits - *restAvail ) );
430 *rest |= tmp;
432 bits -= *restAvail;
434 os.write( rest, 1 );
435 *rest = 0;
436 *restAvail = 8;
438 // This time there are no full bytes to write.
441 // By now we know that bits <= 6 and *restavail == 8
442 if( bits > 0 )
444 char tmp = ( val << ( 8 - bits ) );
445 *rest |= tmp;
446 *restAvail -= bits;
451 RefCountPtr< const Lang::Color >
452 Computation::SingleSidedPolygon3DGray::getColor( ) const
454 static bool warned = false;
455 if( ! warned )
457 // This color is only used for debugging, so it doesn't matter that we don't care about lightening.
458 std::cerr << "Warning: SingleSidedPolygon3DGray::getColor just returns the lightMultiply coefficients as a color." << std::endl
459 << "Warning: The warning above will be suppressed from now on." << std::endl ;
460 warned = true;
462 return interpolator_->getDebugColor( );
465 void
466 Computation::SingleSidedPolygon3DGray::gcMark( Kernel::GCMarkedSet & marked )
468 const_cast< Computation::FacetInterpolatorGray * >( interpolator_.getPtr( ) )->gcMark( marked );
472 Computation::SingleSidedPolygon3DRGB::SingleSidedPolygon3DRGB( const RefCountPtr< const Computation::FacetInterpolatorRGB > & interpolator,
473 bool singleSided,
474 const Concrete::UnitFloatTriple & polygonUnitNormal,
475 Concrete::Length m,
476 Concrete::Length tiebreaker,
477 Concrete::Length viewResolution,
478 Computation::FacetShadeOrder shadeOrder )
479 : Computation::PaintedPolygon3D( singleSided, polygonUnitNormal, m, tiebreaker ),
480 interpolator_( interpolator ),
481 viewResolution_( viewResolution ),
482 shadeOrder_( shadeOrder )
485 Computation::SingleSidedPolygon3DRGB::~SingleSidedPolygon3DRGB( )
488 RefCountPtr< const Lang::PaintedPolygon2D >
489 Computation::SingleSidedPolygon3DRGB::polygon_to2D( const Kernel::PassedDyn & dyn, const Lang::Transform3D & tf, const std::list< RefCountPtr< const Lang::LightSource > > & lights ) const
491 // In the current implementation, the color is only computed at one point. Later, this
492 // shall be extended to nice shadings.
494 Concrete::Length eyez = dyn->getEyeZ( );
496 if( viewResolution_ == Concrete::HUGE_LENGTH &&
497 shadeOrder_ == 0 )
499 return simple_polygon_to2D( eyez, tf, lights );
502 PtrOwner_back_Access< std::list< const FacetLatticeVertex * > > vertexMem;
503 PtrOwner_back_Access< std::list< const FacetLatticeEdge * > > edgeMem;
504 PtrOwner_back_Access< std::list< const Computation::FacetLatticeTriangle * > > lattice;
506 makeLattice( & lattice, & edgeMem, & vertexMem, viewResolution_, eyez, tf );
508 switch( shadeOrder_ )
510 case 0:
511 return render0( eyez, tf, lights, & lattice );
512 case 1:
514 const SimplePDF::PDF_Version::Version SHADE_VERSION = SimplePDF::PDF_Version::PDF_1_3;
515 if( Kernel::the_PDF_version.greaterOrEqual( SHADE_VERSION ) )
517 return render1( eyez, tf, lights, & lattice );
519 else
521 Kernel::the_PDF_version.message( SHADE_VERSION, "Replacing shade order 1 by 0." );
522 return render0( eyez, tf, lights, & lattice );
525 case 2:
527 const SimplePDF::PDF_Version::Version SHADE_VERSION = SimplePDF::PDF_Version::PDF_1_3;
528 if( Kernel::the_PDF_version.greaterOrEqual( SHADE_VERSION ) )
530 return render2( eyez, tf, lights, & lattice, vertexMem );
532 else
534 Kernel::the_PDF_version.message( SHADE_VERSION, "Replacing shade order 2 by 0." );
535 return render0( eyez, tf, lights, & lattice );
538 default:
539 throw Exceptions::InternalError( "SingleSidedPolygon3DRGB::polygon_to2D: shadeOrder_ out of range." );
543 RefCountPtr< const Lang::PaintedPolygon2D >
544 Computation::SingleSidedPolygon3DRGB::simple_polygon_to2D( const Concrete::Length eyez, const Lang::Transform3D & tf, const std::list< RefCountPtr< const Lang::LightSource > > & lights ) const
546 Kernel::GraphicsState * metaStatePtr = new Kernel::GraphicsState( true );
548 metaStatePtr->nonStrokingColor_ = interpolator_->compute( tf, lights, computeMean( ).transformed( tf ), eyez );
550 RefCountPtr< const Kernel::GraphicsState > metaState( metaStatePtr );
552 RefCountPtr< Lang::ElementaryPath2D > path = RefCountPtr< Lang::ElementaryPath2D >( new Lang::ElementaryPath2D( ) );
553 path->close( );
554 if( tf.isIdentity( ) )
556 typedef typeof points_ ListType;
557 for( ListType::const_iterator i = points_.begin( ); i != points_.end( ); ++i )
559 path->push_back( new Concrete::PathPoint2D( i->make2D( eyez ) ) );
562 else
564 typedef typeof points_ ListType;
565 for( ListType::const_iterator i = points_.begin( ); i != points_.end( ); ++i )
567 path->push_back( new Concrete::PathPoint2D( i->transformed( tf ).make2D( eyez ) ) );
571 return RefCountPtr< const Lang::PaintedPolygon2D >( new Lang::PaintedPolygon2D( metaState, path ) );
574 RefCountPtr< const Lang::PaintedPolygon2D >
575 Computation::SingleSidedPolygon3DRGB::render0( const Concrete::Length eyez, const Lang::Transform3D & tf, const std::list< RefCountPtr< const Lang::LightSource > > & lights, PtrOwner_back_Access< std::list< const Computation::FacetLatticeTriangle * > > * lattice ) const
577 RefCountPtr< const Lang::Group2D > contents = Lang::THE_NULL2D;
579 while( ! lattice->empty( ) )
581 const Computation::FacetLatticeTriangle * triangle = lattice->back( );
582 contents = RefCountPtr< const Lang::Group2D >( new Lang::GroupPair2D( triangle->paint( interpolator_, lights, eyez ),
583 contents,
584 Kernel::THE_DEFAULT_STATE ) );
585 delete triangle;
586 lattice->pop_back( );
589 RefCountPtr< Lang::ElementaryPath2D > path = RefCountPtr< Lang::ElementaryPath2D >( new Lang::ElementaryPath2D( ) );
590 path->close( );
591 if( tf.isIdentity( ) )
593 typedef typeof points_ ListType;
594 for( ListType::const_iterator i = points_.begin( ); i != points_.end( ); ++i )
596 path->push_back( new Concrete::PathPoint2D( i->make2D( eyez ) ) );
599 else
601 typedef typeof points_ ListType;
602 for( ListType::const_iterator i = points_.begin( ); i != points_.end( ); ++i )
604 path->push_back( new Concrete::PathPoint2D( i->transformed( tf ).make2D( eyez ) ) );
608 return RefCountPtr< const Lang::PaintedPolygon2D >( new Lang::BBoxed2D( contents, path ) );
611 RefCountPtr< const Lang::PaintedPolygon2D >
612 Computation::SingleSidedPolygon3DRGB::render1( const Concrete::Length eyez, const Lang::Transform3D & tf, const std::list< RefCountPtr< const Lang::LightSource > > & lights, PtrOwner_back_Access< std::list< const Computation::FacetLatticeTriangle * > > * lattice ) const
614 throw Exceptions::NotImplemented( "SingleSidedPolygon3DRGB::render1" );
617 RefCountPtr< const Lang::PaintedPolygon2D >
618 Computation::SingleSidedPolygon3DRGB::render2( const Concrete::Length eyez, const Lang::Transform3D & tf, const std::list< RefCountPtr< const Lang::LightSource > > & lights, PtrOwner_back_Access< std::list< const Computation::FacetLatticeTriangle * > > * lattice, const PtrOwner_back_Access< std::list< const FacetLatticeVertex * > > & vertexMem ) const
620 RefCountPtr< Lang::ElementaryPath2D > bbox = RefCountPtr< Lang::ElementaryPath2D >( new Lang::ElementaryPath2D( ) );
621 bbox->close( );
622 if( tf.isIdentity( ) )
624 typedef typeof points_ ListType;
625 for( ListType::const_iterator i = points_.begin( ); i != points_.end( ); ++i )
627 bbox->push_back( new Concrete::PathPoint2D( i->make2D( eyez ) ) );
630 else
632 typedef typeof points_ ListType;
633 for( ListType::const_iterator i = points_.begin( ); i != points_.end( ); ++i )
635 bbox->push_back( new Concrete::PathPoint2D( i->transformed( tf ).make2D( eyez ) ) );
640 std::vector< RefCountPtr< const Lang::RGB > > vertexColors;
642 vertexColors.reserve( vertexMem.size( ) );
643 typedef typeof vertexMem ListType;
644 for( ListType::const_iterator i = vertexMem.begin( ); i != vertexMem.end( ); ++i )
646 vertexColors.push_back( interpolator_->compute( tf, lights, (*i)->p3D_.transformed( tf ), eyez ) );
650 RefCountPtr< const Lang::ColorSpace > colorSpace = Lang::THE_COLOR_SPACE_DEVICE_RGB;
652 RefCountPtr< SimplePDF::PDF_Stream_out > form;
654 RefCountPtr< SimplePDF::PDF_Object > indirection = SimplePDF::indirect( form, & Kernel::theIndirectObjectCount );
656 (*form)[ "Subtype" ] = SimplePDF::newName( "Shading" );
657 (*form)[ "ShadingType" ] = SimplePDF::newInt( 4 );
658 (*form)[ "ColorSpace" ] = colorSpace->name( );
659 // (*form)[ "BBox" ] =
660 // (*form)[ "AntiAlias" ] =
662 const size_t BITS_PER_COORDINATE = 32;
663 const size_t BITS_PER_COMPONENT = 12;
664 const size_t BITS_PER_FLAG = 4;
665 const size_t NUMBER_OF_COMPONENTS = colorSpace->numberOfComponents( );
666 const size_t NUMBER_OF_COORDINATES = 2; // don't change!
668 if( ( NUMBER_OF_COORDINATES * BITS_PER_COORDINATE + NUMBER_OF_COMPONENTS* BITS_PER_COMPONENT + BITS_PER_FLAG ) % 8 != 0 )
670 throw Exceptions::InternalError( "The sizes of thins don't add upp to a whole number of bytes!" );
673 (*form)[ "BitsPerCoordinate" ] = SimplePDF::newInt( BITS_PER_COORDINATE );
674 (*form)[ "BitsPerComponent" ] = SimplePDF::newInt( BITS_PER_COMPONENT );
675 (*form)[ "BitsPerFlag" ] = SimplePDF::newInt( BITS_PER_FLAG );
677 Concrete::Coords2D x0y0( 0, 0 );
678 Concrete::Coords2D x1y1( 0, 0 );
680 if( ! bbox->boundingRectangle( & x0y0, & x1y1 ) )
682 throw Exceptions::InternalError( "SingleSidedPolygon3DRGB::render2: Polygon without bounding box!" );
684 Concrete::Length bboxWidth = x1y1.x_ - x0y0.x_;
685 Concrete::Length bboxHeight = x1y1.y_ - x0y0.y_;
687 RefCountPtr< SimplePDF::PDF_Vector > decodeArray = RefCountPtr< SimplePDF::PDF_Vector >( new SimplePDF::PDF_Vector( ) );
689 (*form)[ "Decode" ] = decodeArray;
691 decodeArray->vec.push_back( SimplePDF::newFloat( Concrete::Length::offtype( x0y0.x_ ) ) );
692 decodeArray->vec.push_back( SimplePDF::newFloat( Concrete::Length::offtype( x1y1.x_ ) ) );
693 decodeArray->vec.push_back( SimplePDF::newFloat( Concrete::Length::offtype( x0y0.y_ ) ) );
694 decodeArray->vec.push_back( SimplePDF::newFloat( Concrete::Length::offtype( x1y1.y_ ) ) );
695 for( size_t i = 0; i < NUMBER_OF_COMPONENTS; ++i )
697 decodeArray->vec.push_back( SimplePDF::newFloat( 0. ) );
698 decodeArray->vec.push_back( SimplePDF::newFloat( 1. ) );
701 const Computation::FacetLatticeVertex * va = 0;
702 const Computation::FacetLatticeVertex * vb = 0;
703 const Computation::FacetLatticeVertex * vc = 0;
706 // The first triangle is chosen at random. We have no previous vertexes to consider.
707 const Computation::FacetLatticeTriangle * current = lattice->front( );
708 lattice->pop_front( );
709 current->getVertexes( & va, & vb, & vc );
710 delete current;
712 writePacked( form->data,
713 BITS_PER_COORDINATE, BITS_PER_COMPONENT, BITS_PER_FLAG,
714 ( va->p2D_.x_ - x0y0.x_ ) / bboxWidth,
715 ( va->p2D_.y_ - x0y0.y_ ) / bboxHeight,
716 vertexColors[ va->i_ ]->components( ), 0 );
717 writePacked( form->data,
718 BITS_PER_COORDINATE, BITS_PER_COMPONENT, BITS_PER_FLAG,
719 ( vb->p2D_.x_ - x0y0.x_ ) / bboxWidth,
720 ( vb->p2D_.y_ - x0y0.y_ ) / bboxHeight,
721 vertexColors[ vb->i_ ]->components( ), 0 );
722 writePacked( form->data,
723 BITS_PER_COORDINATE, BITS_PER_COMPONENT, BITS_PER_FLAG,
724 ( vc->p2D_.x_ - x0y0.x_ ) / bboxWidth,
725 ( vc->p2D_.y_ - x0y0.y_ ) / bboxHeight,
726 vertexColors[ vc->i_ ]->components( ), 0 );
729 while( ! lattice->empty( ) )
731 typedef typeof *lattice ListType;
732 bool found = false;
733 for( ListType::iterator i = lattice->begin( ); i != lattice->end( ); ++i ) // we could almost have used a const_iterator here,
734 // but since the last thing we do is erase at i, a non-const iterator must be used.
736 const Computation::FacetLatticeTriangle * current = *i;
737 unsigned char flag = current->extendLattice( & va, & vb, & vc );
738 if( flag != 3 )
740 found = true;
742 lattice->erase( i );
744 writePacked( form->data,
745 BITS_PER_COORDINATE, BITS_PER_COMPONENT, BITS_PER_FLAG,
746 ( vc->p2D_.x_ - x0y0.x_ ) / bboxWidth,
747 ( vc->p2D_.y_ - x0y0.y_ ) / bboxHeight,
748 vertexColors[ vc->i_ ]->components( ), flag );
750 delete current;
751 break;
755 if( ! found )
757 // The first triangle is chosen at random. We have no previous vertexes to consider.
758 const Computation::FacetLatticeTriangle * current = lattice->front( );
759 lattice->pop_front( );
760 current->getVertexes( & va, & vb, & vc );
761 delete current;
763 writePacked( form->data,
764 BITS_PER_COORDINATE, BITS_PER_COMPONENT, BITS_PER_FLAG,
765 ( va->p2D_.x_ - x0y0.x_ ) / bboxWidth,
766 ( va->p2D_.y_ - x0y0.y_ ) / bboxHeight,
767 vertexColors[ va->i_ ]->components( ), 0 );
768 writePacked( form->data,
769 BITS_PER_COORDINATE, BITS_PER_COMPONENT, BITS_PER_FLAG,
770 ( vb->p2D_.x_ - x0y0.x_ ) / bboxWidth,
771 ( vb->p2D_.y_ - x0y0.y_ ) / bboxHeight,
772 vertexColors[ vb->i_ ]->components( ), 0 );
773 writePacked( form->data,
774 BITS_PER_COORDINATE, BITS_PER_COMPONENT, BITS_PER_FLAG,
775 ( vc->p2D_.x_ - x0y0.x_ ) / bboxWidth,
776 ( vc->p2D_.y_ - x0y0.y_ ) / bboxHeight,
777 vertexColors[ vc->i_ ]->components( ), 0 );
781 RefCountPtr< const Lang::Type4Shading > contents
782 = RefCountPtr< const Lang::Type4Shading >( new Lang::Type4Shading( indirection, bbox ) );
784 return RefCountPtr< const Lang::PaintedPolygon2D >( new Lang::BBoxed2D( contents, bbox ) );
788 void
789 Computation::SingleSidedPolygon3DRGB::writePacked( std::ostream & os,
790 const size_t BITS_PER_COORDINATE, const size_t BITS_PER_COMPONENT, const size_t BITS_PER_FLAG,
791 const double x, const double y, const Concrete::RGB & color, const unsigned char flag )
793 char rest = 0; // Unused bits must be zero!
794 size_t restAvail = 8; // Number of unused bits in <rest>.
797 size_t BITS = BITS_PER_FLAG;
798 writePackedValue( os, & rest, & restAvail, flag, BITS );
802 size_t BITS = BITS_PER_COORDINATE;
803 unsigned int MAX = UINT_MAX >> ( 8 * sizeof( unsigned int ) - BITS ) ;
804 writePackedValue( os, & rest, & restAvail, (unsigned int)( x * MAX ), BITS );
805 writePackedValue( os, & rest, & restAvail, (unsigned int)( y * MAX ), BITS );
809 size_t BITS = BITS_PER_COMPONENT;
810 unsigned int MAX = UINT_MAX >> ( 8 * sizeof( unsigned int ) - BITS ) ;
811 writePackedValue( os, & rest, & restAvail, (unsigned int)( color.r_ * MAX ), BITS );
812 writePackedValue( os, & rest, & restAvail, (unsigned int)( color.g_ * MAX ), BITS );
813 writePackedValue( os, & rest, & restAvail, (unsigned int)( color.b_ * MAX ), BITS );
816 if( restAvail < 8 )
818 os.write( & rest, 1 );
823 void
824 Computation::SingleSidedPolygon3DRGB::writePackedValue( std::ostream & os, char * rest, size_t * restAvail,
825 unsigned int val, size_t bits )
827 if( bits >= *restAvail )
829 char tmp = ( val >> ( bits - *restAvail ) );
830 *rest |= tmp;
832 val %= ( 1 << ( bits - *restAvail ) );
833 bits -= *restAvail;
835 os.write( rest, 1 );
836 *rest = 0;
837 *restAvail = 8;
839 while( bits >= 8 )
841 char tmp = ( val >> ( bits - 8 ) );
842 os.write( & tmp, 1 );
843 val %= ( 1 << ( bits - 8 ) );
845 bits -= 8;
849 // By now we know that bits <= 7
850 if( bits > *restAvail )
852 char tmp = ( val >> ( bits - *restAvail ) );
853 *rest |= tmp;
855 bits -= *restAvail;
857 os.write( rest, 1 );
858 *rest = 0;
859 *restAvail = 8;
861 // This time there are no full bytes to write.
864 // By now we know that bits <= 6 and *restavail == 8
865 if( bits > 0 )
867 char tmp = ( val << ( 8 - bits ) );
868 *rest |= tmp;
869 *restAvail -= bits;
874 RefCountPtr< const Lang::Color >
875 Computation::SingleSidedPolygon3DRGB::getColor( ) const
877 static bool warned = false;
878 if( ! warned )
880 // This color is only used for debugging, so it doesn't matter that we don't care about lightening.
881 std::cerr << "Warning: SingleSidedPolygon3DRGB::getColor just returns the lightMultiply coefficients as a color." << std::endl
882 << "Warning: The warning above will be suppressed from now on." << std::endl ;
883 warned = true;
885 return interpolator_->getDebugColor( );
888 void
889 Computation::SingleSidedPolygon3DRGB::gcMark( Kernel::GCMarkedSet & marked )
891 const_cast< Computation::FacetInterpolatorRGB * >( interpolator_.getPtr( ) )->gcMark( marked );