Vertex Ambient Occlusion


Attention! 👉Starting November 2024, BlitzCoder.org will now be BlitzBasic.org.

 

Tweet blitz3d code-archives effects 3d-lightmappers
BlitzCoder

System Ambient Occlusion Vertex by Vincenzo Caldarulo Italy-Bari (Vincentx)

Vertex Ambient Occlusion - Blitz3D

;===>O=========================o<=================================================================
;===>O=========================o<=================================================================
;===>   Name file: 
;===>
;===>   Programmatore:
;===>     Caldarulo Vincenzo (Vision&Design Software)
;===>   Descrizione:
;===>
;===>O=========================o<=================================================================
;===>O=========================o<=================================================================
; 
;
AppTitle("Ambient Occlusion Vertex by Vincentx (Vincenzo Caldarulo Italy-Bari)")
;=====================================================
;===>
Type AO_vertex 
    Field Vx#
    Field Vy#
    Field Vz#
    Field Vc%
End Type

;=====================================================
;===>
Type AO_receiver
    ;===>
    Field ObjOrig%
    Field Obj%
    Field FileName$
    ;===>
End Type

;====>
;=====================================================
;===>
Const AO_Method%                = 0 ; 0 = LinePick B3D  // 1 = LinePick SW  // 2 = Octree
Const AO_Ray#                   =120 ; Lenght of ray
Const AO_DetBase#           = 4;    Level of precision AO 3 is a good result
Const AO_Detail#                = (AO_DetBase+1) ;;3=4 INTERAZIONI
Const AO_TotRay#                = ((4*(AO_DetBase-1)) * (AO_DetBase-1))+1
Const AO_Attenuation#   = (255.0 - 1 )/AO_TotRay

;=====================================================
;===>
Dim AO_Vertex.AO_vertex(65535)
For id=0 To 65535
    AO_Vertex(id) = New AO_vertex
Next
;=====================================================
;===>
Global dlr.AO_receiver

Global AO_TimeCollision=0
;Global AO_InterCollision=0

Const AO_LevelAlpha#  = 0.8
;=====================================================
;===>

Dim RayList.Point3D(AO_TotRay)
Global NSphere% = 0

;=====================================================
;===>
Precalcolo();

Global spd# = 0.5

Graphics3D 800,600,32,2
;AmbientLight 255,255,255
;   GameLight=CreateLight():RotateEntity gamelight,0,0,35
;   LightColor gamelight,200,200,200
ClearTextureFilters()
Global Camera = CreateCamera() 

LoadScene()

; =================================================================================================
; ===>
Cls
Print ">===================================================="
Print ">"
Print "> Numero di interazioni oggetto: "+AO_TotRay
Print ">"
Print ">===================================================="
Print ">"
;Stop
Local TimeAO% = AO_Update()
spd# = 0.5
Local l_OldTime,l_CurTime
; =================================================================================================
; ===>

Repeat  
    MoveEntity Camera,(KeyDown(205)-KeyDown(203))*spd,0,(MouseDown(1)-MouseDown(2))*spd
    TurnEntity Camera,-MouseYSpeed()*0.1,-MouseXSpeed()*0.1,0
    RotateEntity Camera,EntityPitch(Camera,True),EntityYaw(Camera,True),0

    MoveMouse GraphicsWidth()*.5,GraphicsHeight()*.5

    ; ===========================================================================
    If KeyHit(2) Then  AO_Show()
    If KeyHit(3) Then  AO_Hide()

    If KeyHit(24) Then  WireFrame True
    If KeyHit(25) Then  WireFrame False

    If (KeyDown(46)) Then 
        PositionEntity Camera,60,60,-60
        RotateEntity Camera,30,45,0
    EndIf

    ; ===========================================================================
    ; ===>
    UpdateWorld()
    RenderWorld()
    ;===>
    Local Riga=0
    ;====>
    Color 255,0,0
    l_CurTime=MilliSecs()-l_OldTime
    l_OldTime=MilliSecs()
    Text(0,Riga,"Ms: "+l_CurTime+" AO Time: "+ TimeAO) : Riga = Riga + 10
    Riga = Riga + 10 : Riga = Riga + 10
    Text(0,Riga," 1 - Enable Ambient occlusion")    : Riga = Riga + 10
    Text(0,Riga," 2 - Disable Ambient occlusion")   : Riga = Riga + 10
    ;===>
    Flip(False)

    ;===>
Until KeyHit(1)

End

Function LoadScene()
    ;===>
    Local Obj;
    Local R = 20
    Local R2 = 20
    Local x,z
    Local Segment=50
    ;===>
    Obj = CPlane(Segment*2) 
    PositionEntity Obj,0,-5,0
    ScaleEntity Obj, 2, 1, 2
        CreateDir("AO_DIR");
    AO_SetReceiver(Obj,"AO_DIR\AO_plane.aof") ; .aof ambient occlusion file
    ;===>
    Local a#;
    For a=0 To 100
        ;Obj = CreateSphere(16)
        Obj = CreateCube()
        ang = a*25.0
        d0  = R2-(a/10.0)
        d1  = a/3.0
        PositionEntity Obj, d0*Cos(ang), d1, d0*Sin(ang)
        RotateEntity Obj, 0, ang, 0
        ScaleEntity Obj, 2, 2, 2

        AO_SetReceiver(Obj,"AO_DIR\AO_cube"+a+".aof")

    Next
    ;===>

End Function

Function CPlane%(Number#)
    ;===>
    If(Number>150) Then Number=150
    ;===>
    Local mesh = CreateMesh()
    Local surf = CreateSurface(mesh)
    Local center#= (Number/2.0)
    ;===>

    For pz# = 0 To Number
        For px# = 0 To Number
            k = AddVertex(surf, px-center, 0, pz-center, px/Number, pz/Number )
        Next
    Next
    ;===>

    For pz=0 To Number-1
        For px=0 To Number-1
            ;===>
            p0 = px+((pz+0)*(Number+1))
            p1 = px+((pz+0)*(Number+1))+1
            p2 = px+((pz+1)*(Number+1))
            p3 = px+((pz+1)*(Number+1))+1
            ;===>
            AddTriangle(surf,p2,p1,p0)
            AddTriangle(surf,p2,p3,p1)
            ;===>
        Next
    Next
    ;===>
    Return mesh
    ;===>
End Function

; ================================================== 
; ----------------------------------------------- 
; Punto 3D 
;--------------------------------------- 
;======================================= 
Type Point3D 
    Field x# 
    Field y# 
    Field z# 
End Type 

; ================================================== 
; ----------------------------------------------- 

Function Point3DSet( Dst.Point3D, x#, y#, z#) 
    ;----> 
    Dst\x = x ; 
    Dst\y = y ; 
    Dst\z = z ; 
    ;----> 
End Function 

; ================================================== 
; ----------------------------------------------- 
; Rotazione Asse X Y
;-------------------------- 
;================================ 
Function RotateXY( Rtn.Point3D, P.Point3D, RotX%, RotY% ) 
    ; ===> 
    Local l_c# = Cos(RotX);
    Local l_s# = Sin(RotX); 
    ; ===> 
    ;Rotazione Asse X 
    Local RX_x# =  P\x 
    Local RX_y# = (P\y * l_c)-(P\z * l_s);
    Local RX_z# = (P\z * l_c)+(P\y * l_s);
    ; ===> 
    l_c# = Cos(RotY);
    l_s# = Sin(RotY); 
    ; ===> 
    ;Rotazione Asse Y 
    Local RY_x# = (RX_x * l_c)+(RX_z * l_s);
    Local RY_y# =  RX_y 
    Local RY_z# = (RX_z * l_c)-(RX_x * l_s)
    ; ===> 
    Rtn\x# = RY_x
    Rtn\y# = RY_y
    Rtn\z# = RY_z
    ; ===> 
End Function 

; ================================================== 
; ----------------------------------------------- 
; Calcolo della normale 
;-------------------------- 
;================================ 
; 
Function CalcNormalFast( Rtn.Point3D, A.Point3D, B.Point3D, C.Point3D) 
    ; ===>
    Local K1x# = A\x - B\x
    Local K1y# = A\y - B\y
    Local K1z# = A\z - B\z
    ; ===>
    Local K2x# = B\x - C\x
    Local K2y# = B\y - C\y
    Local K2z# = B\z - C\z
    ; ===>
    ; Compute their cross product. 
    Local Rx# = K1y#*K2z# - K1z#*K2y# 
    Local Ry# = K1z#*K2x# - K1x#*K2z# 
    Local Rz# = K1x#*K2y# - K1y#*K2x# 
    ; ===>
    Local do# = 1.0 / Sqr( (Rx*Rx) + (Ry*Ry) + (Rz*Rz) ) 
  ; ===>
    Rtn\x = Rx*do; 
    Rtn\y = Ry*do; 
    Rtn\z = Rz*do;
    ;===>
End Function

; ================================================== 
; ----------------------------------------------- 
; Vector To Angle
;-------------------------- 
;================================ 
; 
Function VectorToAngle( dst.Point3D, Vect.Point3D ) 
    ;===>
    Local dist1  = Sqr( (Vect\x*Vect\x)+(Vect\z*Vect\z)) ;
    dst\x = ATan2( Vect\y ,dist1);
    dst\y = ATan2( Vect\x ,Vect\z);
    ;===>
End Function

;===>O=========================o<=================================================================
;===>O=========================o<=================================================================
;===>   Name file: 
;===>
;===>   Programmatore:
;===>     Caldarulo Vincenzo (Vision&Design Software)
;===>   Descrizione:
;===>
;===>O=========================o<=================================================================
;===>O=========================o<=================================================================
; 

;;=====================================================
;;===>
;Type AO_vertex 
;   Field Vx#
;   Field Vy#
;   Field Vz#
;   Field Vc%
;End Type
;
;;=====================================================
;;===>
;Type AO_receiver
;   ;===>
;   Field ObjOrig%
;   Field Obj%
;   ;===>
;End Type
;
;;====>
;;=====================================================
;;===>
;Const AO_Method%               = 0 ; 0 = LinePick B3D  // 1 = LinePick SW  // 2 = Octree
;Const AO_Ray#                  = 100
;Const AO_DetBase#          = 2;
;Const AO_Detail#               = (AO_DetBase+1) ;;3=4 INTERAZIONI
;Const AO_TotRay#               = ((4*(AO_DetBase-1)) * (AO_DetBase-1))+1
;Const AO_Attenuation#  = (255.0 - 64 )/AO_TotRay
;
;
;;=====================================================
;;===>
;Dim AO_Vertex.AO_vertex(65535)
;For id=0 To 65535
;   AO_Vertex(id) = New AO_vertex
;Next
;;=====================================================
;;===>
;Global dlr.AO_receiver
;
;Global AO_TimeCollision=0
;;Global AO_InterCollision=0
;
;Const AO_LevelAlpha#  = 0.8
;;=====================================================
;;===>
;
;Dim RayList.Point3D(AO_TotRay)
;Global NSphere% = 0
;
;;=====================================================
;;===>
;Precalcolo();

;=====================================================
;--------------------------------------------------
;===>
;
;===>
;
Function Precalcolo()
    ;===>
    If (AO_DetBase<=1) Then Return
    ;===>
    NSphere%=0
    Local RX#,RY#,RXa#,RYa#
    Local l_Normal.Point3D  = New Point3D : Point3DSet(l_Normal, 0, AO_Ray, 0)
    Local l_PartRY# = ((AO_DetBase-1)*4)
    Local l_AngS# = 360 / l_PartRY ; 
    Local l_AngT# = 90.0 / AO_DetBase
    ;===>
    For RY=0 To l_PartRY-1
        ;===>
        RYa# = l_AngS*RY
        ;===>
        For RX=1 To AO_DetBase-1 
            ;===>
            RXa# = RX*l_AngT
            ;===>
            RayList.Point3D(NSphere) = New Point3D
            ;===>
            RotateXY(RayList(NSphere),l_Normal, RXa, RYa)
            ;===>
            NSphere = NSphere+1
            ;===>
        Next
        ;===>
    Next
    ;===>
    Delete l_Normal
    ;===>
End Function

;=====================================================
;--------------------------------------------------
;===>
;
;===>
;
Function AO_Free()
    Local l_AO_Recived.AO_receiver
    For l_AO_Recived.AO_receiver = Each AO_receiver
        FreeEntity l_AO_Recived\Obj
        Delete l_AO_Recived
    Next

End Function

;=====================================================
;--------------------------------------------------
;===>
;
;===>
;
Function AO_SetReceiver(mesh, AO_FileName$)
    ;===>
    Local l_AO_Recived.AO_receiver = New AO_receiver
    ;===>

    l_AO_Recived\FileName = AO_FileName;
    l_AO_Recived\ObjOrig = mesh
    l_AO_Recived\Obj = CopyMesh(l_AO_Recived\ObjOrig,l_AO_Recived\ObjOrig)
    NameEntity( l_AO_Recived\Obj, EntityName(l_AO_Recived\ObjOrig))
    EntityAlpha l_AO_Recived\Obj, AO_LevelAlpha
    EntityBlend l_AO_Recived\Obj, 1
    ;
    EntityPickMode(l_AO_Recived\Obj,2)
    ;===>
    EntityFX l_AO_Recived\Obj,2+1+32
    UpdateNormals l_AO_Recived\Obj
    ;===>
    Return l_AO_Recived\Obj
End Function

;=====================================================
;--------------------------------------------------
;===>
;
;===>
;
Function AO_Update()
    ;===>
    Local l_total_tris%,l_total_vert%
    Local Total_ColliTime = 0 
    ;===>
    Local Start_Time=MilliSecs()
    ;===>
    Local l_IdV0c%, l_IdV0x#, l_IdV0y#, l_IdV0z#, l_IdV0.AO_vertex
    Local l_IdV1c%, l_IdV1x#, l_IdV1y#, l_IdV1z#, l_IdV1.AO_vertex
    Local l_IdV2c%, l_IdV2x#, l_IdV2y#, l_IdV2z#, l_IdV2.AO_vertex
    ;===>
    Local l_Point0.Point3D  = New Point3D
    Local l_Point1.Point3D  = New Point3D
    Local l_Point2.Point3D  = New Point3D
    ;===>
    Local l_Normal.Point3D  = New Point3D : Point3DSet(l_Normal, 0, AO_Ray, 0)
    Local l_NorMod.Point3D  = New Point3D
    Local l_Angles.Point3D  = New Point3D
    ;===>
    Local SphereList=0
    Local v%, s%
    ;===>
    Local l_CurObj;
    Local n_surfs
    Local surf, n_tris
    Local Px#,Py#,Pz#;
    ;===>
    Local Color_a# = 0
    Local l_rX#,l_rY#
    ;===>
    Local cnt=0
    Local l_AO_Recived.AO_receiver
    Local Riga$
    ;===>
    Local RYa#,RXa#
    Start_Time=MilliSecs()
    Local Start_ms=Start_Time

    Local l_CurVert.AO_vertex
    Local aamod
    ;===>
    For l_AO_Recived = Each AO_receiver
        ; ===>
        l_CurObj    = l_AO_Recived\Obj
        ;exsist the file AO for object
        If FileType(l_AO_Recived\FileName)=1 Then 
            ;===>
            AO_LoadFile(l_CurObj,l_AO_Recived\FileName);
            ;===>
        Else
            ; ===>
            n_surfs= CountSurfaces(l_CurObj)
            Local l_NewId%=0;
            Print "> Oggetto: "+cnt+" Name: "+EntityName(l_CurObj) 

            cnt=cnt+1
            ;===>
            For s = 1 To n_surfs
                ;===>
                surf = GetSurface(l_CurObj,s)
                n_tris = CountTriangles(surf)-1
                aamod = n_tris * .2
                If aamod=0 Then aamod=1
                ;===>
                If (n_tris>0) Then 
                    ;===>
                    Local l_NVert = CountVertices(surf)-1
                    ;===>
                    l_total_vert = l_total_vert+l_NVert
                    l_total_tris = l_total_tris+n_tris
                    ;===>
                    For v = 0 To l_NVert
                        ;===>
                        l_CurVert = AO_Vertex(v)
                        TFormPoint VertexX( surf, v ), VertexY( surf, v ), VertexZ( surf, v ), l_CurObj, 0
                        l_CurVert\Vx = TFormedX()
                        l_CurVert\Vy = TFormedY()
                        l_CurVert\Vz = TFormedZ()
                        l_CurVert\Vc = 255;
                    Next
                    ;===>
                    For v = 0 To n_tris
                        ; ===>
                        l_IdV0 = AO_Vertex(TriangleVertex ( surf, v, 0 ))
                        l_IdV1 = AO_Vertex(TriangleVertex ( surf, v, 1 ))
                        l_IdV2 = AO_Vertex(TriangleVertex ( surf, v, 2 ))
                        ; ===>
                        l_IdV0x = l_IdV0\Vx ; Vertexx       (surf,l_IdV0)
                        l_IdV0y = l_IdV0\Vy ; VertexY       (surf,l_IdV0)
                        l_IdV0z = l_IdV0\Vz ; VertexZ       (surf,l_IdV0)
                        l_IdV0c = l_IdV0\Vc ; VertexRed (surf,l_IdV0)
                        ;===>
                        l_IdV1x = l_IdV1\Vx ; 
                        l_IdV1y = l_IdV1\Vy ; 
                        l_IdV1z = l_IdV1\Vz ; 
                        l_IdV1c = l_IdV1\Vc ; 
                        ;===>
                        l_IdV2x = l_IdV2\Vx ; 
                        l_IdV2y = l_IdV2\Vy ; 
                        l_IdV2z = l_IdV2\Vz ; 
                        l_IdV2c = l_IdV2\Vc ; 
                        ;===>
                        Px = (l_IdV0x + l_IdV1x + l_IdV2x) * .3333333
                        Py = (l_IdV0y + l_IdV1y + l_IdV2y) * .3333333
                        Pz = (l_IdV0z + l_IdV1z + l_IdV2z) * .3333333
                        ;===>
                        l_Point0\x = l_IdV0x : l_Point0\y = l_IdV0y : l_Point0\z = l_IdV0z;
                        l_Point1\x = l_IdV1x : l_Point1\y = l_IdV1y : l_Point1\z = l_IdV1z;
                        l_Point2\x = l_IdV2x : l_Point2\y = l_IdV2y : l_Point2\z = l_IdV2z;
                        ;===>

                        l_NorMod\x = VertexNX(surf,TriangleVertex ( surf, v, 0 ))
                        l_NorMod\y = VertexNY(surf,TriangleVertex ( surf, v, 0 ))
                        l_NorMod\z = VertexNZ(surf,TriangleVertex ( surf, v, 0 ))
                        CalcNormalFast(l_NorMod, l_Point0, l_Point1, l_Point2);
                        VectorToAngle(l_Angles,l_NorMod)
                        ;===>
                        l_rX# = l_Angles\x + 270 ;
                        l_rY# = l_Angles\y + 180 ;
                        ;===>
                        Color_a = 255
                        ; =========================================================================================================
                        ; ----------------------------------------------------------------------------------------------------
                        ; Solution 2  
                        ; ===>
                        ;
                        ; ===>
                        ; Asse perpedicolare al piano
                        l_NorMod\x = l_NorMod\x*AO_Ray : l_NorMod\y = l_NorMod\y*AO_Ray : l_NorMod\z = l_NorMod\z*AO_Ray
                        ; ===>

                        LinePick(Px, Py, Pz, l_NorMod\x, l_NorMod\y, l_NorMod\z);
                        If (PickedEntity()<>0) Then Color_a = Color_a - AO_Attenuation
                        ; ===>
                        Total_ColliTime = Total_ColliTime + AO_TimeCollision
                        ; ===>
                        If (AO_DetBase>1) Then 
                            ;===>
                            For SphereList=0 To NSphere-1
                                ;===>
                                RotateXY(l_NorMod, RayList(SphereList), l_rX, l_rY)
                                ;===>
                                LinePick(Px, Py, Pz, l_NorMod\x, l_NorMod\y, l_NorMod\z);
                                If (PickedEntity()<>0) Then Color_a = Color_a - AO_Attenuation
                                ;===>
                            Next
                            ; ===>
                        EndIf
                        ;===>
                        Total_ColliTime = Total_ColliTime + AO_TimeCollision
                        ;===>
                        ;----------------------------------------------------------------------------------------------------
                        ;=========================================================================================================
                        ;===>

                        If ( Color_a < l_IdV0c) Then l_IdV0\Vc = Color_a
                        If ( Color_a < l_IdV1c) Then l_IdV1\Vc = Color_a
                        If ( Color_a < l_IdV2c) Then l_IdV2\Vc = Color_a
                        ;===>
                        If ((v Mod aamod)=0) Then 
                            ;===>
                            Riga$ =         "> Surfaces:    " + Float(Int((Float(s)/Float(n_surfs))*10000))/100.0
                            Riga$ = Riga$ + "% Complete:    " + Float(Int((Float(v)/Float(n_tris ))*10000))/100.0
                            Riga$ = Riga$ + "  TimeCol:     " + Total_ColliTime
                            Riga$ = Riga$ + "  TotalTime:   " + (MilliSecs()-Start_ms)
                            Print Riga$
                            ;===>
                            Total_ColliTime = 0 
                            Start_ms=MilliSecs()
                            ;===>
                        EndIf
                        ;===>
                    Next
                    ;===>
                    For v = 0 To l_NVert
                        ;===>
                        Color_a = AO_Vertex(v)\Vc
                        VertexColor surf, v, Color_a, Color_a, Color_a;
                        ;===>
                    Next
                    ;===>
                    Riga$ =         "> Surfaces:    " + Float(Int((Float(s)/Float(n_surfs))*10000))/100.0
                    Riga$ = Riga$ + "% Complete:    " + 100.0
                    Riga$ = Riga$ + "  TimeCol:     " + Total_ColliTime
                    Riga$ = Riga$ + "  TotalTime:   " + (MilliSecs()-Start_ms)
                    Print Riga$
                    ;===>
                    Total_ColliTime = 0 
                    Start_ms=MilliSecs()
                    ;===>
                EndIf
                ;===>
                Print " "
                l_NewId = l_NewId + CountVertices(surf)
                ;===>
            Next        
            ;===>
            AO_SaveFile(l_CurObj, l_AO_Recived\FileName);
            ;===>
        EndIf
        ;===>
    Next
    ;===>
    Delete l_Point0
    Delete l_Point1
    Delete l_Point2

    Delete l_Normal;
    Delete l_NorMod;
    Delete l_Angles;
    ;===>
    Local Stop_Time% = MilliSecs()-Start_Time
    ;===>
    Print "->"
    Print "-> Total Time collision: "+Stop_Time
    Print "->"
    Print " Total Tris: "+l_total_tris
    Print " Total Vert: "+l_total_vert
    Print "->"
    Print " "
    Print "Press any Key"
    WaitKey()
    ;===>
    Return Stop_Time 
    ;===>
End Function

;=====================================================
;--------------------------------------------------
;===>
;
;===>
;
Function AO_Show()
    ;===>
    Local l_AO_Recived.AO_receiver
    ;===>
    For l_AO_Recived.AO_receiver = Each AO_receiver
        ; ===>
        ShowEntity l_AO_Recived\Obj
        ; ===>
    Next
    ;===>
End Function

;=====================================================
;--------------------------------------------------
;===>
;
;===>
;
Function AO_Hide()
    ;===>
    Local l_AO_Recived.AO_receiver
    ;===>
    For l_AO_Recived.AO_receiver = Each AO_receiver
        ; ===>
        HideEntity l_AO_Recived\Obj
        ; ===>
    Next
    ;===>
End Function

Function AO_SaveFile( Mesh, AO_FileName$)
    ;===>
    EntityFX Mesh,2+1
    ;===>
    ;first record the surface count
    Local scount=CountSurfaces(Mesh)
    Local F=WriteFile(AO_FileName$)
    WriteInt F,scount
    ;===>
  For s=1 To scount 
        ;===>
    Local surf=GetSurface(Mesh,s) 
    Local vcount=CountVertices(surf)-1
    ;===>
        ; surfaces can get rearranged if the model is reexported via differnt modelling apps.. so lets
    ; record the surface info here so we can find the matching surface when we reload the map
        WriteInt F,s
        WriteInt F,vcount
        WriteInt F,CountTriangles(surf) ; just here to help make a surface match in the loader
        For v=0 To vcount
         ; Now save the vertex data
         ; since we are not using colored lights, we need only save the red channel
         ; on reload we apply the red channel to all r,g and b  
            WriteFloat F,VertexRed(surf,v)
            WriteFloat F,VertexGreen(surf,v)
            WriteFloat F,VertexBlue(surf,v)
        Next
  Next
    CloseFile F
End Function                        

Function AO_LoadFile( Mesh, AO_FileName$)
    EntityBlend Mesh, 1
    EntityFX Mesh,2+1

    If FileType(AO_FileName$)<>1 Then Return -1
    Local f=OpenFile(AO_FileName$)
    Local scount=ReadInt(f)
    Local surfcount=CountSurfaces(Mesh)
    ;===>
    ;make sure we have at least the needed suface count
    If scount<>surfcount Then 
        CloseFile f
        Return -1
    EndIf
    ;===>
    For i=1 To scount
        ;read vert count and tri count
        Local SurfID=ReadInt(f)
        Local vcount=ReadInt(f)
        Local tricount=ReadInt(f)
        ;find a matching surface
        Local match=0
        ;===>
        ;first lets try the surface stored in the save. but because surfaces can get rearranged if a model is reexported
    ;we wont assume its in the same order it was in when we saved the ambient map
    Local s=GetSurface(Mesh,SurfID)
        If vcount=(CountVertices(s)-1) And tricount=CountTriangles(s) Then
            match=1
            For Vert=0 To vcount
                vr=ReadFloat(f)
                vg=ReadFloat(f)
                vb=ReadFloat(f)
                VertexColor s,vert,vr,vg,vb
            Next
        EndIf
        ;===>
        ; if its not in the right order then match may = 0, if it does 
    ; then we want to search though all the surfaces and find the right one    
    If match=0 Then 
            For getsurf=1 To scount
                s=GetSurface(Mesh,getsurf)
                If vcount=(CountVertices(s)-1) And tricount=CountTriangles(s) Then
                    match=1
                    For Vert=0 To vcount
                        vr=ReadFloat(f)
                        vg=ReadFloat(f)
                        vb=ReadFloat(f)
                        VertexColor s,vert,vr,vg,vb,VertexAlpha(s,vert)
                    Next
                EndIf
            Next
    EndIf
        ;===>
    ;if match still is 0, it means there was no matching surface and the model has changed its gemoetric properties
        If match=0 Then 
        CloseFile f
            Return -1 ; did not find a matching surface for this data
        EndIf
        ;===>
    Next
    ;===>
    CloseFile f
    UpdateNormals Mesh
    Return 1
    ;===>

End Function     

Reply To Topic (minimum 10 characters)

Please log in to reply