Search content:

 

Personal Menu
Username:
Password:
Save password

Become a member

Forgot Password?

 

Don't miss these
EasyBase
Director-3D.com
Store and restore Director objects as an XML string
NJC - Space Invaders
Narration Tool
Moka Xtra
Least Common Denominator
Wait for cuePoint behavior
Setup Anim
Video Status bar
MediaMacros Xtras Mall
 

 

 

Behavior 3D Sprite

Added on 1/31/2000

 

Compatibilities:
D7 D8 Mac PC Script Shockwave

This item has not yet been rated

Author: DaveCole

Rotates a sprite in 3D Requires Dave"s 3D engine The newest version and full example files are always available at http://www.dubbus.com/devnull

-- Dave's Lingo 3D Engine v7.1 FULL - Last Modified 12/14/99
-- Dave Cole - dcole@sigma6.com
-- Special thanks to Terry Schussler of Trevi Media (http://www.trevimedia.com) for optimizations!
--
-- Dave's 3D Engine is Shareware.  If you use this source for commercial gain, you
-- must send a $20 shareware registration fee to:
--
-- Dave Cole
-- 575 Leroy
-- Ferndale, MI 48220
--
--
--
-- Copyright (c) 1998 David Cole
-- All rights reserved.
-- Redistribution and use in source and binary forms are permitted
-- provided that the above copyright notice and this paragraph are
-- duplicated in all such forms and that any documentation,
-- advertising materials, and other materials related to such
-- distribution and use acknowledge that the software was developed
-- by David Cole, as well as that the user, if using this software
-- for financial gain, has paid the $20 shareware registration fee.
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
-- IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
-- WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
--
-- You may freely redistribute this 3D engine so long as the credits and accompanying
-- credits README file remain with the engine at all times.  If you modify it, please
-- annotate notes about your modification and notify me about your changes -- I would
-- like to learn what others can do with this thing!
--
-- The intention of this code is to allow the representation, transformation, and 2D
-- projection and display of 3-dimensional graphics from within a director film.  The
-- interface has been styled loosely after OpenGL for ease of use.
--
-- If this source exists in its original distribution, a manual is available in cast
-- member 3.
--
-- This graphics engine uses a right-handed coordinate system with a view that defaults
-- to looking down the negative z axis from the origin.
--
-- This is the FULL release of Dave's Lingo 3D Engine.  That means that although care
-- has been taken to optimize the routines for speed, the primary intention of this code is
-- to offer a flexibile, accurate, fully-functional 3D graphics system.
--
-- All points use homogenous coordinates.  4x4 Matrices are represented as nested lists:
-- (i.e. [[],[],[],[]]).  1x4 Matrices are represented as a single 4-element list (i.e.
-- [0.0, 0.0, 0.0, 1.0]).  
--
-- *Note: If this engine is removed from its original distribution movie, the lingo below
-- in green can be deleted, all green lingo below is demo-movie specific and not necessary
-- for the 3D Engine to function properly.




--------------------------------------------------------------------------------------------------------
-- Globals  --------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------

global mModelView         -- A 4x4 matrix that represents the current ModelView matrix.
global mProjection        -- A 4x4 matrix that represents the current Projection matrix.
global mModelViewStack    -- A stack of saved ModelView matrices
global mProjectionStack   -- A stack of saved Projection matrices
global mv                 -- 1: Current Matrix Operations performed on ModelView matrix, 0: Current Matrix Ops Performed on Projection Matrix
global point              -- A point datatype for misc. use (in homogenous coordinates)
global xCoefficient       -- used in viewport transformations
global yCoefficient       -- used in viewport transformations
global halffov            -- used to scale sprites accurately
global sortSprites        -- 1: Sprites with a nearer Z value will take a higher # sprite channel (slower)
--                        -- 0: Sprites will stay in their channels (less accurate looking but faster)
global cullBackfaces      -- 1: Cull backfacing quads, 0: don't
global cullBackfaces_cw   -- 1: Clockwise defined vertices determine the front face of a quad, 0: Counterclockwise
--                        -- .. This property only is checked if cullBackfaces = 1
global activateClipping   -- 1: Quads/Sprites are clipped when outside the frustum, 0: no clipping is done
global lookupList
global DWatcher
global DWatcher_newChange
global use3DWatcher

global lightingList       -- a list of lights (format: [uniqueID:[x, y, z, r, g, b]])

global debug              -- Set to 1 to dump tons of debugging information.


global xSlider, ySlider, zSlider, xScale, yScale, zScale, Frustum, rox, roy, roz, roton  -- custom demo program specific


on prepareMovie
  clearGlobals
  
  set mModelView = [[1000, 0, 0, 0], [0, 1000, 0, 0], [0, 0, 1000, 0], [0, 0, 0, 1000]]
  set mProjection = [[1000, 0, 0, 0], [0, 1000, 0, 0], [0, 0, 1000, 0], [0, 0, 0, 1000]]
  
  set activateClipping = 0
  set use3DWatcher = 0
  set cullBackfaces = 1
  set cullBackfaces_cw = 1
  set DWatcher_newChange = 1
  set mModelViewStack = []
  set mProjectionStack = []
  set point = [0, 0, 0, 1.0]
  set lookupList = [:]
  sort lookupList
  set mv = 1
  set sortSprites = 1
  set halffov = 1
  
  set debug = 0                 -- Set to 1 to print tons of debugging info
  ---- custom for-the-demo-only, you can delete this stuff
  set Frustum = 0.8
  set xSlider = 0.0
  set ySlider = 0.0
  set zSlider = -40.0
  
  set xScale = 1.0
  set yScale = 1.0
  set zScale = 1.0
  
  set rox = 0.0
  set roy = 0.0
  set roz = 0.0
  set roton = 1
  ---- end custom for-the-demo-only
  
end

on stopMovie
  set the actorlist = []
end

----------------------------------------------------------------------------------------------------------
--  HIGH-LEVEL ROUTINES  ---------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------

-- xFormPoint takes a 4-element list which defines a point as [x, y, z, w] (homogeneous coordinates) and
-- transforms it into a screen position point in the form of a 3-element list [h, v, z] which represents
-- where on the screen the point should appear after being transformed by the ModelView matrix, the
-- projection matrix, the perspective division, and the viewport transformation.  These are known as the
-- window coordinates.  The z element is returned so that the programmer can illicit depth information
-- about this point.  For more info on this process, research a 3D graphics tutorial near you.
-- 0 is returned if the point is not to be drawn. (i.e. it is outside of the clipping planes.)
on xFormPoint p
  --  if debug then put "xFormPoint--------------"
  --  if debug then put "ModelView: "&RETURN&mModelView
  --  if debug then put "Projection:"&RETURN&mProjection
  --  if debug then put "p = "&p
  set z = getAProp(lookupList, p)
  if z = 0 then
    set m = Matrix1x4Mult(p, mModelView)                    -- Do ModelView xformation
    if debug then put "XFormMV:"&RETURN&m
    if (m <> 0) then set m = Matrix1x4Mult(m, mProjection)  -- Do Projection xformation
    else
      beep
      put "ERROR!:  Point couldn't be converted: "&p
      return 0
    end if
    if debug then put "XFormP:"&RETURN&m
    set m = PerspectiveDivide(m)                            -- Do Perspective division & clipping
    if debug then put "XFormPD:"&RETURN&m
    if (m <> 0) then set m = ViewPortXForm(m)               -- Do viewport transformation
    if debug then put "XFormV:"&RETURN&m
    
    addProp(lookUplist, p, m)
    return m
  else
    return z
  end if
  
end

-- Nudge can be used by a 3DSprite or 3DQuad, or your own custom code, to retrieve the transformed
-- coordinates of a geometry based on the current ModelView matrix without performing any of the
-- projection transformation, perspective division, clipping, or viewport transformations.
-- Useful in multi-step transformations.
on Nudge p
  return(Matrix1x4Mult(p, mModelView))
end

-- pFrustum creates a perspective projection matrix with the viewing frustum volume
-- described by the arguments and multiplies it to the current projection matrix.  It is recommended
-- you call mLoadIdentity before calling this, since its effects are cumulative.  (left, bottom, -near) and
-- (right, top, -near) specify the (x, y, z) coordinates of the lower-left and upper-right corners of the
-- near clipping plane; near and far give the distances from the viewpoint to the near and far clipping planes.
-- near & far should be positive.
on pFrustum left, right, bottom, top, near, far
  lookupList = [:]
  set nn = 2.0*near
  set rl = right - left
  set tb = top - bottom
  set fn = far - near
  set mProjection = [[integer(1000*nn/rl), 0, integer(1000*(right+left)/rl), 0], [0, integer(1000*nn/tb), integer(1000*(top+bottom)/tb), 0], [0, 0, integer(1000*-(far+near)/fn), integer(1000*-(far*nn)/fn)], [0, 0, -1000, 0]]
  set halffov = (1.5708 / abs(atan(float(top) / float(near))))
  return 1  
end

-- pOrtho creates an orthagonal projection matrix with the parallel viewing volume described by the given
-- arguments and multiplies it to the current projection matrix.  It is recommended you call mLoadIdentity before
-- calling this, since its effects are cumulative.  (left, bottom, -near) and (right, top, -near) are mapped to
-- the lower-left and upper-right corners of the viewport window in the near clipping plane.  (left, bottom, -far)
-- and (right, top, -far) are mapped to the lower-left and upper-right corners of the far clipping plane which
-- are also mapped to the same corners of the viewport window.  Both near and far can be positive or negative.
on pOrtho left, right, bottom, top, near, far
  lookUpList = [:]
  set rl = right - left
  set tb = top - bottom
  set fn = far - near
  set mProjection = [[integer(2000/rl), 0, 0, integer(1000*(right+left)/rl)], [0, integer(2000/tb), 0, integer(1000*(top+bottom)/tb)], [0, 0, integer(-200/fn), integer(1000*(far+near)/fn)], [0, 0, 0, 1000]]
  set halffov = -1
  return 1
end



-- pViewPort defines the viewport for the view onto the 3D world.  It defines a pixel rectangle in the
-- window where the final image is mapped.  x and y specify the upper lefthand corner of the viewport,
-- width and height are the size of the viewport rectangle in pixels.  An example use of this would
-- be calling pViewPort(0, 0, windowWidth, windowHeight).
on pViewPort x, y, width, height
  set xCoefficient = (width/2) + x
  set yCoefficient = (height/2) + y
  return 1
end

----------------------------------------------------------------------------------------------------------
--  MATRIX OPERATIONS  -----------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------
-- mSelectMatrix takes either "Projection" or "ModelView" as arguments, and designates the current matrix
-- to have any of the transformations or matrix operations done to it.
on mSelectMatrix arg
  if (arg) = "Projection" then set mv = 0
  else set mv = 1
  return 1
end

-- Push current matrix onto stack, current matrix is a copy of what is on top of the stack until you change it.
on mPush
  if (mv) then
    addAt(mModelViewStack, 1, mModelView)
  else
    addAt(mProjectionStack, 1, mProjection)
  end if
  return 1
end

-- Pop a matrix off the stack, current matrix is now what was on top of the stack
on mPop
  lookUpList = [:]
  if (mv) then
    if count(mModelViewStack) then
      set mModelView = getAt(mModelViewStack, 1)
      deleteAt(mModelViewStack, 1)
    end if
  else
    if count(mProjectionStack) then
      set mProjection = getAt(mProjectionStack, 1)
      deleteAt(mProjectionStack, 1)
    end if
  end if
  return 1
end

-- Load the identity matrix into the current matrix
on mLoadIdentity
  lookupList = [:]
  if (mv) then
    set mModelView = [[1000, 0, 0, 0], [0, 1000, 0, 0], [0, 0, 1000, 0], [0, 0, 0, 1000]]
  else
    set mProjection = [[1000, 0, 0, 0], [0, 1000, 0, 0], [0, 0, 1000, 0], [0, 0, 0, 1000]]
  end if
  return 1
end
---------------------------------------------------------------------------------------------------
--   MODELVIEW TRANSFORMATIONS   ------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
-- MODELING TRANSFORMATIONS:

-- Translate the current matrix by x, y, z
-- Viewing transformations should always preceed modeling transformation in your code.
on xTranslate x, y, z
  lookUpList = [:]
  set m1 = [[1000, 0, 0, integer(1000*x)], [0, 1000, 0, integer(1000*y)], [0, 0, 1000, integer(1000*z)], [0, 0, 0, 1000]]
  set mModelView = Matrix4x4Mult(m1, mModelView)
  if mModelView <> 0 then return 1
  else return 0
end

-- Rotate the current matrix on the X axis by angle (in radians)
-- Viewing transformations should always preceed modeling transformation in your code.
on xRotateX a
  lookUpList = [:]
  set m3 = [[1000, 0, 0, 0], [0, integer(1000*cos(a)), integer(1000*-sin(a)), 0], [0, integer(1000*sin(a)), integer(1000*cos(a)), 0], [0, 0, 0, 1000]]
  set mModelView = Matrix4x4Mult(m3, mModelView)
  if mModelView <> 0 then return 1
  else return 0
end

-- Rotate the current matrix on the Y axis by angle (in radians)
-- Viewing transformations should always preceed modeling transformation in your code.
on xRotateY a
  lookUpList = [:]
  set m4 = [[integer(1000*cos(a)), 0, integer(1000*sin(a)), 0], [0, 1000, 0, 0], [integer(1000*-sin(a)), 0, integer(1000*cos(a)), 0], [0, 0, 0, 1000]]
  set mModelView = Matrix4x4Mult(m4, mModelView)
  if mModelView <> 0 then return 1
  else return 0
end

-- Rotate the current matrix on the Z axis by angle (in radians)
-- Viewing transformations should always preceed modeling transformation in your code.
on xRotateZ a
  lookUpList = [:]
  set m5 = [[integer(1000*cos(a)), integer(1000*-sin(a)), 0, 0], [integer(1000*sin(a)), integer(1000*cos(a)), 0, 0], [0, 0, 1000, 0], [0, 0, 0, 1000]]
  set mModelView = Matrix4x4Mult(m5, mModelView)
  if mModelView <> 0 then return 1
  else return 0
end

-- Scale the current matrix by x, y, z (>1.0 grows, <1.0 shrinks)
-- Viewing transformations should always preceed modeling transformation in your code.
on xScale x, y, z
  lookUpList = [:]
  set m2 = [[integer(1000*x), 0, 0, 0], [0, integer(1000*y), 0, 0], [0, 0, integer(1000*z), 0], [0, 0, 0, 1000]]
  set mModelView = Matrix4x4Mult(m2, mModelView)
  if mModelView <> 0 then return 1
  else return 0
end


-- VIEWING TRANSFORMATIONS: Camera placement routines:

-- pilotView uses the analogy of a plane to position the camera, with the runway at the origin and the
-- plane at coordinates (plane_x, plane_y, plane_z), with a roll, pitch, and heading (in all in degrees)
-- Viewing transformations should always preceed modeling transformation in your code.
on pilotView plane_x, plane_y, plane_z, roll, pitch, heading
  lookUpList = [:]
  set roll = (roll/360.0) * (2.0*PI)
  set pitch = (pitch/360.0) * (2.0*PI)
  set heading = (heading/360.0) * (2.0*PI)
  
  if (xRotateZ(roll) AND xRotateY(pitch) AND xRotateX(heading) AND xTranslate(-plane_x, -plane_y, -plane_z)) then
    return 1
  else
    return 0
  end if
end



-- polarView uses the analogy of a camera orbiting around an object that's centered at the origin, constantly
-- pointing at the origin.  Distance defines the radius of the orbit, azimuth describes the angle of rotation
-- of the camera around the object on the x-y plane, measured from the positive y-axis.  Elevation measures
-- the angle of rotation of the camera in the y-z plane, measured from the positive z-axis.  Twist represents
-- the rotation of the viewing volume around its line of sight.
-- Viewing transformations should always preceed modeling transformation in your code.
on polarView distance, twist, elevation, azimuth
  lookUpList = [:]
  if (xTranslate(0, 0, -distance) AND xRotateZ(-twist) AND xRotateX(-elevation) AND xRotateZ(azimuth)) then
    return 1
  else
    return 0
  end if
end

-----------------------------------------------------------------------------------------------------
-- Utility Routines ---------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
on spawnDWatcher
  set DWatcher = new (script "3DWatcher")
end

on killDWatcher
  repeat while deleteOne(the actorlist, DWatcher)
  end repeat
end

-- isBackfacing determines if, from the given list of transformed vertices and certain environmental variables,
-- a quad's front or back is facing the camera, and returns a 1 if it is backfacing, 0 otherwise.
on isBackfacing vPList
  a = 0
  repeat with i = 0 to 3
    set z = ((i + 1) mod 4)
    set m = i+1
    set n = z+1
    a = a + ((vPList[m][1] * vPList[n][2]) - (vPList[n][1] * vPList[m][2]))
  end repeat
  set a = a/2.0
  if cullBackfaces_cw then
    if a > 0 then return 0
    else return 1
  else
    if a > 0 then return 1
    else return 0
  end if
end


-- zSort sets the locZ properties of the
on zSort listB
  
  put count(listB) into listBCount
  repeat with i = 1 to listBCount
    set vP = listB[i].myVPos
    
    
    if vP <> 0 then
      sprite(listb[i].mySprite).locZ = 1000-(vP[3] * 1000)    
    end if      
  end repeat
  
  return 0
  
end

-- Juggle is an old sprite sorting routine for D6.5 and below.  If you are using D7, use the zSort handler above.
-- It works just like Juggle but doesn't move any sprites around, it instead uses the locZ property and takes one
-- less argument.
on Juggle listB, lowSprite
  global passCtr
  global countlist
  set listA = [:]
  sort listA
  
  put count(listB) into listBCount
  repeat with i = 1 to listBCount
    set vP = the myVPos of getAt(listB, i)
    
    if vP <> 0 then
      
      addProp(listA, getAt(vP, 3), getAt(listB, i))
      
    else
      addProp(listA, 0.0, getAt(listB, i))
      
    end if      
  end repeat
  set countlist = count(lista)
  --sort listA
  --put listA
  set j = 0
  
  put (lowSprite + listBCount - 1) into highSprite
  repeat with i = highSprite down to lowSprite
    set j = j + 1
    set z= getAt(listA, j)
    --    fixScriptInstanceList(z, i)
    
    setSprite(z, i)
    
    set the member of sprite i = the myMember of z  
    set the rect of sprite i = the myRect of z
    set the blend of sprite i = the myBlend of z
    set the ink of sprite i = the myInk of z
    
    
    
    -- backColor, foreColor, editable, moveableSprite, constraint, trails
  end repeat
  
  return 0
  
end



------------------------------------------------------------------------------------------
-- OTHER UTILITY & MATH FUNCTIONS YOU PROBABLY DON'T NEED TO DIRECTLY ACCESS -------------
------------------------------------------------------------------------------------------


-- PerspectiveDivide converts a homogeneous coordinate into a normalized device coordinate.
-- point is a 4 element list.  Returns a 3-element list on success, 0 if the point is not to be drawn.
on PerspectiveDivide thePoint
  
  if count(thePoint) = 4 then
    set w = getAt(thePoint, 4)
    if w <> 0 then
      set x = getAt(thePoint, 1)
      set y = getAt(thePoint, 2)
      set z = getAt(thePoint, 3)
      
      if activateClipping = TRUE then
        case TRUE of
          (z < -w), (z > w), (y < -w), (y > w), (x < -w), (x > w)   : return 0   -- clipping
        end case
      end if
      
      return [x/w, y/w, abs(z/w)]
    else
      return 0
    end if
  else
    return 0
  end if    
end

-- ViewportXForm takes a normalized device coordinate point and transforms it into a
-- window coordinate.  The argument is a 3-element list.  A 3-element list, [h, v, z] is
-- returned on success.  0 if the point is not to be drawn
on ViewportXForm thePoint
  if count(thePoint) = 3 then
    return [(getAt(thePoint, 1) + 1.0) * xCoefficient, (getAt(thePoint, 2) + 1.0) * yCoefficient, getAt(thePoint, 3)]
  else
    return 0
  end if
end

--Useful math functions

-- 4x4 Matrices are defined as nested lists:  [[],[],[],[]]
-- 1x4 Matrices are defined as a 4 element list: [,,,]

on test
  a = [3,3,3,3]
  
  
  starttimer
  repeat with i = 1 to 500000
    set z = getAt(a, 3)
  end repeat
  put the timer
  
  starttimer
  repeat with i = 1 to 500000
    z = a[3]
  end repeat
  put the timer
  
end

--Matrix4x4Mult takes two 4x4 matrices, multiples them and returns the 4x4 result.
-- (Thanks to Jakob Hede Madsen for the optimization!)
on Matrix4x4Mult a, b
  
  a1 = a[1]
  if a1.count - b.count then
    put "Error: Could not multiply matrices, a.cols != b.rows != 4."
    return 0
  end if
  ----
  a2 = a[2]
  a3 = a[3]
  a4 = a[4]
  --
  b1 = b[1]
  b2 = b[2]
  b3 = b[3]
  b4 = b[4]
  --------
  a11 = a1[1]
  a12 = a1[2]
  a13 = a1[3]
  a14 = a1[4]
  --
  a21 = a2[1]
  a22 = a2[2]
  a23 = a2[3]
  a24 = a2[4]
  --
  a31 = a3[1]
  a32 = a3[2]
  a33 = a3[3]
  a34 = a3[4]
  --
  a41 = a4[1]
  a42 = a4[2]
  a43 = a4[3]
  a44 = a4[4]
  ----
  b11 = b1[1]
  b12 = b1[2]
  b13 = b1[3]
  b14 = b1[4]
  --
  b21 = b2[1]
  b22 = b2[2]
  b23 = b2[3]
  b24 = b2[4]
  --
  b31 = b3[1]
  b32 = b3[2]
  b33 = b3[3]
  b34 = b3[4]
  --
  b41 = b4[1]
  b42 = b4[2]
  b43 = b4[3]
  b44 = b4[4]
  ----
  return [¬
[((a11*b11)+(a12*b21)+(a13*b31)+(a14*b41))/1000,¬
((a11*b12)+(a12*b22)+(a13*b32)+(a14*b42))/1000,¬
((a11*b13)+(a12*b23)+(a13*b33)+(a14*b43))/1000,¬
((a11*b14)+(a12*b24)+(a13*b34)+(a14*b44))/1000],¬
[((a21*b11)+(a22*b21)+(a23*b31)+(a24*b41))/1000,¬
((a21*b12)+(a22*b22)+(a23*b32)+(a24*b42))/1000,¬
((a21*b13)+(a22*b23)+(a23*b33)+(a24*b43))/1000,¬
((a21*b14)+(a22*b24)+(a23*b34)+(a24*b44))/1000],¬
[((a31*b11)+(a32*b21)+(a33*b31)+(a34*b41))/1000,¬
((a31*b12)+(a32*b22)+(a33*b32)+(a34*b42))/1000,¬
((a31*b13)+(a32*b23)+(a33*b33)+(a34*b43))/1000,¬
((a31*b14)+(a32*b24)+(a33*b34)+(a34*b44))/1000],¬
[((a41*b11)+(a42*b21)+(a43*b31)+(a44*b41))/1000,¬
((a41*b12)+(a42*b22)+(a43*b32)+(a44*b42))/1000,¬
((a41*b13)+(a42*b23)+(a43*b33)+(a44*b43))/1000,¬
((a41*b14)+(a42*b24)+(a43*b34)+(a44*b44))/1000]]
  
end

--
-- Matrix4x4Mult takes two 4x4 matrices, multiples them and returns the 4x4 result.
--on Matrix4x4Mult a, b
--  
--  if count(a[1]) = count(b) then
--    put a[1][1] into a11
--    put a[2][1] into a21
--    put a[3][1] into a31
--    put a[4][1] into a41
--    put a[1][2] into a12
--    put a[2][2] into a22
--    put a[3][2] into a32
--    put a[4][2] into a42
--    put a[1][3] into a13
--    put a[2][3] into a23
--    put a[3][3] into a33
--    put a[4][3] into a43
--    put a[1][4] into a14
--    put a[2][4] into a24
--    put a[3][4] into a34
--    put a[4][4] into a44
--    put b[1][1] into b11
--    put b[2][1] into b21
--    put b[3][1] into b31
--    put b[4][1] into b41
--    put b[1][2] into b12
--    put b[2][2] into b22
--    put b[3][2] into b32
--    put b[4][2] into b42
--    put b[1][3] into b13
--    put b[2][3] into b23
--    put b[3][3] into b33
--    put b[4][3] into b43
--    put b[1][4] into b14
--    put b[2][4] into b24
--    put b[3][4] into b34
--    put b[4][4] into b44
--    return [¬
--[((a11*b11)+(a12*b21)+(a13*b31)+(a14*b41))/1000,¬
-- ((a11*b12)+(a12*b22)+(a13*b32)+(a14*b42))/1000,¬
-- ((a11*b13)+(a12*b23)+(a13*b33)+(a14*b43))/1000,¬
-- ((a11*b14)+(a12*b24)+(a13*b34)+(a14*b44))/1000],¬
--[((a21*b11)+(a22*b21)+(a23*b31)+(a24*b41))/1000,¬
-- ((a21*b12)+(a22*b22)+(a23*b32)+(a24*b42))/1000,¬
-- ((a21*b13)+(a22*b23)+(a23*b33)+(a24*b43))/1000,¬
-- ((a21*b14)+(a22*b24)+(a23*b34)+(a24*b44))/1000],¬
--[((a31*b11)+(a32*b21)+(a33*b31)+(a34*b41))/1000,¬
-- ((a31*b12)+(a32*b22)+(a33*b32)+(a34*b42))/1000,¬
-- ((a31*b13)+(a32*b23)+(a33*b33)+(a34*b43))/1000,¬
-- ((a31*b14)+(a32*b24)+(a33*b34)+(a34*b44))/1000],¬
--[((a41*b11)+(a42*b21)+(a43*b31)+(a44*b41))/1000,¬
-- ((a41*b12)+(a42*b22)+(a43*b32)+(a44*b42))/1000,¬
-- ((a41*b13)+(a42*b23)+(a43*b33)+(a44*b43))/1000,¬
-- ((a41*b14)+(a42*b24)+(a43*b34)+(a44*b44))/1000]]
--  else
--    put "Error: Could not multiply matrices, a.cols != b.rows != 4."
--    return 0
--  end if
--end

-- Matrix1x4Mult takes a 1x4 matrix as its first argument and a 4x4 matrix as its second argument
-- and multiplies them, returning the resulting 1x4 matrix.
on Matrix1x4Mult c, b
  if count(b[1]) = count(c) then
    a1 = integer(c[1]*1000)
    a2 = integer(c[2]*1000)
    a3 = integer(c[3]*1000)
    a4 = integer(c[4]*1000)
    
    return [¬
((b[1][1]*a1)+(b[1][2]*a2)+(b[1][3]*a3)+(b[1][4]*a4))/100000.0,¬
((b[2][1]*a1)+(b[2][2]*a2)+(b[2][3]*a3)+(b[2][4]*a4))/100000.0,¬
((b[3][1]*a1)+(b[3][2]*a2)+(b[3][3]*a3)+(b[3][4]*a4))/100000.0,¬
((b[4][1]*a1)+(b[4][2]*a2)+(b[4][3]*a3)+(b[4][4]*a4))/100000.0]
  else
    put "Error: Could not multiple matrices, a.cols != b.rows."
    return 0
  end if
end

-- location = x, y, z, intensity = r, g, b
-- creates a light and returns its unique ID in the lightingList
on createLight location, intensity
  set x = count(lightinglist)
  
  lightingList.addProp(x+1, [location[1], location[2], location[3], intensity[1], intensity[2], intensity[3]])
  
  return x
end

-- deletes a light
on deleteLight uniqueID
  lightingList.deleteProp(uniqueID)
end

on deleteAllLights
  lightinglist = [:]
end


on calculateIntensity polygon, lightingList   --, viewPoint
  set x = count(lightingList)
  repeat with i = 1 to x
    
    
    
  end repeat
  if x = 0 then return 0
end


on vGetViewingVector viewPoint, normalTail
  return( [0, 0, 1] )
end

-- vGetH takes the lighting vector and the viewing vector and returns the unit vector halfway between these two.
-- This is cheaper than using the exact reflection vector.
on vGetH l, v
  return vScalarMult(vAdd(l, v)*0.5)
end  

-- vGetReflectionVector takes the normal vector of a surface, n, and the incident lighting vector l,
-- and returns the reflected vector.
on vGetReflectionVector n, l
  return( vSubtract(vScalarMult(n, 2 * vDotProduct(n, l)), l) )
end

-- vGetLightingVector takes the coordinates of a light (4 element list) and a vertex (4 element list) and
-- returns a the lighting vector associated with them.
on vGetLightingVector light, normalTail
  return([light[1] - normalTail[1], light[2] - normalTail[2], light[3] - normalTail[3]])
end

-- vNormal takes three vertices (4 element lists) of a polygon (v2 being "between" v1 and v3) and returns
-- the normal vector to that polygon.
on vNormal v1, v2, v3
  -- convert vertices to two vectors
  nv1 = [v3[1] - v2[1], v3[2] - v2[2], v3[3] - v2[3]]
  nv2 = [v1[1] - v2[1], v1[2] - v2[2], v1[3] - v2[3]]
  -- calculate normal
  return(vCrossProduct(nv1, nv2))
end

-- vCrossProduct takes two vectors (3 element lists each) and returns their cross product (a 3 element list)
on vCrossProduct v, w
  return([v[2]*w[3] - v[3]*w[2], v[3]*w[1] - v[1]*w[3], v[1]*w[2] - v[2]*w[1]])
end

-- vDotProduct takes two vectors (3 element lists each) and returns their dot product
on vDotProduct v, w
  return(v[1]*w[1] + v[2]*w[2] + v[3]*w[3])
end

-- vScalarMult multiplies vector v by a scalar
on vScalarMult v, scalar
  return([v[1] * scalar, v[2] * scalar, v[3] * scalar])
end

-- vNormalize takes a vector and returns the normalize unit vector of that vector
on vNormalize v
  z = vMagnitude(v)
  return([v[1]/float(z[1]), v[2]/float(z[2]), v[3]/float(z[3])])
end

-- vMagnitude takes a vector and returns its magnitude
on vMagnitude v
  return(sqrt((v[1]*v[1] + v[2]*v[2] + v[3]*v[3])))
end

-- vAdd adds one vector to another
on vAdd v, w
  return([v[1] + w[1], v[2] + w[2], v[3] + w[3]])
end

-- vSubtract subtracts one vector from another
on vSubtract v, w
  return([v[1] - w[1], v[2] - w[2], v[3] - w[3]])
end

-- scaleRect takes a rect and scales the size of the rect based on the scalar coefficient
-- returns the new Rect()
on scaleRect oldrect, scalar
  --  set oldh = (the bottom of oldrect) - (the top of oldrect)
  --  set oldw = (the right of oldrect) - (the left of oldrect)
  
  set oldh = the height of oldrect
  set oldw = the width of oldrect
  
  set midw = (oldw/2)+the left of oldrect
  set midh = (oldh/2)+the top of oldrect
  
  set halfh = (scalar * oldh)/2
  set halfw = (scalar * oldw)/2
  
  return(Rect(midw - halfw, midh - halfh, midw + halfw, midh + halfh))
end


-- positionRect positions a rect centered at a point lH, lV
on positionRect oldrect, lH, lV
  
  set oldh2 = (the height of oldrect)/2
  set oldw2 = (the width of oldrect)/2
  
  return(Rect(lH - oldw2, lV - oldh2, lH + oldw2, lV + oldh2))
end

------------------------------------------------------------------------------
-- The functions below aren't used directly in Dave's 3D Engine, but are    --
-- provided for backwards compatibility with previous versions.             --
------------------------------------------------------------------------------

-- acos() - arccosine function (Thanks Hopper-Ex!)
-- takes values between -1 and 1, returns values between 0 and PI
on acos x
  if abs(x) > 1 then
    return 0
  else if x = 0 then
    return 0
  else
    return(atan(sqrt(1.0 - x*x)/float(x)))
  end if
end

-- asin() - arcsine function (Thanks Again Hopper-Ex!)
-- takes values between -1 and 1, returns values between -PI/2.0 and PI/2.0
on asin x
  if abs(x) > 1 then
    return void
  else if x = 1 then
    return(PI/2.0)
  else if x = -1 then
    return(-PI/2.0)
  else
    return atan(float(x)/sqrt(1.0 - x*x))
  end if
end asin


on floatDiv floatA, floatB
  return integer(floatA - 0.5) / integer(floatB - 0.5)
end

 


Upload Provided by ABCUpload ASP

Contact

MMI
22 West Court Sq
Suite 2C
Newnan, GA 30263
USA

Fax - (206) 339-5833

Send e-mail