| 107 | } |
| 108 | |
| 109 | ObjectPtr EnvMapSampler::doOperation( const CompoundObject * operands ) |
| 110 | { |
| 111 | ImagePrimitivePtr image = static_cast<ImagePrimitive *>( imageParameter()->getValue() )->copy(); |
| 112 | Box2i dataWindow = image->getDataWindow(); |
| 113 | |
| 114 | // find the rgb channels |
| 115 | ConstFloatVectorDataPtr redData = image->getChannel<float>( "R" ); |
| 116 | ConstFloatVectorDataPtr greenData = image->getChannel<float>( "G" ); |
| 117 | ConstFloatVectorDataPtr blueData = image->getChannel<float>( "B" ); |
| 118 | if( !(redData && greenData && blueData) ) |
| 119 | { |
| 120 | throw Exception( "Image does not contain valid RGB float channels." ); |
| 121 | } |
| 122 | const vector<float> &red = redData->readable(); |
| 123 | const vector<float> &green = greenData->readable(); |
| 124 | const vector<float> &blue = blueData->readable(); |
| 125 | |
| 126 | // get a luminance channel |
| 127 | LuminanceOpPtr luminanceOp = new LuminanceOp(); |
| 128 | luminanceOp->inputParameter()->setValue( image ); |
| 129 | luminanceOp->copyParameter()->getTypedValue() = false; |
| 130 | luminanceOp->removeColorChannelsParameter()->getTypedValue() = false; |
| 131 | luminanceOp->operate(); |
| 132 | |
| 133 | // do the median cut thing to get some samples |
| 134 | MedianCutSamplerPtr sampler = new MedianCutSampler; |
| 135 | sampler->imageParameter()->setValue( image ); |
| 136 | sampler->subdivisionDepthParameter()->setNumericValue( subdivisionDepthParameter()->getNumericValue() ); |
| 137 | ConstCompoundObjectPtr samples = boost::static_pointer_cast<CompoundObject>( sampler->operate() ); |
| 138 | const vector<V2f> ¢roids = boost::static_pointer_cast<V2fVectorData>( samples->members().find( "centroids" )->second )->readable(); |
| 139 | const vector<Box2i> &areas = boost::static_pointer_cast<Box2iVectorData>( samples->members().find( "areas" )->second )->readable(); |
| 140 | |
| 141 | // get light directions and colors from the samples |
| 142 | V3fVectorDataPtr directionsData = new V3fVectorData; |
| 143 | Color3fVectorDataPtr colorsData = new Color3fVectorData; |
| 144 | vector<V3f> &directions = directionsData->writable(); |
| 145 | vector<Color3f> &colors = colorsData->writable(); |
| 146 | |
| 147 | float radiansPerPixel = M_PI / (dataWindow.size().y + 1); |
| 148 | float angleAtTop = ( M_PI - radiansPerPixel ) / 2.0f; |
| 149 | |
| 150 | for( unsigned i=0; i<centroids.size(); i++ ) |
| 151 | { |
| 152 | const Box2i &area = areas[i]; |
| 153 | Color3f color( 0 ); |
| 154 | for( int y=area.min.y; y<=area.max.y; y++ ) |
| 155 | { |
| 156 | int yRel = y - dataWindow.min.y; |
| 157 | |
| 158 | float angle = angleAtTop - yRel * radiansPerPixel; |
| 159 | float weight = cosf( angle ); |
| 160 | int index = (area.min.x - dataWindow.min.x) + (dataWindow.size().x + 1 ) * yRel; |
| 161 | for( int x=area.min.x; x<=area.max.x; x++ ) |
| 162 | { |
| 163 | color[0] += weight * red[index]; |
| 164 | color[1] += weight * green[index]; |
| 165 | color[2] += weight * blue[index]; |
| 166 | index++; |
nothing calls this directly
no test coverage detected