Articles Archive
Articles Search
Director Wiki

Drawing 3D Bar Charts

June 4, 2002
by Will Turnage

In this final installment of the Handyman series on creating different types of charts using Lingo, it makes sense to talk some about creating charts using the 3D capabilities in Director 8.5. This week, you'll learn how to animate some simple 3D bar charts like in the ones in this movie:

First, you should start your movie by creating a list that will contain the data about your chart.

on initChartData

  barChartList = []
  barChartList.append ([#color: rgb (100, 100, 255), height: 100])
  barChartList.append ([#color: rgb (255, 100, 100), height: 75])
  barChartList.append ([#color: rgb (100, 255, 100), height: 120])
  barChartList.append ([#color: rgb (255, 100, 255), height: 50])
  sendAllSprites (#buildBarChart, barChartList)


This handler starts by creating an empty list. Another property list gets added to this empty list. This property list contains two important pieces of information: the color of the bar, and the final height the bar will reach. Once you have finished entering the different information for all of your bars, then you send the list to all sprites using the buildBarChart handler.

The next step is to create a behavior that will be placed on your Shockwave 3D member. This handler starts by initializing the Shockwave 3D member.

property pWorld
property pDataList

on beginSprite me

  pWorld = sprite (me.spriteNum).member
  pWorld.resetWorld ()


When the sprite begins, the Shockwave3D member is assigned to a variable named pWorld. Then, the world resets itself to be completely empty.

Next, you should create the buildBarChart handler inside your behavior. This handler will receive the data and process it.

on buildBarChart me, dataList

  pDataList = dataList
  counter = pDataList.count
  repeat with i = 1 to counter
    tempResource = pWorld.newModelResource ("BarResource" & i, #box)
    tempResource.width = 20
    tempResource.height = 0
    tempResource.length = 20

This handler starts by storing the data passed to it in the pDataList property. Next, you loop through each element in the list and create all of the 3D elements needed for each bar in your completed bar chart. For each bar, the first thing you must create is a modelResource. In this case, you create a box with a width and length of 20 and a height of 0. Next you need to create the model itself as well as the texture and the shaders.

    tempBar = pWorld.newModel ("Bar" & i, tempResource)
    tempImage = image (16, 16, 16)
    tempImage.fill (rect (0 ,0, 16, 16), pDataList[i].color)
    pWorld.newtexture ("barTexture" & i, #fromImageObject, tempImage)
    pWorld.newshader ("barShader" & i, #standard)
    pWorld.shader ("barShader" & i).texture = pWorld.texture ("barTexture" & i)
    repeat with k = 1 to tempBar.shaderList.count
      tempBar.shaderList[k] = pWorld.shader ("barShader" & i)
    end repeat

This part of the handler starts by creating a new model for the bar. It then creates a blank image that is 16x16 pixels in size and fill it with the color that was passed to the handler. Now that you have an image object, you're able to use that object to create a 3D texture. Once the texture is created, then you create a new shader and assign the texture to theshader. Finally, you loop through each side of your box model and assign the new shader to that side of the model.

Alternatively, if you're only going to use flat shading and one shader per model (as we do in the sample) you can simply set the diffuse property of the shader, remove the default texture from the shader's textureList, and set the model's shaderList property with no index value to modify all of the shaders used by the model.

    tempBar.translate (i * 50, 0, 0)
    pDataList[i].addProp (#model, tempBar)
    pDataList[i].addProp (#modelResource, tempResource)
    pDataList[i].addProp (#currentScale, 1)
  end repeat
  timeout ("animateBarChart").new (50, #animateBarChart, me)


You're almost done. The next step is to move your bar model into its located based on its order in the list. Once you've moved the model, then you add the model and the modelResource to pDataList to make things a bit easier later on when you're animating the models. Finally, you add another property called currentScale to your list that will be used to keep track of how your bar chart is animated. When you're finished creating a model for every piece of data in your list, then you need to create a timeout object that will actually animate the bars. That timeout object will execute the animateBarChart handler, which looks like this:

on animateBarChart me

  counter = 1
  repeat while counter <= pDataList.count
    pDataList[counter].currentScale = pDataList[counter].currentScale + 1
    if pDataList[counter].currentScale > pDataList[counter].height then
      pDataList.deleteAt (counter)
      pDataList[counter].modelResource.height = pDataList[counter].currentScale
      pDataList[counter].model.transform.position.y = pDataList[counter].currentScale / 2.0
      counter = counter + 1
    end if
  end repeat
  if pDataList = [] then
    timeout ("animateBarChart").forget ()
  end if


The animateBarChart handler is called every 50 milliseconds, and when it executes, it loops through each model in thepDataList property. You start the handler by incrementing the currentScale property. Then, you check to see if the currentScale property is greater than the final height of the bar. If it is greater, then you delete the model from pDataList. If the currentScale is less than or equal to the final height, then you reset the height of the modelResource to be the value of currentScale. Next, you reset the position of the model to be exactly half of currentScale. The final effect here is that the bar appears to grow up from its original position. The last step is to check your list to see if there are any models left in it. If the list is empty, then you delete the timeout object because your bar graphs are done animating.

Sample Director 8.5 movies (one using Lingo-created textures and one using the diffuse property) are available for download in ZIP or SIT format.

All colorized Lingo code samples have been processed by Dave Mennenoh's brilliant HTMLingo Xtra, available from his site at

Will Turnage is a multimedia programmer based in New York City. In addition to his weekly role as Director Online's Multimedia Handyman, he is also the Technology Director for Sony Music's Client Side Technologies Group. You can read more about his work at

Copyright 1997-2019, Director Online. Article content copyright by respective authors.