//----------------------------------------------------------------// bool USSurface2D::IsBridge ( ZLVec2D& loc, ZLVec2D& move ) { ZLVec2D destLoc = loc; destLoc.Add ( move ); return ( this->IsOn ( destLoc )); }
//----------------------------------------------------------------// bool USSurface2D::GetRayHit ( ZLVec2D& loc, ZLVec2D& ray, float& time ) { float d; d = ray.Dot ( this->mNorm ); if ( d == 0.0f ) return false; // ray is parallel time = ( loc.Dot ( this->mNorm ) + this->mDist ) / -d; return true; }
//----------------------------------------------------------------// ZLVec2D USSurface2D::GetNorm ( const ZLVec2D& e0, const ZLVec2D& e1 ) { ZLVec2D norm; norm = e0; norm.Sub ( e1 ); norm.Rotate90Anticlockwise (); norm.Norm (); return norm; }
//----------------------------------------------------------------// bool USSurface2D::GetHit ( ZLVec2D& sphereLoc, ZLVec2D& move, SurfaceHit2D& hit ) { // The usual stuff... ZLVec2D unitMove = move; unitMove.Norm (); if ( unitMove.Dot ( this->mNorm ) >= -0.001f ) return false; if ( ZLDist::PointToPlane2D ( sphereLoc, *this ) <= 0.0f ) return false; // Get the point of first contact on the polygon... ZLVec2D pofcop = this->mNorm; pofcop.Reverse (); pofcop.Add ( sphereLoc ); this->ClampPoint ( pofcop ); // Send a ray from the point on the surface to intersect the circle. // The ray is the inverse of the move vec. ZLVec2D inverseMove = move; inverseMove.Reverse (); float t0, t1; u32 sectType; sectType = ZLSect::VecToCircle ( t0, t1, pofcop, inverseMove, sphereLoc, 1.0f ); // Bail if the point will not intersect the sphere. if ( sectType == ZLSect::SECT_PARALLEL ) return false; if ( t0 >= hit.mTime ) return false; // Bail if the point will graze the sphere. if ( sectType == ZLSect::SECT_TANGENT ) return false; // Bail if the point will stay outside of the sphere. if (( t0 > 1.0f ) || ( t1 < 0.0f )) return false; // OMG! We hit something! float time = t0; hit.mTime = time; inverseMove.Scale ( t0 ); hit.mPoint = pofcop; hit.mPoint.Add ( inverseMove ); hit.mNorm = sphereLoc; hit.mNorm.Sub ( hit.mPoint ); hit.mNorm.Norm (); if ( unitMove.Dot ( hit.mNorm ) >= -0.001f ) return false; return true; }
//----------------------------------------------------------------// bool _vecToXYPlane ( const ZLVec3D& v0, const ZLVec3D& v1, ZLVec2D& result ) { ZLVec3D vec; vec = v1; vec.Sub ( v0 ); if ( vec.mZ != 0.0f ) { result.mX = vec.mX; result.mY = vec.mY; float t = v0.mZ / -vec.mZ; if (( t > 0.0f ) && ( t <= 1.0f )) { result.Scale ( t ); result.mX += v0.mX; result.mY += v0.mY; return true; } } return false; }
//----------------------------------------------------------------// bool USSurface2D::GetTouch ( ZLVec2D& sphereLoc, ZLSurfaceTouch2D& touch ) { // The usual stuff... float dist = ZLDist::PointToPlane2D ( sphereLoc, *this ); if ( dist <= 0.0f ) return false; if ( dist > 1.001f ) return false; // Get the point of first contact on the polygon... ZLVec2D pofcop = this->mNorm; pofcop.Reverse (); pofcop.Add ( sphereLoc ); this->ClampPoint ( pofcop ); ZLVec2D ray = pofcop; ray.Sub ( sphereLoc ); dist = ray.NormSafe (); if ( dist >= touch.mDist ) return false; float dot = ray.Dot ( touch.mFinger ); if ( dot < 0.85f ) return false; // we have a touch... touch.mDist = dist; touch.mPoint = pofcop; touch.mTouch = true; touch.mHit = !touch.mPrevTouch; //touch.mNorm = this->GetNorm (); return true; }
//----------------------------------------------------------------// float USSurface2D::GetDepthAlongRay ( ZLVec2D& sphereLoc, ZLVec2D& ray ) { // Get the point of first contact on the polygon... ZLVec2D pofcop = this->mNorm; pofcop.Reverse (); pofcop.Add ( sphereLoc ); this->ClampPoint ( pofcop ); float t0, t1; u32 sectType; sectType = ZLSect::VecToCircle ( t0, t1, pofcop, ray, sphereLoc, 1.0f ); // Bail if the point will not intersect the sphere. if ( sectType == ZLSect::SECT_PARALLEL ) return 0.0f; if ( sectType == ZLSect::SECT_TANGENT ) return 0.0f; return t0; }
//----------------------------------------------------------------// int MOAIVectorUtil::StrokeWedge ( const MOAIVectorStyle& style, ZLVec2D*& verts, const ZLVec2D& origin, const ZLVec2D& n0, const ZLVec2D& n1, float width ) { float wedge = n0.Radians ( n1 ); // angle between two normals u32 steps = style.GetResolutionForWedge ( wedge ); if ( verts ) { float angle = n0.Radians (); // angle of first normal against x axis float angleStep = wedge / ( float )steps; for ( u32 i = 0; i <= steps; ++i, angle += angleStep ) { ZLVec2D v; v.mX = origin.mX + ( Cos ( angle ) * width ); v.mY = origin.mY + ( Sin ( angle ) * width ); *( verts++ ) = v; } } return ( int )( steps + 1 ); }
//----------------------------------------------------------------// bool USSurface2D::GetContact ( ZLVec2D& sphereLoc, ZLVec2D& contact, ZLVec2D& norm ) { // The usual stuff... float dist = ZLDist::PointToPlane2D ( sphereLoc, *this ); if ( dist <= 0.0f ) return false; if ( dist > 1.001f ) return false; // Get the point of first contact on the polygon... contact = this->mNorm; contact.Reverse (); contact.Add ( sphereLoc ); this->ClampPoint ( contact ); norm = sphereLoc; norm.Sub ( contact ); dist = norm.NormSafe (); if ( dist > 1.001f ) return false; return true; }
//----------------------------------------------------------------// bool USSurface2D::GetRayHit ( ZLVec2D& loc, ZLVec2D& ray, float pad, float& time ) { float d; d = ray.Dot ( this->mNorm ); if ( d == 0.0f ) return false; time = ( loc.Dot ( this->mNorm ) + this->mDist ) / -d; // now get the point of impact ZLVec2D sect = ray; sect.Scale ( time ); sect.Add ( loc ); float dot = this->mTangent.Dot ( sect ); if ( dot < ( this->mP0 - pad )) return false; if ( dot > ( this->mP1 + pad )) return false; return true; }
//----------------------------------------------------------------// void MOAIPartitionLevel::GatherProps ( MOAIPartitionResultBuffer& results, MOAIProp* ignore, const ZLVec3D& point, u32 planeID, u32 mask ) { ZLVec2D cellPoint ( 0.0f, 0.0f ); switch ( planeID ) { case ZLBox::PLANE_XY: cellPoint.Init ( point.mX, point.mY ); break; case ZLBox::PLANE_XZ: cellPoint.Init ( point.mX, point.mZ ); break; case ZLBox::PLANE_YZ: cellPoint.Init ( point.mY, point.mZ ); break; }; float halfSize = this->mCellSize * 0.5f; cellPoint.mX = cellPoint.mX - halfSize; cellPoint.mY = cellPoint.mY + halfSize; MOAICellCoord coord = this->mGridSpace.GetCellCoord ( cellPoint.mX, cellPoint.mY ); int width = this->mGridSpace.GetWidth (); int height = this->mGridSpace.GetHeight (); int xTotal = ( width < 2 ) ? 1 : 2; int yTotal = ( height < 2 ) ? 1 : 2; for ( int y = 0; y < yTotal; ++y ) { for ( int x = 0; x < xTotal; ++x ) { MOAICellCoord offset = this->mGridSpace.WrapCellCoord ( coord.mX + x, coord.mY - y ); int addr = this->mGridSpace.GetCellAddr ( offset ); this->mCells [ addr ].GatherProps ( results, ignore, point, mask ); } } }
//----------------------------------------------------------------// void USSurface2D::ClampPoint ( ZLVec2D& p ) { ZLDist::SnapToPlane2D ( p, *this ); float edgeDist = this->mTangent.Dot ( p ); if ( edgeDist < this->mP0 ) { ZLVec2D offset = this->mTangent; offset.Scale ( this->mP0 - edgeDist ); p.Add ( offset ); } else if ( edgeDist > this->mP1 ) { ZLVec2D offset = this->mTangent; offset.Scale ( this->mP1 - edgeDist ); p.Add ( offset ); } }
//----------------------------------------------------------------// void MOAIVectorUtil::ComputeLineJoins ( MOAIVectorLineJoin* joins, const ZLVec2D* verts, int nVerts, bool open, bool forward, bool interior ) { int top = nVerts - 1; float scale = interior ? -1.0f : 1.0f; if ( forward ) { for ( int i = 0; i < nVerts; ++i ) { joins [ i ].mVertex = verts [ i ]; } } else { for ( int i = 0; i < nVerts; ++i ) { joins [ i ].mVertex = verts [ top - i ]; } } for ( int i = 0; i < nVerts; ++i ) { ZLVec2D v0 = joins [ i ].mVertex; ZLVec2D v1 = joins [( i + 1 ) % nVerts ].mVertex; ZLVec2D n = v1; n.Sub ( v0 ); n.Norm (); joins [ i ].mEdgeVec = n; n.Rotate90Anticlockwise (); n.Scale ( scale ); joins [ i ].mEdgeNorm = n; joins [ i ].mIsCap = false; } int start = 0; int max = nVerts; if ( open ) { joins [ 0 ].mIsCap = true; joins [ 0 ].mJointNorm = joins [ 0 ].mEdgeNorm; joins [ top ].mIsCap = true; joins [ top ].mEdgeVec = joins [ top - 1 ].mEdgeVec; joins [ top ].mEdgeNorm = joins [ top - 1 ].mEdgeNorm; joins [ top ].mJointNorm = joins [ top ].mEdgeNorm; start = 1; max = top; } for ( int i = start; i < max; ++i ) { ZLVec2D n = joins [( i + top ) % nVerts ].mEdgeNorm; n.Add ( joins [ i ].mEdgeNorm ); n.Norm (); joins [ i ].mJointNorm = n; } }
//----------------------------------------------------------------// int MOAIVectorUtil::StrokeLine ( const MOAIVectorStyle& style, ZLVec2D* verts, const MOAIVectorLineJoin* joins, int nJoins, float width, bool exact ) { if ( exact ) { if ( verts ) { for ( int i = 0; i < nJoins; ++i ) { *( verts++ ) = joins [ i ].mVertex; } } return nJoins; } u32 count = 0; for ( int i = 0; i < nJoins; ++i ) { int j0 = ( i + nJoins -1 ) % nJoins; int j1 = i; const MOAIVectorLineJoin& join = joins [ j1 ]; float d = join.mEdgeNorm.Dot ( join.mJointNorm ); float miter = width / d; u32 joinStyle = style.mJoinStyle; u32 capStyle = style.mCapStyle; if ( join.mIsCap ) { switch ( capStyle ) { case MOAIVectorStyle::CAP_BUTT: { if ( verts ) { ZLVec2D v = join.mVertex; v.Add ( join.mJointNorm, width ); *( verts++ ) = v; } count = count + 1; break; } case MOAIVectorStyle::CAP_ROUND: { if ( i == 0 ) { ZLVec2D n0 = join.mEdgeVec; n0.Scale ( -1.0f ); count = count + MOAIVectorUtil::StrokeWedge ( style, verts, join.mVertex, n0, join.mEdgeNorm, width ); } else { count = count + MOAIVectorUtil::StrokeWedge ( style, verts, join.mVertex, join.mEdgeNorm, join.mEdgeVec, width ); } break; } case MOAIVectorStyle::CAP_POINTY: { if ( verts ) { ZLVec2D v = join.mVertex; if ( i == 0 ) { v.Add ( join.mEdgeVec, -width ); *( verts++ ) = v; v = join.mVertex; v.Add ( join.mEdgeNorm, width ); *( verts++ ) = v; } else { v.Add ( join.mEdgeNorm, width ); *( verts++ ) = v; v = join.mVertex; v.Add ( join.mEdgeVec, width ); *( verts++ ) = v; } } count = count + 2; break; } case MOAIVectorStyle::CAP_SQUARE: { if ( verts ) { ZLVec2D v = join.mVertex; if ( i == 0 ) { v.Add ( join.mEdgeVec, -width ); *( verts++ ) = v; v.Add ( join.mEdgeNorm, width ); *( verts++ ) = v; } else { v.Add ( join.mEdgeNorm, width ); v.Add ( join.mEdgeVec, width ); *( verts++ ) = v; v.Add ( join.mEdgeNorm, -width ); *( verts++ ) = v; } } count = count + 2; break; } } } else { const MOAIVectorLineJoin& prev = joins [ j0 ]; if ( join.mJointNorm.Dot ( prev.mEdgeVec ) <= 0.0f ) { joinStyle = MOAIVectorStyle::JOIN_MITER; } else if ( joinStyle == MOAIVectorStyle::JOIN_MITER ) { if (( miter / width ) > style.mMiterLimit ) { joinStyle = MOAIVectorStyle::JOIN_BEVEL; } } switch ( joinStyle ) { case MOAIVectorStyle::JOIN_BEVEL: { if ( verts ) { ZLVec2D v0 = prev.mEdgeNorm; v0.Scale ( width ); v0.Add ( join.mVertex ); *( verts++ ) = v0; ZLVec2D v1 = join.mEdgeNorm; v1.Scale ( width ); v1.Add ( join.mVertex ); *( verts++ ) = v1; } count = count + 2; break; } case MOAIVectorStyle::JOIN_MITER: { if ( verts ) { ZLVec2D v = join.mJointNorm; v.Scale ( miter ); v.Add ( join.mVertex ); *( verts++ ) = v; } count = count + 1; break; } case MOAIVectorStyle::JOIN_ROUND: { count = count + MOAIVectorUtil::StrokeWedge ( style, verts, join.mVertex, prev.mEdgeNorm, join.mEdgeNorm, width ); break; } } } } return count; }