MiniB3d for FreeBasic

Headers, Bindings, Libraries for use with FreeBASIC, Please include example of use to help ensure they are tested and usable.
Post Reply
Munair
Posts: 1274
Joined: Oct 19, 2017 15:00
Location: Netherlands
Contact:

Re: MiniB3d for FreeBasic

Post by Munair »

OK, thanks. That wasn't clear to me.
badidea
Posts: 2537
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: MiniB3d for FreeBasic

Post by badidea »

The thing (the Rubik's cube) finally works, but I should probably use ActTurnTo() instead of ActTurnBy() because the cube can get misaligned at certain settings. Or better, replace with 'manual' rotation code.

Code: Select all

#include "openb3d/openb3d.bi"
'#include "2d2.bi"
#include "fbgfx.bi"

const as integer screen_width = 800, screen_height = 600

#define RGBA_A(c) (cuint(c) shr 24)
#define RGBA_R(c) ((cuint(c) shr 16) and &hFF)
#define RGBA_G(c) ((cuint(c) shr 8) and &hFF)
#define RGBA_B(c) (cuint(c) and &hFF)

#define rnd_range(low, high) (rnd(1) * ((high) - (low)) + (low))

const as long FACE_FRONT = 0 'red
const as long FACE_BACK = 1 'orange
const as long FACE_LEFT = 2 'green
const as long FACE_RIGHT = 3 'blue
const as long FACE_TOP = 4 'white
const as long FACE_BOTTOM = 5 'yellow

const as ulong CL_RED = &hB80A31 'front
const as ulong CL_ORANGE = &hFF5700 'back
const as ulong CL_GREEN = &h009C46 'left
const as ulong CL_BLUE = &h0044AF 'right
const as ulong CL_WHITE = &hFFFFFF 'top / up
const as ulong CL_YELLOW = &hFFD600 'bottom / down

'-------------------------------------------------------------------------------

type cubie_type
	dim as any ptr entity
	dim as any ptr quad(0 to 5)
	dim as ulong faceColor(0 to 5) '0 for no quad (F,B,L,R,U,D)
end type

'-------------------------------------------------------------------------------

function estimate_rate(anglesPerSecond as single) as single
	return (anglesPerSecond / 9) * (1.5 / 10)
end function

sub object_key_control_1(obj as any ptr)
	if multikey(FB.SC_UP) then TurnEntity(obj, 0, 0, 2)
	if multikey(FB.SC_DOWN) then TurnEntity(obj, 0, 0,-2)
	if multikey(FB.SC_LEFT) then TurnEntity(obj, 0, 2, 0)
	if multikey(FB.SC_RIGHT) then TurnEntity(obj, 0,-2, 0)
	if multikey(FB.SC_PAGEUP) then TurnEntity(obj, 2, 0, 0)
	if multikey(FB.SC_PAGEDOWN) then TurnEntity(obj, -2, 0, 0)
end sub

sub object_key_control_2(obj as any ptr)
	if multikey(FB.SC_W) then TurnEntity(obj, 0, 0, 2)
	if multikey(FB.SC_S) then TurnEntity(obj, 0, 0,-2)
	if multikey(FB.SC_A) then TurnEntity(obj, 0, 2, 0)
	if multikey(FB.SC_D) then TurnEntity(obj, 0,-2, 0)
	if multikey(FB.SC_Q) then TurnEntity(obj, 2, 0, 0)
	if multikey(FB.SC_E) then TurnEntity(obj, -2, 0, 0)
end sub

'Rotate 1 disc 90 degree, turnStr format is U, U', B, B', etc.
'turnDuration in seconds (not accurate!)
function turn_action(cubie() as cubie_type, turnStr as string, turnDuration as single) as any ptr
	dim as integer x, y, z
	dim as single angle 'positive(+) is clockwise
	dim as any ptr pivotCubie, action
	select case left(turnStr, 1)
		case "F" : z = -1 : angle = -90
		case "B" : z = +1 : angle = +90
		case "L" : x = -1 : angle = +90
		case "R" : x = +1 : angle = -90
		case "U" : y = +1 : angle = -90
		case "D" : y = -1 : angle = +90
	end select
	if mid(turnStr, 2, 1) = "'" then angle = -angle 'reverse direction
	'set the pivot point for disc rotation
	if z <> 0 then 'fixed z, loop x,y
		pivotCubie = cubie(0, 0, z).entity
		for x as integer = -1 to +1
			for y as integer = -1 to +1
				if x = 0 and y = 0 then continue for 'no self-parenting
				EntityParent(cubie(x, y, z).entity, pivotCubie)
			next
		next
	end if
	if x <> 0 then 'fixed x, loop y,z
		pivotCubie = cubie(x, 0, 0).entity
		for y as integer = -1 to +1
			for z as integer = -1 to +1
				if y = 0 and z = 0 then continue for 'no self-parenting
				EntityParent(cubie(x, y, z).entity, pivotCubie)
			next
		next
	end if
	if y <> 0 then 'fixed y, loop x,z
		pivotCubie = cubie(0, y, 0).entity
		for x as integer = -1 to +1
			for z as integer = -1 to +1
				if x = 0 and z = 0 then continue for 'no self-parenting
				EntityParent(cubie(x, y, z).entity, pivotCubie)
			next
		next
	end if
	dim as single rate = estimate_rate(90 / turnDuration)
	'start the turn action
	select case left(turnStr, 1)
		case "F", "B" 'rotation around z-axis
			action = ActTurnBy(pivotCubie, 0, 0, angle, rate)
		case "L", "R" 'rotation around x-axis
			action = ActTurnBy(pivotCubie, angle, 0, 0, rate)
		case "D", "U" 'rotation around y-axis
			action = ActTurnBy(pivotCubie, 0, angle, 0, rate)
	end select
	return action
end function

function random_turn_string() as string
	dim as string turnOptions(0 to 5) = {"F", "B", "L", "R", "U", "D"}
	dim as string retStr = turnOptions(int(rnd * 6))
	if rnd > 0.5 then retStr += "'" '50% counter clock chance
	return retStr
end function

'pop from front of string
function pop_next_turn(byref seqStr as string) as string
	dim as string retStr
	if mid(seqStr, 2, 1) = "'" then
		retStr = mid(seqStr, 1, 2)
		seqStr = mid(seqStr, 3)
	else
		retStr = mid(seqStr, 1, 1)
		seqStr = mid(seqStr, 2)
	end if
	return retStr
end function

'call between openb3d rotations
sub reorder_cube(cubie() as cubie_type, turnStr as string)
	dim as cubie_type tempCubie(-1 to +1, -1 to +1)
	dim as integer a, b
	'copy disc of 9 cubies
	for a = -1 to +1
		for b = -1 to +1
			select case left(turnStr, 1)
				case "F" : tempCubie(a, b) = cubie(a, b, -1) 'z
				case "B" : tempCubie(a, b) = cubie(a, b, +1) 'z
				case "L" : tempCubie(a, b) = cubie(-1, a, b) 'x
				case "R" : tempCubie(a, b) = cubie(+1, a, b) 'x
				case "D" : tempCubie(a, b) = cubie(a, -1, b) 'y
				case "U" : tempCubie(a, b) = cubie(a, +1, b) 'y
			end select
		next
	next
	'copy back & rotate
	for a = -1 to +1
		for b = -1 to +1
			select case left(turnStr, 2)
				case "F" : cubie(a, b, -1) = tempCubie(-b, a)
				case "F'": cubie(a, b, -1) = tempCubie(b, -a)
				case "B" : cubie(a, b, +1) = tempCubie(b, -a)
				case "B'": cubie(a, b, +1) = tempCubie(-b, a)
				case "L" : cubie(-1, a, b) = tempCubie(-b, a)
				case "L'": cubie(-1, a, b) = tempCubie(b, -a)
				case "R" : cubie(+1, a, b) = tempCubie(b, -a)
				case "R'": cubie(+1, a, b) = tempCubie(-b, a)
				case "D" : cubie(a, -1, b) = tempCubie(b, -a)
				case "D'": cubie(a, -1, b) = tempCubie(-b, a)
				case "U" : cubie(a, +1, b) = tempCubie(-b, a)
				case "U'": cubie(a, +1, b) = tempCubie(b, -a)
			end select
		next
	next
end sub

'-------------------------------------------------------------------------------

'define big cube as 3 x 3 x 3 smaller 'cubies'
dim as cubie_type cubie(-1 to +1, -1 to +1, -1 to +1) 'x,y,z

'set face colors for all cubies, 0 for no face
for x as integer = -1 to +1
	for y as integer = -1 to +1
		for z as integer = -1 to +1
			with cubie(x, y, z)
				if x = -1 then .faceColor(FACE_LEFT) = CL_GREEN
				if x = +1 then .faceColor(FACE_RIGHT) = CL_BLUE
				if y = -1 then .faceColor(FACE_BOTTOM) = CL_YELLOW
				if y = +1 then .faceColor(FACE_TOP) = CL_WHITE
				if z = -1 then .faceColor(FACE_FRONT) = CL_RED
				if z = +1 then .faceColor(FACE_BACK) = CL_ORANGE
			end with
		next
	next
next

'turn 6 quad faces to make a 6-color cube
'order: front, back, left, right, up, down
dim as single quadPitch(0 to 5) = {0, 180,   0,   0, -90, +90}
dim as single quadYaw(0 to 5) =   {0,   0, -90, +90,   0,   0}

'central pivot point (to rotate the entire cube)
var pivot = CreatePivot()
'build cube from 27 cubies and 54 face quads
for x as integer = -1 to +1
	for y as integer = -1 to +1
		for z as integer = -1 to +1
			with cubie(x, y, z)
				'build a small cube (cubie) from up to 6 quads with each side a different color
				.entity = CreateCube(pivot) 'has parent pivot, is parent for quads
				ScaleMesh(.entity, 0.48, 0.48, 0.48) 'a bit smaller then 1*1*1
				EntityColor(.entity, 40, 40, 40) 'dark grey cubie
				MoveEntity(.entity, x, y, z) 'position cubie
				for i as integer = 0 to 5 'loop all 6 faces
					dim as ulong c = .faceColor(i)
					if c <> 0 then 'skip face if color is 0
						.quad(i) = CreateQuad(.entity) 'child of cubie
						EntityColor(.quad(i), RGBA_R(c), RGBA_G(c), RGBA_B(c))
						PositionMesh(.quad(i), 0, 0, -1) 'move forward (to camera)
						ScaleMesh(.quad(i), 0.42, 0.42, 0.50) 'shrink face size and distance from cubie center
						RotateMesh(.quad(i), quadPitch(i), quadYaw(i), 0) 'turn face to correct side
					end if
				next
			end with
		next
	next
next

'-------------------------------------------------------------------------------

' Set video mode 
screencontrol(FB.SET_GL_2D_MODE, FB.OGL_2D_MANUAL_SYNC)
screenres(screen_width, screen_height, 32, 1, FB.GFX_OPENGL) 'or GFX_MULTISAMPLE or GFX_ALPHA_PRIMITIVES)
Graphics3d(screen_width, screen_height, 32, 1, 1) 'set openb3d screen

' Setup light and camera
var light1 = CreateLight(1)
var cam1 = CreateCamera()
CameraViewport(cam1, 0, 0, screen_width, screen_height)
PositionEntity(cam1, 0, 0, -5) 'move camera back

dim as string seqStr = "UL'RFD'DLU'RDF'LB'F'L'FR"
dim as string turnStr' = random_turn_string()

'Make freebasic print work on 3d screen (2d2.bi)
'dim as font2d f2d

dim as string myStr
dim as single dPitch, dYaw, dRoll
dim as double tUpdate = timer + 0.5 'action start delay
dim as double t = timer
dim as any ptr action
dim as integer started = 0

randomize timer
TurnEntity(pivot, 25, 30, 0) 'rotate whole cube a bit for better view
while not multikey(FB.SC_ESCAPE)
	object_key_control_1(pivot) ' control cube1 with arrow keys
	if multikey(FB.SC_SPACE) then wireframe(1) else wireframe(0)
	UpdateWorld()
	RenderWorld()
	'dim as long actionBusy = iif(action, cast(long ptr, action)[2], -1) 'integer?
	'myStr = str(actionBusy)
	'f2d.print(10, 10, "Hello Cube! " & myStr)
	flip
	sleep 1
	if timer > tUpdate then
		if started = 0 then
			started = 1
		else
			reorder_cube(cubie(), turnStr) 'skip on first timer update
		end if
		tUpdate = timer + 1.0'change somthing again in ... second
		'turnStr = pop_next_turn(seqStr)
		turnStr = random_turn_string()
		action = turn_action(cubie(), turnStr, 0.8)
	end if
wend
sleep
end
angros47
Posts: 2124
Joined: Jun 21, 2005 19:04

Re: MiniB3d for FreeBasic

Post by angros47 »

I have made several changes to OB3D Plus, and published a new version of it. No features added, but plenty of bugs fixed.

Due to an issue with nvidia driver on Linux, I had to switch to nouveau generic drivers, and I realized that most shaders I wrote didn't work with it: looks like the nvidia proprietary driver is more permissive, while the nouveau implementation has a stricter syntax enforcement.

The new version of OB3D Plus is 64 bit, but can still be compiled to 32 bit if needed.

OB3D Plus is a helper library, to be used with OpenB3D, that adds: High Dynamic Range, Screen Space Ambient Occlusion, Material Capture, Fur Shading, simple Deferred Rendering, Interior Mapping, glass material, toon shading, Depth of Field, Bump Mapping, Shadow Mapping, and some post processing effects like pixel art, or fisheye. Also, it allows to save videos of the rendering.

https://sourceforge.net/projects/minib3d/files/
angros47
Posts: 2124
Joined: Jun 21, 2005 19:04

Re: MiniB3d for FreeBasic

Post by angros47 »

Added also a github repository:

https://github.com/angros47/OpenB3D
Luxan
Posts: 165
Joined: Feb 18, 2009 12:47
Location: New Zealand

Re: MiniB3d for FreeBasic

Post by Luxan »

I'm using Ubuntu 20.04 on an x64 , 4 core, computer; I recently installed an NVIDIA
GTX 1030 graphics card, max GPU power 30W.

Eventually I was able to successfully compile and run the OpenB3D examples provided.
To do so, I firstly copied the libOpenB3D.so, libOpenB3D-64.so , libOpenB3Dplus.so and
libGlee.a to usr/local/lib; as suggested in a previous reply to this thread.
I also copied openb3d.bi and openb3dplus.bi to usr/local/include/freebasic.
However, another step was required, opening the Terminal I then entered the command:
sudo ldconfig , enter, then the user password and enter ; this made the libraries visible system wide.

I've also been busy examining glsl examples from shadertoy, viewtopic.php?t=28001
and at OpenGL shader language math in FreeBASIC.

I assume this has some relevance to OpenB3D.

The code from shadertoy is rather difficult to follow and isn't laid out very clearly.

For beginners there should be a gradual introduction with separable and well defined functions for rotation, mouse control , shader, terrain, box frame, these should be
constructed as individually callable functions then only one mainframe with minimum lines within.

Through OpenB3D and the inherent structures of FreeBasic might you be able to provide some code to illustrate these concepts.

As for multiple channels, that remains a mystery.
Luxan
Posts: 165
Joined: Feb 18, 2009 12:47
Location: New Zealand

Re: MiniB3d for FreeBasic

Post by Luxan »

I mean mainImage , not mainframe .
angros47
Posts: 2124
Joined: Jun 21, 2005 19:04

Re: MiniB3d for FreeBasic

Post by angros47 »

The code from shadertoy is written in a language called glsl, that is compiled by the driver of the graphic card, and it runs on the GPU, not on the CPU. Unfortunately, there are several versions of it, incompatible with each other (so, you have to specify the version you will use, hoping that your driver will support it): also, being compiled by the driver, there is no way to replace it with a different language, because you would need to modify the driver for every possible video card

OpenB3D allows to use it, in the shaders, to achieve some special effects (like, fur surface, glass material, displacement mapping), but it is not necessary: older versions of OpenGL didn't support it, and OpenB3D is compatible with them, too, and it is perfectly usable even without using the shaders.

Earlier versions of GLSL allowed to use the shaders acting directly on the various parameters (texture coords, light type and position, and so on), while newer versions are more versatile, but also harder to use, since they "generalize": you have to pass several attribute, and you decide which one is used for what. OpenB3D allows that, with commands like UseEntity, UseSurface or UseMatrix, but they are advanced features, that cannot be explained without knowing at least the bases of GLSL programming.

If you want some shaders already made for OpenB3D, you can try OB3D Plus, a helper library meant to be used with OpenB3D.
Luxan
Posts: 165
Joined: Feb 18, 2009 12:47
Location: New Zealand

Re: MiniB3d for FreeBasic

Post by Luxan »

Thank you for replying.

About the different glsl versions, I eventually figured that out; most examples from shadertoy
are compatible with version 140. Nevertheless I continue to struggle with the incomplete
explanations and wildly differing and in someway incomplete fragments of code to be found at shadertoy.

From what I've read over the years, SiliconGraphics was the first to develop a language like
OpenGL, then a standards committee was formed and we eventually arrive at the ongoing
revisions; and multiples of these for glsl too.

As I mentioned, I managed to successfully install OpenB3D and OpenB3Dplus and run all
of the examples provided. Are there more examples , documentation, links .
I believe shaders in OpenB3Dplus need my attention.
Luxan
Posts: 165
Joined: Feb 18, 2009 12:47
Location: New Zealand

Re: MiniB3d for FreeBasic

Post by Luxan »

A question, or two, about shadertoy.

At the shadertoy website sometimes more than one channel is used for code.
Each of these channels may also have their own mainImage block.

There are Uniform variables designated iChannel0, iChannel1, iChannel2, iChannel3,
are these related to the shadertoy channels; if so how might these be used.

Apparently static variables aren't available in GLSL.
Post Reply