Modding, Mission Design, and Coding > The Scripting Workshop
luaSDL / nuke makes a 3d engine
(1/1)
Nuke:
ok, i was screwing around with my scripting table, and got fed up with having to waith a couple minutes to load the game each time i wanted to check something. so i went looking for a stand alone imnterpreter so i could test some math functions i was writing. anyway i came across this
after an hour of pulling out hair i got a screen to render stuff. so i took my point rotation functions and some other stuff i was working on and made a cute little 3d graphics engine, well sort of :D you can download the interpreter and play with my attached script. with all the sdl calls i dont thing freespace would like it.
then theres the matter of sdl librarys, think maybe they would perhaps do anything for the scripting system, or would it just be a redundant waste of time :D
btw to get my thingy to work stick the lua file into the root directory of the interpreter (be sure to overwrite the demo one that comes with the interpreter). keypad does everything, del exits.
[attachment deleted by admin]
Bobboau:
wmc should consiter reloading the scripting table every time the main windo gets maximized.
WMCoolmon:
Possibly in debug builds, but not in release builds. You'd get parse errors every time the window was maximized, which wouldn't exactly be very helpful to someone just trying to play the game. Plus _any_ errors would force window minimization (at least at this point) and you'd get caught in an infinite loop.
If/when I put support for the scripting table into the scripting system, I could put in some kind of refresh() command or something. (That's another mind-bending activity, cause you'd probably be calling the refresh command in the scripting table to refresh the scripting table....but as long as the lua maintains the current execution thread while it changes all the table values to Something Else, I think it should be OK, as long as garbage collection is triggered as well so it isn't a massive memory leak.
Nuke:
well i updated it a little. now it has arbitrary axis rotation, linear neutonian physics (rotations use no physics), joystick support, and of course a laser. :D
be sure to run it in that luaSDL interpreter and not in freespace. it can run in freespace with some modifications but youre gonna need to use some different imput, like mousejoy(), change all the vec_3d()s to ba.createVector()s and drawline() with gr.drawLine() and stuff like that.
--- Code: ----------------------------
-----init-----screen-----
-------------------------
SDL = SDL
SDL.SDL_Init(SDL.SDL_INIT_EVERYTHING)
screen = SDL.SDL_SetVideoMode(800, 600, 32, 0)
info = SDL.SDL_GetVideoInfo()
w,h = info.current_w, info.current_h
cx,cy = w/2,h/2
rect = SDL.SDL_Rect_local()
rect.x, rect.y = 0,0
rect.w, rect.h = w,h
grey = SDL.SDL_MapRGB(screen.format, 0x80, 0x80, 0x80)
blue = SDL.SDL_MapRGB(screen.format, 0x00, 0x00, 0x80)
---------------------------------------------
-----end init screen-----start type defs-----
---------------------------------------------
vec_2d = function(xy,ey)
local v = {}
if getmetatable(xy) == vec_2d_mt then
v.x = xy.x
v.y = xy.y
elseif type(xy) == 'table' then
v.x = xy[1]
v.y = xy[2]
elseif type(xy) == 'number' and type(ey) == 'number' then
v.x, v.y = xy, ey
else
v.x, v.y = 0, 0
end
setmetatable(v, vec_2d_mt)
return v
end
vec_2d_mt = {
__add = function(v1,v2) return vec_2d(v1.x + v2.x, v1.y + v2.y) end,
__sub = function(v1,v2) return vec_2d(v1.x - v2.x, v1.y - v2.y) end,
__unm = function(v) return vec_2d(-v.x,-v.y) end,
__mul = function(v1,v2)
if type(v1) == 'number' then
return vec_2d(v1 * v2.x, v1 * v2.y)
elseif type(v2) == 'number' then
return vec_2d(v1.x * v2, v1.y * v2)
else
return vec_2d(v1.x * v2.x, v1.y * v2.y)
end
end,
__div = function(v1,v2)
if type(v1) == 'number' then
return vec_2d(v1 / v2.x, v1 / v2.y)
elseif type(v2) == 'number' then
return vec_2d(v1.x / v2, v1.y / v2)
else
return vec_2d(v1.x / v2.x, v1.y / v2.y)
end
end,
__concat = function(v,r)
local nx = v.x * math.cos(r) - v.y * math.sin(r)
local ny = v.x * math.sin(r) + v.y * math.cos(r)
v = vec_2d( nx, ny )
return v
end,
__index = function(v,key)
if key == 'norm' then
local len = math.sqrt( v.x^2 + v.y^2 )
v.norm = vec_2d( v.x / len, v.y / len )
return v.norm
end
end
}
vec_3d = function(xyz,ey,ez)
local v = {}
if getmetatable(xyz) == vec_3d_mt then
v.x = xyz.x
v.y = xyz.y
v.z = xyz.z
elseif type(xyz) == 'table' then
v.x = xyz[1]
v.y = xyz[2]
v.z = xyz[3]
elseif type(xyz) == 'number' and type(ey) == 'number' and type(ez) == 'number' then
v.x, v.y, v.z = xyz, ey, ez
else
v.x, v.y, v.z = 0, 0, 0
end
setmetatable(v, vec_3d_mt)
return v
end
vec_3d_mt = {
__add = function(v1,v2) return vec_3d(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z) end,
__sub = function(v1,v2) return vec_3d(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z) end,
__unm = function(v) return vec_3d(-v.x,-v.y,-v.z) end,
__mul = function(v1,v2)
if type(v1) == 'number' then
return vec_3d(v1 * v2.x, v1 * v2.y, v1 * v2.z)
elseif type(v2) == 'number' then
return vec_3d(v1.x * v2, v1.y * v2, v1.z * v2)
else
return vec_3d(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z)
end
end,
__div = function(v1,v2)
if type(v1) == 'number' then
return vec_3d(v1 / v2.x, v1 / v2.y, v1 / v2.z)
elseif type(v2) == 'number' then
return vec_3d(v1.x / v2, v1.y / v2, v1.z / v2)
else
return vec_3d(v1.x / v2.x, v1.y / v2.y, v1.z / v2.z)
end
end,
__index = function(v,key)
if key == 'norm' then
local len = math.sqrt( v.x^2 + v.y^2 + v.z^2 )
v.norm = vec_3d( v.x / len, v.y / len, v.z / len )
return v.norm
end
end
}
---------------------------------------
-----end type defs-----start maths-----
---------------------------------------
normalize_2d = function(v)
local len = math.sqrt( math.abs( v[1]*v[1] ) + math.abs( v[2]*v[2] ) )
v[1], v[2] = v[1] / len, v[2] / len
end
normalize_3d = function(v)
local len = math.sqrt( math.abs( v[1]*v[1] ) + math.abs( v[2]*v[2] ) + math.abs( v[3]*v[3] ) )
v[1], v[2], v[3] = v[1] / len, v[2] / len, v[3] / len
end
multmat = function(mat1,mat2) --multiply a couple 3x3 matricies
local mat3 = {}
mat3[1] = (mat1[1] * mat2[1]) + (mat1[2] * mat2[4]) + (mat1[3] * mat2[7])
mat3[2] = (mat1[1] * mat2[2]) + (mat1[2] * mat2[5]) + (mat1[3] * mat2[8])
mat3[3] = (mat1[1] * mat2[3]) + (mat1[2] * mat2[6]) + (mat1[3] * mat2[9])
mat3[4] = (mat1[4] * mat2[1]) + (mat1[5] * mat2[4]) + (mat1[6] * mat2[7])
mat3[5] = (mat1[4] * mat2[2]) + (mat1[5] * mat2[5]) + (mat1[6] * mat2[8])
mat3[6] = (mat1[4] * mat2[3]) + (mat1[5] * mat2[6]) + (mat1[6] * mat2[9])
mat3[7] = (mat1[7] * mat2[1]) + (mat1[8] * mat2[4]) + (mat1[9] * mat2[7])
mat3[8] = (mat1[7] * mat2[2]) + (mat1[8] * mat2[5]) + (mat1[9] * mat2[8])
mat3[9] = (mat1[7] * mat2[3]) + (mat1[8] * mat2[6]) + (mat1[9] * mat2[9])
return mat3
end
matxvec = function(mat,vec) --multiply a vextor by a matrix
local x = (mat[1] * vec[1]) + (mat[2] * vec[2]) + (mat[3] * vec[3])
local y = (mat[4] * vec[1]) + (mat[5] * vec[2]) + (mat[6] * vec[3])
local z = (mat[7] * vec[1]) + (mat[8] * vec[2]) + (mat[9] * vec[3])
vec[1],vec[2],vec[3] = x,y,z
return vec
end
rotnorm = function(norm,angs) --rotates a normal, in theory
local matx = {1,0,0,0,1,0,0,0,1}
local maty = {1,0,0,0,1,0,0,0,1} --create 3x3 matrix arrays for xyz and fill it in with an identity matrix
local matz = {1,0,0,0,1,0,0,0,1}
matx[5] = math.cos(angs[1])
matx[6] = math.sin(angs[1])
matx[8] = -math.sin(angs[1])
matx[9] = math.cos(angs[1])
maty[1] = math.cos(angs[2])
maty[3] = -math.sin(angs[2]) --fill in the nessicary parts of the matrix for each axis
maty[7] = math.sin(angs[2])
maty[9] = math.cos(angs[2])
matz[1] = math.cos(angs[3])
matz[2] = math.sin(angs[3])
matz[4] = -math.sin(angs[3])
matz[5] = math.cos(angs[3])
local mat = multmat(matx,maty) --multiply our matrixies
mat = multmat(mat,matz) --to get total matrix
norm = matxvec(mat,norm) --apply the matrix
return norm
end
rotpoint = function(norm,angs,axis) --point rotation
local mat = {1,0,0,0,1,0,0,0,1} --create 3x3 matrix arrays for xyz and fill it in with an identity matrix
local c = math.cos(angs)
local s = math.sin(angs)
local t = 1 - math.cos(angs)
mat[1] = t * axis[1]^2 + c
mat[2] = t * axis[1] * axis[2] + s * axis[3]
mat[3] = t * axis[1] * axis[3] - s * axis[2]
mat[4] = t * axis[1] * axis[2] - s * axis[3]
mat[5] = t * axis[2]^2 + c
mat[6] = t * axis[2] * axis[3] + s * axis[1]
mat[7] = t * axis[1] * axis[3] + s * axis[2]
mat[8] = t * axis[2] * axis[3] - s * axis[1]
mat[9] = t * axis[3]^2 + c
norm = matxvec(mat,norm) --apply the matrix
return norm
end
---------------------------------------------
-----end maths-----start transformations-----
---------------------------------------------
transmodel = function(m, t)
for i=1, #m do
local pnt = m[i]
pnt[1] = pnt[1] + (t[1] or t.x)
pnt[2] = pnt[2] + (t[2] or t.y)
pnt[3] = pnt[3] + (t[3] or t.z)
m[i] = pnt
end
return m
end
rotmodel = function(m, r)
local posx = m[1][1]
local posy = m[1][2]
local posz = m[1][3]
m = transmodel(m, {-posx,-posy,-posz})
for i=1, #m do
if r[3] ~= 0 then m[i] = rotpoint(m[i], r[3], m[2]) end
if r[2] ~= 0 then m[i] = rotpoint(m[i], r[2], m[3]) end
if r[1] ~= 0 then m[i] = rotpoint(m[i], r[1], m[4]) end
end
m = transmodel(m, {posx,posy,posz} )
return m
end
project = function(vec)
local X = cx + ( ((vec[1] or vec.x) / (vec[3] or vec.z)) * cx )
local Y = cy + (-((vec[2] or vec.y) / (vec[3] or vec.z)) * cy * (w/h) )
return X,Y
end
--------------------------------------------------
-----end transformations-----start rendering------
--------------------------------------------------
drawline = function(v1, v2)
SDL.SDL_LockSurface(screen)
local xd = v1.x - v2.x
local yd = v1.y - v2.y
xd = xd/200
yd = yd/200
SDL.SDL_LockSurface(screen)
for i=1, 200, 1 do
local x,y = v1.x - i*xd,v1.y - i*yd
if x > 0 and y > 0 and x < w and y < h then
SDL.SDL_PutPixel(screen, x,y , blue)
end
end
SDL.SDL_UnlockSurface(screen)
end
drawmodel = function(m)
for i=6, #m - 1, 1 do
drawline( vec_2d( project( m[i] ) ),vec_2d( project( m[i+1] ) ) )
end
end
----------------------------------------------------------
-----start rendering-----start declarations and calls-----
----------------------------------------------------------
model = { {0,0,0},{0,0,1},{0,1,0},{1,0,0},{0,0,5000}, ---heh cobra mk3, format is position, fvec, uvec, svec, model
{0, 15, 0}, --index 5
{0, 15, -32.5},
{44, 10, -32.5},
{65, -3, -32.5},
{60, -3, -13}, --use 9 for gun 1
{16, -0.5, 32.5}, --index 10
{-16, -0.5, 32.5},
{-60, -3, -13}, --and 12 for gun 2
{-65, -3, -32.5},
{-44, 10, -32.5},
{0, 15, 0},
{44, 10, -32.5},
{60, -3, -13},
{16, -0.5, 32.5},
{0, 15, 0},
{-16, -0.5, 32.5},
{-60, -3, -13},
{-44, 10, -32.5},
{0, 15, -32.5},
{16, -15, -32.5},
{-16, -15, -32.5},
{-60, -3, -13},
{-65, -3, -32.5},
{-44, 10, -32.5},
{0, 15, -32.5},
{-16, -15, -32.5},
{-65, -3, -32.5},
{-16, -15, -32.5},
{-16, -0.5, 32.5},
{16, -0.5, 32.5},
{16, -15, -32.5},
{65, -3, -32.5},
{60, -3, -13},
{16, -15, -32.5}
}
model = transmodel(model, {0,0,200} )
vel = {0,0,0}
rot = {0,0,0}
drift = vec_3d(0,0,0)
shot = 0
-------------------------
-----start main loop-----
-------------------------
repeat
local event = SDL.SDL_Event_local()
SDL.SDL_PollEvent(event)
local key = event.key.keysym.sym
if event.type == SDL.SDL_KEYDOWN then
if key == SDL.SDLK_KP_MINUS then joyon = true end
if key == SDL.SDLK_SPACE then fire = 1 end
if key == SDL.SDLK_KP_PERIOD then kill = true end
if key == SDL.SDLK_KP8 then rot[1] = -0.01 end
if key == SDL.SDLK_KP2 then rot[1] = 0.01 end
if key == SDL.SDLK_KP4 then rot[2] = 0.01 end
if key == SDL.SDLK_KP6 then rot[2] = -0.01 end
if key == SDL.SDLK_KP7 then rot[3] = -0.01 end
if key == SDL.SDLK_KP9 then rot[3] = 0.01 end
if key == SDL.SDLK_KP1 then vel[1] = -0.001 end
if key == SDL.SDLK_KP3 then vel[1] = 0.001 end
if key == SDL.SDLK_KP_PLUS then vel[2] = 0.001 end
if key == SDL.SDLK_KP_ENTER then vel[2] = -0.001 end
if key == SDL.SDLK_KP5 then vel[3] = 0.005 end
if key == SDL.SDLK_KP0 then vel[3] = -0.001 end
elseif event.type == SDL.SDL_KEYUP then
if key == SDL.SDLK_SPACE then fire = 0 end
if key == SDL.SDLK_KP8 or key == SDL.SDLK_KP2 then rot[1] = 0 end
if key == SDL.SDLK_KP4 or key == SDL.SDLK_KP6 then rot[2] = 0 end
if key == SDL.SDLK_KP7 or key == SDL.SDLK_KP9 then rot[3] = 0 end
if key == SDL.SDLK_KP1 or key == SDL.SDLK_KP3 then vel[1] = 0 end
if key == SDL.SDLK_KP_PLUS or key == SDL.SDLK_KP_ENTER then vel[2] = 0 end
if key == SDL.SDLK_KP0 or key == SDL.SDLK_KP5 then vel[3] = 0 end
end
if SDL.SDL_NumJoysticks() and joyon then
stick = SDL.SDL_JoystickOpen(0)
axes = SDL.SDL_JoystickNumAxes(stick)
balls = SDL.SDL_JoystickNumHats(stick)
print(balls)
axisx = SDL.SDL_JoystickGetAxis(stick, 0)
axisy = SDL.SDL_JoystickGetAxis(stick, 1)
axisz = SDL.SDL_JoystickGetAxis(stick, 2)
axisx2 = SDL.SDL_JoystickGetAxis(stick, 3)
axisy2 = SDL.SDL_JoystickGetAxis(stick, 4)
axisz2 = SDL.SDL_JoystickGetAxis(stick, 5)
axisx = axisx / 32768 --get sdl axes down to a -1 to 1 scale
axisy = axisy / 32768
axisz = -axisz / 32768
axisx2 = -axisx2 / 32768
axisy2 = axisy2 / 32768
axisz2 = axisz2 / 32768
if axes > 4 then vel[1] = axisy2 / 1000 end --check to make sure the axis exists before using it if no axis exists then use keyboard
if axes > 5 then vel[2] = axisz2 / 1000 end
if axes > 2 then vel[3] = (axisz + 0.333) / 333 end --throttle axis has 5x more forward than backward thrust
if axes > 1 then rot[1] = axisy / 100 end
if axes > 3 then rot[2] = axisx2 / 100 end
if axes > 0 then rot[3] = axisx / 100 end
fire = SDL.SDL_JoystickGetButton(stick, 0)
if SDL.SDL_JoystickGetButton(stick, 1) == 1 then --button 2 closes the stick and goes back to kb mode till kp- is hit again
joyon = false
SDL.SDL_JoystickClose(stick)
end
end
SDL.SDL_FillRect(screen, rect, grey)
muc = vec_3d( model[1] )
muf = vec_3d( model[2] )
muu = vec_3d( model[3] )
mus = vec_3d( model[4] )
meow = ( (mus - muc) * vel[1] )+( (muu - muc) * vel[2] )+( (muf - muc) * vel[3] )
drift = drift + meow
model = transmodel(model, drift)
model = rotmodel(model, rot)
drawmodel(model)
if fire == 1 then
shot = math.random(-5,5)
if shot > 0 then drawline(vec_2d(project(model[10])),vec_2d(project(model[5]))) end
if shot < 0 then drawline(vec_2d(project(model[13])),vec_2d(project(model[5]))) end
end
SDL.SDL_UpdateRect(screen, 0, 0, 0, 0)
until kill ~= nil
--- End code ---
btw controls are
kp7,9 or joy x - roll
kp8,2 or joy y = pitch
kp5,0 or joy z = throttle
kp4,6 or joy twist = yaw
kp1,3 or joy axis 5 = lateral thrust
kp+,enter or joy axis 6 = verticle thrust
space or joy button 1 = fire laser
kp- enable joystick
joy button 2 stop using stick
kpdel end program
kp- turns on joystick
axes override keys if they exist.
Navigation
[0] Message Index
Go to full version