Thank you Roland for your help and LDCad 1.7-alpha-2. The discussed "place on ground" seems to work in a first version. Also porting the collision detection from Java to LUA will take more time...

1: collect all parts recursively and print their filename/description together with its bounding box

3: tbd: check collision of parts by comparing pairs of triangles of pairs of parts

The current implementation collects all parts at first which would not be necessary for case 1 (just print instead of collect+print) and case 2 (just collect maxY instead of all bounding boxes of all parts), so this implementation is far from being optimal in regards to timing or memory usage. But it helps me porting my collision detection

Code:

`Part={triangles={}, orig={}, level=0, pMinX=math.huge,pMinY=math.huge,pMinZ=math.huge, pMaxX=-math.huge,pMaxY=-math.huge,pMaxZ=-math.huge}`

function Part:new(orig, level)

o={}

setmetatable(o, self)

self.__index=self

self.orig=orig or {}

self.level=level or 0

self.pMinX=math.huge

self.pMinY=math.huge

self.pMinZ=math.huge

self.pMaxX=-math.huge

self.pMaxY=-math.huge

self.pMaxZ=-math.huge

return o

end

function Part:add(tri)

table.insert(self.triangles, tri)

if tri.pMinX<self.pMinX then

self.pMinX=tri.pMinX

end

if tri.pMinY<self.pMinY then

self.pMinY=tri.pMinY

end

if tri.pMinZ<self.pMinZ then

self.pMinZ=tri.pMinZ

end

if tri.pMaxX>self.pMaxX then

self.pMaxX=tri.pMaxX

end

if tri.pMaxY>self.pMaxY then

self.pMaxY=tri.pMaxY

end

if tri.pMaxZ>self.pMaxZ then

self.pMaxZ=tri.pMaxZ

end

end

function Part:info()

return self.orig:getFileName()..' ('..self.orig:getDescription()..'): '..self.pMinX..' '..self.pMinY..' '..self.pMinZ..' to '..self.pMaxX..' '..self.pMaxY..' '..self.pMaxZ

end

Triangle={p1={}, p2={}, p3={}, pMinX=math.huge,pMinY=math.huge,pMinZ=math.huge, pMaxX=-math.huge,pMaxY=-math.huge,pMaxZ=-math.huge}

function Triangle:new(p1, p2, p3)

o={}

setmetatable(o, self)

self.__index=self

self.p1=p1

self.p2=p2

self.p3=p3

self.pMinX=math.huge

self.pMinY=math.huge

self.pMinZ=math.huge

self.pMaxX=-math.huge

self.pMaxY=-math.huge

self.pMaxZ=-math.huge

self:check(p1)

self:check(p2)

self:check(p3)

-- print('vec: ', p1,' / ',p2,' / ',p3)

-- print('min/max: ', self.pMinX,' ',self.pMinY,' ',self.pMinZ, ' to ', self.pMaxX,' ',self.pMaxY,' ',self.pMaxZ)

return o

end

function Triangle:check(p)

local pX,pY,pZ=p:get()

if pX<self.pMinX then

self.pMinX=pX

end

if pY<self.pMinY then

self.pMinY=pY

end

if pZ<self.pMinZ then

self.pMinZ=pZ

end

if pX>self.pMaxX then

self.pMaxX=pX

end

if pY>self.pMaxY then

self.pMaxY=pY

end

if pZ>self.pMaxZ then

self.pMaxZ=pZ

end

end

function colldet_walk(sf, ppos, level, parts)

local partCnt=sf:getRefCount()

for i=1,partCnt do

local part=sf:getRef(i):getSubfile()

-- print('-- part ', part:getDescription())

local pos=sf:getRef(i):getPosOri()

pos:mulBA(ppos)

-- print('-- pos ', pos)

local data=part:getRenderData()

if data:isLinked() then

local mpart=Part:new(part, level)

table.insert(parts, mpart)

for g=1,data:getGroupCount() do

local grp=data:getGroup(g)

if grp:isTriangle() then

local cnt=grp:getCount()

-- print('triangle strip contains ', cnt, ' entries')

for j=1,cnt do

local a,b,c=grp:getPositionIndices(j)

-- print('triPosRel: ', data:getPosition(a), '; ', data:getPosition(b), '; ', data:getPosition(c))

-- print('triPosAbs: ', data:getPosition(a):getTransformed(pos), '; ', data:getPosition(b):getTransformed(pos), '; ', data:getPosition(c):getTransformed(pos))

mpart:add(Triangle:new(data:getPosition(a):getTransformed(pos), data:getPosition(b):getTransformed(pos), data:getPosition(c):getTransformed(pos)))

end

elseif grp:isQuad() then

local cnt=grp:getCount()

-- print('quad strip contains ', cnt, ' entries')

for j=1,cnt do

local a,b,c,d=grp:getPositionIndices(j)

-- print('quadPosRel: ', data:getPosition(a), '; ', data:getPosition(b), '; ', data:getPosition(c), '; ', data:getPosition(d))

-- print('quadPosAbs: ', data:getPosition(a):getTransformed(pos), '; ', data:getPosition(b):getTransformed(pos), '; ', data:getPosition(c):getTransformed(pos), '; ', data:getPosition(d):getTransformed(pos))

mpart:add(Triangle:new(data:getPosition(a):getTransformed(pos), data:getPosition(b):getTransformed(pos), data:getPosition(c):getTransformed(pos)))

mpart:add(Triangle:new(data:getPosition(c):getTransformed(pos), data:getPosition(d):getTransformed(pos), data:getPosition(a):getTransformed(pos)))

end

end

end

else

colldet_walk(part, pos, level+1, parts)

end

end

end

function colldet_collect()

local sf=ldc.subfile()

local pos=ldc.matrix()

--identity is set by default: pos:setIdentity()

local parts={}

colldet_walk(sf, pos, 0, parts)

print('found ',#parts,' parts:')

for i=1,#parts do

print(i, ': ', parts[i]:info())

end

end

function colldet_floor()

local sf=ldc.subfile()

local pos=ldc.matrix()

pos:setIdentity()

local parts={}

colldet_walk(sf, pos, 0, parts)

if #parts==0 then

print('no part found')

else

local max=parts[1].pMaxY

for i=2,#parts do

if max<parts[i].pMaxY then

max=parts[i].pMaxY

end

end

local partCnt=sf:getRefCount()

for i=1,partCnt do

local ref=sf:getRef(i)

local x,y,z=ref:getPos():get()

ref:setPos(ldc.vector(x,y-max,z))

end

end

end

function colldet_check()

print('not implemented yet!')

local sf=ldc.subfile()

local pos=ldc.matrix()

pos:setIdentity()

local parts={}

colldet_walk(sf, pos, 0, parts)

for i=2,#parts do

for j=1,i-1 do

local p1=parts[i]

local p2=parts[j]

print('todo: checking ', i, ' (', p1:info(), ') against ', j, ' (', p2:info(), ')')

-- todo

end

end

end

function register()

local macro=ldc.macro('CD: 1 collect parts')

macro:setHint('Collision Detection: collect parts')

macro:setEvent('run', 'colldet_collect')

local macro=ldc.macro('CD: 2 move to floor')

macro:setHint('Collision Detection: move bottom point down/up to 0')

macro:setEvent('run', 'colldet_floor')

local macro=ldc.macro('CD: 3 check collision')

macro:setHint('Collision Detection: check part collision')

macro:setEvent('run', 'colldet_check')

end

register()