3D snippets

Everything related to 3D programming
miso
Enthusiast
Enthusiast
Posts: 466
Joined: Sat Oct 21, 2023 4:06 pm
Location: Hungary

Re: 3D snippets

Post by miso »

Caronte3D wrote: Mon May 12, 2025 2:43 pm On the example 2D, the circle is not perfect on my system (flattened by the poles).
When you got time, could you try this? I got curious, and I wonder if this (2D) works in your system.
Thanks in advance, and sorry for bugging you.

Code: Select all

;VER PB 6.21 Beta 9
EnableExplicit
;-==============================================================
;- MODULE START
;-==============================================================
DeclareModule sys
  #MAIN_DESKTOP             = 0
  #MAIN_WINDOW              = 0
  #APPNAME                  = "Application"
  #SCREEN_FRAMERATE         = 60
  #MAINLOOP_DELAY           = 0
  #COMPILER_MINIMUM_VERSION = 621
  #MAIN_CAMERA              = 1<<0
  #RENDER_CAMERA            = 1<<1
  #PICK                     = 1<<0
  #DONTPICK                 = 1<<1
  #RENDERWIDTH_DEFAULT      = 1366
  #RENDERHEIGHT_DEFAULT     = 768
  
  Global desktopcount.i, renderwidth.i=#RENDERWIDTH_DEFAULT, renderheight.i=#RENDERHEIGHT_DEFAULT
  
  Declare open2d(renderwidth.i=#RENDERWIDTH_DEFAULT,renderheight.i=#RENDERHEIGHT_DEFAULT)
  Declare open3d(renderwidth.i=#RENDERWIDTH_DEFAULT, renderheight.i=#RENDERHEIGHT_DEFAULT)
  Declare SetOrthoCamera()
  Declare SetPerspectiveCamera()
  Declare.i entitycreate(mesh.i,material.i,x=0,y=0,z=0,pickmask.i=#PICK)
  Declare SweepEvents()
  Declare.i escape()
EndDeclareModule

Module sys
  Structure quadobject
    mesh.i
    entity.i
    texture.i
    material.i
  EndStructure
  
  Global quad.quadobject
  
  Declare checks()
  Declare Load3DScripts()
  
;==============================================================
;  Initializes before opening 2D Screen
;  You may correct it to your needs
;==============================================================
  Procedure init2d()
    sys::desktopcount = ExamineDesktops()
    UsePNGImageDecoder()
    InitSprite()
    InitKeyboard()
    InitMouse()
    InitSound()
  EndProcedure
  
;==============================================================
;  Initializes before opening 3D Screen
;  You may correct it to your needs
;==============================================================
  Procedure init3d()
    sys::desktopcount = ExamineDesktops()
    UsePNGImageDecoder()
    InitEngine3D()
    InitSprite()
    InitKeyboard()
    InitMouse()
    InitSound()
  EndProcedure
  
;==============================================================
;  Parse 3d resources
;  You have to add your correct routes
;==============================================================
  Procedure Load3DScripts()
    Add3DArchive(#PB_Compiler_Home+"examples/3d/Data/Main",#PB_3DArchive_FileSystem) 
    Parse3DScripts()
  EndProcedure
  
;==============================================================
;  Opens a fullscreen windowed 3d screen
;  Render resolution can be specified,
;  result will be stretched according to desktop aspect ratio
;==============================================================
  Procedure open2d(renderwidth.i=#RENDERWIDTH_DEFAULT,renderheight.i=#RENDERHEIGHT_DEFAULT)
    init2d()
    OpenWindow(#MAIN_WINDOW,0,0,renderwidth,renderheight,#APPNAME,#PB_Window_BorderLess|#PB_Window_Invisible)
    OpenWindowedScreen(WindowID(#MAIN_WINDOW),0,0,renderwidth,renderheight,1,0,0,#PB_Screen_WaitSynchronization)
    ResizeWindow(#MAIN_WINDOW,0,0,DesktopUnscaledX(DesktopWidth(#MAIN_DESKTOP)),DesktopUnscaledY(DesktopHeight(#MAIN_DESKTOP)))
    HideWindow(#MAIN_WINDOW,#False)
  EndProcedure
  
;==============================================================
;  Opens a fullscreen windowed 3d screen
;  Render resolution can be specified,
;  result won't be stretched
;  Sets the main camera with (ID=1)
;  You don't have to bother with the final render camera (ID=2)
;==============================================================
  Procedure open3d(renderwidth.i=#RENDERWIDTH_DEFAULT, renderheight.i=#RENDERHEIGHT_DEFAULT)
    init3d()
    If renderwidth>DesktopUnscaledX(DesktopWidth(#MAIN_DESKTOP)) : renderwidth = DesktopUnscaledX(DesktopWidth(#MAIN_DESKTOP)) : EndIf
    If renderheight>DesktopUnscaledY(DesktopHeight(#MAIN_DESKTOP)) : renderheight = DesktopUnscaledY(DesktopHeight(#MAIN_DESKTOP)) : EndIf
    OpenWindow(#MAIN_WINDOW,0,0,DesktopUnscaledX(DesktopWidth(#MAIN_DESKTOP)),DesktopUnscaledY(DesktopHeight(#MAIN_DESKTOP)),#APPNAME, #PB_Window_BorderLess)
    OpenWindowedScreen(WindowID(#MAIN_WINDOW),0,0,WindowWidth(#MAIN_WINDOW),WindowHeight(#MAIN_WINDOW),1,0,0,#PB_Screen_SmartSynchronization)
    Load3DScripts() : SetFrameRate(#SCREEN_FRAMERATE)
    CreateCamera(#RENDER_CAMERA,0,0,100,100,#RENDER_CAMERA)
    CreateCamera(#MAIN_CAMERA,0,0,100,100,#MAIN_CAMERA)
    quad\texture  = CreateRenderTexture(#PB_Any,CameraID(#MAIN_CAMERA),renderwidth,renderheight,#PB_Texture_AutomaticUpdate)
    quad\material = CreateMaterial(#PB_Any,TextureID(quad\texture))
    DisableMaterialLighting(quad\material,#True)
    MaterialFilteringMode(quad\material,#PB_Material_Bilinear)
    quad\mesh = CreatePlane(#PB_Any,(ScreenWidth()/ScreenHeight())*1000,1000,1,1,1,1)
    quad\entity = CreateEntity(#PB_Any,MeshID(quad\mesh),MaterialID(quad\material),0,0,-1200,#DONTPICK,#RENDER_CAMERA)
    RotateEntity(quad\entity,90,180,0,#PB_Absolute)
  EndProcedure
  
;=====================================================
; Sets the main world camera to orthographic
;=====================================================
  Procedure SetOrthoCamera()
    If IsCamera(#MAIN_CAMERA)
      CameraProjectionMode(#MAIN_CAMERA,#PB_Camera_Orthographic)
    EndIf
  EndProcedure
  
;=====================================================
; Sets the main world camera to perspective
;=====================================================
  Procedure SetPerspectiveCamera()
    If IsCamera(#MAIN_CAMERA)
      CameraProjectionMode(#MAIN_CAMERA,#PB_Camera_Perspective)
    EndIf
  EndProcedure
  
;=====================================================
; Shortened entity creation, it uses raw PB ID-s
;=====================================================
  Procedure.i entitycreate(mesh.i,material.i,x.i=0,y.i=0,z.i=0,pickmask.i=#PICK)
    Protected.i returnvalue=-1
    If IsMesh(mesh)
      If IsMaterial(material)
        returnvalue = CreateEntity(#PB_Any,MeshID(mesh),MaterialID(material),x,y,z,#PICK,#MAIN_CAMERA)
      Else
        returnvalue = CreateEntity(#PB_Any,MeshID(mesh),#PB_Material_None,x,y,z,pickmask,#MAIN_CAMERA)
      EndIf
     EndIf
    ProcedureReturn returnvalue
  EndProcedure
  
;=====================================================
; Check for compiler version and debugger
; Adjust it to your needs
;=====================================================
  Procedure Checks()
    If #PB_Compiler_Version<#COMPILER_MINIMUM_VERSION
      Debug "Minimum Compiler version is "+ Str(#COMPILER_MINIMUM_VERSION) + "."
      End
    EndIf
    If #PB_Compiler_Debugger
      Debug "Please run without debugger"
      End
    EndIf
  EndProcedure
  
;=====================================================
; Processes windows events
; Delays(0), and examines the keyboard and mouse
;=====================================================
  Procedure SweepEvents()
    Protected w_event.i
    Delay(#MAINLOOP_DELAY)
    Repeat 
      w_event = WindowEvent() : If w_event = #PB_Event_CloseWindow : End : EndIf
    Until Not w_event
    ExamineKeyboard():ExamineMouse()
  EndProcedure
  
;=====================================================
;Short check if Escape is pressed
;=====================================================
  Procedure.i Escape()
    If KeyboardPushed(#PB_Key_Escape)
      ProcedureReturn #True
    EndIf
    ProcedureReturn #False
  EndProcedure
EndModule
;-=====================================================
;-MODULE END
;-=====================================================

;=====================================================
;- EXAMPLES
;=====================================================
Procedure create_example_sprite()
  CreateSprite(1,100,100,#PB_Sprite_AlphaBlending)
  StartDrawing(SpriteOutput(1))
  DrawingMode(#PB_2DDrawing_AllChannels)
  Box(0,0,OutputWidth(),OutputHeight(),RGBA(0,0,0,0))
  Circle(OutputWidth()/2,OutputHeight()/2,Round(OutputWidth()/2-1,#PB_Round_Down),RGBA(255,0,0,255))
  StopDrawing()
EndProcedure

;=====================================================
; A 2d example
;=====================================================
Procedure example_2d()
  ExamineDesktops()
  Sys::open2d(DesktopWidth(0),DesktopHeight(0))
  create_example_sprite()
  ZoomSprite(1,ScreenHeight()/2,ScreenHeight()/2)
  Repeat
    sys::SweepEvents()
    ClearScreen(RGB(20,60,90))
    RotateSprite(1,1,#PB_Relative)
    DisplayTransparentSprite(1,ScreenWidth()/2-SpriteWidth(1)/2,ScreenHeight()/2-SpriteHeight(1)/2)
    FlipBuffers()
  Until sys::Escape()
EndProcedure


;=====================================================
; A 3d example
;=====================================================
Procedure example_3d()
  Protected.i cubeobj
  Sys::open3d(1366,768)
  ;sys::SetOrthoCamera() :;uncomment this line to switch the camera to orthographic
  create_example_sprite()
  CreateLight(1,RGB(255,255,255),0,0,0,#PB_Light_Directional) : LightDirection(1,1,-1,1)
  CreateCube(1,100) 
  cubeobj = sys::entitycreate(1,0,0,0,-500)
  Repeat
    sys::SweepEvents()
    RotateEntity(cubeobj,0,1,0,#PB_Relative)
    RenderWorld()
    RotateSprite(1,1,#PB_Relative)
    DisplayTransparentSprite(1,25,25)
    FlipBuffers()
  Until sys::Escape()
EndProcedure

;-==============================================================
;-RUN THE EXAMPLES HERE
;-==============================================================

example_2d()
;example_3d()
Edit: Left a minor error in the code, fixed.
Last edited by miso on Tue May 13, 2025 1:38 pm, edited 1 time in total.
User avatar
Caronte3D
Addict
Addict
Posts: 1361
Joined: Fri Jan 22, 2016 5:33 pm
Location: Some Universe

Re: 3D snippets

Post by Caronte3D »

Works perfect now! :wink:
User avatar
minimy
Enthusiast
Enthusiast
Posts: 616
Joined: Mon Jul 08, 2013 8:43 pm
Location: off world

Re: 3D snippets

Post by minimy »

Hey miso, yes, work perfect here in 6.21 x86 and x64.
Thanks for share!
If translation=Error: reply="Sorry, Im Spanish": Endif
miso
Enthusiast
Enthusiast
Posts: 466
Joined: Sat Oct 21, 2023 4:06 pm
Location: Hungary

Re: 3D snippets

Post by miso »

Thank you all for testing, I'm confident its good enough. Also small enough to be easily modified.
(manual texture update might be needed in some cases)
One case is if you want to use debugmode renders. Turn on debugmode, render the texture, turn off debugmode and call renderworld.
(otherwise it will be shown on all cameras.)
If needed, I can provide example for that.
User avatar
minimy
Enthusiast
Enthusiast
Posts: 616
Joined: Mon Jul 08, 2013 8:43 pm
Location: off world

Path for entity and cameraman

Post by minimy »

This is a group of procedures to move entity, camera or any thing you want following a path wit curve bezier and easy inout. The camera use zoom and wide lens while follow the object.
Work with this procedures:
bezierNew() add one new.
bezier3Dpoint() start 3 vectors for the first bezier.
bezier3DnextPoint() add 2 new vectors.
bezier3DcloseLoop() add 1 end vector to close the loop.
bezier3Danim() process animation.
Keep out for not abduction, you are advice! :lol:

Code: Select all

;{ SISTEMA 3D GENERAL
Structure sys_struc
  window.i
  scrW.c
  scrH.c
  sprMouse.i
  camara.i
  luz.i
  renderTime.i
EndStructure
Global sys.sys_struc
;}

Global dir.Vector3
Procedure.f getDIstance3D(x1.f,y1.f,z1.f,x2.f,y2.f,z2.f)
  ;devuelve la distancia desde las coordenadas x1,y1,z1 hasta x2,y2,z2
  Protected.f a = x2 - x1
  Protected.f b = y2 - y1
  Protected.f c = z2 - z1
  ProcedureReturn  Sqr(a * a + b * b + c * c)  
EndProcedure

Structure bezier_point_stru
  x.f
  y.f
  z.f
  d.Vector3
  key.b
EndStructure
Structure bezier_stru
  obje.i
  tipo.b
  frame.i
  List p.bezier_point_stru()
EndStructure
Global NewList bezier.bezier_stru()
; Global NewList bezier.Vector3()
#bezier_entity=   0
#bezier_light=    1
#bezier_camera=   2

#bezier_first=    9999999998
#bezier_last=     9999999999
Procedure   bezier3Dnew(obj.i,tipo.b=#bezier_entity)
  AddElement(bezier())
  bezier()\obje= obj
  bezier()\tipo= tipo
  ProcedureReturn bezier()\obje
EndProcedure
Procedure   bezier3Dpoint(obj.i, x1.f,y1.f,z1.f, x2.f,y2.f,z2.f, x3.f,y3.f,z3.f, steps=100)
  ; Genera los puntos de la curva Bezier cuadrática con easing "ease-in-out"
  Protected i, t.f
  
  ForEach bezier()
    If bezier()\obje= obj
      If x1=#bezier_last
        LastElement(bezier()\p()):x1=bezier()\p()\x
      EndIf
      If y1=#bezier_last
        LastElement(bezier()\p()):y1=bezier()\p()\y
      EndIf
      If z1=#bezier_last
        LastElement(bezier()\p()):z1=bezier()\p()\z
      EndIf
      If x3=#bezier_first
        FirstElement(bezier()\p()):x3=bezier()\p()\x
      EndIf
      If y3=#bezier_first
        FirstElement(bezier()\p()):y3=bezier()\p()\y
      EndIf
      If z3=#bezier_first
        FirstElement(bezier()\p()):z3=bezier()\p()\z
      EndIf
      LastElement(bezier()\p())
      For i = 0 To steps
        t = i / steps
        t = t * t * (3 - 2 * t)
        
        AddElement(bezier()\p())
        bezier()\p()\x = Pow((1 - t),2) * x1 + 2 * (1 - t) * t * x2 + Pow(t,2) * x3
        bezier()\p()\y = Pow((1 - t),2) * y1 + 2 * (1 - t) * t * y2 + Pow(t,2) * y3
        bezier()\p()\z = Pow((1 - t),2) * z1 + 2 * (1 - t) * t * z2 + Pow(t,2) * z3
        
        If bezier()\p()\x= x1 And bezier()\p()\y= y1 And bezier()\p()\z= z1 
          bezier()\p()\key= 1
        ElseIf bezier()\p()\x= x2 And bezier()\p()\y= y3 And bezier()\p()\z= z2 
          bezier()\p()\key= 2
        ElseIf bezier()\p()\x= x3 And bezier()\p()\y= y3 And bezier()\p()\z= z3 
          bezier()\p()\key= 3
        Else
          bezier()\p()\key= 0
        EndIf
      Next
    EndIf
  Next
EndProcedure
Procedure   bezier3DnextPoint(obj.i, x1.f,y1.f,z1.f, x2.f,y2.f,z2.f,steps=100)
  bezier3Dpoint(obj,#bezier_last,#bezier_last,#bezier_last,x1,y1,z1,x2,y2,z2,steps)
EndProcedure
Procedure   bezier3DcloseLoop(obj.i, x2.f,y2.f,z2.f,steps=100)
  bezier3Dpoint(obj,#bezier_last,#bezier_last,#bezier_last,x2,y2,z2,#bezier_first,#bezier_first,#bezier_first,steps)
EndProcedure

Procedure   bezier3Danim()
  ForEach bezier()
    If bezier()\tipo= #bezier_entity
      MoveEntity(bezier()\obje,bezier()\p()\x,bezier()\p()\y,bezier()\p()\z,#PB_Absolute)
    ElseIf bezier()\tipo= #bezier_camera
      MoveCamera(bezier()\obje,bezier()\p()\x,bezier()\p()\y,bezier()\p()\z,#PB_Absolute)
    EndIf
    bezier()\frame+1: If bezier()\frame=ListSize(bezier()\p()):bezier()\frame=0:EndIf: SelectElement(bezier()\p(),bezier()\frame)
  Next
EndProcedure

;---- DEMO
Procedure   iniDX(title.s="",decorado.b=#True)
  Protected w,h
  UsePNGImageDecoder()
  UseJPEGImageDecoder()
  
  InitEngine3D()
    InitSprite()
    InitKeyboard()
    InitMouse()
    sys\window= 0
    OpenWindow(0,0,0,800,600,title,#PB_Window_ScreenCentered|#PB_Window_BorderLess|#PB_Window_Maximize);|#PB_Window_Invisible)
    SetWindowColor(0,$444444)
    sys\scrW= WindowWidth(0):sys\scrH=WindowHeight(0)
    AntialiasingMode(#PB_AntialiasingMode_None)
    OpenWindowedScreen(WindowID(0), 0, 0, sys\scrW,sys\scrH, 0,0,0,#PB_Screen_NoSynchronization)
    KeyboardMode(#PB_Keyboard_International)
    CompilerIf #PB_Compiler_Version >= 620
      Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Main", #PB_3DArchive_FileSystem)
      Parse3DScripts() 
    CompilerEndIf
    WorldShadows(#PB_Shadow_Modulative, -1, RGB(128,128,128), 2048)
    EnableWorldPhysics(1)
    EnableWorldCollisions(1)
    
    sys\luz=      CreateLight(#PB_Any,$775544,30,50,0,#PB_Light_Point)
    
    sys\camara=   CreateCamera(#PB_Any,0,0,100,100)
                  MoveCamera(sys\camara,0,25,30)
                  CameraRange(sys\camara, 0.1,1000)
                  CameraBackColor(sys\camara,$995533)
                  
    ;decorados
    If decorado
    Protected   size= 350, res= 256
    Protected.l col1= 0, col2=$aaaaaa
    Protected   suelo_tx3D, suelo_mate, suelo_mesh, suelo
    Protected   cubo_mesh, cubo_mate, cubo_enti
    suelo_tx3D=   CreateTexture(#PB_Any,res,res)
    StartDrawing(TextureOutput(suelo_tx3D))
      Box(0,0,OutputWidth(),OutputHeight(),col1)
      Box(10,10,OutputWidth()-20,OutputHeight()-20,col2)
    StopDrawing()
  
    suelo_mesh=   CreatePlane(#PB_Any,size,size,1,1,1,1)
    suelo_mate=   CreateMaterial(#PB_Any,TextureID(suelo_tx3D))
                  ScaleMaterial(suelo_mate,1/(size/2),1/(size/2))
    suelo=        CreateEntity(#PB_Any, MeshID(suelo_mesh), MaterialID(suelo_mate))
    EndIf

  ProcedureReturn suelo
EndProcedure
Procedure   controlCam()
  Protected.f MouseX,MouseY, mouseW, KeyX,KeyY
  Protected.f CamSpeed= 0.005
  Protected.f CamRotar= 0.01
  
  If KeyboardPushed(#PB_Key_A)
    KeyX = -CamSpeed
  ElseIf KeyboardPushed(#PB_Key_D)
    KeyX = CamSpeed
  Else
    KeyX = 0
  EndIf
  
  If KeyboardPushed(#PB_Key_W)
    KeyY = -CamSpeed
  ElseIf KeyboardPushed(#PB_Key_S)
    KeyY = CamSpeed
  Else
    KeyY = 0
  EndIf
  
  MouseX = -MouseDeltaX() * CamRotar * sys\RenderTime
  MouseY = -MouseDeltaY() * CamRotar * sys\RenderTime
  RotateCamera(sys\camara, MouseY, MouseX, 0, #PB_Relative)
  MoveCamera  (sys\camara, KeyX * sys\RenderTime, 0, KeyY * sys\RenderTime)
EndProcedure

cubo= iniDX("UFO",#True)
AmbientColor($555555)

cubo_mesh=    CreateCube(#PB_Any,2)
bola_mesh=    CreateSphere(#PB_Any,2)
cubo_mat1=    CreateMaterial(#PB_Any, #Null,443322)
SetMaterialColor(cubo_mat1,#PB_Material_DiffuseColor,$332211)
SetMaterialColor(cubo_mat1,#PB_Material_AmbientColor,$332211)
; MaterialShininess(cubo_mat1,2,$887766)
cubo_mat3=    CreateMaterial(#PB_Any, #Null,$ffaa66)
cubo_mat4=    CreateMaterial(#PB_Any, #Null,$ffff00)
cubo_mat2=    CreateMaterial(#PB_Any, #Null,$888888)
DisableMaterialLighting(cubo_mat4,1)
cubo=         CreateEntity(#PB_Any, MeshID(bola_mesh), MaterialID(cubo_mat1));,0,3,0)
ScaleEntity(cubo,1,0.25,1)
cubo3=        CreateEntity(#PB_Any, MeshID(bola_mesh), MaterialID(cubo_mat3));,0,3,0)
ScaleEntity(cubo3,0.5,0.35,0.5)
cubo4=        CreateEntity(#PB_Any, MeshID(bola_mesh), MaterialID(cubo_mat4));,0,3,0)
ScaleEntity(cubo4,0.2,0.2,1.02)
cubo5=        CreateEntity(#PB_Any, MeshID(bola_mesh), MaterialID(cubo_mat4));,0,3,0)
ScaleEntity(cubo5,1.02,0.2,0.2)

cubo2=        CreateEntity(#PB_Any, MeshID(cubo_mesh), MaterialID(cubo_mat2),0,1,0)
AttachEntityObject(cubo,"",EntityID(cubo3))
AttachEntityObject(cubo,"",EntityID(cubo4))
AttachEntityObject(cubo,"",EntityID(cubo5))
MoveEntity(cubo3,0,0.5,0)

CreateStaticGeometry(0, 1000, 1000, 1000, #True)
For p= 1 To 250
  e=CopyEntity(cubo2,#PB_Any)
  s= Random(8,2)
  ScaleEntity(e,s/Random(4,1),s,s/Random(4,1),#PB_Absolute)
  MoveEntity(e,Random(300)-150,s/2,Random(300)-150,#PB_Absolute)
;   e=CopyEntity(cubo2,#PB_Any)
;   s= Random(8,2)
;   ScaleEntity(e,s/4,s,s/4,#PB_Absolute)
;   MoveEntity(e,Random(100)*-1,1,Random(100)*-1,#PB_Absolute)
Next p
BuildStaticGeometry(0)


;-------------ENTITY
bezier3Dnew(cubo)
pasos= 100
a= Random(360,65)
bezier3Dpoint(cubo,Random(a,a/2)-(a/2),20+Random(5,1),Random(a,a/2)-(a/2),
              Random(a,a/2)-(a/2),20+Random(5,1),Random(a,a/2)-(a/2),
              Random(a,a/2)-(a/2),20+Random(5,1),Random(a,a/2)-(a/2),pasos)
For p= 1 To 10
RandomSeed(p)
  bezier3DnextPoint(cubo,Random(a,a/2)-(a/2),20+Random(21,1),Random(a,a/2)-(a/2),
                    Random(a,a/2)-(a/2),20+Random(20,1),Random(a,a/2)-(a/2),pasos)
Next p
bezier3DcloseLoop(cubo,Random(a,a/2)-(a/2),20+Random(5,1),Random(a,a/2)-(a/2),pasos)

FirstElement(bezier()\p())
MoveEntity(cubo,bezier()\p()\x,bezier()\p()\y,bezier()\p()\z,#PB_Absolute)

;-------------CAMARA
bezier3Dnew(sys\camara,#bezier_camera)
pasos= 200
a= Random(360,65)
bezier3Dpoint(sys\camara,Random(a,a/2)-(a/2),20+Random(5,3),Random(a,a/2)-(a/2),
              Random(a,a/2)-(a/2),Random(5,3),20+Random(a,a/2)-(a/2),
              Random(a,a/2)-(a/2),20+Random(5,3),Random(a,a/2)-(a/2),pasos)
For p= 1 To 20
  RandomSeed(p+10)
  bezier3DnextPoint(sys\camara,Random(a,a/2)-(a/2),20+Random(81,3),Random(a,a/2)-(a/2),
                    Random(a,a/2)-(a/2),20+Random(20,1),10+Random(a,a/2)-(a/2),pasos)
Next p
bezier3DcloseLoop(sys\camara,Random(a,a/2)-(a/2),20+Random(5,3),Random(a,a/2)-(a/2),pasos)

FirstElement(bezier()\p())
; MoveCamera(sys\camara,bezier()\p()\x,bezier()\p()\y,bezier()\p()\z,#PB_Absolute)


; bezier3DvectorDir(cubo)
CameraLookAt(sys\camara, EntityX(cubo),EntityY(cubo),EntityZ(cubo))


;----- LOOP
AddWindowTimer(sys\window,0,1000/60)
Repeat
  Repeat
    ev= WindowEvent()
    Select ev
      Case #PB_Event_Timer
        bezier3Danim()
    EndSelect
  Until ev= 0
  
  ExamineKeyboard()
  ExamineMouse()
  controlCam()

  If KeyboardPushed(#PB_Key_Escape)
    sal=1
  EndIf
  
  
  d.f= 90-getDIstance3D(CameraX(sys\camara),CameraY(sys\camara),CameraZ(sys\camara),EntityX(cubo),EntityY(cubo),EntityZ(cubo))
  If d < 20
    d=20
  ElseIf d > 140
    d=140
  EndIf
  CameraFOV(sys\camara, d)
  RotateEntity(cubo,0,5,0,#PB_Relative)

  CameraLookAt(sys\camara, EntityX(cubo),EntityY(cubo),EntityZ(cubo))
  sys\renderTime = RenderWorld()
  
  FlipBuffers()
  Delay(1)
Until sal=1
If translation=Error: reply="Sorry, Im Spanish": Endif
miso
Enthusiast
Enthusiast
Posts: 466
Joined: Sat Oct 21, 2023 4:06 pm
Location: Hungary

Re: 3D snippets

Post by miso »

Nice!
User avatar
Caronte3D
Addict
Addict
Posts: 1361
Joined: Fri Jan 22, 2016 5:33 pm
Location: Some Universe

Re: 3D snippets

Post by Caronte3D »

Useful procedures, thanks for sharing! :wink:
miso
Enthusiast
Enthusiast
Posts: 466
Joined: Sat Oct 21, 2023 4:06 pm
Location: Hungary

Re: 3D snippets

Post by miso »

As I said, it's cool. Let me add a tip and trick. In my distance calculus if it's in a game that needs speed, I often drop the sqr part and check against the multiplied radius if I need only the information if something is in range.
miso
Enthusiast
Enthusiast
Posts: 466
Joined: Sat Oct 21, 2023 4:06 pm
Location: Hungary

Re: 3D snippets

Post by miso »

Tiny mesh file format. Goal was to reduce the size of the mesh data (to fit in codes created for the PB forum).

Code: Select all

;TINY MESH FILE FORMAT
;Created by miso
;20250518 PB 6.21 beta 9

;===============
;-SPECIFICATIONS
;=====================================================================================================
;Handles submeshes up To 256 total
;A single submesh can have maximum 65535 vertices
;A single submesh can have maximum 65535 triangles
;Does not work with extreme huge meshes or with ones that are translated extreme far from the origo
;Never  seen  this while testing, but because  it is  interpolated, it is  in it's  nature 
;to create  visual artifacts if mesh is very big, and the geometric details are very small
;The saved tiny mesh is not a lossless exact copy of the original, but a mimic that closely
;resembles to it.
;=====================================================================================================


EnableExplicit
;-========================================
;-PROCEDURES
;-========================================
Procedure Displayinfo()
  Debug "Original mesh size: " + Str(FileSize(#PB_Compiler_Home+"examples/3d/Data/Models/PureBasic.mesh"))+" bytes."
  Debug "Datasection size: "+Str(?pbe-?pb)+" bytes."
EndProcedure

Procedure.f LERP(a.f,b.f,t.f)
  ProcedureReturn(((1.0-t.f)*a) + (b*t))
EndProcedure
  
Procedure.f INVLERP(a.f,b.f,v.f)
  If a=b : ProcedureReturn(1) : EndIf
  ProcedureReturn((v-a) / (b-a))
EndProcedure
  
Procedure.f remap(iMin.f,iMAX.f, oMin.f, oMax.f, v.f)  
  Protected t.f
  t.f = INVLERP(iMin,iMAX,v)
  ProcedureReturn(LERP(oMin,oMax,t))
EndProcedure

;**************************************************
;This saves an existing mesh to disk in Tiny format
;**************************************************
Procedure Save_TinyMesh(mesh_id,filename.s)
  If IsMesh(mesh_id)
    Protected minx.f=1000000,maxx.f=-1000000,miny.f=1000000,maxy.f=-1000000,minz.f=1000000,maxz.f=-1000000,minu.f=1000000,maxu.f=-1000000,minv.f=1000000,maxv.f=-1000000
    Protected fh.i,i.i,j.i
    Protected Dim vertices.MeshVertex(0)
    Protected Dim faces.MeshFace(0)
    fh =OpenFile(#PB_Any,GetCurrentDirectory()+filename.s)
    For i = 0 To SubMeshCount(mesh_id)-1
      GetMeshData(mesh_id,i,vertices(),#PB_Mesh_Vertex|#PB_Mesh_UVCoordinate|#PB_Mesh_Normal,0,MeshVertexCount(Mesh_ID,i)-1)
      For j = 0 To MeshVertexCount(mesh_id,i)-1
        If vertices(j)\x<minx : minx = vertices(j)\x:EndIf
        If vertices(j)\y<miny : miny = vertices(j)\y:EndIf
        If vertices(j)\z<minz : minz = vertices(j)\z:EndIf
        If vertices(j)\u<minu : minu = vertices(j)\u:EndIf
        If vertices(j)\v<minv : minv = vertices(j)\v:EndIf
        If vertices(j)\x>maxx : maxx = vertices(j)\x:EndIf
        If vertices(j)\y>maxy : maxy = vertices(j)\y:EndIf
        If vertices(j)\z>maxz : maxz = vertices(j)\z:EndIf
        If vertices(j)\u>maxu : maxu = vertices(j)\u:EndIf
        If vertices(j)\v>maxv : maxv = vertices(j)\v:EndIf
      Next j
    Next i
    
    WriteFloat(fh,minx):WriteFloat(fh,maxx)
    WriteFloat(fh,miny):WriteFloat(fh,maxy)
    WriteFloat(fh,minz):WriteFloat(fh,maxz)
    WriteFloat(fh,minu):WriteFloat(fh,maxu)
    WriteFloat(fh,minv):WriteFloat(fh,maxv)
    WriteAsciiCharacter(fh,SubMeshCount(mesh_id))
    
    For i = 0 To SubMeshCount(mesh_id)-1
      WriteUnicodeCharacter(fh,MeshVertexCount(Mesh_ID.i,i))
      ReDim vertices(MeshVertexCount(Mesh_ID,i))
      GetMeshData(mesh_id,i,vertices(),#PB_Mesh_Vertex|#PB_Mesh_UVCoordinate|#PB_Mesh_Normal,0,MeshVertexCount(Mesh_ID,i)-1)
      For j = 0 To MeshVertexCount(mesh_id,i)-1
        WriteAsciiCharacter(fh,Round(remap(minx,maxx,0,255,vertices(j)\x),#PB_Round_Nearest))
        WriteAsciiCharacter(fh,Round(remap(miny,maxy,0,255,vertices(j)\y),#PB_Round_Nearest))
        WriteAsciiCharacter(fh,Round(remap(minz,maxz,0,255,vertices(j)\z),#PB_Round_Nearest))
        WriteAsciiCharacter(fh,Round(remap(minu,maxu,0,255,vertices(j)\u),#PB_Round_Nearest))
        WriteAsciiCharacter(fh,Round(remap(minv,maxv,0,255,vertices(j)\v),#PB_Round_Nearest))
      Next j
      WriteUnicodeCharacter(fh,MeshIndexCount(mesh_id,i))
      ReDim faces(MeshIndexCount(mesh_id,i))
      GetMeshData(mesh_id,i,faces(),#PB_Mesh_Face,0,MeshIndexCount(mesh_id,i)-1)
      For j = 0 To MeshIndexCount(mesh_id,i)-1
        WriteUnicodeCharacter(fh,faces(j)\Index)
      Next j
    Next i
    CloseFile(fh)
  EndIf
EndProcedure

;*******************************************************************
;This catches a Tiny format mesh from memory or datasection location
;*******************************************************************
Procedure.i CatchTinymesh(*buffer)
  Protected submeshes.i,i.i,vcount.i,j.i,m_ind.i,bytes.i,o.i,mesh_id.i
  Protected minx.f,maxx.f,miny.f,maxy.f,minz.f,maxz.f,minu.f,minv.f,maxu.f,maxv.f
  Protected Dim vertices.MeshVertex(0)
  Protected Dim faces.MeshFace(0)
  mesh_id = CreateMesh(#PB_Any,#PB_Mesh_TriangleList,#PB_Mesh_Static)
  minx = PeekF(*buffer+o):o+4:maxx = PeekF(*buffer+o):o+4
  miny = PeekF(*buffer+o):o+4:maxy = PeekF(*buffer+o):o+4
  minz = PeekF(*buffer+o):o+4:maxz = PeekF(*buffer+o):o+4
  minu = PeekF(*buffer+o):o+4:maxu = PeekF(*buffer+o):o+4
  minv = PeekF(*buffer+o):o+4:maxv = PeekF(*buffer+o):o+4
  submeshes = PeekA(*buffer+o):o+1
  For i = 0 To SubMeshes-1
    If i<>0:AddSubMesh(): EndIf
    vcount = PeekU(*buffer+o):o+2
    ReDim vertices(vcount)
    For j = 0 To vcount-1
      vertices(j)\x=remap(0,255,minx,maxx,PeekA(*buffer+o)):o+1
      vertices(j)\y=remap(0,255,miny,maxy,PeekA(*buffer+o)):o+1
      vertices(j)\z=remap(0,255,minz,maxz,PeekA(*buffer+o)):o+1
      vertices(j)\u=remap(0,255,minu,maxu,PeekA(*buffer+o)):o+1
      vertices(j)\v=remap(0,255,minv,maxv,PeekA(*buffer+o)):o+1
      vertices(j)\Color=RGB(128,128,128)
      MeshVertex(vertices(j)\x,vertices(j)\y,vertices(j)\z,vertices(j)\u,vertices(j)\v,vertices(j)\Color,vertices(j)\NormalX,vertices(j)\NormalY,vertices(j)\NormalZ)
    Next j
    m_ind=PeekU(*buffer+o):o+2
    ReDim faces(m_ind)
    For j = 0 To m_ind-1
      faces(j)\Index=PeekU(*buffer+o):o+2
      MeshIndex(faces(j)\index)
    Next j
  Next i
  FinishMesh(#True)
  ProcedureReturn mesh_id
EndProcedure

;*******************************************************************
;This catches a Tiny format mesh from memory or datasection location
;that is inside a zip.
;*******************************************************************
Procedure.i CatchTinyZipMesh(*buffer2,size.i,name.s)
  Protected pack.i,packsize.i,mesh_id.i,*buffer
  UseZipPacker()
  pack=CatchPack(#PB_Any,*buffer2,size)
  ExaminePack(pack)
  While NextPackEntry(pack)
    If PackEntryName(pack) = name
      packsize=PackEntrySize(pack,#PB_Packer_UncompressedSize)
      *buffer= AllocateMemory(packsize)
      UncompressPackMemory(pack,*buffer,packsize)
      mesh_id =CatchTinymesh(*buffer)
      FreeMemory(*buffer)
      ClosePack(pack)
      ProcedureReturn mesh_id
     EndIf
   Wend
   ClosePack(pack)
  ProcedureReturn -1
EndProcedure

;***************************************
;This Loads a Tiny format mesh from disk
;***************************************
Procedure.i LOAD_TinyMesh(filename.s)
  Protected mesh_id.i,*buffer,bytes.i,fh.i
  If IsMesh(mesh_id) Or Not FileSize(filename): ProcedureReturn(-1) :EndIf
  *buffer = AllocateMemory(FileSize(filename))
  Debug *buffer
  fh = ReadFile(#PB_Any,GetCurrentDirectory()+filename.s)
  bytes = ReadData(fh,*buffer,FileSize(filename))
  CloseFile(fh)
  If bytes <> FileSize(filename)
    FreeMemory(*buffer)
    ProcedureReturn -1
  Else
    mesh_id = CatchTinymesh(*buffer)
    FreeMemory(*buffer)
    ProcedureReturn(mesh_id)
  EndIf
EndProcedure
 
EnableExplicit
;-========================================
;-MAIN PROGRAM
;-========================================
ExamineDesktops()
InitEngine3D()
InitSprite()
InitKeyboard()
InitMouse()
OpenWindow(0,0,0,DesktopUnscaledX(DesktopWidth(0)),DesktopUnscaledY(DesktopHeight(0)),"Tinymesh", #PB_Window_BorderLess)
OpenWindowedScreen(WindowID(0),0,0,WindowWidth(0),WindowHeight(0),1,0,0,#PB_Screen_SmartSynchronization):SetFrameRate(60)
CreateCamera(0,0,0,100,100)
CreateLight(0,RGB(255,255,255),0,0,0,#PB_Light_Directional)
LightDirection(0,1,-1,-1)

Define tm.i  = CatchTinyZipMesh(?pb,?pbe-?pb,"pb.tiny") : NormalizeMesh(tm)
Define mat.i = CreateMaterial(#PB_Any,#Null,RGB(255,15,15)) : MaterialShadingMode(mat,#PB_Material_Gouraud)
Define ent.i = CreateEntity(#PB_Any,MeshID(tm),MaterialID(mat),0,0,-50)

Repeat
  Repeat: Until Not WindowEvent()
  ExamineKeyboard() : ExamineMouse()
  RotateEntity(ent,0,1,0,#PB_Relative)
  RenderWorld()
  FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)

Displayinfo()
;-========================================
;-DATA
;-========================================
DataSection
pb:
Data.q $0002001404034B50,$A77B5AB25AB20008,$090D000005E59F56,$6270000000070000,$EB953D796E69742E,$25101FC614655457,$62A5A0A8968948F3,$30540C71D208B479,$033359864A882E93
Data.q $BD60BB52B22323DE,$28B94505E0E0AFDE,$599898638EBBC778,$5F1BEB4B56703FD1,$B25C1F43E78FAB5A,$7BD9EB256B3BF67B,$BDF9FBD9F670739F,$AFEF177B9C94ED43,$FE2B7BCCF167FA28
Data.q $6777D3CFE574575E,$3FF99FF60B3B3ADC,$078305C4BF8EFD27,$B434DC18D2F319B9,$D8E9B98B6974BCC5,$333706DECA65E0DB,$6CDC19B2F069DD51,$39B830E5E42DAAD8,$C1B909A9417909A8
Data.q $85B83215E0595544,$0C370661781495B0,$F156E0C557843D5B,$9544FADC017ABC1D,$0AD876DC19DAF213,$46AD84EDC193AF21,$06D2863706317836,$C4546EDC1B4A5BAF,$6A893DB988A91EBC
Data.q $9AB60F5C18F3CC78,$715B0BDB832F5E2A,$B8B1294ED79D114A,$E93B8D694A746693,$51332751DD94A746,$5B1B64EA3B7294E9,$4E8C72711AD294E9,$4A74A89827113529,$A53A56C6853BE489
Data.q $A53A56C6C277CE3C,$C9294E8CAA72483C,$372529D2A27D4E49,$1C9294E95B1BB4EC,$15194A74AD8D3A71,$D3A8D294A7466275,$127A7716594A746D,$B633C77119294E95,$5B1AF4E7D02529D2
Data.q $06188E7D87914A71,$D2177343485DEB98,$6C8759B8990EADB1,$620895D507225734,$FE308837F8851049,$408F505352154148,$D5644E895A91DA25,$2EAAC6E875058621,$D08F821E0BAB20F4
Data.q $878FC0034411EF0B,$DE895A247C4D3C7E,$D2CBDEA0D3EA0863,$E80D7C7BC08955CB,$BAA0F92F435F406B,$864BD00D9D416192,$E4BD017BD2CBDE80,$F7D0A6FA14DF429B,$5EFE53ECBA1AA7D3
Data.q $3E7D878653E88A6A,$9FB8D699A7EE2C4C,$EA3B734CFD47766E,$7E231B4F88D69B67,$DF38F342FDF244D0,$4E49957E49079B0F,$C9376FD86E4DEBF2,$2034FA8A8CD3BF11,$64C7BF71659B77EA
Data.q $EE5EFCFA04CF7DC4,$3BA2A77454EE17D4,$2A77454EE8A9DD15,$7454EE8A9DD153BA,$4EE8A9DD153BA2A7,$8A9DD153BA2A7745,$8029FA22A77454EE,$0F6563D9A8F6743D,$6243D8B8F6423D93
Data.q $57416F22DF85868F,$744AEEC22E87B5E3,$D1921240C9B50CCF,$F152006A7F414A8F,$C183820C49E20604,$4C4218D3C29E1A54,$8E18B3C19E186286,$C9B9146246046A0C,$631E7873C18C68C2
Data.q $0263C68C4F1A8E31,$30931708988BC05E,$720AF57265E12F19,$0454D4298ABD4791,$47C86BC74DA08D30,$15D48B3133033501,$B981BC1CC75E3661,$EF1B785BC4DEA628,$8058F98A50F304A0
Data.q $3DEA22C5DEA32885,$807C12C7DE316394,$92A05411B022110F,$600A8CB05352969D,$A4AC02A82B1D3539,$1CD4D58455156266,$FA7662F29315447C,$A13E3E6A1AC12A98,$3954A7C22D4D50CA
Data.q $2D610A8CF825A86A,$3AC4BE05F1CF8155,$B579AF857C06C7AC,$AB2362D45BE0DF0E,$69F1360C3DF3F8EF,$DBDE56C16F33362D,$5DAB276076ACED86,$8EA2F7AC3D8DD9FC,$BBBF8FB29F9EABFF
Data.q $071FB43A068A319D,$710743A41C01D0E8,$C46A1D23421D0E88,$11D0E84718743A61,$4743A51C26A1D134,$6A1D33431D0E8C71,$6A1D2B416A1D0B46,$743A71C36A1D1B45,$49E89E09D0E8271C
Data.q $5A7649C0EA1D0754,$E9D9A70A74EC538F,$A7659C19D3B0CE34,$9D9E70E74EC738B3,$4EC0BA89A02BF3CE,$3B12E22E9D917017,$EC2B8CBA7665C25D,$B1AE2AE9D9570574,$C1B8EBA7675C35D3
Data.q $E4DD41D1CDF8374E,$BEE7ACBDCE23362E,$0A4FEC2967EC2960,$2A1C81F881C3916F,$821C391761498385,$4A87247E1870E4DB,$F9330E43BC290661,$A54392EF0A459445,$44FE149B30A59C70
Data.q $9F8C9C391EE2270E,$F23CC393EE0E61C9,$798061C8F22E4B91,$7CE602C39008B91A,$9367988B0E405172,$5C973CCC5872228B,$A2E479E612C39314,$6517242F31961C84,$2728B931799CB0E4
Data.q $CFB108D930E62187,$CFB2970A47911252,$2B3ECE5C2900E672,$CD59F64AE1480B99,$73154FB3570A445C,$25CC359F62AC2931,$91973354FB0D70A4,$85272E61A9F66AC2,$D70A443996B3EC35
Data.q $52E92367A4759A92,$70B6E644DAC90CC2,$64EF5E56D2C85BCB,$6A57E177985F81DE,$6DA495B7324EE30F,$4DE46FDB48FB6B27,$01FFD0A5B4B64B69,$39B4B20C6E91ADE4,$A18DD135BC8D3FF4
Data.q $D386DA5379187FF4,$A68C6E85ADE411FF,$D2D636D29BC863FF,$74ED6F204FFE9E36,$D24EDE4C9FFD1263,$83B69603B696FD8D,$DB4B46B69643B696,$A5935B4B11DB4B61,$D9ADA598EDA5A8ED
Data.q $B5B4B56B6962D6D2,$DA584EDA5B8EDA59,$B724EDA41D6D2DDA,$16ADA40DAADFE711,$001402014B5001FF,$5AB2000800020014,$05E59F56A77B5AB2,$00070000090D0000,$0000000000000000
Data.q $0000000000000020,$50796E69742E6270,$010000000006054B,$0A00000035000100
Data.a $06,$00,$00,$00,$00
pbe:
EndDataSection
User avatar
minimy
Enthusiast
Enthusiast
Posts: 616
Joined: Mon Jul 08, 2013 8:43 pm
Location: off world

Re: 3D snippets

Post by minimy »

Thanks for comments! Aliens are comming :mrgreen:

Fantastic!! miso, your Tiny mesh file format is very usefull. Great idea to include all in one.
Thanks a lot for share this snippet, i think is one of the most useful piece of code in the 3D forum.
miso wrote: Sat May 17, 2025 11:46 am As I said, it's cool. Let me add a tip and trick. In my distance calculus if it's in a game that needs speed, I often drop the sqr part and check against the multiplied radius if I need only the information if something is in range.
Nice idea! yes is more fast, if use integer is more fast. Thanks for lesson friend!
If translation=Error: reply="Sorry, Im Spanish": Endif
User avatar
minimy
Enthusiast
Enthusiast
Posts: 616
Joined: Mon Jul 08, 2013 8:43 pm
Location: off world

Normal map texture from image

Post by minimy »

Hello again! :lol: I did 3 procedures for my own use.
showImage(img) As say.. Show and image, is nice to watch procedural images. (i think)..
brick(s=256,spc=2) I cant remember what do this.. Ah! create brick image.
ImgToNormalMap(imageID, strength.f=1.0, invertX.b=#False, invertY.b=#False)
Play with strength, invertX and invertY to found your perfect normal map.

Code: Select all


UsePNGImageDecoder()
UseJPEGImageDecoder()

Procedure   showImage(img)
  If IsImage(img)
    SetWindowColor(OpenWindow(#PB_Any,0,0,ImageWidth(img),ImageHeight(img),"Test imagen: "+Str(img)) , $ff0000)
    
    ImageGadget(#PB_Any,0,0,ImageWidth(img),ImageHeight(img),ImageID(img))
  EndIf
EndProcedure
Procedure   brick(s=256,spc=2)
  Protected   i= CreateImage(#PB_Any,s,s,32)
  Protected   x,y,w=s*0.2,h=s*0.1
  Protected   n
  Protected.l ink=$ff5577aa, paper=$ff343434;$ff223344
  StartVectorDrawing(ImageVectorOutput(i))
  VectorSourceColor(paper)
  AddPathBox(0,0,VectorOutputWidth(),VectorOutputHeight())
  FillPath()
  Repeat
    VectorSourceColor(ink)
    AddPathBox(x+spc,y+spc,w-(spc*2),h-(spc*2)): x+w
    FillPath()
    If x>VectorOutputWidth()
      n+1:y+h: If n%2:x=-(w/2):Else:x=0:EndIf
    EndIf
  Until y>VectorOutputHeight()
  StopVectorDrawing()
  
  ;dirty
  StartDrawing(ImageOutput(i))
  DrawingMode(#PB_2DDrawing_AlphaBlend)
    For y= 0 To OutputHeight()-1 Step 4
      For x= 0 To OutputWidth()-1 Step 4
        If Red(Point(x,y))= Red(ink)
          If Random(1)
            Circle(x,y,Random(spc*2),RGBA(255,255,255,15))
          Else
            Circle(Random(2)+x-1,Random(2)+y-1,Random(spc*2),RGBA(0,0,0,15))
          EndIf
            
        EndIf
      Next x
    Next y
    
    For y= 0 To OutputHeight()-1 Step 4
      For x= 0 To OutputWidth()-1 Step 4
        If Red(Point(x,y))= Red(paper) 
          Circle(Random(2)+x-1,Random(2)+y-1,Random(spc*2),paper)
          Circle(Random(2)+x-1,Random(2)+y-1,Random(spc*2),RGBA(0,0,0,35))
        EndIf
      Next x
    Next y
    
    For y= 0 To OutputHeight()-1 Step 4
      For x= 0 To OutputWidth()-1 Step 4
        If Red(Point(x,y))= Red(paper)
          If Random(1)
            Circle(Random(2)+x-1,Random(2)+y-1,Random(spc*2),RGBA(0,Random(200,100),0,65))
          Else
            Circle(Random(2)+x-1,Random(2)+y-1,Random(spc*2),RGBA(0,Random(100,30),0,75))
          EndIf
        EndIf
      Next x
    Next y
  StopDrawing()
  
  ProcedureReturn i
EndProcedure

Procedure   ImgToNormalMap(image, strength.f=1.0, invertX.b=#False, invertY.b=#False)
  Protected.f deltaX,deltaY
  Protected.l gleft,gRight,gUp,gDown
  Protected.c x,y
  Protected.a r,g,b
  Protected   normalMapID
  Protected.c width = ImageWidth(image)
  Protected.c height = ImageHeight(image)
  Protected.f nx,ny,nz
  Protected.l Dim px(width,height)
  StartDrawing(ImageOutput(image))
  For y = 1 To height - 2
    For x = 1 To width - 2
      If invertX
        gleft=  Point(x+1,y): gRight= Point(x-1,y)
      Else
        gleft=  Point(x-1,y): gRight= Point(x+1,y)
      EndIf
      deltaX = ((Red(gRight) + Green(gRight) + Blue(gRight)) / 3.0) - ((Red(gLeft) + Green(gLeft) + Blue(gLeft)) / 3.0)
      If invertY
        gUp=    Point(x,y+1): gDown=  Point(x,y-1)
      Else
        gUp=    Point(x,y-1): gDown=  Point(x,y+1)
      EndIf
      deltaY = ((Red(gDown) + Green(gDown) + Blue(gDown)) / 3.0) - ((Red(gUp) + Green(gUp) + Blue(gUp)) / 3.0)
      nx = deltaX * strength: ny = deltaY * strength: nz = 1.0
      length = Sqr(nx*nx + ny*ny + nz*nz): nx = nx / length: ny = ny / length: nz = nz / length
      r = Int((nx + 1) * 127.5):g = Int((ny + 1) * 127.5): b = Int((nz + 1) * 127.5)
      px(x,y)= RGB(r, g, b)
    Next x
  Next y
  StopDrawing()
  normalMapID = CreateImage(#PB_Any, width, height, 32)
  StartDrawing(ImageOutput(normalMapID))
  For y = 1 To height - 2
    For x = 1 To width - 2
      Plot(x,y,px(x,y))
    Next x
  Next y
  StopDrawing()
  FreeArray(px())
  ProcedureReturn normalMapID
EndProcedure

; img= LoadImage(#PB_Any,"D:\ladrillo.jpg") ;load your own image
img= brick()
showImage(img)
img2= ImgToNormalMap(img, 0.02, #True, #True)
showImage(img2)

InitEngine3D():InitSprite():InitKeyboard():InitMouse()

ExamineDesktops():dx=DesktopWidth(0)*0.6:dy=DesktopHeight(0)*0.6
OpenWindow(0, 0,0, DesktopUnscaledX(dx),DesktopUnscaledY(dy), "NormalMap",#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0), 0, 0, dx, dy, 0, 0, 0)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Main",#PB_3DArchive_FileSystem)
Parse3DScripts()

light = CreateLight(#PB_Any ,$ffffff, 20, 40, -10, #PB_Light_Point)
; AmbientColor(RGB(15,15,15))

CreateCamera(0,0,0,100,100):MoveCamera(0,1,3,-2,#PB_Absolute):CameraLookAt(0,0,1,0)

;image --> textures
tx3d1= CreateTexture(#PB_Any,ImageWidth(img),ImageHeight(img))
StartDrawing(TextureOutput(tx3d1))
  DrawingMode(#PB_2DDrawing_AllChannels)
  DrawImage(ImageID(img),0,0)
StopDrawing()
tx3d2= CreateTexture(#PB_Any,ImageWidth(img),ImageHeight(img))
StartDrawing(TextureOutput(tx3d2))
  DrawingMode(#PB_2DDrawing_AllChannels)
  DrawImage(ImageID(img2),-1,-1,ImageWidth(img2)+2,ImageHeight(img2)+2)
StopDrawing()

;bumpy party
mesh= CreateCube(#PB_Any,1)
mate=  CreateShaderMaterial(#PB_Any, #PB_Material_BumpShader)
MaterialShaderTexture(mate,TextureID(tx3d1),TextureID(tx3d2),0,0)
MaterialShaderParameter(mate,#PB_Shader_Fragment,"bumpy",#PB_Shader_Float,1,0,0,0)
SetMaterialColor(mate, #PB_Material_DiffuseColor,RGB(250,250,250))
SetMaterialColor(mate, #PB_Material_AmbientColor,RGB(60,60,60))
MaterialShininess(mate,125,$ffffff)
MaterialFilteringMode(mate,#PB_Material_Trilinear)

enti= CreateEntity(#PB_Any,MeshID(mesh),MaterialID(mate),0,1.2,0)

ReleaseMouse(#True)
Repeat
  While WindowEvent():Wend
  ExamineMouse(): ExamineKeyboard()
  RotateEntity(enti,0,0.1,0,#PB_Relative)
  RenderWorld()
  FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)
End

If translation=Error: reply="Sorry, Im Spanish": Endif
miso
Enthusiast
Enthusiast
Posts: 466
Joined: Sat Oct 21, 2023 4:06 pm
Location: Hungary

Re: 3D snippets

Post by miso »

That's pretty cool, thanks for sharing.
User avatar
minimy
Enthusiast
Enthusiast
Posts: 616
Joined: Mon Jul 08, 2013 8:43 pm
Location: off world

Re: 3D snippets

Post by minimy »

Thanks miso!
If translation=Error: reply="Sorry, Im Spanish": Endif
User avatar
minimy
Enthusiast
Enthusiast
Posts: 616
Joined: Mon Jul 08, 2013 8:43 pm
Location: off world

Draw texture and bump at once

Post by minimy »

Im here again with more textures, hehe... :mrgreen:
This is a group of procedures to draw as startdrawing, more or less. But can set the deep of the object to draw. Later return the number of the image and the bump image in normal way (gray) or like a normal map.

The procedures are:
ShowImage() and ImgToNormalMap(image, strength.f=1.0, invertX.b=#False, invertY.b=#False) (can see in the previous post)

dtbAdd(x.c,y.c,w.c,h.c, ink.l=$ffffff, level.b=0, type.a=#dtb_box, r1.a=10,r2.a=10, txt.s="",font=-1) Add shape to draw list.
dtbGetTexture(w=512,h=512) Return the image.
dtbAdd(x.c,y.c,w.c,h.c, ink.l=$ffffff, level.b=0, type.a=#dtb_box, r1.a=10,r2.a=10, txt.s="",font=-1) Return the bump image
dtbClear() Clean the list to start other image.

include one texture as example.

Code: Select all

Procedure   showImage(img)
  If IsImage(img)
    SetWindowColor(OpenWindow(#PB_Any,0,0,ImageWidth(img),ImageHeight(img),"Test imagen: "+Str(img)) , $ff0000)
    ImageGadget(#PB_Any,0,0,ImageWidth(img),ImageHeight(img),ImageID(img))
  EndIf
EndProcedure
Procedure   ImgToNormalMap(image, strength.f=1.0, invertX.b=#False, invertY.b=#False)
  Protected.f deltaX,deltaY
  Protected.l gleft,gRight,gUp,gDown
  Protected.c x,y
  Protected.a r,g,b
  Protected   normalMapID
  Protected.c width = ImageWidth(image)
  Protected.c height = ImageHeight(image)
  Protected.f nx,ny,nz
  Protected.l Dim px(width,height)
  StartDrawing(ImageOutput(image))
  For y = 1 To height - 2
    For x = 1 To width - 2
      If invertX
        gleft=  Point(x+1,y): gRight= Point(x-1,y)
      Else
        gleft=  Point(x-1,y): gRight= Point(x+1,y)
      EndIf
      deltaX = ((Red(gRight) + Green(gRight) + Blue(gRight)) / 3.0) - ((Red(gLeft) + Green(gLeft) + Blue(gLeft)) / 3.0)
      If invertY
        gUp=    Point(x,y+1): gDown=  Point(x,y-1)
      Else
        gUp=    Point(x,y-1): gDown=  Point(x,y+1)
      EndIf
      deltaY = ((Red(gDown) + Green(gDown) + Blue(gDown)) / 3.0) - ((Red(gUp) + Green(gUp) + Blue(gUp)) / 3.0)
      nx = deltaX * strength: ny = deltaY * strength: nz = 1.0
      length = Sqr(nx*nx + ny*ny + nz*nz): nx = nx / length: ny = ny / length: nz = nz / length
      r = Int((nx + 1) * 127.5):g = Int((ny + 1) * 127.5): b = Int((nz + 1) * 127.5)
      px(x,y)= RGB(r, g, b)
    Next x
  Next y
  StopDrawing()
  normalMapID = CreateImage(#PB_Any, width, height, 32)
  StartDrawing(ImageOutput(normalMapID))
  For y = 1 To height - 2
    For x = 1 To width - 2
      Plot(x,y,px(x,y))
    Next x
  Next y
  StopDrawing()
  FreeArray(px())
  ProcedureReturn normalMapID
EndProcedure

;{ DTB draw real texture bump map - Draw bump map independent of texture color
#dtb_box=     0
#dtb_roundBox=1
#dtb_ellipse= 2
#dtb_line=    3
#dtb_text=    4
Structure   drawTx3dBump_stru
  x.c
  y.c
  w.c
  h.c
  r1.a
  r2.a
  ink.l
  level.a
  type.a
  txt.s
  font.i
EndStructure
Global NewList dtb.drawTx3dBump_stru()
Procedure   dtbGetTexture(w=512,h=512)
  Protected   i= CreateImage(#PB_Any,w,h)
  StartDrawing(ImageOutput(i))
  DrawingMode(#PB_2DDrawing_Transparent)
  ForEach dtb()
    Select dtb()\type
      Case #dtb_box
        Box(dtb()\x,dtb()\y,dtb()\w,dtb()\h,dtb()\ink)
      Case #dtb_roundBox
        RoundBox(dtb()\x,dtb()\y,dtb()\w,dtb()\h,dtb()\r1,dtb()\r2,dtb()\ink)
      Case #dtb_ellipse
        Ellipse(dtb()\x,dtb()\y,dtb()\w,dtb()\h,dtb()\ink)
      Case #dtb_line
        LineXY(dtb()\x,dtb()\y,dtb()\w,dtb()\h,dtb()\ink)
      Case #dtb_text
        If dtb()\font>-1:DrawingFont(FontID(dtb()\font)):EndIf
        DrawText(dtb()\x,dtb()\y,dtb()\txt,dtb()\ink)
    EndSelect
  Next
  StopDrawing()
  ProcedureReturn i
EndProcedure
Procedure   dtbGetBumpMap(w=512,h=512, strenght.f=0.2,flipX.b=#True,flipY.b=#True,normalMap.b=#True)
  Protected   ni, i= CreateImage(#PB_Any,w,h)
  StartDrawing(ImageOutput(i))
  DrawingMode(#PB_2DDrawing_Transparent)
  ForEach dtb()
    Select dtb()\type
      Case #dtb_box
        Box(dtb()\x,dtb()\y,dtb()\w,dtb()\h,dtb()\level)
      Case #dtb_roundBox
        RoundBox(dtb()\x,dtb()\y,dtb()\w,dtb()\h,dtb()\r1,dtb()\r2,dtb()\level)
      Case #dtb_ellipse
        Ellipse(dtb()\x,dtb()\y,dtb()\w,dtb()\h,dtb()\level)
      Case #dtb_line
        LineXY(dtb()\x,dtb()\y,dtb()\w,dtb()\h,dtb()\level)
      Case #dtb_text
        If dtb()\font>-1:DrawingFont(FontID(dtb()\font)):EndIf
        DrawText(dtb()\x,dtb()\y,dtb()\txt,dtb()\level)
    EndSelect
  Next
  StopDrawing()
  If normalMap
    ni=ImgToNormalMap(i,strenght,flipX,flipY)
    FreeImage(i):i=ni
  EndIf
  ProcedureReturn i
EndProcedure
Procedure   dtbClear()
  ClearList(dtb())
EndProcedure
Procedure   dtbAdd(x.c,y.c,w.c,h.c, ink.l=$ffffff, level.b=0, type.a=#dtb_box, r1.a=10,r2.a=10, txt.s="",font=-1) ;grey level for bump 0-15
  ;add new shape to the list, level: 0=down,15=top
  Protected.s a: a= Hex(level):For n=1 To 3:a+a:Next n:a="$"+Left(a,6)
  AddElement(dtb())
  dtb()\type=   type
  dtb()\level=  Val(a)
  dtb()\ink=    ink
  dtb()\x=      x
  dtb()\y=      y
  dtb()\w=      w
  dtb()\h=      h
  dtb()\r1=     r1
  dtb()\r2=     r2
  dtb()\txt=    txt
  dtb()\font=   font
EndProcedure
;}

; draw textures
dtbAdd(0,0,511,511,$ffffff)
dtbAdd(10,10,492,492,$bb3300,2,#dtb_roundBox)
dtbAdd(70,70,371,371,$bb3300,5,#dtb_roundBox)
dtbAdd(40,40,15,15,$aaaaaa,12,#dtb_ellipse)
dtbAdd(472,40,15,15,$aaaaaa,11,#dtb_ellipse)
dtbAdd(472,472,15,15,$aaaaaa,13,#dtb_ellipse)
dtbAdd(40,472,15,15,$aaaaaa,15,#dtb_ellipse)
dtbAdd(38,30,4,20,$444444,9,#dtb_box)
dtbAdd(30,470,20,4,$444444,8,#dtb_box)
dtbAdd(462,38,20,4,$444444,10,#dtb_box)
dtbAdd(470,462,4,20,$444444,11,#dtb_box)
For p= 0 To 9
  dtbAdd(100,100+p*20,311,10,$bb3300,1,#dtb_box)
Next p
LoadFont(0,"Impact",75,#PB_Font_HighQuality)
dtbAdd(120,300,0,0,$00ffff,2,#dtb_text,0,0,"Bumpy",0)

; get textures as images
img1= dtbGetTexture()
img2= dtbGetBumpMap(512,512,0.8,1,1)
dtbClear()

; preview textures
showImage(img1)
showImage(img2)

; bla bla bla ;-)
InitEngine3D():InitSprite():InitKeyboard():InitMouse()
ExamineDesktops():dx=DesktopWidth(0)*0.6:dy=DesktopHeight(0)*0.6
OpenWindow(0, 0,0, DesktopUnscaledX(dx),DesktopUnscaledY(dy), "DTB draw texture bump",#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0), 0, 0, dx, dy, 0, 0, 0)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Main",#PB_3DArchive_FileSystem)
Parse3DScripts()
light = CreateLight(#PB_Any ,$ffffff, 20, 40, -10, #PB_Light_Point)
CreateCamera(0,0,0,100,100):MoveCamera(0,1,3,-2,#PB_Absolute):CameraLookAt(0,0,1,0)

;image --> textures
tx3d1= CreateTexture(#PB_Any,ImageWidth(img1),ImageHeight(img1))
StartDrawing(TextureOutput(tx3d1))
  DrawingMode(#PB_2DDrawing_AllChannels)
  DrawImage(ImageID(img1),0,0)
StopDrawing()
tx3d2= CreateTexture(#PB_Any,ImageWidth(img2),ImageHeight(img2))
StartDrawing(TextureOutput(tx3d2))
  DrawingMode(#PB_2DDrawing_AllChannels)
  DrawImage(ImageID(img2),-1,-1,ImageWidth(img2)+2,ImageHeight(img2)+2)
StopDrawing()

;bumpy party
mesh= CreateCube(#PB_Any,1)
mate=  CreateShaderMaterial(#PB_Any, #PB_Material_BumpShader)
MaterialShaderTexture(mate,TextureID(tx3d1),TextureID(tx3d2),0,0)
MaterialShaderParameter(mate,#PB_Shader_Fragment,"bumpy",#PB_Shader_Float,1,0,0,0)
SetMaterialColor(mate, #PB_Material_DiffuseColor,RGB(250,250,250))
SetMaterialColor(mate, #PB_Material_AmbientColor,RGB(60,60,60))
MaterialShininess(mate,125,$ffffff)
MaterialFilteringMode(mate,#PB_Material_Trilinear)

enti= CreateEntity(#PB_Any,MeshID(mesh),MaterialID(mate),0,1.2,0)

ReleaseMouse(#True)
Repeat
  While WindowEvent():Wend
  ExamineMouse(): ExamineKeyboard()
  RotateEntity(enti,0,0.1,0,#PB_Relative)
  RenderWorld()
  FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)
End
If translation=Error: reply="Sorry, Im Spanish": Endif
Post Reply