3D cube drawing

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
neil
Posts: 594
Joined: Mar 17, 2022 23:26

Re: 3D cube drawing

Post by neil »

Here's my floating cube on the moon demo. You can experiment with the gravity effect.
Changing ge to 0.01 will change the gravity effect, or changing the gravity to 0.05, you can just experiment.
Use the arrow keys to control the cube.

Code: Select all

' Floating cube on the moon by neil
' Use the arrow keys to control the cube.

Declare Sub delay(ByVal amt As Single, ByVal thr As Ulong = 2)

Sub delay(ByVal amt As Single, ByVal thr As Ulong)
    Dim As Double t1 = Timer
    Dim As Double t2 = t1 + amt / 1000
    If amt > thr + 0.5 Then Sleep amt - thr, 1
    Do
    Loop Until Timer >= t2
End Sub

Dim As Single ge,x,y,x1,x2,y1,y2,velocity_y,velocity_x,gravity
Dim As Ubyte dr,Red,Green,Blue
ScreenRes 1280,720,32
setmouse 0,0,0

Dim As Any Ptr cube = ImageCreate( 402, 402, RGB(0, 0, 0))

'gravity effect default: ge = 0.05:gravity = .005
'changing ge to 0.01 will change the gravity effect, or changing the gravity to 0.05
ge = 0.05:gravity = .005

Red = 255:Green = 255:blue = 0

LINE cube, (100,100)-(100,300), RGBA(Red, Green, Blue,255)
LINE cube, (100,100)-(300,100), RGBA(Red, Green, Blue,255)
LINE cube, (300,100)-(300,300), RGBA(Red, Green, Blue,255)
LINE cube, (300,300)-(100,300), RGBA(Red, Green, Blue,255)

LINE cube, (200,200)-(200,400), RGBA(Red, Green, Blue,255)
LINE cube, (200,200)-(400,200), RGBA(Red, Green, Blue,255)
LINE cube, (400,200)-(400,400), RGBA(Red, Green, Blue,255)
LINE cube, (400,400)-(200,400), RGBA(Red, Green, Blue,255)

LINE cube, (100,100)-(200,200), RGBA(Red, Green, Blue,255)
LINE cube, (100,300)-(200,400), RGBA(Red, Green, Blue,255)
LINE cube, (300,100)-(400,200), RGBA(Red, Green, Blue,255)
LINE cube, (300,300)-(400,400), RGBA(Red, Green, Blue,255)

sleep 500,1
color 14, 0
Cls

x = 300: y = -94:x2 = x: y2 = y
velocity_y = .05:velocity_x = .05

' Main Loop
DO
 Screenlock
 Cls
 Put (X, Y), cube,alpha
 Screenunlock
 
 ' adjust as needed
 delay 10

 x2 = x:y2 = y
 dr = 0
 IF multikey(&H4D) AND MULTIKEY(&H4B) = 0 Then dr = 1 ' right arrow
 IF multikey(&H4B) AND MULTIKEY(&H4D) = 0 Then dr = 2 ' left arrow
 IF multikey(&H48) AND MULTIKEY(&H50) = 0 Then dr = 3 ' up  arrow
 IF multikey(&H50) AND MULTIKEY(&H48) = 0 Then dr = 4 ' down arrow

 IF multikey(&H01) THEN Exit Do ' Escape Key
 velocity_y = velocity_y + gravity

 y = y + velocity_y
 
 'update velocity_x
 x = x + velocity_x
 if y >= 312 Then y = 312:velocity_y -= ge
 if y <= -94 Then y = -94:velocity_y += ge
 if x <= -92 Then x = -92:velocity_x += ge
 if x >= 872 Then x = 872:velocity_x -= ge

  'right direction
 if dr = 1 THEN velocity_x = velocity_x + ge
 'left direction
 if dr = 2 THEN velocity_x = velocity_x - ge
 'up direction
 if dr = 3 THEN velocity_y = velocity_y - ge
 'down direction
 if dr = 4 THEN velocity_y = velocity_y + ge

Loop Until inkey = (Chr(255) & "k")
ImageDestroy cube

End
Last edited by neil on Jan 11, 2024 8:01, edited 2 times in total.
neil
Posts: 594
Joined: Mar 17, 2022 23:26

Re: 3D cube drawing

Post by neil »

I updated my floating cube on the moon. It was flickering. I put Screenlock before Cls.
It seems to be OK now. I added part of fxm's timer regulator, and it runs smoother on all PCs.
To slow it down or speed it up, use delay 8.2 or delay 10, etc.
neil
Posts: 594
Joined: Mar 17, 2022 23:26

Re: 3D cube drawing

Post by neil »

A Tunnel effect. Maybe?
Remove the comment on lines 14 or 15 to reverse it.

Code: Select all

DIM AS Integer h,w,col,x
Dim As String key
W =  680
H =  680

screenres w, h, 32
setmouse 0,0,0

col = 64

DO 
key = inkey
     
For x = w / 2 TO 1 Step -1 'forward
' For x = 1 to w / 2 'reverse

  Line (w / 2 - x, h / 2 - x)-(w / 2 - 1 + x, h / 2 - 1 + x), rgb(80,col,80), B
  col = col + 4
  If col >= 256 Then col = 64
Next

    sleep 60,1
Loop Until (key = Chr(27)) Or (key = Chr(255) & "k")
End
neil
Posts: 594
Joined: Mar 17, 2022 23:26

Re: 3D cube drawing

Post by neil »

Here's a transparent rotating 3D cube.

Code: Select all

#define PI 3.14159265358979323
#define Scale 100
#define Size 500
#define zoff 0.5773502691896257645091487805019574556
#define cylr 1.6329931618554520654648560498039275946
screenres 500,500,32
Dim as double theta = 0.0, dtheta = 1.5, x(0 to 5), lasttime, dt = 1./30
Dim as double cylphi(0 to 5) = {PI/6, 5*PI/6, 3*PI/2, 11*PI/6, PI/2, 7*PI/6}
Dim As String key

sub drawcube( x() as double, colr as uinteger )
    colr = rgb(255,255,0)
    Screenlock
    Cls
    For i as uinteger = 0 to 2
        Line (Size/2, Size/2-Scale/zoff) - (x(i), Size/2-Scale*zoff), colr
        Line (Size/2, Size/2+Scale/zoff) - (x(5-i), Size/2+Scale*zoff), colr
        Line ( x(i), Size/2-Scale*zoff ) - ( x(i mod 3 + 3), Size/2+Scale*zoff ), colr
        Line ( x(i), Size/2-Scale*zoff ) - ( x((i+1) mod 3 + 3), Size/2+Scale*zoff ), colr
    Next
Screenunlock
end sub

Do
    key = Inkey
    For i as uinteger = 0 to 5
        x(i) = Size/2 + Scale*cylr*cos(cylphi(i)+theta)
    Next

    drawcube x(), rgb(255,255,0)
    sleep 40,1
    theta += dtheta  * (0.03)
Loop Until (key = Chr(27)) Or (key = Chr(255) & "k")
End
neil
Posts: 594
Joined: Mar 17, 2022 23:26

Re: 3D cube drawing

Post by neil »

It's time to make a clock. A swinging pendulum.

Code: Select all

' a swinging pendulum

Const PI = 3.141592920
Dim As Double theta, g, l, accel, speed, px, py, bx, by
Dim As String key
theta = PI/2
g = 9.81
l = 1
speed = 0
px = 320
py = 10
Screen 18
Do
    key = Inkey
    bx=px+l*300*Sin(theta)
    by=py-l*300*Cos(theta)
    Cls
    Line (px,py)-(bx,by)
    Circle (bx,by),5,,,,,F
    accel=g*Sin(theta)/l/100
    speed=speed+accel/100
    theta=theta+speed
    Draw String (0,370), "Pendulum"
    Draw String (0,385), "Press Esc key to quit"
    Sleep 20
Loop Until (key = Chr(27)) Or (key = Chr(255) & "k")
neil
Posts: 594
Joined: Mar 17, 2022 23:26

Re: 3D cube drawing

Post by neil »

Drawing a sphere without using the Circle Function.

Code: Select all

' drawing a sphere without using the Circle Function

#Define W 640
#Define H 480

ScreenRes W, H, 32

Dim As UInteger R = 100, R2 = R * R          
Dim As UInteger X0 = W / 2, Y0 = H / 2       
Dim As Integer X, Y, C, D2                   
   
For Y = -R To R                              
  For X = -R To R                            
 D2 = X * X + Y * Y 
  If D2 <= R2 Then                         
    C = Sqr(R2 - D2) - ( X + Y) / 2 + 130  
    Color C Shl 8 + C 
    PSet(X + X0, Y + Y0)
  End If
  Next 
Next 

Locate 50,2
Color(RGB(255,255,255),RGB(0,0,0))
Print "Press any key to exit program"
Sleep
End
neil
Posts: 594
Joined: Mar 17, 2022 23:26

Re: 3D cube drawing

Post by neil »

OpenGL 3D cuboid demo.

Code: Select all

' OpenGL 3D cuboid demo

#include once "GL/gl.bi"
#include once "GL/glu.bi"

dim rquad as single

screen 18, 16, , 2

glViewport 0, 0, 640, 480                      '' Reset The Current Viewport
glMatrixMode GL_PROJECTION                     '' Select The Projection Matrix
glLoadIdentity                                 '' Reset The Projection Matrix
gluPerspective 45.0, 640.0/480.0, 0.1, 100.0   '' Calculate The Aspect Ratio Of The Window
glMatrixMode GL_MODELVIEW                      '' Select The Modelview Matrix
glLoadIdentity                                 '' Reset The Modelview Matrix
glShadeModel GL_SMOOTH                         '' Enable Smooth Shading
glClearColor 0.0, 0.0, 0.0, 0.5                '' Black Background
glClearDepth 1.0                               '' Depth Buffer Setup
glEnable GL_DEPTH_TEST                         '' Enables Depth Testing
glDepthFunc GL_LEQUAL                          '' The Type Of Depth Testing To Do
glHint GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST    '' Really Nice Perspective Calculations
do
	glClear GL_COLOR_BUFFER_BIT OR GL_DEPTH_BUFFER_BIT      '' Clear Screen And Depth Buffer
	glLoadIdentity                                          '' Reset The Current Modelview Matrix
   	
	glLoadIdentity                                          '' Reset The Current Modelview Matrix
	glTranslatef 0.0, 0.0, -7.0                             '' Move Right 1.5 Into The Screen 7.0
	glRotatef rquad,1.0, 1.0, 1.0                           '' Rotate The Quad On The X axis ( NEW )
   		
	glBegin GL_QUADS                                        '' Draw A Quad
    glColor3f 0.0, 1.0, 0.0                              '' Set The Color To Blue
    glVertex3f 1.0, 1.5, -2.0                            '' Top Right Of The Quad (Top)
    glVertex3f -1.0, 1.5, -2.0                           '' Top Left Of The Quad (Top)
    glVertex3f -1.0, 1.5, 2.0                            '' Bottom Left Of The Quad (Top)
    glVertex3f 1.0, 1.5, 2.0                             '' Bottom Right Of The Quad (Top)
		    
    glColor3f 1.0, 0.5, 0.0                              '' Set The Color To Orange
    glVertex3f 1.0, -1.5, 2.0                            '' Top Right Of The Quad (Bottom)
    glVertex3f -1.0, -1.5, 2.0                           '' Top Left Of The Quad (Bottom)
    glVertex3f -1.0, -1.5, -2.0                          '' Bottom Left Of The Quad (Bottom)
    glVertex3f 1.0, -1.5, -2.0                           '' Bottom Right Of The Quad (Bottom)
		    
    glColor3f 1.0, 0.0, 0.0                              '' Set The Color To Red
    glVertex3f 1.0, 1.5, 2.0                             '' Top Right Of The Quad (Front)
    glVertex3f -1.0, 1.5, 2.0                            '' Top Left Of The Quad (Front)
    glVertex3f -1.0, -1.5, 2.0                           '' Bottom Left Of The Quad (Front)
    glVertex3f 1.0, -1.5, 2.0                            '' Bottom Right Of The Quad (Front)
		    
    glColor3f 1.0, 1.0, 0.0                              '' Set The Color To Yellow
    glVertex3f 1.0, -1.5, -2.0                           '' Top Right Of The Quad (Back)
    glVertex3f -1.0, -1.5, -2.0                          '' Top Left Of The Quad (Back)
    glVertex3f -1.0, 1.5, -2.0                           '' Bottom Left Of The Quad (Back)
    glVertex3f 1.0, 1.5, -2.0                            '' Bottom Right Of The Quad (Back)
		    
    glColor3f 0.0, 0.0, 1.0                              '' Set The Color To Blue
    glVertex3f -1.0, 1.5, 2.0                            '' Top Right Of The Quad (Left)
    glVertex3f -1.0, 1.5, -2.0                           '' Top Left Of The Quad (Left)
    glVertex3f -1.0, -1.5, -2.0                          '' Bottom Left Of The Quad (Left)
    glVertex3f -1.0, -1.5, 2.0                           '' Bottom Right Of The Quad (Left)
		    
    glColor3f 1.0, 0.0, 1.0                              '' Set The Color To Violet
    glVertex3f 1.0, 1.5, -2.0                            '' Top Right Of The Quad (Right)
    glVertex3f 1.0, 1.5, 2.0                             '' Top Left Of The Quad (Right)
    glVertex3f 1.0, -1.5, 2.0                            '' Bottom Left Of The Quad (Right)
    glVertex3f 1.0, -1.5, -2.0                           '' Bottom Right Of The Quad (Right)
    glEnd                                                   '' Done Drawing The Quad

	rquad -= 0.15                                     

	flip
loop while inkey = ""
End
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: 3D cube drawing

Post by dodicat »

Hi neil.
If you like opengl here is a text method.
Also, better to include a sleep 1 in the loop.

Code: Select all

' OpenGL 3D cuboid demo

#include once "GL/gl.bi"
#include once "GL/glu.bi"

dim rquad as single
declare Sub drawstring(xpos As Long,ypos As Long,text As String ,col As Ulong,size As Single,xres As Long,yres As Long)
declare function framecounter as long 
screen 18, 16, , 2
dim as long xres,yres
screeninfo xres,yres

dim as string chars=string(255,0)
for n as long=0 to 255
    chars[n]=n
    next

glViewport 0, 0, 640, 480                      '' Reset The Current Viewport
glMatrixMode GL_PROJECTION                     '' Select The Projection Matrix
glLoadIdentity                                 '' Reset The Projection Matrix
gluPerspective 45.0, 640.0/480.0, 0.1, 100.0   '' Calculate The Aspect Ratio Of The Window
glMatrixMode GL_MODELVIEW                      '' Select The Modelview Matrix
glLoadIdentity                                 '' Reset The Modelview Matrix
glShadeModel GL_SMOOTH                         '' Enable Smooth Shading
glClearColor 0.0, 0.0, 0.0, 0.5                '' Black Background
glClearDepth 1.0                               '' Depth Buffer Setup
glEnable GL_DEPTH_TEST                         '' Enables Depth Testing
glDepthFunc GL_LEQUAL                          '' The Type Of Depth Testing To Do
glHint GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST    '' Really Nice Perspective Calculations
do
	glClear GL_COLOR_BUFFER_BIT OR GL_DEPTH_BUFFER_BIT      '' Clear Screen And Depth Buffer
	glLoadIdentity                                          '' Reset The Current Modelview Matrix
   	
	glLoadIdentity                                          '' Reset The Current Modelview Matrix
	glTranslatef 0.0, 0.0, -7.0                             '' Move Right 1.5 Into The Screen 7.0
	glRotatef rquad,1.0, 1.0, 1.0                           '' Rotate The Quad On The X axis ( NEW )
   		
	glBegin GL_QUADS                                        '' Draw A Quad
    glColor3f 0.0, 1.0, 0.0                              '' Set The Color To Blue
    glVertex3f 1.0, 1.5, -2.0                            '' Top Right Of The Quad (Top)
    glVertex3f -1.0, 1.5, -2.0                           '' Top Left Of The Quad (Top)
    glVertex3f -1.0, 1.5, 2.0                            '' Bottom Left Of The Quad (Top)
    glVertex3f 1.0, 1.5, 2.0                             '' Bottom Right Of The Quad (Top)
		    
    glColor3f 1.0, 0.5, 0.0                              '' Set The Color To Orange
    glVertex3f 1.0, -1.5, 2.0                            '' Top Right Of The Quad (Bottom)
    glVertex3f -1.0, -1.5, 2.0                           '' Top Left Of The Quad (Bottom)
    glVertex3f -1.0, -1.5, -2.0                          '' Bottom Left Of The Quad (Bottom)
    glVertex3f 1.0, -1.5, -2.0                           '' Bottom Right Of The Quad (Bottom)
		    
    glColor3f 1.0, 0.0, 0.0                              '' Set The Color To Red
    glVertex3f 1.0, 1.5, 2.0                             '' Top Right Of The Quad (Front)
    glVertex3f -1.0, 1.5, 2.0                            '' Top Left Of The Quad (Front)
    glVertex3f -1.0, -1.5, 2.0                           '' Bottom Left Of The Quad (Front)
    glVertex3f 1.0, -1.5, 2.0                            '' Bottom Right Of The Quad (Front)
		    
    glColor3f 1.0, 1.0, 0.0                              '' Set The Color To Yellow
    glVertex3f 1.0, -1.5, -2.0                           '' Top Right Of The Quad (Back)
    glVertex3f -1.0, -1.5, -2.0                          '' Top Left Of The Quad (Back)
    glVertex3f -1.0, 1.5, -2.0                           '' Bottom Left Of The Quad (Back)
    glVertex3f 1.0, 1.5, -2.0                            '' Bottom Right Of The Quad (Back)
		    
    glColor3f 0.0, 0.0, 1.0                              '' Set The Color To Blue
    glVertex3f -1.0, 1.5, 2.0                            '' Top Right Of The Quad (Left)
    glVertex3f -1.0, 1.5, -2.0                           '' Top Left Of The Quad (Left)
    glVertex3f -1.0, -1.5, -2.0                          '' Bottom Left Of The Quad (Left)
    glVertex3f -1.0, -1.5, 2.0                           '' Bottom Right Of The Quad (Left)
		    
    glColor3f 1.0, 0.0, 1.0                              '' Set The Color To Violet
    glVertex3f 1.0, 1.5, -2.0                            '' Top Right Of The Quad (Right)
    glVertex3f 1.0, 1.5, 2.0                             '' Top Left Of The Quad (Right)
    glVertex3f 1.0, -1.5, 2.0                            '' Bottom Left Of The Quad (Right)
    glVertex3f 1.0, -1.5, -2.0                           '' Bottom Right Of The Quad (Right)
    glEnd                                                   '' Done Drawing The Quad

	rquad -= 0.15 * 10 
    drawstring(10,0,"Frames per second "+str(framecounter),rgb(200,200,200),1,xres,yres)
    drawstring(10,20,"Some text for opengl:",rgb(0,200,0),1,xres,yres)
    drawstring(10,40,mid(chars,1,60),rgb(0,200,0),1,xres,yres)
    drawstring(10,60,mid(chars,60,60),rgb(0,200,0),1,xres,yres)
    drawstring(10,80,mid(chars,120,60),rgb(0,200,0),1,xres,yres)
    drawstring(10,100,mid(chars,180,60),rgb(0,200,0),1,xres,yres)
    drawstring(10,120,mid(chars,240),rgb(0,200,0),1,xres,yres)
    drawstring(10,400,"Press any key to quit",rgb(0,100,255),2,xres,yres)


	flip
    sleep 1,1
loop while inkey = ""
End

'================ TEXT =============================
Sub drawstring(xpos As Long,ypos As Long,text As String ,col As Ulong,size As Single,xres As Long,yres As Long)
    glMatrixMode GL_PROJECTION 'save projection
    glPushMatrix
    glMatrixMode GL_MODELVIEW
    glPushMatrix
   
    glMatrixMode GL_PROJECTION 'make ortho
    glLoadIdentity
    glOrtho 0, xres, yres, 0,-1, 1
    glMatrixMode GL_MODELVIEW
    glLoadIdentity
    #define Red(c) ((c) Shr 16 And 255)
    #define Green(c) ((c) Shr  8 And 255)
    #define Blue(c) ((c) And 255)
    #define Alph(c) ((c) Shr 24)
    glColor4ub Red(col),Green(col),Blue(col),alph(col)
    glend
    glpointsize(1.1*size)
    glBegin (GL_POINTS)
    Type D2
        As Single x,y
    End Type
    Static As d2 cpt(),XY()
    Static As Long runflag
    If runflag=0 Then   
        Redim  XY(128,255)
        Redim cpt(1 To 64*2)
        Screen 8
        Width 640\8,200\16
        Dim As Ulong Pointer img
        Dim count As Long
        For ch As Long=1 To 255
            img=Imagecreate(640,200)
            Draw String img,(1,1),Chr(ch)
            For x As Long=1 To 8
                For y As Long=1 To 16
                    If Point(x,y,img)<>0 Then
                        count=count+1
                        XY(count,ch)=Type<D2>(x,y)
                    End If
                Next y
            Next x
            count=0
            Imagedestroy img
        Next ch
        runflag=1
    End If
    If size=0 Then Exit Sub
    Dim As D2 np,t
    #macro Scale(p1,p2,d)
    np.x=d*(p2.x-p1.x)+p1.x
    np.y=d*(p2.y-p1.y)+p1.y
    #endmacro
   
    Dim As D2 c=Type<D2>(xpos,ypos)
    Dim As Long dx=xpos,dy=ypos
    For z6 As Long=1 To Len(text)
        Var asci=text[z6-1]
        For _x1 As Long=1 To 64*2
            t=Type<D2>(XY(_x1,asci).x+dx,XY(_x1,asci).y+dy)         
            Scale(c,t,size)
            cpt(_x1)=np
           
            If XY(_x1,asci).x<>0 Then
                If Abs(size)>0 Then
                    glVertex3f (cpt(_x1).x,(cpt(_x1).y),0)
                End If
            End If
        Next _x1
        dx=dx+8
    Next z6
    glend
    glMatrixMode GL_PROJECTION 'restore
    glPopMatrix
    glMatrixMode GL_MODELVIEW
    glPopMatrix
End Sub

Sub inittext Constructor
    drawstring(0,0,"",0,0,0,0)
End Sub

function framecounter as long static
    dim as long c,framerate
    dim as double t
    c += 1
	If Timer - t > 1 Then
		framerate = c
		c = 0
		t = Timer
	End If
    return framerate
end function


 
neil
Posts: 594
Joined: Mar 17, 2022 23:26

Re: 3D cube drawing

Post by neil »

@dodicat
Thanks for the OpenGL tips.
Do you have any 3D demo's of a icosahedron?
If doesn't have to be OpenGL FreeBasic is fine.

Nevermind, you have a demo. I just found it.
viewtopic.php?t=29721
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: 3D cube drawing

Post by dodicat »

Did you know that on an opengl screen (line 15 ish) the winapi buttons and fonts work.
You have to use PeekMessage to get the opengl loop.

Code: Select all


#include "windows.bi"
#include "GL/gl.bi"
Sub setupgl
      Dim As Integer xres,yres
      Screeninfo xres,yres
      glDisable (GL_DEPTH_TEST)
      glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA)
      glEnable (GL_BLEND)
      glEnable (GL_LINE_SMOOTH)
      glOrtho 0, xres, yres,0,-1, 1
      glclearcolor 1,1,1,1
End Sub
Screen 20,32,,2
setupgl
Dim Shared As Long wire,solid,glass

Type pt
      As Double x,y,z
End Type

Type triangle
      As pt p(0 To 2)
      As pt ctr
      As Ulong col
      As pt norm
End Type

Type angle3D             'FLOATS for angles
      As Single sx,sy,sz
      As Single cx,cy,cz
      Declare Static Function construct(As Single,As Single,As Single) As Angle3D
End Type

Function Angle3D.construct(x As Single,y As Single,z As Single) As Angle3D
      Return   Type (Sin(x),Sin(y),Sin(z), _
      Cos(x),Cos(y),Cos(z))
End Function

Function Rotate(c As pt,p As pt,a As Angle3D,scale As pt=Type(1,1,1)) As pt
      Dim As Single dx=p.x-c.x,dy=p.y-c.y,dz=p.z-c.z
      Return Type<pt>((scale.x)*((a.cy*a.cz)*dx+(-a.cx*a.sz+a.sx*a.sy*a.cz)*dy+(a.sx*a.sz+a.cx*a.sy*a.cz)*dz)+c.x,_
      (scale.y)*((a.cy*a.sz)*dx+(a.cx*a.cz+a.sx*a.sy*a.sz)*dy+(-a.sx*a.cz+a.cx*a.sy*a.sz)*dz)+c.y,_
      (scale.z)*((-a.sy)*dx+(a.sx*a.cy)*dy+(a.cx*a.cy)*dz)+c.z)
End Function

Function perspective(p As pt,eyepoint As pt) As pt
      Dim As Single   w=1+(p.z/eyepoint.z)
      Return Type<pt>((p.x-eyepoint.x)/w+eyepoint.x,_
      (p.y-eyepoint.y)/w+eyepoint.y,_
      (p.z-eyepoint.z)/w+eyepoint.z)
End Function

Function dot(p As pt,v2 As Pt) As Single 'dot product |v1| * |v2| *cos(angle between v1 and v2)
      Dim As Single d1=Sqr(p.x*p.x + p.y*p.y+ p.z*p.z),d2=Sqr(v2.x*v2.x + v2.y*v2.y +v2.z*v2.z)
      Dim As Single v1x=p.x/d1,v1y=p.y/d1,v1z=p.z/d1 'normalize
      Dim As Single v2x=v2.x/d2,v2y=v2.y/d2,v2z=v2.z/d2 'normalize
      Return (v1x*v2x+v1y*v2y+v1z*v2z)
End Function

Sub drawpolygon(p() As pt, c As Ulong) 
      Var col=Cptr(Ubyte Ptr,@c)
      glcolor4ub(col[2],col[1],col[0],255)
      Dim k As Long=Ubound(p)+1
      Dim As Long index,nextindex
      For n As Long=Lbound(p) To Ubound(p)
            index=n Mod k:nextindex=(n+1) Mod k
            If nextindex=0 Then nextindex=Lbound(p)
            glvertex2d(p(index).x,p(index).y)
            glvertex2d(p(nextindex).x,p(nextindex).y)
      Next
End Sub


Sub fill(p() As Pt,c As Ulong,im As Any Ptr=0,flag As Long)
      Var col=Cptr(Ubyte Ptr,@c)
      glcolor4ub(col[2],col[1],col[0],150)
      If glass Then glcolor4ub(0,0,50,55)
      glbegin gl_lines
      #define ub Ubound
      Dim As Long Sy=1e6,By=-1e6,i,j,y,k
      Dim As Single a(Ub(p)+1,1),dx,dy
      For i =0 To Ub(p)
            a(i,0)=p(i).x
            a(i,1)=p(i).y
            If Sy>p(i).y Then Sy=p(i).y
            If By<p(i).y Then By=p(i).y
      Next i
      Dim As Single xi(Ub(a,1)),S(Ub(a,1))
      a(Ub(a,1),0) = a(0,0)
      a(Ub(a,1),1) = a(0,1)
      For i=0 To Ub(a,1)-1
            dy=a(i+1,1)-a(i,1)
            dx=a(i+1,0)-a(i,0)
            If dy=0 Then S(i)=1
            If dx=0 Then S(i)=0
            If dy<>0 Andalso dx<>0 Then S(i)=dx/dy
      Next i
      For y=Sy-1 To By+1
            k=0
            For i=0 To Ub(a,1)-1
                  If (a(i,1)<=y Andalso a(i+1,1)>y) Orelse _
                  (a(i,1)>y Andalso a(i+1,1)<=y) Then
                  xi(k)=(a(i,0)+S(i)*(y-a(i,1)))
                  k+=1
            End If
      Next i
      For j=0 To k-2
            For i=0 To k-2
                  If xi(i)>xi(i+1) Then Swap xi(i),xi(i+1)
            Next i
      Next j
      
      For i = 0 To k - 2 Step 2
            If wire=0 Or glass=1 Then
                  glvertex2d(xi(i)+1,y)
                  glvertex2d(xi(i+1)+1-1,y)
            End If
      Next i
Next y
If wire=1 Then
      drawpolygon(p(),Rgb(0,0,0))
Else
      If flag =0 And solid=0 Then  drawpolygon(p(),Rgb(255,255,255))
End If
glend
End Sub

Sub blow(d() As pt,t As pt,m As Double)
      For n As Long=1 To 12
            d(n).x=(d(n).x)*m+t.x
            d(n).y=(d(n).y)*m+t.y
            d(n).z=(d(n).z)*m+t.z
      Next
End Sub

Sub setup(p() As triangle,d() As pt,colours() As Ulong)
      Dim As Long i
      Dim As Double cx,cy,cz
      Dim As pt centre=Type(1024\2,768\2,0)
      For n As Long=1 To 20
            cx=0:cy=0:cz=0
            For k As Long=0 To 2
                  Read i
                  p(n).p(k)=d(i)
                  cx+=d(i).x
                  cy+=d(i).y
                  cz+=d(i).z
            Next k
            p(n).ctr=Type(cx/3,cy/3,cz/3)
            p(n).norm=Type(p(n).ctr.x-centre.x,p(n).ctr.y-centre.y,p(n).ctr.z-centre.z)
            p(n).col=colours(n)
      Next n
      
End Sub

Sub show(p() As triangle)
      #define map(a,b,x,c,d) ((d)-(c))*((x)-(a))/((b)-(a))+(c)
      Dim As Long flag
      Dim As pt lightsource
      lightsource=Type(.5,0,.5)
      For n As Long=Lbound(p) To Ubound(p)
            If n<=10 Then flag=1 Else flag=0
            Var col=Cptr(Ubyte Ptr,@p(n).col)
            Dim As Single dt=dot(p(n).norm,lightsource)
            Var dtt=map(1,-1,dt,0,1)
            Dim As Ulong clr=Rgba(dtt*col[2],dtt*col[1],dtt*col[0],150)
            fill(p(n).p(),clr,0,flag)
      Next n
End Sub

Sub sort(p() As triangle)
      For n1 As Long =Lbound(p) To Ubound(p)-1
            For n2 As Long=n1+1 To Ubound(p)
                  If p(n1).ctr.z<p(n2).ctr.z Then Swap p(n1),p(n2)
            Next n2
      Next n1
End Sub

Function Regulate(Byval MyFps As Long,Byref fps As Long=0) As Long
    Static As Double timervalue,_lastsleeptime,t3,frames
    Var t=Timer
    frames+=1
    If (t-t3)>=1 Then t3=t:fps=frames:frames=0
    Var sleeptime=_lastsleeptime+((1/myfps)-T+timervalue)*1000
    If sleeptime<1 Then sleeptime=1
    _lastsleeptime=sleeptime
    timervalue=T
    Return sleeptime
End Function


Sub setcolours(colours() As Ulong,colour As Ulong=Rgb(100,255,0))
      Randomize 2
      For n As Long=1 To 20
            colours(n)=Rgba(Rnd*255,Rnd*255,Rnd*255,15)
      Next n
End Sub


Function Set_Font (Font As String,Size As Long,Bold As Long,Italic As Long,Underline As Long,StrikeThru As Long) As HFONT
      Dim As HDC hDC=GetDC(HWND_DESKTOP)
      Dim As Long CyPixels=GetDeviceCaps(hDC,LOGPIXELSY)
      ReleaseDC(HWND_DESKTOP,hDC)
      Return CreateFont(0-(Size*CyPixels)/72,0,0,0,Bold,Italic,Underline,StrikeThru,ANSI_CHARSET _
      ,OUT_TT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FF_DONTCARE,Font)
End Function


'===============================================================================
Dim As pt d(1 To 12)={ _
(0.000000,-0.525731,0.850651), _
(0.850651,0.000000,0.525731), _
(0.850651,0.000000,-0.525731), _
(-0.850651,0.000000,-0.525731), _
(-0.850651,0.000000,0.525731), _
(-0.525731,0.850651,0.000000), _
(0.525731,0.850651,0.000000), _
(0.525731,-0.850651,0.000000), _
(-0.525731,-0.850651,0.000000), _
(0.000000,-0.525731,-0.850651), _
(0.000000,0.525731,-0.850651), _
(0.000000,0.525731,0.850651)}

Dim As Ulong colours(1 To 20)
Dim As triangle p(1 To 20),rot(1 To 20)
blow(d(),Type(1024\2,768\2,0),200)
setcolours(colours())
setup(p(),d(),colours())

Dim  As Angle3D A3d
Dim As pt ang
Dim As pt c=Type(1024\2,768\2,0)
Dim As Long mx,my,btn
Color ,Rgb(255,255,255)

Dim Win As Any Ptr

Screencontrol 2, *Cptr(Integer Ptr,@Win )
Dim Shared As HFONT  ThisFont:ThisFont=Set_Font("Times new roman",16,0,0,0,0)
Var Cc=CreateWindowEx(0,"button","alpha", WS_VISIBLE Or WS_CHILD,0,0,70,30,win,0,0,0)
Var Dd=CreateWindowEx(0,"Button","solid", WS_VISIBLE Or WS_CHILD,70,0,70,30,win,0,0,0)
Var c1=CreateWindowEx(0,"STATIC","", WS_VISIBLE Or WS_CHILD ,150,650,300,40,win,0,0,0)
Var Ee=CreateWindowEx(0,"Button","wire",WS_BORDER Or WS_VISIBLE Or WS_CHILD,140,0,70,30,win,0,0,0)
Var Gg=CreateWindowEx(0,"Button","glass",WS_BORDER Or WS_VISIBLE Or WS_CHILD,210,0,70,30,win,0,0,0)
SendMessage(Cc,WM_SETFONT,Cast(WPARAM,ThisFont),0)
SendMessage(Dd,WM_SETFONT,Cast(WPARAM,ThisFont),0)
SendMessage(Ee,WM_SETFONT,Cast(WPARAM,ThisFont),0)
SendMessage(Gg,WM_SETFONT,Cast(WPARAM,ThisFont),0)
ThisFont=Set_Font("Times new roman",26,0,0,0,0)
SendMessage(C1,WM_SETFONT,Cast(WPARAM,ThisFont),0)
Dim As msg msg
Dim As Long flag,fps
While true
      While (PeekMessage (@Msg, NULL, 0, 0, PM_REMOVE) > 0)
            TranslateMessage (@Msg)
            DispatchMessage (@Msg)
            Select Case msg.hwnd
            Case Cc 'alpha
                  Select Case msg.message
                  
                  Case WM_LBUTTONDOWN
                        wire=0
                        solid=0
                        glass=0
                        glEnable (GL_BLEND)
                  End Select
                  
            Case Dd 'solid
                  Select Case msg.message
                  Case WM_LBUTTONDOWN
                        wire=0
                        solid=1
                        glass=0
                        gldisable (GL_BLEND)
                  End Select 
                  
            Case Ee
                  Select Case msg.message
                  Case WM_LBUTTONDOWN
                        wire=1
                        solid=0
                        glass=0
                  End Select
                  
            Case Gg 'glass
                  Select Case msg.message
                  Case WM_LBUTTONDOWN
                        wire=1
                        'solid=1
                        glass=1
                        glEnable (GL_BLEND)
                  End Select
                  
            Case Else
                  
                  setwindowtext(C1,"framerate = "+Str(fps))   
                  
            End Select
            
            If Inkey=Chr(255)+"k" Then End
      Wend
      ang.x+=.03/2  'the orbiting speed
      ang.y+=.02/2
      ang.z+=.01/2
      
      A3D=Angle3D.construct(ang.x,ang.y,ang.z)
      For n As Long=1 To 20
            For m As Long=0 To 2
                  rot(n).p(m)=Rotate(c,p(n).p(m),A3D)
                  rot(n).p(m)=perspective(rot(n).p(m),Type(1024\2,768\2,2000))
            Next m
            rot(n).ctr=Rotate(c,p(n).ctr,A3D)
            rot(n).norm=Type(rot(n).ctr.x-c.x,rot(n).ctr.y-c.y,rot(n).ctr.z)
            rot(n).col=p(n).col
      Next n
      
      sort(rot())
      
      glClear(GL_COLOR_BUFFER_BIT)
      show(rot())
      Flip
      Sleep regulate(60,fps),1
Wend

triangles:
Data _
2,3, 7, _
2, 8, 3, _
4, 5, 6, _
5, 4, 9, _
7, 6, 12, _
6, 7, 11, _
10, 11, 3, _
11, 10, 4, _
8, 9, 10, _
9, 8, 1, _
12, 1, 2, _
1, 12, 5, _
7, 3, 11, _
2, 7, 12, _
4, 6, 11, _
6, 5, 12, _
3, 8, 10, _
8, 2, 1, _
4, 10, 9, _
5, 9, 1



  
neil
Posts: 594
Joined: Mar 17, 2022 23:26

Re: 3D cube drawing

Post by neil »

Your latest code doesn't compile on Linux.
It's probably because Linux doesn't like #include "windows.bi"

/usr/bin/../bin/ld: cannot find -lkernel32
/usr/bin/../bin/ld: cannot find -lgdi32
/usr/bin/../bin/ld: cannot find -lmsimg32
/usr/bin/../bin/ld: cannot find -luser32
/usr/bin/../bin/ld: cannot find -lversion
/usr/bin/../bin/ld: cannot find -ladvapi32
/usr/bin/../bin/ld: cannot find -limm32
neil
Posts: 594
Joined: Mar 17, 2022 23:26

Re: 3D cube drawing

Post by neil »

I just tested your latest icosahedron code on Windows 10. It's a nice program, with quite a few options to choose from.
It would be great if it could compile and run on Linux as well.
fxm
Moderator
Posts: 12133
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: 3D cube drawing

Post by fxm »

Other icosahedron codes at: Icosahedron
neil
Posts: 594
Joined: Mar 17, 2022 23:26

Re: 3D cube drawing

Post by neil »

Here's a rotating ring or circle.

Code: Select all

' rotating ring or circle by neil

const SCREEN_WIDTH = 800
const SCREEN_HEIGHT = 600

dim as double x_radius = 200
dim as double y_radius = 100
dim as integer num_segments = 30
const pi = 3.1459265 

screenres SCREEN_WIDTH, SCREEN_HEIGHT, 32
windowtitle "Rotating Ring"

dim shared as double angle = 0

do
    angle += 0.01
    screenlock
    cls 
    ' draw the ring or circle
    for i as integer = 0 to num_segments
        dim as double theta1 = (2 * pi * i) / num_segments
        dim as double theta2 = (2 * pi * (i + 1)) / num_segments

        dim as integer x1 = SCREEN_WIDTH / 2 + x_radius * cos(angle + theta1)
        dim as integer y1 = SCREEN_HEIGHT / 2 + y_radius * sin(theta1)

        dim as integer x2 = SCREEN_WIDTH / 2 + x_radius * cos(angle + theta2)
        dim as integer y2 = SCREEN_HEIGHT / 2 + y_radius * sin(theta2)

        line (x1, y1)-(x2, y2)
    next i
    screenunlock

    sleep 5
loop until inkey = chr(27)
Post Reply