RetroBASIC
Retrogamecoding(.org) => Examples => Topic started by: Bereb on November 20, 2012, 03:06:59 PM
-
A simple 3D demo :
#!/usr/bin/egsl
-----------------------
-- screen set
-----------------------
openwindow(650,450,32,"3D demo - EGSL")
backcolour(255,255,255)
colour(0,0,0)
clearscreen()
---------------------------
-- constants & variables
---------------------------
rad = math.rad
ox, oy = screenwidth()/2, screenheight()/2
coorx, coory = 0, 0
pen = true
heading = 0
--------------------------------
-- main graphic function
--------------------------------
function pos(x,y)
-- draw if pen is down (== true)
if pen then aaline(ox+coorx, oy-coory, ox+x, oy-y) end
-- set new position
coorx, coory = x, y
end
-----------------
-- 3D functions
-----------------
function isopoint(a,b,c)
pos( (a-c)*0.886 , b-(a+c)*0.5 )
end
function cone(r,l)
r = l/2
-- set at point (0,0,0)
pen = false
local h, v
for h = 0, l, 10 do
for v = 0, 360, 20 do
isopoint( (h/2)*cos(rad(v)), h, (h/2)*sin(rad(v)) )
pen = true
end
pen = false
end
for v = 0, 360, 20 do
for h = 0, l, 10 do
isopoint( (h/2)*cos(rad(v)), h, (h/2)*sin(rad(v)) )
pen= true
end
pen = false
end
end
function ellipsoid(r1, r2, r3)
-- set at point (100,-30,100)
local u, v, l, m, n
pen = false
for u = 0, 360, 20 do
for v = 0, 180, 20 do
l = (r1 * cos(rad(u))) * sin(rad(v))
m = r3 * sin(rad(u))
n = (r2 * cos(rad(u))) * cos(rad(v))
isopoint(100 + l, -30 + m, 100 + n)
pen = true
end
pen= false
end
for v = 0, 180, 20 do
for u = 0, 360, 20 do
l = (r1 * cos(rad(u))) * sin(rad(v))
m = r3 * sin(rad(u))
n = r2 * cos(rad(u)) * cos(rad(v))
isopoint(100 + l, -30 + m, 100 + n)
pen = true
end
pen = false
end
end
function cylinder(r, l)
-- set at point (120,-100,-120)
local h, v
pen= false
for h = 0, l, 10 do
for v = 0, 360, 20 do
isopoint( 120+r*cos(rad(v)), -100+h, -120+r*sin(rad(v)) )
pen = true
end
pen = false
end
for v = 0, 360, 20 do
for h = 0, l, 10 do
isopoint( 120+r*cos(rad(v)), -100+h, -120+r*sin(rad(v)) )
pen = true
end
pen= false
end
end
function sphere(r)
-- set at point (-120,-100,120)
local u, v, l, m, n
pen = false
for u = 0, 360, 20 do
for v = 0, 180, 20 do
l = (r * cos(rad(u))) * sin(rad(v))
m = r * sin(rad(u))
n = (r * cos(rad(u))) * cos(rad(v))
isopoint(-120 + l, -100 + m, 120 + n)
pen= true
end
pen = false
end
for v = 0, 180, 20 do
for u = 0, 360, 20 do
l = (r * cos(rad(u))) * sin(rad(v))
m = r * sin(rad(u))
n = (r * cos(rad(u))) * cos(rad(v))
isopoint(-120 + l, -100 + m, 120 + n)
pen= true
end
pen = false
end
end
---------------------------------
-- 3D demo : main program
---------------------------------
sphere(40)
cone(40, 70)
cylinder(30, 90)
ellipsoid(60, 40, 25)
redraw()
inkey()
closewindow()
-
A rotating pyramid :
#!/usr/bin/egsl
openwindow(400,360,0,"Rotating Pyramid - EGSL")
backcolor(100,100,100)
clearscreen()
color(255,255,255)
local ox, oy = screenwidth()/2, screenheight()/2 -- center of screen
local taille = 100
local alpha, beta = 0, 30
local rad = math.rad
local key
local ax, ay, bx, by, cx, cy, dx, dy
repeat
key = getkey()
clearscreen()
-- building pyramid
ax = taille * cos(rad(alpha))
ay = sin(rad(beta)) * taille * sin(rad(alpha))
bx = taille * cos(rad((alpha + 90) % 360))
by = sin(rad(beta)) * taille * sin(rad((alpha + 90) % 360))
cx = taille * cos(rad((alpha + 180) % 360))
cy = sin(rad(beta)) * taille * sin(rad((alpha + 180) % 360))
dx = taille * cos(rad((alpha + 270) % 360))
dy = sin(rad(beta)) * taille * sin(rad((alpha + 270) % 360))
-- drawing pyramid
aaline(ox, oy-120, ox+ax, oy-ay)
aaline(ox, oy-120, ox+bx, oy-by)
aaline(ox, oy-120, ox+cx, oy-cy)
aaline(ox, oy-120, ox+dx, oy-dy)
aaline(ox+ax, oy-ay, ox+bx, oy-by)
aaline(ox+bx, oy-by, ox+cx, oy-cy)
aaline(ox+cx, oy-cy, ox+dx, oy-dy)
aaline(ox+dx, oy-dy, ox+ax, oy-ay)
redraw()
-- rotating pyramid
alpha = alpha+1
until key == 27
closewindow()
Sorry, I've not translated my whole script ... taille means size ;)
-
A cone :
openwindow(400,400,8,"CONE")
backcolour(255,255,255)
colour(0,0,0)
clearscreen()
-- constants
local rad = math.rad
local ox, oy = screenwidth()/2, screenheight()/2
-- variables
local x, y, h, beta = 0, 0, 0, 0, 0
-- main loop
repeat
key = getkey()
clearscreen()
for alpha = 0, 360, 8 do
x = 100 * cos(rad(alpha))
y = sin(rad(alpha)) * sin(rad(beta)) * 80
h = 100 * cos(rad(beta))
aaline(ox, oy, ox+x, oy-(y - h))
end
redraw()
beta = beta + 2
until key == 27
closewindow()
Faster without anti-aliasing ( i.e. line() instead of aaline() )
-
Awesome. Who starts coding an ELITE clone? 8)
-
good work. what about textures?
-
good work. what about textures?
It's just simple 3D. I'm not clever enough to end up doing that ???
;D
-
Maybe not textures but coloured sides? Like in the ELITE for AMIGA ...
(http://www.mobygames.com/images/shots/l/132071-elite-amiga-screenshot-a-ship-leaving-the-space-stations.gif)
I would recommend using filltriangle ... ;)
-
This could be helpful: http://www.codeproject.com/Articles/170296/3D-Software-Rendering-Engine-Part-I
I think I will have a closer look myself ...
-
We can take a look at Object Oriented Programming in Lua (http://lua-users.org/wiki/ObjectOrientedProgramming) to see if we could create easily this way graphic objects (e.g. a set of filled triangles), to build more complex 3D objects with some properties and methods.
When I used Windows, I liked Elica Logo (http://www.elica.net/site/), which is a modern 'Logo' using NOOP (Natural Object Oriented Programing) in a very simple manner. This Logo is able to exploit 3D graphics in the easiest way, with awesome performances (best performances than in its 2D graphics features). But that Logo implementation is not cross-platform.
However, personally, I'm not a real advanced programer to find good solutions or to assure any good results :-[
-
I'll try to illustrate my previous remark with a quickly done script, using a table for a very simple 2D object prototype:
Moving square
local rad = math.rad
local width = 400
local height = 400
local bcol = 255 -- background color = white
local fcol = 0 -- foreground color = black
local xcor, ycor, heading, i, pen = 0, 0, 0, 1, true
local coor = {x = 0, y = 0}
local polygon = {nsides = 4, size = 30, pos = coor, orientation = 0}
local square = polygon
square.size = 80
------------------------------------------------------------------
-- Graphic procedures (basic procedures for polar/turtle graphics)
------------------------------------------------------------------
function setpos(x, y)
-- set new position
if pen then
-- draw if pen is down (=true)
line(xcor, ycor, x, y)
end
xcor, ycor = x, y
end
function turn(d)
-- set orientation in degree (right: positive d / left: negative d)
heading = (heading + d) % 360
end
function go(dist)
-- move (forward: positive dist / backward: negative dist)
setpos(xcor + (dist * sin(rad(heading))), ycor + (dist * cos(rad(heading))))
end
------------------------------------------------------------------
-- Polygon procedures
------------------------------------------------------------------
function draw_polygon(poly)
for n = 1, poly.nsides do
go(poly.size)
turn(360 / poly.nsides)
end
end
function display_polygon(poly, mode)
local col = fcol
if not mode then col = bcol end
color(col, col, col)
pen = false
setpos(poly.pos.x, poly.pos.y)
heading = poly.orientation
pen = true
draw_polygon(poly)
end
------------------------------------------------------------------
-- Main program
------------------------------------------------------------------
openwindow(width, height, 0, "Moving Square - EGSL")
backcolor(bcol, bcol, bcol)
color(fcol, fcol, fcol)
clearscreen()
repeat
k = getkey()
display_polygon(square, false)
if (square.pos.x > width or square.pos.x < 0) or (square.pos.y > height or square.pos.y < 0) then
i = 1
else
i = i + 2
end
square.pos.x = i + 2
square.pos.y = i + 2
square.orientation = i * 2
display_polygon(square, true)
redraw()
until k == 27
closewindow()
We could probably do better with tables and metatables (very interesting Lua's features) as decribed here (http://retrogamecoding.org/forum/index.php?page=Thread&threadID=279), and create more complex objects :)
But no solution this way to fill objects with color or texture :(