Who Am I?

My photo
Toney, Alabama, United States
Software Engineer, Systems Analyst, XML/X3D/VRML97 Designer, Consultant, Musician, Composer, Writer

Saturday, March 17, 2007

Walking Kamala

This installment begins with the philosophical background of the River of Life. Good games or stories need a back story: the history of a character including the history of the character’s culture, family, and most importantly the choices the character has made that reveal and create character. If I find fault with some 3D On the Web, it is the lack of any depth to the story or the lack of a story at all.

It is technically easy to create a heads-up display with a gun sticking out of it that can shoot gazeeks from Gazorp, or undresses a buff but slightly anorexic body somewhere between Paris Hilton and her next scandal. Anyone can build that. Any fast igniter can start a fire but it takes an axe and a strong arm to get fuel that lasts because passion without knowledge is fire without fuel. To write a good story, one becomes a good researcher and roams far and wide to read and observe. You can only write “Love Me Do” once, then you need to start finding out why.


Watch. Listen. Remember. Play. Let the story inform the act and the art.


The Lord of the Dance


The power of the game is that playing the game can change the player. The dance can change the dancer. The song can change the singer. Without this impetus to change, games are little more than finger exercises because the only result of playing them beyond distraction from the moment is faster reflexes. There is nothing wrong with the distraction of entertainment, but the unrealized power of passion harnessed to the evolution of the player is a goal worthy of disciplined effort. In this section, before we walk with Kamala, I provide the back story of a philosophy that informs my conception of the River of Life.

You may skip past this and go on to the code, but in my humble opinion, the great game artists and world builders will be the great storytellers. Rhythm and complexity of progression make for great music, but it is the story in the lyric that makes mind and heart reach beyond the moment into the possible. That reaching is the very essence of human evolution. 3D games and worlds are tools of self-directed evolution as in fact, are all tools.

Serendipity


It is said that serendipity is a happy accident. There are no accidents. It is my experience that serendipity is the outcome of happy choices that lead to happy if unpredicted ends. One of my favorite sayings for events that lead to some happy or unhappy outcome is from a Dutch story about a man who had a chauvinistic but wise way of treating his bride.

As the twig is bent, so grows the tree.


The choices we make in the beginning create or dispel the choices we make later. The path is free but self-circumscribed. Finite space has infinite choice, but as with the chicken crossing the road, our legs are only so long and can only move so fast. They move faster if they have to but we can choose those circumstances. Where we cannot choose the circumstance, we can choose our actions in response to the limits of our skill, knowledge and intuition and if we choose wisely, these grow in strength such that we gain more choices and choose even more wisely. Life may be infinitely diverse, but we walk the path in finite time with linear choices. Free will is the act of choosing our own choices. Responsibility is the act of accepting the consequences of free will.

Chaos, Complexity, and Learning


Chaos theory and complexity theory describe the sensitivity of outcomes to initial conditions, the so-called Butterfly Effect. The idea is that a small change in the value of initial conditions has huge effects some number of iterations later, but the actual engine of that effect is feedback where the outputs of a process are routed back into the inputs as if you take a microphone or an electric guitar, turn up the volume and put the pickups next to the amplifier speaker. This is uncontrolled feedback if you don’t adjust the distance or mute the strings. If you do, you can create notes that sustain. If you don’t, you blow up the speakers and some eardrums, likely, yours.

You choose. The principle of compounding choice is the concept behind all complexity theory.

So, we see that feedback is not the only principle of evolving complexity and emergent effects. In a self-regulating system, the signal being fed back is measured and the flow is adjusted in real time. This immediate awareness of the signal with the ability to adjust it controls the evolution of the sound by recognizing the signal components, then modifying them repeatedly toward some desired state of being. In behavioral psychology, this is referred to as shaping behavior or behavioral modification. Behaviorists do not attempt to explain the control mechanisms beyond a stimulus/response model where rewards may be positive or negative reinforcement of a specific behavior which by observation and control can be chained to another behavior to create self-reinforcing behavioral sequence.

To study the theories of the evolution of motivational controls, you study cognitive psychology.

In evolving systems, while the signal or behavior is changed, it is the control that evolves. There is a computer science concept for this called ‘second order cybernetics’. Systems feedback changes in values to processes that amplify and/or measure those values, then feed them back again and modify the controls over the changes thus controlling the evolution of the system through measurements of the effects of change. Thus the sensation of self-aware consciousness emerges as controls over change through recognition then measurement and modification.

The mystery is the source of the desire to choose the goal. Cybernetics is silent on this question. Here science can not predict well nor test nor prove. Yet stories can and do because stories can illustrate and comment on our desires. Our emotions are the signals to self and other of our acceptance or refusal of the outcomes of our acts in accordance with our need to satisfy our desires. Two easily recognized signals of our emotions are the rate and depth of our breathing.

Desire is the maker. Desire is the destroyer. – Bhagavad Gita


The Lord of Beginnings


In the Hindu religion, a divinity named Lord Ganesha is the god of beginnings. Hindus pray to this divinity at the beginning of a journey that their choices may be well-considered and right for all that they will change by their choices.


Mystics describe the etheric body where all of life’s experiences are stored in a type of holographic template and from the template, lost souls create a world of their own perceptions that is located in the living world but to them is of their lost world; thus, the haunted see the past in the present, and the haunting see the present in the future. The divine dance is one of intertwining intent and desire mixing with memory and habit in constant motion such that all one might say really exists is motion itself.



The Wind and The Water


Except that there is more than motion. That is the water in motion. There is also rhythm, the repetition of breath in metric time or beats. The soul of the rhythm of the river is the wind on the water. The expression is the sound of water driven by wind and currents beating on the shores to shape the land and change the rhythm as the shores change shape. This can be thought of as the dance of wind and water that with the shaping of the land becomes a river.

The outward movement of motion as act from inner being into the world is emotion. Emotion is the true language of the human and the gods of old Bharata. Emotion is where the divine becomes human and the human, divine. Emotion shapes us and makes of us what we become by signaling our desire to self and other as the wind changes the water and the water shapes the land. We are the river of life, constrained by an ever changing shore but eternally in motion. We express this in our arts and in our treatment of self and other.

Those familiar with Hindu music know the ragas, the tonal scales, are intertwined with the talas, the divisions of beat in metric time. Each raga is a mood and combined with the tala has an appropriate time of day. Thus, RagaNataBharavi: a raga, Bharvav, played in the early evening to set a mood that is a little sad and yet mysterious with the possibility of change, of romance, of love. Indian music considers the potential in the moment and has power over the emotions of the listener not matched in Western compositions.

When we play and dance, our emotions are the wind blowing across the waters of other souls whose shores are shaped by their responses and their inner desires to be other than they are at the moment our emotions touch the many surfaces of their hearts in motion.



In Hindu mythology, the dancing god, Shiva the Nataraja, represents this manifesting potential in all things. Shiva is the first dancer. Shiva is the Lord of the Cosmic Dance of creation, preservation and death and is felt as the physical force of rhythm. Shiva dances in the heaven of Indra, Lord of Rain. As Shiva dances, the rain falls to fill the rivers of life.

The Divine Vehicle


For all the text and mystery of other worlds and gods, the Hindu religion is conjugal. Sex is the creative power of worship and the Hindu embraces sex for this purpose beyond fleeting pleasure and without the need to make of it something less worthy or trivial as it is in the West. The feminine force is the power of creativity and the manifestation of God in the flesh and Earth. Without the feminine force, there is no life and without life, there is no evolution. To trivialize sex is to trivialize the feminine and deny life’s powerful expression or to destroy it. To trivialize a woman is to lose all that human evolution has gained through a million and more years of refusal and acceptance.

To destroy a woman’s love is to blind God.

Love and devotion are all important. Love without duty is not love at all. Devotion without pleasure is not life. Love is the divine vehicle on the river of life wherein rides the mahatma, the great soul of human evolution expressed most purely in the love of a woman for family and God.


Dharme cha. Artha cha. Kamme cha. Natticharami.
With you in duty. With you in wealth. With you in pleasure. Always with you.
- Hindu wedding vow. -


The Dance of Love


The first female dancer is Lakshmi, wife of Vishnu. Lakshmi is the goddess of wealth and beauty. She is considered in some texts, the goddess of classical dance and it was she who taught humanity to dance. Krishna, the divine flute player, dances with his consort, Radha, beneath the moon attended by enamored maidens. Radha is human emotion and this dance and music call the human soul to God by freeing it of earthly attachment to unnecessary suffering or desire. When free of attachments, a soul returns to the one source to be reborn or remains knowing only then its true nature as One God Called By Many Names.

To learn to dance or to play music is to discipline the emotions, to lead a disciplined life, and ultimately to know God by the practice of music and dance as worship.

Throughout Hindu literature is the concept that the rhythm of life in all forms, from dance to music, the spoken word and nature, the sound of wind and rain, of sorrow and joy all these emanate from one source which is the universal consciousness of God. In this sense, all life is the radiation of a single life, and in each life all life is found. This idea of the many in the one and the one in the many finds expression not only in art but in science as well.

There are scientific theories that claim the universe we experience is itself a very complex very large hologram where every part of it can be found in the smallest part reminiscent of the mystic saying, “As Above, so Below.”. The Hindu knows this in prayers when chanting OM, the spoken symbol of breath, peace, eternity and even Lord Ganesha. The prayer or chant begins and ends with this single syllable that contains all of creation within it.

“You can understand everything about music by understanding one note.” Pandit Ravi Shankar


Binding the Soul of the Dancer


Wherever the river of life goes, whatever the woman on the bridge is, they are made of a long circuitous journey of research and reflection on Hindu teachings, Bollywood movies, and thoughts on love and loss, or ‘binding one’s soul to the eyes of a woman”.



I am not Hindu. One is born to that. I saw marvelous faith and a wonderful light in the beguiling eyes of a Hindu lady and surrendered to the need to understand that faith and that light because as an artist, it is as Keats wrote, “Beauty is all you know. It is all you need know.” And then I changed.

The Devadasi


The sad-eyed babe on the bridge is Kamala. She is a devadasi. It means, ‘female servant of God’. Wikipedia describes the devadasi thus


A Devadasi is a Hindu temple priestess who performs ritualistic dances and songs, primarily to please the gods in a temple's "Sanctum Sanctorum" (inner sanctum), but also to help the temple worshippers elevate their consciousness. She is considered to be married to the divinity of the temple….


Some texts say the devadasi were originally female priestesses of Buddhist temples forced to become temple dancers by the rise to power of the Brahmin caste who they served as both entertainers and sexual playmates.



Originally the lovers of the caste wealthy, over time their role became one of prostitution to anyone who could pay the price of their mistress; so, they became much like the modern call girl but with extraordinary talents as artists. They could have one patron, but still entertain other men as long as the patron was pre-eminent in their time and affections. Faithfulness is not an act of sexual exclusivity nor faithlessness an act of promiscuity, but of devotion and duty or abandonment and lust.



Other texts say the devadasi were celibate (brahmacharya) until the time of the rajadasi when the devadasi were made to dance in the royal palaces to entertain the royal class where their art was transformed from one of worship to one of seduction which as any entertainer can attest, is an easy transformation. Worship is the act of love. Whether for the divine or the mortal, faithful love transforms the beloved and is the path of ascendance for the lover.




Wikipedia goes on to say


A devadasi had to satisfy her own soul while she danced unwatched and offered herself to the god, but the rajadasi's dance was meant to be an entertainment.


The devadasi of old were trained in the arts of the dance, songs, poetry and love. They were prized above all women and often above the wives of the royals to the sorrow of the dancers. They were shrewd, powerful women in their own way because they could mark a man or a woman as no other woman could and capture their heart for life even if they were passed on as seedcake is passed. They were not forgotten, they were deeply mourned, and they are enshrined on the temples of old India.

The Transformation


There is a historical story of a devadasi so gifted that she became sharii: a master poet. This was uncommon because it was believed only men possessed such insight into the worlds of spirit and earth. Her name was, Amiran, renamed Umrao Jann by her mistress and she lived in India in the time when the old rajas were overcome by the British. There is a very famous Bollywood movie by that name starring an even more famous Indian actress, Rekkha Ganesan who portrays the sad eyed Umrao.



“Umrao Jann” was the first Bollywood movie I saw. It was recommended to me by a friend, one Alka C. Singh. If you pay attention to the credits for ROL, you will note that it is dedicated to Alka. A fastidious devoted Hindu lady, the faithful wife of Mohinder Singh, Alka pointed the way to the journey through Hindu thought and belief that brought me to create ROL.

For the marvelous faith that she so completely exemplified and the wonderful light in her face that I came to love so deeply, The River of Life is dedicated to Alka whom I have not seen for many years but will not forget. I treasure her marvelous faith and the wonderful light that shows through it because it transformed me

… painfully but assuredly.

In any journey, we will meet and pass other souls. If we listen and if we pay the price of knowledge which is suffering, we can transform ourselves into better people just as Amiran became Umrao, not by her own choosing of her path but by choosing how she would treat each soul she encountered on the path chosen for her. She suffered for her love but she did not betray her love. Originally a Hindu country girl, life and discipline made of her the sad but most powerfully expressive poet of her time. She was the Rose in the garden of old Bharata.

The seed of a flower must come from the ground; the seedcake is made by deliberation and well-considered choices of ingredients and preparation. Then it is given to all who will eat and if made well, it will transform them.

Shukriya, Alka ji. Namaste.


The Hotei


I, by happy choice, am a Hotei. In the generations of Buddha, a Hotei is a happy mendicant who makes toys for children out of the little bits of junk he finds on his journey. He is the so-called Laughing Buddha sometimes confused with the first Buddha but historically a Buddhist priest some generations later. Often depicted sitting with a smile and a fat belly, or standing and laughing with his hands over his head, statues of this Buddha are easily contrasted with the austere Gautama, the first Buddha, who sits serenely, eyes closed, in the classic lotus position for meditation.




A Hotei is the Buddha of this world, joyful, laughing without care even if without money, and always willing to make toys for children, to give candy, and to make of life a celebration of life in this world even while preparing for the next. He begs for food without humiliation, but asks that you dine with him in mirth and celebration of the gift. He shares without fear of loss because he owns nothing and gives all without regard to the gift returned. It is a philosophy the Hindu shares. To the Hindu, a gift must be given without thought of reward or it is no gift at all, merely a bribe. The desire for reward robs the transformative power of the act of love.

We may live in fear that our next breath will be our last, because we know that to each, death will come. Yet, between each breath, there is an infinitesimal moment to choose fear or joy. The Hotei chooses joy. For the breath that has come cannot be taken away, and the breath that comes cannot be held until it comes, and for all our will and strength and purpose, breath can not be held for long. Even to make the attempt is to deny the breath that comes and make worthless the breath one holds, to in fact, deny life through fear of death. A Hotei’s joy is love given by an open hand held high to life one breath at a time. Such a love cannot be asked; it must be chosen, as the lover chooses the beloved, and the beloved accepts or refuses this choice.

The Bhagavad Gita teaches the threefold faith. Acts of giving can be offered to the unworthy or for gain for the giver, given darkly for power or revenge, or given without any thought of reward. Only the third gift is of divine origin. It is often hard to understand, but the gift given without thought of reward is the transformative gift, the gift that has the power to change us simply by the nature of the act. To give up self, is to give up suffering. To give up self for other is to feel divine joy by accepting surrender to the love of God. This is bliss. To refuse this gift or to deny it to others is to suffer the greatest torment there is: to be alone, to be separate from love, to be separate from God.

That to which the worshipper offers devotion, he lives assimilate. – Bhagavad Gita


The Dance of Serendipity


Kamala is a serendipitous outcome of all of my choices. One part Bollywood, one part faith, her sad face is the face of Rekkha Ganesan, but her sad heart is somehow mine and somehow the heart of the tales of the devadasi who once attended the shrines of the Buddha, but found themselves dedicating their wonderful talents to the service of the Brahmin and the rajas, and from that, came beautiful sad songs of love’s loss, of innocence mourned, and of the sweet seedcake of love’s offering and acceptance or refusal. Kamala is a happy outcome of my journey to this understanding of breath and light.

Kamala is made of the mythic world of the river of life. She lives in an age long ago and now that always exists and has never existed. All we know about her we learn by walking with her and seeing what she sees where she goes feeling what she feels until the rains of compassion at last wash the sorrow from her eyes… and perhaps our own.



We create what we believe. We believe what we create. We become what we believe. Dharma, artha, and kama are inseparable karma.

To be inseparable with another in these is to love truly and completely. When we meet our twin soul, we change. When we meet our soul mate, we ascend. To believe this is shraddha, the marvelous faith.

Om shanti. Om shanti. Om shanti Om.


Let’s meet our sad-eyed divine dancer, Kamala, a devadasi on the River of Life.

Wednesday, March 14, 2007

A Public Service Announcement

We would like to pause from our regularly scheduled blog for a message from our station manager on behalf of the owners and operators of this blog.

Good evening. On behalf of the management and staff of this blog, I'd like to say a few words in response to public inquiries about the title, tenor and tone of this blog. The idea that CHEAP!! 3D indicates the quality, class, glamour and sexyness of the products of the VRML/X3D community are less than that of similar brands found elsewhere is a misunderstanding. This is not our intent and is not the meaning of our message.

CHEAP!! is our way of saying *accesible to all comers*. Getting into the 3D game market should not require that a young person or an old person give us their college tuition to buy a copy of 3D Max or sell the family dog. High quality content comes of the passion of the author, not the classiness and certainly not the cost of the toolkits.

The VRML/X3D community continues to offer its products in the same spirit as Bill Gaines offered Mad Magazine: for what you get, the price is STILL CHEAP!

In the beginning, the web was not created by the market plans of big companies. It was not financed by the major venture capital funds. It was not regulated into existence, and it was barely and badly designed. What it had was the passion, time, commitment and cheap free software created by a generation of college kids and teenagers charged up on Jolt Cola, big coffee, big dreams, and a lot of cheap pizza.

It is the policy of the management and staff of this blog that 3D is to the kids of today what rock n' roll was to the flower power children of the 60s. It is their mode of powerful and surreal expression. It it their thing, not our thing. The best we can do is hold a door open for them and let them go up that stairway to heaven behind it. Then get off the stage.

They need their own thing, not our thing. 3D is their thing.

There is heart in that. As the long tongued devil band KISS sang to us, "God gave rock n' roll to you. Put it in the soul of everyone!"

They need their easy lick cheap trick painted prophets too, and for them, it is games, virtual reality, and CHEAP 3D. Why? Because for the young, these are the terms they understand and can afford. Same as it was for us. Same as it always is in the beginning of a powerful art.

Pick up your prize.

Thank you for listening. We return you now to the regularly scheduled blog.

Tuesday, March 13, 2007

Rolling On The River

At this point, most of you will be in one of two camps:

a) That’s trivial and easy. Anyone can do that.

b) That’s hard. I don’t get it. I’ll never be able to do that.

Both camps are right and both camps are wrong. It does take practice to learn the basics of VRML. Then there is X3D which is a step up, but also a bit more complex in terms of multiple encodings and some nasty syntax surprises. On the other hand, VRML/X3D are in the sweet spot between lower level languages like OpenGL which are very powerful but much closer to the metal and require a considerable technical grasp of graphics programming and the higher level languages such as 3DML designed to do a few things well but at the cost of freedom of expression so not very powerful.

In other camps are the closed-system proprietary languages such as are used in platform implementations such as Second Life. These provide tools for building in-world or a virtual economy, so once in, you can make some money. On the other hand, you get to do what Linden Labs wants you to do and regardless of the intellectual property policy that says what you create there, you own, you can’t take it with you anywhere else so it is like owning your own baggage in the Greyhound lines terminal. It may go from bus stop to bus stop but you can’t take it home.

VRML/X3D is designed not to be the fastest language or the easiest to learn, but to sit somewhere in between as the open language for royalty-free (say CHEAP!) 3D on The Web. If you are in the second camp, I assure you that I am not a graphics programmer, I am not a graduate student, and I don’t own a company trying to sell you graphics games or standards. I have a degree in English and Music, am a performing musician, have been a technical writer and self-taught programmer for various companies, am a technical consultant now, and have done some standards work in a former life.

If I can do this, you can do this. It ain’t rocket science. I live in the town where the original rocket scientists live. I say with complete certainty this ain’t THAT hard or that expensive.

If you are in the first camp, then show me yours. I’m showing you mine. Some people want to go to Valhalla and demand to be recognized. But you can only cross the Rainbow Bridge with heads in your pelt or your head in someone else’s pelt.

Build and show or shut up.

So on to the examples.

Begin At The Beginning



To begin at the beginning is to create an entry point in your world or story. In VRML, this is the first Viewpoint on the stack, the first thing the user will see when the world opens, and the first opportunity you have to acquaint the user with your intentions. Get this right and what follows is easy. Get this wrong and what follows is unpredictable.

"The Sims" creator, Will Wright, makes an excellent point about building games that applies to our journey and is similar to Glenda’s advice to Dorothy in the Wizard of Oz.

Wright’s most excellent advice is that the first view should entail a task or puzzle that teaches the user how to navigate. Then increase the problems to solve slowly so that by the time they have done the first three or four, they are masters of the user interface.

Those of us who like games or 3D worlds are so proficient with the mouse that we automatically press the left button and push. Not surprisingly, this simple motion confuses the heck out of lots of otherwise well-educated adults if not most children. Couple this to the need to have that first motion result in an experience that explains the topic of this story and you realize that you have to combine your storytelling artistry with your technical VRML chops and come up with an object that does both easily.

  • Keep it simple. Make it easy to recognize and easier to do.
  • Simplicity and ease for the user means more work for you.
  • Make it fit the story. The story is your friend. It will suggest to you what you need to build if you listen. If what you build doesn’t fit the story, it doesn’t work. Like bad acting, if the audience can spot your acting chops, you failed.

    In other words, don’t under rate obviousness and don’t over rate cleverness. An early game pioneer once remarked, “We consistently overestimated their intelligence and underestimated their manual dexterity.” People aren’t really stupid. Don’t assume that. They sometimes aren’t patient. That’s reliable. Entertain them.

    The code in these examples comes from my VRML world, The River of Life (ROL after this), a story of a devadasi or temple dancer in a mythical version of old Bharata (India). Many a river journey begins with boat at a dock by the river.

    That’s obvious. The instructions for ROL can be summarized as:

  • Get on the boat.
  • Follow the babe.
  • Click on things that move or things that interest the babe.
  • If you get lost or bored, find the babe.
  • If you find the wrong babe, bad things happen. Just like life.

    ROL opens with a title screen with an animated psychedelic background and scrolling credits.



    As I said in the last tutorial, library code is the key to productivity. The success of VRML is based on the fact that code written ten years ago still works. The title 3D text was created with Flux Studio. The background is a piece of code from Robert St John distributed with the old V-Realm Builder VRML editor.

    After the credits complete, a single line of red text asks the user to click on the title to open the world. Most of us can do that. If they watch the credits, good. The next world is loading in the background. If they don’t, ok. The world will just appear to take longer to load. The credits are a side show. The opening view of ROL is shown here.



    The boat and the dock were created with Parallel Graphics Internet Scene Builder (ISB) free demo. CHEAP!!

    Note that this world has an automatic sky proto provided from an online PROTO library. It checks the time on your computer and more or less matches the virtual time of day of your local machine minus the weather conditions. In theory, one could do both but that is beyond this tutorial. However, it points out one reason to become a proficient scripter. Some of the sequences have to work in day or night conditions, and a changing background has surprising effects on renderings of objects such as text. I’ll demonstrate this.

    Some people believe an author should put text instructions at every step as if the user were building a kitchen cabinet from a kit. If possible, I prefer to minimize imperative instructions and big overview maps. They destroy immersion. A user should be able to get lost. That’s part of the fun. Remember, this is a computer medium but not of necessity, a computer application like a spreadsheet. This is for fun and some cerebral exercise maybe, but not to keep your books or your photos or your FaveFive in. Use your cell phone for that, ok?

    On the other hand, VRML worlds are sometimes referred to as ‘free roamers’. Unlike games that are maze-driven, a VRML world usually enables you to go wherever you want once you enter the world. This is much more like Second Life than Myst. So it is up to the author to use their story telling skills, graphics skills, and programming skills to encourage the user to follow a pre-defined path of discovery. As we go through this example, I will point out some design decisions I made to encourage the user to choose to follow the story.

    At the dock, the user can either get on the boat or wander off to roam. If they skip the boat, they won’t see some information that provides clues. There will be other entry points into the story, but if they miss the boat, some of those clues will be missed. To get on the boat, they have to get through the dock and to do that, they have to learn to push the mouse and turn.

    Story telling in a free-roamer can be cinematic (single path) or like a game (multi-path) but the cost of the extremes of the former is boredom played once, and the costs in the latter to create the separate converging and diverging paths to get to the end state of the story/game (IF THERE IS ONE) are your time and maybe the loss of the user’s attention.

    We’ll come back to this in another tutorial and discuss really abstract make-your-eyes-glaze-over (MYEGO) topics such as path metrics for complexity ratings that differentiate genre of 3D applications (Give me a grant for that one, Mr. MacArthur!). For now, remember that every multiple choice situation exponentially raises the costs of completing the world for you and the user. In English,

    The more you offer, the longer it takes to choose, the more it takes to provide the choices.

    As Rita Turkowski says, “Baby steps, baby steps, baby steps.”

    Take the Ride



    If the user gets through the dock and steps on the boat, the boat takes over and a little show begins consisting of a ghost floating up out of the river, flying eyes that “flash at the sound of lies”, some excellent Hindi movie music and flaming text. This is our first sequence. It is completely automatic. The user should relax, read the text, and enjoy the ride.



    As I said, to make this easy for the user, you have to write some code. In this sequence, all of that code is located in the boat.wrl file.

    Did I tell you that VRML files conventionally have wrl file extensions unless compressed? Well, I am telling you now. Typically, a scene will be made up of several world (wrl) files, each with some VRML object or several objects and the code that makes them behave. One technique we will be learning later in this tutorial is how to enable these objects in different files to send and receive events to and from each other, but our first example of a sequence is initiated and controlled completely from within one object: the boat.

    “Baby steps…” sayeth the Turk.


    As soon as the user gets on the boat, a VRML object called a Proximity Sensor fires. The boat’s Proximity Sensor

  • Sets the viewpoint within the transform of the boat to be the current viewpoint

  • Sets the boat in motion down a predetermined set of positions. Because the viewpoint is within the boat transform, it automatically moves with the boat (children follow parents).

  • Starts the motion of three animated gifs

  • Starts the text animation

  • Starts the music sequences.

    All of this is initiated by a single sensor firing. Let’s look at the code that makes that happen.

    Code!! Thank God, I thought he would never shut up!


    Viewpoints, Navigation Nodes and Defined Names



    First we have the two VRML objects for the entry point view and the navigation


    DEF ShoreView Viewpoint {
    orientation 0 1 0 1.70
    position 342 4.0 -80
    description "Temple Dock"
    }


    A Viewpoint named Shoreview at the coordinates X (342 meters from world origin in the X axis, 4 meters above the origin in the Y axis, and a negative 80 meters in the Z axis) is turned to the left and given the description “Temple Dock”.

    Did I tell you the unit of measurement in VRML is meters? Well, I’m telling you now. Like radians for angles, it is one of those geeky things that is inconvenient for some people and downright baffling to Americans, but we cope by not giving a frik about proper scaling and blaming it all on the French who reply by blaming the XML encoding of X3D on us and of course, they are right about that. Yanno, when they’re right, they’re right. Of course when they are left, they are still right. That’s what it is to be French.

    The description value is displayed in the pop-up menu of the browser when the user right clicks if the browser is a Bit Management Contact browser. Different browsers put these descriptions in different parts of the GUI, but a right click pop-menu is common.

    Note the DEF keyword assigning the name ShoreView. When referring to the Viewpoint from ROUTEs or Scripts or USE statements, etc., it is the DEF name that is used for reference, not the description value. The description value is simply a label for the user interface. If you leave this blank, the user cannot find this viewpoint using the GUI and that can be quite useful because sometimes you want to hide viewpoints from the user but use them in scripts.

    DEF names are used by ALL VRML objects as the names for referring to them. This is similar to the concept of SGML/XML id (identifier) values in Document Type Definitions. A DEF name is a ‘defined’ name. The difference is in XML, an id value has to be declared in a DTD or Schema. In VRML the DEF keyword is used in the data itself. So if you don’t define a name, you can’t refer to the object later.

    Define the name BEFORE you need to use it in a file. Just do it or the browser may complain about nodes not existing or “INVALID REFERENCES” even though you can see right there in the file. Just do it.

    Don’t define names that you don’t need. It wastes resources. You may not notice it, but it does. On the other hand, you may name it just so you can find it easily while you are building the world. That’s ok. There are utilities for cleaning up later, in fact, FREE utilities. Say mondo CHEAP!


    DEF DefaultNav NavigationInfo {
    type "NONE"
    }


    A default Navigation node is provided that sets the navigation type to NONE. This keeps the user from getting off the boat midstream. A captive audience is a wonderful karma. There are other important properties of Navigation nodes, but we don’t need them here.

    Next we see the transforms and other objects that make up the boat itself. They begin as follows:


    DEF Boat Transform {
    translation 245 -3.1 582
    rotation 0 1 0 -1.57
    scale 1 1.3 1.5
    children [

    Transform { rotation 0 0 1 -0.15 children [
    DEF BoatView Viewpoint {
    orientation 0 1 0 1.55
    position 1.8888 2.9 -3
    }
    ]}


    Note the nesting for these two transforms (children are positioned relative to parents) and that the second transform contains the Viewpoint for the boat itself. As mentioned above, when motion is applied to the boat transform, the Viewpoint moves with it. There are various geometric objects that make up the visible structure of the boat, but we aren’t looking at those here.

    Proximity Sensor



    The next object is very necessary. It is the proximity sensor that starts the journey as described above:


    DEF OnBoat ProximitySensor { size 12 12 12 }


    Proximity Sensors are surprisingly simple looking for what they can do. This is an example of the language’s pre-built objects provided by the browser. The browser tracks the current position of the user. Proximity sensors enable the author to declare regions in the virtual space of interest. When a user enters or exits the area defined in the sensor declaration, in this case an area of a 12 meter cube (X = 12, Y = 12, Z = 12), the sensor sends an enterTime event. When the user exits, it sends an exitTime event. These can be used, of course, to start other behaviors.

    In fact, a Proximity Sensor continuously sends position and orientation events of the user as long at they are in that sensor’s area allowing you to track the user through the sensor area continuously and with considerable precision. This is important but we don’t need it here. There are other important events and properties of Proximity Sensors but for now, we only need the enterTime and the exitTime event Outs. Yet the simple looking Proximity Sensor is one of the most powerful objects in the VRML language for many purposes.

    Remember, events have types, and types must match when routed to other objects. The enterTime and exitTime events (both event Outs because the sensor emits them to other objects), are both SFTime events, that is, timestamps. By sending a timestamp event to another object with an eventIn of type SFTime, one can use these events to start behaviors or even start several. It’s all a matter of routing.

    Time Sensor


    The behaviors we need for the boat trip are:

  • Turn on a light and keep the user on the boat as the boat moves
  • Move the boat on the river.
  • Turn the boat to follow the river.
  • Animate the textures used for the ghosts
  • Animate the text
  • Turn the sounds up and down
  • Plop the user on the dock at the end of the boat journey up the river

    To create the sequence of events for these behaviors, we need :

  • A Proximity Sensor to start the event sequence (described above)
  • A Script to control the behaviors initiated by the events with event handlers
  • VRML engines to describe the behaviors
  • Routes to connect the events to the script event handlers

    To capture the user on the boat, the boat proximity sensor sends an enterTime event to a script that binds the boat viewpoint as the current viewpoint. The script then sets the boat in motion by sending the enterTime to the startTime event of a VRML engine called a TimeSensor. The TimeSensor sends time events to other engines, specifically a Position Interpolator for moving the boat in the XYZ coordinate system.

    To turn the boat as it follows the river, it also sends the same TimeSensor timing events to another engine called an Orientation Interpolator. These could be controlled by different timers but it is easier to synchronize the movements by using the same timer; so in the example, I use one timer for both. There can be reasons for separating these but we’ll look at that in the next section as we dissect the interpolator declarations.

    TimeSensors are the verbs of VRML in the sense that they cause actions. When naming them, it helps to use verbs in the DEF name or at least to indicate the kind of behavior they control. This is the TimeSensor that controls the motion of the boat by sending timing events to the movement engines, the Position and Orientation Interpolators.


    DEF BoatRideTimer TimeSensor {cycleInterval 180}


    The cycleInterval property specifies that the BoatRideTimer TimeSensor runs for 180 seconds one time. If I want it to repeat, I can specify a loop property of TRUE or FALSE. It defaults to FALSE. There are other property values for Time Sensors and because we will use them later, let’s look at them now. Here is the complete node specification for a TimeSensor object:


    TimeSensor {
    cycleInterval 1 # exposed field SFTime
    enabled TRUE # exposed field SFBool
    loop FALSE # exposed field SFBool
    startTime 0 # exposed field SFTime
    stopTime 0 # exposed field SFTime
    }


    When reading a node specification, the syntax looks the syntax used in the instance. It provides the sensor type, the properties of the sensor, the default values that you can rely on being there if you don’t change them, and the data type of each field. If these are exposed fields, they can be set by other nodes in the world.

    Not shown in the node specification but shown in the documentation are the event interfaces. A TimeSensor has the following event interfaces:

  • isActive eventOut SFBool

    the event is sent when the sensor starts to run (TRUE) and when it stops (FALSE).


  • cycleTime eventOut SFTime

    the current time sent at the start of each cycle. If the loop property value for the RideBoat Timer was TRUE, this interface would send a timestamp every 180 seconds.


  • fraction_changed eventOut SFFloat

    the fraction of the current cycle that has completed. The cycle is divided from 0 to 1 where 0 is the beginning of the cycle and 1 is the completion of the cycle. All divisions between 0 and 1 are floating point numbers, for example, 0.0, 0.1, 0.18372 and so on.


  • time eventOut SFTime

    the current time, in seconds since 12 midnight GMT January 1, 1970


  • Remember that event interfaces are the destinations for ROUTEd events. Exposed fields can be set by the author, by default, or by scripts. To understand VRML objects, learn to read the node specifications.

    This is important:

    The restriction on what nodes can be routed to other nodes is the type compatibility of the events, not the nodes themselves. If a node exposes, for example, an SFTime eventIn and another node exposes an SFTime eventOut, these nodes can be connected. The same is true for other event data types such as SFFloats. The power of this becomes apparent as you build more VRML worlds.

    Interpolators


    This is out of order in the code, but first let’s look at the ROUTEs for the boat movement because they can be considered a single movement given they are controlled by the same Time Sensor: RideBoatTimer.


    ROUTE RideBoatTimer.fraction_changed TO RideBoatPosition.set_fraction
    ROUTE RideBoatPosition.value_changed TO Boat.set_translation
    ROUTE RideBoatTimer.fraction_changed TO RideBoatOrientation.set_fraction
    ROUTE RideBoatOrientation.value_changed TO Boat.rotation


    Note that the only way you can tell that these are initiated by the same sensor is the sensor DEF name is used to identify the timing source: BoatRideTimer. The timer is sending SFFloat events (fraction of the timer cycle) to the Position and Orientation eventIns for SFFloats. The Position and interpolator event Outs are then sending two different kinds of events to the Boat transform: a vector (XYZ) and a rotation (the axis to be rotated and the angle of rotation. By sending these with the same timer, I am ensuring that the rotations of the boat occur as specific positions in the journey. It makes sense. You really don’t want to run the boat up on the banks do you?

    To understand precisely how this works, we must look at the Position and Orientation interpolators themselves.


    DEF BoatRidePosition PositionInterpolator {
    key [0, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1]
    keyValue [ 243 -3.1 582, 225 -3.1 450, 225 -3.1 445, 225 -3.1 438, 370 -3.1 365, 375 -3.1 355, 375 -3.1 300, 375 -3.1 200, 375 -3.1 100, 346 -3.1 -80 ] }

    DEF BoatRideOrientation OrientationInterpolator {
    key [ 0 .1 .2 .3 .5 .6 1 ]
    keyValue [ 0 1 0 -1.21, 0 1 0 -1.57, 0 1 0 -1.57, 0 1 0 -2, 0 1 0 -3.07, 0 1 0 -1.57, 0 1
    0 -1.57 ] }


    Note that both have two parts: a set of keys and a set of key values. Keys and key values are paired. At key 0, the position is XYZ (243 -3.1 582). At key 1, the position is XYZ(346 -3.1 -80). These are the start and stop positions of the boat on the trip respectively. The same pairing relationship is used in the orientation, but the values are different.

    To understand this, the TimeSensor sends time stamps that are allocated to the keys. The interpolator allocates the time events proportionally to the keys which point to the key values for each interpolator. The series of position and orientation moves will start and stop at the same times but the independent moves happen at different fractions of that time. It takes some experimentation to set the values so turns happen at correct bends in the river, and positions go in the directions pointed to by the turns thus keeping the prow pointing forward, but that is how it works.

    Note that by setting keys to different intervals, you can speed up or slow down certain parts of the movements. To keep movement natural, objects under the influence of gravity or water or any other force of resistance are slower when they start, faster once in motion, and slow down as they stop or they go kerflop. Natural motion has these elements of force. Since currently there is no physics engine in VRML browsers for simulating this, you can use interval distance to approximate it. There is a physics engine specification in the works for X3D engines, and it should be there Real Soon Now. However, if you want to create natural motion, you should get into the habit of observing different kinds of objects in motion to see how they behave and mentally try to model that using intervals. It is one way of preparing for a trance dance. Breathe.

    The technical term for this is keyframe animation. In theory, there are an infinite number of positions along any path. In practice, that is GeekyCaca. Remember the old gag in math class where they prove to you that if a chicken crossing the road has to cross half of it first, but then half of that first, then half of that, the chicken is run down by a car before they can cross the road because there is an infinite number of steps. This drives you nuts until you realize that there is not an infinite number of steps. The chicken is taking approximately the same length of step each time, even if speeding up to avoid the car. There is an infinite number of divisions because the function for dividing the steps is looping (really recursing but let’s not go mathGeeky). The chicken may indeed get run over if he isn’t fast enough, but not because he has to cross an infinite space with tiny legs.

    The author sets the key for specific moves and positions along the path. The browser engine determines the in-between positions through a mathematical process called interpolation (thus position and orientation interpolators). So you can think of the key value positions as the minimum and maximum steps the chicken takes, the orientation angles as the minimum and maximum angles it turns as it runs, and the keys as the length of time each one of those takes given a time sensor sending fractions (SFFloats) of some cycle interval. Really, the key is the division of the fraction but the engine automatically maps that to the time. Don’t worry. Given type compatibility, it just works.

    Let’s look at another timer/interpolator pair that turns the sounds up and down in volume/intensity to better understand the principles of type compatibility and intervals.


    DEF TurnDownTimer TimeSensor { cycleInterval 3}
    DEF TurnDownSound ScalarInterpolator {
    key [0,1]
    keyValue [1,0] }

    DEF TurnUpTimer TimeSensor { cycleInterval 4 }
    DEF TurnUpSound ScalarInterpolator { key [0,1] keyValue [0,1] }


    This is simpler but the principle is the same. A scalarInterpolator takes a single floating point value such as ‘intensity’, the volume of a sound playing’ and changes it by the scale in the key value. So if a volume starts at 0 (no sound), a scale of 1 turns it up all the way (not to Eleven, just 1). So a timer with a cycleInterval of 3 seconds routed to a scalar with only the values 0 and 1 routed to a sound node will turn it up to full volume in three seconds. One can add intervening fractions to make the sound go up evenly or unevenly just as one can speed up the boat when going in a straight line and slow it down during turns by adjusting the gaps between the key values.

    Note in the example above that I used two different timers. Why? Because otherwise initiating a single timer would attempt to turn it up and down at the same time and that doesn’t work, does it? Also note that I use two different lengths for the cycleIntervals. Why? Because I wanted to. That’s all. Observing people, they usually turn sound up slower than they turn it down. It simply feels natural.


    To live well in real time or virtual time:
    Learn to watch. Learn to listen.
    Listening and Seeing are everything. Timing is everything else.
    Practice makes it real. Skill makes it virtually real.
    Breathe. Remember.


    Sound Nodes and the Switch Proto



    Before getting to the Script node that ties the sequences together, let’s look at two objects being animated by the Timers and Script that are not the boat or the user’s viewpoint. These are the sound nodes that provide the background music, and a series of three gif graphics that are the ghosts and they eyes of the soul of the river. Spooky stuff.

    Sound Node



    Here is the first sound node used in the journey:


    DEF Soprano_Sound Sound {
    maxBack 1300
    maxFront 1300
    source DEF SopranoGreeting AudioClip {
    url "audio/sopranoGreeting.wav"
    }
    spatialize FALSE
    }


    A sound node is actually two nodes:

  • DEF name Sound {…} :the sound container which describes the spatial characteristics of the sound such at the size of the oval within which it can be heard relative to its position in space and whether or not the user position changes its perception of direction. If you have stereo speakers, this position essentially varies between the left and right speakers. When the user turns in space, the sound will move in the stereo field. The Sound node also has properties for setting the intensity (volume), if the sound loops, and the startTime.


  • AudioClip…{}: the audio clip is named and contains the URL for the actual sound file, typically a wave file or a midi file. Audio clips also have events such as isActive to enable it to tell other nodes when it starts and stops. This is very handy when you want to use a sound to initiate another behavior as we will see.


  • There are two sound nodes in the boat journey. The first as shown here is an acapella soprano (big gal whining alone). The sound plays once and stops. The second is an synth bass drone with a repeating riff. This is a loop that plays until the end of the boat ride. These sounds are timed and interpolated so that as the soprano finishes the looped bass riff begins. These could be one wav file easily but I chose to keep them separate because I reuse different sounds in different parts of the world. I loop the second sound because that makes it smaller. Also, the sounds are reusable too. Some sounds serve are themes for characters and emotions, events, and so on. Keeping them small and discrete keeps them available when I need them.

    HINT: a sound loop library is just as important as a texture library for exactly the same reason. Make them in your spare time when waiting for Doctor Who to return to the Sci-Fi channel. Decorate audio space as carefully and passionately as you decorate visual space and remember, they are BOTH 3D+Time and in combination, used well, the soul of virtual reality.


    DEF Travel_Sound Sound {
    intensity 0
    maxBack 1300
    maxFront 1300
    source DEF Travel AudioClip {
    loop TRUE
    startTime -1
    url "audio/travel02.wav"
    }
    spatialize FALSE }


    Note the first node is set with the intensity and loop to defaults. The second is set with the intensity at zero (silent) and the loop at TRUE. I use the combination of timers and scalar interpolators to turn it up as the first sound completes its one cycle. Thus, I get the effect of a single sequenced music background from two sounds and use the intensity to blend them. The browser I am using supports up to 16 channels of sound, meaning you can theoretically keep sixteen sounds going at one time. Your mileage may vary given your sound card but most handle that with varying degrees of fidelity.

    If you were running ROL right now, you would notice that two sounds run continuously in the background: wind and water. Near the temples there are some music loops that run automatically. Together, these comprise the ambient background sounds over which all other discrete sounds must run, be heard, and must blend. I will show you how these can be controlled by the objects in the world later using events send among the objects in different files.

    The size of good sounding wave files is one of the bigger obstacles to decent download times for virtual worlds. Graphic texture sizes are nothing when compared to the size of a sound file; yet sound is one of the single best ways to make a virtual world come alive until Smell nodes are implemented.

    I could use MIDI which is considerably smaller but depends too much on the local machine for fidelity (say too many cheap SoundBlaster cards out there and they aren’t the worst) and because MIDI cards don’t usually have whining soprano sounds or wind and water on them. There are sound cards with wav samples on them, but these don’t exist too frequently outside of recording studios or the homes of serious musicians, which are the same thing these days.

    I could combine MIDI and wave files but that is even more unpredictable. At this point, mp3 sound support is only in the MovieTexture nodes of most browsers and streaming sound support is spotty but improving.

    What’s a guitar hero to do?

    I will dedicate a whole tutorial to sounds in VRML, but for now, know that these are 22khz mono wav files and that is as much compromise in fidelity that I as a musician will make with the web for bandwidth. Go below that and sound sucks. Tell the local bandwidth nazis to go pick on YouTube.

    The Switch Node and Switch Interpolator (A PROTO)



    To give the effect of a ghost rising from the water, floating toward the boat, then transforming into a pair of flashing sultry eyes, I use some really…. Cheap… tricks. If you want to play, you have to pay. There are some sophisticated ways to do this with morphing of mesh surfaces, but hey, this isn’t Disney or Shrek and you and I aren’t paid per vertex yet.

    The effect is achieved by having three textures using the combination of a timer, position and orientation interpolators to move the textures, and a PROTO node to switch them out in series as they move toward the boat. We’ve already covered the first nodes and I explained PROTOs in the first part of the tutorial. Let’s look at the Switch proto briefly then how these combine.

    The Switch Interpolator proto was provided to the VRML community by Jed Hartmann and Josie Wernecke in “The VRML 2.0 Handbook”. Originally provided for flipbook animation where a series of images are changed in rapid succession to emulate motion animation as in a flipbook, I adapted these to drive text displays similar to karaoke text displays and for tricks like the GhostEyes animation. I’m not including the PROTO itself here because I am unsure what the copyright position of the publisher is on that.

    However, the instance of the proto looks like this:


    DEF GhostEyes_Animator SwitchInterpolator {
    key [ 0, 0.1, 0.5, 1 ]
    keyValue [ 0, 1, 2, 3 ]}


    As you can see, like the earlier interpolators, this is a set of keys that index key values. The key values represent the number of nodes or choices in the Switch. So if I want to have 27 lines of text, I would have 29 values so that the first and last nodes are blank. If I want one to remain on the screen at the end, I would decrease the keyValue by one member. Actually, no don’t need the intervening values for a simple switch. You can as I do in other places where I use the Switch Interpolator do this:

    DEF mySwitch SwitchInterpolator { key [0,1] keyValue [0,28]}

    The timer and the browser will see to it that 28 nodes are displayed at equal intervals of time.

    What the interpolator does is send the key values to a VRML Switch node to change the whichChoice value of the Switch, thus changing the text node or the graphic node, or any node inside the switch node to the next node in succession. A timer drives the SwitchInterpolator and is routed just as we have seen before:


    ROUTE TextBackTimer.fraction_changed TO GhostEyes_Animator.set_fraction
    ROUTE GhostEyes_Animator.value_changed TO GhostEyes.whichChoice


    The position and orientation engines create the movement. The graphics spin as they approach. To create the illusion that there is one graphic, they are switched as they turn. The tricky bit here is to time the switch so they change as they are on edge toward the viewer. This works because from the viewers perspective, when on edge, they are a line so the switch to the next graphic is not perceptible except for the last switch when it is close enough that the actual detail can be seen changing from the image of the spirit into the flashing eyes. As I said, cheap tricks. They aren’t perfect but they are cheap.

    Compare the values in the position and orientations to see how this works. Distance matters to illusions:

    DEF EyesPosition PositionInterpolator {
    key [0, 0.35, 0.5, 0.65, 1]
    keyValue [ 1 -10, -50, 1 5, -50, 1 5, -40, 1 6, -35, 0 0.36 -.2]}

    DEF EyesOrientation OrientationInterpolator {
    key [0, 0.2, 0.3, 0.5, 0.95, 0.99999999, 1]
    keyValue [ 0 1 0 -3.14, 0 1 0 -1.57,0 1 0 3.14,0 1 0 -1.57,0 1 0 3.14,0 1 0 -1.57, 0 1 0 3.14]}

    The secret is that the movement of the graphics, the switch, and the texts are all controlled by a single timer that synchronizes when the switching occurs relative to the position and orientation and the display of the text that is the first part of the story.


    ROUTE TextBackTimer.fraction_changed TO EyesPosition.set_fraction
    ROUTE EyesPosition.value_changed TO TextBackground.set_translation

    ROUTE TextBackTimer.fraction_changed TO EyesOrientation.set_fraction
    ROUTE EyesOrientation.value_changed TO TextBackground.set_rotation

    ROUTE TextBackTimer.fraction_changed TO GhostEyes_Animator.set_fraction
    ROUTE GhostEyes_Animator.value_changed TO GhostEyes.whichChoice


    If this seems insanely complex, it isn’t really. You build and test it one piece at a time until it works as you think it should. Then tweak.

    A Switch node is a group that has a choice value which can be changed by sending values to it as illustrated by the switch interpolator, basically a proto that take series of values, converts them to integers and send them as event outs. Here is the first part of the text node switch. The choice counts from zero to n and the 0 choice is displayed by default. To give the appearance of the text appearing in empty space, I set the first node with values I will use for the other nodes but don’t include a string property value. That ensures the first text node is blank but useful.


    DEF RiverPoem Switch {
    whichChoice 0
    choice [
    Transform {
    children Shape {
    appearance Appearance {
    material DEF WhiteFont Material {
    diffuseColor 1 0 0
    shininess 1}}
    geometry Text {
    fontStyle DEF Poem FontStyle {
    justify "MIDDLE"
    size 0.22
    style "ITALIC"}}}}

    Transform {
    children [
    Transform {
    children Shape {
    appearance Appearance {
    material USE WhiteFont
    texture DEF Flame MovieTexture {
    url "movies/flame.gif"
    }}
    geometry Text {
    string "The River of Life"
    fontStyle DEF Title FontStyle {
    justify "MIDDLE"
    size 0.3
    style "ITALIC"}}}}]}


    By the way, you can route values into the nodes in a switch for cheap tricks such as changing the color of each line of text as it appears, set the transparency of each texture to make them appear and disappear or appear to be … ghostly, and so on. I do that in ROL. I won’t illustrate it here because it is a combination of cheap tricks we’ve already looked at. (Hint: send scalar values to transparency values to fade the image in and out just as you turn sounds up and down.)

    You will also note in the example that I use a MovieTexture node, in this case, a gif animation, to give the text in the switch the appearance of being on fire. Such 2D animation on 3D surfaces is extremely useful and extremely cheap when compared to creating such effects in 3D for a one shot deal. Try to do fire in 3D. Just try. Then come back here another time and I’ll show you a way to make a 2D fire look as if it were 3D WITHOUT Billboard nodes. ;-)

    The Sequencing Script



    Now we come to programming over declared nodes. Without scripts, VRML worlds are just elaborate cuckoo clocks. They will do the same thing every time more or less monotonically. With clever timing in loops, it can appear casually that these are more complex than they are, but randomness only goes so far to emulating life. Eventually, an organizing decision making structure must be used to give flight to fancy. I’m not advocating intelligent design as the principle of the universe, but for intelligent VR, you need scripts to make choices and to elaborate choices. That life emerges from random accidents or intelligence is a matter of philosophy; that life directs its own evolution as a matter of intelligent choice is scientific fact.

    The script serves as a place to route events from objects, then change the values of these or other objects based on the values of the events received. In the last tutorial, I illustrated the structure of a script, how events are declared, how these also rely on type compatibility, and how nodes can be USEd in fields so that their property values can be set within the script event handlers or in functions called from those handlers.

    With that said, I give you the script here without too much comment. You will want to note how different event types are used to activate the behaviors, how these are chained to start and stop behaviors to create the sequence, and nuances such as using the same SFTime event and adding a value to it to enable behaviors to start later than the time the timestamp is received.

    DEF SetViewPoint Script {
    eventIn SFBool jumpToBoat
    eventIn SFTime boatRide
    eventIn SFTime getOnDock
    eventIn SFBool setViews
    eventIn SFBool stopSound
    field SFNode boatnav USE BoatNav
    field SFNode defnav USE DefaultNav
    field SFNode shoreview USE ShoreView
    field SFNode boatview USE BoatView
    field SFNode boattimer USE BoatRideTimer
    field SFNode onboat USE OnBoat
    field SFNode greeting USE SopranoGreeting
    field SFNode travel USE Travel
    field SFNode templedock USE TempleDock
    field SFNode dockstop USE DockStop
    field SFNode turndown USE TurnDownTimer
    field SFNode turnup USE TurnUpTimer
    field SFNode poemtimer USE PoemTimer
    field SFNode textbacktimer USE TextBackTimer
    field SFNode textback USE TextBack
    field SFNode eyes USE Eyes
    url "javascript:


    function jumpToBoat (value) {

    if (value == TRUE ) {
    boatview.set_bind = TRUE;
    boatnav.set_bind = TRUE;
    }
    }

    function boatRide (value) {
    if (value > 0 ) {
    boattimer.startTime = value + 2;
    greeting.startTime = value + 2;
    travel.startTime = value + 21;
    turnup.startTime = value + 21;
    poemtimer.startTime = value + 7;
    textbacktimer.startTime = value + 2.5;
    }
    }

    function getOnDock (value) {
    if (value > 0 ) {
    turndown.startTime = value;
    dockstop.startTime = value + 4;
    templedock.startTime = value + 18;
    }
    }

    function stopSound (value) {
    if (value == FALSE ) {
    travel.loop = FALSE;
    }
    }

    function setViews (value) {
    if (value == FALSE ) {
    shoreview.set_bind = TRUE;
    boatnav.set_bind = FALSE;
    onboat.enabled = FALSE;
    textback.transparency = 1;
    eyes.loop = FALSE;
    }
    }"
    }

    ROUTE OnBoat.isActive TO SetViewPoint.jumpToBoat
    ROUTE OnBoat.isActive TO EyeLight.on
    ROUTE OnBoat.enterTime TO SetViewPoint.boatRide
    ROUTE OnBoat.exitTime TO SetViewPoint.getOnDock
    ROUTE BoatRideTimer.isActive TO SetViewPoint.setViews
    ROUTE TurnDownTimer.isActive TO SetViewPoint.stopSound

    ROUTE BoatRideTimer.fraction_changed TO BoatRidePosition.set_fraction
    ROUTE BoatRidePosition.value_changed TO Boat.set_translation
    ROUTE BoatRideTimer.fraction_changed TO BoatRideOrientation.set_fraction
    ROUTE BoatRideOrientation.value_changed TO Boat.rotation

    ROUTE TextBackTimer.fraction_changed TO EyesPosition.set_fraction
    ROUTE EyesPosition.value_changed TO TextBackground.set_translation

    ROUTE TextBackTimer.fraction_changed TO EyesOrientation.set_fraction
    ROUTE EyesOrientation.value_changed TO TextBackground.set_rotation

    ROUTE TextBackTimer.fraction_changed TO GhostEyes_Animator.set_fraction
    ROUTE GhostEyes_Animator.value_changed TO GhostEyes.whichChoice


    The Babe On The Bridge


    When the river journey ends, the script will automatically take you out of the boat and plop you on the dock with an ominous sound. The status of the boat trip timer isActive property is routed to the setViews function. When isActive sends an SFBool value of FALSE, meaning the timer has ceased (it has one long cycleInterval) sending timing events, this function binds the view to the Temple Dock, resets the Navigation node to the default, disables the Proximity sensor, and makes the Material node with the ghostly eyes disappear by setting it to transparent.


    function setViews (value) {
    if (value == FALSE ) {
    shoreview.set_bind = TRUE;
    boatnav.set_bind = FALSE;
    onboat.enabled = FALSE;
    textback.transparency = 1;
    }


    isActive events are useful for initiating sequencing transitions. Notice that AudioClips also send isActive events so they can also be used for this and I do that in other parts of th world. In fact, sequencing is as much about finding useful event combinations as timing. One can also route the fraction changed events and use comparison statements (eg, if statements) in the code to initiate events based on the approximate values of the current fraction, thus having a series of seemingly unrelated events being keyed by one timer without the timer actually being routed to them. Using a script to do this is one way to get around type compatibility. The handler has to receive type compatible events, but setting USEd node values within the handler itself does not rely on that.

    A hint on using Javascript: = and == are two different operators. The first is an assignment operator. The second compares two values. Javascript interpreters are sometimes lax but if you mix these up in a statement where you are trying to determine a value such as a fraction changed and compare it, eg,


    if (value == .999) { ….}

    and instead you enter


    if (value = .999) { ….}


    the interpreter accepts that, but it isn’t logical and things may not work as you expect. Just a hint…

    The ominous sound is just for drama. When you move toward the babe, she will sing with an accompanying low note that is a nice cadence out of the dock sound, but the reason for plopping you is that getting out of the boat is harder than getting in. The user needs more skill maneuvering and most won’t be able to do it without practice. That struggle slows down the pace of the story. Also, it’s a nice dramatic effect to suddenly be looking from the temple dock at the temples in the distance, and between you and the temples, that sad eyed babe on the bridge. We’ll meet her soon enough.



    At Journey's End


    There are lots of tricks and variations on these combinations of nodes, events, routes and scripting but they are all just combinations of the same tricks used differently. However, this sequence works inside one object. In the next installment, I will explain, as it was explained to me by the brilliant and often dry humored Sergey Bederov at Parallel Graphics how to use PROTOs and EXTERNPROTOs to enable objects to communicate when they are in discrete files. This enables very powerful cheap tricks for reactive characters, and if you are very clever and have the time, non-linear worlds.

    Sunday, March 11, 2007

    From Here to There and Back Again, Mr. Proto

    Whimsically, Bilbo Baggins wrote a tale of his time away from the shire for most of his life in the shire, but finished it in Rivendale and showed it to Frodo before the younger began his journey to return the ring to fires. Sometimes one has to travel a long ways to finish a story.

    Many a tale is told as a road trip, a journey, a walk from here to there where all of the adventures depend on the twists in the trail, the companions and adversaries, and how well one fares with each. This same model of events and situations, call and response, request and acknowledgement is found in all forms of communication and art.

    A prosaic term for this used in music is sequencing. Some sequences are like the trip we take to the local grocer or the song we sing in church. There is a plan of stops or notes and if all goes according to plan, the events are predictable. If there are surprises along the way, we make decisions about the next stop or next note. Most of us like trips that aren’t the same every time we travel a road. The same is true of many stories and some adventures in life. Some journeys go straight to their destination, and some journeys and most stories take side trips.

    I am not going to philosophize about that. I am going to show you how to author that in 3D using sequencing techniques. In this tutorial, I am going to show you how to set up animation and sound sequences in VRML/X3D that may be planned and provide choices. This tutorial has three parts:

    Part 1: The Basic VRML Nodes Used To Create Sequences

    Part 2: Rolling on the River and

    Part 3: Walking Kamala

    The Basics of Ring Givers and Ring Bearers


    First, we will learn about basic VRML/X3D animation sequencing and how this is created by sending and receiving events.

    In Western tradition of marriage, bride and groom give and receive rings. There are two important concepts:

  • Rings are exchanged.

  • Rings are expected.

    In animation, instead of rings, events are exchanged. Instead of placing a ring on a finger, events are sent by event outs, and received by events in. As with the ring, event ins and event outs have to match by type or just event types. If a ring is given, a ring is expected. If an event is given, an event of the same type is expected.

    Events


    Event types are also called 'data types'. Data types will be numbers and characters of special forms. We have to live with a bit of geekSpeak here. Some examples of event types are:

  • SFInt32: A single field integer. Or simply, 0, 1, 2, 3 and so on with no fractions allowed and no multiple integers such as (0 1 2).

  • SFFloat: A single field floating point number. This allows fractions but only one and conventionally, between 0 and 1, so 0.23, or even just .23.

  • MFFloat: a set or array of floating point numbers, so multiple fractions between 1 and 0.

  • SFVec3F: an XYZ coordinate (a vector)

  • MFVec3F: a set or array of XYZ coordinates (an array of vectors)

  • SFNode: a node within the file by name.

  • MFNode: a set or array of nodes in the file

  • SFTime: a timestamp or value of time automatically generated by the system on request.

  • SFRotation: A single field multiple number value that describes a vector (XYZ coordinate) and a rotation angle in radians. For example, 0 1 0 1.57.

    Let's decode the rotation event. The example says, there is a rotation event of 1.57 radians (90 degrees) about the Y axis Think of the X Y Z values not as positions but as yes/no switches that tell the VRML engine which axis is the axis about which something is to be rotated, or simply, X is NO, Y is YES, Z is NO and the angle of rotation is 90 degrees. So, turn the receiver of the event one quarter of a complete turn.

    Transforms


    Before we talk about grooms that can offer rotation events (rings), let’s look at brides that can accept them. In VRML/X3D, all of the elements of the language are referred to as ‘nodes’. A basic organizing element of a VRML world is the transform node. Just like the bride, a transform node can have children nodes and when asked the right way, can turn the children around.

    Transform {
    rotation 0 1 0 1.57
    children [
    … child nodes
    ]
    }

    In geekSpeak, the concept that nodes have other nodes as children is called ‘containment’ or ‘hierarchy’. The idea in animation is that any event received by the outermost or parent node passes that event to all of its children. So, if the bride turns 90 degrees, so do all of the children. On the other hand, it the child receives an event, it turns 90 degrees relative to where the parent is without turning the parent.

    What? Children turning around without permission from their parents? Merciful heavens! Children follow their parents otherwise. Clear? Good.

    To make this possible, transforms can be the children of other transforms.

    Transform {
    rotation 0 1 0 1.57
    children [
    Transform {
    rotation 0 1 0 1.57
    children [
    … child nodes such as transforms, groups, boxes, spheres, text, etc.
    ] }]}

    However, a transform is not something you can see. It is actually the space that something you can see is inside. So a transform with a transform as a child is a space contained within a space. The geekSpeak term for this is ‘nested finite coordinate system’, or simply FCS. Don’t let this become a burden to you, but remember this:

    A rotation or any event that changes the location, rotation of position of any thing seeable within the transform is figured relative to the parent.

    If you remember anything from high school geometry beyond how hot it was in that room or the bodacious body two seats in front of you, you remember the concept of an ‘origin’, that is the zero point in the graph from which you count upwards or into negative numbers. For now just know that each transform has its own origin and it is relative the origin of the world space, the outermost origin which the system gives you for free, or it is relative to the space is it inside of.

    Know what’s inside your head. Know what your head is inside of.

    That is all you need to know.

    Fields


    A transform is an example of a node that can only receive events. It cannot send them. However, it does not use a received event to set the rotation value. It uses a property that is said to be “set”. This will confuse you if you take it too literally. You will want to know why we are suddenly talking about properties instead of events. Accept it. Don’t fight the author. Oh drat! I suppose I have to explain it anyway.

    When an event is sent or received, it is property value that is set as a result of sending or receiving the event. The event ins and event outs are the interfaces that serve as connection to the node. When an event is received, a property value is changed to the value of the event it receives. These property values are called fields.

    In VRML, there are two kinds of fields:

  • field: a property value set by the author. It is the same for the life of the world or has an initial value that can be changed by a script.
  • exposed field: a property value that can be changed by events.

    In X3D, the new version of VRML, all fields are exposed, but for this tutorial, we will only look at VRML and in VRML, you need to know which fields are exposed and which can only be set by the author. There is a very good book by Jed Hartman and Josie Wernecke, The VRML 2.0 Handbook that I keep by my side at all times when authoring. There are also several sites on the web with that information. I will tell you that and leave it up to you to go Google for the information.

    Or….what the heck… See VRML97. Polite, ain’t I?

    So let’s go over that in short form:

  • Node field values change as a result of receiving events sent by other nodes.
  • Events are values of specific types.
  • Event interfaces are eventIns or eventOuts.
  • Any event sent by an eventOut must match the corresponding type of the eventIn.

    Routes


    Before we leave the basics of our journey, let’s talk about the Map. Most travelers have a good map. A VRML adventurer NEVER leaves home without one even if only in their head. A map is a territory with routes to destination. A VRML map is the same. For an event to travel from node to node, it uses ROUTEs.


    ROUTE AvatarProx.enterTime TO doAct.walkFromBridgeToTemple


    This example of a ROUTE instructs a time eventOut (SFTime) to be sent from a Proximity Sensor object named AvatarProx to a time eventIn (SFTime) in a script object named doAct. In this case, when the user gets near the object with the proximity sensor, it will automatically activate and send the time of the user entering the area described in the sensor to the script. Upon receiving this event, the script will act on it and start the avatar’s walk from its current location on a bridge in the world to a temple in that world.

    Scripts


    There is another way to enable these events to be sent and received. I’ll describe that later. It is a bit like Gandalf perishing in the gorge and coming back with a new and better smelling robe but the same horse. In other words, it is script magic.

    A script is also a node and can receive and send events. Unlike the nodes we’ve looked at so far, where the nodes are defined by the designers of the VRML language, you determine what kinds of events are handled by the script, the fields and the names of both. A script node structure is this:

    DEF nameOfScript Script {

    eventIn eventType eventName
    eventOut eventType eventName
    field fieldType fieldname fieldDefaultValue

    directOutput TRUE # Optional. see below.

    url "javascript:

    function functionName (value, timestamp) {
    someLogic

    }”
    }

    Take particular heed of the quotation marks. Dropping one of these is a common error and your browser won’t necessarily tell you anything more than something about bad syntax. The quotation marks are the languages way of telling the VRML browser that what is in the quote marks is NOT VRML syntax, it is Javascript, so give this to the Javascript handler.

    This will give you misery at times. For example, to comment out a VRML statement, you use the # sign (octothorpe or pound sign depending on which side of the big pond you live). In Javascript, you use the // or double slash. If like me you use an ASCII editor such as Professional File Editor (free and highly recommended because it can find beginning and end curly braces), you’ll screw this up more than once and find yourself screaming at the system because you KNOW your logic is right so why is the system complaining, then you realize you used # where you needed \\, and so on.

    That’s life in the UTF trenches. Don’t look it up. Think: ‘U Da Fool’.

    The eventIns and Outs behave exactly as for any other VRML node. They must be type-compatible with their senders and receivers. For each event, there is a corresponding function or handler that will receive or send the event. The name of the function is exactly the same as the name of the event in or out that is handles. The value passed by the function is of the same type as the event. The timestamp is automatically generated by the browser for the time that the event is received. To the value and the timestamp can be used in the function logically, errrr… for comparing, for setting other values, etc.

    The fields can be of any type including other nodes. This is particularly useful because it enables you to set the property values of these nodes from within the script. Note that fields don’t have handlers. Fields are properties that can have their values set either by default in their declaration or by the event handlers.

    I assume that you are familiar with Javascript. If not, this tutorial is not for you. There are plenty of good resources on the web and at Barnes and Nobles to teach you how to write Javascript. In the example that follows, I explain the purpose of the script statements, but you are advised to get a good reference book. Ok? Ok.

    Earlier I said that there is magic in scripts that obviate (nice word that; the opposite of bloviate almost) the need for ROUTE statements. The phase ‘directOut TRUE’ is that magical spell. Some claim it is ‘black magic’ and makes a VRML file harder to read. I believe the opposite. Its convenience far outweighs its obsfuscation. Don’t look that up either. Just understand that when directOut is set to true, you can send eventOuts declared in the script directly to the nodes referenced in the script.

    In the interface declaration of the Script you will see a statement with this structure:

    field fieldType fieldname USE nameOfNodeInFile

    That USE keyword tells the VRML browser to automatically route any event or property change to the named node via the fieldname alias. So you will see something like this:

    field SFNode turnDownSoundTS USE TurnDownSounds

    In a script you can see:

    turnDownSoundTS.startTime = value;

    where the startTime is a property of the TurnDownSounds node, the value is an SFTime value that was passed to the function enclosing the statement or is the timestamp of the event. Note the dot (.) between the node alias and the startTime property name. That is a standard Javascript or object-property name convention you see in several object-oriented languages. Simply,

    objectName.propertyName.

    To summarize, a script is a node type for getting and setting property values in other nodes including itself. A script has an interface specification for the events and fields it will handle. For each event, there is a corresponding Javascript function or event handler of the same name. Within the script, the Javascript functions can conditionally set the values of the fields of the Script node and other nodes within the file with or without the use of ROUTE statements.

    PROTO


    You had to have wondered if the title of this tutorial contained a typo. The nephew of Bilbo Baggins was Frodo, not Proto. Sue me.

    A proto is the keyword to identify a VRML prototype. What is a prototype?

    XML talks longingly and smugly about ‘extensibility’. However, any webHead who has written a page of it knows that adding or subtracting tags from an XML Schema does not a language extend. No sir, without scripts, there are no semantics. Without reliable field types, there are no semantics. XML is really just a syntax the way curly brackets and square brackets and commas and white space and keywords in VRML are a syntax.

    EYURRP? Keywords, didja say? Aren’t those bad? No Matilda. All things have names if they want to behave in polite society or polite computer code. A keyword is a word reserved by the language for the things its handler, the VRML browser in this case, must….handle. It’s just a name but a name in a namespace meaning it has meaning and you can’t use it because…. Well, never mind.

    All of the fixed names are the names of node types. A Transform is the name for a bit of space. A TimeSensor is a name for an object that provides time stamps instead of foodstamps. A FoodSensor is a dog downstairs or my son but not a reserved node name in VRML. But isn’t VRML a modeling language? What is you really want a FoodSensor, need a FoodSensor, just can’t live without a FoodSensor.

    Well, you prototype one using a keyword, a name, and a bit of bracketing.

    PROTO FoodSensor [
    interfaceSpecification … eventIns, Outs, and fields

    ]{

    ... VRML nodes including other protos and scripts for events and ROUTEs

    }

    You will note that a PROTO looks a lot like a script. A secret: all of the VRML nodes are really just protos with special status as being handled by the VRML browser instead of by your code. Or so they say. I’ve never looked.

    The differences between a script and a proto are that the script can only occur once in a VRML file, and it cannot contain other nodes except as fields. A script is a node itself. A proto is a specification for a node. What does that mean? It means that a script can do stuff when you reference it by name and event interface such as

    ROUTE someTS.startTime TO doAct.turndownsound

    but it cannot be used to create other nodes like itself. A proto cannot ever receive or send events or do anything EXCEPT create nodes like itself which then CAN receive or send events. In other words, a PROTO is a template or prototype for creating new node types. These new node types have the same interface as the PROTO, duplicate the event handlers and other nodes specified in the proto, and can be referenced many times to create as many of these nodes as you need the same way you can with other VRML nodes. To use a proto, somewhere below the proto declaration you will see

    DEF MyDogMurdock FoodSensor{property-value pairs}
    DEF MySonDaniel FoodSensor {property-value pairs}

    And so on. Until all the food is eaten or the langoliers get them first.

    This is a very cool thing and very handy. When you are looking at a VRML world, the creatures you see such as avatars are typically PROTO node instances. In fact, creating protos and sharing them or selling them is one of the most creative-friendly or business-lucrative products you can make other than the worlds themselves. There are whole libraries of protos for sale and for love on the Internet. Go to Google and type in “VRML PROTO” and look at all the nice toys the furry VRMLers before you have left for you to play with. Protos are the key to production work in VRML.

    EXTERNPROTO



    But how do we share protos without copying them into each VRML file that needs them? Glad to see you’re thinking ahead.

    Sharing a proto is done with an EXTERNPROTO. This ‘external proto’ is just that: a named reference to a PROTO in another file. An externproto duplicates the name and the interfaces of the PROTO it needs and refers to. Note I said, needs, not necessarily all of the events and fields of that proto. Why? An externproto is itself, not a complete specification. It is a reference to a proto that does that. By making that reference, the proto can be used in the file that references it as if it were there, but doesn’t necessarily need all of the events and fields, only the ones to be used in the referring file. Otherwise, it is the same with one difference. It needs the URL of the proto it refers to. So an EXTERNPROTO might look like this:

    EXTERNPROTO FoodSensor [
    eventIn SFBool walkToRefrigerator
    eventOut SFTime turnDownTelevision
    eventOut SFTime StartRummaging
    ]
    "daniel.wrl"

    while the complete Daniel prototype has many more events such as telephoneRings, walkMurdock, and so on. He is really a pretty complete model for a teen-ager.

    EXTERNPROTOs play a very important role in VRML besides enabling you to reuse code. They serve as the means to route events AMONG VRML files used in the same world. I will demonstrate that in the example that follows because this is a key concept that is not often taught well if taught at all. When creating VRML, you want to create modular reusable components as with any building or development task for all the same reasons. When assembling these, you may use Inline statements that act like Include statements in other languages. In VRML, inlines are namespace-opaque. That means that you cannot simply route an event to another node in a different file unless it exposes an interface for that task. Inlines cannot do that.

    Externprotos can and do as we’ll see in the next installment of this tutorial.
  •