Author Topic: [Lua] Tiny3D  (Read 26730 times)

0 Members and 2 Guests are viewing this topic.

Offline Chockosta

  • LV6 Super Member (Next: 500)
  • ******
  • Posts: 447
  • Rating: +169/-6
    • View Profile
[Lua] Tiny3D
« on: September 24, 2011, 09:01:10 am »
Hello guys !

I haven't done anything for two weeks, because of my homework :(
But I have a new project ! This is a small 3D engine.
I know that there is already Make3D by Levak, which is amazing, but I have to train with 3D. Moreover, mine is supposed to be a game engine, because it is very small. (I don't know if Lua is fast enough to use it)

So if anyone's interested, I post my engine...
I also add screenshots of a little 3D viewer made with that engine.
For now, it only draw vertices and edges. I'll try to add triangles...

________________________________________________________________________________

EDIT

10/01/2011 : The engine is finished...
New code :
Spoiler For Spoiler:
Code: [Select]
--Lua Tiny3D - By Loic Pujet

function multiplyMatrix(matrix,vector)
 local x=matrix[1][1]*vector[1]+matrix[1][2]*vector[2]+matrix[1][3]*vector[3]
 local y=matrix[2][1]*vector[1]+matrix[2][2]*vector[2]+matrix[2][3]*vector[3]
 local z=matrix[3][1]*vector[1]+matrix[3][2]*vector[2]+matrix[3][3]*vector[3]
 return x,y,z
end

function width() return platform.window:width() end
function height() return platform.window:height() end

function reverseTable(tbl)
 local tbl2={}
 for i,e in ipairs(tbl) do
  tbl2[#tbl-i+1]=e
 end
 return tbl2
end

function replaceFaces(tbl1,tbl2,faces)
 local faces2,count={},1
 for i,e in pairs(tbl1) do
  for j,e2 in pairs(tbl2) do
   if e2 then
    if e==e2 then
     faces2[count]=faces[j]
     count=count+1
     tbl2[j]=nil
    end
   end
  end
 end
 return reverseTable(faces2)
end

function sortFaces(vertices,faces,offset)
 local faces2,distTbl,facesTbl={},{},{}
 local middle={}
 local dist,xsum,ysum,zsum=0,0,0,0
 for i,e in pairs(faces) do
  xsum,ysum,zsum=0,0,0,0
  for j,e2 in pairs(e) do
   xsum,ysum,zsum=xsum+vertices[e2][1],ysum+vertices[e2][2],zsum+vertices[e2][3]
  end
  middle={xsum/#e,ysum/#e+offset,zsum/#e}
   dist=middle[1]*middle[1]+middle[2]*middle[2]+middle[3]*middle[3]
  distTbl[i]=dist
  facesTbl[i]=dist
 end
 table.sort(distTbl)
 return replaceFaces(distTbl,facesTbl,faces)
end

function chooseColor(gc,vertices,face,color)
 if #face<3 then
  gc:setColorRGB(color[1],color[2],color[3])
 else
  local a,b,c=vertices[face[1]][1]-vertices[face[2]][1],vertices[face[1]][2]-vertices[face[2]][2],vertices[face[1]][3]-vertices[face[2]][3]
  local d,e,f=vertices[face[1]][1]-vertices[face[3]][1],vertices[face[1]][2]-vertices[face[3]][2],vertices[face[1]][3]-vertices[face[3]][3]
  local normale={math.abs(b*f-c*e),math.abs(c*d-a*f),math.abs(a*e-b*d)}
  local angle=math.atan(math.sqrt(normale[1]*normale[1]+normale[3]*normale[3])/normale[2])
  local R,G,B=color[1]+angle*-60+50,color[2]+angle*-60+50,color[3]+angle*-60+50
  R,G,B=R>255 and 255 or R,G>255 and 255 or G,B>255 and 255 or B
  R,G,B=R<0 and 0 or R,G<0 and 0 or G,B<0 and 0 or B
  gc:setColorRGB(R,G,B)
 end
end

function renderFaces(gc,vertices,faces,pos,mode,color,offset)
 local polygon,size,faces2={},0,{}
 if mode==4 or mode==5 or mode==6 then
  faces2=sortFaces(vertices,faces,offset)
 else
  faces2=faces
 end
 for i,e in pairs(faces2) do
  polygon,size={},0
  drawPoly=true
  for j,f in pairs(faces2[i]) do
   if not pos[f] then
    drawPoly=false
   else
    polygon[j*2-1]=pos[f][1]
    polygon[j*2]=pos[f][2]
    size=size+2
   end
  end
  if drawPoly then
   polygon[size+1]=pos[faces2[i][1]][1]
   polygon[size+2]=pos[faces2[i][1]][2]
   if mode==4 then
    gc:setColorRGB(color[1],color[2],color[3])
    gc:fillPolygon(polygon)
   elseif mode==5 or mode==6 then
    chooseColor(gc,vertices,e,color)
    gc:fillPolygon(polygon)
   end
   if mode==2 or mode==3 or mode==4 or mode==5 then
    gc:setColorRGB(0,0,0)
    gc:setPen("thin","smooth")
    gc:drawPolyLine(polygon)
   end
  end
 end
end

function renderVertices(gc,pos)
 gc:setColorRGB(0,0,0)
 for i,e in pairs(pos) do
  if e then
   gc:fillRect(e[1]-1,e[2]-1,3,3)
  end
 end
end

----------------------------------------------------------------------------

function rotate(vertices,angle,x,y,z)
 local sum=x+y+z
 x,y,z=x/sum,y/sum,z/sum
 local c,s=math.cos(angle),math.sin(angle)
 local matrix={{x*x+(1-x*x)*c,x*y*(1-c)-z*s,x*z*(1-c)+y*s},{x*y*(1-c)+z*s,y*y+(1-y*y)*c,y*z*(1-c)-x*s},{x*z*(1-c)-y*s,y*z*(1-c)+x*s,z*z+(1-z*z)*c}}
 for i,e in pairs(vertices) do
  vertices[i]={multiplyMatrix(matrix,e)}
 end
end

function translate(vertices,x,y,z)
 for i,e in pairs(vertices) do
  vertices[i]={e[1]+x,e[2]+y,e[3]+z}
 end
end

function scale(vertices,x,y,z)
 for i,e in pairs(vertices) do
  vertices[i]={e[1]*x,e[2]*y,e[3]*z}
 end
end

function render(gc,vertices,faces,mode,color,offset)
 local yDist,pos=0,{}
 for i,e in pairs(vertices) do
  if e[2]>-offset then
   yDist=offset/(e[2]+offset)
   pos[i]={e[1]*yDist*25+width()/2,height()/2-e[3]*yDist*25}
  else
   pos[i]=false
  end
 end
 if mode==1 or mode==2 then
  renderVertices(gc,pos)
 end
 if #faces>0 and (mode==2 or mode==3 or mode==4 or mode==5 or mode==6) then
  renderFaces(gc,vertices,faces,pos,mode,color,offset)
 end
end

----------------------------------------------------------------------------
New screenshots :
« Last Edit: December 04, 2011, 08:26:01 am by Chockosta »

Offline Eiyeron

  • Urist McEiyolobster
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1430
  • Rating: +130/-10
  • (-_(//));
    • View Profile
    • Rétro-Actif : Rétro/Prog/Blog
Re: [Lua] Tiny3D
« Reply #1 on: September 24, 2011, 09:15:38 am »
Great work! Is it enough fast?

Offline Chockosta

  • LV6 Super Member (Next: 500)
  • ******
  • Posts: 447
  • Rating: +169/-6
    • View Profile
Re: [Lua] Tiny3D
« Reply #2 on: September 24, 2011, 09:21:49 am »
I think I can get 100 FPS...
If I draw 200 cubes, It's more like 5-10 FPS

Offline Levak

  • LV9 Veteran (Next: 1337)
  • *********
  • Posts: 1002
  • Rating: +208/-39
    • View Profile
    • My website
Re: [Lua] Tiny3D
« Reply #3 on: September 24, 2011, 09:36:30 am »
Note : it is fast without fill-face-algorithms :D
If you're not sure of the speed (because 100fps is really fast) just make an animation of a turn around, like 10 turns, and calculate the time it took.

Then, calculate the number of frames it requires to make this turnaround.
Like if the increment is 5°, it will take 360/5 frames to make a complete turn.

And then : fps=(number of frames)/(seconds) :D
« Last Edit: September 24, 2011, 09:39:29 am by Levak »
I do not get mad at people, I just want them to learn the way I learnt.
My website - TI-Planet - iNspired-Lua

Offline Chockosta

  • LV6 Super Member (Next: 500)
  • ******
  • Posts: 447
  • Rating: +169/-6
    • View Profile
Re: [Lua] Tiny3D
« Reply #4 on: September 24, 2011, 09:59:00 am »
48 FPS...
With "timer.start(0.01)" to repeat the rotation.

Offline Levak

  • LV9 Veteran (Next: 1337)
  • *********
  • Posts: 1002
  • Rating: +208/-39
    • View Profile
    • My website
Re: [Lua] Tiny3D
« Reply #5 on: September 24, 2011, 10:07:56 am »
On CX ? ClickPad/TouchPad ? Computer Software ?
Because each of those values are differents =)
« Last Edit: September 24, 2011, 10:08:14 am by Levak »
I do not get mad at people, I just want them to learn the way I learnt.
My website - TI-Planet - iNspired-Lua

Offline Chockosta

  • LV6 Super Member (Next: 500)
  • ******
  • Posts: 447
  • Rating: +169/-6
    • View Profile
Re: [Lua] Tiny3D
« Reply #6 on: September 24, 2011, 10:09:44 am »
On my Clickpad.
Which one is the slowest ?

Offline Levak

  • LV9 Veteran (Next: 1337)
  • *********
  • Posts: 1002
  • Rating: +208/-39
    • View Profile
    • My website
Re: [Lua] Tiny3D
« Reply #7 on: September 24, 2011, 10:10:08 am »
On my Clickpad.
Which one is the slowest ?
The CX =)

Computer Software > ClickPad/TouchPad > CX
« Last Edit: September 24, 2011, 10:10:37 am by Levak »
I do not get mad at people, I just want them to learn the way I learnt.
My website - TI-Planet - iNspired-Lua

Offline Chockosta

  • LV6 Super Member (Next: 500)
  • ******
  • Posts: 447
  • Rating: +169/-6
    • View Profile
Re: [Lua] Tiny3D
« Reply #8 on: September 24, 2011, 10:13:50 am »
And, by the way, what is the fastest way to draw faces ?
With a lot of gc:fillRect(x,y,1,height) ?
Or with gc:fillPolygon ?

Offline Levak

  • LV9 Veteran (Next: 1337)
  • *********
  • Posts: 1002
  • Rating: +208/-39
    • View Profile
    • My website
Re: [Lua] Tiny3D
« Reply #9 on: September 24, 2011, 10:18:22 am »
And, by the way, what is the fastest way to draw faces ?
With a lot of gc:fillRect(x,y,1,height) ?
Or with gc:fillPolygon ?

Hummm ... I really don't know, but let's think ...
 - Lua methods are implemented in C directly in the OS.
 - how a fillpolygon method works ? by filling horizontal or vertical lines. I don't know other methods.
 - How a fillRect method works ? by filling hozintal or vertical lines.

Basicly it uses the same underground methods don't you think ?
So I guess using fillPolygon is smarter.

It is the one I use with Make3D
« Last Edit: September 24, 2011, 10:18:33 am by Levak »
I do not get mad at people, I just want them to learn the way I learnt.
My website - TI-Planet - iNspired-Lua

Offline Chockosta

  • LV6 Super Member (Next: 500)
  • ******
  • Posts: 447
  • Rating: +169/-6
    • View Profile
Re: [Lua] Tiny3D
« Reply #10 on: September 24, 2011, 10:20:42 am »
Yes, I think you're right.
I'll try to add this to my engine... Tomorrow.

Offline Jim Bauwens

  • Lua! Nspire! Linux!
  • Editor
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1881
  • Rating: +206/-7
  • Linux!
    • View Profile
    • nothing...
Re: [Lua] Tiny3D
« Reply #11 on: September 24, 2011, 11:36:10 am »
Looks very nice, good job :)

Offline Loulou 54

  • LV4 Regular (Next: 200)
  • ****
  • Posts: 165
  • Rating: +39/-0
    • View Profile
    • Mes programmes sur TI bank.
Re: [Lua] Tiny3D
« Reply #12 on: September 24, 2011, 01:59:28 pm »
Quote
but I have to train with 3D
lol %)

Great job indeed ! :)
Some of my program available here.. :)
http://ti.bank.free.fr/index.php?mod=archives&ac=voir2&id=1471

     

Offline mrmprog

  • LV7 Elite (Next: 700)
  • *******
  • Posts: 559
  • Rating: +35/-1
    • View Profile
Re: [Lua] Tiny3D
« Reply #13 on: September 24, 2011, 02:04:32 pm »
Wow, that looks very good. 3d stuff on calc always amazes me.

Offline Chockosta

  • LV6 Super Member (Next: 500)
  • ******
  • Posts: 447
  • Rating: +169/-6
    • View Profile
Re: [Lua] Tiny3D
« Reply #14 on: September 25, 2011, 08:01:53 am »
Quote
but I have to train with 3D
lol %)
Er... What's fun ?

__________________
Now my engine displays faces !

New code :
Spoiler For Spoiler:
Code: [Select]
function multiplyMatrix(matrix,vector)
 local x=matrix[1][1]*vector[1]+matrix[1][2]*vector[2]+matrix[1][3]*vector[3]
 local y=matrix[2][1]*vector[1]+matrix[2][2]*vector[2]+matrix[2][3]*vector[3]
 local z=matrix[3][1]*vector[1]+matrix[3][2]*vector[2]+matrix[3][3]*vector[3]
 return x,y,z
end

function rotate(vertices,angle,x,y,z)
 local sum=x+y+z
 x,y,z=x/sum,y/sum,z/sum
 local c,s=math.cos(angle),math.sin(angle)
 local matrix={{x*x+(1-x*x)*c,x*y*(1-c)-z*s,x*z*(1-c)+y*s},{x*y*(1-c)+z*s,y*y+(1-y*y)*c,y*z*(1-c)-x*s},{x*z*(1-c)-y*s,y*z*(1-c)+x*s,z*z+(1-z*z)*c}}
 for i,e in pairs(vertices) do
  vertices[i]={multiplyMatrix(matrix,e)}
 end
end

function translate(vertices,x,y,z)
 for i,e in pairs(vertices) do
  vertices[i]={e[1]+x,e[2]+y,e[3]+z}
 end
end

function scale(vertices,x,y,z)
 for i,e in pairs(vertices) do
  vertices[i]={e[1]*x,e[2]*y,e[3]*z}
 end
end

function width() return platform.window:width() end
function height() return platform.window:height() end

function reverseTable(tbl)
 local tbl2={}
 for i,e in ipairs(tbl) do
  tbl2[#tbl-i+1]=e
 end
 return tbl2
end

function replaceFaces(tbl1,tbl2,faces)
 local faces2={}
 for i,e in pairs(tbl1) do
  for j,e2 in pairs(tbl2) do
   if e2 then
    if e==e2 then
     table.insert(faces2,faces[j])
     tbl2[j]=nil
    end
   end
  end
 end
 return reverseTable(faces2)
end

function sortFaces(vertices,faces)
 local faces2,distTbl,facesTbl={},{},{}
 local middle={}
 local dist,xsum,ysum,zsum=0,0,0,0
 for i,e in pairs(faces) do
  xsum,ysum,zsum=0,0,0,0
  for j,e2 in pairs(e) do
   xsum,ysum,zsum=xsum+vertices[e2][1],ysum+vertices[e2][2],zsum+vertices[e2][3]
  end
  middle={xsum/#e,ysum/#e-5,zsum/#e}
   dist=math.sqrt(middle[1]*middle[1]+middle[2]*middle[2]+middle[3]*middle[3])
  table.insert(distTbl,dist)
  table.insert(facesTbl,dist)
 end
 table.sort(distTbl)
 return replaceFaces(distTbl,facesTbl,faces)
end

function renderFaces(gc,vertices,faces,pos,mode)
 local polygon={}
 local faces2=sortFaces(vertices,faces)
 for i,e in pairs(faces2) do
  polygon={}
  for j,f in pairs(faces2[i]) do
   table.insert(polygon,pos[f][1])
   table.insert(polygon,pos[f][2])
  end
  table.insert(polygon,pos[faces2[i][1]][1])
  table.insert(polygon,pos[faces2[i][1]][2])
  if mode==4 or mode==5 then
   gc:setColorRGB(200,200,200)
   gc:fillPolygon(polygon)
  end
  if mode==2 or mode==3 or mode==4 then
   gc:setColorRGB(0,0,0)
   gc:drawPolyLine(polygon)
  end
 end
end

function renderVertices(gc,pos)
 gc:setColorRGB(0,0,0)
 for i,e in pairs(pos) do
  if e then
   gc:fillRect(e[1]-1,e[2]-1,3,3)
  end
 end
end

function render(gc,vertices,faces,mode)
 local ray,dist,nb,pos={},0,0,{}
 for i,e in pairs(vertices) do
  if e[2]<5 then
   ray={e[1],e[2]-5,e[3]}
    dist=math.sqrt(ray[1]*ray[1]+ray[2]*ray[2]+ray[3]*ray[3])
   nb=((dist*5)/(ray[2]))/dist
   table.insert(pos,{ray[1]*nb*25+width()/2,ray[3]*nb*25+height()/2})
  else
   table.insert(pos,false)
  end
 end
 if mode==1 or mode==2 then
  renderVertices(gc,pos)
 end
 if mode==2 or mode==3 or mode==4 or mode==5 then
  renderFaces(gc,vertices,faces,pos,mode)
 end
end