void CC3LocalContentNode::setShouldDrawLocalContentWireframeBox( bool shouldDraw )
{	
	// Fetch the wireframe node from the child nodes.
	CC3WireframeBoundingBoxNode* wf = getLocalContentWireframeBoxNode();
	
	// If the wireframe exists, but should not, remove it
	if (wf && !shouldDraw) 
		wf->remove();
	
	// If there is no wireframe, but there should be, add it by creating a
	// CC3WireframeLocalContentBoundingBoxNode from the localContentBoundingBox
	// property and add it as a child of this node. If the bounding box is null,
	// don't create a wireframe. Since the local content of a node does not
	// normally change shape, the bounding box is NOT set to update its vertices
	// by default from the bounding box of this node on each update pass.
	if(!wf && shouldDraw) 
	{
		CC3Box mbb = getLocalContentBoundingBox();
		if ( !mbb.isNull() )
		{
			wf = CC3WireframeLocalContentBoundingBoxNode::nodeWithName( getLocalContentWireframeBoxName() );
			wf->populateAsWireBox( mbb );
			wf->setEmissionColor( getInitialLocalContentWireframeBoxColor() );
			addChild( wf );
		}
	}
}
// Overridden to include local content
CC3Box CC3LocalContentNode::getBoundingBoxRelativeTo( CC3Node* ancestor )
{
	CC3Box lcbb = (shouldContributeToParentBoundingBox()
				   ? getLocalContentBoundingBoxRelativeTo( ancestor )
				   : CC3Box::kCC3BoxNull);

	return lcbb.boxUnion( super::getBoundingBoxRelativeTo(ancestor) );
}
/**
 * Overridden to return the parent's local content bounding box,
 * or kCC3BoxZero if no parent, or if parent doesn't have a bounding box.
 */
CC3Box CC3WireframeLocalContentBoundingBoxNode::getParentBoundingBox()
{
	if (m_pParent && m_pParent->hasLocalContent()) 
	{
		CC3Box pbb = ((CC3LocalContentNode*)m_pParent)->getLocalContentBoundingBox();
		if ( !pbb.isNull() )
			return pbb;
	}
    
	return CC3Box::kCC3BoxZero;
}
/**
 * Returns the parent's bounding box, or kCC3BoxZero if no parent,
 * or if parent doesn't have a bounding box.
 */
CC3Box CC3WireframeBoundingBoxNode::getParentBoundingBox()
{
	if ( m_pParent )
    {
		CC3Box pbb = m_pParent->getBoundingBox();
		if ( !pbb.isNull() )
            return pbb;
	}
    
	return CC3Box::kCC3BoxZero;
}
/** 
 * Overridden to establish a default parent bounding box for parents that have no bounding
 * box, such as cameras and lights. The default parent box is calculated as 5% of the size
 * of the entire scene.
 */
CC3Box CC3DirectionMarkerNode::getParentBoundingBox()
{
	CC3Box pbb = super::getParentBoundingBox();
	if ( !pbb.isZero() )
		return pbb;

	CC3Vector bbDim = CC3Vector::kCC3VectorZero;
	CC3Scene* pScene = getScene();
	if ( pScene )
		bbDim = getScene()->getBoundingBox().getSize().scaleUniform( 0.05f );
		
	return CC3Box( bbDim.negate(), bbDim );
}
void CC3TouchBox::setBox( const CC3Box& aBox )
{
	if ( aBox.isNull() ) {
		setMesh( NULL );
	} else {
		populateBox( aBox );
	}
}
CC3Box CC3LocalContentNode::getLocalContentBoundingBoxRelativeTo( CC3Node* ancestor )
{
	CC3Box lcbb = getLocalContentBoundingBox();
	if (ancestor == this)
		return lcbb;

	CC3Matrix4x3 tMtx;
	getGlobalTransformMatrix()->populateCC3Matrix4x3( &tMtx );

	if ( ancestor )
		ancestor->getGlobalTransformMatrixInverted()->leftMultiplyIntoCC3Matrix4x3( &tMtx );
	
	// The eight vertices of the transformed local bounding box
	CC3Vector bbVertices[8];
	
	// Get the corners of the local bounding box
	CC3Vector bbMin = lcbb.minimum;
	CC3Vector bbMax = lcbb.maximum;
	
	// Construct all 8 corner vertices of the local bounding box and transform each
	// to the coordinate system of the ancestor. The result is an oriented-bounding-box.
	bbVertices[0] = CC3Matrix4x3TransformLocation(&tMtx, cc3v(bbMin.x, bbMin.y, bbMin.z));
	bbVertices[1] = CC3Matrix4x3TransformLocation(&tMtx, cc3v(bbMin.x, bbMin.y, bbMax.z));
	bbVertices[2] = CC3Matrix4x3TransformLocation(&tMtx, cc3v(bbMin.x, bbMax.y, bbMin.z));
	bbVertices[3] = CC3Matrix4x3TransformLocation(&tMtx, cc3v(bbMin.x, bbMax.y, bbMax.z));
	bbVertices[4] = CC3Matrix4x3TransformLocation(&tMtx, cc3v(bbMax.x, bbMin.y, bbMin.z));
	bbVertices[5] = CC3Matrix4x3TransformLocation(&tMtx, cc3v(bbMax.x, bbMin.y, bbMax.z));
	bbVertices[6] = CC3Matrix4x3TransformLocation(&tMtx, cc3v(bbMax.x, bbMax.y, bbMin.z));
	bbVertices[7] = CC3Matrix4x3TransformLocation(&tMtx, cc3v(bbMax.x, bbMax.y, bbMax.z));
	
	// Construct a transformed mesh bounding box that surrounds the eight global vertices
	CC3Box bb = CC3Box::kCC3BoxNull;
	for (int i = 0; i < 8; i++) 
		bb = bb.boxEngulfLocation( bbVertices[i] );
	return bb;
}
Exemple #8
0
CC3Vector CC3Camera::calculateLocationToShowAllOf( CC3Node* aNode, const CC3Vector& targLoc, const CC3Vector& aDirection, GLfloat padding, bool checkScene )
{
    ensureSceneUpdated( checkScene );

    // Complementary unit vectors pointing towards camera from node, and vice versa
    CC3Vector camDir = aDirection.normalize();
    CC3Vector viewDir = camDir.negate();

    // The camera's new forward direction will be viewDir. Use a matrix to detrmine
    // the camera's new up and right directions assuming the same scene up direction.
    CC3Matrix3x3 rotMtx;
    CC3Matrix3x3PopulateToPointTowards(&rotMtx, viewDir, getReferenceUpDirection());
    CC3Vector upDir = CC3Matrix3x3ExtractUpDirection(&rotMtx);
    CC3Vector rtDir = CC3Matrix3x3ExtractRightDirection(&rotMtx);

    // Determine the eight vertices, of the node's bounding box, in the global coordinate system
    CC3Box gbb = aNode->getGlobalBoundingBox();

    CC3Vector targetLoc = targLoc;
    // If a target location has not been specified, use the center of the node's global bounding box
    if ( targetLoc.isNull() )
        targetLoc = gbb.getCenter();

    CC3Vector bbMin = gbb.minimum;
    CC3Vector bbMax = gbb.maximum;
    CC3Vector bbVertices[8];
    bbVertices[0] = cc3v(bbMin.x, bbMin.y, bbMin.z);
    bbVertices[1] = cc3v(bbMin.x, bbMin.y, bbMax.z);
    bbVertices[2] = cc3v(bbMin.x, bbMax.y, bbMin.z);
    bbVertices[3] = cc3v(bbMin.x, bbMax.y, bbMax.z);
    bbVertices[4] = cc3v(bbMax.x, bbMin.y, bbMin.z);
    bbVertices[5] = cc3v(bbMax.x, bbMin.y, bbMax.z);
    bbVertices[6] = cc3v(bbMax.x, bbMax.y, bbMin.z);
    bbVertices[7] = cc3v(bbMax.x, bbMax.y, bbMax.z);

    // Express the camera's FOV in terms of ratios of the near clip bounds to
    // the near clip distance, so we can determine distances using similar triangles.
    CCSize fovRatios = getFovRatios();

    // Iterate through all eight vertices of the node's bounding box, and calculate
    // the largest distance required to place the camera away from the center of the
    // node in order to fit all eight vertices within the camera's frustum.
    // Simultaneously, calculate the extra distance from the center of the node to
    // the vertex that will be farthest from the camera, so we can ensure that all
    // vertices will fall within the frustum's far end.
    GLfloat maxCtrDist = 0;
    GLfloat maxVtxDeltaDist = 0;
    GLfloat minVtxDeltaDist = 0;
    for (int i = 0; i < 8; i++)
    {
        // Get a vector from the target location to the vertex
        CC3Vector relVtx = bbVertices[i] - targetLoc;

        // Project that vector onto each of the camera's new up and right directions,
        // and use similar triangles to determine the distance at which to place the
        // camera so that the vertex will fit in both the up and right directions.
        GLfloat vtxDistUp = fabs(relVtx.dot( upDir ) / fovRatios.height);
        GLfloat vtxDistRt = fabs(relVtx.dot( rtDir ) / fovRatios.width);
        GLfloat vtxDist = MAX(vtxDistUp, vtxDistRt);

        // Calculate how far along the view direction the vertex is from the center
        GLfloat vtxDeltaDist = relVtx.dot( viewDir );
        GLfloat ctrDist = vtxDist - vtxDeltaDist;

        // Accumulate the maximum distance from the node's center to the camera
        // required to fit all eight points, and the distance from the node's
        // center to the vertex that will be farthest away from the camera.
        maxCtrDist = MAX(maxCtrDist, ctrDist);
        maxVtxDeltaDist = MAX(maxVtxDeltaDist, vtxDeltaDist);
        minVtxDeltaDist = MIN(minVtxDeltaDist, vtxDeltaDist);
    }

    // Add some padding so we will have a bit of space around the node when it fills the view.
    maxCtrDist *= (1 + padding);

    // Determine if we need to move the far end of the camera frustum farther away
    GLfloat farClip = viewDir.scaleUniform(maxCtrDist + maxVtxDeltaDist).length();
    farClip *= (GLfloat)(1 + kCC3FrustumFitPadding);		// Include a little bit of padding
    if (farClip > getFarClippingDistance())
        setFarClippingDistance( farClip );

    // Determine if we need to move the near end of the camera frustum closer
    GLfloat nearClip = viewDir.scaleUniform(maxCtrDist + minVtxDeltaDist).length();
    nearClip *= (GLfloat)(1 - kCC3FrustumFitPadding);		// Include a little bit of padding
    if (nearClip < getNearClippingDistance())
        setNearClippingDistance( nearClip );

    //LogTrace(@"%@ moving to %@ to show %@ at %@ within %@ with new farClip: %.3f", self,
    //			  NSStringFromCC3Vector(CC3VectorAdd(targLoc, CC3VectorScaleUniform(camDir, maxCtrDist))),
    //			  aNode, NSStringFromCC3Vector(targLoc), _frustum, self.farClippingDistance);

    // Return the new location of the camera,
    return targetLoc.add( camDir.scaleUniform( maxCtrDist ) );
}
CC3Vector CC3LocalContentNode::getLocalContentCenterOfGeometry()
{
	CC3Box bb = getLocalContentBoundingBox();
	return bb.isNull() ? CC3Vector::kCC3VectorZero : bb.getCenter();
}