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
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, 2010 Henrik Tidefelt
21 #include "shapestypes.h"
22 #include "shapesexceptions.h"
27 #include "statetypes.h"
28 #include "lighttypes.h"
29 #include "shadingtypes.h"
31 #include "trianglefunctions.h"
37 using namespace Shapes
;
41 binaryFormat( unsigned int value
, size_t bits
)
43 std::ostringstream oss
;
44 for( int i
= bits
- 1; i
>= 0; --i
)
46 oss
<< ( ( ( ( value
>> i
) & (size_t)( 1 ) ) != 0 ) ? '1' : 'o' ) ;
52 Computation::SingleSidedPolygon3DGray::SingleSidedPolygon3DGray( const RefCountPtr
< const Computation::FacetInterpolatorGray
> & interpolator
,
54 const Concrete::UnitFloatTriple
& polygonUnitNormal
,
56 Concrete::Length tiebreaker
,
57 Concrete::Length viewResolution
,
58 Computation::FacetShadeOrder shadeOrder
)
59 : Computation::PaintedPolygon3D( singleSided
, polygonUnitNormal
, m
, tiebreaker
),
60 interpolator_( interpolator
),
61 viewResolution_( viewResolution
),
62 shadeOrder_( shadeOrder
)
65 Computation::SingleSidedPolygon3DGray::~SingleSidedPolygon3DGray( )
68 RefCountPtr
< const Lang::PaintedPolygon2D
>
69 Computation::SingleSidedPolygon3DGray::polygon_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const std::list
< RefCountPtr
< const Lang::LightSource
> > & lights
) const
71 // In the current implementation, the color is only computed at one point. Later, this
72 // shall be extended to nice shadings.
74 Concrete::Length eyez
= dyn
->getEyeZ( );
76 if( viewResolution_
== Concrete::HUGE_LENGTH
&&
79 return simple_polygon_to2D( eyez
, tf
, lights
);
82 PtrOwner_back_Access
< std::list
< const FacetLatticeVertex
* > > vertexMem
;
83 PtrOwner_back_Access
< std::list
< const FacetLatticeEdge
* > > edgeMem
;
84 PtrOwner_back_Access
< std::list
< const Computation::FacetLatticeTriangle
* > > lattice
;
86 makeLattice( & lattice
, & edgeMem
, & vertexMem
, viewResolution_
, eyez
, tf
);
91 return render0( eyez
, tf
, lights
, & lattice
);
94 const SimplePDF::PDF_Version::Version SHADE_VERSION
= SimplePDF::PDF_Version::PDF_1_3
;
95 if( Kernel::the_PDF_version
.greaterOrEqual( SHADE_VERSION
) )
97 return render1( eyez
, tf
, lights
, & lattice
);
101 Kernel::the_PDF_version
.message( SHADE_VERSION
, "Replacing shade order 1 by 0." );
102 return render0( eyez
, tf
, lights
, & lattice
);
107 const SimplePDF::PDF_Version::Version SHADE_VERSION
= SimplePDF::PDF_Version::PDF_1_3
;
108 if( Kernel::the_PDF_version
.greaterOrEqual( SHADE_VERSION
) )
110 return render2( eyez
, tf
, lights
, & lattice
, vertexMem
);
114 Kernel::the_PDF_version
.message( SHADE_VERSION
, "Replacing shade order 2 by 0." );
115 return render0( eyez
, tf
, lights
, & lattice
);
119 throw Exceptions::InternalError( "SingleSidedPolygon3DGray::polygon_to2D: shadeOrder_ out of range." );
123 RefCountPtr
< const Lang::PaintedPolygon2D
>
124 Computation::SingleSidedPolygon3DGray::simple_polygon_to2D( const Concrete::Length eyez
, const Lang::Transform3D
& tf
, const std::list
< RefCountPtr
< const Lang::LightSource
> > & lights
) const
126 Kernel::GraphicsState
* metaStatePtr
= new Kernel::GraphicsState( true );
128 metaStatePtr
->nonStrokingColor_
= interpolator_
->compute( tf
, lights
, computeMean( ).transformed( tf
), eyez
);
130 RefCountPtr
< const Kernel::GraphicsState
> metaState( metaStatePtr
);
132 RefCountPtr
< Lang::ElementaryPath2D
> path
= RefCountPtr
< Lang::ElementaryPath2D
>( new Lang::ElementaryPath2D( ) );
134 if( tf
.isIdentity( ) )
136 typedef typeof points_ ListType
;
137 for( ListType::const_iterator i
= points_
.begin( ); i
!= points_
.end( ); ++i
)
139 path
->push_back( new Concrete::PathPoint2D( i
->make2D( eyez
) ) );
144 typedef typeof points_ ListType
;
145 for( ListType::const_iterator i
= points_
.begin( ); i
!= points_
.end( ); ++i
)
147 path
->push_back( new Concrete::PathPoint2D( i
->transformed( tf
).make2D( eyez
) ) );
151 return RefCountPtr
< const Lang::PaintedPolygon2D
>( new Lang::PaintedPolygon2D( metaState
, path
) );
154 RefCountPtr
< const Lang::PaintedPolygon2D
>
155 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
157 RefCountPtr
< const Lang::Group2D
> contents
= Lang::THE_NULL2D
;
159 while( ! lattice
->empty( ) )
161 const Computation::FacetLatticeTriangle
* triangle
= lattice
->back( );
162 contents
= RefCountPtr
< const Lang::Group2D
>( new Lang::GroupPair2D( triangle
->paint( interpolator_
, lights
, eyez
),
164 Kernel::THE_DEFAULT_STATE
) );
166 lattice
->pop_back( );
169 RefCountPtr
< Lang::ElementaryPath2D
> path
= RefCountPtr
< Lang::ElementaryPath2D
>( new Lang::ElementaryPath2D( ) );
171 if( tf
.isIdentity( ) )
173 typedef typeof points_ ListType
;
174 for( ListType::const_iterator i
= points_
.begin( ); i
!= points_
.end( ); ++i
)
176 path
->push_back( new Concrete::PathPoint2D( i
->make2D( eyez
) ) );
181 typedef typeof points_ ListType
;
182 for( ListType::const_iterator i
= points_
.begin( ); i
!= points_
.end( ); ++i
)
184 path
->push_back( new Concrete::PathPoint2D( i
->transformed( tf
).make2D( eyez
) ) );
188 return RefCountPtr
< const Lang::PaintedPolygon2D
>( new Lang::BBoxed2D( contents
, path
) );
191 RefCountPtr
< const Lang::PaintedPolygon2D
>
192 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
194 throw Exceptions::NotImplemented( "SingleSidedPolygon3DGray::render1" );
197 RefCountPtr
< const Lang::PaintedPolygon2D
>
198 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
200 RefCountPtr
< Lang::ElementaryPath2D
> bbox
= RefCountPtr
< Lang::ElementaryPath2D
>( new Lang::ElementaryPath2D( ) );
202 if( tf
.isIdentity( ) )
204 typedef typeof points_ ListType
;
205 for( ListType::const_iterator i
= points_
.begin( ); i
!= points_
.end( ); ++i
)
207 bbox
->push_back( new Concrete::PathPoint2D( i
->make2D( eyez
) ) );
212 typedef typeof points_ ListType
;
213 for( ListType::const_iterator i
= points_
.begin( ); i
!= points_
.end( ); ++i
)
215 bbox
->push_back( new Concrete::PathPoint2D( i
->transformed( tf
).make2D( eyez
) ) );
220 std::vector
< RefCountPtr
< const Lang::Gray
> > vertexColors
;
222 vertexColors
.reserve( vertexMem
.size( ) );
223 typedef typeof vertexMem ListType
;
224 for( ListType::const_iterator i
= vertexMem
.begin( ); i
!= vertexMem
.end( ); ++i
)
226 vertexColors
.push_back( interpolator_
->compute( tf
, lights
, (*i
)->p3D_
.transformed( tf
), eyez
) );
230 RefCountPtr
< const Lang::ColorSpace
> colorSpace
= Lang::THE_COLOR_SPACE_DEVICE_GRAY
;
232 RefCountPtr
< SimplePDF::PDF_Stream_out
> form
;
234 RefCountPtr
< SimplePDF::PDF_Object
> indirection
= SimplePDF::indirect( form
, & Kernel::theIndirectObjectCount
);
236 (*form
)[ "Subtype" ] = SimplePDF::newName( "Shading" );
237 (*form
)[ "ShadingType" ] = SimplePDF::newInt( 4 );
238 (*form
)[ "ColorSpace" ] = colorSpace
->name( );
239 // (*form)[ "BBox" ] =
240 // (*form)[ "AntiAlias" ] =
242 const size_t BITS_PER_COORDINATE
= 32;
243 const size_t BITS_PER_COMPONENT
= 12;
244 const size_t BITS_PER_FLAG
= 4;
245 const size_t NUMBER_OF_COMPONENTS
= colorSpace
->numberOfComponents( );
246 const size_t NUMBER_OF_COORDINATES
= 2; // don't change!
248 if( ( NUMBER_OF_COORDINATES
* BITS_PER_COORDINATE
+ NUMBER_OF_COMPONENTS
* BITS_PER_COMPONENT
+ BITS_PER_FLAG
) % 8 != 0 )
250 throw Exceptions::InternalError( "The sizes of thins don't add upp to a whole number of bytes!" );
253 (*form
)[ "BitsPerCoordinate" ] = SimplePDF::newInt( BITS_PER_COORDINATE
);
254 (*form
)[ "BitsPerComponent" ] = SimplePDF::newInt( BITS_PER_COMPONENT
);
255 (*form
)[ "BitsPerFlag" ] = SimplePDF::newInt( BITS_PER_FLAG
);
257 Concrete::Coords2D
x0y0( 0, 0 );
258 Concrete::Coords2D
x1y1( 0, 0 );
260 if( ! bbox
->boundingRectangle( & x0y0
, & x1y1
) )
262 throw Exceptions::InternalError( "SingleSidedPolygon3DGray::render2: Polygon without bounding box!" );
264 Concrete::Length bboxWidth
= x1y1
.x_
- x0y0
.x_
;
265 Concrete::Length bboxHeight
= x1y1
.y_
- x0y0
.y_
;
267 RefCountPtr
< SimplePDF::PDF_Vector
> decodeArray
= RefCountPtr
< SimplePDF::PDF_Vector
>( new SimplePDF::PDF_Vector( ) );
269 (*form
)[ "Decode" ] = decodeArray
;
271 decodeArray
->vec
.push_back( SimplePDF::newFloat( Concrete::Length::offtype( x0y0
.x_
) ) );
272 decodeArray
->vec
.push_back( SimplePDF::newFloat( Concrete::Length::offtype( x1y1
.x_
) ) );
273 decodeArray
->vec
.push_back( SimplePDF::newFloat( Concrete::Length::offtype( x0y0
.y_
) ) );
274 decodeArray
->vec
.push_back( SimplePDF::newFloat( Concrete::Length::offtype( x1y1
.y_
) ) );
275 for( size_t i
= 0; i
< NUMBER_OF_COMPONENTS
; ++i
)
277 decodeArray
->vec
.push_back( SimplePDF::newFloat( 0. ) );
278 decodeArray
->vec
.push_back( SimplePDF::newFloat( 1. ) );
281 const Computation::FacetLatticeVertex
* va
= 0;
282 const Computation::FacetLatticeVertex
* vb
= 0;
283 const Computation::FacetLatticeVertex
* vc
= 0;
286 // The first triangle is chosen at random. We have no previous vertexes to consider.
287 const Computation::FacetLatticeTriangle
* current
= lattice
->front( );
288 lattice
->pop_front( );
289 current
->getVertexes( & va
, & vb
, & vc
);
292 writePacked( form
->data
,
293 BITS_PER_COORDINATE
, BITS_PER_COMPONENT
, BITS_PER_FLAG
,
294 ( va
->p2D_
.x_
- x0y0
.x_
) / bboxWidth
,
295 ( va
->p2D_
.y_
- x0y0
.y_
) / bboxHeight
,
296 vertexColors
[ va
->i_
]->components( ), 0 );
297 writePacked( form
->data
,
298 BITS_PER_COORDINATE
, BITS_PER_COMPONENT
, BITS_PER_FLAG
,
299 ( vb
->p2D_
.x_
- x0y0
.x_
) / bboxWidth
,
300 ( vb
->p2D_
.y_
- x0y0
.y_
) / bboxHeight
,
301 vertexColors
[ vb
->i_
]->components( ), 0 );
302 writePacked( form
->data
,
303 BITS_PER_COORDINATE
, BITS_PER_COMPONENT
, BITS_PER_FLAG
,
304 ( vc
->p2D_
.x_
- x0y0
.x_
) / bboxWidth
,
305 ( vc
->p2D_
.y_
- x0y0
.y_
) / bboxHeight
,
306 vertexColors
[ vc
->i_
]->components( ), 0 );
309 while( ! lattice
->empty( ) )
311 typedef typeof *lattice ListType
;
313 for( ListType::iterator i
= lattice
->begin( ); i
!= lattice
->end( ); ++i
) // we could almost have used a const_iterator here,
314 // but since the last thing we do is erase at i, a non-const iterator must be used.
316 const Computation::FacetLatticeTriangle
* current
= *i
;
317 unsigned char flag
= current
->extendLattice( & va
, & vb
, & vc
);
324 writePacked( form
->data
,
325 BITS_PER_COORDINATE
, BITS_PER_COMPONENT
, BITS_PER_FLAG
,
326 ( vc
->p2D_
.x_
- x0y0
.x_
) / bboxWidth
,
327 ( vc
->p2D_
.y_
- x0y0
.y_
) / bboxHeight
,
328 vertexColors
[ vc
->i_
]->components( ), flag
);
337 // The first triangle is chosen at random. We have no previous vertexes to consider.
338 const Computation::FacetLatticeTriangle
* current
= lattice
->front( );
339 lattice
->pop_front( );
340 current
->getVertexes( & va
, & vb
, & vc
);
343 writePacked( form
->data
,
344 BITS_PER_COORDINATE
, BITS_PER_COMPONENT
, BITS_PER_FLAG
,
345 ( va
->p2D_
.x_
- x0y0
.x_
) / bboxWidth
,
346 ( va
->p2D_
.y_
- x0y0
.y_
) / bboxHeight
,
347 vertexColors
[ va
->i_
]->components( ), 0 );
348 writePacked( form
->data
,
349 BITS_PER_COORDINATE
, BITS_PER_COMPONENT
, BITS_PER_FLAG
,
350 ( vb
->p2D_
.x_
- x0y0
.x_
) / bboxWidth
,
351 ( vb
->p2D_
.y_
- x0y0
.y_
) / bboxHeight
,
352 vertexColors
[ vb
->i_
]->components( ), 0 );
353 writePacked( form
->data
,
354 BITS_PER_COORDINATE
, BITS_PER_COMPONENT
, BITS_PER_FLAG
,
355 ( vc
->p2D_
.x_
- x0y0
.x_
) / bboxWidth
,
356 ( vc
->p2D_
.y_
- x0y0
.y_
) / bboxHeight
,
357 vertexColors
[ vc
->i_
]->components( ), 0 );
361 RefCountPtr
< const Lang::Type4Shading
> contents
362 = RefCountPtr
< const Lang::Type4Shading
>( new Lang::Type4Shading( indirection
, bbox
) );
364 return RefCountPtr
< const Lang::PaintedPolygon2D
>( new Lang::BBoxed2D( contents
, bbox
) );
369 Computation::SingleSidedPolygon3DGray::writePacked( std::ostream
& os
,
370 const size_t BITS_PER_COORDINATE
, const size_t BITS_PER_COMPONENT
, const size_t BITS_PER_FLAG
,
371 const double x
, const double y
, const Concrete::Gray
& color
, const unsigned char flag
)
373 char rest
= 0; // Unused bits must be zero!
374 size_t restAvail
= 8; // Number of unused bits in <rest>.
377 size_t BITS
= BITS_PER_FLAG
;
378 writePackedValue( os
, & rest
, & restAvail
, flag
, BITS
);
382 size_t BITS
= BITS_PER_COORDINATE
;
383 unsigned int MAX
= UINT_MAX
>> ( 8 * sizeof( unsigned int ) - BITS
) ;
384 writePackedValue( os
, & rest
, & restAvail
, (unsigned int)( x
* MAX
), BITS
);
385 writePackedValue( os
, & rest
, & restAvail
, (unsigned int)( y
* MAX
), BITS
);
389 size_t BITS
= BITS_PER_COMPONENT
;
390 unsigned int MAX
= UINT_MAX
>> ( 8 * sizeof( unsigned int ) - BITS
) ;
391 writePackedValue( os
, & rest
, & restAvail
, (unsigned int)( color
.gr_
* MAX
), BITS
);
396 os
.write( & rest
, 1 );
402 Computation::SingleSidedPolygon3DGray::writePackedValue( std::ostream
& os
, char * rest
, size_t * restAvail
,
403 unsigned int val
, size_t bits
)
405 if( bits
>= *restAvail
)
407 char tmp
= ( val
>> ( bits
- *restAvail
) );
410 val
%= ( 1 << ( bits
- *restAvail
) );
419 char tmp
= ( val
>> ( bits
- 8 ) );
420 os
.write( & tmp
, 1 );
421 val
%= ( 1 << ( bits
- 8 ) );
427 // By now we know that bits <= 7
428 if( bits
> *restAvail
)
430 char tmp
= ( val
>> ( bits
- *restAvail
) );
439 // This time there are no full bytes to write.
442 // By now we know that bits <= 6 and *restavail == 8
445 char tmp
= ( val
<< ( 8 - bits
) );
452 RefCountPtr
< const Lang::Color
>
453 Computation::SingleSidedPolygon3DGray::getColor( ) const
455 static bool warned
= false;
458 // This color is only used for debugging, so it doesn't matter that we don't care about lightening.
459 WARN_OR_THROW( Exceptions::InternalError( "SingleSidedPolygon3DGray::getColor just returns the lightMultiply coefficients as a color.", true ) )
460 WARN_OR_THROW( Exceptions::InternalError( "The warning above will be suppressed from now on.", true ) )
463 return interpolator_
->getDebugColor( );
467 Computation::SingleSidedPolygon3DGray::gcMark( Kernel::GCMarkedSet
& marked
)
469 const_cast< Computation::FacetInterpolatorGray
* >( interpolator_
.getPtr( ) )->gcMark( marked
);
473 Computation::SingleSidedPolygon3DRGB::SingleSidedPolygon3DRGB( const RefCountPtr
< const Computation::FacetInterpolatorRGB
> & interpolator
,
475 const Concrete::UnitFloatTriple
& polygonUnitNormal
,
477 Concrete::Length tiebreaker
,
478 Concrete::Length viewResolution
,
479 Computation::FacetShadeOrder shadeOrder
)
480 : Computation::PaintedPolygon3D( singleSided
, polygonUnitNormal
, m
, tiebreaker
),
481 interpolator_( interpolator
),
482 viewResolution_( viewResolution
),
483 shadeOrder_( shadeOrder
)
486 Computation::SingleSidedPolygon3DRGB::~SingleSidedPolygon3DRGB( )
489 RefCountPtr
< const Lang::PaintedPolygon2D
>
490 Computation::SingleSidedPolygon3DRGB::polygon_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const std::list
< RefCountPtr
< const Lang::LightSource
> > & lights
) const
492 // In the current implementation, the color is only computed at one point. Later, this
493 // shall be extended to nice shadings.
495 Concrete::Length eyez
= dyn
->getEyeZ( );
497 if( viewResolution_
== Concrete::HUGE_LENGTH
&&
500 return simple_polygon_to2D( eyez
, tf
, lights
);
503 PtrOwner_back_Access
< std::list
< const FacetLatticeVertex
* > > vertexMem
;
504 PtrOwner_back_Access
< std::list
< const FacetLatticeEdge
* > > edgeMem
;
505 PtrOwner_back_Access
< std::list
< const Computation::FacetLatticeTriangle
* > > lattice
;
507 makeLattice( & lattice
, & edgeMem
, & vertexMem
, viewResolution_
, eyez
, tf
);
509 switch( shadeOrder_
)
512 return render0( eyez
, tf
, lights
, & lattice
);
515 const SimplePDF::PDF_Version::Version SHADE_VERSION
= SimplePDF::PDF_Version::PDF_1_3
;
516 if( Kernel::the_PDF_version
.greaterOrEqual( SHADE_VERSION
) )
518 return render1( eyez
, tf
, lights
, & lattice
);
522 Kernel::the_PDF_version
.message( SHADE_VERSION
, "Replacing shade order 1 by 0." );
523 return render0( eyez
, tf
, lights
, & lattice
);
528 const SimplePDF::PDF_Version::Version SHADE_VERSION
= SimplePDF::PDF_Version::PDF_1_3
;
529 if( Kernel::the_PDF_version
.greaterOrEqual( SHADE_VERSION
) )
531 return render2( eyez
, tf
, lights
, & lattice
, vertexMem
);
535 Kernel::the_PDF_version
.message( SHADE_VERSION
, "Replacing shade order 2 by 0." );
536 return render0( eyez
, tf
, lights
, & lattice
);
540 throw Exceptions::InternalError( "SingleSidedPolygon3DRGB::polygon_to2D: shadeOrder_ out of range." );
544 RefCountPtr
< const Lang::PaintedPolygon2D
>
545 Computation::SingleSidedPolygon3DRGB::simple_polygon_to2D( const Concrete::Length eyez
, const Lang::Transform3D
& tf
, const std::list
< RefCountPtr
< const Lang::LightSource
> > & lights
) const
547 Kernel::GraphicsState
* metaStatePtr
= new Kernel::GraphicsState( true );
549 metaStatePtr
->nonStrokingColor_
= interpolator_
->compute( tf
, lights
, computeMean( ).transformed( tf
), eyez
);
551 RefCountPtr
< const Kernel::GraphicsState
> metaState( metaStatePtr
);
553 RefCountPtr
< Lang::ElementaryPath2D
> path
= RefCountPtr
< Lang::ElementaryPath2D
>( new Lang::ElementaryPath2D( ) );
555 if( tf
.isIdentity( ) )
557 typedef typeof points_ ListType
;
558 for( ListType::const_iterator i
= points_
.begin( ); i
!= points_
.end( ); ++i
)
560 path
->push_back( new Concrete::PathPoint2D( i
->make2D( eyez
) ) );
565 typedef typeof points_ ListType
;
566 for( ListType::const_iterator i
= points_
.begin( ); i
!= points_
.end( ); ++i
)
568 path
->push_back( new Concrete::PathPoint2D( i
->transformed( tf
).make2D( eyez
) ) );
572 return RefCountPtr
< const Lang::PaintedPolygon2D
>( new Lang::PaintedPolygon2D( metaState
, path
) );
575 RefCountPtr
< const Lang::PaintedPolygon2D
>
576 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
578 RefCountPtr
< const Lang::Group2D
> contents
= Lang::THE_NULL2D
;
580 while( ! lattice
->empty( ) )
582 const Computation::FacetLatticeTriangle
* triangle
= lattice
->back( );
583 contents
= RefCountPtr
< const Lang::Group2D
>( new Lang::GroupPair2D( triangle
->paint( interpolator_
, lights
, eyez
),
585 Kernel::THE_DEFAULT_STATE
) );
587 lattice
->pop_back( );
590 RefCountPtr
< Lang::ElementaryPath2D
> path
= RefCountPtr
< Lang::ElementaryPath2D
>( new Lang::ElementaryPath2D( ) );
592 if( tf
.isIdentity( ) )
594 typedef typeof points_ ListType
;
595 for( ListType::const_iterator i
= points_
.begin( ); i
!= points_
.end( ); ++i
)
597 path
->push_back( new Concrete::PathPoint2D( i
->make2D( eyez
) ) );
602 typedef typeof points_ ListType
;
603 for( ListType::const_iterator i
= points_
.begin( ); i
!= points_
.end( ); ++i
)
605 path
->push_back( new Concrete::PathPoint2D( i
->transformed( tf
).make2D( eyez
) ) );
609 return RefCountPtr
< const Lang::PaintedPolygon2D
>( new Lang::BBoxed2D( contents
, path
) );
612 RefCountPtr
< const Lang::PaintedPolygon2D
>
613 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
615 throw Exceptions::NotImplemented( "SingleSidedPolygon3DRGB::render1" );
618 RefCountPtr
< const Lang::PaintedPolygon2D
>
619 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
621 RefCountPtr
< Lang::ElementaryPath2D
> bbox
= RefCountPtr
< Lang::ElementaryPath2D
>( new Lang::ElementaryPath2D( ) );
623 if( tf
.isIdentity( ) )
625 typedef typeof points_ ListType
;
626 for( ListType::const_iterator i
= points_
.begin( ); i
!= points_
.end( ); ++i
)
628 bbox
->push_back( new Concrete::PathPoint2D( i
->make2D( eyez
) ) );
633 typedef typeof points_ ListType
;
634 for( ListType::const_iterator i
= points_
.begin( ); i
!= points_
.end( ); ++i
)
636 bbox
->push_back( new Concrete::PathPoint2D( i
->transformed( tf
).make2D( eyez
) ) );
641 std::vector
< RefCountPtr
< const Lang::RGB
> > vertexColors
;
643 vertexColors
.reserve( vertexMem
.size( ) );
644 typedef typeof vertexMem ListType
;
645 for( ListType::const_iterator i
= vertexMem
.begin( ); i
!= vertexMem
.end( ); ++i
)
647 vertexColors
.push_back( interpolator_
->compute( tf
, lights
, (*i
)->p3D_
.transformed( tf
), eyez
) );
651 RefCountPtr
< const Lang::ColorSpace
> colorSpace
= Lang::THE_COLOR_SPACE_DEVICE_RGB
;
653 RefCountPtr
< SimplePDF::PDF_Stream_out
> form
;
655 RefCountPtr
< SimplePDF::PDF_Object
> indirection
= SimplePDF::indirect( form
, & Kernel::theIndirectObjectCount
);
657 (*form
)[ "Subtype" ] = SimplePDF::newName( "Shading" );
658 (*form
)[ "ShadingType" ] = SimplePDF::newInt( 4 );
659 (*form
)[ "ColorSpace" ] = colorSpace
->name( );
660 // (*form)[ "BBox" ] =
661 // (*form)[ "AntiAlias" ] =
663 const size_t BITS_PER_COORDINATE
= 32;
664 const size_t BITS_PER_COMPONENT
= 12;
665 const size_t BITS_PER_FLAG
= 4;
666 const size_t NUMBER_OF_COMPONENTS
= colorSpace
->numberOfComponents( );
667 const size_t NUMBER_OF_COORDINATES
= 2; // don't change!
669 if( ( NUMBER_OF_COORDINATES
* BITS_PER_COORDINATE
+ NUMBER_OF_COMPONENTS
* BITS_PER_COMPONENT
+ BITS_PER_FLAG
) % 8 != 0 )
671 throw Exceptions::InternalError( "The sizes of thins don't add upp to a whole number of bytes!" );
674 (*form
)[ "BitsPerCoordinate" ] = SimplePDF::newInt( BITS_PER_COORDINATE
);
675 (*form
)[ "BitsPerComponent" ] = SimplePDF::newInt( BITS_PER_COMPONENT
);
676 (*form
)[ "BitsPerFlag" ] = SimplePDF::newInt( BITS_PER_FLAG
);
678 Concrete::Coords2D
x0y0( 0, 0 );
679 Concrete::Coords2D
x1y1( 0, 0 );
681 if( ! bbox
->boundingRectangle( & x0y0
, & x1y1
) )
683 throw Exceptions::InternalError( "SingleSidedPolygon3DRGB::render2: Polygon without bounding box!" );
685 Concrete::Length bboxWidth
= x1y1
.x_
- x0y0
.x_
;
686 Concrete::Length bboxHeight
= x1y1
.y_
- x0y0
.y_
;
688 RefCountPtr
< SimplePDF::PDF_Vector
> decodeArray
= RefCountPtr
< SimplePDF::PDF_Vector
>( new SimplePDF::PDF_Vector( ) );
690 (*form
)[ "Decode" ] = decodeArray
;
692 decodeArray
->vec
.push_back( SimplePDF::newFloat( Concrete::Length::offtype( x0y0
.x_
) ) );
693 decodeArray
->vec
.push_back( SimplePDF::newFloat( Concrete::Length::offtype( x1y1
.x_
) ) );
694 decodeArray
->vec
.push_back( SimplePDF::newFloat( Concrete::Length::offtype( x0y0
.y_
) ) );
695 decodeArray
->vec
.push_back( SimplePDF::newFloat( Concrete::Length::offtype( x1y1
.y_
) ) );
696 for( size_t i
= 0; i
< NUMBER_OF_COMPONENTS
; ++i
)
698 decodeArray
->vec
.push_back( SimplePDF::newFloat( 0. ) );
699 decodeArray
->vec
.push_back( SimplePDF::newFloat( 1. ) );
702 const Computation::FacetLatticeVertex
* va
= 0;
703 const Computation::FacetLatticeVertex
* vb
= 0;
704 const Computation::FacetLatticeVertex
* vc
= 0;
707 // The first triangle is chosen at random. We have no previous vertexes to consider.
708 const Computation::FacetLatticeTriangle
* current
= lattice
->front( );
709 lattice
->pop_front( );
710 current
->getVertexes( & va
, & vb
, & vc
);
713 writePacked( form
->data
,
714 BITS_PER_COORDINATE
, BITS_PER_COMPONENT
, BITS_PER_FLAG
,
715 ( va
->p2D_
.x_
- x0y0
.x_
) / bboxWidth
,
716 ( va
->p2D_
.y_
- x0y0
.y_
) / bboxHeight
,
717 vertexColors
[ va
->i_
]->components( ), 0 );
718 writePacked( form
->data
,
719 BITS_PER_COORDINATE
, BITS_PER_COMPONENT
, BITS_PER_FLAG
,
720 ( vb
->p2D_
.x_
- x0y0
.x_
) / bboxWidth
,
721 ( vb
->p2D_
.y_
- x0y0
.y_
) / bboxHeight
,
722 vertexColors
[ vb
->i_
]->components( ), 0 );
723 writePacked( form
->data
,
724 BITS_PER_COORDINATE
, BITS_PER_COMPONENT
, BITS_PER_FLAG
,
725 ( vc
->p2D_
.x_
- x0y0
.x_
) / bboxWidth
,
726 ( vc
->p2D_
.y_
- x0y0
.y_
) / bboxHeight
,
727 vertexColors
[ vc
->i_
]->components( ), 0 );
730 while( ! lattice
->empty( ) )
732 typedef typeof *lattice ListType
;
734 for( ListType::iterator i
= lattice
->begin( ); i
!= lattice
->end( ); ++i
) // we could almost have used a const_iterator here,
735 // but since the last thing we do is erase at i, a non-const iterator must be used.
737 const Computation::FacetLatticeTriangle
* current
= *i
;
738 unsigned char flag
= current
->extendLattice( & va
, & vb
, & vc
);
745 writePacked( form
->data
,
746 BITS_PER_COORDINATE
, BITS_PER_COMPONENT
, BITS_PER_FLAG
,
747 ( vc
->p2D_
.x_
- x0y0
.x_
) / bboxWidth
,
748 ( vc
->p2D_
.y_
- x0y0
.y_
) / bboxHeight
,
749 vertexColors
[ vc
->i_
]->components( ), flag
);
758 // The first triangle is chosen at random. We have no previous vertexes to consider.
759 const Computation::FacetLatticeTriangle
* current
= lattice
->front( );
760 lattice
->pop_front( );
761 current
->getVertexes( & va
, & vb
, & vc
);
764 writePacked( form
->data
,
765 BITS_PER_COORDINATE
, BITS_PER_COMPONENT
, BITS_PER_FLAG
,
766 ( va
->p2D_
.x_
- x0y0
.x_
) / bboxWidth
,
767 ( va
->p2D_
.y_
- x0y0
.y_
) / bboxHeight
,
768 vertexColors
[ va
->i_
]->components( ), 0 );
769 writePacked( form
->data
,
770 BITS_PER_COORDINATE
, BITS_PER_COMPONENT
, BITS_PER_FLAG
,
771 ( vb
->p2D_
.x_
- x0y0
.x_
) / bboxWidth
,
772 ( vb
->p2D_
.y_
- x0y0
.y_
) / bboxHeight
,
773 vertexColors
[ vb
->i_
]->components( ), 0 );
774 writePacked( form
->data
,
775 BITS_PER_COORDINATE
, BITS_PER_COMPONENT
, BITS_PER_FLAG
,
776 ( vc
->p2D_
.x_
- x0y0
.x_
) / bboxWidth
,
777 ( vc
->p2D_
.y_
- x0y0
.y_
) / bboxHeight
,
778 vertexColors
[ vc
->i_
]->components( ), 0 );
782 RefCountPtr
< const Lang::Type4Shading
> contents
783 = RefCountPtr
< const Lang::Type4Shading
>( new Lang::Type4Shading( indirection
, bbox
) );
785 return RefCountPtr
< const Lang::PaintedPolygon2D
>( new Lang::BBoxed2D( contents
, bbox
) );
790 Computation::SingleSidedPolygon3DRGB::writePacked( std::ostream
& os
,
791 const size_t BITS_PER_COORDINATE
, const size_t BITS_PER_COMPONENT
, const size_t BITS_PER_FLAG
,
792 const double x
, const double y
, const Concrete::RGB
& color
, const unsigned char flag
)
794 char rest
= 0; // Unused bits must be zero!
795 size_t restAvail
= 8; // Number of unused bits in <rest>.
798 size_t BITS
= BITS_PER_FLAG
;
799 writePackedValue( os
, & rest
, & restAvail
, flag
, BITS
);
803 size_t BITS
= BITS_PER_COORDINATE
;
804 unsigned int MAX
= UINT_MAX
>> ( 8 * sizeof( unsigned int ) - BITS
) ;
805 writePackedValue( os
, & rest
, & restAvail
, (unsigned int)( x
* MAX
), BITS
);
806 writePackedValue( os
, & rest
, & restAvail
, (unsigned int)( y
* MAX
), BITS
);
810 size_t BITS
= BITS_PER_COMPONENT
;
811 unsigned int MAX
= UINT_MAX
>> ( 8 * sizeof( unsigned int ) - BITS
) ;
812 writePackedValue( os
, & rest
, & restAvail
, (unsigned int)( color
.r_
* MAX
), BITS
);
813 writePackedValue( os
, & rest
, & restAvail
, (unsigned int)( color
.g_
* MAX
), BITS
);
814 writePackedValue( os
, & rest
, & restAvail
, (unsigned int)( color
.b_
* MAX
), BITS
);
819 os
.write( & rest
, 1 );
825 Computation::SingleSidedPolygon3DRGB::writePackedValue( std::ostream
& os
, char * rest
, size_t * restAvail
,
826 unsigned int val
, size_t bits
)
828 if( bits
>= *restAvail
)
830 char tmp
= ( val
>> ( bits
- *restAvail
) );
833 val
%= ( 1 << ( bits
- *restAvail
) );
842 char tmp
= ( val
>> ( bits
- 8 ) );
843 os
.write( & tmp
, 1 );
844 val
%= ( 1 << ( bits
- 8 ) );
850 // By now we know that bits <= 7
851 if( bits
> *restAvail
)
853 char tmp
= ( val
>> ( bits
- *restAvail
) );
862 // This time there are no full bytes to write.
865 // By now we know that bits <= 6 and *restavail == 8
868 char tmp
= ( val
<< ( 8 - bits
) );
875 RefCountPtr
< const Lang::Color
>
876 Computation::SingleSidedPolygon3DRGB::getColor( ) const
878 static bool warned
= false;
881 // This color is only used for debugging, so it doesn't matter that we don't care about lightening.
882 WARN_OR_THROW( Exceptions::InternalError( "SingleSidedPolygon3DRGB::getColor just returns the lightMultiply coefficients as a color.", true ) )
883 WARN_OR_THROW( Exceptions::InternalError( "The warning above will be suppressed from now on.", true ) )
886 return interpolator_
->getDebugColor( );
890 Computation::SingleSidedPolygon3DRGB::gcMark( Kernel::GCMarkedSet
& marked
)
892 const_cast< Computation::FacetInterpolatorRGB
* >( interpolator_
.getPtr( ) )->gcMark( marked
);