예제 #1
0
void CC3Billboard::populateAsBoundingRectangle()
{
	CC3Vector* vertices;		// Array of simple vertex location data

	// Start with default initial values
	GLfloat xMin = 0.0f;
	GLfloat xMax = 1.0f;
	GLfloat yMin = 0.0f;
	GLfloat yMax = 1.0f;
	int vCount = 4;
	
	CC3VertexLocations* locArray = CC3VertexLocations::vertexArray();
	locArray->setDrawingMode( GL_TRIANGLE_STRIP );			// Location array will do the drawing as a strip
	locArray->setVertexStride( 0 );							// Tightly packed locations only
	locArray->setElementOffset( 0 );							// Only locations
	locArray->setAllocatedVertexCapacity( vCount );
	vertices = (CC3Vector*)locArray->getVertices();
	
	// Populate vertex locations in the X-Y plane
	vertices[0] = cc3v(xMax, yMax, 0.0f);
	vertices[1] = cc3v(xMin, yMax, 0.0f);
	vertices[2] = cc3v(xMax, yMin, 0.0f);
	vertices[3] = cc3v(xMin, yMin, 0.0f);
	
	// Create mesh with vertex location array
	CC3Mesh* aMesh = CC3Mesh::mesh();
	aMesh->setVertexLocations( locArray );
	setMesh( aMesh );

	updateBoundingMesh();
}
예제 #2
0
/** If the bounding mesh exists, update its vertices to match the bounding box of the 2D node. */
void CC3Billboard::updateBoundingMesh()
{
	if (m_pMesh) 
	{
		CCRect bRect = getBillboardBoundingRect();
		GLfloat xMin = bRect.getMinX();
		GLfloat xMax = bRect.getMaxX();
		GLfloat yMin = bRect.getMinX();
		GLfloat yMax = bRect.getMaxY();
		m_pMesh->setVertexLocation( cc3v(xMax, yMax, 0.0), 0 );
		m_pMesh->setVertexLocation( cc3v(xMin, yMax, 0.0), 1 );
		m_pMesh->setVertexLocation( cc3v(xMax, yMin, 0.0), 2 );
		m_pMesh->setVertexLocation( cc3v(xMin, yMin, 0.0), 3 );
	}
}
예제 #3
0
/**
 * Calculate the end of the directonal marker line.
 *
 * This is done by calculating the scale we need to multiply the directional marker by to
 * reach each of the three sides of the bounding box, then take the smallest of these,
 * because that is the side it will intersect. Finally, multiply by an overall scale factor.
 */
CC3Vector CC3DirectionMarkerNode::calculateLineEnd()
{
	CC3Box pbb = getParentBoundingBox();
	CC3Vector md = getMarkerDirection();
	
	CC3Vector pbbDirScale = cc3v(calcScale( md.x, pbb.minimum.x, pbb.maximum.x ),
								 calcScale( md.y, pbb.minimum.y, pbb.maximum.y ),
								 calcScale( md.z, pbb.minimum.z, pbb.maximum.z ));
	//CC3_PUSH_NOSHADOW
	GLfloat dirScale = MIN(pbbDirScale.x, MIN(pbbDirScale.y, pbbDirScale.z));
	dirScale = dirScale * getDirectionMarkerScale();
	//CC3_POP_NOSHADOW

	// Ensure that the direction marker has the minimum length specified by directionMarkerMinimumLength
	if (directionMarkerMinimumLength) {
		GLfloat gblUniScale = getGlobalScale().length() / CC3Vector::kCC3VectorUnitCubeLength;
		GLfloat minScale = directionMarkerMinimumLength / gblUniScale;
		dirScale = MAX(dirScale, minScale);
	}

	CC3Vector lineEnd = md.scaleUniform( dirScale );
	//LogTrace(@"%@ calculated line end %@ from pbb scale %@ and dir scale %.3f and min global length: %.3f", self,
	//		 NSStringFromCC3Vector(lineEnd), NSStringFromCC3Vector(pbbDirScale), dirScale, directionMarkerMinimumLength);
	return lineEnd;
}
예제 #4
0
/** Measures the bounding box of the parent node and updates the vertex locations. */
void CC3WireframeBoundingBoxNode::updateFromParentBoundingBoxWithVisitor( CC3NodeUpdatingVisitor* visitor )
{
	CC3Box pbb = getParentBoundingBox();
	setVertexLocation( cc3v(pbb.minimum.x, pbb.minimum.y, pbb.minimum.z), 0 );
	setVertexLocation( cc3v(pbb.minimum.x, pbb.minimum.y, pbb.maximum.z), 1 );
	setVertexLocation( cc3v(pbb.minimum.x, pbb.maximum.y, pbb.minimum.z), 2 );
	setVertexLocation( cc3v(pbb.minimum.x, pbb.maximum.y, pbb.maximum.z), 3 );
	setVertexLocation( cc3v(pbb.maximum.x, pbb.minimum.y, pbb.minimum.z), 4 );
	setVertexLocation( cc3v(pbb.maximum.x, pbb.minimum.y, pbb.maximum.z), 5 );
	setVertexLocation( cc3v(pbb.maximum.x, pbb.maximum.y, pbb.minimum.z), 6 );
	setVertexLocation( cc3v(pbb.maximum.x, pbb.maximum.y, pbb.maximum.z), 7 );
	updateVertexLocationsGLBuffer();
}
예제 #5
0
/** Transform the bounding rectangle of the 2D node on the X-Y plane into 3D. */
void CC3BillboardBoundingBoxArea::transformVolume()
{
	super::transformVolume();

	// Get the corners of the CCNode bounding box
	CCRect br = getBillboardBoundingRect();
	CCPoint bbMin = ccp(br.getMinX(), br.getMinY());
	CCPoint bbMax = ccp(br.getMaxX(), br.getMaxY());
	
	// Construct all 4 corner vertices of the local bounding box and transform each to global coordinates
	m_vertices[0] = m_pNode->getGlobalTransformMatrix()->transformLocation( cc3v(bbMin.x, bbMin.y, 0.0) );
	m_vertices[1] = m_pNode->getGlobalTransformMatrix()->transformLocation( cc3v(bbMin.x, bbMax.y, 0.0) );
	m_vertices[2] = m_pNode->getGlobalTransformMatrix()->transformLocation( cc3v(bbMax.x, bbMin.y, 0.0) );
	m_vertices[3] = m_pNode->getGlobalTransformMatrix()->transformLocation( cc3v(bbMax.x, bbMax.y, 0.0) );
	
	/*LogTrace(@"%@ bounding volume transformed %@ MinMax(%@, %@) to (%@, %@, %@, %@)", _node,
			 NSStringFromCGRect(br),
			 NSStringFromCGPoint(bbMin), NSStringFromCGPoint(bbMax), 
			 NSStringFromCC3Vector(_vertices[0]), NSStringFromCC3Vector(_vertices[1]),
			 NSStringFromCC3Vector(_vertices[2]), NSStringFromCC3Vector(_vertices[3]));*/
}
예제 #6
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;
}
예제 #7
0
void CC3TouchBox::populateBox( const CC3Box& aBox )
{
	CC3Mesh* mesh = prepareParametricMesh();
	
	// Now update the vertex locations with the box data
	GLuint vIdx = 0;
	CC3Vector bbMin = aBox.minimum;
	CC3Vector bbMax = aBox.maximum;
	mesh->setVertexLocation( cc3v(bbMin.x, bbMin.y, bbMin.z), vIdx++ );
	mesh->setVertexLocation( cc3v(bbMin.x, bbMin.y, bbMax.z), vIdx++ );
	mesh->setVertexLocation( cc3v(bbMin.x, bbMax.y, bbMin.z), vIdx++ );
	mesh->setVertexLocation( cc3v(bbMin.x, bbMax.y, bbMax.z), vIdx++ );
	mesh->setVertexLocation( cc3v(bbMax.x, bbMin.y, bbMin.z), vIdx++ );
	mesh->setVertexLocation( cc3v(bbMax.x, bbMin.y, bbMax.z), vIdx++ );
	mesh->setVertexLocation( cc3v(bbMax.x, bbMax.y, bbMin.z), vIdx++ );
	mesh->setVertexLocation( cc3v(bbMax.x, bbMax.y, bbMax.z), vIdx++ );
	
	mesh->updateVertexLocationsGLBuffer();
	markBoundingVolumeDirty();
}
예제 #8
0
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;
}
예제 #9
0
void CC3ActionScaleTo::initWithDuration( float t, GLfloat aScale )
{
	return initWithDuration( t, cc3v(aScale, aScale, aScale) );
}
예제 #10
0
CC3ActionScaleBy* CC3ActionScaleBy::actionWithDuration( float t, GLfloat aScale )
{
	return actionWithDuration( t, cc3v(aScale, aScale, aScale) );
}
예제 #11
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 ) );
}