示例#1
0
//----------------------------------------------------------------//
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;
}
//----------------------------------------------------------------//
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 );
	}
}
//----------------------------------------------------------------//
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 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 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;
}