Who's Online:

  • [Bot]
Now online:
  • 1 robot

 

ED_SiteArticles

 

DBPro Text Graphic Games:

 

 

DBPro Articles:

 

 

 

[Offsite] DarkBasic Professional & Dark GDK/C++:



 


rem ###################################################################
rem Load Object - By: Todd Riggins - ExoDev.Com - Dec. 8, 2010
rem 3D Object Format Info: http://en.wikipedia.org/wiki/Obj
rem ###################################################################


rem ###################################################################
rem GLOBALS
rem ###################################################################

GLOBAL global_CamID as INTEGER

DIM array_string(0) AS STRING

TYPE TYPE_VERTEX
    x AS FLOAT
    y AS FLOAT
    z AS FLOAT
ENDTYPE
DIM array_vertex(0) AS TYPE_VERTEX

TYPE TYPE_TEXCOORD
    u AS FLOAT
    v AS FLOAT
ENDTYPE
DIM array_texcoord(0) AS TYPE_TEXCOORD

TYPE TYPE_NORMAL
    x AS FLOAT
    y AS FLOAT
    z AS FLOAT
ENDTYPE
DIM array_normal(0) AS TYPE_NORMAL

TYPE TYPE_FACE
    V1Vertex AS INTEGER
    V1TexCoord AS INTEGER
    V1Normal AS INTEGER
    V2Vertex AS INTEGER
    V2TexCoord AS INTEGER
    V2Normal AS INTEGER
    V3Vertex AS INTEGER
    V3TexCoord AS INTEGER
    V3Normal AS INTEGER
ENDTYPE
DIM array_face(0) AS TYPE_FACE

GLOBAL gThisStringPosition AS INTEGER
GLOBAL gIndiceStep AS INTEGER
GLOBAL gNumberOfVertices,gNumberOfFaces AS INTEGER

GLOBAL Global_CamID AS INTEGER
GLOBAL Global_RightMouseClick AS INTEGER


rem ###################################################################
rem Start Main Loop
rem ###################################################################

Main()
END

rem ###################################################################
rem Main Loop
rem ###################################################################

FUNCTION Main()
    LOCAL local_ObjectID AS INTEGER
    LOCAL local_SpaceHelm2Image AS INTEGER
    
    rem Initialize Display Setup
    InitDisplaySetup()
    
    rem Retrieve image used by obj 3d object
    local_SpaceHelm2Image = GetNewImageID()
    LOAD IMAGE "BadGuy1.png",local_SpaceHelm2Image,0
    
    rem Load the obj 3d file
    local_ObjectID = GetNewObjectID()
    LoadObj("BadGuy1.obj",local_ObjectID,local_SpaceHelm2Image)

    rem Don't know if Sculptris can save out normals in it's obj export
    rem so I manually create smoothing normals for it here
    SET OBJECT NORMALS local_ObjectID
    SET OBJECT SMOOTHING local_ObjectID,100
    
    rem Rotate the object to face the camera
    ROTATE OBJECT local_ObjectID,0,180,0

    rem Main loop
    REPEAT
        UserControls()


        TEXT 10,30,"Faces:"+str$(gNumberOfFaces)
        TEXT 1,1,"FPS:"+STR$(SCREEN FPS())
        SYNC
    UNTIL ESCAPEKEY()=1
ENDFUNCTION


rem ###################################################################
rem FUNCTIONS
rem ###################################################################


rem Setup Display and Camera
FUNCTION InitDisplaySetup()
    SYNC ON
    SYNC RATE 30

    SET WINDOW POSITION 0,0
    SET WINDOW LAYOUT 0,0,0
    MAXIMIZE WINDOW

    SET DISPLAY MODE DESKTOP WIDTH(),DESKTOP HEIGHT(),0, 0    
    SET WINDOW OFF

    rem create camera
    global_CamID = 1
    MAKE CAMERA global_CamID
    POSITION CAMERA global_CamID,0,2,-1000
    COLOR BACKDROP global_CamID, RGB(16,16,16)
    SET CAMERA FOV global_CamID,45
    SET CAMERA RANGE global_CamID,1,10000
    
    HIDE LIGHT 0

    rem create light to follow camera    
    MAKE LIGHT 1
    SET LIGHT RANGE 1,7000
    POSITION LIGHT 1,CAMERA POSITION X(global_CamID),CAMERA POSITION Y(global_CamID),CAMERA POSITION Z(global_CamID)
    
    DISABLE ESCAPEKEY
ENDFUNCTION


Function UserControls()
    LOCAL local_CameraAngleX as FLOAT
    LOCAL local_CameraAngleY as FLOAT
    LOCAL local_mmovex as INTEGER
    LOCAL local_mmovex as INTEGER
    
    local_mmovex = mousemovex()
    local_mmovey = mousemovey()

    ` Camera Control:
    ` Move Camera Position
    `W=17
    if (keystate(17)=1)
        Move Camera global_CamID,10.0
    endif
    `S=31
    if (keystate(31)=1)
        Move Camera global_CamID,-10.0
    endif
    `A=30
    if (keystate(30)=1)
        `
    endif
    `D=32
    if (keystate(32)=1)
        `
    endif


    ` Rotate camera on right click
    if mouseclick()=2
        if Global_RightMouseClick = 0
            Global_RightMouseClick = 1
            hide mouse
        endif
        ` keep mouse centered when rotating camera
        position mouse screen width()/2, screen height()/2
        ` Get Current Anlges
        local_CameraAngleX = Camera Angle X(global_CamID)
        local_CameraAngleY = Camera Angle Y(global_CamID)
        ` create a rotation axis based on controller movement
        local_CameraAngleX = WrapValue ( local_CameraAngleX + (local_mmovey) )
        local_CameraAngleY = WrapValue ( local_CameraAngleY + (local_mmovex) )
        ` rotate camera and lock x-axis between 0 and 90
        if ((( local_CameraAngleX >= 0 ) and ( local_CameraAngleX <= 90 )) or (( local_CameraAngleX >= 270 ) and ( local_CameraAngleX < 360 )))
            XRotate Camera global_CamID, local_CameraAngleX
        endif
        
        YRotate Camera global_CamID, local_CameraAngleY
    else
        if mouseclick()=0 and Global_RightMouseClick = 1
            Global_RightMouseClick = 0
            position mouse screen width()/2, screen height()/2                
            show mouse
        endif
    endif
    
    rem keep light at current camera position
    POSITION LIGHT 1,CAMERA POSITION X(global_CamID),CAMERA POSITION Y(global_CamID),CAMERA POSITION Z(global_CamID)    
EndFunction


rem Load in a .obj 3d file
FUNCTION LoadObj(Filename$,ObjectID,ImageID)
    LOCAL local_index,local_index2 AS INTEGER
    LOCAL local_count AS INTEGER
    LOCAL vertex_index AS INTEGER
    LOCAL indice_index AS INTEGER
    LOCAL local_vi AS INTEGER
    LOCAL local_tci AS INTEGER
    LOCAL local_ni AS INTEGER
    LOCAL local_vx AS FLOAT
    LOCAL local_vy AS FLOAT
    LOCAL local_vz AS FLOAT
    LOCAL local_u AS FLOAT
    LOCAL local_v AS FLOAT
    LOCAL local_nx AS FLOAT
    LOCAL local_ny AS FLOAT
    LOCAL local_nz AS FLOAT

    rem store file in memory/array of strings
    OPEN TO READ 1,Filename$
    IF FILE OPEN(1)=1
    
        REPEAT
            READ STRING 1,thisLine$
            
            IF thisLine$<>""
                ADD TO STACK array_string(0)
                local_index = ARRAY COUNT(array_string(0))
                array_string(local_index)=thisLine$
            ENDIF
        
        UNTIL FILE END(1)=1
    ENDIF
    CLOSE FILE 1
    
    local_count = ARRAY COUNT(array_string(0))
    
    FOR local_index=1 TO local_count
        IF UPPER$(LEFT$(array_string(local_index),2))="V "
            ADD TO STACK array_vertex(0)
            local_index2 = ARRAY COUNT(array_vertex(0))
            array_vertex(local_index2).x=GetFloatFromString(array_string(local_index),2)
            array_vertex(local_index2).y=GetFloatFromString(array_string(local_index),gThisStringPosition)
            array_vertex(local_index2).z=GetFloatFromString(array_string(local_index),gThisStringPosition)
        ENDIF
        IF UPPER$(LEFT$(array_string(local_index),3))="VT "
            ADD TO STACK array_texcoord(0)
            local_index2 = ARRAY COUNT(array_texcoord(0))
            array_texcoord(local_index2).u=GetFloatFromString(array_string(local_index),3)
            array_texcoord(local_index2).v=GetFloatFromString(array_string(local_index),gThisStringPosition)
        ENDIF
        IF UPPER$(LEFT$(array_string(local_index),3))="VN "
            ADD TO STACK array_normal(0)
            local_index2 = ARRAY COUNT(array_normal(0))
            array_normal(local_index2).x=GetFloatFromString(array_string(local_index),3)
            array_normal(local_index2).y=GetFloatFromString(array_string(local_index),gThisStringPosition)
            array_normal(local_index2).z=GetFloatFromString(array_string(local_index),gThisStringPosition)
        ENDIF
        IF UPPER$(LEFT$(array_string(local_index),2))="F "
            ADD TO STACK array_face(0)
            local_index2 = ARRAY COUNT(array_face(0))
            gIndiceStep=1 : array_face(local_index2).V1Vertex=GetIntegerFromString(array_string(local_index),2)
            gIndiceStep=2 : array_face(local_index2).V1TexCoord=GetIntegerFromString(array_string(local_index),gThisStringPosition)
            gIndiceStep=3 : array_face(local_index2).V1Normal=GetIntegerFromString(array_string(local_index),gThisStringPosition)
            
            gIndiceStep=1 : array_face(local_index2).V2Vertex=GetIntegerFromString(array_string(local_index),gThisStringPosition)
            gIndiceStep=2 : array_face(local_index2).V2TexCoord=GetIntegerFromString(array_string(local_index),gThisStringPosition)
            gIndiceStep=3 : array_face(local_index2).V2Normal=GetIntegerFromString(array_string(local_index),gThisStringPosition)

            gIndiceStep=1 : array_face(local_index2).V3Vertex=GetIntegerFromString(array_string(local_index),gThisStringPosition)
            gIndiceStep=2 : array_face(local_index2).V3TexCoord=GetIntegerFromString(array_string(local_index),gThisStringPosition)
            gIndiceStep=3 : array_face(local_index2).V3Normal=GetIntegerFromString(array_string(local_index),gThisStringPosition)
            
        ENDIF
    NEXT
    
    gNumberOfVertices=ARRAY COUNT(array_vertex(0))
    gNumberOfFaces=ARRAY COUNT(array_face(0))

    
    rem Build Obj Mesh
    MAKE OBJECT TRIANGLE ObjectID,0,0,0,1,1,0,2,0,0 ` here: triangle coordinates don't matter
    MAKE MESH FROM OBJECT 1, ObjectID
    FOR local_index=1 TO gNumberOfFaces-1
        ADD LIMB ObjectID,local_index,1
    NEXT
    DELETE MESH 1
    MAKE MESH FROM OBJECT 1, ObjectID
    DELETE OBJECT ObjectID
    MAKE OBJECT ObjectID,1,ImageID
    DELETE MESH 1

    indice_index=0
    vertex_index=0
    LOCK VERTEXDATA FOR LIMB ObjectID, 0
        FOR local_index=1 TO gNumberOfFaces

            local_vi=array_face(local_index).V1Vertex
            local_vx=array_vertex(local_vi).x
            local_vy=array_vertex(local_vi).y
            local_vz=array_vertex(local_vi).z
            SET VERTEXDATA POSITION vertex_index,local_vx,local_vy,local_vz
            local_tci=array_face(local_index).V1TexCoord
            IF local_tci>0
                local_u = array_texcoord(local_tci).u
                local_v = array_texcoord(local_tci).v
                SET VERTEXDATA UV vertex_index,0,local_u,-local_v
            ELSE
                SET VERTEXDATA UV vertex_index,0,0    
            ENDIF
            local_ni=array_face(local_index).V1Normal
            IF local_tci>0
                local_nx=array_normal(local_ni).x
                local_ny=array_normal(local_ni).y
                local_nz=array_normal(local_ni).z
                SET VERTEXDATA NORMALS vertex_index,local_nx,local_ny,local_nz
            ELSE
                SET VERTEXDATA NORMALS vertex_index,0,0,0
            ENDIF
            SET INDEXDATA indice_index,vertex_index
            INC vertex_index : INC indice_index    
                        
            local_vi=array_face(local_index).V2Vertex
            local_vx=array_vertex(local_vi).x
            local_vy=array_vertex(local_vi).y
            local_vz=array_vertex(local_vi).z
            SET VERTEXDATA POSITION vertex_index,local_vx,local_vy,local_vz        
            local_tci=array_face(local_index).V2TexCoord
            IF local_tci>0
                local_u = array_texcoord(local_tci).u
                local_v = array_texcoord(local_tci).v
                SET VERTEXDATA UV vertex_index,0,local_u,-local_v
            ELSE
                SET VERTEXDATA UV vertex_index,0,0                    
            ENDIF
            local_ni=array_face(local_index).V2Normal
            IF local_tci>0
                local_nx=array_normal(local_ni).x
                local_ny=array_normal(local_ni).y
                local_nz=array_normal(local_ni).z
                SET VERTEXDATA NORMALS vertex_index,local_nx,local_ny,local_nz
            ELSE
                SET VERTEXDATA NORMALS vertex_index,0,0,0                
            ENDIF
            SET INDEXDATA indice_index,vertex_index
            INC vertex_index : INC indice_index    
                                                
            local_vi=array_face(local_index).V3Vertex
            local_vx=array_vertex(local_vi).x
            local_vy=array_vertex(local_vi).y
            local_vz=array_vertex(local_vi).z
            SET VERTEXDATA POSITION vertex_index,local_vx,local_vy,local_vz    
            local_tci=array_face(local_index).V3TexCoord
            IF local_tci>0
                local_u = array_texcoord(local_tci).u
                local_v = array_texcoord(local_tci).v
                SET VERTEXDATA UV vertex_index,0,local_u,-local_v
            ELSE
                SET VERTEXDATA UV vertex_index,0,0                    
            ENDIF
            local_ni=array_face(local_index).V3Normal
            IF local_tci>0
                local_nx=array_normal(local_ni).x
                local_ny=array_normal(local_ni).y
                local_nz=array_normal(local_ni).z
                SET VERTEXDATA NORMALS vertex_index,local_nx,local_ny,local_nz
            ELSE
                SET VERTEXDATA NORMALS vertex_index,0,0,0                
            ENDIF
            SET INDEXDATA indice_index,vertex_index
            INC vertex_index : INC indice_index        
            

        NEXT
    UNLOCK VERTEXDATA

    CALCULATE OBJECT BOUNDS ObjectID
ENDFUNCTION


rem used to parse a float out of the obj file
FUNCTION GetFloatFromString(thisString$,Position)
    LOCAL local_length AS INTEGER
    LOCAL local_index AS INTEGER
    LOCAL local_done AS INTEGER
    LOCAL local_string AS STRING
    LOCAL local_float AS FLOAT
    
    local_string=""
    local_done=0
    local_length=LEN(thisString$)
    REPEAT
        Position=Position+1
        IF MID$(thisString$,Position)<>" "
            local_string=local_string+MID$(thisString$,Position)
        ELSE
            gThisStringPosition=Position
            local_done=1
        ENDIF
    UNTIL (Position=local_length) OR (local_done=1)
    
    local_float=VAL(local_string)
    
ENDFUNCTION local_float

rem used to parse an integer out of the obj file
FUNCTION GetIntegerFromString(thisString$,Position)
    LOCAL local_length AS INTEGER
    LOCAL local_index AS INTEGER
    LOCAL local_string AS STRING
    LOCAL local_int AS INTEGER
    
    local_string=""
    local_done=0
    local_length=LEN(thisString$)

    rem In case of "f v1/vt1 v2/vt2 v3/vt3 ...", return 0 for normal indice
    IF (gIndiceStep=3)
        IF (Position>=local_length)
            EXITFUNCTION 0
        ELSE
            IF (MID$(thisString$,Position)=" ")
                EXITFUNCTION 0
            ENDIF
        ENDIF
    ENDIF
    
    rem In case of "f v1 v2 v3 v4 ..."
    IF (gIndiceStep=2) AND (MID$(thisString$,Position)=" ")
        gThisStringPosition=Position
        EXITFUNCTION 0
    ENDIF
    
    rem In case of  "f v1//vn1 v2//vn2 v3//vn3 ...", return 0 for texture coordinates indice
    IF (gIndiceStep=2) AND (MID$(thisString$,Position)="/") AND (MID$(thisString$,Position+1)="/")
        gThisStringPosition=Position+1
        EXITFUNCTION 0
    ENDIF
    
    rem if string position > string length then nothing left to process
    IF (Position>=local_length) THEN EXITFUNCTION 0
        
    REPEAT
        Position=Position+1
        IF (MID$(thisString$,Position)<>" ") AND (MID$(thisString$,Position)<>"/")
            local_string=local_string+MID$(thisString$,Position)
        ELSE
            gThisStringPosition=Position
            local_int=VAL(local_string)
            EXITFUNCTION local_int
        ENDIF
    UNTIL Position>=local_length
    gThisStringPosition=Position
    local_int=VAL(local_string)
    
ENDFUNCTION local_int

rem find unused object ID
Function GetNewObjectID()
    ObjectID=0
    repeat
        inc ObjectID
    until object exist(ObjectID)=0
EndFunction ObjectID

rem find unused image ID
Function GetNewImageID()
    imageID=0
    repeat
        inc imageID
    until image exist(imageID)=0
EndFunction imageID