示例#1
0
/**
 * When drawing in 2D, this method is invoked automatically to dynamically scale the
 * node so that it appears with the correct perspective. This is required because
 * when drawing as a 2D overlay, the node will not otherwise be drawn with the
 * perspective of the 3D billboard's location.
 */
void CC3Billboard::align2DToCamera( CC3Camera* camera )
{
	// Use the camera to project the 3D location of this node
	// into 2D and then set the billboard to that position
	camera->projectNode( this );
	CCPoint pPos = getProjectedPosition();
	m_pBillboard->setPosition( ccpAdd(pPos, m_offsetPosition) );
	
	CCPoint newBBScale;
	// If only one non-zero scale is allowed (min == max), ensure that the billboard is set to that scale
	if (!m_minimumBillboardScale.equals(CCPointZero)
		&& m_maximumBillboardScale.equals(m_minimumBillboardScale)) 
	{
		newBBScale = m_minimumBillboardScale;
		//LogTrace(@"Projecting billboard %@ to %@ with fixed scaling %@", self,
		//		 NSStringFromCGPoint(pPos), NSStringFromCGPoint(newBBScale));
	} 
	else 
	{
		// Calc how much to scale the billboard by comparing distance from camera to billboard
		// and camera to the defined unity-scale distance. Neither may be smaller than the near
		// clipping plane.
		GLfloat camNear = camera->getNearClippingDistance();
		GLfloat camDist = MAX( getGlobalLocation().distance( camera->getGlobalLocation() ), camNear);
		GLfloat unityDist = MAX(getUnityScaleDistance(), camNear);
		GLfloat distScale = unityDist / camDist;
		newBBScale.x = distScale;
		newBBScale.y = distScale;
		
		// Ensure result is within any defined min and max scales
		newBBScale.x = MAX(newBBScale.x, m_minimumBillboardScale.x);
		newBBScale.y = MAX(newBBScale.y, m_minimumBillboardScale.y);
		
		newBBScale.x = (m_maximumBillboardScale.x != 0.0) ? MIN(newBBScale.x, m_maximumBillboardScale.x) : newBBScale.x;
		newBBScale.y = (m_maximumBillboardScale.y != 0.0) ? MIN(newBBScale.y, m_maximumBillboardScale.y) : newBBScale.y;
		
		// Factor in the scale of this CC3Billboard node.
		CC3Vector myScale = getScale();
		newBBScale.x *= myScale.x;
		newBBScale.y *= myScale.y;
		//LogTrace(@"Projecting billboard %@ to %@, scaled to %@ using distance %.2f and unity distance %.2f",
		//		 self, NSStringFromCGPoint(pPos), NSStringFromCGPoint(newBBScale), camDist, unityDist);
	}
	
	// If consistency across devices is desired, adjust size of 2D billboard so that
	// it appears the same size relative to 3D artifacts across all device resolutions
	if (m_shouldNormalizeScaleToDevice) 
		newBBScale = ccpMult(newBBScale, deviceScaleFactor());
	
	// Set the new scale only if it has changed. 
	if (m_pBillboard->getScaleX() != newBBScale.x) 
		m_pBillboard->setScaleX( newBBScale.x );
	if (m_pBillboard->getScaleY() != newBBScale.y) 
		m_pBillboard->setScaleY( newBBScale.y );
}
示例#2
0
CC3Ray CC3Camera::unprojectPoint( const CCPoint& cc2Point )
{
    // Scale from UI points to GL points
    CCPoint glPoint = ccpMult(cc2Point, CCDirector::sharedDirector()->getContentScaleFactor());

    // Express the glPoint X & Y as proportion of the viewport dimensions.
    CC3Viewport vp = getViewport();
    GLfloat xp = ((2.0f * glPoint.x) / vp.w) - 1;
    GLfloat yp = ((2.0f * glPoint.y) / vp.h) - 1;

    // Ensure that the camera's frustum is up to date, and then map the proportional point
    // on the viewport to its position on the near clipping rectangle. The Z-coordinate is
    // negative because the camera points down the negative Z axis in its local coordinates.
    buildProjection();
    CC3Vector pointLocNear = cc3v(_frustum->getRight() * xp, _frustum->getTop() * yp, -_frustum->getNear());

    CC3Ray ray;
    if ( isUsingParallelProjection() )
    {
        // The location on the near clipping plane is relative to the camera's
        // local coordinates. Convert it to global coordinates before returning.
        // The ray direction is straight out from that global location in the
        // camera's globalForwardDirection.
        ray.startLocation =  getGlobalTransformMatrix()->transformLocation( pointLocNear );
        ray.direction = getGlobalForwardDirection();
    }
    else
    {
        // The location on the near clipping plane is relative to the camera's local
        // coordinates. Since the camera's origin is zero in its local coordinates,
        // this point on the near clipping plane forms a directional vector from the
        // camera's origin. Rotate this directional vector with the camera's rotation
        // matrix to convert it to a global direction vector in global coordinates.
        // Thanks to Cocos3D forum user Rogs for suggesting the use of the globalRotationMatrix.
        ray.startLocation = getGlobalLocation();
        ray.direction = getGlobalRotationMatrix()->transformDirection( pointLocNear );
    }

    // Ensure the direction component is normalized before returning.
    ray.direction = ray.direction.normalize();

    //LogTrace(@"%@ unprojecting point %@ to near plane location %@ and to ray starting at %@ and pointing towards %@",
    //			  [self class], NSStringFromCGPoint(glPoint), NSStringFromCC3Vector(pointLocNear),
    //			  NSStringFromCC3Vector(ray.startLocation), NSStringFromCC3Vector(ray.direction));

    return ray;
}
示例#3
0
/**
 * When drawing in 3D, thd 2D node will automatically be drawn with the correct
 * perspective projection, but this method is invoked automatically to enforce
 * the minimum and maximum scales.
 */
void CC3Billboard::align3DToCamera( CC3Camera* camera )
{
	// Don't waste time if no min or max scale has been set.
	if (m_minimumBillboardScale.equals(CCPointZero) &&
		m_maximumBillboardScale.equals(CCPointZero)) 
		return;

	GLfloat camNear = camera->getNearClippingDistance();
	GLfloat unityDist = MAX(getUnityScaleDistance(), camNear);
	GLfloat camDist = MAX(getGlobalLocation().distance(camera->getGlobalLocation()), camNear);

	CCPoint newBBScale = ccp(m_pBillboard->getScaleX(), m_pBillboard->getScaleY());

	if (m_minimumBillboardScale.x > 0.0) {
		GLfloat minScaleDistX = unityDist / m_minimumBillboardScale.x;
		newBBScale.x = (camDist > minScaleDistX) ? (camDist / minScaleDistX) : 1.0f;
	}
	
	if (m_minimumBillboardScale.y > 0.0) {
		GLfloat minScaleDistY = unityDist / m_minimumBillboardScale.y;
		newBBScale.y = (camDist > minScaleDistY) ? (camDist / minScaleDistY) : 1.0f;
	}
	
	if (m_maximumBillboardScale.x > 0.0) {
		GLfloat maxScaleDistX = unityDist / m_maximumBillboardScale.x;
		newBBScale.x = (camDist < maxScaleDistX) ? (camDist / maxScaleDistX) : 1.0f;
	}
	
	if (m_maximumBillboardScale.y > 0.0) {
		GLfloat maxScaleDistY = unityDist / m_maximumBillboardScale.y;
		newBBScale.y = (camDist < maxScaleDistY) ? (camDist / maxScaleDistY) : 1.0f;
	}
	
	// Set the new scale only if it has changed. 
	if (m_pBillboard->getScaleX() != newBBScale.x) 
		m_pBillboard->setScaleX( newBBScale.x );

	if (m_pBillboard->getScaleY() != newBBScale.y) 
		m_pBillboard->setScaleY( newBBScale.y );
}
示例#4
0
CC3Vector CC3Camera::getProjectLocation( const CC3Vector& a3DLocation )
{
    // Convert specified location to a 4D homogeneous location vector
    // and transform it using the modelview and projection matrices.
    CC3Vector4 hLoc;
    hLoc.fromLocation(a3DLocation);
    hLoc = getViewMatrix()->transformHomogeneousVector( hLoc );
    hLoc = getProjectionMatrix()->transformHomogeneousVector( hLoc );

    // Convert projected 4D vector back to 3D.
    CC3Vector projectedLoc = hLoc.homogenizedCC3Vector();

    // The projected vector is in a projection coordinate space between -1 and +1 on all axes.
    // Normalize the vector so that each component is between 0 and 1 by calculating ( v = (v + 1) / 2 ).
    projectedLoc = projectedLoc.average( CC3Vector::kCC3VectorUnitCube );

    CCAssert(_viewport.h > 0 && _viewport.w > 0, "%CC3Camera does not have a valid viewport");

    // Map the X & Y components of the projected location (now between 0 and 1) to display coordinates.
    GLfloat g2p = 1.0f / CCDirector::sharedDirector()->getContentScaleFactor();
    projectedLoc.x *= ((GLfloat)_viewport.w * g2p);
    projectedLoc.y *= ((GLfloat)_viewport.h * g2p);

    // Using the vector from the camera to the 3D location, determine whether or not the
    // 3D location is in front of the camera by using the dot-product of that vector and
    // the direction the camera is pointing. Set the Z-component of the projected location
    // to be the signed distance from the camera to the 3D location, with a positive sign
    // indicating the location is in front of the camera, and a negative sign indicating
    // the location is behind the camera.
    CC3Vector camToLocVector = a3DLocation - getGlobalLocation();
    GLfloat camToLocDist = camToLocVector.length();
    GLfloat frontOrBack = (GLfloat)SIGN( camToLocVector.dot( getGlobalForwardDirection() ) );
    projectedLoc.z = frontOrBack * camToLocDist;

    //LogTrace(@"%@ projecting location %@ to %@ and orienting with device to %@ using viewport %@",
    //		 self, NSStringFromCC3Vector(a3DLocation), NSStringFromCC3Vector(projectedLoc),
    //		 NSStringFromCC3Vector(orientedLoc), NSStringFromCC3Viewport(_viewport));
    return projectedLoc;
}
示例#5
0
// Overridden to take into consideration the isDirectionalOnly property
CC3Vector4 CC3Light::getGlobalHomogeneousPosition()
{
	return (isDirectionalOnly()
			? CC3Vector4().fromDirection(getGlobalLocation())
			: CC3Vector4().fromLocation(getGlobalLocation()));
}
示例#6
0
void CC3Camera::moveWithDurationLookAt( float t, CC3Node* aNode, const CC3Vector& targetLoc, GLfloat padding )
{
    ensureSceneUpdated( true );
    CC3Vector moveDir = getGlobalLocation() - aNode->getGlobalLocation();
    moveWithDuration( t, aNode, targetLoc, moveDir, padding, false );
}
示例#7
0
void CC3Camera::moveWithDuration( float t, CC3Node* aNode, GLfloat padding )
{
    ensureSceneUpdated( true );
    CC3Vector moveDir = getGlobalLocation() - aNode->getGlobalLocation();
    moveWithDuration( t, aNode, CC3Vector::kCC3VectorNull, moveDir, padding, false );
}
示例#8
0
void CC3Camera::moveToShowAllOfLookAt( CC3Node* aNode, const CC3Vector& targetLoc, GLfloat padding )
{
    ensureSceneUpdated( true );
    CC3Vector moveDir = getGlobalLocation() - aNode->getGlobalLocation();
    moveToShowAllOfLookAt( aNode, targetLoc, moveDir, padding, false );
}
示例#9
0
void CC3Camera::moveToShowAllOf( CC3Node* aNode, GLfloat padding )
{
    ensureSceneUpdated( true );
    CC3Vector moveDir = getGlobalLocation() - aNode->getGlobalLocation();
    moveToShowAllOfLookAt( aNode, CC3Vector::kCC3VectorNull, moveDir, padding, false );
}