November 30, 2020, 01:38:44 AM

Author Topic: [bb] Ambient Volume Lib by RifRaf [ 1+ years ago ]  (Read 620 times)

Offline BlitzBot

  • Jr. Member
  • **
  • Posts: 1
[bb] Ambient Volume Lib by RifRaf [ 1+ years ago ]
« on: June 29, 2017, 12:28:42 AM »
Title : Ambient Volume Lib
Author : RifRaf
Posted : 1+ years ago

Description : With this lib you can Create and save Ambient Volume Maps which are basically a large 3D grid containing ambient color settings per cell.  The lib allows you to make these over your large maps. Once done you can ambient map your level and ambient shade moving and still entities dynamically with very little cpu or gpu cost.

No additional line picks or collision checks will be needed to utilize the volume data once its been created.

You can also drop ambient volume static lights, once i improve the colored light placement im going to add moving lights as well via a second grid holding only lights.

If you make any improvements please post them here.  Thanks


Code :
Code: BlitzBasic
  1. Include "amb_volume.bb"
  2. ;//----------------------------------------------------------       ----TEST LIB---
  3. ;//----------------------------------------------------------       ----TEST LIB---
  4. ;//----------------------------------------------------------       ----TEST LIB---
  5. ;// PRESS 1 TO DROP A RANDOM COLORED LIGHT
  6. ;// click SPACE BAR button to toggle ambient volume map on the level mesh
  7.  
  8. Print "AMBIENT VOLUME LIB v1.0"
  9. Print ""
  10. Print ""
  11. Print ""
  12. Print "[ SPACEBAR ] : Toggle ambient scene mapping."
  13. Print "[ 1 ]        : Drop a ambient volume light."
  14. Print "[ ESCAPE ]        : Quit program. "
  15. Print "[ MOUSE BUTTONS ] : move around."
  16. Print ""
  17. Print "press any key to start "
  18. WaitKey()
  19.  
  20. amb_smoothContrastdown_Startat=3
  21. amb_smoothContrastdown_Endat=5
  22.  
  23. amb_smoothContrastDown#=.95
  24.  
  25. amb_SmoothContrastup_Startat=2
  26. amb_SmoothContrastup_Endat=3
  27.  
  28. amb_SmoothContrastup#=1.01
  29.  
  30.  
  31. Graphics3D 800,600,0,2
  32.  
  33.  displayamb=1
  34.  camera=CreateCamera()
  35.  CameraClsColor camera,0,55,125
  36.  CameraRange camera,1,13000
  37.  avatar=CreateSphere()
  38.  EntityFX avatar,1
  39.  
  40.  PositionEntity avatar,0,-2,3
  41.  EntityParent avatar,camera
  42.  mesh=LoadMesh("yourmodelhere.b3d")
  43.  ;toonmeshuv mesh
  44.  EntityPickMode mesh,2
  45.  Amb_width# = MeshWidth(mesh)
  46.  Amb_Height#= MeshHeight(mesh)
  47.  Amb_Depth# = MeshDepth(mesh)
  48.  AmbientLight 190,190,190
  49.  
  50.  PositionEntity camera,-100,-250,0
  51.  
  52.  ;//if you want to play with different settings in this test, just change
  53.  ;//the filename here to something that will never exist.. such as "ambientvolume44.dat"
  54.  ;//if you dont then it will only create the volume once, then load it the next time.
  55.  If FileType("ambientvolume.dat")<>1 Then
  56.      
  57.          amb_smoothContrastdown_Startat=2
  58.          amb_smoothContrastdown_Endat=3
  59.          amb_smoothContrastDown#=.95
  60.          amb_SmoothContrastup_Startat=3
  61.          amb_SmoothContrastup_Endat=5
  62.          amb_SmoothContrastup#=1.5
  63.      smooth_times=5
  64.      lowest_Ambient=15
  65.      x_cells=100
  66.      y_cells=60
  67.      z_cells=100
  68.  
  69.     ;another setting to try
  70.     ; amb_smoothContrastdown_Startat=3
  71.         ; amb_smoothContrastdown_Endat=5
  72.         ; amb_smoothContrastDown#=.95
  73.         ; amb_SmoothContrastup_Startat=1
  74.         ; amb_SmoothContrastup_Endat=5
  75.         ; amb_SmoothContrastup#=1.01
  76.     ; smooth_times=5
  77.     ; lowest_Ambient=30
  78.     ; x_cells=120
  79.     ; y_cells=90
  80.     ; z_cells=120
  81.  
  82.      ;prep and create flipped mesh copy
  83.          Amb_prepMeshBeforeCreation(mesh)
  84.    
  85.      ;//the following two calls accomplish the same thing, but can be useful to use area if youre level mesh is not centered in global space
  86.          ;//you can specify how many smooths to do in the creaion.. or you can do it later with a direct call to smoothambientvolume()
  87.  
  88.          ;createambientvolume_area(-1660,-1250,-1700,1660,1250,1700,smooth_times,lowest_ambient,x_cells,y_cells,z_cells)
  89.      ;CreateblankAmbientVolume  (mesh,Smooth_Times,Lowest_Ambient,x_cells,y_cells,z_cells)
  90.      CreateAmbientVolume_SizeOfMesh     (mesh,Smooth_Times,Lowest_Ambient,x_cells,y_cells,z_cells)
  91.      ;remove flipped mesh copy    
  92.          Amb_freesparemeshes()
  93.  
  94.      ;save and apply the volume
  95.          saveambientvolume ("ambientvolume.dat")
  96.          ApplyAmbientVolumeToMesh(mesh)
  97.  
  98.  Else
  99.  
  100.      ;if the file exists load and apply volume
  101.          loadambientvolume("ambientvolume.dat")
  102.          ApplyAmbientVolumeToMesh(mesh)
  103.  EndIf
  104.  
  105.  
  106.  
  107. While Not KeyDown(1)
  108.         ;hit SPACEBAR  to see with and without volume applied to level mesh
  109.         If KeyHit(57) Then
  110.          displayamb=displayamb-1
  111.          If displayamb<=0 Then displayamb=3
  112.          Select displayamb
  113.          Case 2
  114.              FreeEntity mesh
  115.                          mesh=LoadMesh("cabin.b3d")
  116.                          EntityPickMode mesh,2
  117.              
  118.                         removeambientvolumefrommesh(mesh,0)
  119.                         EntityFX mesh,2
  120.          Case 3
  121.                         removeambientvolumefrommesh(mesh,1)
  122.                     applyambientvolumetomesh(mesh)
  123.                         EntityFX mesh,2
  124.                  Case 1
  125.                          applyambientvolumetomesh(mesh)
  126.                         EntityFX mesh,2
  127.                 End Select        
  128.         EndIf
  129.  
  130.     ;press 1 on the keyboard to drop a random colored volume light
  131.         If KeyHit(2) Then
  132.         ;go ahead and prep main mesh (make flipped copy) to help the light accuracy (needs all the help it can get)
  133.         Amb_prepMeshBeforeCreation(mesh)
  134.                 r=Rand(120,255)
  135.                 g=Rand(120,255)
  136.                 b=Rand(120,255)
  137.             Amb_InsertLight(EntityX(camera),EntityY(Camera),EntityZ(Camera),350,r,g,b)
  138.             Amb_freesparemeshes()
  139.         applyambientvolumetomesh(mesh)
  140.         EndIf
  141.  
  142.     ;allow camera movement with the mouse buttons
  143.         MoveEntity Camera,(KeyDown(205)-KeyDown(203))*5,0,(MouseDown(1)-MouseDown(2))*5
  144.         TurnEntity Camera,MouseYSpeed()*0.1,-MouseXSpeed()*0.1,0
  145.         RotateEntity Camera,EntityPitch(Camera,True),EntityYaw(Camera,True),0
  146.  
  147.     ;use amb_entitycolor() to show how an enity can be shaded by the ambient volume
  148.         amb_entitycolor(Avatar)
  149.     ;position mouse in middle so mouselook can work
  150.         MoveMouse GraphicsWidth()*.5,GraphicsHeight()*.5
  151.         UpdateWorld()
  152.         RenderWorld()
  153.         Flip
  154. Wend
  155. amb_vol_clearall()
  156. EndGraphics()
  157. End
  158. ;//----------------------------------------------------------       ----END TEST---
  159. ;//----------------------------------------------------------       ----END TEST---
  160. ;//----------------------------------------------------------       ----END TEST---


Comments :


RifRaf(Posted 1+ years ago)

 
Code: [Select]
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;Ambient volume dynamic shading lib. by Jeff Frazier ( rifraf )
;Aug, 2011
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
; if you improve on this lib , please update me ( gamemaker04@... ) and/or repost in the original code archives entry
; thank you.
;/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


Dim ambientVolume(0,0,0)
Dim ambientVolumeSmooth(0,0,0)
Global amb_brightest=255


;the following four globals are used in SmoothAmbientVolume()
;to allow contrasting freedoms per volume created, please review the
;smoothing loop "for rep=" in that function to see how these play a part
Global amb_smoothContrastdown_Endat=5
Global amb_smoothContrastdown_Startat=2
Global amb_smoothContrastDown#=.95
Global amb_SmoothContrastup_Startat=3
Global amb_SmoothContrastup_Endat=5
Global amb_SmoothContrastup#=1.2

;THE DIVISION FOR CURVING THE COLOR OF SHADED ENTITIES
;LARGER NUMBERS = SMOOTHING COLOR TRANSITIONS..
Const AMB_ColorShiftFrames=30

Global Amb_default_Ambient%=40

;Used to store temporaty flipped mesh copies before a createvolume() call
Type Amb_flippedmesh
  Field ent
End Type

;used as return values from Amb_splitcolors()
Global amb_split_red%
Global amb_split_green%
Global amb_split_blue%

;Stores an entities scale factors when you call Amb_getmeshscale()
Global amb_XScale#
Global amb_YScale#
Global amb_ZScale#

;used as return values from createambientvolume() and loadambientvolume(()
;these pertain the the volume dementions and space it takes up
Global AMB_Vol_MaxGridX=1
Global AMB_Vol_MaxGridY=1
Global AMB_Vol_MaxGridZ=1
Global AMB_VOL_SPACEX#=1
Global AMB_VOL_SPACEY#=1
Global AMB_VOL_SPACEZ#=1

;used as return values from createambientvolume() and loadambientvolume(()
;these values are needed to use Amb_InsertLight()
Global Amb_width#
Global Amb_Height#
Global Amb_Depth#

;Return values from the coordinate convertion functions
Global Grid_getx#
Global Grid_gety#
Global Grid_getz#
Global ent_Gridx%
Global ent_Gridy%
Global ent_Gridz%


;used store entities that are colored via Amb_Entitycolor() but the type list is handled by the lib
Type Amb_RGB
Field r
Field g
Field b
End Type



Function Delete_AmbEntityColor(ent)
    ;NOTE if you free an entity that could have a amb_rbg type assosiated with it then
    ;you must call this function before you free the entity else the next call here
    ;for that entity will MAV
This.amb_RGB = Object.amb_RGB( EntityName( Ent ) )
If this<>Null Then Delete this
End Function


Global Recent_EntityRed%,Recent_EntityGreen%,Recent_EntityBlue%
Function amb_entitycolor_update(ent,r,g,b)

This.amb_RGB = Object.amb_RGB( EntityName( Ent ) )
If this<>Null Then
    recent_entityred%=   amb_curve(r,this,AMB_ColorShiftFrames)
   recent_entitygreen%= amb_curve(g,thisg,AMB_ColorShiftFrames)
    recent_entityblue%=  amb_curve(b,this,AMB_ColorShiftFrames)
   Amb_EntityAnimColor ent,Recent_EntityRed%,Recent_EntityGreen%,Recent_EntityBlue%
    this=Recent_EntityRed%
   thisg=Recent_EntityGreen%
    this=Recent_EntityBlue%
Else
This.amb_RGB = New amb_RGB
ThisR = r
ThisG = g
ThisB = b
NameEntity Ent, Handle( This )
Amb_EntityAnimColor ent,r,g,b
EndIf
End Function

;use this on entities that will be moving around so they can change shades smoothly
Function amb_entitycolor(ent)
GetEntityGrid(ent)
amb_splitcolors(ambientvolume(ent_gridx,ent_gridy,ent_gridz))
amb_entitycolor_update ent,amb_split_Red,amb_split_green,amb_split_blue
End Function

;use this one if you dont want gradually shade shifting.. for example on scenery items dropped into place
;durring map loading.
Function amb_entitycolor_instant(ent,plusr=-1,plusg=-1,plusb=-1)
 EntityFX ent,0
 EntityBlend ent,1
PositionEntity projectilepivot,EntityX(ent,1),EntityY(Ent,1)+10,EntityZ(Ent,1)
GetEntityGrid(projectilepivot)
amb_splitcolors(ambientvolume(ent_gridx,ent_gridy,ent_gridz))
    If plusr>-1 Or plusg>-1 Or plusb>-1 Then
   Newr#=((amb_split_red+plusr)/2)
   Newg#=((amb_split_green+plusg)/2)
    Newb#=((amb_split_blue+plusb)/2)
    Else
        newr=amb_split_red
        newg=amb_split_green
        newb=amb_split_blue
    EndIf
Amb_EntityAnimColor ent,newr,newg,newb
End Function

;returns where an entity is in the volume array
;storing the result in  ent_gridx,ent_gridy,ent_gridz
Function GetEntityGrid(entity)
    gx#=EntityX(entity,1)
    gy#=EntityY(entity,1)+4
    gz#=EntityZ(entity,1)
ent_gridX=Int((gx/AMB_VOL_SPACEX))+(AMB_Vol_MaxGridX/2)
ent_gridY=Int((gy/AMB_VOL_SPACEY))+(AMB_Vol_MaxGridY/2)
ent_gridZ=Int((gz/AMB_VOL_SPACEZ))+(AMB_Vol_MaxGridZ/2)
    If ent_gridx<0 Or ent_gridx>AMB_Vol_MaxGridx Then ent_gridx=0
    If ent_gridy<0 Or ent_gridy>AMB_Vol_MaxGridy Then ent_gridy=0
    If ent_gridz<0 Or ent_gridz>AMB_Vol_MaxGridz Then ent_gridz=0
End Function

;returns the 3d space real coordinates of a volume array space
;stores the result in grid_getx,grid_getx,grid_getz
Function GridToCoords(gx,gy,gz)
grid_getx#=((gx*AMB_VOL_SPACEX)-(AMB_Vol_MaxGridX/2)*AMB_VOL_SPACEX)
grid_gety#=((gy*AMB_VOL_SPACEY)-(AMB_Vol_MaxGridY/2)*AMB_VOL_SPACEY)
grid_getz#=((gz*AMB_VOL_SPACEZ)-(AMB_Vol_MaxGridZ/2)*AMB_VOL_SPACEZ)
End Function

;returns the volume array space of a real global x,y,z coordinate
;storing the result in  ent_gridx,ent_gridy,ent_gridz
Function CoordsToGrid(gx#,gy#,gz#)
ent_gridX=Int((gx/AMB_VOL_SPACEX))+(AMB_Vol_MaxGridX/2)
ent_gridY=Int((gy/AMB_VOL_SPACEY))+(AMB_Vol_MaxGridY/2)
ent_gridZ=Int((gz/AMB_VOL_SPACEZ))+(AMB_Vol_MaxGridZ/2)
   ;error check
    If ent_gridx<0 Or ent_gridx>AMB_Vol_MaxGridx Then ent_gridx=0
    If ent_gridy<0 Or ent_gridy>AMB_Vol_MaxGridy Then ent_gridy=0
    If ent_gridz<0 Or ent_gridz>AMB_Vol_MaxGridz Then ent_gridz=0
End Function

Function CoordsToGridBetter(gx#,gy#,gz#)
    ;this snaps the coors to grid, but also checks the vertex coordinat distance from all
    ;neightbor grids to make sure we arent landing near the line of a neighbor cell and are closer to its
    ;center than the default snap location. . used in creating lights.. but not for real time dynamic entity shading
ent_gridX=Int((gx/AMB_VOL_SPACEX))+(AMB_Vol_MaxGridX/2)
ent_gridY=Int((gy/AMB_VOL_SPACEY))+(AMB_Vol_MaxGridY/2)
ent_gridZ=Int((gz/AMB_VOL_SPACEZ))+(AMB_Vol_MaxGridZ/2)
    Dister#=999999
    For GridX=-2 To 2
    For Gridz=-2 To 2
    For gridY=-2 To 2
              gridtocoords(ent_gridx+gridx,ent_gridy+gridy,ent_gridz+gridz)
              checkd#= amb_distance(grid_getx,grid_Gety,grid_getz,gx,gy,gz)
              If checkd#<dister# Then
                 dister#=checkd#
                 winnerx=ent_gridx+gridx                
                 winnery=ent_gridy+gridy                
                 winnerz=ent_gridz+gridz                
             EndIf
            Next
         Next
    Next
   ;error check
    ent_gridx=winnerx
    ent_gridy=winnery
    ent_gridz=winnerz
    If ent_gridx<0 Or ent_gridx>AMB_Vol_MaxGridx Then ent_gridx=0
    If ent_gridy<0 Or ent_gridy>AMB_Vol_MaxGridy Then ent_gridy=0
    If ent_gridz<0 Or ent_gridz>AMB_Vol_MaxGridz Then ent_gridz=0
End Function


;save the volume for later use.. much faster than recalculating each time you need it
Function SaveAmbientVolume(fn$)
F=WriteFile(fn$)
WriteFloat f,Amb_width#
WriteFloat f,Amb_Height#
WriteFloat f,Amb_Depth#

WriteInt F,AMB_Vol_MaxGridX
WriteInt F,AMB_Vol_MaxGridY
WriteInt F,AMB_Vol_MaxGridZ
WriteInt F,AMB_VOL_SPACEX
WriteInt F,AMB_VOL_SPACEY
WriteInt F,AMB_VOL_SPACEZ
    For i=0 To AMB_Vol_MaxGridX
    For ii=0 To AMB_Vol_MaxGridY
For iii=0 To AMB_Vol_MaxGridZ
  WriteInt f,ambientvolume(i,ii,iii)
Next
Next
Next
CloseFile f
Return
End Function



;loading of volume
Function LoadAmbientVolume(fn$,scalex#=1.0,scaley#=1.0,scalez#=1.0,loadpower#=1.0)
 If FileType(fn$)=0 Then
     Use_AmbVolume=False
     Return
  EndIf  
 F=ReadFile(fn$)
 Amb_width# = ReadFloat(f)*scalex#
 Amb_Height#= ReadFloat(f)*scaley#
 Amb_Depth# = ReadFloat(f)*scalez#
 AMB_Vol_MaxGridX=ReadInt(F)
 AMB_Vol_MaxGridY=ReadInt(F)
 AMB_Vol_MaxGridZ=ReadInt(F)
 AMB_VOL_SPACEX=ReadInt(F)*scalex
 AMB_VOL_SPACEY=ReadInt(F)*scaley
 AMB_VOL_SPACEZ=ReadInt(F)*scalez
 Dim AMBIENTVOLUME(AMB_Vol_MaxGridX,AMB_Vol_MaxGridY,AMB_Vol_MaxGridZ)
 For ax=0 To AMB_Vol_MaxGridX
  For ay=0 To  AMB_Vol_MaxGridY
  For az=0 To  AMB_Vol_MaxGridZ
    cv=ReadInt(f)
    amb_splitcolors(cv)
    amb_split_red=amb_split_Red*loadpower
    amb_split_green=amb_split_green*loadpower
    amb_split_blue=amb_split_blue*loadpower
    cv=amb_Tricolor(amb_split_Red,amb_split_green,amb_split_blue)
    ambientVolume(ax,ay,az)=cv
  Next
  Next
 Next
CloseFile f
Return
End Function



;The slowest part of this library, smooths a newly created volume to look much much better
Function SmoothAmbientVolume(amount=1,offset#=1)
Dim ambientVolumeSmooth(AMB_Vol_MaxGridX,AMB_Vol_MaxGridy,AMB_Vol_MaxGridz)
For rep=1 To amount
totalseen=0
newr=0
newg=0
newb=0
multi#=1.0
 For ax=1 To AMB_Vol_MaxGridX-1
  For ay=1 To  AMB_Vol_MaxGridY-1
 For az=1 To  AMB_Vol_MaxGridZ-1
amb_splitcolors(ambientvolume(ax,ay,az))
           r0=amb_split_Red
           g0=amb_split_green
           b0=amb_split_blue
   ;newr=newr+r0
                   ; newg=newg+g0
                   ; newb=newb+b0
;totalseen=totalseen+1
       ;     If r0=255 And b0=255 And g0=255 Then
                    If REP=>amb_smoothContrastdown_Startat And rep<= amb_smoothContrastdown_endat Then multi#= amb_smoothContrastDown# ;.95
;Else
If REP=>amb_SmoothContrastup_Startat And rep<= amb_SmoothContrastup_endat Then multi=amb_SmoothContrastup# ;1.1
        ;    EndIf

  If Grids_Inview(ax,ay,az,ax+1,ay,az) Then
   amb_splitcolors(ambientvolume(ax+1,ay,az))
           r1=amb_split_Red
           g1=amb_split_green
           b1=amb_split_blue
                    newr=newr+(r1*multi#)
                    newg=newg+(g1*multi#)
                    newb=newb+(b1*multi#)
totalseen=totalseen+1
EndIf
If Grids_Inview(ax,ay,az,ax-1,ay,az) Then
amb_splitcolors(ambientvolume(ax-1,ay,az))
           r2=amb_split_Red
           g2=amb_split_green
           b2=amb_split_blue
                    newr=newr+(r2*multi#)
                    newg=newg+(g2*multi#)
                    newb=newb+(b2*multi#)
totalseen=totalseen+1
EndIf
If Grids_Inview(ax,ay,az,ax,ay,az+1) Then
   amb_splitcolors(ambientvolume(ax,ay,az+1))
           r3=amb_split_Red
           g3=amb_split_green
           b3=amb_split_blue
                    newr=newr+(r3*multi#)
                    newg=newg+(g3*multi#)
                    newb=newb+(b3*multi#)
totalseen=totalseen+1
EndIf
If Grids_Inview(ax,ay,az,ax,ay,az-1) Then
   amb_splitcolors(ambientvolume(ax,ay,az-1))
           r4=amb_split_Red
           g4=amb_split_green
           b4=amb_split_blue
                    newr=newr+(r4*multi#)
                    newg=newg+(g4*multi#)
                    newb=newb+(b4*multi#)
totalseen=totalseen+1
EndIf
If Grids_Inview(ax,ay,az,ax+1,ay,az-1) Then
   amb_splitcolors(ambientvolume(ax+1,ay,az-1))
           r5=amb_split_Red
           g5=amb_split_green
           b5=amb_split_blue
                    newr=newr+(r5*multi#)
                    newg=newg+(g5*multi#)
                    newb=newb+(b5*multi#)
totalseen=totalseen+1
EndIf
If Grids_Inview(ax,ay,az,ax+1,ay,az+1) Then
   amb_splitcolors(ambientvolume(ax+1,ay,az+1))
       r6=amb_split_Red
           g6=amb_split_green
            b6=amb_split_blue
                    newr=newr+(r6*multi#)
                    newg=newg+(g6*multi#)
                    newb=newb+(b6*multi#)
totalseen=totalseen+1
EndIf
If Grids_Inview(ax,ay,az,ax-1,ay,az-1) Then
   amb_splitcolors(ambientvolume(ax-1,ay,az-1))
           r7=amb_split_Red
           g7=amb_split_green
           b7=amb_split_blue
                    newr=newr+(r7*multi#)
                    newg=newg+(g7*multi#)
                    newb=newb+(b7*multi#)
totalseen=totalseen+1
EndIf
If Grids_Inview(ax,ay,az,ax-1,ay,az+1) Then
   amb_splitcolors(ambientvolume(ax-1,ay,az+1))
           r8=amb_split_Red
           g8=amb_split_green
           b8=amb_split_blue
                    newr=newr+(r8*multi#)
                    newg=newg+(g8*multi#)
                    newb=newb+(b8*multi#)
totalseen=totalseen+1
EndIf
If totalseen>0 Then
            newr=(newr/totalseen)*offset
            newg=(newg/totalseen)*offset
            newb=(newb/totalseen)*offset
EndIf
totalseen=0
            If newr>255 Then newr=255
            If newg>255 Then newg=255
            If newb>255 Then newb=255

            If newr<amb_default_Ambient Then newr=amb_default_ambient
            If newg<amb_default_Ambient Then newg=amb_default_ambient
            If newb<amb_default_Ambient Then newb=amb_default_ambient

            ambientvolumesmooth(ax,ay,az)=amb_tricolor(newr,newg,newb)
   Next
    Next
   
  Next
 For ax=1 To AMB_Vol_MaxGridX-1
  For ay=1 To  AMB_Vol_MaxGridY-1
 For az=1 To  AMB_Vol_MaxGridZ-1
            ambientvolume(ax,ay,az)=ambientvolumesmooth(ax,ay,az)
      Next
    Next
 Next

Next;rep
  Dim ambientVolumeSmooth(0,0,0)
End Function

Function CreateAmbientVolume_Area(x1#,y1#,z1#,x2#,y2#,z2#,Smoothing=3,AmbC=30,maxx=90,maxy=90,maxz=90,replacemesh=0)
tempmesh=CreateCube()
ScaleMesh tempmesh,1,1,1
sizex#=x2-x1
sizey#=y2-y1
sizez#=z2-z1
FitMesh tempmesh,x1,y1,z1,sizex,sizey,sizez,False
FlipMesh tempmesh
EntityColor tempmesh,255,0,0
CreateAmbientVolume_SizeOfMesh(tempmesh,Smoothing,AmbC,maxx,maxy,maxz)
FreeEntity tempmesh
End Function

Function Amb_prepMeshBeforeCreation(mesh,flipit=True)
    ;//NOTICE YOU WILL AT LEAST WANT TO RUN THIS ON YOUR MAIN LEVEL MESH
    ;//BECORE THE CREATION PROCESS.. it is not required though for a load from file ambvolume

;copy the mesh and flip it
;our smoothing is done by doing vision checks from one cell to the other
;these checks will be inacurate if the map mesh is one sided
;any objects that you want to inpact the volume creation need to have a pickmode of 2
    ;however large complex objects should be ran through this prepmesh function

    ;basically we record a flipped version of the entity so that picks dont go though walls if they are
    ;going from the backface to a light source , and proper light source obsuring accurs
     Ambf.Amb_flippedmesh=New Amb_flippedmesh
ambfent=CopyMesh (mesh)
If flipit=True Then FlipMesh ambfent
EntityPickMode ambfent,2
PositionEntity ambfent,EntityX(mesh,1),EntityY(mesh,1),EntityZ(mesh,1)
RotateEntity ambfent,EntityPitch(mesh,1),EntityYaw(mesh,1),EntityRoll(mesh,1)
EntityPickMode mesh,2
End Function


Function Amb_FreeSpareMeshes()
     For Ambf.Amb_flippedmesh=Each Amb_flippedmesh
FreeEntity ambfent
        Delete ambf
     Next
End Function

Function CreateBlankambientvolume(Mesh,Smoothing=3,AmbC=30,maxx=90,maxy=90,maxz=90)
Amb_width# = MeshWidth(mesh)*4
Amb_Height#= MeshHeight(mesh)*4
Amb_Depth# = MeshDepth(mesh)*4
;The default setting gives you 90 cells on all axi = 90x90x90 cell resoluton
;all created around your mesh. This consumes about 6 megs or ram, and a 6 meg save file
;you can reduce this my reducing the cell counts on one or all axis.  Be careful using higher values
;as theres no limit to the ram you can use.. ive used up to 400 megs on very high res volumes
;those sizes also take hours to calculate and smooth. On my system this default volume res takes about 1 minute

;copy the mesh and flip it
;our smoothing is done by doing vision checks from one cell to the other
;these checks will be inacurate if the map mesh is one sided
;also any objects that you want to inpact the volume creation need to have a pickmode of 2 before you call this
;function

Amb_default_Ambient=ambc
If abv_amb<0 Then amv_ambient=0
If abv_amb>255 Then amv_ambient=255

AMB_Vol_MaxGridX=MAXX
AMB_Vol_MaxGridY=MAXY
AMB_Vol_MaxGridZ=MAXZ

AMB_VOL_SPACEX=amb_width  / (maxx/2)
AMB_VOL_SPACEY=amb_height/ (maxy/2)
AMB_VOL_SPACEZ=amb_depth  / (maxz/2)

Dim AMBIENTVOLUME(AMB_Vol_MaxGridX,AMB_Vol_MaxGridY,AMB_Vol_MaxGridZ)
;set all cells to default ambient color
For ix=0 To maxx:For iy=0 To maxy:For iz=0 To maxz
ambientvolume(ix,iy,iz)=amb_tricolor(Amb_default_Ambient,Amb_default_Ambient,Amb_default_Ambient)
Next:Next:Next

End Function

Function amb_FillVolumeColor(Cvalr,cvalg,cvalb)
 For i=0 To amb_col_maxgridx
For ii=0 To amb_col_maxgridx
For ii=0 To amb_col_maxgridx
ambientvolume(i,i,ii)=amb_tricolor(cvalr,cvalg,cvalb)
Next
Next
Next
End Function

Function CreateAmbientVolume_SizeOfMesh(Mesh,Smoothing=3,AmbC=30,maxx=90,maxy=90,maxz=90)
Amb_width# = MeshWidth(mesh)
Amb_Height#= MeshHeight(mesh)
Amb_Depth# = MeshDepth(mesh)
;The default setting gives you 90 cells on all axi = 90x90x90 cell resoluton
;all created around your mesh. This consumes about 6 megs or ram, and a 6 meg save file
;you can reduce this my reducing the cell counts on one or all axis.  Be careful using higher values
;as theres no limit to the ram you can use.. ive used up to 400 megs on very high res volumes
;those sizes also take hours to calculate and smooth. On my system this default volume res takes about 1 minute

;copy the mesh and flip it
;our smoothing is done by doing vision checks from one cell to the other
;these checks will be inacurate if the map mesh is one sided
;also any objects that you want to inpact the volume creation need to have a pickmode of 2 before you call this
;function

Amb_default_Ambient=ambc
If abv_amb<0 Then amv_ambient=0
If abv_amb>amb_brightest Then amv_ambient=amb_brightest

AMB_Vol_MaxGridX=MAXX
AMB_Vol_MaxGridY=MAXY
AMB_Vol_MaxGridZ=MAXZ

AMB_VOL_SPACEX=amb_width  / (maxx/2)
AMB_VOL_SPACEY=amb_height/ (maxy/2)
AMB_VOL_SPACEZ=amb_depth  / (maxz/2)

Dim AMBIENTVOLUME(AMB_Vol_MaxGridX,AMB_Vol_MaxGridY,AMB_Vol_MaxGridZ)
;set all cells to default ambient color
For ix=0 To maxx:For iy=0 To maxy:For iz=0 To maxz
ambientvolume(ix,iy,iz)=amb_tricolor(Amb_default_Ambient,Amb_default_Ambient,Amb_default_Ambient)
Next:Next:Next
    ;pick down from just the top most Height of the volume.. where the pick lands.. we assign that column all the way
    ;up from the pick to the top of the volume to full bright, then we smooth out the entire volume to finish it up
For ix=0 To maxx:For iz=0 To maxz
iy=maxy
        gridtocoords(ix,iy,iz)
        xloop=grid_getx#
        yloop=grid_gety#
        zloop=grid_getz#
pk= LinePick(xloop,yloop+400,zloop,0 ,-7500 ,0 ,.1)
        pkx#=PickedX()
        pky#=PickedY()+Float(amb_vol_spacey)*.2
        pkz#=PickedZ()
        coordstogrid(pkx,pky,pkz)
        If pk=0 Then ent_gridy=0
        For colmn=ent_gridy To maxy Step 1
        ambientvolume(ent_gridx,colmn,ent_gridz)=amb_tricolor(amb_brightest,amb_brightest,amb_brightest)
        Next
        Next
Next

smoothambientvolume(smoothing)
End Function


Function MatchVert_toEnt(mesh)
     ;if you entity has a rotation other than 0,0,0 or scale other than 1,1,1 you
     ;must pass it though this if you want to use ApplyAmbientVolumetoMesh() so the verts will fall into
     ;the proper volmues and be colored correctly.
RotateMesh mesh,EntityPitch(mesh,1),EntityYaw(mesh,1),EntityRoll(mesh,1)
     amb_getmeshscale(mesh)
ScaleMesh mesh,amb_XScale#,amb_yScale#,amb_zccale#
     ;we dont need to positionmesh because we can use entityxyz offsets in the applyambientcolumetomesh() call
;PositionMesh
End Function



Function  ApplyAmbientVolumeToMesh(ent,power#=1.0)
 ;//NOTE this will not work on entiies that were copied via copyentity()
 ;to work on several copies you must use copymesh()
 EntityFX ent,2
 scount=CountSurfaces(ent)
 For sloop=1 To scount
     surf=GetSurface(ent,sloop)
     v=CountVertices(surf)-1
     For vloop=0 To v
        vnx#=VertexNX(surf,vloop)
        vny#=VertexNY(surf,vloop)
        vnz#=VertexNZ(surf,vloop)
      vx#=VertexX(surf,vloop)+EntityX(ent)+(Sgn(vnx)*(AMB_VOL_SPACEx/2))  ;
      vy#=VertexY(surf,vloop)+EntityY(ent)+(Sgn(vny)*(AMB_VOL_SPACEY/2))  ;move up or down slightly
      vz#=VertexZ(surf,vloop)+EntityZ(ent)+(Sgn(vnz)*(AMB_VOL_SPACEz/2))  ;
CoordsToGrid(vx#,vy#,vz#)
        gridtocoords(ent_gridx,ent_gridy,ent_gridz)
amb_splitcolors(ambientvolume(ent_gridx,ent_gridy,ent_gridz))
       va#=VertexAlpha(surf,vloop)
   finish_Red#=Float(amb_split_red)*power
            finish_green#=Float(amb_split_green)*power
            finish_blue#=Float(amb_split_blue)*power
            If finish_red>255 Then finish_Red=255
            If finish_green>255 Then finish_green=255
            If finish_blue>255 Then finish_blue=255
        VertexColor(surf,vloop,finish_Red,finish_green,finish_blue,va)

     Next
 Next

End Function        


;useless function I made for fun.. kept it in because you can really see the ambient volume mapping this way
Function  ToonmeshUV(ent)
 scount=CountSurfaces(ent)
 For sloop=1 To scount
     surf=GetSurface(ent,sloop)
     v=CountVertices(surf)-1
     For vloop=0 To v
VertexTexCoords (surf,vloop,.4,.4)
     Next
 Next
UpdateNormals(ent)
End Function

;useless in a game, but useful in editing ambient volumes
Function  RemoveAmbientVolumeFromMesh(ent,cleartextures=0)
 scount=CountSurfaces(ent)
 For sloop=1 To scount
     surf=GetSurface(ent,sloop)
     If cleartextures<>0 Then
    b=CreateBrush(255,255,255)
    PaintSurface surf,b
    FreeBrush b
     EndIf
     v=CountVertices(surf)-1
     For vloop=0 To v
        va#=VertexAlpha(surf,vloop)
        VertexColor(surf,vloop,255,255,255,va)
     Next
 Next
End Function        



Function amb_tricolor(r,g,b)
    Return $FF000000 Or b Or g Shl 8 Or r Shl 16
End Function

Function amb_splitcolors(val%)

amb_Split_Red=  (val% Shr 16) And $ff
amb_split_Green=(val% Shr 8) And $ff
amb_split_Blue=  val% And $ff
End Function


Function Amb_Distance#( x#, y#, z#, x2#, y2#, z2# )
value#=Sqr((x#-x2#)*(x#-x2#)+(y#-y2#)*(y#-y2#)+(z#-z2#)*(z#-z2#))
Return value#
End Function

Function Amb_Distance2d#( v#, v2#)
value#=Sqr((v#-v2#)*(v#-v2#))
Return value#
End Function

Function Amb_Curve#(newvalue#,oldvalue#,increments#)
    If increments>1 Then oldvalue#=oldvalue#-(oldvalue#-newvalue#)/increments
If increments<=1 Then oldvalue=newvalue
Return oldvalue#
End Function


;///NOTE THIS FUNCTION COULD BE BETTER.. IF ANY SMART BLITZERS WANT TO IMPROVE ON THIS, PLEASE DO.
Function Amb_InsertLight(x#,y#,z#,range#,r,g,b)
;you must have any light obscuring meshes set to pick mode 2

;convert range from coordinate range To volume cell range
average_Space#=((AMB_VOL_SPACEX+AMB_VOL_SPACEZ+AMB_VOL_SPACEY)/3)
range= range / average_space

temppiv3=CreateCube()
temppiv2=CreateCube()
temppiv=CreateCube()


EntityRadius temppiv,1
EntityPickMode temppiv,1
ScaleEntity temppiv,1,1,1
EntityRadius temppiv2,1
EntityPickMode temppiv2,1
ScaleEntity temppiv2,1,1,1

;//AQUIRE 3D ASPECT -----------
        ;because the same amount of Cells represent varied length width and height
; of the light volume depending on the size of level mesh used
        ; we must sort out the 3D apsect ratio to get a circular light range  
rangex=range
rangey=range
rangez=range
        If amb_width>amb_depth Then
           dif#=amb_width / amb_Depth  
           ratio_x#=1.0  
           ratio_z#=dif#  
           rangex=range
           rangez=range*dif
           If amd_height<amb_width Then
            dif#=amb_width / amb_height
           rangey=range*dif
           ratio_y#=dif#  
    Else
            dif#=amb_height / amb_width  
               ratio_y#=1.0  
               ratio_x#=dif#  
          rangey=range
          rangex=range*dif
          EndIf
        ;//
        Else
        ;//
           dif#= amb_depth / amb_width
           rangez=range
           ratio_z#=1.0  
           ratio_x#=dif#  
           rangex=range*dif
           If amd_height<amb_depth Then
            dif#=amb_depth / amb_height
           rangey=range*dif
                ratio_y#=dif#
    Else
            dif#=amb_height / amb_depth
          rangey=range
          rangez=range*dif
               ratio_y#=1.0
               ratio_z#=dif#  
          EndIf

        EndIf
        ;// ASPECT RATIOS CALCULATED CORRECTLY

        halfrangex=rangex/2
        halfrangey=rangey/2
        halfrangez=rangez/2
        CoordsToGrid(x,y,z)
;//LOOP THROUGH THE REGION
        For xl=ent_gridx-halfrangex To ent_gridx+halfrangex
       For yl=ent_gridy+halfrangey To ent_gridy-halfrangey Step -1
      For zl=ent_gridz-halfrangez To ent_gridz+halfrangez
                   If xl>0 And xl< AMB_Vol_MaxGridX And yl>0 Or yl< AMB_Vol_MaxGridY And zl>0 And zl< AMB_Vol_MaxGridZ Then
;ok inside the volume and inside the range of the light
;//CALCULATE THE POWER OF THE LIGHT OUTWARD FROM ITS CENTER -----------
                            ;//PERHAPS  B3D MATH WIZARD CAN IMPROVE ON THIS ROUTING
                            ddx#=amb_distance2d(xl,ent_gridx)*(1.0/ratio_x)
                            ddy#=amb_distance2d(yl,ent_gridy)*(1.0/ratio_y)
                            ddz#=amb_distance2d(zl,ent_gridz)*(1.0/ratio_z)
                            dd#=(ddx+ddy+ddz)

                            power#=(1.2/range) * (dd/2)
                            If power#<0 Then power=0
                            If power>1 Then power=1

                       
                            amb_splitcolors(ambientvolume(xl,yl,zl))

                            totalr#=Float(amb_split_red)*  (1.0-power)  
                            totalg#=Float(amb_split_green)*(1.0-power)
                            totalb#=Float(amb_split_blue)* (1.0-power)  
totalr=totalr + (Float(r)*power)
  totalg=totalg + (Float(g)*power)
totalb=totalb + (Float(b)*power)
                           
                             ;dont allow the light to bring a color below the ambient
                             If totalr<amb_split_red Then totalr=amb_split_Red
                             If totalg<amb_split_green Then totalg=amb_split_green
                             If totalb<amb_split_blue Then totalb=amb_split_blue

                             If totalr>255 Then totalr=255
                             If totalg>255 Then totalg=255
                             If totalb>255 Then totalb=255

                               

   ;dy#=DeltaYaw(temppiv,temppiv2)
   ;dp#=DeltaPitch(temppiv,temppiv2)

                             ;Since the volume is a rigid grid and mapping fluid flowing vertex patterns are not, then
                             ;you will likely get some vertex bleeding.. the below is my attempt to best set the
                             ;volumes for added colored lights so that mesh mapping can look alright.
                      ;gridtocoords(xl,yl,zl)
                             ;PositionEntity temppiv,x,y,z
                             ;PositionEntity temppiv3,x,y,z
                             ;PositionEntity temppiv2,grid_getx,grid_gety,grid_getz
                             ;PointEntity temppiv2,temppiv
                             ;PointEntity temppiv,temppiv2
                              ;dlp#=EntityDistance(temppiv,temppiv2)
                               ;  ;MoveEntity temppiv2,0,0,dlp/10
                                ; MoveEntity temppiv,0,0,dlp/5
              ;If EntityPick (temppiv,2000)=temppiv2  Then
  ;If EntityPick (temppiv2,2000)=temppiv  Then  
ambientvolume(xl,yl,zl)=amb_tricolor(totalr,totalg,totalb)
;EndIf
      ;EndIf
  EndIf
 Next
Next
Next

        FreeEntity temppiv
        FreeEntity temppiv2
        FreeEntity temppiv3

End Function

;returns whether or not two grid spaces have a line of sight to each other from any of the straight lines
Function Grids_Inview(x1,y1,z1,x2,y2,z2)
   If grid_linepick(x1,y1,z1,x2,y2,z2)<>0 Then
  If grid_linepick(x1+1,y1,z1,x2,y2,z2)<>0 Then
  If grid_linepick(x1,y1,z1+1,x2,y2,z2)<>0 Then
  If grid_linepick(x1-1,y1,z1,x2,y2,z2)<>0 Then
  If grid_linepick(x1,y1,z1-1,x2,y2,z2)<>0 Return 0
EndIf
EndIf
EndIf
EndIf
Return 1

End Function

;performs a line pick from two volume cells(grids)
Function Grid_linepick(x1#,y1#,z1#,x2#,y2#,z2#)

overshotx=AMB_VOL_SPACEX
overshoty=AMB_VOL_SPACEy
overshotz=AMB_VOL_SPACEz
         GridToCoords(x1,y1,z1)
         x1#=grid_getx#
         y1#=grid_gety#
         z1#=grid_getz#

         GridToCoords(x2,y2,z2)
         x2#=grid_getx#
         y2#=grid_gety#
         z2#=grid_getz#
         dx#=Sgn(x2-x1)
         dy#=Sgn(y2-y1)
         dz#=Sgn(z2-z1)
  Pck=LinePick(x1-(dx*overshotx),Y1-(dy*overshoty),Z1-(dz*overshotz),dx+(dx*overshotx),dy+(dx*overshoty),dz+(dx*overshotz),.1)



         Return pck+pck2
End Function

;color an entity and all its children, you can filter out children by entityname$ .. if you dont want all children colored
Function Amb_EntityAnimColor(ent,r,g,b)
 EntityColor ent,r,g,b
 numc=CountChildren(ent)
 For c=1 To numc
  this=GetChild(ent,c)
  If EntityClass$(this)="Mesh" Then
 ename$=Lower$(EntityName$(this))
; And Instr(ename$,"classbox")=0
;Instr(ename$,"hbar")=0
    If ename$<>"flag"   And Instr(ename$,"rel")=0   And Instr(ename$,"rank")=0  Then
  EntityColor this,r,g,b
  amb_entityanimcolor this,r,g,b
 EndIf
  EndIf
 Next
End Function


Function amb_getmeshscale(mesh)
vx# = GetMatElement#(Mesh, 0, 0)
vy# = GetMatElement#(Mesh, 0, 1)
vz# = GetMatElement#(Mesh, 0, 2)
amb_XScale# = Sqr(vx# * vx# + vy# * vy# + vz# * vz#)
vx# = GetMatElement#(Mesh, 1, 0)
vy# = GetMatElement#(Mesh, 1, 1)
vz# = GetMatElement#(Mesh, 1, 2)
amb_YScale# = Sqr(vx# * vx# + vy# * vy# + vz# * vz#)
vx# = GetMatElement#(Mesh, 2, 0)
vy# = GetMatElement#(Mesh, 2, 1)
vz# = GetMatElement#(Mesh, 2, 2)
amb_ZScale# = Sqr(vx# * vx# + vy# * vy# + vz# * vz#)
End Function


;free the lib
Function Amb_Vol_ClearAll()
 Amb_FreeSpareMeshes()
 Delete Each amb_rgb
 Dim ambientVolume(0,0,0)
 AMB_Vol_MaxGridX=1
 AMB_Vol_MaxGridY=1
 AMB_Vol_MaxGridZ=1
 AMB_VOL_SPACEX=1
 AMB_VOL_SPACEY=1
 AMB_VOL_SPACEZ=1
End Function



RifRaf(Posted 1+ years ago)

 ok I updated this lib.Above in the first post is the testing code, just add your own model to try it.  A level map works bestThe second post is the library itself "amb_volume.bb"


Blitzplotter(Posted 1+ years ago)

 This is very nice code - I've been mulling over how to create some terrain from some GPS data - this nicely fits the bill. I just need to invoke some logic to even out the 'spikes'.... [/i]

 

SimplePortal 2.3.6 © 2008-2014, SimplePortal