Merge branch 'newRenderer' of github.com:darkdukey/cocos2d-x into newRenderer

This commit is contained in:
Nite Luo 2013-11-27 10:16:34 -08:00
commit 83972ecf57
9 changed files with 635 additions and 5 deletions

View File

@ -1 +1 @@
89e13afae7209dd4e3bc13d195b83c0be4cf85ae
a5d82b59c287429e558e99fdb693f7507bd381cb

View File

@ -62,7 +62,7 @@ THE SOFTWARE.
#include "CCEventDispatcher.h"
#include "CCFontFreeType.h"
#include "Renderer.h"
#include "renderer/Frustum.h"
/**
Position of the FPS
@ -136,7 +136,9 @@ bool Director::init(void)
_winSizeInPoints = Size::ZERO;
_openGLView = nullptr;
_cullingFrustum = new Frustum();
_contentScaleFactor = 1.0f;
// scheduler
@ -260,7 +262,17 @@ void Director::drawScene()
}
kmGLPushMatrix();
//construct the frustum
{
kmMat4 view;
kmMat4 projection;
kmGLGetMatrix(KM_GL_PROJECTION, &projection);
kmGLGetMatrix(KM_GL_MODELVIEW, &view);
_cullingFrustum->setupFromMatrix(view, projection);
}
// draw the scene
if (_runningScene)
{
@ -713,6 +725,7 @@ void Director::purgeDirector()
CC_SAFE_RELEASE_NULL(_FPSLabel);
CC_SAFE_RELEASE_NULL(_SPFLabel);
CC_SAFE_RELEASE_NULL(_drawsLabel);
CC_SAFE_DELETE(_cullingFrustum);
// purge bitmap cache
LabelBMFont::purgeCachedData();

View File

@ -55,6 +55,7 @@ class Scheduler;
class ActionManager;
class EventDispatcher;
class TextureCache;
class Frustum;
/**
@brief Class that creates and handles the main Window and manages how
@ -330,6 +331,12 @@ public:
*/
void setContentScaleFactor(float scaleFactor);
float getContentScaleFactor() const;
/**
Get the Culling Frustum
*/
Frustum* getFrustum() const { return _cullingFrustum; }
public:
/** Gets the Scheduler associated with this director
@ -434,6 +441,8 @@ protected:
unsigned int _totalFrames;
unsigned int _frames;
float _secondsPerFrame;
Frustum* _cullingFrustum;
/* The running scene */
Scene *_runningScene;

View File

@ -11,6 +11,8 @@
#include "Renderer.h"
#include "QuadCommand.h"
#include "CCMenuItem.h"
#include "Frustum.h"
#include "CCDirector.h"
NS_CC_BEGIN
@ -132,10 +134,46 @@ void NewSprite::updateQuadVertices()
void NewSprite::draw(void)
{
updateQuadVertices();
if(false == culling())
{
//static int count =0;
//CCLOG("culling Sprite New to not visible %d ",++count);
return;
}
//TODO implement z order
QuadCommand* renderCommand = new QuadCommand(0, _vertexZ, _texture->getName(), _shaderProgram, _blendFunc, &_quad, 1);
Renderer::getInstance()->addCommand(renderCommand);
}
bool NewSprite::culling() const
{
Frustum* frustum = Director::getInstance()->getFrustum();
AffineTransform worldTM = getNodeToWorldTransform();
//generate aabb
Point lowLeft(0,0);
Point topRight = lowLeft + Point(getContentSize());
Point lowRight(topRight.x,0);
Point topLeft(0, topRight.y);
lowLeft = PointApplyAffineTransform(lowLeft,worldTM);
lowRight = PointApplyAffineTransform(lowRight,worldTM);
topRight = PointApplyAffineTransform(topRight,worldTM);
topLeft = PointApplyAffineTransform(topLeft,worldTM);
kmVec3 point = {lowLeft.x, lowLeft.y, _vertexZ};
AABB aabb(point,point);
point = {lowRight.x, lowRight.y, _vertexZ};
aabb.expand(point);
point = {topLeft.x, topLeft.y, _vertexZ};
aabb.expand(point);
point = {topRight.x, topRight.y, _vertexZ};
aabb.expand(point);
return Frustum::IntersectResult::OUTSIDE !=frustum->intersectAABB(aabb);
}
NS_CC_END

View File

@ -25,10 +25,12 @@ public:
~NewSprite();
virtual bool initWithTexture(Texture2D *texture, const Rect& rect, bool rotated);
virtual void updateQuadVertices();
virtual void draw(void) override;
bool culling() const;
protected:
};

View File

@ -0,0 +1,390 @@
#include "Frustum.h"
#include <stdlib.h>
#include "CCCommon.h"
NS_CC_BEGIN
ViewTransform::ViewTransform()
{
_position = {0, 0, 0};
_focus = {0, 0, -1};
_up = {0, 1, 0 };
_dirty = true;
kmMat4Identity(&_matrix);
}
ViewTransform::~ViewTransform()
{
}
void ViewTransform::Init(const kmVec3 &pos, const kmVec3 &focus, const kmVec3 &up)
{
_position = pos;
_focus = focus;
_up = up;
_dirty = true;
}
void ViewTransform::LazyAdjust() const
{
if(!_dirty) return;
kmVec3Subtract(&_adjustDir, &_focus, &_position);
kmVec3Normalize(&_adjustDir, &_adjustDir);
kmVec3Cross(&_adjustRight, &_adjustDir, &_up);
kmVec3Normalize(&_adjustRight, &_adjustRight);
kmVec3Cross(&_adjustUp, &_adjustRight, &_adjustDir);
kmVec3Normalize(&_adjustUp, &_adjustUp);
_dirty = false;
}
const kmVec3& ViewTransform::getDirection() const
{
LazyAdjust();
return _adjustDir;
}
const kmVec3& ViewTransform::getRight() const
{
LazyAdjust();
return _adjustRight;
}
const kmVec3& ViewTransform::getUp() const
{
LazyAdjust();
return _adjustUp;
}
AABB::AABB(const kmVec3& min, const kmVec3& max)
{
_min = min;
_max = max;
if(_min.x > _max.x)
{
CCLOG("_min.x is greater than _max.x, it will be swapped!");
float temp = _min.x; _min.x = _max.x; _max.x = temp;
}
if(_min.y > _max.y)
{
CCLOG("_min.y is greater than _max.y, it will be swapped!");
float temp = _min.y; _min.y = _max.y; _max.y = temp;
}
if(_min.z > _max.z)
{
CCLOG("_min.z is greater than _max.z, it will be swapped!");
float temp = _min.z; _min.z = _max.z; _max.z = temp;
}
}
AABB::~AABB()
{
}
kmVec3 AABB::getCenter() const
{
kmVec3 result;
kmVec3Add(&result, &_min, &_max);
kmVec3Scale(&result, &result, 0.5f);
return result;
}
float AABB::getDimensionX() const
{
return _max.x - _min.x;
}
float AABB::getDimensionY() const
{
return _max.y - _min.y;
}
float AABB::getDimensionZ() const
{
return _max.z - _min.z;
}
kmVec3 AABB::getPositivePoint(const kmVec3& direction) const
{
kmVec3 result = _max;
if( direction.x < 0 ) result.x = _min.x;
if( direction.y < 0 ) result.y = _min.y;
if( direction.z < 0 ) result.z = _min.z;
return result;
}
const AABB& AABB::expand(const kmVec3& point)
{
if(point.x > _max.x) _max.x = point.x;
if(point.y > _max.y) _max.y = point.y;
if(point.z > _max.z) _max.z = point.z;
if(point.x < _min.x) _min.x = point.x;
if(point.y < _min.y) _min.y = point.y;
if(point.z < _min.z) _min.z = point.z;
return *this;
}
kmVec3 AABB::getNegativePoint(const kmVec3& direction) const
{
kmVec3 result = _min;
if( direction.x < 0 ) result.x = _max.x;
if( direction.y < 0 ) result.y = _max.y;
if( direction.z < 0 ) result.z = _max.z;
return result;
}
Frustum::Frustum()
{
}
Frustum::~Frustum()
{
}
void Frustum::setupProjectionOrthogonal(const cocos2d::ViewTransform &view, float width, float height, float near, float far)
{
kmVec3 cc = view.getPosition();
kmVec3 cDir = view.getDirection();
kmVec3 cRight = view.getRight();
kmVec3 cUp = view.getUp();
kmVec3Normalize(&cDir, &cDir);
kmVec3Normalize(&cRight, &cRight);
kmVec3Normalize(&cUp, &cUp);
//near
{
kmVec3 point;
kmVec3 normal;
normal = cDir;
kmVec3Scale(&point, &cDir, near);
kmVec3Add(&point, &point, &cc);
kmPlaneFromPointNormal(&_frustumPlanes[FrustumPlane::NEAR], &point, &normal);
}
//far
{
kmVec3 point;
kmVec3 normal;
kmVec3Scale(&normal, &cDir, -1);
kmVec3Scale(&point, &cDir, far);
kmVec3Add(&point, &point, &cc);
kmPlaneFromPointNormal(&_frustumPlanes[FrustumPlane::FAR], &point, &normal);
}
//left
{
kmVec3 point;
kmVec3 normal;
normal = cRight;
kmVec3Scale(&point, &cRight, -width * 0.5);
kmVec3Add(&point, &point, &cc);
kmPlaneFromPointNormal(&_frustumPlanes[FrustumPlane::LEFT], &point, &normal);
}
//right
{
kmVec3 point;
kmVec3 normal;
kmVec3Scale(&normal, &cRight, -1);
kmVec3Scale(&point, &cRight, width * 0.5);
kmVec3Add(&point, &point, &cc);
kmPlaneFromPointNormal(&_frustumPlanes[FrustumPlane::RIGHT], &point, &normal);
}
//bottom
{
kmVec3 point;
kmVec3 normal;
normal = cUp;
kmVec3Scale(&point, &cUp, -height * 0.5);
kmVec3Add(&point, &point, &cc);
kmPlaneFromPointNormal(&_frustumPlanes[FrustumPlane::BOTTOM], &point, &normal);
}
//top
{
kmVec3 point;
kmVec3 normal;
kmVec3Scale(&normal, &cUp, -1);
kmVec3Scale(&point, &cUp, height * 0.5);
kmVec3Add(&point, &point, &cc);
kmPlaneFromPointNormal(&_frustumPlanes[FrustumPlane::TOP], &point, &normal);
}
}
void Frustum::setupProjectionPerspective(const ViewTransform& view, float left, float right, float top, float bottom, float near, float far)
{
kmVec3 cc = view.getPosition();
kmVec3 cDir = view.getDirection();
kmVec3 cRight = view.getRight();
kmVec3 cUp = view.getUp();
kmVec3Normalize(&cDir, &cDir);
kmVec3Normalize(&cRight, &cRight);
kmVec3Normalize(&cUp, &cUp);
kmVec3 nearCenter;
kmVec3 farCenter;
kmVec3Scale(&nearCenter, &cDir, near);
kmVec3Add(&nearCenter, &nearCenter, &cc);
kmVec3Scale(&farCenter, &cDir, far);
kmVec3Add(&farCenter, &farCenter, &cc);
//near
{
kmPlaneFromPointNormal(&_frustumPlanes[FrustumPlane::NEAR], &nearCenter, &cDir);
}
//far
{
kmVec3 normal;
kmVec3Scale(&normal, &cDir, -1);
kmPlaneFromPointNormal(&_frustumPlanes[FrustumPlane::FAR], &farCenter, &normal);
}
//left
{
kmVec3 point;
kmVec3Scale(&point, &cRight, left);
kmVec3Add(&point, &point, &nearCenter);
kmVec3 normal;
kmVec3Subtract(&normal, &point, &cc);
kmVec3Cross(&normal, &normal, &cUp);
kmVec3Normalize(&normal, &normal);
kmPlaneFromPointNormal(&_frustumPlanes[FrustumPlane::LEFT], &point, &normal);
}
//right
{
kmVec3 point;
kmVec3Scale(&point, &cRight, right);
kmVec3Add(&point, &point, &nearCenter);
kmVec3 normal;
kmVec3Subtract(&normal, &point, &cc);
kmVec3Cross(&normal, &cUp, &normal);
kmVec3Normalize(&normal, &normal);
kmPlaneFromPointNormal(&_frustumPlanes[FrustumPlane::RIGHT], &point, &normal);
}
//bottom
{
kmVec3 point;
kmVec3Scale(&point, &cUp, bottom);
kmVec3Add(&point, &point, &nearCenter);
kmVec3 normal;
kmVec3Subtract(&normal, &point, &cc);
kmVec3Cross(&normal, &cRight, &normal);
kmVec3Normalize(&normal, &normal);
kmPlaneFromPointNormal(&_frustumPlanes[FrustumPlane::BOTTOM], &point, &normal);
}
//top
{
kmVec3 point;
kmVec3Scale(&point, &cUp, top);
kmVec3Add(&point, &point, &nearCenter);
kmVec3 normal;
kmVec3Subtract(&normal, &point, &cc);
kmVec3Cross(&normal, &normal, &cRight);
kmVec3Normalize(&normal, &normal);
kmPlaneFromPointNormal(&_frustumPlanes[FrustumPlane::TOP], &point, &normal);
}
}
void Frustum::setupProjectionPerspectiveFov(const ViewTransform& view, float fov, float ratio, float near, float far)
{
float width = 2 * near * tan(fov * 0.5);
float height = width/ratio;
setupProjectionPerspective(view, -width/2, width/2, height/2, -height/2, near, far);
}
void Frustum::setupFromMatrix(const kmMat4 &view, const kmMat4 &projection)
{
kmMat4 mvp;
kmMat4Multiply(&mvp, &projection, &view);
kmMat4ExtractPlane(&_frustumPlanes[FrustumPlane::NEAR], &mvp, KM_PLANE_NEAR);
kmMat4ExtractPlane(&_frustumPlanes[FrustumPlane::FAR], &mvp, KM_PLANE_FAR);
kmMat4ExtractPlane(&_frustumPlanes[FrustumPlane::LEFT], &mvp, KM_PLANE_LEFT);
kmMat4ExtractPlane(&_frustumPlanes[FrustumPlane::RIGHT], &mvp, KM_PLANE_RIGHT);
kmMat4ExtractPlane(&_frustumPlanes[FrustumPlane::BOTTOM], &mvp, KM_PLANE_BOTTOM);
kmMat4ExtractPlane(&_frustumPlanes[FrustumPlane::TOP], &mvp, KM_PLANE_TOP);
}
Frustum::IntersectResult Frustum::intersectPoint(const kmVec3 &point) const
{
int indexFirst = static_cast<int>(FrustumPlane::NEAR);
int indexNumber = static_cast<int>(FrustumPlane::NUMBER);
for(int planeIndex = indexFirst; planeIndex < indexNumber; ++planeIndex)
{
if(kmPlaneDotCoord(&_frustumPlanes[static_cast<FrustumPlane>(planeIndex)], &point) < 0)
return IntersectResult::OUTSIDE;
}
return IntersectResult::INSIDE;
}
Frustum::IntersectResult Frustum::intersectAABB(const AABB& aabb) const
{
IntersectResult result = IntersectResult::INSIDE;
int indexFirst = static_cast<int>(FrustumPlane::NEAR);
int indexNumber = static_cast<int>(FrustumPlane::NUMBER);
for(int planeIndex = indexFirst; planeIndex < indexNumber; ++planeIndex)
{
kmPlane plane = _frustumPlanes[static_cast<FrustumPlane>(planeIndex)];
kmVec3 normal = {plane.a, plane.b, plane.c};
kmVec3Normalize(&normal, &normal);
kmVec3 positivePoint = aabb.getPositivePoint(normal);
kmVec3 negativePoint = aabb.getNegativePoint(normal);
if(kmPlaneDotCoord(&plane, &positivePoint) < 0)
return IntersectResult::OUTSIDE;
if(kmPlaneDotCoord(&plane, &negativePoint) < 0)
result = IntersectResult::INTERSECT;
}
return result;
}
Frustum::IntersectResult Frustum::intersectSphere(const kmVec3& center, float radius) const
{
IntersectResult result = IntersectResult::INSIDE;
int indexFirst = static_cast<int>(FrustumPlane::NEAR);
int indexNumber = static_cast<int>(FrustumPlane::NUMBER);
for(int planeIndex = indexFirst; planeIndex < indexNumber; ++planeIndex)
{
kmPlane plane = _frustumPlanes[static_cast<FrustumPlane>(planeIndex)];
kmVec3 normal = {plane.a, plane.b, plane.c};
float distance = kmPlaneDotCoord(&plane, &center);
distance = distance / kmVec3Length(&normal);
if(distance < -radius) return IntersectResult::OUTSIDE;
if(distance <= radius && distance >= -radius) result = IntersectResult::INTERSECT;
}
return result;
}
NS_CC_END

View File

@ -0,0 +1,96 @@
#ifndef __CC_FRUSTUM_H__
#define __CC_FRUSTUM_H__
#include "CCPlatformMacros.h"
#include "math/kazmath/include/kazmath/kazmath.h"
NS_CC_BEGIN
class ViewTransform
{
public:
ViewTransform();
~ViewTransform();
void Init(const kmVec3& pos, const kmVec3& focus, const kmVec3& up);
const kmVec3& getPosition() const { return _position; }
const kmVec3& getFocus() const { return _focus; }
const kmVec3& getDirection() const;
const kmVec3& getRight() const;
const kmVec3& getUp() const;
private:
void LazyAdjust() const;
private:
kmVec3 _position;
kmVec3 _focus;
kmVec3 _up;
mutable bool _dirty;
mutable kmMat4 _matrix;
mutable kmVec3 _adjustDir;
mutable kmVec3 _adjustRight;
mutable kmVec3 _adjustUp;
};
class AABB
{
public:
AABB(const kmVec3& min, const kmVec3& max);
~AABB();
kmVec3 getCenter() const;
float getDimensionX() const;
float getDimensionY() const;
float getDimensionZ() const;
kmVec3 getPositivePoint(const kmVec3& direction) const;
kmVec3 getNegativePoint(const kmVec3& direction) const;
const AABB& expand(const kmVec3& point);
private:
kmVec3 _min;
kmVec3 _max;
};
class Frustum
{
public:
enum class IntersectResult
{
OUTSIDE = 0,
INTERSECT = 1,
INSIDE = 2
};
public:
Frustum();
~Frustum();
void setupProjectionOrthogonal(const ViewTransform& view, float width, float height, float near, float far);
void setupProjectionPerspective(const ViewTransform& view, float left, float right, float top, float bottom, float near, float far);
void setupProjectionPerspectiveFov(const ViewTransform& view, float fov, float ratio, float near, float far);
void setupFromMatrix(const kmMat4& view, const kmMat4& projection);
IntersectResult intersectPoint(const kmVec3& point) const;
IntersectResult intersectAABB(const AABB& aabb) const;
IntersectResult intersectSphere(const kmVec3& center, float radius) const;
private:
enum FrustumPlane
{
NEAR = 0,
FAR = 1,
BOTTOM = 2,
TOP = 3,
LEFT = 4,
RIGHT = 5,
NUMBER = 6
};
kmPlane _frustumPlanes[FrustumPlane::NUMBER];
};
NS_CC_END
#endif

View File

@ -21,6 +21,7 @@ static std::function<Layer*()> createFunctions[] =
CL(NewSpriteBatchTest),
CL(NewClippingNodeTest),
CL(NewDrawNodeTest),
CL(NewCullingTest),
};
#define MAX_LAYER (sizeof(createFunctions) / sizeof(createFunctions[0]))
@ -401,3 +402,71 @@ string NewDrawNodeTest::subtitle()
{
return "DrawNode";
}
NewCullingTest::NewCullingTest()
{
auto s = Director::getInstance()->getWinSize();
std::vector<string> images;
images.push_back("Images/grossini_dance_01.png");
images.push_back("Images/grossini_dance_02.png");
images.push_back("Images/grossini_dance_03.png");
images.push_back("Images/grossini_dance_04.png");
images.push_back("Images/grossini_dance_05.png");
images.push_back("Images/grossini_dance_06.png");
images.push_back("Images/grossini_dance_07.png");
images.push_back("Images/grossini_dance_08.png");
images.push_back("Images/grossini_dance_09.png");
images.push_back("Images/grossini_dance_10.png");
images.push_back("Images/grossini_dance_11.png");
images.push_back("Images/grossini_dance_12.png");
images.push_back("Images/grossini_dance_13.png");
images.push_back("Images/grossini_dance_14.png");
images.push_back("Images/grossini.png");
auto parent = Node::create();
parent->setPosition(s.width/2, s.height/2);
addChild(parent);
for(int index = 0; index < 500; ++index)
{
auto parent2 = Node::create();
parent2->setPosition(0,0);
parent->addChild(parent2);
parent2->setPosition(-50,0);
parent2->runAction(RepeatForever::create((JumpBy::create(10, Point(0,0), 400, 1))));
NewSprite* sprite = NewSprite::create(images[index % images.size()].c_str());
sprite->setPosition(Point(0,0));
//sprite->runAction(RepeatForever::create(RotateBy::create(3, 360)));
sprite->runAction(RepeatForever::create(Sequence::createWithTwoActions(ScaleBy::create(2, 2), ScaleBy::create(2,0.5))));
parent2->addChild(sprite);
}
for(int index = 0; index < 500; ++index)
{
auto parent2 = Node::create();
parent->addChild(parent2);
parent2->setPosition(50,0);
parent2->runAction(RepeatForever::create((JumpBy::create(7, Point(0,0), 400, 1))));
NewSprite* sprite = NewSprite::create(images[index % images.size()].c_str());
sprite->setPosition(Point(0,0));
//sprite->runAction(RepeatForever::create(RotateBy::create(3, 360)));
sprite->runAction(RepeatForever::create(Sequence::createWithTwoActions(ScaleBy::create(2, 2), ScaleBy::create(2,0.5))));
parent2->addChild(sprite);
}
}
NewCullingTest::~NewCullingTest()
{
}
string NewCullingTest::title()
{
return "New Render";
}
string NewCullingTest::subtitle()
{
return "Culling";
}

View File

@ -107,4 +107,17 @@ protected:
virtual ~NewDrawNodeTest();
};
class NewCullingTest : public MultiSceneTest
{
public:
CREATE_FUNC(NewCullingTest)
virtual string title();
virtual string subtitle();
protected:
NewCullingTest();
virtual ~NewCullingTest();
};
#endif //__NewRendererTest_H_