// Dump a pixel sample void CqMPDump::dump(int x, int y, int idx, const CqVector2D& pos) { short id = 2; TqFloat f; if (m_outFile==NULL) { Aqsis::log() << error << "Attempted to write to unopened mpdump file." << std::endl; return; } size_t len_written = fwrite((void*)&id, sizeof(short), 1, m_outFile); len_written += fwrite((void*)&x, sizeof(int), 1, m_outFile); len_written += fwrite((void*)&y, sizeof(int), 1, m_outFile); len_written += fwrite((void*)&idx, sizeof(int), 1, m_outFile); f = pos.x(); len_written += fwrite((void*)&f, sizeof(TqFloat), 1, m_outFile); f = pos.y(); len_written += fwrite((void*)&f, sizeof(TqFloat), 1, m_outFile); if(len_written != 6) AQSIS_THROW_XQERROR(XqInvalidFile, EqE_System, "Error writing mpdump file"); }
// Dump all pixel samples of the current bucket void CqMPDump::dumpPixelSamples(const CqBucketProcessor& bp) { const std::vector<CqImagePixelPtr>& pixels = bp.pixels(); for(std::vector<CqImagePixelPtr>::const_iterator p = pixels.begin(), e = pixels.end(); p != e; ++p) { const CqImagePixel& pixel = **p; for(int i = 0, numSamples = pixel.numSamples(); i < numSamples; ++i) { CqVector2D pos = pixel.SampleData(i).position; if(!( pos.x() <= bp.SampleRegion().xMin() || pos.x() > bp.SampleRegion().xMax() || pos.y() <= bp.SampleRegion().yMin() || pos.y() > bp.SampleRegion().yMax() ) ) { // Only dump samples which are inside bp.SampleRegion() // this means that only samples which are actually computed for // the current bucket will be considered. dump(lfloor(pos.x()), lfloor(pos.y()), i, pos); } } } }
bool CqCurve::Diceable() { // OK, here the CqCubicCurveSegment line has two options: // 1. split into two more lines // 2. turn into a bilinear patch for rendering // We don't want to go turning into a patch unless absolutely // necessary, since patches cost more. We only want to become a patch // if the current curve is "best handled" as a patch. For now, I'm // choosing to define that the curve is best handled as a patch under // one or more of the following two conditions: // 1. If the maximum width is a significant fraction of the length of // the line (width greater than 0.75 x length; ignoring normals). // 2. If the length of the line (ignoring the width; cos' it's // covered by point 1) is such that it's likely a bilinear // patch would be diced immediately if we created one (so that // patches don't have to get split!). // 3. If the curve crosses the eye plane (m_fDiceable == false). // find the length of the CqLinearCurveSegment line in raster space if( m_splitDecision == Split_Undecided ) { // AGG - 31/07/04 // well, if we follow the above statagy we end up splitting into // far too many grids (with roughly 1 mpg per grid). so after // profiling a few scenes, the fastest method seems to be just // to convert to a patch immediatly. // we really need a native dice for curves but until that time // i reckon this is best. //m_splitDecision = Split_Patch; CqMatrix matCtoR; QGetRenderContext() ->matSpaceToSpace( "camera", "raster", NULL, NULL, QGetRenderContextI()->Time(), matCtoR ); // control hull CqVector2D hull[2] = { vectorCast<CqVector2D>(matCtoR * P()->pValue(0)[0]), vectorCast<CqVector2D>(matCtoR * P()->pValue(1)[0]) }; CqVector2D lengthVector = hull[ 1 ] - hull[ 0 ]; TqFloat lengthraster = lengthVector.Magnitude(); // find the approximate "length" of a diced patch in raster space TqFloat gridlength = GetGridLength(); // decide whether to split into more curve segments or a patch if(( lengthraster < gridlength ) || ( !m_fDiceable )) { // split into a patch m_splitDecision = Split_Patch; } else { // split into smaller curves m_splitDecision = Split_Curve; } } return false; }
bool CqImageBuffer::CullSurface( CqBound& Bound, const boost::shared_ptr<CqSurface>& pSurface ) { // If the primitive is completely outside of the hither-yon z range, cull it. if ( Bound.vecMin().z() >= m_optCache.clipFar || Bound.vecMax().z() <= m_optCache.clipNear ) return true; // This needs to be re-enabled when the RiClippingPlane code is wired up. #if 0 if(QGetRenderContext()->clippingVolume().whereIs(Bound) == CqBound::Side_Outside) { return(true); } #endif // If the primitive spans the epsilon plane and the hither plane and can be split, if ( Bound.vecMin().z() <= FLT_EPSILON ) { // Mark the primitive as not dicable. pSurface->ForceUndiceable(); CqString objname( "unnamed" ); const CqString* pattrName = pSurface->pAttributes() ->GetStringAttribute( "identifier", "name" ); if ( pattrName != 0 ) objname = pattrName[ 0 ]; Aqsis::log() << info << "Object \"" << objname.c_str() << "\" spans the epsilon plane" << std::endl; if ( pSurface->SplitCount() > m_optCache.maxEyeSplits ) { Aqsis::log() << warning << "Max eyesplits for object \"" << objname.c_str() << "\" exceeded" << std::endl; return( true ); } return ( false ); } TqFloat minz = Bound.vecMin().z(); TqFloat maxz = Bound.vecMax().z(); // Convert the bounds to raster space. CqMatrix mat; QGetRenderContext() ->matSpaceToSpace( "camera", "raster", NULL, NULL, QGetRenderContext()->Time(), mat ); Bound.Transform( mat ); // Take into account depth-of-field if ( QGetRenderContext() ->UsingDepthOfField() ) { const CqVector2D minZCoc = QGetRenderContext()->GetCircleOfConfusion( minz ); const CqVector2D maxZCoc = QGetRenderContext()->GetCircleOfConfusion( maxz ); TqFloat cocX = max( minZCoc.x(), maxZCoc.x() ); TqFloat cocY = max( minZCoc.y(), maxZCoc.y() ); Bound.vecMin().x( Bound.vecMin().x() - cocX ); Bound.vecMin().y( Bound.vecMin().y() - cocY ); Bound.vecMax().x( Bound.vecMax().x() + cocX ); Bound.vecMax().y( Bound.vecMax().y() + cocY ); } // And expand to account for filter size. Bound.vecMin().x( Bound.vecMin().x() - m_optCache.xFiltSize / 2.0f ); Bound.vecMin().y( Bound.vecMin().y() - m_optCache.yFiltSize / 2.0f ); Bound.vecMax().x( Bound.vecMax().x() + m_optCache.xFiltSize / 2.0f ); Bound.vecMax().y( Bound.vecMax().y() + m_optCache.yFiltSize / 2.0f ); // If the bounds are completely outside the viewing frustum, cull the primitive. if( Bound.vecMin().x() > QGetRenderContext()->cropWindowXMax() || Bound.vecMin().y() > QGetRenderContext()->cropWindowYMax() || Bound.vecMax().x() < QGetRenderContext()->cropWindowXMin() || Bound.vecMax().y() < QGetRenderContext()->cropWindowYMin() ) return ( true ); // Restore Z-Values to camera space. Bound.vecMin().z( minz ); Bound.vecMax().z( maxz ); // Cache the Bound. pSurface->CacheRasterBound( Bound ); return ( false ); }