Now with walking!
require(asset.documents.Craft.Cameras)
function setup()
scene = craft.scene()
scene.sun.rotation = quat.eulerAngles(45, 355, 0)
viewer.mode = FULLSCREEN
obv = scene.camera:add(OrbitViewer, vec3(0,8,0), 30, 2, 120)
obv.rx = 20
obv.ry = 130
rig = adventurerRig(scene)
function setupParameters()
local function add(name, minV, maxV, defaultV)
local startValue = readLocalData(name, defaultV)
_G[name] = startValue
parameter.number(name, minV, maxV, startValue, function(v)
_G[name] = v
saveLocalData(name, v)
end)
end
add("ArmPivotX", 0, 1, 0.38)
add("ArmPivotY", -1, 15, 10.66)
add("ArmPivotZ", -1, 1, 0)
add("LegPivotX", 0, 1, 0.18)
add("LegPivotY", -1, 15, 6.86)
add("LegPivotZ", -1, 1, 0)
add("ArmSwing", 0, 90, 31.20)
add("LegSwing", 0, 90, 38.95)
add("WalkSpeed", 0, 10, 3)
end
setupParameters()
--[[
--settings for a normal walk:
ArmPivotX = ArmPivotX or 0.38
ArmPivotY = ArmPivotY or 10.66
ArmPivotZ = ArmPivotZ or 0
LegPivotX = LegPivotX or 0.18
LegPivotY = LegPivotY or 6.86
LegPivotZ = LegPivotZ or 0
ArmSwing = ArmSwing or 31.20
LegSwing = LegSwing or 38.95
WalkSpeed = WalkSpeed or 5]]
end
function draw()
animateWalk(rig, ElapsedTime)
scene:update(DeltaTime)
scene:draw()
end
function touched(t)
obv:touched(t)
end
BODY_PARTS = {
head = {13,14,15,16,17,18,19,20,21,22,23,24},
torso = {1,2,3,4,5,6,7,8,9,10,11,12,49,52},
leftArm = {25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77},
rightArm = {78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131},
leftLeg = {132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167},
rightLeg = {168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203}
}
function adventurerInPieces(scene)
local model = craft.model(asset.builtin.Blocky_Characters.Adventurer)
local material = craft.material(asset.builtin.Materials.Standard)
material.map = readImage(asset.builtin.Blocky_Characters.AdventurerSkin)
local ind = model.indices
local triangles = {}
for i = 1, #ind, 3 do
triangles[#triangles+1] = {i1=ind[i], i2=ind[i+1], i3=ind[i+2]}
end
local function buildMesh(triIndices)
local pos, uv, col, norm = model.positions, model.uvs, model.colors, model.normals
local newPos, newUV, newCol, newNorm, newInd, vertexMap = {}, {}, {}, {}, {}, {}
local function addVertex(old)
if vertexMap[old] then return vertexMap[old] end
local new = #newPos + 1
vertexMap[old] = new
newPos[new] = pos[old]
if uv then newUV[new] = uv[old] end
if col then newCol[new] = col[old] end
if norm then newNorm[new] = norm[old] end
return new
end
for _, id in ipairs(triIndices) do
local t = triangles[id]
if t then
table.insert(newInd, addVertex(t.i1))
table.insert(newInd, addVertex(t.i2))
table.insert(newInd, addVertex(t.i3))
end
end
local m = craft.model()
m.positions = newPos
m.indices = newInd
if #newUV > 0 then m.uvs = newUV end
if #newCol > 0 then m.colors = newCol end
if #newNorm > 0 then m.normals = newNorm end
return m
end
local parts = {}
for name, triIndices in pairs(BODY_PARTS) do
local e = scene:entity()
e.model = buildMesh(triIndices)
e.material = material
parts[name] = e
end
return parts
end
function adventurerRig(scene)
local model = craft.model(asset.builtin.Blocky_Characters.Adventurer)
local material = craft.material(asset.builtin.Materials.Standard)
material.map = readImage(asset.builtin.Blocky_Characters.AdventurerSkin)
local ind = model.indices
local triangles = {}
for i = 1, #ind, 3 do
triangles[#triangles+1] = {
i1 = ind[i],
i2 = ind[i+1],
i3 = ind[i+2]
}
end
local function buildMesh(triIndices)
local pos = model.positions
local uv = model.uvs
local col = model.colors
local norm = model.normals
local newPos = {}
local newUV = {}
local newCol = {}
local newNorm = {}
local newInd = {}
local vertexMap = {}
local function addVertex(old)
local existing = vertexMap[old]
if existing then
return existing
end
local new = #newPos + 1
vertexMap[old] = new
newPos[new] = pos[old]
if uv then newUV[new] = uv[old] end
if col then newCol[new] = col[old] end
if norm then newNorm[new] = norm[old] end
return new
end
for _, triId in ipairs(triIndices) do
local t = triangles[triId]
if t then
table.insert(newInd, addVertex(t.i1))
table.insert(newInd, addVertex(t.i2))
table.insert(newInd, addVertex(t.i3))
end
end
local m = craft.model()
m.positions = newPos
m.indices = newInd
if #newUV > 0 then m.uvs = newUV end
if #newCol > 0 then m.colors = newCol end
if #newNorm > 0 then m.normals = newNorm end
return m
end
--------------------------------------------------
-- root
--------------------------------------------------
local root = scene:entity()
--------------------------------------------------
-- pivots
--------------------------------------------------
local torsoPivot = scene:entity()
torsoPivot.parent = root
local headPivot = scene:entity()
headPivot.parent = torsoPivot
local leftArmPivot = scene:entity()
leftArmPivot.parent = torsoPivot
local rightArmPivot = scene:entity()
rightArmPivot.parent = torsoPivot
local leftLegPivot = scene:entity()
leftLegPivot.parent = torsoPivot
local rightLegPivot = scene:entity()
rightLegPivot.parent = torsoPivot
--------------------------------------------------
-- meshes
--------------------------------------------------
local meshes = {}
for name, triIndices in pairs(BODY_PARTS) do
local e = scene:entity()
e.model = buildMesh(triIndices)
e.material = material
meshes[name] = e
end
meshes.torso.parent = torsoPivot
meshes.head.parent = headPivot
meshes.leftArm.parent = leftArmPivot
meshes.rightArm.parent = rightArmPivot
meshes.leftLeg.parent = leftLegPivot
meshes.rightLeg.parent = rightLegPivot
--------------------------------------------------
-- joint locations
--------------------------------------------------
leftArmPivot.position = vec3( 0.38, 0.40, 0)
rightArmPivot.position = vec3(-0.38, 0.40, 0)
leftLegPivot.position = vec3( 0.18,-0.50, 0)
rightLegPivot.position = vec3(-0.18,-0.50, 0)
headPivot.position = vec3(0,0.72,0)
--------------------------------------------------
-- compensate mesh positions
--------------------------------------------------
meshes.leftArm.position = -leftArmPivot.position
meshes.rightArm.position = -rightArmPivot.position
meshes.leftLeg.position = -leftLegPivot.position
meshes.rightLeg.position = -rightLegPivot.position
meshes.head.position = -headPivot.position
--------------------------------------------------
-- return rig
--------------------------------------------------
return {
root = root,
torsoPivot = torsoPivot,
headPivot = headPivot,
leftArmPivot = leftArmPivot,
rightArmPivot = rightArmPivot,
leftLegPivot = leftLegPivot,
rightLegPivot = rightLegPivot,
meshes = meshes
}
end
function animateWalk(rig, t)
local s = math.sin(t * WalkSpeed)
rig.leftArmPivot.position =
vec3( ArmPivotX, ArmPivotY, ArmPivotZ )
rig.rightArmPivot.position =
vec3(-ArmPivotX, ArmPivotY, ArmPivotZ )
rig.leftLegPivot.position =
vec3( LegPivotX, LegPivotY, LegPivotZ )
rig.rightLegPivot.position =
vec3(-LegPivotX, LegPivotY, LegPivotZ )
rig.meshes.leftArm.position =
-rig.leftArmPivot.position
rig.meshes.rightArm.position =
-rig.rightArmPivot.position
rig.meshes.leftLeg.position =
-rig.leftLegPivot.position
rig.meshes.rightLeg.position =
-rig.rightLegPivot.position
rig.meshes.head.position =
-rig.headPivot.position
rig.leftArmPivot.rotation =
quat.eulerAngles( s * ArmSwing, 0, 0)
rig.rightArmPivot.rotation =
quat.eulerAngles(-s * ArmSwing, 0, 0)
rig.leftLegPivot.rotation =
quat.eulerAngles(-s * LegSwing, 0, 0)
rig.rightLegPivot.rotation =
quat.eulerAngles( s * LegSwing, 0, 0)
end