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 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"
36 using namespace Shapes
;
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' ) ;
51 Computation::SingleSidedPolygon3DGray::SingleSidedPolygon3DGray( const RefCountPtr
< const Computation::FacetInterpolatorGray
> & interpolator
,
53 const Concrete::UnitFloatTriple
& polygonUnitNormal
,
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
)
64 Computation::SingleSidedPolygon3DGray::~SingleSidedPolygon3DGray( )
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
&&
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
);
90 return render0( eyez
, tf
, lights
, & lattice
);
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
);
100 Kernel::the_PDF_version
.message( SHADE_VERSION
, "Replacing shade order 1 by 0." );
101 return render0( eyez
, tf
, lights
, & lattice
);
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
);
113 Kernel::the_PDF_version
.message( SHADE_VERSION
, "Replacing shade order 2 by 0." );
114 return render0( eyez
, tf
, lights
, & lattice
);
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( ) );
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
) ) );
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
),
163 Kernel::THE_DEFAULT_STATE
) );
165 lattice
->pop_back( );
168 RefCountPtr
< Lang::ElementaryPath2D
> path
= RefCountPtr
< Lang::ElementaryPath2D
>( new Lang::ElementaryPath2D( ) );
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
) ) );
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( ) );
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
) ) );
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
);
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
;
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
);
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
);
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
);
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
) );
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
);
395 os
.write( & rest
, 1 );
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
) );
409 val
%= ( 1 << ( bits
- *restAvail
) );
418 char tmp
= ( val
>> ( bits
- 8 ) );
419 os
.write( & tmp
, 1 );
420 val
%= ( 1 << ( bits
- 8 ) );
426 // By now we know that bits <= 7
427 if( bits
> *restAvail
)
429 char tmp
= ( val
>> ( bits
- *restAvail
) );
438 // This time there are no full bytes to write.
441 // By now we know that bits <= 6 and *restavail == 8
444 char tmp
= ( val
<< ( 8 - bits
) );
451 RefCountPtr
< const Lang::Color
>
452 Computation::SingleSidedPolygon3DGray::getColor( ) const
454 static bool warned
= false;
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
;
462 return interpolator_
->getDebugColor( );
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
,
474 const Concrete::UnitFloatTriple
& polygonUnitNormal
,
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
&&
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_
)
511 return render0( eyez
, tf
, lights
, & lattice
);
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
);
521 Kernel::the_PDF_version
.message( SHADE_VERSION
, "Replacing shade order 1 by 0." );
522 return render0( eyez
, tf
, lights
, & lattice
);
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
);
534 Kernel::the_PDF_version
.message( SHADE_VERSION
, "Replacing shade order 2 by 0." );
535 return render0( eyez
, tf
, lights
, & lattice
);
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( ) );
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
) ) );
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
),
584 Kernel::THE_DEFAULT_STATE
) );
586 lattice
->pop_back( );
589 RefCountPtr
< Lang::ElementaryPath2D
> path
= RefCountPtr
< Lang::ElementaryPath2D
>( new Lang::ElementaryPath2D( ) );
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
) ) );
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( ) );
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
) ) );
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
);
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
;
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
);
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
);
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
);
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
) );
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
);
818 os
.write( & rest
, 1 );
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
) );
832 val
%= ( 1 << ( bits
- *restAvail
) );
841 char tmp
= ( val
>> ( bits
- 8 ) );
842 os
.write( & tmp
, 1 );
843 val
%= ( 1 << ( bits
- 8 ) );
849 // By now we know that bits <= 7
850 if( bits
> *restAvail
)
852 char tmp
= ( val
>> ( bits
- *restAvail
) );
861 // This time there are no full bytes to write.
864 // By now we know that bits <= 6 and *restavail == 8
867 char tmp
= ( val
<< ( 8 - bits
) );
874 RefCountPtr
< const Lang::Color
>
875 Computation::SingleSidedPolygon3DRGB::getColor( ) const
877 static bool warned
= false;
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
;
885 return interpolator_
->getDebugColor( );
889 Computation::SingleSidedPolygon3DRGB::gcMark( Kernel::GCMarkedSet
& marked
)
891 const_cast< Computation::FacetInterpolatorRGB
* >( interpolator_
.getPtr( ) )->gcMark( marked
);