Add lua bindings for Terrain and two test cases about it.

This commit is contained in:
samuele3hu 2015-04-08 10:03:50 +08:00
parent 4bd304da80
commit 3a2601a1f8
7 changed files with 707 additions and 18 deletions

View File

@ -38,6 +38,8 @@
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
1502702D1AD3BDBC0089CD03 /* TerrainTest in Resources */ = {isa = PBXBuildFile; fileRef = B603F1B31AC8FBFB00A9579C /* TerrainTest */; };
1502702E1AD3BDC90089CD03 /* TerrainTest in Resources */ = {isa = PBXBuildFile; fileRef = B603F1B31AC8FBFB00A9579C /* TerrainTest */; };
150F918819DA409E00B89F57 /* lua_test_bindings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 150F918619DA409E00B89F57 /* lua_test_bindings.cpp */; };
150F918919DA409F00B89F57 /* lua_test_bindings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 150F918619DA409E00B89F57 /* lua_test_bindings.cpp */; };
15427B79198B879900DC375D /* libluacocos2d iOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 15EFA665198B33EE000C57D3 /* libluacocos2d iOS.a */; };
@ -4376,6 +4378,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
1502702E1AD3BDC90089CD03 /* TerrainTest in Resources */,
157B08EC1A90864100B7BEA4 /* Particle3D in Resources */,
15B13E5219F0FD4D008A1ADC /* Manifests in Resources */,
156EAE071977D0BD00F53709 /* ActionTimeline in Resources */,
@ -4421,6 +4424,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
1502702D1AD3BDBC0089CD03 /* TerrainTest in Resources */,
157B08ED1A90865600B7BEA4 /* Particle3D in Resources */,
15B3709A19EE5EED00ABE682 /* Manifests in Resources */,
15AECE0F195C1FDD00907DB0 /* cocosvideo.mp4 in Resources */,

View File

@ -116,7 +116,7 @@ tolua_lerror:
return 0;
}
int lua_cocos2dx_3d_Sprite3D_createAsync(lua_State* tolua_S)
int lua_cocos2dx_3d_Sprite3D_createAsync(lua_State* L)
{
int argc = 0;
bool ok = true;
@ -125,39 +125,39 @@ int lua_cocos2dx_3d_Sprite3D_createAsync(lua_State* tolua_S)
#endif
#if COCOS2D_DEBUG >= 1
if (!tolua_isusertable(tolua_S,1,"cc.Sprite3D",0,&tolua_err)) goto tolua_lerror;
if (!tolua_isusertable(L,1,"cc.Sprite3D",0,&tolua_err)) goto tolua_lerror;
#endif
argc = lua_gettop(tolua_S)-1;
argc = lua_gettop(L)-1;
do
{
if (argc == 3)
{
std::string modelPath;
ok &= luaval_to_std_string(tolua_S, 2,&modelPath, "cc.Sprite3D:createAsync");
ok &= luaval_to_std_string(L, 2,&modelPath, "cc.Sprite3D:createAsync");
if (!ok)
break;
std::string texturePath;
ok &= luaval_to_std_string(tolua_S, 3,&texturePath, "cc.Sprite3D:createAsync");
ok &= luaval_to_std_string(L, 3,&texturePath, "cc.Sprite3D:createAsync");
if (!ok)
break;
#if COCOS2D_DEBUG >= 1
if (!toluafix_isfunction(tolua_S,4,"LUA_FUNCTION",0,&tolua_err)) {
if (!toluafix_isfunction(L,4,"LUA_FUNCTION",0,&tolua_err)) {
goto tolua_lerror;
}
#endif
LUA_FUNCTION handler = toluafix_ref_function(tolua_S,4,0);
LUA_FUNCTION handler = toluafix_ref_function(L,4,0);
cocos2d::Sprite3D::createAsync(modelPath, texturePath, [=](cocos2d::Sprite3D* sprite, void* callbackparam){
int id = (sprite) ? (int)sprite->_ID : -1;
int* luaID = (sprite) ? &sprite->_luaID : nullptr;
toluafix_pushusertype_ccobject(tolua_S, id, luaID, (void*)sprite,"cc.Sprite3D");
toluafix_pushusertype_ccobject(L, id, luaID, (void*)sprite,"cc.Sprite3D");
LuaEngine::getInstance()->getLuaStack()->executeFunctionByHandler(handler, 1);
}, nullptr);
lua_settop(tolua_S, 1);
lua_settop(L, 1);
return 1;
}
} while (0);
@ -167,34 +167,34 @@ int lua_cocos2dx_3d_Sprite3D_createAsync(lua_State* tolua_S)
if (argc == 2)
{
std::string modelPath;
ok &= luaval_to_std_string(tolua_S, 2,&modelPath, "cc.Sprite3D:createAsync");
ok &= luaval_to_std_string(L, 2,&modelPath, "cc.Sprite3D:createAsync");
if (!ok)
break;
#if COCOS2D_DEBUG >= 1
if (!toluafix_isfunction(tolua_S, 3, "LUA_FUNCTION", 0, &tolua_err)) {
if (!toluafix_isfunction(L, 3, "LUA_FUNCTION", 0, &tolua_err)) {
goto tolua_lerror;
}
#endif
LUA_FUNCTION handler = toluafix_ref_function(tolua_S, 3, 0);
LUA_FUNCTION handler = toluafix_ref_function(L, 3, 0);
cocos2d::Sprite3D::createAsync(modelPath, [=](cocos2d::Sprite3D* sprite, void* callbackparam){
int id = (sprite) ? (int)sprite->_ID : -1;
int* luaID = (sprite) ? &sprite->_luaID : nullptr;
toluafix_pushusertype_ccobject(tolua_S, id, luaID, (void*)sprite,"cc.Sprite3D");
toluafix_pushusertype_ccobject(L, id, luaID, (void*)sprite,"cc.Sprite3D");
LuaEngine::getInstance()->getLuaStack()->executeFunctionByHandler(handler, 1);
}, nullptr);
lua_settop(tolua_S, 1);
lua_settop(L, 1);
return 1;
}
} while (0);
ok = true;
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "cc.Sprite3D:createAsync",argc, 3);
luaL_error(L, "%s has wrong number of arguments: %d, was expecting %d", "cc.Sprite3D:createAsync",argc, 3);
return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'lua_cocos2dx_3d_Sprite3D_createAsync'.",&tolua_err);
tolua_error(L,"#ferror in function 'lua_cocos2dx_3d_Sprite3D_createAsync'.",&tolua_err);
#endif
return 0;
}
@ -212,12 +212,327 @@ static void extendSprite3D(lua_State* L)
lua_pop(L, 1);
}
bool luaval_to_terraindata(lua_State* L, int lo, cocos2d::Terrain::TerrainData* outValue , const char* funcName = "")
{
if (nullptr == L || nullptr == outValue)
return false;
bool ok = true;
tolua_Error tolua_err;
if (!tolua_istable(L, lo, 0, &tolua_err))
{
#if COCOS2D_DEBUG >=1
luaval_to_native_err(L,"#ferror:",&tolua_err,funcName);
ok = false;
#endif
}
if (ok)
{
lua_pushstring(L, "chunkSize");
lua_gettable(L,lo);
if (!lua_isnil(L, -1))
{
luaval_to_size(L, -1, &(outValue->chunkSize));
}
else
{
outValue->chunkSize = cocos2d::Size(32, 32);
}
lua_pop(L, 1);
lua_pushstring(L, "heightMapSrc");
lua_gettable(L,lo);
outValue->heightMapSrc = tolua_tocppstring(L, -1, "");
lua_pop(L,1);
lua_pushstring(L, "alphaMapSrc");
lua_gettable(L,lo);
outValue->alphaMapSrc = const_cast<char*>(tolua_tocppstring(L, -1, ""));
lua_pop(L,1);
lua_pushstring(L, "detailMaps");
lua_gettable(L,lo);
if (lua_istable(L, -1))
{
size_t len = lua_objlen(L, -1);
for (size_t i = 0; i < len; i++)
{
lua_pushnumber(L,i + 1);
lua_gettable(L,-2);
if (lua_istable(L, -1))
{
lua_pushstring(L, "detailMapSrc");
lua_gettable(L,-2);
outValue->detailMaps[i].detailMapSrc = tolua_tocppstring(L, -1, "");
lua_pop(L,1);
lua_pushstring(L, "detailMapSize");
lua_gettable(L,-2);
outValue->detailMaps[i].detailMapSize = lua_isnil(L,-1) ? 0.0f : (float)lua_tonumber(L,-1);
lua_pop(L,1);
}
lua_pop(L, 1);
}
}
lua_pop(L,1);
lua_pushstring(L, "mapHeight");
lua_gettable(L,lo);
outValue->mapHeight = lua_isnil(L,-1) ? 2.0f : (float)lua_tonumber(L,-1);
lua_pop(L,1);
lua_pushstring(L, "mapScale");
lua_gettable(L,lo);
outValue->mapScale = lua_isnil(L,-1) ? 0.1f : (float)lua_tonumber(L,-1);
lua_pop(L,1);
lua_pushstring(L, "_detailMapAmount");
lua_gettable(L,lo);
outValue->_detailMapAmount = lua_isnil(L,-1) ? 0 : (int)lua_tonumber(L,-1);
lua_pop(L,1);
lua_pushstring(L, "skirtHeightRatio");
lua_gettable(L,lo);
outValue->skirtHeightRatio = lua_isnil(L,-1) ? 1.0f : (float)lua_tonumber(L,-1);
lua_pop(L,1);
}
return ok;
}
void terraindata_to_luaval(lua_State* L,const cocos2d::Terrain::TerrainData& inValue)
{
if (nullptr == L)
return;
lua_newtable(L);
lua_pushstring(L, "chunkSize");
size_to_luaval(L, inValue.chunkSize);
lua_rawset(L, -3);
if (inValue.heightMapSrc.length() > 0)
{
lua_pushstring(L, "heightMapSrc");
lua_pushstring(L, inValue.heightMapSrc.c_str());
lua_rawset(L, -3);
}
if (nullptr != inValue.alphaMapSrc)
{
lua_pushstring(L, "alphaMapSrc");
lua_pushstring(L, inValue.alphaMapSrc);
lua_rawset(L, -3);
}
lua_pushstring(L, "detailMaps");
lua_newtable(L);
for (int i = 0; i < 4; i++)
{
lua_pushnumber(L, (lua_Number) i + 1);
lua_newtable(L);
lua_pushstring(L, "detailMapSrc");
lua_pushstring(L, inValue.detailMaps[i].detailMapSrc.c_str());
lua_rawset(L, -3);
lua_pushstring(L, "detailMapSize");
lua_pushnumber(L, (lua_Number)inValue.detailMaps[i].detailMapSize);
lua_rawset(L, -3);
lua_rawset(L, -3);
}
lua_rawset(L, -3);
lua_pushstring(L, "mapHeight");
lua_pushnumber(L, (lua_Number)inValue.mapHeight);
lua_rawset(L, -3);
lua_pushstring(L, "mapScale");
lua_pushnumber(L, (lua_Number)inValue.mapScale);
lua_rawset(L, -3);
lua_pushstring(L, "_detailMapAmount");
lua_pushnumber(L, (lua_Number)inValue._detailMapAmount);
lua_rawset(L, -3);
lua_pushstring(L, "skirtHeightRatio");
lua_pushnumber(L, (lua_Number)inValue.skirtHeightRatio);
lua_rawset(L, -3);
}
int lua_cocos2dx_3d_Terrain_create(lua_State* L)
{
int argc = 0;
bool ok = true;
#if COCOS2D_DEBUG >= 1
tolua_Error tolua_err;
#endif
#if COCOS2D_DEBUG >= 1
if (!tolua_isusertable(L,1,"cc.Terrain",0,&tolua_err)) goto tolua_lerror;
#endif
argc = lua_gettop(L) - 1;
if (argc == 1)
{
cocos2d::Terrain::TerrainData arg0;
ok &= luaval_to_terraindata(L, 2, &arg0);
if(!ok)
{
tolua_error(L,"invalid arguments in function 'lua_cocos2dx_3d_Terrain_create'", nullptr);
return 0;
}
cocos2d::Terrain* ret = cocos2d::Terrain::create(arg0);
object_to_luaval<cocos2d::Terrain>(L, "cc.Terrain",(cocos2d::Terrain*)ret);
return 1;
}
if (argc == 2)
{
cocos2d::Terrain::TerrainData arg0;
cocos2d::Terrain::CrackFixedType arg1;
ok &= luaval_to_terraindata(L, 2, &arg0);
ok &= luaval_to_int32(L, 3,(int *)&arg1, "cc.Terrain:create");
if(!ok)
{
tolua_error(L,"invalid arguments in function 'lua_cocos2dx_3d_Terrain_create'", nullptr);
return 0;
}
cocos2d::Terrain* ret = cocos2d::Terrain::create(arg0, arg1);
object_to_luaval<cocos2d::Terrain>(L, "cc.Terrain",(cocos2d::Terrain*)ret);
return 1;
}
luaL_error(L, "%s has wrong number of arguments: %d, was expecting %d\n ", "cc.Terrain:create",argc, 1);
return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(L,"#ferror in function 'lua_cocos2dx_3d_Terrain_create'.",&tolua_err);
#endif
return 0;
}
int lua_cocos2dx_3d_Terrain_getHeight(lua_State* L)
{
int argc = 0;
cocos2d::Terrain* cobj = nullptr;
bool ok = true;
#if COCOS2D_DEBUG >= 1
tolua_Error tolua_err;
#endif
#if COCOS2D_DEBUG >= 1
if (!tolua_isusertype(L,1,"cc.Terrain",0,&tolua_err)) goto tolua_lerror;
#endif
cobj = (cocos2d::Terrain*)tolua_tousertype(L,1,0);
#if COCOS2D_DEBUG >= 1
if (!cobj)
{
tolua_error(L,"invalid 'cobj' in function 'lua_cocos2dx_3d_Terrain_getHeight'", nullptr);
return 0;
}
#endif
argc = lua_gettop(L)-1;
do{
if (argc == 1) {
cocos2d::Vec2 arg0;
ok &= luaval_to_vec2(L, 2, &arg0, "cc.Terrain:getHeight");
if (!ok) { break; }
double ret = cobj->getHeight(arg0);
tolua_pushnumber(L,(lua_Number)ret);
return 1;
}
}while(0);
ok = true;
do{
if (argc == 2) {
cocos2d::Vec2 arg0;
ok &= luaval_to_vec2(L, 2, &arg0, "cc.Terrain:getHeight");
if (!ok) { break; }
cocos2d::Vec3* arg1;
ok &= luaval_to_object<cocos2d::Vec3>(L, 3, "cc.Vec3",&arg1);
if (!ok) { break; }
double ret = cobj->getHeight(arg0, arg1);
tolua_pushnumber(L,(lua_Number)ret);
vec3_to_luaval(L, *arg1);
return 2;
}
}while(0);
ok = true;
do{
if (argc == 2) {
double arg0;
ok &= luaval_to_number(L, 2,&arg0, "cc.Terrain:getHeight");
if (!ok) { break; }
double arg1;
ok &= luaval_to_number(L, 3,&arg1, "cc.Terrain:getHeight");
if (!ok) { break; }
double ret = cobj->getHeight(arg0, arg1);
tolua_pushnumber(L,(lua_Number)ret);
return 1;
}
}while(0);
ok = true;
do{
if (argc == 3) {
double arg0;
ok &= luaval_to_number(L, 2,&arg0, "cc.Terrain:getHeight");
if (!ok) { break; }
double arg1;
ok &= luaval_to_number(L, 3,&arg1, "cc.Terrain:getHeight");
if (!ok) { break; }
cocos2d::Vec3 arg2;
ok &= luaval_to_vec3(L, 4, &arg2);
if (!ok) { break; }
double ret = cobj->getHeight(arg0, arg1, &arg2);
tolua_pushnumber(L,(lua_Number)ret);
vec3_to_luaval(L, arg2);
return 2;
}
}while(0);
ok = true;
luaL_error(L, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Terrain:getHeight",argc, 2);
return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(L,"#ferror in function 'lua_cocos2dx_3d_Terrain_getHeight'.",&tolua_err);
#endif
return 0;
}
static void extendTerrain(lua_State* L)
{
lua_pushstring(L, "cc.Terrain");
lua_rawget(L, LUA_REGISTRYINDEX);
if (lua_istable(L,-1))
{
tolua_function(L, "create", lua_cocos2dx_3d_Terrain_create);
tolua_function(L, "getHeight", lua_cocos2dx_3d_Terrain_getHeight);
}
lua_pop(L, 1);
}
static int register_all_cocos2dx_3d_manual(lua_State* L)
{
if (nullptr == L)
return 0;
extendSprite3D(L);
extendTerrain(L);
return 0;
}

View File

@ -0,0 +1,9 @@
if nil == cc.Terrain then
return
end
cc.Terrain.CrackFixedType =
{
SKIRT = 0,
INCREASE_LOWER = 1,
}

View File

@ -441,6 +441,22 @@ function cc.quaternion(_x, _y ,_z,_w)
return { x = _x, y = _y, z = _z, w = _w }
end
function cc.quaternion_createFromAxisAngle(axis, angle)
local halfAngle = angle * 0.5
local sinHalfAngle = math.sin(halfAngle)
local normal = cc.vec3(axis.x, axis.y, axis.z)
normal = cc.vec3normalize(normal)
local dst = cc.vec3(0.0, 0.0, 0.0)
dst.x = normal.x * sinHalfAngle
dst.y = normal.y * sinHalfAngle
dst.z = normal.z * sinHalfAngle
dst.w = math.cos(halfAngle)
return dst
end
function cc.blendFunc(_src, _dst)
return {src = _src, dst = _dst}
end

View File

@ -0,0 +1,342 @@
require "cocos.3d.3dConstants"
----------------------------------------
----TerrainSimple
----------------------------------------
local TerrainSimple = class("TerrainSimple", function ()
local layer = cc.Layer:create()
Helper.initWithLayer(layer)
return layer
end)
function TerrainSimple:ctor()
-- body
self:init()
end
function TerrainSimple:init()
Helper.titleLabel:setString(self:title())
Helper.subtitleLabel:setString(self:subtitle())
local visibleSize = cc.Director:getInstance():getVisibleSize()
--use custom camera
self._camera = cc.Camera:createPerspective(60, visibleSize.width/visibleSize.height, 0.1, 800)
self._camera:setCameraFlag(cc.CameraFlag.USER1)
self:addChild(self._camera)
local detailMapR = { detailMapSrc = "TerrainTest/dirt.dds", detailMapSize = 35}
local detailMapG = { detailMapSrc = "TerrainTest/Grass2.dds", detailMapSize = 35}
local detailMapB = { detailMapSrc = "TerrainTest/road.dds", detailMapSize = 35}
local detailMapA = { detailMapSrc = "TerrainTest/GreenSkin.jpg", detailMapSize = 35}
local terrainData = { heightMapSrc = "TerrainTest/heightmap16.jpg", alphaMapSrc = "TerrainTest/alphamap.png" , detailMaps = {detailMapR, detailMapG, detailMapB, detailMapA}, _detailMapAmount = 4 }
self._terrain = cc.Terrain:create(terrainData,cc.Terrain.CrackFixedType.SKIRT)
self._terrain:setLODDistance(1000.2, 6.4, 9.6)
self._terrain:setMaxDetailMapAmount(4)
self:addChild(self._terrain)
self._terrain:setCameraMask(2)
self._terrain:setDrawWire(false)
local listener = cc.EventListenerTouchAllAtOnce:create()
listener:registerScriptHandler(function (touches, event)
local delta = cc.Director:getInstance():getDeltaTime()
local touch = touches[1]
local location = touch:getLocation()
local previousLocation = touch:getPreviousLocation()
local newPos = {x=previousLocation.x - location.x, y=previousLocation.y - location.y}
local matTransform = self:getNodeToWorldTransform()
local cameraDir = {x = -matTransform[9], y = -matTransform[10], z = -matTransform[11]}
cameraDir = cc.vec3normalize(cameraDir)
cameraDir.y = 0
local cameraRightDir = {x = matTransform[1], y = matTransform[2], z = matTransform[3]}
cameraRightDir = cc.vec3normalize(cameraRightDir)
cameraRightDir.y = 0
local cameraPos = self._camera:getPosition3D()
cameraPos = { x = cameraPos.x + cameraDir.x * newPos.y * 0.5 * delta, y = cameraPos.y + cameraDir.y * newPos.y * 0.5 * delta, z = cameraPos.z + cameraDir.z * newPos.y * 0.5 * delta }
cameraPos = { x = cameraPos.x + cameraRightDir.x * newPos.x * 0.5 * delta, y = cameraPos.y + cameraRightDir.y * newPos.x * 0.5 * delta, z = cameraPos.z + cameraRightDir.z * newPos.x * 0.5 * delta }
self._camera:setPosition3D(cameraPos)
end,cc.Handler.EVENT_TOUCHES_MOVED)
local eventDispatcher = self:getEventDispatcher()
eventDispatcher:addEventListenerWithSceneGraphPriority(listener, self)
end
function TerrainSimple:title()
return "Terrain with skirt"
end
function TerrainSimple:subtitle()
return "Drag to walkThru"
end
----------------------------------------
----TerrainWalkThru
----------------------------------------
local PLAER_STATE =
{
LEFT = 0,
RIGHT = 1,
IDLE = 2,
FORWARD = 3,
BACKWARD = 4,
}
local PLAYER_HEIGHT = 0
local camera_offset = cc.vec3(0, 45, 60)
local Player = class("Player", function(file, cam, terrain)
local sprite = cc.Sprite3D:create(file)
if nil ~= sprite then
sprite._headingAngle = 0
sprite._playerState = PLAER_STATE.IDLE
sprite._cam = cam
sprite._terrain = terrain
end
return sprite
end)
function Player:ctor()
-- body
self:init()
end
function Player:init()
self._headingAxis = cc.vec3(0.0, 0.0, 0.0)
self:scheduleUpdateWithPriorityLua(function(dt)
local curPos = self:getPosition3D()
if self._playerState == PLAER_STATE.IDLE then
elseif self._playerState == PLAER_STATE.FORWARD then
local newFaceDir = cc.vec3( self._targetPos.x - curPos.x, self._targetPos.y - curPos.y, self._targetPos.z - curPos.z)
newFaceDir.y = 0.0
newFaceDir = cc.vec3normalize(newFaceDir)
local offset = cc.vec3(newFaceDir.x * 25.0 * dt, newFaceDir.y * 25.0 * dt, newFaceDir.z * 25.0 * dt)
curPos = cc.vec3(curPos.x + offset.x, curPos.y + offset.y, curPos.z + offset.z)
self:setPosition3D(curPos)
elseif self._playerState == PLAER_STATE.BACKWARD then
local transform = self:getNodeToWorldTransform()
local forward_vec = cc.vec3(-transform[9], -transform[10], -transform[11])
forward_vec = cc.vec3normalize(forward_vec)
self:setPosition3D(cc.vec3(curPos.x - forward_vec.x * 15 * dt, curPos.y - forward_vec.y * 15 * dt, curPos.z - forward_vec.z * 15 *dt))
elseif self._playerState == PLAER_STATE.LEFT then
player:setRotation3D(cc.vec3(curPos.x, curPos.y + 25 * dt, curPos.z))
elseif self._playerState == PLAER_STATE.RIGHT then
player:setRotation3D(cc.vec3(curPos.x, curPos.y - 25 * dt, curPos.z))
end
local normal = cc.vec3(0.0, 0.0, 0.0)
local player_h, normal = self._terrain:getHeight(self:getPositionX(), self:getPositionZ(), normal)
self:setPositionY(player_h + PLAYER_HEIGHT)
--need to scriptfile
local q2 = cc.quaternion_createFromAxisAngle(cc.vec3(0, 1, 0), -math.pi)
local headingQ = cc.quaternion_createFromAxisAngle(self._headingAxis, self._headingAngle)
local x = headingQ.w * q2.x + headingQ.x * q2.w + headingQ.y * q2.z - headingQ.z * q2.y
local y = headingQ.w * q2.y - headingQ.x * q2.z + headingQ.y * q2.w + headingQ.z * q2.x
local z = headingQ.w * q2.z + headingQ.x * q2.y - headingQ.y * q2.x + headingQ.z * q2.w
local w = headingQ.w * q2.w - headingQ.x * q2.x - headingQ.y * q2.y - headingQ.z * q2.z
headingQ = cc.quaternion(x, y, z, w)
self:setRotationQuat(headingQ)
local vec_offset = cc.vec4(camera_offset.x, camera_offset.y, camera_offset.z, 1)
local transform = self:getNodeToWorldTransform()
local dst = cc.vec4(0.0, 0.0, 0.0, 0.0)
vec_offset = mat4_transformVector(transform, vec_offset, dst)
local playerPos = self:getPosition3D()
self._cam:setPosition3D(cc.vec3(playerPos.x + camera_offset.x, playerPos.y + camera_offset.y, playerPos.z + camera_offset.z))
self:updateState()
end, 0)
self:registerScriptHandler(function (event)
-- body
if "exit" == event then
self:unscheduleUpdate()
end
end)
end
function Player:updateState()
if self._playerState == PLAER_STATE.FORWARD then
local player_pos = cc.p(self:getPositionX(),self:getPositionZ())
local targetPos = cc.p(self._targetPos.x, self._targetPos.z)
local dist = cc.pGetDistance(player_pos, targetPos)
if dist < 1 then
self._playerState = PLAER_STATE.IDLE
end
end
end
local TerrainWalkThru = class("TerrainWalkThru", function ()
local layer = cc.Layer:create()
Helper.initWithLayer(layer)
return layer
end)
function TerrainWalkThru:ctor()
-- body
self:init()
end
function TerrainWalkThru:init()
Helper.titleLabel:setString(self:title())
Helper.subtitleLabel:setString(self:subtitle())
local listener = cc.EventListenerTouchAllAtOnce:create()
listener:registerScriptHandler(function (touches, event)
end,cc.Handler.EVENT_TOUCHES_BEGAN)
listener:registerScriptHandler(function (touches, event)
local delta = cc.Director:getInstance():getDeltaTime()
local touch = touches[1]
local location = touch:getLocation()
local previousLocation = touch:getPreviousLocation()
local newPos = cc.p(previousLocation.x - location.x, previousLocation.y - location.y)
local matTransform = self._camera:getNodeToWorldTransform()
local cameraDir = {x = -matTransform[9], y = -matTransform[10], z = -matTransform[11]}
cameraDir = cc.vec3normalize(cameraDir)
cameraDir.y = 0
local cameraRightDir = {x = matTransform[1], y = matTransform[2], z = matTransform[3]}
cameraRightDir = cc.vec3normalize(cameraRightDir)
cameraRightDir.y = 0
local cameraPos = self._camera:getPosition3D()
cameraPos = { x = cameraPos.x + cameraDir.x * newPos.y * 0.5 * delta, y = cameraPos.y + cameraDir.y * newPos.y * 0.5 * delta, z = cameraPos.z + cameraDir.z * newPos.y * 0.5 * delta }
cameraPos = { x = cameraPos.x + cameraRightDir.x * newPos.x * 0.5 * delta, y = cameraPos.y + cameraRightDir.y * newPos.x * 0.5 * delta, z = cameraPos.z + cameraRightDir.z * newPos.x * 0.5 * delta }
self._camera:setPosition3D(cameraPos)
end,cc.Handler.EVENT_TOUCHES_MOVED)
listener:registerScriptHandler(function (touches, event)
local touch = touches[1]
local location = touch:getLocationInView()
if self._camera ~= nil then
if self._player ~= nil then
local nearP = cc.vec3(location.x, location.y, 0.0)
local farP = cc.vec3(location.x, location.y, 1.0)
local size = cc.Director:getInstance():getWinSize()
nearP = self._camera:unproject(size, nearP, nearP)
farP = self._camera:unproject(size, farP, farP)
local dir = cc.vec3(farP.x - nearP.x, farP.y - nearP.y, farP.z - nearP.z)
dir = cc.vec3normalize(dir)
local rayStep = cc.vec3(15 * dir.x, 15 * dir.y, 15 * dir.z)
local rayPos = nearP
local rayStartPosition = nearP
local lastRayPosition = rayPos
rayPos = cc.vec3(rayPos.x + rayStep.x, rayPos.y + rayStep.y, rayPos.z + rayStep.z)
-- Linear search - Loop until find a point inside and outside the terrain Vector3
local height = self._terrain:getHeight(rayPos.x, rayPos.z)
while rayPos.y > height do
lastRayPosition = rayPos
rayPos = cc.vec3(rayPos.x + rayStep.x, rayPos.y + rayStep.y, rayPos.z + rayStep.z)
height = self._terrain:getHeight(rayPos.x,rayPos.z)
end
local startPosition = lastRayPosition
local endPosition = rayPos
for i = 1, 32 do
-- Binary search pass
local middlePoint = cc.vec3(0.5 * (startPosition.x + endPosition.x), 0.5 * (startPosition.y + endPosition.y), 0.5 * (startPosition.z + endPosition.z))
if (middlePoint.y < height) then
endPosition = middlePoint
else
startPosition = middlePoint
end
end
local collisionPoint = cc.vec3(0.5 * (startPosition.x + endPosition.x), 0.5 * (startPosition.y + endPosition.y), 0.5 * (startPosition.z + endPosition.z))
local playerPos = self._player:getPosition3D()
dir = cc.vec3(collisionPoint.x - playerPos.x, collisionPoint.y - playerPos.y, collisionPoint.z - playerPos.z)
dir.y = 0
dir = cc.vec3normalize(dir)
self._player._headingAngle = -1 * math.acos(-dir.z)
self._player._headingAxis = vec3_cross(dir, cc.vec3(0, 0, -1), self._player._headingAxis)
self._player._targetPos = collisionPoint
-- self._player:forward()
self._player._playerState = PLAER_STATE.FORWARD
end
end
end,cc.Handler.EVENT_TOUCHES_ENDED)
local eventDispatcher = self:getEventDispatcher()
eventDispatcher:addEventListenerWithSceneGraphPriority(listener, self)
local visibleSize = cc.Director:getInstance():getVisibleSize()
self._camera = cc.Camera:createPerspective(60, visibleSize.width/visibleSize.height, 0.1, 200)
self._camera:setCameraFlag(cc.CameraFlag.USER1)
self:addChild(self._camera)
local detailMapR = { detailMapSrc = "TerrainTest/dirt.dds", detailMapSize = 35}
local detailMapG = { detailMapSrc = "TerrainTest/Grass2.dds", detailMapSize = 10}
local detailMapB = { detailMapSrc = "TerrainTest/road.dds", detailMapSize = 35}
local detailMapA = { detailMapSrc = "TerrainTest/GreenSkin.jpg", detailMapSize = 20}
local terrainData = { heightMapSrc = "TerrainTest/heightmap16.jpg", alphaMapSrc = "TerrainTest/alphamap.png" , detailMaps = {detailMapR, detailMapG, detailMapB, detailMapA}, _detailMapAmount = 4, mapHeight = 40.0, mapScale = 2.0 }
self._terrain = cc.Terrain:create(terrainData,cc.Terrain.CrackFixedType.SKIRT)
self._terrain:setLODDistance(1000.2, 6.4, 9.6)
self._terrain:setMaxDetailMapAmount(4)
self._terrain:setCameraMask(2)
self._terrain:setDrawWire(false)
self._terrain:setSkirtHeightRatio(3)
self._terrain:setLODDistance(64,128,192)
self._player = Player:create("Sprite3DTest/girl.c3b", self._camera, self._terrain)
self._player:setCameraMask(2)
self._player:setScale(0.08)
self._player:setPositionY(self._terrain:getHeight(self._player:getPositionX(), self._player:getPositionZ()) + PLAYER_HEIGHT)
local animation = cc.Animation3D:create("Sprite3DTest/girl.c3b","Take 001")
if nil ~= animation then
local animate = cc.Animate3D:create(animation)
self._player:runAction(cc.RepeatForever:create(animate))
end
local playerPos = self._player:getPosition3D()
self._camera:setPosition3D(cc.vec3(playerPos.x + camera_offset.x, playerPos.y + camera_offset.y, playerPos.z + camera_offset.z))
self._camera:setRotation3D(cc.vec3(-45,0,0))
self:addChild(self._player)
self:addChild(self._terrain)
end
function TerrainWalkThru:title()
return "TerrainWalkThru"
end
function TerrainWalkThru:subtitle()
return ""
end
function TerrainTest()
local scene = cc.Scene:create()
Helper.createFunctionTable =
{
TerrainSimple.create,
TerrainWalkThru.create,
}
scene:addChild(TerrainSimple.create())
scene:addChild(CreateBackMenuItem())
return scene
end

View File

@ -43,6 +43,7 @@ require "Sprite3DTest/Sprite3DTest"
require "SpriteTest/SpriteTest"
require "SceneTest/SceneTest"
require "SpineTest/SpineTest"
require "TerrainTest/TerrainTest"
require "Texture2dTest/Texture2dTest"
require "TileMapTest/TileMapTest"
require "TouchesTest/TouchesTest"
@ -123,6 +124,7 @@ local _allTests = {
{ isSupported = false, name = "SchdulerTest" , create_func= SchdulerTestMain },
{ isSupported = false, name = "ShaderTest" , create_func= ShaderTestMain },
{ isSupported = true, name = "Sprite3DTest" , create_func = Sprite3DTest },
{ isSupported = true, name = "TerrainTest" , create_func = TerrainTest },
{ isSupported = true, name = "SpriteTest" , create_func = SpriteTest },
{ isSupported = false, name = "TextInputTest" , create_func= TextInputTestMain },
{ isSupported = true, name = "Texture2DTest" , create_func = Texture2dTestMain },

View File

@ -26,7 +26,7 @@ headers = %(cocosdir)s/cocos/cocos2d.h
# what classes to produce code for. You can use regular expressions here. When testing the regular
# expression, it will be enclosed in "^$", like this: "^Menu*$".
classes = Animate3D Sprite3D Animation3D Skeleton3D ^Mesh$ AttachNode BillBoard Sprite3DCache TextureCube Skybox
classes = Animate3D Sprite3D Animation3D Skeleton3D ^Mesh$ AttachNode BillBoard Sprite3DCache TextureCube Skybox Terrain
# what should we skip? in the format ClassName::[function function]
# ClassName is a regular expression, but will be used like this: "^ClassName$" functions are also
@ -40,7 +40,8 @@ skip = Mesh::[create getAABB getVertexBuffer hasVertexAttrib getSkin getMeshInde
Skeleton3D::[create],
Animation3D::[getBoneCurveByName getBoneCurves],
BillBoard::[draw],
Sprite3DCache::[addSprite3DData getSpriteData]
Sprite3DCache::[addSprite3DData getSpriteData],
Terrain::[lookForIndicesLODSkrit lookForIndicesLOD insertIndicesLOD insertIndicesLODSkirt getIntersectionPoint getAABB getQuadTree create getHeight]
rename_functions =