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; }
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(); }