//------------------------------------------------------------------------------ // bool gosFX::ShapeCloud::AnimateParticle( unsigned index, const Stuff::LinearMatrix4D *world_to_new_local, Stuff::Time till ) { Check_Object(this); // //----------------------------------------- // Animate the parent then get our pointers //----------------------------------------- // if (!SpinningCloud::AnimateParticle(index, world_to_new_local, till)) return false; Set_Statistic(Shape_Count, Shape_Count+1); Specification *spec = GetSpecification(); Check_Object(spec); Particle *particle = GetParticle(index); Check_Object(particle); Stuff::Scalar seed = particle->m_seed; Stuff::Scalar age = particle->m_age; // //------------------ // Animate the color //------------------ // particle->m_color.red = spec->m_pRed.ComputeValue(age, seed); particle->m_color.green = spec->m_pGreen.ComputeValue(age, seed); particle->m_color.blue = spec->m_pBlue.ComputeValue(age, seed); particle->m_color.alpha = spec->m_pAlpha.ComputeValue(age, seed); return true; }
UnitQuaternion& UnitQuaternion::FastLerp( const UnitQuaternion& p, const UnitQuaternion& q, Scalar t ) { if (!UseFastLerp) return Lerp(p,q,t); Start_Timer(SlerpTime); Set_Statistic(SlerpCount, SlerpCount+1); Verify(quaternionFastLerpTableBuilt); Scalar cosom,sclp,sclq; cosom = p.x*q.x + p.y*q.y + p.z*q.z + p.w*q.w; if ( (1.0f + cosom) > 0.01f) { // usual case if ( (1.0f - cosom) > 0.00001f ) { //usual case //table_entry = (int)Scaled_Float_To_Bits(cosom, MinCosom, MaxCosom, 10); float tabled_float = cosom - MinCosom; int cos_table_entry = Truncate_Float_To_Word(((tabled_float*CosomRangeOverOne) * CosBiggestNumber)); Verify(cos_table_entry >= 0); Verify(cos_table_entry <= QuaternionLerpTableSize); #if 0 sclp = Sin((1.0f - t)*Omega_Table[cos_table_entry]) * SinomOverOne_Table[cos_table_entry]; sclq = Sin(t*Omega_Table[cos_table_entry]) * SinomOverOne_Table[cos_table_entry]; #else float difference, percent, lerped_sin; tabled_float = ((1.0f - t)*Omega_Table[cos_table_entry]) - MinSin; int sclp_table_entry = Truncate_Float_To_Word(((tabled_float*SinRangeOverOne) * SinBiggestNumber)); if (!(sclp_table_entry < SinTableSize)) { Max_Clamp(sclp_table_entry, SinTableSize-1); } Verify(sclp_table_entry >= 0 && sclp_table_entry < SinTableSize); difference = tabled_float - (SinIncrement * sclp_table_entry); percent = difference / SinIncrement; int lerp_to_entry = sclp_table_entry + 1; Max_Clamp(lerp_to_entry, SinTableSize-1); lerped_sin = Stuff::Lerp(Sin_Table[sclp_table_entry], Sin_Table[lerp_to_entry], percent); sclp = lerped_sin * SinomOverOne_Table[cos_table_entry]; tabled_float = (t*Omega_Table[cos_table_entry]) - MinSin; int sclq_table_entry = Truncate_Float_To_Word(((tabled_float*SinRangeOverOne) * SinBiggestNumber)); Verify(sclq_table_entry >= 0 && sclq_table_entry < SinTableSize); difference = tabled_float - (SinIncrement * sclq_table_entry); percent = difference / SinIncrement; lerp_to_entry = sclq_table_entry + 1; Max_Clamp(lerp_to_entry, SinTableSize-1); lerped_sin = Stuff::Lerp(Sin_Table[sclq_table_entry], Sin_Table[lerp_to_entry], percent); sclq = lerped_sin * SinomOverOne_Table[cos_table_entry]; #endif } else { // ends very close -- just lerp sclp = 1.0f - t; sclq = t; } x = sclp*p.x + sclq*q.x; y = sclp*p.y + sclq*q.y; z = sclp*p.z + sclq*q.z; w = sclp*p.w + sclq*q.w; } else { //SPEW(("jerryeds","SPECIAL CASE")); /* p and q nearly opposite on sphere-- this is a 360 degree rotation, but the axis of rotation is undefined, so slerp really is undefined too. So this apparently picks an arbitrary plane of rotation. However, I think this code is incorrect. */ //really we want the shortest distance. They are almost on top of each other. UnitQuaternion r; r.Subtract(q, p); Vector3D scaled_rotation; scaled_rotation = r; scaled_rotation *= t; UnitQuaternion scaled_quat; scaled_quat = scaled_rotation; Multiply(scaled_quat, p); Normalize(); } Stop_Timer(SlerpTime); return *this; }
UnitQuaternion &UnitQuaternion::Lerp(const UnitQuaternion& p, const UnitQuaternion& q, Scalar t) { Start_Timer(SlerpTime); Set_Statistic(SlerpCount, SlerpCount+1); Scalar omega,cosom,sinom,sclp,sclq; //UnitQuaternion qt; //UnitQuaternion q = q_temp; //UnitQuaternion p = p_temp; cosom = p.x*q.x + p.y*q.y + p.z*q.z + p.w*q.w; if ( (1.0f + cosom) > 0.01f) { // usual case if ( (1.0f - cosom) > 0.00001f ) { //usual case omega = Arccos(cosom); sinom = Sin(omega); //SPEW(("jerryeds","omega:%f sinom:%f", omega, sinom)); sclp = Sin((1.0f - t)*omega) / sinom; sclq = Sin(t*omega) / sinom; //SPEW(("jerryeds", "* %f %f", sclp, sclq)); } else { // ends very close -- just lerp sclp = 1.0f - t; sclq = t; //SPEW(("jerryeds", "# %f %f", sclp, sclq)); } x = sclp*p.x + sclq*q.x; y = sclp*p.y + sclq*q.y; z = sclp*p.z + sclq*q.z; w = sclp*p.w + sclq*q.w; //SPEW(("jerryeds", "r:<%f,%f,%f,%f>",x,y,z,w)); } else { //SPEW(("jerryeds","SPECIAL CASE")); /* p and q nearly opposite on sphere-- this is a 360 degree rotation, but the axis of rotation is undefined, so slerp really is undefined too. So this apparently picks an arbitrary plane of rotation. However, I think this code is incorrect. */ //really we want the shortest distance. They are almost on top of each other. UnitQuaternion r; r.Subtract(q, p); Vector3D scaled_rotation; scaled_rotation = r; scaled_rotation *= t; UnitQuaternion scaled_quat; scaled_quat = scaled_rotation; Multiply(scaled_quat, p); } Stop_Timer(SlerpTime); return *this; }
//===========================================================================// // Copyright (C) Microsoft Corporation. All rights reserved. // //===========================================================================// //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void CLASSNAME::Lighting ( MLRLight* const* lights, int nrLights ) { Check_Object(this); // //---------------------------------------------------------------------- // If no lights or normals are specified, use the original vertex colors //---------------------------------------------------------------------- // actualColors = &colors; int state_mask = GetCurrentState().GetLightingMode(); if (nrLights == 0 || normals.GetLength() == 0 || state_mask == MLRState::LightingOffMode) return; Check_Pointer(lights); // //------------------------------- // See if we need vertex lighting //------------------------------- // if (state_mask & MLRState::VertexLightingMode) { Verify(colors.GetLength() == litColors.GetLength()); Verify(normals.GetLength() == colors.GetLength()); Verify(coords.GetLength() == colors.GetLength()); int i, k, len = colors.GetLength(); MLRVertexData vertexData; #if COLOR_AS_DWORD TO_DO; #else RGBAColor *color = &colors[0]; #endif // //-------------------------------- // Now light the array of vertices //-------------------------------- // vertexData.point = &coords[0]; vertexData.color = &litColors[0]; vertexData.normal = &normals[0]; for(k=0;k<len;k++) { if(visibleIndexedVertices[k] != 0) { vertexData.color->red = 0.0f; vertexData.color->green = 0.0f; vertexData.color->blue = 0.0f; vertexData.color->alpha = color->alpha; for (i=0;i<nrLights;i++) { MLRLight *light = lights[i]; Check_Object(light); int mask = state_mask & light->GetLightMask(); if (!mask) continue; if (mask&MLRState::VertexLightingMode) { if ( GetCurrentState().GetBackFaceMode() != MLRState::BackFaceOffMode || light->GetLightType() == MLRLight::AmbientLight ) { light->LightVertex(vertexData); Set_Statistic(LitVertices, LitVertices+1); } } } } vertexData.point++; vertexData.color++; vertexData.normal++; color++; } actualColors = &litColors; } }
//------------------------------------------------------------------------------ // bool gosFX::CardCloud::AnimateParticle( uint32_t index, const Stuff::LinearMatrix4D* world_to_new_local, Stuff::Time till) { // Check_Object(this); // //----------------------------------------- // Animate the parent then get our pointers //----------------------------------------- // if (!SpinningCloud::AnimateParticle(index, world_to_new_local, till)) return false; Set_Statistic(Card_Count, Card_Count + 1); Specification* spec = GetSpecification(); Check_Object(spec); Particle* particle = GetParticle(index); Check_Object(particle); float seed = particle->m_seed; float age = particle->m_age; // //------------------ // Animate the color //------------------ // Check_Pointer(m_P_color); m_P_color[index].red = spec->m_pRed.ComputeValue(age, seed); m_P_color[index].green = spec->m_pGreen.ComputeValue(age, seed); m_P_color[index].blue = spec->m_pBlue.ComputeValue(age, seed); m_P_color[index].alpha = spec->m_pAlpha.ComputeValue(age, seed); // //---------------- // Animate the uvs //---------------- // float u = spec->m_UOffset.ComputeValue(age, seed); float v = spec->m_VOffset.ComputeValue(age, seed); float u2 = spec->m_USize.ComputeValue(age, seed); float v2 = spec->m_VSize.ComputeValue(age, seed); // //-------------------------------------------------------------- // If we are animated, figure out the row/column to be displayed //-------------------------------------------------------------- // if (spec->m_animated) { uint8_t columns = Stuff::Truncate_Float_To_Byte(spec->m_pIndex.ComputeValue(age, seed)); uint8_t rows = static_cast<uint8_t>(columns / spec->m_width); columns = static_cast<uint8_t>(columns - rows * spec->m_width); // //--------------------------- // Now compute the end points //--------------------------- // u += u2 * columns; v += v2 * rows; } u2 += u; v2 += v; index *= 4; m_P_uvs[index].x = u; m_P_uvs[index].y = v2; m_P_uvs[++index].x = u2; m_P_uvs[index].y = v2; m_P_uvs[++index].x = u2; m_P_uvs[index].y = v; m_P_uvs[++index].x = u; m_P_uvs[index].y = v; return true; }
//------------------------------------------------------------------------------ // bool gosFX::PointCloud::AnimateParticle( uint32_t index, const Stuff::LinearMatrix4D* world_to_new_local, Stuff::Time till ) { Check_Object(this); // //----------------------------------------------------------------------- // If this cloud is unparented, we need to transform the point from local // space into world space and set the internal position/velocity pointers // to these temporary values //----------------------------------------------------------------------- // Particle* particle = GetParticle(index); Check_Object(particle); float age = particle->m_age; if(age >= 1.0f) return false; Set_Statistic(Point_Count, Point_Count + 1); Stuff::Vector3D* velocity = &particle->m_localLinearVelocity; Stuff::Point3D* translation = &m_P_localTranslation[index]; int32_t sim_mode = GetSimulationMode(); if(sim_mode == DynamicWorldSpaceSimulationMode) { Check_Object(translation); Check_Object(velocity); particle->m_worldLinearVelocity.Multiply(*velocity, m_localToWorld); particle->m_worldTranslation.Multiply(*translation, m_localToWorld); translation = &particle->m_worldTranslation; velocity = &particle->m_worldLinearVelocity; } Check_Object(translation); Check_Object(velocity); // //------------------------------------------------------------------ // First, calculate the drag on the particle. Drag can never assist // velocity //------------------------------------------------------------------ // float seed = particle->m_seed; Specification* spec = GetSpecification(); Check_Object(spec); Stuff::Vector3D ether; ether.x = spec->m_pEtherVelocityX.ComputeValue(age, seed); ether.y = spec->m_pEtherVelocityY.ComputeValue(age, seed); ether.z = spec->m_pEtherVelocityZ.ComputeValue(age, seed); Stuff::Vector3D accel(Stuff::Vector3D::Identity); // //------------------------------------------------------------------- // Deal with pseudo-world simulation. In this mode, we interpret the // forces as if they are already in worldspace, and we transform them // back to local space //------------------------------------------------------------------- // float drag = -spec->m_pDrag.ComputeValue(age, seed); Max_Clamp(drag, 0.0f); if(sim_mode == StaticWorldSpaceSimulationMode) { Stuff::LinearMatrix4D world_to_effect; world_to_effect.Invert(m_localToWorld); Stuff::Vector3D local_ether; local_ether.MultiplyByInverse(ether, world_to_effect); Stuff::Vector3D rel_vel; rel_vel.Subtract(*velocity, local_ether); accel.Multiply(rel_vel, drag); // //----------------------------------------- // Now, add in acceleration of the particle //----------------------------------------- // Stuff::Vector3D world_accel; world_accel.x = spec->m_pAccelerationX.ComputeValue(age, seed); world_accel.y = spec->m_pAccelerationY.ComputeValue(age, seed); world_accel.z = spec->m_pAccelerationZ.ComputeValue(age, seed); Stuff::Vector3D local_accel; local_accel.Multiply(world_accel, world_to_effect); accel += local_accel; } // //---------------------------------------------------------------------- // Otherwise, just add the forces in the same space the particles are in //---------------------------------------------------------------------- // else { Stuff::Vector3D rel_vel; rel_vel.Subtract(*velocity, ether); accel.Multiply(rel_vel, drag); // //----------------------------------------- // Now, add in acceleration of the particle //----------------------------------------- // accel.x += spec->m_pAccelerationX.ComputeValue(age, seed); accel.y += spec->m_pAccelerationY.ComputeValue(age, seed); accel.z += spec->m_pAccelerationZ.ComputeValue(age, seed); } // //------------------------------------------------- // Compute the particle's new velocity and position //------------------------------------------------- // float time_slice = static_cast<float>(till - m_lastRan); velocity->AddScaled(*velocity, accel, time_slice); translation->AddScaled(*translation, *velocity, time_slice); // //--------------------------------------------------------------------- // If we are unparented, we need to transform the velocity and position // data back into the NEW local space //--------------------------------------------------------------------- // if(sim_mode == DynamicWorldSpaceSimulationMode) { Check_Object(world_to_new_local); particle->m_localLinearVelocity.Multiply( particle->m_worldLinearVelocity, *world_to_new_local ); m_P_localTranslation[index].Multiply( particle->m_worldTranslation, *world_to_new_local ); } // //------------------ // Animate the color //------------------ // Check_Pointer(m_P_color); m_P_color[index].red = spec->m_pRed.ComputeValue(age, seed); m_P_color[index].green = spec->m_pGreen.ComputeValue(age, seed); m_P_color[index].blue = spec->m_pBlue.ComputeValue(age, seed); m_P_color[index].alpha = spec->m_pAlpha.ComputeValue(age, seed); return true; }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int MLRIndexedTriangleCloud::Clip(MLRClippingState clippingFlags, GOSVertexPool *vt) { int myNumberUsedClipVertex, myNumberUsedClipIndex, myNumberUsedClipLength; myNumberUsedClipVertex = 0; myNumberUsedClipIndex = 0; myNumberUsedClipLength = 0; Verify(*usedNrOfTriangles > 0); // //------------------------ // Handle the indexed case //------------------------ // memset(visibleIndexedVertices->GetData(), 0, *usedNrOfPoints); // //----------------------------------------------------------------- // Step through each polygon, making sure that we don't try to clip // backfaced polygons //----------------------------------------------------------------- // int i, j, k, k0, k1, *cs = (int *)clipPerVertex->GetData(); unsigned short l; int index0, index1, index2, ret = 0; int mask; Scalar a = 0.0f; for(i=0,j=0;i<*usedNrOfTriangles;j+=3,++i) { index0 = index[j]; index1 = index[j+1]; index2 = index[j+2]; // //--------------------------------------------------------------- // Test each vertex of the polygon against the allowed clipping // planes, and accumulate status for which planes always clip and // which planes clipped at least once //--------------------------------------------------------------- // theAnd = cs[index0]; theAnd &= (cs[index1] & cs[index2]); theOr |= (cs[index1] | cs[index2]); theAnd = theOr = 0; //ASSUME NO CLIPPING NEEDED FOR MC2. Its just not done here! // //------------------------------------------------------------------- // If any bit is set for all vertices, then the polygon is completely // outside the viewing space and we don't have to draw it. On the // other hand, if no bits at all were ever set, we can do a trivial // accept of the polygon //------------------------------------------------------------------- // if (theAnd != 0) { testList[i] = 0; #ifdef LAB_ONLY Set_Statistic(PolysClippedButOutside, PolysClippedButOutside+1); #endif } else if (theOr == 0) { testList[i] = 1; ret++; (*visibleIndexedVertices)[index0] = 1; (*visibleIndexedVertices)[index1] = 1; (*visibleIndexedVertices)[index2] = 1; #ifdef LAB_ONLY Set_Statistic(PolysClippedButInside, PolysClippedButInside+1); #endif } // //----------------------------------------------------------------- // It is not a trivial case, so we must now do real clipping on the // polygon //----------------------------------------------------------------- // else { unsigned short numberVerticesPerPolygon = 0; // //--------------------------------------------------------------- // Handle the case of a single clipping plane by stepping through // the vertices and finding the edge it originates //--------------------------------------------------------------- // bool firstIsIn; if (theOr.GetNumberOfSetBits() == 1) { #ifdef LAB_ONLY Set_Statistic(PolysClippedButOnePlane, PolysClippedButOnePlane+1); #endif for(k=j;k<j+3;k++) { k0 = index[k]; k1 = index[(k+1) < j+3 ? k+1 : j]; // //---------------------------------------------------- // If this vertex is inside the viewing space, copy it // directly to the clipping buffer //---------------------------------------------------- // int clipped_index = myNumberUsedClipVertex + numberVerticesPerPolygon; theTest = cs[k0]; if(theTest == 0) { firstIsIn = true; (*clipExtraCoords)[clipped_index] = (*transformedCoords)[k0]; (*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(cs[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(cs[k1] != 0) { Verify(cs[k1] == cs[k0]); continue; } } // //-------------------------------------------------- // We now find the distance along the edge where the // clipping plane will intersect //-------------------------------------------------- // int ct = 0; mask = 1; theTest |= cs[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); // //---------------------------------------------------------- // If there are colors, lerp them in screen space for now as // most cards do that anyway //---------------------------------------------------------- // #if COLOR_AS_DWORD (*clipExtraColors)[clipped_index] = Color_DWORD_Lerp ( colors[k0], colors[k1], a ); #else (*clipExtraColors)[clipped_index].Lerp( colors[k0], colors[k1], a ); #endif // //----------------------------------------------------- // 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); // //---------------------------------------------------------- // If there are colors, lerp them in screen space for now as // most cards do that anyway //---------------------------------------------------------- // #if COLOR_AS_DWORD (*clipExtraColors)[clipped_index] = Color_DWORD_Lerp ( colors[k1], colors[k0], a ); #else (*clipExtraColors)[clipped_index].Lerp( colors[k1], colors[k0], a ); #endif // //----------------------------------------------------- // 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++; } (*clipExtraLength)[myNumberUsedClipLength] = numberVerticesPerPolygon; #ifdef _ARMOR (*clipExtraLength)[myNumberUsedClipLength] &= ~0x8000; #endif } // //--------------------------------------------------------------- // 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.colors = clipBuffer[dstBuffer].colors.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=j,l=0;k<j+3;k++,l++) { int indexK = index[k]; srcPolygon.coords[l] = (*transformedCoords)[indexK]; srcPolygon.colors[l] = colors[indexK]; srcPolygon.texCoords[l] = texCoords[indexK]; srcPolygon.clipPerVertex[l] = (*clipPerVertex)[indexK]; } srcPolygon.length = l; // //-------------------------------- // Point to the destination buffer //-------------------------------- // dstBuffer = 0; dstPolygon.coords = clipBuffer[dstBuffer].coords.GetData(); dstPolygon.colors = clipBuffer[dstBuffer].colors.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; #if HUNT_CLIP_ERROR for(k=0;k<srcPolygon.length;k++) { DEBUG_STREAM << setiosflags( ios::scientific) << setprecision(20) << srcPolygon.coords[k].x << " " << srcPolygon.coords[k].y << " " << srcPolygon.coords[k].z << " " << srcPolygon.coords[k].w << '\n'; } #endif #if HUNT_CLIP_ERROR DEBUG_STREAM << "TheOriginalOR: " << hex << theOr.GetClippingState() << dec << '\n'; #endif do { for(l=0; l<MLRClippingState::NextBit; l++) { if(theOr.IsClipped(mask)) { // //----------------------------------- // Clip each vertex against the plane //----------------------------------- // #if HUNT_CLIP_ERROR DEBUG_STREAM << l << ": " << '\n'; #endif 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]; #if HUNT_CLIP_ERROR DEBUG_STREAM << k << " goes " << setiosflags( ios::scientific) << setprecision(20) << srcPolygon.coords[k].x << " " << srcPolygon.coords[k].y << " " << srcPolygon.coords[k].z << " " << srcPolygon.coords[k].w << '\n'; #endif dstPolygon.clipPerVertex[dstPolygon.length] = srcPolygon.clipPerVertex[k]; dstPolygon.colors[dstPolygon.length] = srcPolygon.colors[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 ); #if HUNT_CLIP_ERROR DEBUG_STREAM << "True " << a << " " << k << " " << k1 << " we get " << dstPolygon.length << '\n'; DEBUG_STREAM << setiosflags( ios::scientific) << setprecision(20) << dstPolygon.coords[dstPolygon.length].x << " " << dstPolygon.coords[dstPolygon.length].y << " " << dstPolygon.coords[dstPolygon.length].z << " " << dstPolygon.coords[dstPolygon.length].w << '\n'; #endif DoClipTrick(dstPolygon.coords[dstPolygon.length], l); // //---------------------------------------------------------- // If there are colors, lerp them in screen space for now as // most cards do that anyway //---------------------------------------------------------- // #if COLOR_AS_DWORD dstPolygon.colors[dstPolygon.length] = Color_DWORD_Lerp( srcPolygon.colors[k], srcPolygon.colors[k1], a ); #else dstPolygon.colors[dstPolygon.length].Lerp( srcPolygon.colors[k], srcPolygon.colors[k1], a ); #endif // //----------------------------------------------------- // 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 ); #if HUNT_CLIP_ERROR DEBUG_STREAM << "False " << a << " " << k << " " << k1 << " we get " << dstPolygon.length << '\n'; DEBUG_STREAM << setiosflags( ios::scientific) << setprecision(20) << dstPolygon.coords[dstPolygon.length].x << " " << dstPolygon.coords[dstPolygon.length].y << " " << dstPolygon.coords[dstPolygon.length].z << " " << dstPolygon.coords[dstPolygon.length].w << '\n'; #endif DoClipTrick(dstPolygon.coords[dstPolygon.length], l); // //---------------------------------------------------------- // If there are colors, lerp them in screen space for now as // most cards do that anyway //---------------------------------------------------------- // #if COLOR_AS_DWORD dstPolygon.colors[dstPolygon.length] = Color_DWORD_Lerp( srcPolygon.colors[k1], srcPolygon.colors[k], a ); #else dstPolygon.colors[dstPolygon.length].Lerp( srcPolygon.colors[k1], srcPolygon.colors[k], a ); #endif // //----------------------------------------------------- // 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.colors = clipBuffer[dstBuffer].colors.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.colors = clipBuffer[dstBuffer].colors.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]; } #if HUNT_CLIP_ERROR DEBUG_STREAM << "TheOR: " << hex << theNewOr.GetClippingState() << dec << '\n'; #endif theOr = theNewOr; } while (theNewOr != 0 && loop--); // //-------------------------------------------------- // could not clip this rare case, just ignore it //-------------------------------------------------- // if(theNewOr != 0) { testList[i] = 0; continue; } // //-------------------------------------------------- // Move the most recent polygon into the clip buffer //-------------------------------------------------- // #if HUNT_CLIP_ERROR DEBUG_STREAM << "Final: " << srcPolygon.length << '\n'; #endif for(k=0;k<srcPolygon.length;k++) { int clipped_index = myNumberUsedClipVertex + k; #if HUNT_CLIP_ERROR DEBUG_STREAM << setiosflags( ios::scientific) << setprecision(20) << srcPolygon.coords[k].x << " " << srcPolygon.coords[k].y << " " << srcPolygon.coords[k].z << " " << srcPolygon.coords[k].w << '\n'; #endif (*clipExtraCoords)[clipped_index] = srcPolygon.coords[k]; (*clipExtraColors)[clipped_index] = srcPolygon.colors[k]; (*clipExtraTexCoords)[clipped_index] = srcPolygon.texCoords[k]; } numberVerticesPerPolygon = srcPolygon.length; #if HUNT_CLIP_ERROR DEBUG_STREAM << "---" << '\n'; #endif (*clipExtraLength)[myNumberUsedClipLength] = numberVerticesPerPolygon; #ifdef _ARMOR (*clipExtraLength)[myNumberUsedClipLength] |= 0x8000; #endif } myNumberUsedClipVertex += numberVerticesPerPolygon; myNumberUsedClipLength++; ret++; // clip // dont draw the original testList[i] = 0; } } Check_Object(vt); gos_vertices = vt->GetActualVertexPool(); numGOSVertices = 0; gos_indices = vt->GetActualIndexPool(); numGOSIndices = 0; unsigned short strideIndex; for(j=0,strideIndex=0;j<*usedNrOfPoints;j++) { if((*visibleIndexedVertices)[j] == 0) { strideIndex++; } else { indexOffset[j] = static_cast<unsigned short>(j-strideIndex); GOSCopyData( &gos_vertices[numGOSVertices], transformedCoords->GetData(), colors, texCoords, j ); #ifdef LAB_ONLY if(gShowClippedPolys) { gos_vertices[numGOSVertices].argb = 0xff0000ff; gos_vertices[numGOSVertices].u = 0.0f; gos_vertices[numGOSVertices].v = 0.0f; } #endif numGOSVertices++; } } for(i=0,j=0;i<*usedNrOfTriangles;j+=3,++i) { if(testList[i] == 0) { continue; } Verify((vt->GetLastIndex() + 3 + numGOSIndices) < vt->GetLength()); Verify(indexOffset[index[j]] < numGOSVertices); gos_indices[numGOSIndices] = indexOffset[index[j]]; Verify(indexOffset[index[j+2]] < numGOSVertices); gos_indices[numGOSIndices+1] = indexOffset[index[j+2]]; Verify(indexOffset[index[j+1]] < numGOSVertices); gos_indices[numGOSIndices+2] = indexOffset[index[j+1]]; numGOSIndices += 3; } unsigned short stride; if(myNumberUsedClipLength > 0) { for(i=0,j=0;i<myNumberUsedClipLength;i++) { #ifdef _ARMOR stride = static_cast<unsigned short>((*clipExtraLength)[i] & 0x7fff); #else stride = static_cast<unsigned short>((*clipExtraLength)[i]); #endif for(k=1;k<stride-1;k++) { Verify((vt->GetLast() + 3 + numGOSVertices) < vt->GetLength()); Verify((vt->GetLastIndex() + 3 + numGOSIndices) < vt->GetLength()); GOSCopyTriangleData( &gos_vertices[numGOSVertices], clipExtraCoords->GetData(), clipExtraColors->GetData(), clipExtraTexCoords->GetData(), j, j+k+1, j+k ); #ifdef LAB_ONLY if(gShowClippedPolys) { if((*clipExtraLength)[i] & 0x8000) { gos_vertices[numGOSVertices].argb = 0xffff0000; gos_vertices[numGOSVertices].u = 0.0f; gos_vertices[numGOSVertices].v = 0.0f; gos_vertices[numGOSVertices+1].argb = 0xffff0000; gos_vertices[numGOSVertices+1].u = 0.0f; gos_vertices[numGOSVertices+1].v = 0.0f; gos_vertices[numGOSVertices+2].argb = 0xffff0000; gos_vertices[numGOSVertices+2].u = 0.0f; gos_vertices[numGOSVertices+2].v = 0.0f; } else { gos_vertices[numGOSVertices].argb = 0xffff9999; gos_vertices[numGOSVertices].u = 0.0f; gos_vertices[numGOSVertices].v = 0.0f; gos_vertices[numGOSVertices+1].argb = 0xffff9999; gos_vertices[numGOSVertices+1].u = 0.0f; gos_vertices[numGOSVertices+1].v = 0.0f; gos_vertices[numGOSVertices+2].argb = 0xffff9999; gos_vertices[numGOSVertices+2].u = 0.0f; gos_vertices[numGOSVertices+2].v = 0.0f; } } #endif Verify((vt->GetLastIndex() + 3 + numGOSIndices) < vt->GetLength()); Verify(numGOSIndices%3 == 0); gos_indices[numGOSIndices] = (unsigned short)numGOSVertices; gos_indices[numGOSIndices+1] = (unsigned short)(numGOSVertices + 1); gos_indices[numGOSIndices+2] = (unsigned short)(numGOSVertices + 2); numGOSVertices += 3; numGOSIndices += 3; } j += stride; } #if HUNT_CLIP_ERROR DEBUG_STREAM << "***" << endl << endl; #endif } vt->Increase(numGOSVertices); vt->IncreaseIndex(numGOSIndices); return numGOSIndices; }
//--------------------------------------------------------- bool CGPS_Track_Aggregation::On_Execute(void) { bool bVerbose, bPolar; int Time_Span, fRefID, fX, fY, fTrack, fDate, fTime, fParameter, Observation, iDropped, nDropped; double eps_Space, eps_Time, off_Time, iTime; TSG_Point Position; CSG_String iTrack, iDate; CSG_Table_Record *pAggregate, *pObservation; CSG_Shape *pReference, *pNearest; CSG_Simple_Statistics Statistic, Time; CSG_Table *pObservations, *pAggregated, Observations; CSG_Shapes_Search Reference; //----------------------------------------------------- pObservations = Parameters("OBSERVATIONS") ->asTable (); pAggregated = Parameters("AGGREGATED") ->asTable (); fRefID = Parameters("REFERENCE_ID") ->asInt (); fX = Parameters("X") ->asInt (); fY = Parameters("Y") ->asInt (); fTrack = Parameters("TRACK") ->asInt (); fDate = Parameters("DATE") ->asInt (); fTime = Parameters("TIME") ->asInt (); fParameter = Parameters("PARAMETER") ->asInt (); Time_Span = Parameters("TIME_SPAN") ->asInt (); eps_Space = Parameters("EPS_SPACE") ->asDouble(); off_Time = Parameters("OFF_TIME") ->asDouble() * 60.0; bVerbose = Parameters("VERBOSE") ->asBool (); bPolar = Parameters("POLAR") ->asBool (); switch( Time_Span ) { default: eps_Time = 0.0; break; case 1: eps_Time = Parameters("EPS_TIME")->asDouble(); break; case 2: eps_Time = Parameters("FIX_TIME")->asDouble() * 60.0; break; } if( eps_Time <= 0.0 ) { Time_Span = 0; } //----------------------------------------------------- if( !Reference.Create(Parameters("REFERENCE")->asShapes()) ) { Error_Set(_TL("could not initialize reference point search engine")); return( false ); } //----------------------------------------------------- if( Time_Span == 2 ) // pre-processing for 'fix' time span { Observations.Create(*pObservations); Observations.Add_Field(SG_T("REF_ID"), SG_DATATYPE_String); fTrack = pObservations->Get_Field_Count(); pObservations = &Observations; for(Observation=0; Observation<pObservations->Get_Count() && Set_Progress(Observation, pObservations->Get_Count()); Observation++) { pObservation = pObservations->Get_Record(Observation); pNearest = Reference.Get_Point_Nearest(pObservation->asDouble(fX), pObservation->asDouble(fY)); pObservation ->Set_Value(fTrack, pNearest->asString(fRefID)); } } //----------------------------------------------------- if( !pObservations->Set_Index(fTrack, TABLE_INDEX_Ascending, fDate, TABLE_INDEX_Ascending, fTime, TABLE_INDEX_Ascending) ) { Error_Set(_TL("could not create index on observations")); return( false ); } //----------------------------------------------------- pAggregated->Destroy(); pAggregated->Fmt_Name("%s [%s]", pObservations->Get_Name(), _TL("aggregated")); pAggregated->Add_Field("REFID", SG_DATATYPE_String); // AGG_ID pAggregated->Add_Field("TRACK", SG_DATATYPE_String); // AGG_TRACK pAggregated->Add_Field("DATE" , SG_DATATYPE_String); // AGG_DATE pAggregated->Add_Field("TIME" , SG_DATATYPE_String); // AGG_TIME pAggregated->Add_Field(pObservations->Get_Field_Name(fParameter), SG_DATATYPE_Double); // AGG_PARM if( bVerbose ) { pAggregated->Add_Field("MIN" , SG_DATATYPE_Double); // AGG_MIN, pAggregated->Add_Field("MAX" , SG_DATATYPE_Double); // AGG_MAX pAggregated->Add_Field("RANGE" , SG_DATATYPE_Double); // AGG_RANGE pAggregated->Add_Field("STDDEV" , SG_DATATYPE_Double); // AGG_STDDEV, pAggregated->Add_Field("COUNT" , SG_DATATYPE_Int ); // AGG_COUNT, pAggregated->Add_Field("DROPPED", SG_DATATYPE_Int ); // AGG_DROPPED, pAggregated->Add_Field("DTIME" , SG_DATATYPE_Double); // AGG_DTIME, pAggregated->Add_Field("X" , SG_DATATYPE_Double); // AGG_X pAggregated->Add_Field("Y" , SG_DATATYPE_Double); // AGG_Y } //----------------------------------------------------- pAggregate = NULL; nDropped = 0; iDropped = 0; //----------------------------------------------------- for(Observation=0; Observation<pObservations->Get_Count() && Set_Progress(Observation, pObservations->Get_Count()); Observation++) { pObservation = pObservations->Get_Record_byIndex(Observation); if( !pAggregate || iTrack.Cmp(pObservation->asString(fTrack)) || iDate .Cmp(pObservation->asString(fDate )) || (eps_Time > 0.0 && eps_Time <= pObservation->asDouble(fTime) - iTime) ) { pReference = NULL; } Position.x = pObservation->asDouble(fX); Position.y = pObservation->asDouble(fY); pNearest = Reference.Get_Point_Nearest(Position.x, Position.y); if( eps_Space > 0.0 && eps_Space <= (bPolar ? SG_Get_Distance_Polar(Position, pNearest->Get_Point(0)) : SG_Get_Distance(Position, pNearest->Get_Point(0))) ) { nDropped++; iDropped++; } else { if( pReference != pNearest ) { Set_Statistic(pAggregate, Statistic, Time, iDropped, bVerbose); Statistic .Invalidate(); Time .Invalidate(); iDropped = 0; iTrack = pObservation->asString(fTrack); iDate = pObservation->asString(fDate ); switch( Time_Span ) { default: iTime = 0.0; break; case 1: iTime = pObservation->asDouble(fTime); break; case 2: iTime = (int)(pObservation->asDouble(fTime) / eps_Time) * eps_Time - off_Time; break; } pReference = pNearest; pAggregate = pAggregated->Add_Record(); pAggregate ->Set_Value(AGG_ID , pReference->asString(fRefID)); pAggregate ->Set_Value(AGG_TRACK, iTrack); pAggregate ->Set_Value(AGG_DATE , iDate ); if( bVerbose ) { pAggregate ->Set_Value(AGG_X, pReference->Get_Point(0).x); pAggregate ->Set_Value(AGG_Y, pReference->Get_Point(0).y); } } Statistic += pObservation->asDouble(fParameter); Time += pObservation->asDouble(fTime ); } } Set_Statistic(pAggregate, Statistic, Time, iDropped, bVerbose); //----------------------------------------------------- if( nDropped > 0 ) { Message_Fmt("\n%s: %d", _TL("number of dropped observations"), nDropped); } //----------------------------------------------------- return( true ); }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // 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); } } }
//------------------------------------------------------------------------------ // bool gosFX::Card::Execute(ExecuteInfo *info) { Check_Object(this); Check_Object(info); if (!IsExecuted()) return false; // //------------------------ // Do the effect animation //------------------------ // if (!Singleton::Execute(info)) return false; // //----------------------------------------- // Animate the parent then get our pointers //----------------------------------------- // Set_Statistic(Card_Count, Card_Count+1); Specification *spec = GetSpecification(); Check_Object(spec); // //---------------- // Animate the uvs //---------------- // Stuff::Scalar u = spec->m_UOffset.ComputeValue(m_age, m_seed); Stuff::Scalar v = spec->m_VOffset.ComputeValue(m_age, m_seed); Stuff::Scalar u2 = spec->m_USize.ComputeValue(m_age, m_seed); Stuff::Scalar v2 = spec->m_VSize.ComputeValue(m_age, m_seed); // //-------------------------------------------------------------- // If we are animated, figure out the row/column to be displayed //-------------------------------------------------------------- // if (spec->m_animated) { BYTE columns = Stuff::Truncate_Float_To_Byte( spec->m_index.ComputeValue(m_age, m_seed) ); BYTE rows = static_cast<BYTE>(columns / spec->m_width); columns = static_cast<BYTE>(columns - rows*spec->m_width); // //--------------------------- // Now compute the end points //--------------------------- // u += u2*columns; v += v2*rows; } u2 += u; v2 += v; m_uvs[0].x = u; m_uvs[0].y = v2; m_uvs[1].x = u2; m_uvs[1].y = v2; m_uvs[2].x = u2; m_uvs[2].y = v; m_uvs[3].x = u; m_uvs[3].y = v; // //------------------ // Fill in the color //------------------ // m_colors[0] = m_color; m_colors[1] = m_color; m_colors[2] = m_color; m_colors[3] = m_color; // //--------------------- // Fill in the position //--------------------- // m_vertices[0].x = m_scale*m_halfX; m_vertices[0].y = -m_scale*m_halfY; m_vertices[0].z = 0.0f; m_vertices[1].x = -m_scale*m_halfX; m_vertices[1].y = -m_scale*m_halfY; m_vertices[1].z = 0.0f; m_vertices[2].x = -m_scale*m_halfX; m_vertices[2].y = m_scale*m_halfY; m_vertices[2].z = 0.0f; m_vertices[3].x = m_scale*m_halfX; m_vertices[3].y = m_scale*m_halfY; m_vertices[3].z = 0.0f; return true; }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int MLRNGonCloud::Clip(MLRClippingState clippingFlags, GOSVertexPool *vt) { Check_Object(this); int i, j, k; int end, len = *usedNrOfNGons, ret = 0; #if EFECT_CLIPPED // this effect gets not clipped int l, mask, k1, ct=0; Scalar a=0.0f, bc0, bc1; #endif Check_Object(vt); gos_vertices = vt->GetActualVertexPool(); Check_Pointer(gos_vertices); numGOSVertices = 0; // //-------------------------------------- // See if we don't have to draw anything //-------------------------------------- // if(clippingFlags.GetClippingState() == 0 || len <= 0) { if(len <= 0) { visible = 0; } else { // //------------------------------- // Handle the non-indexed version //------------------------------- // for(i=0,j=0;i<len;i++,j += numOfVertices) { // if(IsOn(i) == false) // { // continue; // } DWORD inColor = GOSCopyColor(&colors[2*i]); DWORD outColor = GOSCopyColor(&colors[2*i+1]); for(int z=1; z < numOfVertices-1; z++) { GOSCopyTriangleData( &gos_vertices[numGOSVertices], transformedCoords->GetData(), j, z+j+1, z+j, true ); gos_vertices[numGOSVertices].argb = inColor; gos_vertices[numGOSVertices+1].argb = outColor; gos_vertices[numGOSVertices+2].argb = outColor; numGOSVertices += 3; } } Check_Object(vt); vt->Increase(numGOSVertices); visible = numGOSVertices ? 1 : 0; } return visible; } int myNumberUsedClipVertex, myNumberUsedClipIndex, myNumberUsedClipLength; myNumberUsedClipVertex = 0; myNumberUsedClipIndex = 0; myNumberUsedClipLength = 0; // //------------------------------- // Handle the non-indexed version //------------------------------- // // //----------------------------------------------------------------- // Step through each polygon, making sure that we don't try to clip // backfaced polygons //----------------------------------------------------------------- // for(i=0,j=0;i<len;i++,j+=numOfVertices) { // if(IsOn(i) == false) // { // continue; // } TurnVisible(i); // //--------------------------------------------------------------- // Test each vertex of the polygon against the allowed clipping // planes, and accumulate status for which planes always clip and // which planes clipped at least once //--------------------------------------------------------------- // theAnd.SetClippingState(0x3f); theOr.SetClippingState(0); end = j+numOfVertices; Stuff::Vector4D *v4d = transformedCoords->GetData()+j; MLRClippingState *cs = clipPerVertex->GetData()+j; for(k=j;k<end;k++,v4d++,cs++) { cs->Clip4dVertex(v4d); theAnd &= (*clipPerVertex)[k]; theOr |= (*clipPerVertex)[k]; #ifdef LAB_ONLY if(*cs==0) { Set_Statistic(NonClippedVertices, NonClippedVertices+1); } else { Set_Statistic(ClippedVertices, ClippedVertices+1); } #endif } theAnd = theOr = 0; //ASSUME NO CLIPPING NEEDED FOR MC2. Its just not done here! // //------------------------------------------------------------------- // If any bit is set for all vertices, then the polygon is completely // outside the viewing space and we don't have to draw it. On the // other hand, if no bits at all were ever set, we can do a trivial // accept of the polygon //------------------------------------------------------------------- // if (theAnd != 0) { TurnInVisible(i); } else if (theOr == 0) { TurnVisible(i); DWORD inColor = GOSCopyColor(&colors[2*i]); DWORD outColor = GOSCopyColor(&colors[2*i+1]); for(int z=1; z < numOfVertices-1; z++) { GOSCopyTriangleData( &gos_vertices[numGOSVertices], transformedCoords->GetData(), j, z+j+1, z+j, true ); gos_vertices[numGOSVertices].argb = inColor; gos_vertices[numGOSVertices+1].argb = outColor; gos_vertices[numGOSVertices+2].argb = outColor; #ifdef LAB_ONLY if(gShowClippedPolys) { gos_vertices[numGOSVertices].argb = 0xff0000ff; gos_vertices[numGOSVertices].u = 0.0f; gos_vertices[numGOSVertices].v = 0.0f; gos_vertices[numGOSVertices+1].argb = 0xff0000ff; gos_vertices[numGOSVertices+1].u = 0.0f; gos_vertices[numGOSVertices+1].v = 0.0f; gos_vertices[numGOSVertices+2].argb = 0xff0000ff; gos_vertices[numGOSVertices+2].u = 0.0f; gos_vertices[numGOSVertices+2].v = 0.0f; } #endif numGOSVertices += 3; } ret++; } // //----------------------------------------------------------------- // It is not a trivial case, so we must now do real clipping on the // polygon //----------------------------------------------------------------- // else { #if EFECT_CLIPPED // this effect gets not clipped int numberVerticesPerPolygon = 0; // //--------------------------------------------------------------- // Handle the case of a single clipping plane by stepping through // the vertices and finding the edge it originates //--------------------------------------------------------------- // if (theOr.GetNumberOfSetBits() == 1) { for(k=j;k<end;k++) { k1 = (k + 1 < end) ? k+1 : j; // //---------------------------------------------------- // If this vertex is inside the viewing space, copy it // directly to the clipping buffer //---------------------------------------------------- // int clipped_index = myNumberUsedClipVertex + numberVerticesPerPolygon; theTest = clipPerVertex[k]; if(theTest == 0) { clipExtraCoords[clipped_index] = transformedCoords[k]; if(k==j) { clipExtraColors[clipped_index] = colors[2*i]; } else { clipExtraColors[clipped_index] = colors[2*i+1]; } 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(clipPerVertex[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 if(clipPerVertex[k1] != 0) { Verify(clipPerVertex[k1] == clipPerVertex[k]); continue; } // //-------------------------------------------------- // We now find the distance along the edge where the // clipping plane will intersect //-------------------------------------------------- // mask = 1; theTest |= clipPerVertex[k1]; // //----------------------------------------------------- // Find the boundary conditions that match our clipping // plane //----------------------------------------------------- // for (l=0; l<MLRClippingState::NextBit; l++) { if(theTest.IsClipped(mask)) { // //------------------------------------------- // Find the clipping interval from bc0 to bc1 //------------------------------------------- // a = GetLerpFactor(l, (*transformedCoords)[k], (*transformedCoords)[k1]); Verify(a >= 0.0f && a <= 1.0f); ct = l; break; } mask <<= 1; } // //------------------------------ // Lerp the homogeneous position //------------------------------ // clipExtraCoords[clipped_index].Lerp( transformedCoords[k], transformedCoords[k1], a ); DoClipTrick(clipExtraCoords[clipped_index], ct); // //---------------------------------------------------------- // If there are colors, lerp them in screen space for now as // most cards do that anyway //---------------------------------------------------------- // clipExtraColors[clipped_index].Lerp( (k==j) ? colors[2*i] : colors[2*i+1], (k1==j) ? colors[2*i] : colors[2*i+1], 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 { EffectClipData srcPolygon, dstPolygon; int dstBuffer = 0; specialClipColors[0] = colors[2*i]; for(l=1;l<numOfVertices;l++) { specialClipColors[l] = colors[2*i+1]; } // //----------------------------------------------------- // Point the source polygon buffer at our original data //----------------------------------------------------- // srcPolygon.coords = &transformedCoords[j]; srcPolygon.clipPerVertex = &clipPerVertex[j]; srcPolygon.flags = 0; srcPolygon.colors = specialClipColors.GetData(); srcPolygon.length = numOfVertices; // //-------------------------------- // Point to the destination buffer //-------------------------------- // dstPolygon.coords = clipBuffer[dstBuffer].coords.GetData(); dstPolygon.colors = clipBuffer[dstBuffer].colors.GetData(); dstPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData(); dstPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.GetData(); dstPolygon.flags = srcPolygon.flags; 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) { dstPolygon.coords[dstPolygon.length] = srcPolygon.coords[k]; dstPolygon.clipPerVertex[dstPolygon.length] = srcPolygon.clipPerVertex[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 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 //------------------------------------------- // bc0 = GetBC(l, srcPolygon.coords[k]); bc1 = GetBC(l, srcPolygon.coords[k1]); Verify(!Close_Enough(bc0, bc1)); a = bc0 / (bc0 - bc1); Verify(a >= 0.0f && a <= 1.0f); // //------------------------------ // Lerp the homogeneous position //------------------------------ // dstPolygon.coords[dstPolygon.length].Lerp( srcPolygon.coords[k], srcPolygon.coords[k1], a ); DoCleanClipTrick(dstPolygon.coords[dstPolygon.length], l); // //---------------------------------------------------------- // If there are colors, lerp them in screen space for now as // most cards do that anyway //---------------------------------------------------------- // dstPolygon.colors[dstPolygon.length].Lerp( srcPolygon.colors[k], srcPolygon.colors[k1], 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.colors = clipBuffer[dstBuffer].colors.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.colors = clipBuffer[dstBuffer].colors.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++) { int clipped_index = myNumberUsedClipVertex + k; if(srcPolygon.coords[k].z == srcPolygon.coords[k].w) { srcPolygon.coords[k].z -= SMALL; } clipExtraCoords[clipped_index] = srcPolygon.coords[k]; clipExtraColors[clipped_index] = srcPolygon.colors[k]; } numberVerticesPerPolygon = srcPolygon.length; } clipExtraLength[myNumberUsedClipLength] = numberVerticesPerPolygon; myNumberUsedClipVertex += numberVerticesPerPolygon; myNumberUsedClipLength++; ret++; // clip // dont draw the original TurnInVisible(i); #endif } } #if EFECT_CLIPPED // this effect gets not clipped if(myNumberUsedClipLength > 0) { for(i=0,j=0;i<myNumberUsedClipLength;i++) { int stride = clipExtraLength[i]; for(k=1;k<stride-1;k++) { Verify((vt->GetLast() + 3 + numGOSVertices) < vt->GetLength()); GOSCopyTriangleData( &gos_vertices[numGOSVertices], clipExtraCoords.GetData(), clipExtraColors.GetData(), j, j+k+1, j+k, true ); #ifdef LAB_ONLY if(gShowClippedPolys) { gos_vertices[numGOSVertices].argb = 0xffff0000; gos_vertices[numGOSVertices].u = 0.0f; gos_vertices[numGOSVertices].v = 0.0f; gos_vertices[numGOSVertices+1].argb = 0xffff0000; gos_vertices[numGOSVertices+1].u = 0.0f; gos_vertices[numGOSVertices+1].v = 0.0f; gos_vertices[numGOSVertices+2].argb = 0xffff0000; gos_vertices[numGOSVertices+2].u = 0.0f; gos_vertices[numGOSVertices+2].v = 0.0f; } #endif numGOSVertices += 3; } j += stride; } } #endif vt->Increase(numGOSVertices); visible = numGOSVertices ? 1 : 0; if(visible) { } else { } return visible; }