This application was designed specifically to teach the idea of 3D game design. While this engine was built with simplicity in mind, it was also built to maximize efficiency and minimize the computation required to display good looking graphics. With that said this is an excellent engine to make 3D games, I don't ask for any credit, and anyone can use this program for their own purposes.
Use the comment section below for help, or if you have any questions, I'll be glad to help!
To see the power of SIM.3D, I added some regular demos that will give a better idea on how to use SIM.3D. The files include:
Doing so will load the 3D engine into program slot 3, then insert the code from program slot 0 into program slot 3, then execute itself.
the full documentation of SIM.3D
The most basic application to rotate a cube in the center of the screen is as follows:
PRGEDIT 3 EXEC "PRG3:3D.ENGINE" END
VAR C=ADDCUBE(0,0,0,1,1,1,#GRAY)
@LOOP
VSYNC
ROTOBJ C,0,1,0
RENDER
GOTO @LOOP
There are a few things to be aware of before diving into the 3D engine
- One in-world unit is the equivalent of 50 pixels from the default camera position. Adding a scale definition like this makes the game feel more realistic. This can be customized by changing the WSC (world scaling constant) variable.
- When working with SIM.3D, you must work in the default program slot 0, you will need to save every time you run the code. Any errors can be traced to your code in program slot 3 where the actual engine is.
- Or you could work directly in the 3D engine and avoid the use of the loader. There's a spot in the beginning of the code dedicated for user programs to go.
- Every object is composed of triangles. If a triangle is defined clockwise then it will be visible from the outside of the object. There are preset objects to make this easier to work with.
- So triangles can only be seen from one side (for higher performance), using STRETCHOBJ with negative values to stretch an object inside-out will let you see the object's back faces instead of front
- Every object is given an index. This index will never change until the object is deleted, in which case the ID will be given to the next future object to be defined.
Engine variables:VAR CAMX,CAMY,CAMZ
VAR CAMRX,CAMRY,CAMRZ
VAR CAMDIST
VAR FOV
VAR WSC
VAR CUTOFF_RATIO
VAR BOUNDCAMANGLES
VAR RENDERDIST
VAR ACCELERATED_RENDERING
VAR FPS
VAR GMW0,GMH0
VAR GMW1,GMH1
VAR GMW05,GMH05
Here are the preset object definitions:ADDCUBE(X,Y,Z,LENGTH,WIDTH,HEIGHT,COLOR)
ADDWCUBE(X,Y,Z,LENGTH,WIDTH,HEIGHT,COLOR)
ADDSPHERE(X,Y,Z,RADIUS,COLOR)
ADDLINE(X1,Y1,Z1,X2,Y2,Z2,COLOR)
ADDPYRAMID(X,Y,Z,WIDTH,HEIGHT,COLOR)
ADDDIAMOND(X,Y,Z,WIDTH,HEIGHT,COLOR)
ADDCRYSTAL(X,Y,Z,WIDTH,HEIGHT,COLOR)
ADDSKYBOX(X,Y,Z,LENGTH,WIDTH,HEIGHT,COLOR)
ADDSURFACE(X,Y,Z,GRIDX,GRIDY,LENGTH,WIDTH,COLOR)
ADDFLAG(X,Y,Z,COLOR)
ADDTEXT X,Y,Z,TEXT$,COLOR
You may also consider defining your own objectADDOBJ(TYPE$,X[],Y[],Z[],COLOR)
Every object contains these variables:OBJX
OBJY
OBJZ
OBJTEXT$
OBJTAG$
ONJTYPE$
OBJINDEX
OBJLENGTH
OBJRX
OBJRY
OBJRZ
OBJSX
OBJSY
OBJRZ
OBJMINX
OBJMINY
OBJMINZ
OBJMAXX
OBJMAXY
OBJMAXZ
OBJVX
OBJVY
OBJVZ
OBJVISSTATIC
OBJMASK
OBX[OBJMASK[MY_OBJECT_INDEX]]=FOO
Here is a list of object functionsSTRETCHOBJ INDEX,SCALEX,SCALEY,SCALEZ
MOVEOBJ INDEX,DX,DY,DZ
MOVEOBJTO INDEX,X,Y,Z
ROTOBJ INDEX,AX,AY,AZ
ROTOBJTO INDEX,AX,AY,AZ
ROTOBJAROUND INDEX,X,Y,Z,AX,AY,AZ
ROTOBJAROUNDOBJ INDEX,INDEX2,AX,AY,AZ
ROTOBJTOPOINT INDEX,X,Y,Z
MERGEOBJS(INDEX1,INDEX2)
SPLITOBJ INDEX,TRIANGLES OUT INDEX1,INDEX2
DELOBJ INDEX : INDEX=-1
CHANGEOBJCOLOR INDEX,COLOR
CHANGEOBJFACECOLOR INDEX,FACE,COLOR
CHANGEOBJCOLORAB OBJECT,INDEX1,INDEX2,COLOR
SETTAG INDEX,TAG$
GETTAG$(INDEX)
FINDIBJBYTAG(TAG$)
SETSTR INDEX,S$
GETSTR$(INDEX)
FINDIBJBYSTR(S$)
GETOBJTYPE$(INDEX)
"CUBE","SPHERE","DIAMOND","CRYSTAL","PYRAMID","SKYBOX","LINE","SURFACE","TEXT",etc...
GETOBJSBYDIST(X,Y,Z)
UPDATEWCUBEAROUNDOBJ INDEX1,INDEX2
APPLYSURFACEEQUATION INDEX,EQU$,MINY,MAXY,SCX,SCY,SCZ
GETUNMASKEDINDEX(MASKEDINDEX)
UPDATEOBJCENTER INDEX
SETSTATICOBJ INDEX,STATE
ADDVEL INDEX,VX,VY,VZ
And a few other functions, slightly unrelated, but implemented nonetheless:RENDER
BUFFER
_RENDER
BUFFERBOTTOM
GETCAMRAY OUT X,Y,Z
GETCAMRAY2D OUT X,Z
RAYTHROUGHOBJ(X,Y,Z,RX,RY,RZ,INDEX)
NORMALIZE X,Y,Z OUT X,Y,Z
CLEARWORLD
ADDTRI INDEX,TAG$,X1,Y1,Z1,X2,Y2,Z2,X3,Y3,Z3,COLOR
SETTRI INDEX,X1,Y1,Z1,X2,Y2,Z2,X3,Y3,Z3
DELTRI TRIANGLEINDEX
SPLITSCREENDRAW X1,Y1,Z1,RX1,RY1,RZ1,X2,Y2,Z2,RX2,RY2,RZ2
QUADRUPLEDRAW X1,Y1,Z1,RX1,RY1,RZ1,X2,Y2,Z2,RX2,RY2,RZ2,X3,Y3,Z3,RX3,RY3,RZ3,X4,Y4,Z4,RX4,RY4,RZ4
ROT X,Y,Z,ORIGINX,ORIGINY,ORIGINZ,ANGLEX,ANGLEY,ANGLEZ OUT X,Y,Z
ROTX X,Y,Z,ANGLE OUT X,Y,Z
ROTY X,Y,Z,ANGLE OUT X,Y,Z
ROTZ X,Y,Z,ANGLE OUT X,Y,Z
INSERT ARRAY[],INDEX,VALUE
REMOVE ARRAY[],INDEX
TRIM$(S$)
HSV2RGB HUE,SATURATION,VALUE OUT RED,GREEN,BLUE
RGB2HSV RED,GREEN,BLUE OUT HUE,SATURATION,VALUE
HSV(HUE,SATURATION,VALUE)
FCIRCLE X,Y,RADIUS,FILLCOLOR,BORDERCOLOR
TEXT X,Y,TEXT$,COLOR
PERSPECTIVE X,Y,Z OUT X,Y,Z
PERSPECTIVEZ(X,Y,Z)
ARYOP_PERSPECTIVE X[],Y[],Z[] OUT X[],Y[],Z[]
some examples of SIM.3D usage
Four cubes with one smaller one orbiting around it, supports moving the camera using the circle padPRGEDIT 3 EXEC "PRG3:3D.ENGINE" END
VAR STX,STY,C
C=ADDCUBE(0,0,0,1,1,1,#GRAY)
C=ADDCUBE(0,1.5,0,1,1,1,#GREEN)
C=ADDCUBE(1.5,0,0,1,1,1,#CYAN)
C=ADDCUBE(0,0,1.5,1,1,1,#WHITE)
C=ADDCUBE(0,0,3,0.5,0.5,0.5,HSV(0,255,255))
@LOOP
VSYNC
STICK OUT STX,STY
CAMRX=CAMRX-STX*5
CAMRY=CAMRY-STY*5
ROTOBJAROUND C,0,0,0,1,1,0
RENDER
GOTO @LOOP
You are a cube, you can rotate your camera and move around the world. In the world there is a large 3D Sierpinski tetrahedron fractal generated recursivelyPRGEDIT 3 EXEC "PRG3:3D.ENGINE"
VAR I,J
I=ADDSKYBOX(0,5,50,120,120,120,RGB(60,60,60))
VAR PLAYER=ADDCUBE(0,0,0,1,1,1,#WHITE)
VAR BTN,STX,STY,X,Y,Z
SIERPINSKI 0,30,50,40,50,3,RND(360),150,255
@LOOP
VSYNC
CLS
PRINT "FPS ";FPS
MOVEOBJTO PLAYER,CAMX,CAMY,CAMZ
CONTROLS
IF CAMRY<-90 THEN CAMRY=-90
IF CAMRY>90 THEN CAMRY=90
RENDER
GOTO @LOOP
DEF CONTROLS
STICK OUT STX,STY
BTN=BUTTON()
DEC CAMRX,STX*6*COSCAMRZ
DEC CAMRY,STY*6*COSCAMRZ
IF BTN AND #UP THEN CAMDIST=CAMDIST/1.05
IF BTN AND #DOWN THEN CAMDIST=CAMDIST*1.05
IF BTN AND #X THEN
VAR X,Y,Z
GETCAMRAY OUT X,Y,Z
INC CAMX,X/2
INC CAMY,Y/2
INC CAMZ,Z/2
ENDIF
IF BTN AND #B THEN
VAR X,Y,Z
GETCAMRAY OUT X,Y,Z
DEC CAMX,X/2
DEC CAMY,Y/2
DEC CAMZ,Z/2
ENDIF
END
DEF SIERPINSKI X,Y,Z,W_,H_,DEPTH,HU,SA,VA
VAR I,W=W_*0.5,H=H_*0.5
IF DEPTH==0 THEN
I=ADDPYRAMID(X,Y,Z,W_*2,H_,HSV(HU,SA,VA))
ELSE
SIERPINSKI X,Y-H,Z,W,H,DEPTH-1,HU+100,SA,VA
SIERPINSKI X-W,Y,Z-W,W,H,DEPTH-1,HU,SA,VA
SIERPINSKI X-W,Y,Z+W,W,H,DEPTH-1,HU,SA,VA
SIERPINSKI X+W,Y,Z-W,W,H,DEPTH-1,HU,SA,VA
SIERPINSKI X+W,Y,Z+W,W,H,DEPTH-1,HU,SA,VA
ENDIF
END
