StatusWithExpression ExpressionParser::_parseNot( const char* name, const BSONElement& e ) { if ( e.type() == RegEx ) { StatusWithExpression s = _parseRegexElement( name, e ); if ( !s.isOK() ) return s; std::auto_ptr<NotExpression> n( new NotExpression() ); Status s2 = n->init( s.getValue() ); if ( !s2.isOK() ) return StatusWithExpression( s2 ); return StatusWithExpression( n.release() ); } if ( e.type() != Object ) return StatusWithExpression( ErrorCodes::BadValue, "$not needs a regex or a document" ); std::auto_ptr<AndExpression> theAnd( new AndExpression() ); Status s = _parseSub( name, e.Obj(), theAnd.get() ); if ( !s.isOK() ) return StatusWithExpression( s ); std::auto_ptr<NotExpression> theNot( new NotExpression() ); s = theNot->init( theAnd.release() ); if ( !s.isOK() ) return StatusWithExpression( s ); return StatusWithExpression( theNot.release() ); }
StatusWithMatchExpression MatchExpressionParser::_parseNot( const char* name, const BSONElement& e ) { if ( e.type() == RegEx ) { StatusWithMatchExpression s = _parseRegexElement( name, e ); if ( !s.isOK() ) return s; std::auto_ptr<NotMatchExpression> n( new NotMatchExpression() ); Status s2 = n->init( s.getValue() ); if ( !s2.isOK() ) return StatusWithMatchExpression( s2 ); return StatusWithMatchExpression( n.release() ); } if ( e.type() != Object ) return StatusWithMatchExpression( ErrorCodes::BadValue, "$not needs a regex or a document" ); BSONObj notObject = e.Obj(); if ( notObject.isEmpty() ) return StatusWithMatchExpression( ErrorCodes::BadValue, "$not cannot be empty" ); std::auto_ptr<AndMatchExpression> theAnd( new AndMatchExpression() ); Status s = _parseSub( name, notObject, theAnd.get() ); if ( !s.isOK() ) return StatusWithMatchExpression( s ); // TODO: this seems arbitrary? // tested in jstests/not2.js for ( unsigned i = 0; i < theAnd->numChildren(); i++ ) if ( theAnd->getChild(i)->matchType() == MatchExpression::REGEX ) return StatusWithMatchExpression( ErrorCodes::BadValue, "$not cannot have a regex" ); std::auto_ptr<NotMatchExpression> theNot( new NotMatchExpression() ); s = theNot->init( theAnd.release() ); if ( !s.isOK() ) return StatusWithMatchExpression( s ); return StatusWithMatchExpression( theNot.release() ); }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MLRLightMap::DrawLightMaps(MLRSorter *sorter) { Check_Object(stream); void *ptr, *end = stream->GetPointer(); Stuff::Matrix4D *currentMatrix=NULL; MLRClippingState currentClippingState; MLRState currentState, masterState; unsigned short stride; int i, pointerValue; Stuff::Point3D *coords = NULL; Stuff::RGBAColor color; Stuff::RGBAColor *colors = NULL; Vector2DScalar *texCoords = NULL; DWORD argb = 0xffffffff; Check_Object(vertexPool); GOSVertex* gos_vertices = vertexPool->GetActualVertexPool(); int numGOSVertices = 0; int msd; MemoryStreamData type; stream->Rewind(); ptr = stream->GetPointer(); while(ptr < end) { *stream >> msd; type = static_cast<MemoryStreamData>(msd); switch(msd) { case Matrix4D: *stream >> pointerValue; currentMatrix = reinterpret_cast<Stuff::Matrix4D*>(pointerValue); break; case ClippingState: currentClippingState.Load(stream); break; case MasterRenderState: masterState.Load(stream, Current_MLR_Version); break; case LightMapRenderState: { MLRState lightmapState; lightmapState.Load(stream, Current_MLR_Version); lightmapState.Combine(masterState, lightmapState); if(numGOSVertices && (lightmapState != currentState)) { vertexPool->Increase(numGOSVertices); SortData *sd = sorter->SetRawData ( gos_vertices, numGOSVertices, currentState, SortData::TriList ); if(currentState.GetDrawNowMode()==MLRState::DrawNowOnMode) { SortData::DrawFunc drawFunc = sd->Draw[sd->type]; (sd->*drawFunc)(); } else { sorter->AddSortRawData(sd); } gos_vertices = vertexPool->GetActualVertexPool(); numGOSVertices = 0; } currentState = lightmapState; } break; case Polygon: { *stream >> stride; Verify(stride<=Limits::Max_Number_Vertices_Per_Polygon); *stream >> color; argb = GOSCopyColor(&color); coords = (Stuff::Point3D *)stream->GetPointer(); stream->AdvancePointer(stride*sizeof(Stuff::Point3D)); texCoords = (Vector2DScalar *)stream->GetPointer(); stream->AdvancePointer(stride*sizeof(Vector2DScalar)); MLRClippingState theAnd(0x3f), theOr(0); MLRClippingState *cs = clippingStates->GetData(); Vector4D *v4d = transformedCoords->GetData(); for(i=0;i<stride;i++,v4d++,cs++) { v4d->Multiply(coords[i], *currentMatrix); if(currentClippingState!=0) { cs->Clip4dVertex(v4d); theAnd &= *cs; theOr |= *cs; } #if defined(_ARMOR) else { Verify((*transformedCoords)[i].x >= 0.0f && (*transformedCoords)[i].x <= (*transformedCoords)[i].w ); Verify((*transformedCoords)[i].y >= 0.0f && (*transformedCoords)[i].y <= (*transformedCoords)[i].w ); Verify((*transformedCoords)[i].z >= 0.0f && (*transformedCoords)[i].z <= (*transformedCoords)[i].w ); } #endif } if(theOr == 0) { for(i=1;i<stride-1;i++) { Verify((vertexPool->GetLast() + 3 + numGOSVertices) < vertexPool->GetLength()); GOSCopyTriangleData( &gos_vertices[numGOSVertices], transformedCoords->GetData(), texCoords, 0, i + 1, i ); gos_vertices[numGOSVertices].argb = argb; gos_vertices[numGOSVertices+1].argb = argb; gos_vertices[numGOSVertices+2].argb = argb; numGOSVertices+=3; } } else { if(theAnd != 0) { break; } else { int k, k0, k1, l, mask, ct = 0; Scalar a = 0.0f; int numberVerticesPerPolygon = 0; // //--------------------------------------------------------------- // Handle the case of a single clipping plane by stepping through // the vertices and finding the edge it originates //--------------------------------------------------------------- // bool firstIsIn; MLRClippingState theTest; if (theOr.GetNumberOfSetBits() == 1) { #ifdef LAB_ONLY Set_Statistic(PolysClippedButOnePlane, PolysClippedButOnePlane+1); #endif for(k=0;k<stride;k++) { int clipped_index = numberVerticesPerPolygon; k0 = k; k1 = (k+1) < stride ? k+1 : 0; // //---------------------------------------------------- // If this vertex is inside the viewing space, copy it // directly to the clipping buffer //---------------------------------------------------- // theTest = (*clippingStates)[k0]; if(theTest == 0) { firstIsIn = true; (*clipExtraCoords)[clipped_index] = (*transformedCoords)[k0]; Verify((*clipExtraCoords)[clipped_index].x >= 0.0f && (*clipExtraCoords)[clipped_index].x <= (*clipExtraCoords)[clipped_index].w ); Verify((*clipExtraCoords)[clipped_index].y >= 0.0f && (*clipExtraCoords)[clipped_index].y <= (*clipExtraCoords)[clipped_index].w ); Verify((*clipExtraCoords)[clipped_index].z >= 0.0f && (*clipExtraCoords)[clipped_index].z <= (*clipExtraCoords)[clipped_index].w ); (*clipExtraTexCoords)[clipped_index] = texCoords[k0]; numberVerticesPerPolygon++; clipped_index++; // //------------------------------------------------------- // We don't need to clip this edge if the next vertex is // also in the viewing space, so just move on to the next // vertex //------------------------------------------------------- // if((*clippingStates)[k1] == 0) { continue; } } // //--------------------------------------------------------- // This vertex is outside the viewing space, so if the next // vertex is also outside the viewing space, no clipping is // needed and we throw this vertex away. Since only one // clipping plane is involved, it must be in the same space // as the first vertex //--------------------------------------------------------- // else { firstIsIn = false; if((*clippingStates)[k1] != 0) { Verify((*clippingStates)[k1] == (*clippingStates)[k0]); continue; } } // //-------------------------------------------------- // We now find the distance along the edge where the // clipping plane will intersect //-------------------------------------------------- // mask = 1; theTest |= (*clippingStates)[k1]; // //----------------------------------------------------- // Find the boundary conditions that match our clipping // plane //----------------------------------------------------- // for (l=0; l<MLRClippingState::NextBit; l++) { if(theTest.IsClipped(mask)) { // GetDoubleBC(l, bc0, bc1, transformedCoords[k0], transformedCoords[k1]); // //------------------------------------------- // Find the clipping interval from bc0 to bc1 //------------------------------------------- // if(firstIsIn==true) { a = GetLerpFactor(l, (*transformedCoords)[k0], (*transformedCoords)[k1]); } else { a = GetLerpFactor(l, (*transformedCoords)[k1], (*transformedCoords)[k0]); } Verify(a >= 0.0f && a <= 1.0f); ct = l; break; } mask <<= 1; } // //------------------------------ // Lerp the homogeneous position //------------------------------ // if(firstIsIn==true) { (*clipExtraCoords)[clipped_index].Lerp( (*transformedCoords)[k0], (*transformedCoords)[k1], a ); DoClipTrick((*clipExtraCoords)[clipped_index], ct); Verify((*clipExtraCoords)[clipped_index].x >= 0.0f && (*clipExtraCoords)[clipped_index].x <= (*clipExtraCoords)[clipped_index].w ); Verify((*clipExtraCoords)[clipped_index].y >= 0.0f && (*clipExtraCoords)[clipped_index].y <= (*clipExtraCoords)[clipped_index].w ); Verify((*clipExtraCoords)[clipped_index].z >= 0.0f && (*clipExtraCoords)[clipped_index].z <= (*clipExtraCoords)[clipped_index].w ); // //----------------------------------------------------- // If there are texture uv's, we need to lerp them in a // perspective correct manner //----------------------------------------------------- // (*clipExtraTexCoords)[clipped_index].Lerp ( texCoords[k0], texCoords[k1], a ); } else { (*clipExtraCoords)[clipped_index].Lerp( (*transformedCoords)[k1], (*transformedCoords)[k0], a ); DoClipTrick((*clipExtraCoords)[clipped_index], ct); Verify((*clipExtraCoords)[clipped_index].x >= 0.0f && (*clipExtraCoords)[clipped_index].x <= (*clipExtraCoords)[clipped_index].w ); Verify((*clipExtraCoords)[clipped_index].y >= 0.0f && (*clipExtraCoords)[clipped_index].y <= (*clipExtraCoords)[clipped_index].w ); Verify((*clipExtraCoords)[clipped_index].z >= 0.0f && (*clipExtraCoords)[clipped_index].z <= (*clipExtraCoords)[clipped_index].w ); // //----------------------------------------------------- // If there are texture uv's, we need to lerp them in a // perspective correct manner //----------------------------------------------------- // (*clipExtraTexCoords)[clipped_index].Lerp ( texCoords[k1], texCoords[k0], a ); } // //-------------------------------- // Bump the polygon's vertex count //-------------------------------- // numberVerticesPerPolygon++; } } // //--------------------------------------------------------------- // We have to handle multiple planes. We do this by creating two // buffers and we switch between them as we clip plane by plane //--------------------------------------------------------------- // else { #ifdef LAB_ONLY Set_Statistic(PolysClippedButGOnePlane, PolysClippedButGOnePlane+1); #endif ClipData2 srcPolygon, dstPolygon; int dstBuffer = 1; srcPolygon.coords = clipBuffer[dstBuffer].coords.GetData(); srcPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData(); srcPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.GetData(); // //---------------------------------------------------------- // unravel and copy the original data into the source buffer //---------------------------------------------------------- // for(k=0;k<stride;k++) { srcPolygon.coords[k] = (*transformedCoords)[k]; srcPolygon.texCoords[k] = texCoords[k]; srcPolygon.clipPerVertex[k] = (*clippingStates)[k]; } srcPolygon.length = stride; // //-------------------------------- // Point to the destination buffer //-------------------------------- // dstBuffer = 0; dstPolygon.coords = clipBuffer[dstBuffer].coords.GetData(); dstPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData(); dstPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.GetData(); dstPolygon.length = 0; // //----------------------------------------------------------- // Spin through each plane that clipped the primitive and use // it to actually clip the primitive //----------------------------------------------------------- // mask = 1; MLRClippingState theNewOr(0); int loop = 4; do { for(l=0; l<MLRClippingState::NextBit; l++) { if(theOr.IsClipped(mask)) { // //----------------------------------- // Clip each vertex against the plane //----------------------------------- // for(k=0;k<srcPolygon.length;k++) { k1 = (k+1) < srcPolygon.length ? k+1 : 0; theTest = srcPolygon.clipPerVertex[k]; // //---------------------------------------------------- // If this vertex is inside the viewing space, copy it // directly to the clipping buffer //---------------------------------------------------- // if(theTest.IsClipped(mask) == 0) { firstIsIn = true; dstPolygon.coords[dstPolygon.length] = srcPolygon.coords[k]; dstPolygon.clipPerVertex[dstPolygon.length] = srcPolygon.clipPerVertex[k]; dstPolygon.texCoords[dstPolygon.length] = srcPolygon.texCoords[k]; dstPolygon.length++; // //------------------------------------------------------- // We don't need to clip this edge if the next vertex is // also in the viewing space, so just move on to the next // vertex //------------------------------------------------------- // if(srcPolygon.clipPerVertex[k1].IsClipped(mask) == 0) { continue; } } // //--------------------------------------------------------- // This vertex is outside the viewing space, so if the next // vertex is also outside the viewing space, no clipping is // needed and we throw this vertex away. Since only one // clipping plane is involved, it must be in the same space // as the first vertex //--------------------------------------------------------- // else { firstIsIn = false; if(srcPolygon.clipPerVertex[k1].IsClipped(mask) != 0) { Verify( srcPolygon.clipPerVertex[k1].IsClipped(mask) == srcPolygon.clipPerVertex[k].IsClipped(mask) ); continue; } } // //------------------------------------------- // Find the clipping interval from bc0 to bc1 //------------------------------------------- // if(firstIsIn == true) { a = GetLerpFactor (l, srcPolygon.coords[k], srcPolygon.coords[k1]); Verify(a >= 0.0f && a <= 1.0f); // //------------------------------ // Lerp the homogeneous position //------------------------------ // dstPolygon.coords[dstPolygon.length].Lerp( srcPolygon.coords[k], srcPolygon.coords[k1], a ); DoClipTrick(dstPolygon.coords[dstPolygon.length], l); // //----------------------------------------------------- // If there are texture uv's, we need to lerp them in a // perspective correct manner //----------------------------------------------------- // dstPolygon.texCoords[dstPolygon.length].Lerp ( srcPolygon.texCoords[k], srcPolygon.texCoords[k1], a ); } else { a = GetLerpFactor (l, srcPolygon.coords[k1], srcPolygon.coords[k]); Verify(a >= 0.0f && a <= 1.0f); // //------------------------------ // Lerp the homogeneous position //------------------------------ // dstPolygon.coords[dstPolygon.length].Lerp( srcPolygon.coords[k1], srcPolygon.coords[k], a ); DoClipTrick(dstPolygon.coords[dstPolygon.length], l); // //----------------------------------------------------- // If there are texture uv's, we need to lerp them in a // perspective correct manner //----------------------------------------------------- // dstPolygon.texCoords[dstPolygon.length].Lerp ( srcPolygon.texCoords[k1], srcPolygon.texCoords[k], a ); } // //------------------------------------- // We have to generate a new clip state //------------------------------------- // dstPolygon.clipPerVertex[dstPolygon.length].Clip4dVertex(&dstPolygon.coords[dstPolygon.length]); // //---------------------------------- // Bump the new polygon vertex count //---------------------------------- // dstPolygon.length++; } // //----------------------------------------------- // Swap source and destination buffer pointers in // preparation for the next plane test //----------------------------------------------- // srcPolygon.coords = clipBuffer[dstBuffer].coords.GetData(); srcPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData(); srcPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.GetData(); srcPolygon.length = dstPolygon.length; dstBuffer = !dstBuffer; dstPolygon.coords = clipBuffer[dstBuffer].coords.GetData(); dstPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData(); dstPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.GetData(); dstPolygon.length = 0; } mask = mask << 1; } theNewOr = 0; for(k=0;k<srcPolygon.length;k++) { theNewOr |= srcPolygon.clipPerVertex[k]; } theOr == theNewOr; loop++; } while (theNewOr != 0 && loop--); Verify(theNewOr == 0); // //-------------------------------------------------- // Move the most recent polygon into the clip buffer //-------------------------------------------------- // for(k=0;k<srcPolygon.length;k++) { (*clipExtraCoords)[k] = srcPolygon.coords[k]; Verify((*clipExtraCoords)[k].x >= 0.0f && (*clipExtraCoords)[k].x <= (*clipExtraCoords)[k].w ); Verify((*clipExtraCoords)[k].y >= 0.0f && (*clipExtraCoords)[k].y <= (*clipExtraCoords)[k].w ); Verify((*clipExtraCoords)[k].z >= 0.0f && (*clipExtraCoords)[k].z <= (*clipExtraCoords)[k].w ); (*clipExtraTexCoords)[k] = srcPolygon.texCoords[k]; } numberVerticesPerPolygon = srcPolygon.length; } // clip for(i=1;i<numberVerticesPerPolygon-1;i++) { Verify((vertexPool->GetLast() + 3 + numGOSVertices) < vertexPool->GetLength()); GOSCopyTriangleData( &gos_vertices[numGOSVertices], clipExtraCoords->GetData(), clipExtraTexCoords->GetData(), 0, i + 1, i ); gos_vertices[numGOSVertices].argb = argb; gos_vertices[numGOSVertices+1].argb = argb; gos_vertices[numGOSVertices+2].argb = argb; numGOSVertices+=3; } } } } break; case PolygonWithColor: { *stream >> stride; Verify(stride<=Limits::Max_Number_Vertices_Per_Polygon); coords = (Stuff::Point3D *)stream->GetPointer(); stream->AdvancePointer(stride*sizeof(Stuff::Point3D)); colors = (Stuff::RGBAColor *)stream->GetPointer(); stream->AdvancePointer(stride*sizeof(Stuff::RGBAColor)); texCoords = (Vector2DScalar *)stream->GetPointer(); stream->AdvancePointer(stride*sizeof(Vector2DScalar)); MLRClippingState theAnd(0x3f), theOr(0); MLRClippingState *cs = clippingStates->GetData(); Vector4D *v4d = transformedCoords->GetData(); for(i=0;i<stride;i++,v4d++,cs++) { v4d->Multiply(coords[i], *currentMatrix); if(currentClippingState!=0) { cs->Clip4dVertex(v4d); theAnd &= *cs; theOr |= *cs; } #if defined(_ARMOR) else { Verify((*transformedCoords)[i].x >= 0.0f && (*transformedCoords)[i].x <= (*transformedCoords)[i].w ); Verify((*transformedCoords)[i].y >= 0.0f && (*transformedCoords)[i].y <= (*transformedCoords)[i].w ); Verify((*transformedCoords)[i].z >= 0.0f && (*transformedCoords)[i].z <= (*transformedCoords)[i].w ); } #endif } if(theOr == 0) { for(i=1;i<stride-1;i++) { Verify((vertexPool->GetLast() + 3 + numGOSVertices) < vertexPool->GetLength()); GOSCopyTriangleData( &gos_vertices[numGOSVertices], transformedCoords->GetData(), colors, texCoords, 0, i + 1, i ); numGOSVertices+=3; } } else { if(theAnd != 0) { break; } else { int k, k0, k1, l, mask, ct = 0; Scalar a = 0.0f; int numberVerticesPerPolygon = 0; // //--------------------------------------------------------------- // Handle the case of a single clipping plane by stepping through // the vertices and finding the edge it originates //--------------------------------------------------------------- // bool firstIsIn; MLRClippingState theTest; if (theOr.GetNumberOfSetBits() == 1) { #ifdef LAB_ONLY Set_Statistic(PolysClippedButOnePlane, PolysClippedButOnePlane+1); #endif for(k=0;k<stride;k++) { int clipped_index = numberVerticesPerPolygon; k0 = k; k1 = (k+1) < stride ? k+1 : 0; // //---------------------------------------------------- // If this vertex is inside the viewing space, copy it // directly to the clipping buffer //---------------------------------------------------- // theTest = (*clippingStates)[k0]; if(theTest == 0) { firstIsIn = true; (*clipExtraCoords)[clipped_index] = (*transformedCoords)[k0]; Verify((*clipExtraCoords)[clipped_index].x >= 0.0f && (*clipExtraCoords)[clipped_index].x <= (*clipExtraCoords)[clipped_index].w ); Verify((*clipExtraCoords)[clipped_index].y >= 0.0f && (*clipExtraCoords)[clipped_index].y <= (*clipExtraCoords)[clipped_index].w ); Verify((*clipExtraCoords)[clipped_index].z >= 0.0f && (*clipExtraCoords)[clipped_index].z <= (*clipExtraCoords)[clipped_index].w ); (*clipExtraColors)[clipped_index] = colors[k0]; (*clipExtraTexCoords)[clipped_index] = texCoords[k0]; numberVerticesPerPolygon++; clipped_index++; // //------------------------------------------------------- // We don't need to clip this edge if the next vertex is // also in the viewing space, so just move on to the next // vertex //------------------------------------------------------- // if((*clippingStates)[k1] == 0) { continue; } } // //--------------------------------------------------------- // This vertex is outside the viewing space, so if the next // vertex is also outside the viewing space, no clipping is // needed and we throw this vertex away. Since only one // clipping plane is involved, it must be in the same space // as the first vertex //--------------------------------------------------------- // else { firstIsIn = false; if((*clippingStates)[k1] != 0) { Verify((*clippingStates)[k1] == (*clippingStates)[k0]); continue; } } // //-------------------------------------------------- // We now find the distance along the edge where the // clipping plane will intersect //-------------------------------------------------- //) mask = 1; theTest |= (*clippingStates)[k1]; // //----------------------------------------------------- // Find the boundary conditions that match our clipping // plane //----------------------------------------------------- // for (l=0; l<MLRClippingState::NextBit; l++) { if(theTest.IsClipped(mask)) { // GetDoubleBC(l, bc0, bc1, transformedCoords[k0], transformedCoords[k1]); // //------------------------------------------- // Find the clipping interval from bc0 to bc1 //------------------------------------------- // if(firstIsIn==true) { a = GetLerpFactor(l, (*transformedCoords)[k0], (*transformedCoords)[k1]); } else { a = GetLerpFactor(l, (*transformedCoords)[k1], (*transformedCoords)[k0]); } Verify(a >= 0.0f && a <= 1.0f); ct = l; break; } mask <<= 1; } // //------------------------------ // Lerp the homogeneous position //------------------------------ // if(firstIsIn==true) { (*clipExtraCoords)[clipped_index].Lerp( (*transformedCoords)[k0], (*transformedCoords)[k1], a ); DoClipTrick((*clipExtraCoords)[clipped_index], ct); Verify((*clipExtraCoords)[clipped_index].x >= 0.0f && (*clipExtraCoords)[clipped_index].x <= (*clipExtraCoords)[clipped_index].w ); Verify((*clipExtraCoords)[clipped_index].y >= 0.0f && (*clipExtraCoords)[clipped_index].y <= (*clipExtraCoords)[clipped_index].w ); Verify((*clipExtraCoords)[clipped_index].z >= 0.0f && (*clipExtraCoords)[clipped_index].z <= (*clipExtraCoords)[clipped_index].w ); // //----------------------------------------------------- // If there are texture uv's, we need to lerp them in a // perspective correct manner //----------------------------------------------------- // (*clipExtraTexCoords)[clipped_index].Lerp ( texCoords[k0], texCoords[k1], a ); (*clipExtraColors)[clipped_index].Lerp ( colors[k0], colors[k1], a ); } else { (*clipExtraCoords)[clipped_index].Lerp( (*transformedCoords)[k1], (*transformedCoords)[k0], a ); DoClipTrick((*clipExtraCoords)[clipped_index], ct); Verify((*clipExtraCoords)[clipped_index].x >= 0.0f && (*clipExtraCoords)[clipped_index].x <= (*clipExtraCoords)[clipped_index].w ); Verify((*clipExtraCoords)[clipped_index].y >= 0.0f && (*clipExtraCoords)[clipped_index].y <= (*clipExtraCoords)[clipped_index].w ); Verify((*clipExtraCoords)[clipped_index].z >= 0.0f && (*clipExtraCoords)[clipped_index].z <= (*clipExtraCoords)[clipped_index].w ); // //----------------------------------------------------- // If there are texture uv's, we need to lerp them in a // perspective correct manner //----------------------------------------------------- // (*clipExtraTexCoords)[clipped_index].Lerp ( texCoords[k1], texCoords[k0], a ); (*clipExtraColors)[clipped_index].Lerp ( colors[k1], colors[k0], a ); } // //-------------------------------- // Bump the polygon's vertex count //-------------------------------- // numberVerticesPerPolygon++; } } // //--------------------------------------------------------------- // We have to handle multiple planes. We do this by creating two // buffers and we switch between them as we clip plane by plane //--------------------------------------------------------------- // else { #ifdef LAB_ONLY Set_Statistic(PolysClippedButGOnePlane, PolysClippedButGOnePlane+1); #endif ClipData2 srcPolygon, dstPolygon; int dstBuffer = 1; srcPolygon.coords = clipBuffer[dstBuffer].coords.GetData(); srcPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData(); srcPolygon.colors = clipBuffer[dstBuffer].colors.GetData(); srcPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.GetData(); // //---------------------------------------------------------- // unravel and copy the original data into the source buffer //---------------------------------------------------------- // for(k=0;k<stride;k++) { srcPolygon.coords[k] = (*transformedCoords)[k]; srcPolygon.texCoords[k] = texCoords[k]; srcPolygon.colors[k] = colors[k]; srcPolygon.clipPerVertex[k] = (*clippingStates)[k]; } srcPolygon.length = stride; // //-------------------------------- // Point to the destination buffer //-------------------------------- // dstBuffer = 0; dstPolygon.coords = clipBuffer[dstBuffer].coords.GetData(); dstPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData(); dstPolygon.colors = clipBuffer[dstBuffer].colors.GetData(); dstPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.GetData(); dstPolygon.length = 0; // //----------------------------------------------------------- // Spin through each plane that clipped the primitive and use // it to actually clip the primitive //----------------------------------------------------------- // mask = 1; MLRClippingState theNewOr(0); int loop = 4; do { for(l=0; l<MLRClippingState::NextBit; l++) { if(theOr.IsClipped(mask)) { // //----------------------------------- // Clip each vertex against the plane //----------------------------------- // for(k=0;k<srcPolygon.length;k++) { k1 = (k+1) < srcPolygon.length ? k+1 : 0; theTest = srcPolygon.clipPerVertex[k]; // //---------------------------------------------------- // If this vertex is inside the viewing space, copy it // directly to the clipping buffer //---------------------------------------------------- // if(theTest.IsClipped(mask) == 0) { firstIsIn = true; dstPolygon.coords[dstPolygon.length] = srcPolygon.coords[k]; dstPolygon.clipPerVertex[dstPolygon.length] = srcPolygon.clipPerVertex[k]; dstPolygon.texCoords[dstPolygon.length] = srcPolygon.texCoords[k]; dstPolygon.colors[dstPolygon.length] = srcPolygon.colors[k]; dstPolygon.length++; // //------------------------------------------------------- // We don't need to clip this edge if the next vertex is // also in the viewing space, so just move on to the next // vertex //------------------------------------------------------- // if(srcPolygon.clipPerVertex[k1].IsClipped(mask) == 0) { continue; } } // //--------------------------------------------------------- // This vertex is outside the viewing space, so if the next // vertex is also outside the viewing space, no clipping is // needed and we throw this vertex away. Since only one // clipping plane is involved, it must be in the same space // as the first vertex //--------------------------------------------------------- // else { firstIsIn = false; if(srcPolygon.clipPerVertex[k1].IsClipped(mask) != 0) { Verify( srcPolygon.clipPerVertex[k1].IsClipped(mask) == srcPolygon.clipPerVertex[k].IsClipped(mask) ); continue; } } // //------------------------------------------- // Find the clipping interval from bc0 to bc1 //------------------------------------------- // if(firstIsIn == true) { a = GetLerpFactor (l, srcPolygon.coords[k], srcPolygon.coords[k1]); Verify(a >= 0.0f && a <= 1.0f); // //------------------------------ // Lerp the homogeneous position //------------------------------ // dstPolygon.coords[dstPolygon.length].Lerp( srcPolygon.coords[k], srcPolygon.coords[k1], a ); DoClipTrick(dstPolygon.coords[dstPolygon.length], l); // //----------------------------------------------------- // If there are texture uv's, we need to lerp them in a // perspective correct manner //----------------------------------------------------- // dstPolygon.texCoords[dstPolygon.length].Lerp ( srcPolygon.texCoords[k], srcPolygon.texCoords[k1], a ); dstPolygon.colors[dstPolygon.length].Lerp ( srcPolygon.colors[k], srcPolygon.colors[k1], a ); } else { a = GetLerpFactor (l, srcPolygon.coords[k1], srcPolygon.coords[k]); Verify(a >= 0.0f && a <= 1.0f); // //------------------------------ // Lerp the homogeneous position //------------------------------ // dstPolygon.coords[dstPolygon.length].Lerp( srcPolygon.coords[k1], srcPolygon.coords[k], a ); DoClipTrick(dstPolygon.coords[dstPolygon.length], l); // //----------------------------------------------------- // If there are texture uv's, we need to lerp them in a // perspective correct manner //----------------------------------------------------- // dstPolygon.texCoords[dstPolygon.length].Lerp ( srcPolygon.texCoords[k1], srcPolygon.texCoords[k], a ); dstPolygon.colors[dstPolygon.length].Lerp ( srcPolygon.colors[k1], srcPolygon.colors[k], a ); } // //------------------------------------- // We have to generate a new clip state //------------------------------------- // dstPolygon.clipPerVertex[dstPolygon.length].Clip4dVertex(&dstPolygon.coords[dstPolygon.length]); // //---------------------------------- // Bump the new polygon vertex count //---------------------------------- // dstPolygon.length++; } // //----------------------------------------------- // Swap source and destination buffer pointers in // preparation for the next plane test //----------------------------------------------- // srcPolygon.coords = clipBuffer[dstBuffer].coords.GetData(); srcPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData(); srcPolygon.colors = clipBuffer[dstBuffer].colors.GetData(); srcPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.GetData(); srcPolygon.length = dstPolygon.length; dstBuffer = !dstBuffer; dstPolygon.coords = clipBuffer[dstBuffer].coords.GetData(); dstPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData(); dstPolygon.colors = clipBuffer[dstBuffer].colors.GetData(); dstPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.GetData(); dstPolygon.length = 0; } mask = mask << 1; } theNewOr = 0; for(k=0;k<srcPolygon.length;k++) { theNewOr |= srcPolygon.clipPerVertex[k]; } theOr == theNewOr; loop++; } while (theNewOr != 0 && loop--); Verify(theNewOr == 0); // //-------------------------------------------------- // Move the most recent polygon into the clip buffer //-------------------------------------------------- // for(k=0;k<srcPolygon.length;k++) { (*clipExtraCoords)[k] = srcPolygon.coords[k]; Verify((*clipExtraCoords)[k].x >= 0.0f && (*clipExtraCoords)[k].x <= (*clipExtraCoords)[k].w ); Verify((*clipExtraCoords)[k].y >= 0.0f && (*clipExtraCoords)[k].y <= (*clipExtraCoords)[k].w ); Verify((*clipExtraCoords)[k].z >= 0.0f && (*clipExtraCoords)[k].z <= (*clipExtraCoords)[k].w ); (*clipExtraTexCoords)[k] = srcPolygon.texCoords[k]; (*clipExtraColors)[k] = srcPolygon.colors[k]; } numberVerticesPerPolygon = srcPolygon.length; } // clip for(i=1;i<numberVerticesPerPolygon-1;i++) { Verify((vertexPool->GetLast() + 3 + numGOSVertices) < vertexPool->GetLength()); GOSCopyTriangleData( &gos_vertices[numGOSVertices], clipExtraCoords->GetData(), clipExtraColors->GetData(), clipExtraTexCoords->GetData(), 0, i + 1, i ); numGOSVertices+=3; } } } } break; } ptr = stream->GetPointer(); } if(numGOSVertices) { vertexPool->Increase(numGOSVertices); SortData *sd = sorter->SetRawData ( gos_vertices, numGOSVertices, currentState, SortData::TriList ); if(currentState.GetDrawNowMode()==MLRState::DrawNowOnMode) { SortData::DrawFunc drawFunc = sd->Draw[sd->type]; (sd->*drawFunc)(); } else { sorter->AddSortRawData(sd); } } }