Plane3 Unit(Plane3 p) { double nt = max(Length(p.normal), fpabsmax(p.normal)); if(nt) return Plane3(p.delta / nt, p.normal / nt); return p; }
void Clipper::update() { Vector3 planepts[3]; if (!valid()) { planepts[0] = Vector3(0, 0, 0); planepts[1] = Vector3(0, 0, 0); planepts[2] = Vector3(0, 0, 0); setClipPlane(Plane3(0, 0, 0, 0)); } else { AABB bounds(Vector3(0, 0, 0), Vector3(64, 64, 64)); getPlanePoints(planepts, bounds); if (_switch) { std::swap(planepts[0], planepts[1]); } setClipPlane(Plane3(planepts)); } GlobalMainFrame().updateAllWindows(); }
void BestPoint(std::size_t count, Vector4 clipped[9], SelectionIntersection& best, clipcull_t cull) { Vector3 normalised[9]; { for(std::size_t i=0; i<count; ++i) { normalised[i][0] = clipped[i][0] / clipped[i][3]; normalised[i][1] = clipped[i][1] / clipped[i][3]; normalised[i][2] = clipped[i][2] / clipped[i][3]; } } if(cull != eClipCullNone && count > 2) { double signed_area = triangle_signed_area_XY(normalised[0], normalised[1], normalised[2]); if((cull == eClipCullCW && signed_area > 0) || (cull == eClipCullCCW && signed_area < 0)) return; } if(count == 2) { Segment3D segment(normalised[0], normalised[1]); Point3D point = segment_closest_point_to_point(segment, Vector3(0, 0, 0)); assign_if_closer(best, SelectionIntersection(point.z(), 0)); } else if(count > 2 && !point_test_polygon_2d(Vector3(0, 0, 0), normalised, normalised + count)) { point_iterator_t end = normalised + count; for(point_iterator_t previous = end-1, current = normalised; current != end; previous = current, ++current) { Segment3D segment(*previous, *current); Point3D point = segment_closest_point_to_point(segment, Vector3(0, 0, 0)); double depth = point.z(); point.z() = 0; double distance = point.getLengthSquared(); assign_if_closer(best, SelectionIntersection(depth, distance)); } } else if(count > 2) { assign_if_closer( best, SelectionIntersection( static_cast<float>( Ray(Vector3(0, 0, 0), Vector3(0, 0, 1)).getDistance( Plane3(normalised[0], normalised[1], normalised[2]) )), 0 ) ); } }
// TODO: 最优分割面选择需要考虑到二叉树的平衡性 // weight = fabs(左数目-右数目)+分割数目 // 越小越优先考虑 int BspTree::BspNode::BestIndex( std::vector< BspTriangle >& polyList ) { /** * The current hueristic is blind least-split */ // run through the list, searching for the best one. // the highest BspTriangle we'll bother testing (10% of total) int maxCheck; maxCheck = (int)(polyList.size() * percentageToCheck); if( !maxCheck ) maxCheck = 1; int bestSplits = 100000; int bestIndex = -1; int currSplits; // 这个平面总共分割了多少平面 int frontCount, backCount; Plane3 currPlane; for(int i=0; i<maxCheck; i++ ) { currSplits = 0; frontCount = backCount = 0; currPlane = Plane3( polyList[i] ); PointListLoc res; for(unsigned int i2=0; i2< polyList.size(); i2++ ) { if( i == i2 ) continue; res = currPlane.TestPoly( polyList[i2] ); switch(res) { case plistSplit: currSplits++; break; case plistFront: frontCount++; break; case plistBack: backCount++; break; } } int weight = abs(frontCount - backCount) + currSplits; //int weight = currSplits; if( weight < bestSplits ) { bestSplits = weight; bestIndex = i; } } assert( bestIndex >= 0 ); return bestIndex; }
void FaceInstance::addLight(const Matrix4& localToWorld, const RendererLight& light) { const Plane3& facePlane = getFace().plane3(); Plane3 tmp = Plane3(facePlane.normal(), -facePlane.dist()) .transformed(localToWorld); if (!tmp.testPoint(light.worldOrigin()) || !tmp.testPoint(light.getLightOrigin())) { m_lights.addLight(light); } }
// Get a transformed copy of this frustum Frustum Frustum::getTransformedBy(const Matrix4& matrix) const { // greebo: DR's Plane3 is seriuosly hampered by its internal representation // which is nx,ny,nz,dist instead of a,b,c,d. This causes a lot of confusion // and makes it necessary to invert the dist() member each time before // applying a transformation matrix. Plane3 rightTemp = Plane3(right.normal(), -right.dist()).transform(matrix); Plane3 leftTemp = Plane3(left.normal(), -left.dist()).transform(matrix); Plane3 topTemp = Plane3(top.normal(), -top.dist()).transform(matrix); Plane3 bottomTemp = Plane3(bottom.normal(), -bottom.dist()).transform(matrix); Plane3 backTemp = Plane3(back.normal(), -back.dist()).transform(matrix); Plane3 frontTemp = Plane3(front.normal(), -front.dist()).transform(matrix); rightTemp.dist() = -rightTemp.dist(); leftTemp.dist() = -leftTemp.dist(); topTemp.dist() = -topTemp.dist(); bottomTemp.dist() = -bottomTemp.dist(); backTemp.dist() = -backTemp.dist(); frontTemp.dist() = -frontTemp.dist(); return Frustum( rightTemp, leftTemp, bottomTemp, topTemp, backTemp, frontTemp ); }
BspTree::BspNode::BspNode( std::vector< BspTriangle >& in ) : m_bIsLeaf( false ) { // if the list is empty, we're bombing out. assert( in.size() ); // get the best index to use as a splitting plane int bestIndex = BestIndex( in ); // we could remove the index from the vector, but that's slow. // instead we'll just kind of ignore it during the next phase. // remove the best index BspTriangle splitPoly = in[bestIndex]; m_plane = Plane3( splitPoly ); m_Triangle = splitPoly; // take the rest of the polygons and divide them. std::vector< BspTriangle > frontList, backList; unsigned int i; for( i=0; i<in.size(); i++ ) { // ignore the BspTriangle if it's the one // we're using as the splitting plane if( i == bestIndex ) continue; // test the BspTriangle against this node. PointListLoc res = m_plane.TestPoly( in[i] ); //BspTriangle front, back; // used in plistSPLIT switch( res ) { case plistFront: // drop down the front frontList.push_back( in[i] ); break; case plistBack: // drop down the back backList.push_back( in[i] ); break; case plistSplit: // split the BspTriangle, drop the halves down. m_plane.Split( in[i], frontList, backList ); //frontList.push_back( front ); //backList.push_back( back ); break; case plistCoplanar: // add the BspTriangle to this node's list m_coplanarList.push_back( in[i] ); // hack : 对于位于平面上的点,放到front列表中 //frontList.push_back( in[i] ); break; } } // we're done processing the BspTriangle list. Deal with them. if( frontList.size() ) { m_pFront = new BspNode( frontList ); } else { m_pFront = new BspNode( false ); } if( backList.size() ) { m_pBack = new BspNode( backList ); } else { m_pBack = new BspNode( true ); } }
DragRestricter* createDragRestricter(const InputState& inputState, const Vec3& initialPoint) const { return new PlaneDragRestricter(Plane3(initialPoint, inputState.camera().direction().firstAxis())); }