Neatware Company

An ISV for Mobile, Cloud, and Video Technologies and Software.

Dolphin

Tween and skinning are two kinds of 3D animation techniques. Tween or key frame interpolation technique blends vertex positions or normals with a time parameter. The linear tween generates a new vertice from two vertices v0 and v1 with the formula v0*(1-t) + v1*t (t in [0, 1]). Hermite spline interpolation is a more complex tween technique. The dolphins under the sea used the key frame interpolation.

The Dolphin swimming example is implemented with MCL and vertex shader assembly language. It extended the single dolphin example in the Microsoft DirectX SDK 8.1. The dolphin performs lerp and moves around circular path under the seafloor. The lerp animation is completed by interpolation between three dolphin models. The seafloor is implemented as caustic texture. Two dolphins are rendered by two shaders in sequence.

Dolphin Couple

This example demostrated

  • multi-object with two dolphins and seafloor
  • multi-shader that each object has a vertex shader
  • multi-layer executes shaders in sequence
  • caustic for seafloor environment
  • keyframe interpolation on dolphin lerp
  • matrix transform specifies the motion around of dolphins

To run this example, you need to download the MS DirectX 8.1 SDK.

Now let's study the source code.

package require mcl

This command loaded the mcl package.

proc GetWeight {fBlendWeight} {
  float fWeight1
  float fWeight2
  float fWeight3
  if {fBlendWeight > 0.0} {
    set fWeight1 $fBlendWeight
    set fWeight2 [expr 1.0-fBlendWeight]

    set fWeight3 0.0
  } else {
    set fWeight1 0.0
    set fWeight2 [expr 1.0+fBlendWeight]
    set fWeight3 [expr -fBlendWeight]
  }
  
  return [list $fWeight1 $fWeight2 $fWeight3 0.0]
}

It gets blend weight components for the linear interpolation. Suppose a = fabs(fBlendWeight), if fBlendWeight > 0 then the blend vector is (a, 1-a, 0, 0), otherwise it is (0, 1-a, a, 0).

proc MoveDolphin {n} {
  global app asmShader
  global mat curCausticTexture 

MoveDolphin is a procedure to let dolphins move. The argument n represents the dolphin identification. global command specifies the global variables that may have been defined or used in other procedures. app is the application object. asmShader is the shader object. mat is an array of global variable. Finally, curCausticTexture is the current caustic texture.

  set fTime [$app getTime]
  switch -exact $n {
    0  {  
         float fKickFreq   [expr 3*fTime]
         float fPhase [expr (fTime+3.0)/3.0]
         float fBlendWeight    [expr sin(fKickFreq)]  
       }
    1  {
         float fKickFreq [expr 2*fTime]
         float fPhase [expr fTime/3.0]
         float fBlendWeight [expr sin(fKickFreq)]
       }
  }

[$app getTime] retrives the current time to fTime. The fKickFreq represents the lerp frequency of a dolphin. Since the dolphin 0 has the value 3 multiply the fTime that is bigger than the fKickFreq of dolphin 1 with the value 2, the first dolphin kick faster than second one. The fPhase value sets the initial cycle position. The dolphin lerp with a sin cyclic function.

  MatrixScaling      $mat(Dolphin)   0.01 0.01 0.01




  MatrixRotationZ    $mat(Rotate1)   [expr -cos(fKickFreq)/6.0]
  MatrixMultiply     $mat(Dolphin)   $mat(Dolphin) $mat(Rotate1)
  MatrixRotationY    $mat(Rotate2)   $fPhase
  MatrixMultiply     $mat(Dolphin)   $mat(Dolphin) $mat(Rotate2)
  MatrixTranslation  $mat(Trans)     [expr -5.0*sin(fPhase)] \\
                                     [expr sin(fKickFreq)/2.0] \\
                                     [expr 10.0-10.0*cos(fPhase)]
  MatrixMultiply     $mat(Dolphin)   $mat(Dolphin) $mat(Trans)

The matrix completes following transforms:

M(Dolphin) = Scale(a, b, c)*RotationZ(-cos(freq)/6.0)*RotationY(fPhase)*Translation(x, y, z)

It scales a little bit then rotation around Z and Y and move ahead.

  set curCausticTexture [expr int([$app getTime]*32)%32]

  # Set the vertex shader constants.    
  float4 vZero       [list   0.0    0.0    0.0    0.0]
  float4 vOne        [list   1.0    0.5    0.2    0.05]
  float4 vWeight     [GetWeight   $fBlendWeight]       
  float4 fLight      [list   0.0    1.0    0.0    0.0]
  float4 fDiffuse    [list   1.0    1.0    1.0    1.0]
  float4 fAmbient    [list   0.25   0.25   0.25   0.25]
  float4 fFog        [list   0.5    50.0   [expr 1.0/(50.0-1.0)]  0.0] 
  float4 fCaustics   [list   0.05   0.05   \\
                       [expr sin(fTime)/8.0] [expr cos(fTime)/10.0]]

This code sets the values of vertex shader constants. curCausticTexture is the current Caustic number. Its value is from 0 to 31. vZero and vOne is the constant vector. vWeight is the weight value for interpolation. The fLight, fDiffuse, fAmbient, and fFog are vectors for light, diffuse, ambient, and fog. fCaustics is the caustic vector.

  # set matrix
  MatrixMultiply     $mat(Camera) $mat(Dolphin) $mat(View)
  MatrixMultiply     $mat(Temp) $mat(Camera) $mat(Proj)
  MatrixTranspose    $mat(CameraTranspose) $mat(Camera)
  MatrixTranspose    $mat(Transpose) $mat(Temp)
  MatrixTranspose    $mat(ViewTranspose) $mat(View)
  MatrixTranspose    $mat(ProjTranspose) $mat(Proj)

M(CameraTranspose) = Transpose( M(Dolphin)*M(View) )
M(Transpose) = Transpose( M(Dolphin)*M(View)*mat(Proj) )
M(ViewTranspose) = Transpose( M(View) )
M(ProjTranspose) = Transpose( M(Proj) )

  # set vertex shader constants
  $asmShader($n) vconst 0    $vZero                 1
  $asmShader($n) vconst 1    $vOne                  1
  $asmShader($n) vconst 2    $vWeight               1
  $asmShader($n) vconst 4    $mat(Transpose)        4
  $asmShader($n) vconst 8    $mat(CameraTranspose)  4
  $asmShader($n) vconst 12   $mat(ViewTranspose)    4
  $asmShader($n) vconst 20   $fLight                1
  $asmShader($n) vconst 21   $fDiffuse              1
  $asmShader($n) vconst 22   $fAmbient              1
  $asmShader($n) vconst 23   $fFog                  1
  $asmShader($n) vconst 24   $fCaustics             1
  $asmShader($n) vconst 28   $mat(ProjTranspose)    4
}

This code sets the constants of for each asmShader(n) vertex shader.

proc InitStartup {} {}

This is a required callback function although there is nothing to do inside.

proc FrameMove {} {
  global app mat vfillmode

  if {[$app keyState F]}  {
    if {[string compare $vfillmode wireframe] == 0} {
      set vfillmode  solid
    } else {
      set vfillmode wireframe
    }
    $app setRenderState fillmode $vfillmode
  }
}

FrameMove sets the paramters for each frame. [$app keyState F] checks if the key 'F' is pressed, if it is true the fillmode state will be changed. If current fillmode is solid then the new fillmode will be wireframe. By pressing the F key you can see the wireframe and back from it.

proc Render {} {
  global app asmShader vtShader
  global vbDolphin vbSeafloor
  global mhDolphin mhSeafloor
  global ibDolphin ibSeafloor
  global texDolphin texSeafloor texCaustic
  global curCausticTexture
  global vertice ft water_color
  global nNum mat


  # clear flags color z stencil with water color ARGB
  $app clear {target zbuffer} $water_color 1.0 0
  $app beginScene

Render is a callback funciton to render polygons. Here the global command declares the global variables used inside the Render. [$app clear flags color z stencil] clear the clip plane with target and zbuffer flags. The flags could be a list with elements from . color is a 32-bit value. The water_color has the value 0x00004080 with ARGB (00, 00, 40, 80). z and stencil are float values for zbuffer and stencil respectively.

[$app beginScene] starts the scene.

  for {set h 0} {h < 2} {incr h} {
    # render seafloor and dolphin 0
    MoveDolphin $h

This loop starts render 3 dolphin model to simulat the leap of the dolphins.

    # Render seafloor
    $texSeafloor set 0
    $vtShader(Seafloor) active
    $vbSeafloor stream 0 [$vertice size]
    $ibSeafloor indices 0
    $app drawIndexedPrimitive trianglelist \\
           0 $nNum(SeafloorVertices) 0 $nNum(SeafloorFaces) 

It sets the seafloor texture and active the shader with the stream 0. After setting the indices of index buffer of seafloor with 0, it draws indexed primitive trianglelist.

	  # Render dolphin 0
    $texDolphin($h) set 0
    $vtShader(Dolphin,$h) active
    for {set i 0} {i < 3} {incr i} {
      $vbDolphin($h,$i) stream $i [$vertice size]
    }
    $ibDolphin($h) indices 0
    $app drawIndexedPrimitive trianglelist \\
           0 $nNum(DolphinVertices) 0 $nNum(DolphinFaces)

like seafloor, this code paragraph renders dolphin. Notes that there are 3 streams for each dolphin models.

    # set render state
    $app setRenderState alphablendenable true
    $app setRenderState srcblend srccolor
    $app setRenderState destblend one

It sets the render state with alpha belnd enable, srcblend to be srccolor, and destblend to be one.

    $texCaustic($curCausticTexture) set 0 

    float4 ambientDark {0.0 0.0 0.0 0.0}
    $asmShader(0) vconst 22 $ambientDark 1
    $app setRenderState fogcolor 0x00000000

it sets the ambient dark to shader constant.

    $vtShader(Seafloor2) active 
    $vbSeafloor stream 0 [$vertice size]
    $ibSeafloor indices 0
    $app drawIndexedPrimitive trianglelist \\
           0 $nNum(SeafloorVertices) 0 $nNum(SeafloorFaces)

    # render dolphin 0 again
    $vtShader(Dolphin2,$h) active
    for {set i 0} {i < 3} {incr i} {
      $vbDolphin($h,$i) stream $i [$vertice size]
    }
    $ibDolphin($h) indices 0
    $app drawIndexedPrimitive trianglelist \\
           0 $nNum(DolphinVertices) 0 $nNum(DolphinFaces)

it render seafloor2 and dolphin2 again.

    $app setRenderState alphablendenable false
    $app setRenderState fogcolor $water_color
  }

restore to disable the alphablendenable and set fog color as water color.

  if {[$app showHelp]} {
      set cmdTitle "Keyboard Controls:"
      set cmdOp "Play\nStep\nHelp\nPlay\nFullscreen\nExit"
      set cmdKey  "Enter\nSpace\nF1\nF2\nF5\nEsc"

      $ft(1) draw   2    40   0xFFFFFFFF   $cmdTitle
      $ft(1) draw   20   60   0xFFFFFFFF   $cmdOp
      $ft(1) draw   210  60   0xFF00FFFF   $cmdKey 
      $ft(0) draw   2    0    0xff00ff00   [$app getFrameStats]
      $ft(0) draw   2    20   0xff00ff00   [$app getDeviceStats]
  }

This code shows the help text on the window. ft(0) and ft(1) are two font objects defined in the MCLMain. [$ft(0) draw row col text-color text-string] draws text-string in the row and the col with text-color. [$app getFrameStats] returns a string with the frame rate and windows' width, height, and color depth. [$app getDeviceStats] returns a information string of the video card.

  $app endScene
}

[$app endScene] terminates a scene.


proc InitDeviceObjects {} {
  global app vertice ft
  global asmShader texDolphin texSeafloor texCaustic
  global mhDolphin mhSeafloor
  global vbDolphin vbSeafloor
  global ibDolphin ibSeafloor
  global nNum vertice

InitDeviceObjects starts with the declaration of global variables.

  $ft(0) init
  $ft(1) init

it initializes font objects ft.

  # create asm shader
  set asmShader(0) [$app shader asm]
  set asmShader(1) [$app shader asm]

it creates two assembly shaders.

# create dolphin texture set texDolphin(0) [$asmShader(0) texture "stripe.bmp"] set texDolphin(1) [$asmShader(1) texture "dolphin.bmp"] # create sea floor texture set texSeafloor [$asmShader(0) texture "seafloor.bmp"]

now we create two shaders. Shader 0 includes a texture for Dolphin, Seafloor, and a series of caustic textures. Another shader includes another dolphin texture.

  # create caustic textures
  for {set i 0} {i < 32} {incr i} {
    set fmt [format %02ld $i]
    set texCaustic($i) [$asmShader(0) texture "Caust$fmt.tga"]
  }

texCaustic(i) is the caustic texture object. Caustic is a method to generate a new curve from a given curve and a point. The light rays from the point are reflected from the curve and their envolve forms a new curve.

  # create dolphin meshes
  for {set i 0} {i < 3} {incr i} {
    set mhDolphin(0,$i) [$app mesh "dolphin[expr i+1].x"]
    set mhDolphin(1,$i) [$app mesh "dolphin[expr i+1].x"]
  }

  # create sea floor mesh
  set mhSeafloor [$app mesh "SeaFloor.x"]

it opens the meshes of dolphin and the mesh of seafloor.

  # set FVF
  for {set i 0} {i < 3} {incr i} {
    $mhDolphin(0,$i) setFVF {xyz normal tex1}
    $mhDolphin(1,$i) setFVF {xyz normal tex1}
   }
  $mhSeafloor setFVF {xyz normal tex1}

it sets the FVF of two dolphins and seafloor as {xyz normal text}. Read D3D document to get more details about the FVF.

  # get number of vertices and faces 
  set nNum(DolphinVertices) [$mhDolphin(0,0) getNumVertices]
  set nNum(DolphinFaces) [$mhDolphin(0,0) getNumFaces]  
  set nNum(SeafloorVertices) [$mhSeafloor getNumVertices]
  set nNum(SeafloorFaces) [$mhSeafloor getNumFaces]

get the number of vertices and faces of Dolphin and Seafloor from meshes.

  # create vbuffers
  for {set i 0} {i < 3} {incr i} {
    set vbDolphin(0,$i) [$app vbuffer $nNum(DolphinVertices) \\
                           [$vertice size] writeonly 0 managed]
    set vbDolphin(1,$i) [$app vbuffer $nNum(DolphinVertices) \\
                           [$vertice size] writeonly 0 managed]
  }
  set vbSeafloor [$app vbuffer $nNum(SeafloorVertices) \\
                    [$vertice size] writeonly 0 managed]

it creates 3 vertex buffers for two Dolphins. Seafloor vertex buffer is also created. [$app vbuffer length vstruct usage fvf pool] is the command to create the vbuffer. The length argument specefies the vertice size, vstruct is the vertex structure. The usage is the specification about the vertex buffer usage. The FVF argument specifies the FVF format. When it is 0 the FVF format is ignored. The pool argument describes the way of memory management.

  # create ibuffers 
  set ibDolphin(0) [$app ibuffer [expr {$nNum(DolphinFaces)*3}] \\
                      writeonly index16 managed]
  set ibDolphin(1) [$app ibuffer [expr {$nNum(DolphinFaces)*3}] \\
                      writeonly index16 managed]
  set ibSeafloor [$app ibuffer [expr {$nNum(SeafloorFaces)*3}] \\
                      writeonly index16 managed]

[$app ibuffer length usage format pool] creates index buffers for two Dolphins and Seafloor. The first argument is the byte length of faces. The second argument is the usage of index buffer. The format argument with two possible value index16/index32 specifies the index unit size. The index16/index32 represents the item type is a word (16-bit)/a dword (32-bit) respectively. The pool is method to manage the memory.

  # clone dolphins
  set size [$vertice size]
  for {set i 0} {i < 3} {incr i} {
    $mhDolphin(0,$i) vlock
      $vbDolphin(0,$i) lock 
        $mhDolphin(0,$i) vcopy [$vbDolphin(0,$i) getBuffer] \\
          [expr {$nNum(DolphinVertices)*size}]
      $vbDolphin(0,$i) unlock
    $mhDolphin(0,$i) vunlock
  }

it copies three vertex buffers of dolphins from three Dolphin models .

  for {set i 0} {i < 3} {incr i} {
    $mhDolphin(1,$i) vlock
      $vbDolphin(1,$i) lock 

it locks the vertex buffer of in both the dolphin mesh and the new buffer.

        $mhDolphin(1,$i) vcopy [$vbDolphin(1,$i) getBuffer] \\
          [expr {$nNum(DolphinVertices)*size}]
        $vertice init [$vbDolphin(1,$i) getBuffer]
        float3 pos
        for {set k 0} {k < $nNum(DolphinVertices)} {incr k} {
          set pos [$vertice get position]
          Vec3X+= $pos 100.0
          Vec3Y+= $pos 100.0
          Vec3Z+= $pos 100.0
          $vertice set position $pos
          $vertice next 1
        }

vcopy copies the vertex buffer from a model to a new vertex buffer. [$vertice init ...] sets the vertice struct pointer to the dolphin's buffer. [$vertice get position] gets the position item from the vertice. [Vec3X+= $pos 100.0] added the x component of the vector pos with the float 100.0. [$vertice set position $pos] sets position of vertice as the vector pos. [$vertice next 1] moves the vertice to next position in the buffer.

      $vbDolphin(1,$i) unlock
    $mhDolphin(1,$i) vunlock
  }

it unlocks both the vertex buffer in the mesh of dolphin and the created vertex buffer.

  # set sea floor vertices
  $mhSeafloor vlock
    $vbSeafloor lock
      $mhSeafloor vcopy [$vbSeafloor getBuffer] \\
        [expr {$nNum(SeafloorVertices)*size}]

it clones Seafloor in the way similar to Dolphin. lock seafloor vertex buffers of mesh and new buffer. then copy the buffer.

 
      float3 p
      float2 t
      $vertice init [$vbSeafloor getBuffer]
      for {set i 0} {i < $nNum(SeafloorVertices)} {incr i} {
        set p [$vertice get position]
        set t [$vertice get tex1]       
              
        Vec3X+= $p [expr rand()]
        Vec3Y+= $p [expr rand()]
        Vec3Z+= $p [expr rand()]
        Vec2X*= $t 10
        Vec2Y*= $t 10

        $vertice set position $p
        $vertice set tex1 $t
        $vertice next 1        
      }

modify the position and texture items. The accumulated rand() value generates the sand effects under the sea.

    $vbSeafloor unlock
  $mhSeafloor vunlock

unlock the vbuffer and mesh.

  $mhDolphin(0,0) ilock
    $ibDolphin(0) lock
      $mhDolphin(0,0) icopy [$ibDolphin(0) getBuffer] \\
        [expr {$nNum(DolphinFaces)*3*2}]
    $ibDolphin(0) unlock
  $mhDolphin(0,0) iunlock

it clones index buffer of dolphin(0,0).

  $mhDolphin(1,0) ilock
    $ibDolphin(1) lock
      $mhDolphin(1,0) icopy [$ibDolphin(1) getBuffer] \\
        [expr {$nNum(DolphinFaces)*3*2}]
    $ibDolphin(1) unlock
  $mhDolphin(1,0) iunlock

it colnes index buffer of dolphin(1,0)

  $mhSeafloor ilock
    $ibSeafloor lock
      $mhSeafloor icopy [$ibSeafloor getBuffer] \\
        [expr {$nNum(SeafloorFaces)*3*2}]
    $ibSeafloor unlock
  $mhSeafloor iunlock
}

it clones index buffer of seafloor.

proc RestoreDeviceObjects {} {
  global app ft
  global water_color mat
  global asmShader vtShader

RestoreDeviceObjects will reset matrix and set states.

  # set the transform matrices
  float3 vEyePt     [list 0.0   0.0    -5.0]
  float3 vLookatPt  [list 0.0   0.0     0.0]
  float3 vUpVec     [list 0.0   1.0     0.0]

  set fBackBufferWidth [expr double([$app getBackBufferWidth])]
  set fBackBufferHeight [expr double([$app getBackBufferHeight])]
  float fAspectRatio [expr fBackBufferWidth/fBackBufferHeight]
  MatrixLookAtLH $mat(View) $vEyePt $vLookatPt $vUpVec
  MatrixPerspectiveFovLH $mat(Proj) 60.0 $fAspectRatio 1.0 10000.0

The view matrix mat(View) is generated by vEyePt, vLookatPt, and vUpVec vectors. The perspective matrix mat(Proj) is generated with the field of view angle 60 degree, aspect ratio divided back buffer width by back buffer height, 1.0 as z-value of the near view-plane, and 10000.0 as z-value of the far view-plane.

  # set states
  $app setRenderState lighting false
  $app setRenderState cullmode none

to use the pixel shader requires the disabled lighting. Cullmode specifies how back-facing triangles are culled. none does not cull back faces. cw will cull back faces with clockwise vertices. ccw will cull back faces with counterclockwise vertices

  $app setTextureStageState 0 minfilter linear
  $app setTextureStageState 0 magfilter linear

[$app setTextureStageState 0 minfilter linear] sets the state value for the currently assigned texture 0. minfilter and linear indicate the texture minification linear filter to use when rendering the texture onto surface. magfilter and linear indicate the texture magfication linear filter to use when rendering the texture onto surface.

  $app setRenderState zenable true
  $app setRenderState fogenable true
  $app setRenderState fogcolor $water_color

zenable and fogenable are enabled for zbuffer and fog. The fog color is set to water_color.

  # dolphin decl
  set vtDolphinDecl {{0 float3 0 float3 3 float2 6}
        {1 float3 1 float3 4 float2 7}
        {2 float3 2 float3 5 float2 8}}

it specifies the dolphin declaration.

  set vtShader(Dolphin,0) \\
        [$asmShader(0) vertex "DolphinTween.vsh" $vtDolphinDecl]
  set vtShader(Dolphin2,0) \\
        [$asmShader(0) vertex "DolphinTween2.vsh" $vtDolphinDecl] 

it creates asm vertex shader for dolphin(0) and dolphin2(0).

  # create asm vertex shader for dolphin 1
  set vtShader(Dolphin,1) \\
        [$asmShader(1) vertex "DolphinTween.vsh" $vtDolphinDecl]
  set vtShader(Dolphin2,1) \\
        [$asmShader(1) vertex "DolphinTween2.vsh" $vtDolphinDecl] 

it creates asm vertex shader for dolphin(1) and dolphin2(1).

  # seafloor decl  
  set vtSeafloorDecl { {0 float3 0 float3 3 float2 6} }

  # create asm vertex shader for seafloor
  set vtShader(Seafloor) \\
        [$asmShader(0) vertex "SeaFloor.vsh" $vtSeafloorDecl]
  set vtShader(Seafloor2) \\
        [$asmShader(0) vertex "SeaFloor2.vsh" $vtSeafloorDecl]

it specifies seafloor declaration adn create asm vertex shader for seafloor.

  # restore font
  $ft(0) restore
  $ft(1) restore
}

restore font objects.

#
# InvalidateDeviceObjects
#    close shaders
#
proc InvalidateDeviceObjects {} {
  global ft vtShader

  $vtShader(Dolphin2,1) release
  $vtShader(Dolphin,1) release
  $vtShader(Seafloor2) release
  $vtShader(Seafloor) release
  $vtShader(Dolphin2,0) release
  $vtShader(Dolphin,0) release

  $ft(1) invalidate
  $ft(0) invalidate
}

close vertex shaders and font objects in reverse order.

proc DeleteDeviceObjects {} {
  global ibSeafloor ibDolphin
  global vbSeafloor vbDolphin 
  global mhSeafloor mhDolphin
  global texCaustic texSeafloor texDolphin
  global ft

  # ibuffer
  $ibSeafloor release
  $ibDolphin(1) release
  $ibDolphin(0) release

release index buffers.

  # vbuffer
  $vbSeafloor release
  for {set i 2} {i >= 0} {incr i -1} {
    $vbDolphin(1,$i) release
    $vbDolphin(0,$i) release
  }

release vertex buffers

  # mesh
  $mhSeafloor release
  for {set i 2} {i >= 0} {incr i -1} {
    $mhDolphin(1,$i) release
    $mhDolphin(0,$i) release
  }

release meshes

  # texture
  for {set i 31} {i >= 0} {incr i -1} {
    $texCaustic($i) release
  }
  $texSeafloor release

  # release tex 
  $texDolphin(1) release
  $texDolphin(0) release

release textures

  # font
  $ft(1) delete
  $ft(0) delete
}

delete fonts

proc FinalCleanup {} {
  global ft

  $ft(1) release
  $ft(0) release
}

FinalCleanup released the font objects.

proc curpath {} {
  return [file join [pwd] [file dirname [info script]]]
}

[info script] returns current path of the MCL script. [file dirname ...] retrives the directory from the full path. [pwd] returns the current path. [file join ...] constructs path with components.

  
proc getTexture {fname} {
  return [file join [curpath] .. media texture $fname]
}

it returns a fname in the texture folder media\texture.

proc getXFile {fname} {
  return [file join [curpath] .. media models x $fname]
}

getXFile returns a .x file full path in the media/models/x folder.

proc main {} {
  global app ft vertice

  # create app
  set app [MCL::application]

  # create text font
  set ft(0) [$app font Vertana   10   0]
  set ft(1) [$app font Arial     8     0]

  # create vertice struct decl
  set vertice [MCL::struct {float3 position float3 normal float2 tex1}]

main starts the application. Where app is the application object created with the MCL::application command. [$app font fontType size style] command creates font objects which are used to display the status. [MCL::struct {type name ...}] creates a struct declaration with a list of the items of type and name.

   
  # set required vertex shader version 1.1
  $app version vertex 1 1

[$app version shader major minor] specifies the required shader version. The shader could be vertex or pixel to represent their versions respectively. The code required vertex shader 1.1. If the hardware supports that version the accelerator will be used. Otherwise the software vertex shader will be used or returns failed. No pixel shader used in this example.

  # run
  $app create 
  $app run
}

[$app create] opens an application window and initializes the application through RestoreDeviceObjects. [$app run] starts the message loop of the window.

set PI 3.1415926535897932384626
set vfillmode solid
set water_color 0x00004080
set count 0

Set global constants. PI is the standard constant. vfillmode is used to display wireframe or real shading. water_color names a color value.

matrix mat(World)
matrix mat(View)
matrix mat(Proj)

creates global matrix. mat(World), matr(View), and mat(Proj) are for world, view, and perspective transforms.

matrix mat(Dolphin) 
matrix mat(Trans)
matrix mat(Rotate1)
matrix mat(Rotate2)

matrix mat(Temp)
matrix mat(Camera) 
matrix mat(Transpose) 
matrix mat(CameraTranspose)
matrix mat(ViewTranspose)
matrix mat(ProjTranspose)

these matrix are declared as global to avoid the cost of creation.

main
exit 0

main starts the application. exit 0 will terminate the application.

Future Sea World Project

  • Different kinds of fishes
  • Swimming in different paths
  • Lights under sea