//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // MLRIndexedPolyMesh::MLRIndexedPolyMesh( MemoryStream *stream, int version ): MLRIndexedPrimitive(DefaultData, stream, version) { Check_Pointer(this); Check_Pointer(stream); facePlanes.SetLength(GetNumPrimitives()); testList.SetLength(GetNumPrimitives()); FindFacePlanes(); }
/* ============ idMapEntity::Write ============ */ bool idMapEntity::Write( idFile *fp, int entityNum ) const { int i; idMapPrimitive *mapPrim; idVec3 origin; fp->WriteFloatString( "// entity %d\n{\n", entityNum ); // write entity epairs for ( i = 0; i < epairs.GetNumKeyVals(); i++) { fp->WriteFloatString( "\"%s\" \"%s\"\n", epairs.GetKeyVal(i)->GetKey().c_str(), epairs.GetKeyVal(i)->GetValue().c_str()); } epairs.GetVector( "origin", "0 0 0", origin ); // write pritimives for ( i = 0; i < GetNumPrimitives(); i++ ) { mapPrim = GetPrimitive( i ); switch( mapPrim->GetType() ) { case idMapPrimitive::TYPE_BRUSH: static_cast<idMapBrush*>(mapPrim)->Write( fp, i, origin ); break; case idMapPrimitive::TYPE_PATCH: static_cast<idMapPatch*>(mapPrim)->Write( fp, i, origin ); break; } } fp->WriteFloatString( "}\n" ); return true; }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MLRIndexedPolyMesh::ResetTestList() { int i, numPrimitives = GetNumPrimitives(); unsigned char *iPtr = &testList[0]; for(i=0;i<numPrimitives;i++,iPtr++) { *iPtr = 1; } }
bool JRenderServer::Draw( int firstIdx, int numIdx, int firstVert, int numVert, PrimitiveType primType ) { if (numVert == 0) return false; bool bIndexed = true; int numPri = 0; if (numIdx == 0) { numPri = GetNumPrimitives( primType, numVert ); bIndexed = false; } else { numPri = GetNumPrimitives( primType, numIdx ); } if (primType == PrimitiveType_QuadList) { numPri = numVert/2; bIndexed = true; firstIdx = 0; SetIB( m_QuadIB, firstVert ); } HRESULT hRes = m_pDevice->BeginScene(); if (hRes != S_OK) return false; if (bIndexed) { hRes = m_pDevice->DrawIndexedPrimitive( ConvertPrimitiveType( primType ), 0, numVert, firstIdx, numPri ); } else { hRes = m_pDevice->DrawPrimitive( ConvertPrimitiveType( primType ), firstVert, numPri ); } hRes = m_pDevice->EndScene(); if (hRes != S_OK) return false; return (hRes == S_OK); } // JRenderServer::Draw
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int MLRIndexedPolyMesh::FindBackFace(const Point3D& u) { Check_Object(this); int i, numPrimitives = GetNumPrimitives(); int ret = 0, len = lengths.GetLength(); unsigned char *iPtr; Plane *p; if(len <= 0) { visible = 0; return 0; } p = &facePlanes[0]; iPtr = &testList[0]; if(state.GetBackFaceMode() == MLRState::BackFaceOffMode) { ResetTestList(); ret = 1; } else { for(i=0;i<numPrimitives;i++,p++,iPtr++) { // Scalar s = p->DistanceTo(u); // *iPtr = !Get_Sign_Bit(s); *iPtr = (p->DistanceTo(u) >= 0.0f) ? (unsigned char)1: (unsigned char)0; ret += *iPtr; } visible = ret ? (unsigned char)1 : (unsigned char)0; } visible = ret ? (unsigned char)1 : (unsigned char)0; FindVisibleVertices(); return ret; }
/* =============== idMapEntity::GetGeometryCRC =============== */ unsigned int idMapEntity::GetGeometryCRC( void ) const { int i; unsigned int crc; idMapPrimitive *mapPrim; crc = 0; for ( i = 0; i < GetNumPrimitives(); i++ ) { mapPrim = GetPrimitive( i ); switch( mapPrim->GetType() ) { case idMapPrimitive::TYPE_BRUSH: crc ^= static_cast<idMapBrush*>(mapPrim)->GetGeometryCRC(); break; case idMapPrimitive::TYPE_PATCH: crc ^= static_cast<idMapPatch*>(mapPrim)->GetGeometryCRC(); break; } } return crc; }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MLRIndexedPolyMesh::FindFacePlanes() { Check_Object(this); int i, j, stride, numPrimitives = GetNumPrimitives(); Vector3D v; Verify(index.GetLength() > 0); for(i=0,j=0;i<numPrimitives;i++) { stride = lengths[i]; facePlanes[i].BuildPlane( coords[index[j]], coords[index[j+1]], coords[index[j+2]] ); j += stride; } }
//--------------------------------------------------------------------------- // bool MLRIndexedPolyMesh::CastRay( Line3D *line, Normal3D *normal ) { Check_Object(this); Check_Object(line); Check_Pointer(normal); // //--------------------------------------------------------------------- // We have to spin through each of the polygons stored in the shape and // collide the ray against each //--------------------------------------------------------------------- // int poly_start = 0, numPrimitives = GetNumPrimitives(); bool hit = false; for (int polygon=0; polygon<numPrimitives; ++polygon) { int stride = lengths[polygon]; Verify(stride>2); // //--------------------------------- // See if the line misses the plane //--------------------------------- // Scalar product; const Plane *plane = &facePlanes[polygon]; Check_Object(plane); Scalar distance = line->DistanceTo(*plane, &product); if (distance < 0.0f || distance > line->length) { poly_start += stride; continue; } bool negate = false; if (product > -SMALL) { if (GetCurrentState().GetBackFaceMode() == MLRState::BackFaceOnMode) { poly_start += stride; continue; } negate = true; } // //------------------------------------------- // Figure out where on the plane the line hit //------------------------------------------- // Point3D impact; line->Project(distance, &impact); // //------------------------------------------------------------------- // We now need to find out which cardinal plane we should project the // triangle onto //------------------------------------------------------------------- // int s,t; Scalar nx = Abs(plane->normal.x); Scalar ny = Abs(plane->normal.y); Scalar nz = Abs(plane->normal.z); if (nx > ny) { if (nx > nz) { s = Y_Axis; t = Z_Axis; } else { s = X_Axis; t = Y_Axis; } } else if (ny > nz) { s = Z_Axis; t = X_Axis; } else { s = X_Axis; t = Y_Axis; } // //---------------------------------------- // Initialize the vertex and leg variables //---------------------------------------- // Point3D *v1, *v2, *v3; v1 = &coords[index[poly_start]]; v2 = &coords[index[poly_start+1]]; v3 = &coords[index[poly_start+2]]; // //--------------------------------------- // Get the projection of the impact point //--------------------------------------- // Scalar s0 = impact[s] - (*v1)[s]; Scalar t0 = impact[t] - (*v1)[t]; Scalar s1 = (*v2)[s] - (*v1)[s]; Scalar t1 = (*v2)[t] - (*v1)[t]; // //------------------------------------------------------------ // For each triangle, figure out what the second leg should be //------------------------------------------------------------ // bool local_hit = false; int next_v = 3; Test_Triangle: Check_Pointer(v3); Scalar s2 = (*v3)[s] - (*v1)[s]; Scalar t2 = (*v3)[t] - (*v1)[t]; // //-------------------------------- // Now, see if we hit the triangle //-------------------------------- // if (Small_Enough(s1)) { Verify(!Small_Enough(s2)); Scalar beta = s0 / s2; if (beta >= 0.0f && beta < 1.0f) { Verify(!Small_Enough(t1)); Scalar alpha = (t0 - beta*t2) / t1; local_hit = (alpha >= 0.0f && alpha+beta <= 1.0f); } } else { Scalar beta = (t0*s1 - s0*t1); Scalar alpha = (t2*s1 - s2*t1); beta /= alpha; if (beta >= 0.0f && beta <= 1.0f) { alpha = (s0 - beta*s2) / s1; local_hit = (alpha >= 0.0f && alpha+beta <= 1.0f); } } // //----------------------------- // Set up for the next triangle //----------------------------- // if (next_v < stride && !local_hit) { v2 = v3; v3 = &coords[index[poly_start+next_v++]]; s1 = s2; t1 = t2; goto Test_Triangle; } // //---------------------------------------------------- // Handle the hit status, and move to the next polygon //---------------------------------------------------- // if (local_hit) { hit = true; line->length = distance; if (negate) normal->Negate(plane->normal); else *normal = plane->normal; Verify(*normal * line->direction <= -SMALL); } poly_start += stride; } // //---------------------- // Return the hit status //---------------------- // return hit; }