Oh, and a new video... Basically I've been adding surface creation, vertex manipulation commands and brushes... So, with what I have, I re-created the classic Blitz3D "castle" example skybox code in BambooBasic... The video is here:
And this is the code (Fully commented):
; BlitzBasic Castle Skybox
; Build skybox using mesh/surface functions, like the example in Blitz3D
Import "BBRuntime64.decls"
Include "../../BBR_INCLUDE.bam"
Function Main()
Print "BlitzBasic Castle Example-Styleee Skybox"
b3dShowConsoleOutput(True)
; Initialize 3D graphics
b3dGraphics3D(1280, 720, BBR_WINDOW_MODE_WVC)
sysSetAppTitle("BlitzBasic Castle Example-Styleee Skybox")
b3dAmbientLight(200, 200, 200)
; Create camera
local camera:Int = b3dCreateCamera()
b3dCameraRange(camera, 0.01, 1000.0)
b3dPositionEntity(camera, 0, 5, 0)
b3dCameraClsColor(camera, 0, 0, 0)
; Create mesh (like Blitz3D CreateMesh)
local skybox:Int = b3dCreateMesh(BBR_ONE_SLOT, BBR_TEXTURE_UV, 0)
b3dLockMesh(skybox)
; Using padded textures (260x260) with 2-pixel edge padding on each side
; To minimize seams, sample from pixel 2.5 to 257.5 (slightly inward from padding)
;
; UV Calculation for different texture sizes:
; If original texture is NxN and padded texture is (N+4)x(N+4):
; uvMin = 2.5 / (N+4)
; uvMax = (N+1.5) / (N+4)
;
; Examples:
; 256x256 -> 260x260: uvMin = 2.5/260 = 0.00961538, uvMax = 257.5/260 = 0.99038462
; 512x512 -> 516x516: uvMin = 2.5/516 = 0.00484496, uvMax = 513.5/516 = 0.99515504
; 1024x1024 -> 1028x1028: uvMin = 2.5/1028 = 0.00243210, uvMax = 1025.5/1028 = 0.99756790
;
; Adjust these values to fine-tune seam visibility vs texture alignment
local uvMin:Double = 0.00961538
local uvMax:Double = 0.99038462
local brushFront:Int = b3dCreateBrush()
local tex:Int = b3dLoadTexture3D("environ/padded_sky_BK.jpg")
b3dBrushTexture(brushFront, tex)
local surf:Int = b3dCreateSurface(skybox)
local v0:Int = b3dAddVertex(skybox, surf, -1.0, +1.0, -1.0, uvMax, uvMin)
local v1:Int = b3dAddVertex(skybox, surf, +1.0, +1.0, -1.0, uvMin, uvMin)
local v2:Int = b3dAddVertex(skybox, surf, +1.0, -1.0, -1.0, uvMin, uvMax)
local v3:Int = b3dAddVertex(skybox, surf, -1.0, -1.0, -1.0, uvMax, uvMax)
b3dAddTriangle(skybox, surf, v0, v1, v2)
b3dAddTriangle(skybox, surf, v0, v2, v3)
b3dPaintSurface(skybox, surf, brushFront)
b3dFreeBrush(brushFront)
; Left face (using _LF.jpg like Blitz3D)
local brush:Int = b3dCreateBrush()
tex = b3dLoadTexture3D("environ/padded_sky_LF.jpg")
b3dBrushTexture(brush, tex)
surf = b3dCreateSurface(skybox)
v0 = b3dAddVertex(skybox, surf, +1.0, +1.0, -1.0, uvMax, uvMin)
v1 = b3dAddVertex(skybox, surf, +1.0, +1.0, +1.0, uvMin, uvMin)
v2 = b3dAddVertex(skybox, surf, +1.0, -1.0, +1.0, uvMin, uvMax)
v3 = b3dAddVertex(skybox, surf, +1.0, -1.0, -1.0, uvMax, uvMax)
b3dAddTriangle(skybox, surf, v0, v1, v2)
b3dAddTriangle(skybox, surf, v0, v2, v3)
b3dPaintSurface(skybox, surf, brush)
b3dFreeBrush(brush)
; Front face (using _FR.jpg like Blitz3D)
brush = b3dCreateBrush()
tex = b3dLoadTexture3D("environ/padded_sky_FR.jpg")
b3dBrushTexture(brush, tex)
surf = b3dCreateSurface(skybox)
v0 = b3dAddVertex(skybox, surf, +1.0, +1.0, +1.0, uvMax, uvMin)
v1 = b3dAddVertex(skybox, surf, -1.0, +1.0, +1.0, uvMin, uvMin)
v2 = b3dAddVertex(skybox, surf, -1.0, -1.0, +1.0, uvMin, uvMax)
v3 = b3dAddVertex(skybox, surf, +1.0, -1.0, +1.0, uvMax, uvMax)
b3dAddTriangle(skybox, surf, v0, v1, v2)
b3dAddTriangle(skybox, surf, v0, v2, v3)
b3dPaintSurface(skybox, surf, brush)
b3dFreeBrush(brush)
; Right face (using _RT.jpg like Blitz3D)
brush = b3dCreateBrush()
tex = b3dLoadTexture3D("environ/padded_sky_RT.jpg")
b3dBrushTexture(brush, tex)
surf = b3dCreateSurface(skybox)
v0 = b3dAddVertex(skybox, surf, -1.0, +1.0, +1.0, uvMax, uvMin)
v1 = b3dAddVertex(skybox, surf, -1.0, +1.0, -1.0, uvMin, uvMin)
v2 = b3dAddVertex(skybox, surf, -1.0, -1.0, -1.0, uvMin, uvMax)
v3 = b3dAddVertex(skybox, surf, -1.0, -1.0, +1.0, uvMax, uvMax)
b3dAddTriangle(skybox, surf, v0, v1, v2)
b3dAddTriangle(skybox, surf, v0, v2, v3)
b3dPaintSurface(skybox, surf, brush)
b3dFreeBrush(brush)
; Top face (using _UP.jpg like Blitz3D)
brush = b3dCreateBrush()
tex = b3dLoadTexture3D("environ/padded_sky_UP.jpg")
b3dBrushTexture(brush, tex)
surf = b3dCreateSurface(skybox)
v0 = b3dAddVertex(skybox, surf, -1.0, +1.0, +1.0, uvMax, uvMax)
v1 = b3dAddVertex(skybox, surf, +1.0, +1.0, +1.0, uvMax, uvMin)
v2 = b3dAddVertex(skybox, surf, +1.0, +1.0, -1.0, uvMin, uvMin)
v3 = b3dAddVertex(skybox, surf, -1.0, +1.0, -1.0, uvMin, uvMax)
b3dAddTriangle(skybox, surf, v0, v1, v2)
b3dAddTriangle(skybox, surf, v0, v2, v3)
b3dPaintSurface(skybox, surf, brush)
b3dFreeBrush(brush)
; Bottom face (using _DN.jpg like Blitz3D)
brush = b3dCreateBrush()
tex = b3dLoadTexture3D("environ/padded_sky_DN.jpg")
b3dBrushTexture(brush, tex)
surf = b3dCreateSurface(skybox)
Print "Created DOWN surface: " & ToString(surf)
v0 = b3dAddVertex(skybox, surf, -1.0, -1.0, -1.0, uvMin, uvMin)
v1 = b3dAddVertex(skybox, surf, +1.0, -1.0, -1.0, uvMin, uvMax)
v2 = b3dAddVertex(skybox, surf, +1.0, -1.0, +1.0, uvMax, uvMax)
v3 = b3dAddVertex(skybox, surf, -1.0, -1.0, +1.0, uvMax, uvMin)
b3dAddTriangle(skybox, surf, v0, v1, v2)
b3dAddTriangle(skybox, surf, v0, v2, v3)
Print "Painting DOWN surface with brush"
b3dPaintSurface(skybox, surf, brush)
b3dFreeBrush(brush)
Print "Welding vertices..."
b3dWeldVertices(skybox, 0.001)
b3dUnlockMesh(skybox)
Print "Created 6 surfaces, now scaling and flipping mesh"
; Scale and flip mesh like Blitz3D (ScaleMesh 100,100,100 + FlipMesh)
b3dScaleEntity(skybox, 100.0, 100.0, 100.0)
Print "Flipping mesh..."
b3dFlipMesh(skybox)
Print "Mesh flipped"
; Set full-bright rendering (bit 0 = fullbright) + disable backface culling (bit 4 = 16)
b3dSetEntityRenderFlags(skybox, 17) ; 1 + 16 = fullbright + no culling
Print "Set entity render flags to 17 (fullbright + no culling)"
; Position skybox at origin (will update position in main loop to follow camera)
b3dPositionEntity(skybox, 0, 0, 0)
Print "Skybox will follow camera position (but not rotation)"
; Create a ground plane for reference
local ground:Int = b3dCreateGrid(BBR_ONE_SLOT, BBR_NO_TEXTURE_UV, 0, 100, 100, 10, 10)
b3dPositionEntity(ground, 0, 0, 0)
b3dSetEntityColorFX(ground, 50, 100, 50)
; Create a cube for reference
local cube:Int = b3dCreateCube(BBR_ONE_SLOT, BBR_NO_TEXTURE_UV, 0)
b3dPositionEntity(cube, 0, 2, -10)
b3dScaleEntity(cube, 2, 2, 2)
b3dSetEntityColorFX(cube, 200, 100, 50)
Print ""
Print "Controls:"
Print " Arrow Keys - Move camera"
Print " W/S - Pitch camera"
Print " A/D - Turn camera"
Print " ESC - Exit"
; Main loop
While Not inpIsKeyHit(VKEY_ESCAPE)
sysUpdateEvents()
; Camera movement
If inpIsKeyDown(VKEY_UP)
b3dMoveEntity(camera, 0, 0, 0.5)
EndIf
If inpIsKeyDown(VKEY_DOWN)
b3dMoveEntity(camera, 0, 0, -0.5)
EndIf
If inpIsKeyDown(VKEY_LEFT)
b3dMoveEntity(camera, -0.5, 0, 0)
EndIf
If inpIsKeyDown(VKEY_RIGHT)
b3dMoveEntity(camera, 0.5, 0, 0)
EndIf
If inpIsKeyDown(VKEY_A)
b3dTurnEntity(camera, 0, -0.5, 0)
EndIf
If inpIsKeyDown(VKEY_D)
b3dTurnEntity(camera, 0, 0.5, 0)
EndIf
If inpIsKeyDown(VKEY_W)
b3dTurnEntity(camera, 0.5, 0, 0)
EndIf
If inpIsKeyDown(VKEY_S)
b3dTurnEntity(camera, -0.5, 0, 0)
EndIf
If inpIsKeyDown(VKEY_Q)
b3dMoveEntity(camera, 0, 0.5, 0)
EndIf
If inpIsKeyDown(VKEY_Z)
b3dMoveEntity(camera, 0, -0.5, 0)
EndIf
; Rotate cube for visual interest
b3dTurnEntity(cube, 0.5, 1.0, 0.3)
; Update skybox position to match camera (but not rotation!)
b3dPositionEntity(skybox, b3dEntityX(camera), b3dEntityY(camera), b3dEntityZ(camera))
; Render
b3dCls3D()
b3dRenderWorld()
b3dFlip3D()
Wend
b3dEnd()
Return False
EndFunction
Very powerful feature really! :)
Dabzy