Lib Explode


Tweet blitz3d code-archives mesh rated
(Posted 1 month ago) RonTek

Explodable mesh library.

Author: big10p

Library that creates explodable meshes by copying existing meshes, unwelding all triangles and performing optional, recursive subdivision to give large-tri meshes more pieces to explode.

Explosions are dynamic: the variable strength explosion that disintegrates a mesh can be set to any point relative to the mesh's centre, either using coords aligned to the mesh's axes or aligned to the world axes. This also allows explosions to be either internal or external to the mesh. Meshes can be blown-up with multiple explosions, too.

Image

; Usage:
; 1) Place a copy of LIB_mesh_explode.bb in the same directory as your project.
; 2) Add the following lines to your code, somewhere after the Graphics3D call:
;      Include "LIB_mesh_explode.bb"
;      open_mesh_explode()
; 3) Call copy_mesh_explode() to make an explodable copy of an existing mesh,
;    preferably, do this before entering your main loop e.g. in your level setup code.
; 4) In your main loop, add a call to update_mesh_explode() between UpdateWorld and RenderWorld.
; 5) Make a call to start_mesh_explode() whenever you want the mesh to, er, start exploding!
; 6) Finally, add a call to close_mesh_explode() just before ending your program.
;
; See text at the start of each function for a full description, params required etc.
;

    ; Explosion control constants:
    ; FADE_START  - Set to value between 0 and 1 to say when, during an explosion
    ;               animation, the pieces should start to fade out. e.g. 1 to start
    ;               immediately, .5 to start halfway through, 0 to never fade.
    ; GRAVITY     - Per frame factor by which pieces gravitate towards the world.
    ; XZ_DECAY    - Per frame factor by which pieces' world X and Z velocity decays.
    ; JIGGLE_TRAJ - False to set exploding pieces on an exact trajectory defined by
    ;               the vector from the blast focus to the centre of the tri.
    ;               True to set exploding pieces on a trajectory based on the vector
    ;               defined above, but with an added 'jiggle' factor. This adds a
    ;               more realistic, chaotic appearance to the explosion and helps
    ;               disguise the often uniform construction of meshes. However, this
    ;               makes a call to start_mesh_explode() slower.
    Const FADE_START# = 1
    Const GRAVITY# = 0.001
    Const XZ_DECAY# = 2.0 + GRAVITY     
    Const JIGGLE_TRAJ% = True

    Type tri_linkT
        Field prev.tri_linkT
        Field surf
        Field tri
        Field dx#,dy#,dz#
        Field pitch#,yaw#,roll#
    End Type

    Type explode_ctrlT
        Field tri_list.tri_linkT
        Field mesh
        Field life%
        Field fader#
        Field fade_start%
        Field exploding%
        Field o_pitch#
        Field o_yaw#
        Field o_roll#
        Field entity_fx%
    End Type    

    ; Library globals.
    Global tm_mesh
    Global tm_surf
    Global sd_mesh
    Global sd_surf
    Global vm_mesh
    Global vm_surf


;
; Initializes library, ready for use.
;
Function open_mesh_explode()

    ; Scratch pad single tri mesh for doing rotations.
    tm_mesh = CreateMesh()
    tm_surf = CreateSurface(tm_mesh)
    AddVertex(tm_surf,0,0,0)
    AddVertex(tm_surf,0,0,0)
    AddVertex(tm_surf,0,0,0)
    AddTriangle(tm_surf,0,1,2)
    HideEntity tm_mesh

    ; Scratch pad mesh used by copy_tri_explode() for subdivision.
    sd_mesh = CreateMesh()
    sd_surf = CreateSurface(sd_mesh)
    HideEntity sd_mesh

    ; Scratch pad single vertex mesh used to 'jiggle'
    ; particle trajectory vectors.
    vm_mesh = CreateMesh()
    vm_surf = CreateSurface(vm_mesh)
    AddVertex(vm_surf,0,0,0)
    HideEntity vm_mesh

End Function


;
; Closes down lib, freeing all mem used.
;
Function close_mesh_explode()

    For this.explode_ctrlT = Each explode_ctrlT
        free_mesh_explode(this)
    Next

    FreeEntity tm_mesh
    FreeEntity sd_mesh
    FreeEntity vm_mesh

End Function


;
; Updates ALL explodable meshes that are currently exploding.
;
Function update_mesh_explode()

    For this.explode_ctrlT = Each explode_ctrlT

        If this\exploding

            If this\life
                tri.tri_linkT = this\tri_list

                If this\life <= this\fade_start
                    EntityAlpha this\mesh,this\life * this\fader
                EndIf

                ; Update all tris in linked list.
                While tri <> Null
                    v0 = TriangleVertex(tri\surf,tri\tri,0)
                    v1 = TriangleVertex(tri\surf,tri\tri,1)
                    v2 = TriangleVertex(tri\surf,tri\tri,2)

                    ; Get 'centre of tri' vertex.
                    cx# = VertexX(tri\surf,v2+1)
                    cy# = VertexY(tri\surf,v2+1)
                    cz# = VertexZ(tri\surf,v2+1)

                    ; Load scratch pad tri mesh.
                    VertexCoords tm_surf,0,VertexX(tri\surf,v0)-cx,VertexY(tri\surf,v0)-cy,VertexZ(tri\surf,v0)-cz
                    VertexCoords tm_surf,1,VertexX(tri\surf,v1)-cx,VertexY(tri\surf,v1)-cy,VertexZ(tri\surf,v1)-cz
                    VertexCoords tm_surf,2,VertexX(tri\surf,v2)-cx,VertexY(tri\surf,v2)-cy,VertexZ(tri\surf,v2)-cz
                    VertexNormal tm_surf,0,VertexNX(tri\surf,v0),VertexNY(tri\surf,v0),VertexNZ(tri\surf,v0)
                    VertexNormal tm_surf,1,VertexNX(tri\surf,v1),VertexNY(tri\surf,v1),VertexNZ(tri\surf,v1)
                    VertexNormal tm_surf,2,VertexNX(tri\surf,v2),VertexNY(tri\surf,v2),VertexNZ(tri\surf,v2)

                    ; Do rotations.
                    RotateMesh tm_mesh,tri\pitch,tri\yaw,tri\roll

                    ; Copy back to mesh tri adding translation.
                    VertexCoords tri\surf,v0,VertexX(tm_surf,0)+cx+tri\dx,VertexY(tm_surf,0)+cy+tri\dy,VertexZ(tm_surf,0)+cz+tri\dz
                    VertexCoords tri\surf,v1,VertexX(tm_surf,1)+cx+tri\dx,VertexY(tm_surf,1)+cy+tri\dy,VertexZ(tm_surf,1)+cz+tri\dz
                    VertexCoords tri\surf,v2,VertexX(tm_surf,2)+cx+tri\dx,VertexY(tm_surf,2)+cy+tri\dy,VertexZ(tm_surf,2)+cz+tri\dz
                    VertexNormal tri\surf,v0,VertexNX(tm_surf,0),VertexNY(tm_surf,0),VertexNZ(tm_surf,0)
                    VertexNormal tri\surf,v1,VertexNX(tm_surf,1),VertexNY(tm_surf,1),VertexNZ(tm_surf,1)
                    VertexNormal tri\surf,v2,VertexNX(tm_surf,2),VertexNY(tm_surf,2),VertexNZ(tm_surf,2)

                    VertexCoords tri\surf,v2+1,cx+tri\dx,cy+tri\dy,cz+tri\dz

                    ; Update gravity effect, ready for next update.
                    tri\dy = tri\dy-GRAVITY
                    tri\dx = tri\dx/XZ_DECAY
                    tri\dz = tri\dz/XZ_DECAY

                    tri = tri\prev
                Wend

                this\life = this\life - 1
            Else
                ; Mesh has finished exploding.
                free_mesh_explode(this)
            EndIf

        EndIf

    Next

End Function


;
; Creates a subdivided (optional), unwelded copy of an existing mesh.
; Explode info for all tris in the new mesh are kept in a separate linked list
; contained in the control variable returned to the caller.
; Note: the source mesh being copied remains completely unaltered.
;
; Params:
; s_mesh    - Source mesh to be copied.
; divs      - Number of times to perform x4 subdivision on each source tri.
; entity_fx - The entity FX to be applied to the explodable mesh. This takes
;             the same bit flags as the EntityFX command. Default is 0 (nothing).
; Returns:
; Pointer to the control variable (of type explode_ctrlT) for the
; new explodable mesh created.
;
Function copy_mesh_explode.explode_ctrlT(s_mesh,divs=0,entity_fx%=0)

    tri_list.tri_linkT = Null

    d_mesh = CreateMesh()

    total_surfs = CountSurfaces(s_mesh)

    For sno = 1 To total_surfs
        d_surf = CreateSurface(d_mesh)

        s_surf = GetSurface(s_mesh,sno)
        nt = CountTriangles(s_surf)

        For tno = 0 To nt-1
            tri_list = copy_tri_explode(s_surf,tno,d_surf,divs,tri_list)
        Next

    Next

    ; Create and return this explodable mesh's control variable.
    ctrl.explode_ctrlT = New explode_ctrlT
    ctrl\tri_list = tri_list
    ctrl\mesh = d_mesh
    ctrl\exploding = False
    ctrl\entity_fx = entity_fx

    ; Paint all surfaces in the explodable mesh with the same
    ; surface brushes as the original mesh.
    For sno = 1 To total_surfs
        brush = GetSurfaceBrush(GetSurface(s_mesh,sno))
        PaintSurface GetSurface(d_mesh,sno),brush
        FreeBrush brush
    Next

    EntityFX ctrl\mesh,entity_fx

    Return ctrl

End Function


;
; Adds an unwelded copy of a tri from the source surface to the destination
; surface, performing any subdivision requested.
;
; Subdivision is done by calling this function recursively, splitting the
; source tri into 4 unwelded tris each time, like so:
;
;           v1
;           /\ 
;         /____\
;       /  \  /  \
;     /_____\/_____\
;    v0            v2
;
; Params:
; s_surf   - Source surface containing tri to be copied.
; tri      - Index of tri to be copied.
; d_surf   - Destination surface to copy the source tri to.
; divs     - Number of times to perform x4 subdivision on the source tri.
; tri_list - Current top item in the linked list.
; reset    - True (default) to clear scratch pad mesh.
;            False to not clear scratch pad mesh (used internally only!).
;
; Returns:
; The current top item in the linked list.
;
Function copy_tri_explode.tri_linkT(s_surf,tri,d_surf,divs,tri_list.tri_linkT,reset%=True)

    If reset Then ClearSurface(sd_surf)

    sv0 = TriangleVertex(s_surf,tri,0)
    sv1 = TriangleVertex(s_surf,tri,1)
    sv2 = TriangleVertex(s_surf,tri,2)

    ; Get coords of all 3 vertices of source tri.
    x0# = VertexX(s_surf,sv0)
    y0# = VertexY(s_surf,sv0)
    z0# = VertexZ(s_surf,sv0)
    x1# = VertexX(s_surf,sv1)
    y1# = VertexY(s_surf,sv1)
    z1# = VertexZ(s_surf,sv1)
    x2# = VertexX(s_surf,sv2)
    y2# = VertexY(s_surf,sv2)
    z2# = VertexZ(s_surf,sv2)

    ; Get normals of all 3 vertices of source tri.
    nx0# = VertexNX(s_surf,sv0)
    ny0# = VertexNY(s_surf,sv0)
    nz0# = VertexNZ(s_surf,sv0)
    nx1# = VertexNX(s_surf,sv1)
    ny1# = VertexNY(s_surf,sv1)
    nz1# = VertexNZ(s_surf,sv1)
    nx2# = VertexNX(s_surf,sv2)
    ny2# = VertexNY(s_surf,sv2)
    nz2# = VertexNZ(s_surf,sv2)

    ; Get tex coords of all 3 vertices of source tri.
    u0# = VertexU(s_surf,sv0)
    v0# = VertexV(s_surf,sv0)
    w0# = VertexW(s_surf,sv0)
    u1# = VertexU(s_surf,sv1)
    v1# = VertexV(s_surf,sv1)
    w1# = VertexW(s_surf,sv1)
    u2# = VertexU(s_surf,sv2)
    v2# = VertexV(s_surf,sv2)
    w2# = VertexW(s_surf,sv2)

    ; Get colour of all 3 vertices of source tri.
    r0# = VertexRed(s_surf,sv0)
    g0# = VertexGreen(s_surf,sv0)
    b0# = VertexBlue(s_surf,sv0)
    r1# = VertexRed(s_surf,sv1)
    g1# = VertexGreen(s_surf,sv1)
    b1# = VertexBlue(s_surf,sv1)
    r2# = VertexRed(s_surf,sv2)
    g2# = VertexGreen(s_surf,sv2)
    b2# = VertexBlue(s_surf,sv2)

    If divs
        ; Calculate coords of the 3 discrete vertices used by subdivision.
        x3# = (x1+x0)/2.0
        y3# = (y1+y0)/2.0
        z3# = (z1+z0)/2.0
        x4# = (x2+x1)/2.0
        y4# = (y2+y1)/2.0
        z4# = (z2+z1)/2.0
        x5# = (x0+x2)/2.0
        y5# = (y0+y2)/2.0
        z5# = (z0+z2)/2.0

        ; Calculate normals of the 3 discrete vertices used by subdivision.
        nx3# = (nx1+nx0)/2.0
        ny3# = (ny1+ny0)/2.0
        nz3# = (nz1+nz0)/2.0
        nx4# = (nx2+nx1)/2.0
        ny4# = (ny2+ny1)/2.0
        nz4# = (nz2+nz1)/2.0
        nx5# = (nx0+nx2)/2.0
        ny5# = (ny0+ny2)/2.0
        nz5# = (nz0+nz2)/2.0

        ; Unify.
        nl# = Sqr(nx3*nx3 + ny3*ny3 + nz3*nz3)
        nx3 = nx3 / nl#
        ny3 = ny3 / nl#
        nz3 = nz3 / nl#
        nl# = Sqr(nx4*nx4 + ny4*ny4 + nz4*nz4)
        nx4 = nx4 / nl#
        ny4 = ny4 / nl#
        nz4 = nz4 / nl#
        nl# = Sqr(nx5*nx5 + ny5*ny5 + nz5*nz5)
        nx5 = nx5 / nl#
        ny5 = ny5 / nl#
        nz5 = nz5 / nl#

        ; Calculate tex coords of the 3 discrete vertices used by subdivision.
        u3# = (u1+u0)/2.0
        v3# = (v1+v0)/2.0
        w3# = (w1+w0)/2.0
        u4# = (u2+u1)/2.0
        v4# = (v2+v1)/2.0
        w4# = (w2+w1)/2.0
        u5# = (u0+u2)/2.0
        v5# = (v0+v2)/2.0
        w5# = (w0+w2)/2.0

        ; Calculate colour of the 3 discrete vertices used by subdivision.
        r3# = (r1+r0)/2.0
        g3# = (g1+g0)/2.0
        b3# = (b1+b0)/2.0
        r4# = (r2+r1)/2.0
        g4# = (g2+g1)/2.0
        b4# = (b2+b1)/2.0
        r5# = (r0+r2)/2.0
        g5# = (g0+g2)/2.0
        b5# = (b0+b2)/2.0

        ; Add the 4 unwelded tris comprising the subdivision to the
        ; temporary, scratch pad mesh surface.
        tv0 = AddVertex(sd_surf,x0,y0,z0)
        tv3 = AddVertex(sd_surf,x3,y3,z3)
        tv5 = AddVertex(sd_surf,x5,y5,z5)
        tri0 = AddTriangle(sd_surf,tv0,tv3,tv5)
        VertexNormal sd_surf,tv0,nx0,ny0,nz0
        VertexNormal sd_surf,tv3,nx3,ny3,nz3
        VertexNormal sd_surf,tv5,nx5,ny5,nz5
        VertexColor sd_surf,tv0,r0,g0,b0
        VertexColor sd_surf,tv3,r3,g3,b3
        VertexColor sd_surf,tv5,r5,g5,b5
        VertexTexCoords sd_surf,tv0,u0,v0,w0
        VertexTexCoords sd_surf,tv3,u3,v3,w3
        VertexTexCoords sd_surf,tv5,u5,v5,w5

        tv1 = AddVertex(sd_surf,x1,y1,z1)
        tv4 = AddVertex(sd_surf,x4,y4,z4)
        tv3b = AddVertex(sd_surf,x3,y3,z3)
        tri1 = AddTriangle(sd_surf,tv1,tv4,tv3b)
        VertexNormal sd_surf,tv1,nx1,ny1,nz1
        VertexNormal sd_surf,tv4,nx4,ny4,nz4
        VertexNormal sd_surf,tv3b,nx3,ny3,nz3
        VertexColor sd_surf,tv1,r1,g1,b1
        VertexColor sd_surf,tv4,r4,g4,b4
        VertexColor sd_surf,tv3b,r3,g3,b3
        VertexTexCoords sd_surf,tv1,u1,v1,w1
        VertexTexCoords sd_surf,tv4,u4,v4,w4
        VertexTexCoords sd_surf,tv3b,u3,v3,w3

        tv2 = AddVertex(sd_surf,x2,y2,z2)
        tv5b = AddVertex(sd_surf,x5,y5,z5)
        tv4b = AddVertex(sd_surf,x4,y4,z4)
        tri2 = AddTriangle(sd_surf,tv2,tv5b,tv4b)
        VertexNormal sd_surf,tv2,nx2,ny2,nz2
        VertexNormal sd_surf,tv5b,nx5,ny5,nz5
        VertexNormal sd_surf,tv4b,nx4,ny4,nz4
        VertexColor sd_surf,tv2,r2,g2,b2
        VertexColor sd_surf,tv5b,r5,g5,b5
        VertexColor sd_surf,tv4b,r4,g4,b4
        VertexTexCoords sd_surf,tv2,u2,v2,w2
        VertexTexCoords sd_surf,tv5b,u5,v5,w5
        VertexTexCoords sd_surf,tv4b,u4,v4,w4

        tv3c = AddVertex(sd_surf,x3,y3,z3)
        tv4c = AddVertex(sd_surf,x4,y4,z4)
        tv5c = AddVertex(sd_surf,x5,y5,z5)
        tri3 = AddTriangle(sd_surf,tv3c,tv4c,tv5c)
        VertexNormal sd_surf,tv3c,nx3,ny3,nz3
        VertexNormal sd_surf,tv4c,nx4,ny4,nz4
        VertexNormal sd_surf,tv5c,nx5,ny5,nz5
        VertexColor sd_surf,tv3c,r3,g3,b3
        VertexColor sd_surf,tv4c,r4,g4,b4
        VertexColor sd_surf,tv5c,r5,g5,b5
        VertexTexCoords sd_surf,tv3c,u3,v3,w3
        VertexTexCoords sd_surf,tv4c,u4,v4,w4
        VertexTexCoords sd_surf,tv5c,u5,v5,w5

        divs = divs - 1

        tri_list = copy_tri_explode(sd_surf,tri0,d_surf,divs,tri_list,False)
        tri_list = copy_tri_explode(sd_surf,tri1,d_surf,divs,tri_list,False)
        tri_list = copy_tri_explode(sd_surf,tri2,d_surf,divs,tri_list,False)
        tri_list = copy_tri_explode(sd_surf,tri3,d_surf,divs,tri_list,False)

    Else

        dv0 = AddVertex(d_surf,x0,y0,z0)
        dv1 = AddVertex(d_surf,x1,y1,z1)
        dv2 = AddVertex(d_surf,x2,y2,z2)

        ; Calculate and add a lone 'centre of tri' vertex (needed for
        ; per-tri rotations and blast trajectory calculation).
        tx# = (x2+x1)/2.0
        ty# = (y2+y1)/2.0
        tz# = (z2+z1)/2.0
        cvx# = tx - ((tx-x0)/3.0)
        cvy# = ty - ((ty-y0)/3.0)
        cvz# = tz - ((tz-z0)/3.0)
        AddVertex(d_surf,cvx,cvy,cvz)

        real_tri = AddTriangle(d_surf,dv0,dv1,dv2)

        VertexNormal d_surf,dv0,nx0,ny0,nz0
        VertexNormal d_surf,dv1,nx1,ny1,nz1
        VertexNormal d_surf,dv2,nx2,ny2,nz2
        VertexColor d_surf,dv0,r0,g0,b0
        VertexColor d_surf,dv1,r1,g1,b1
        VertexColor d_surf,dv2,r2,g2,b2
        VertexTexCoords d_surf,dv0,u0,v0,w0
        VertexTexCoords d_surf,dv1,u1,v1,w1
        VertexTexCoords d_surf,dv2,u2,v2,w2

        ; Add this tri to the linked list.
        link.tri_linkT = New tri_linkT
        link\prev = tri_list
        link\surf = d_surf
        link\tri = real_tri

        tri_list = link 
    EndIf

    Return tri_list

End Function


;
; Initializes and authorizes a mesh to start exploding.
; Note: can handle starting an explosion on a mesh that's already exploding.
;
; Params:
; ctrl        - Control variable of the mesh to start exploding.
; blast       - Strength of the blast to explode the mesh with.
; life        - Duration of the explosion animation (in frames).
; bfx,bfy,bfz - Blast focus coords (point in 3D space where the explosion is to
;               occur), relative to mesh centre.
; loc         - True to set blast focus using local space coords.
;               False (default) to set blast focus using coords aligned to world
;               axes. e.g. a blast focus of 0,-1,0 will cause an explosion directly
;               below the mesh's centre, regardless of the mesh's current rotation.
;
Function start_mesh_explode(ctrl.explode_ctrlT,blast#=1,life%=100,bfx#=0,bfy#=0,bfz#=0,loc%=False)

    If loc
        If ctrl\exploding
            ; Temporarily re-instate mesh's original rotation so we can
            ; calculate local blast focus coords.
            RotateEntity ctrl\mesh,ctrl\o_pitch,ctrl\o_yaw,ctrl\o_roll,1

            ; Convert blast focus to world-aligned coords.  
            TFormPoint bfx,bfy,bfz,ctrl\mesh,0
            bfx = TFormedX() - EntityX(ctrl\mesh,1)
            bfy = TFormedY() - EntityY(ctrl\mesh,1)
            bfz = TFormedZ() - EntityZ(ctrl\mesh,1)

            RotateEntity ctrl\mesh,0,0,0,1
        Else
            ; Convert blast focus to world-aligned coords.  
            TFormPoint bfx,bfy,bfz,ctrl\mesh,0
            bfx = TFormedX() - EntityX(ctrl\mesh,1)
            bfy = TFormedY() - EntityY(ctrl\mesh,1)
            bfz = TFormedZ() - EntityZ(ctrl\mesh,1)
        EndIf
    EndIf

    If Not ctrl\exploding
        ; Align mesh axes to world axes, keeping mesh's visible
        ; orientation (needed for gravity to work).
        ctrl\o_pitch = EntityPitch(ctrl\mesh,1)
        ctrl\o_yaw = EntityYaw(ctrl\mesh,1)
        ctrl\o_roll = EntityRoll(ctrl\mesh,1)
        RotateEntity ctrl\mesh,0,0,0,1
        RotateMesh ctrl\mesh,ctrl\o_pitch,ctrl\o_yaw,ctrl\o_roll
    EndIf

    tri.tri_linkT = ctrl\tri_list

    If JIGGLE_TRAJ
        While tri <> Null

            ; Get 'centre of tri' vertex.
            cv = TriangleVertex(tri\surf,tri\tri,2) + 1
            cvx# = VertexX(tri\surf,cv)
            cvy# = VertexY(tri\surf,cv)
            cvz# = VertexZ(tri\surf,cv)

            ; Use the vector from bfx,bfy,bfz (blast focus) to cvx,cvy,cvz ('centre
            ; of tri' vert) as the trajectory, adding a random 'jiggle' factor.
            VertexCoords vm_surf,0,cvx-bfx,cvy-bfy,cvz-bfz
            RotateMesh vm_mesh,Rnd(-10,10),Rnd(-10,10),Rnd(-10,10)

            tvx# = VertexX(vm_surf,0)
            tvy# = VertexY(vm_surf,0)
            tvz# = VertexZ(vm_surf,0)
            tvl# = Sqr(tvx*tvx + tvy*tvy + tvz*tvz)

            ; Set velocity along trajectory vector based on proximity to
            ; explosion (blast focus), explosion strength and a random factor.
            v_scale# = tvl * Rnd(20.0,50.0)

            ; Add to current dx,dy,dz in case this mesh is already exploding!
            tri\dx = tri\dx + (((tvx/tvl)/v_scale) * blast)
            tri\dy = tri\dy + (((tvy/tvl)/v_scale) * blast)
            tri\dz = tri\dz + (((tvz/tvl)/v_scale) * blast)

            ; Base rotation on velocity.
            rot# = (Abs(tri\dx) + Abs(tri\dy) + Abs(tri\dz)) * 100
            tri\pitch = Rnd(-rot,rot)
            tri\yaw = Rnd(-rot,rot)
            tri\roll = Rnd(-rot,rot)

            tri = tri\prev
        Wend
    Else
        While tri <> Null

            ; Get 'centre of tri' vertex.
            cv = TriangleVertex(tri\surf,tri\tri,2) + 1
            cvx# = VertexX(tri\surf,cv)
            cvy# = VertexY(tri\surf,cv)
            cvz# = VertexZ(tri\surf,cv)

            ; Use the vector from bfx,bfy,bfz (blast focus) to cvx,cvy,cvz
            ; ('centre of tri' vert) as the trajectory.
            tvx# = cvx - bfx
            tvy# = cvy - bfy
            tvz# = cvz - bfz
            tvl# = Sqr(tvx*tvx + tvy*tvy + tvz*tvz)

            ; Set velocity along trajectory vector based on proximity to
            ; explosion (blast focus), explosion strength and a random factor.
            v_scale# = tvl * Rnd(20.0,50.0)

            ; Add to current dx,dy,dz in case this mesh is already exploding!
            tri\dx = tri\dx + (((tvx/tvl)/v_scale) * blast)
            tri\dy = tri\dy + (((tvy/tvl)/v_scale) * blast)
            tri\dz = tri\dz + (((tvz/tvl)/v_scale) * blast)

            ; Base rotation on velocity.
            rot# = (Abs(tri\dx) + Abs(tri\dy) + Abs(tri\dz)) * 100
            tri\pitch = Rnd(-rot,rot)
            tri\yaw = Rnd(-rot,rot)
            tri\roll = Rnd(-rot,rot)

            tri = tri\prev
        Wend
    EndIf

    ctrl\life = life
    ctrl\fade_start = Ceil(Float(life)*FADE_START#)
    ctrl\fader = 1.0/(ctrl\fade_start+1)
    ctrl\exploding = True

    ; Make sure backface culling is turned off so exploding pieces
    ; aren't just single sided.
    EntityFX ctrl\mesh,ctrl\entity_fx Or 16

End Function


;
; Free all mem used by an explodable mesh created with copy_mesh_explode().
;
; Params:
; ctrl - Control variable of the explodable mesh to be freed.
;
Function free_mesh_explode(ctrl.explode_ctrlT)

    this.tri_linkT = ctrl\tri_list

    While this <> Null
        delme.tri_linkT = this
        this = delme\prev
        Delete delme
    Wend

    FreeEntity ctrl\mesh
    Delete ctrl

End Function

Example Demo


; Simple demo to load a model and explode it when SPACE is pressed.
;

    Graphics3D 800,600,32,2

    SetBuffer BackBuffer()

    Include "LIB_explode_mesh.bb"
    open_mesh_explode()

    SeedRnd MilliSecs()

    fps_timer = CreateTimer(60)

    cam = CreateCamera()
    PositionEntity cam,0,0,-9
    CameraClsColor cam,0,0,150

    light = CreateLight()
    TurnEntity light,0,-45,0

    ; Load mesh to make explodable copy of.
    mesh = LoadMesh("mak_running.3ds")  

    ; Make subdivided copy of original mesh.
    c.explode_ctrlT = copy_mesh_explode(mesh,1)

    ; Original mesh no longer needed.
    FreeEntity mesh

    bang% = False

    ; Main loop
    While Not KeyHit(1)

        ; Quit if explosion has finished.
        If Last explode_ctrlT = Null Then Exit

        If bang = False
            If KeyHit(57)
                start_mesh_explode(c,2,250)
                bang = True
            Else
                TurnEntity c\mesh,1,1,1 
            EndIf
        EndIf

        UpdateWorld
        update_mesh_explode()
        RenderWorld

        WaitTimer(fps_timer)
        Flip(1)

    Wend

    close_mesh_explode()

    End

Reply To Topic (minimum 10 characters)

Please log in to reply