A PROTO is similar to a Group, but more versatile, and useful e.g. when scripting animations. Avatars with gestures are always done by using PROTOs. There are two kinds of PROTOs;
EXTERNPROTO and
PROTO. I like to think of them as the stylesheets of VRML. They can be anything from very simple (e.g. a definition of colour) to very, very complex (and that's beyond this guide and beyond me!)
The best thing about PROTOs, in my opinion, is when you have several instances of the same object and want them all animated independently. I once made a chocolate box and animated each piece of chocolate separately, to disappear when clicked. If I had used references, all of the pieces would have dissappeared when any one of them were clicked. But with PROTOs, you can make one piece of chocolate, animate it to dissappear and then use 30 PROTOs - each one will only dissappear when you click that one, and it will save you time and make the filesize smaller. Too bad I didn't know that, when I made the chocolate box! (I also use it for things like doors, where of course clicking on a door should open only that door and not every door in the house...) Another example of when PROTOs come in handy, is when you have two or more items that consist of several parts (e.g. a table) and you want several tables in your scene, but they should all have different colours. You could build each table of referenced geometries with new colours, or you could use a PROTO. Here's an example with two simple PROTOs (Note that the word is always in all-caps in the code):
#VRML V2.0 utf8 WorldInfo { title "PROTO" info ["handcoding vrml - using PROTOs"]}
PROTO blue_mat [] { Material { diffuseColor 0 0 1 }} PROTO box_geo [] { Box { size 1 1 1 }}
Shape { appearance Appearance { material blue_mat {} } geometry box_geo {} } | |
Take note of the "pattern" of writing a PROTO: first you declare that it's a PROTO, then comes the name of the PROTO, then the [ ] brackets that can include additional info (see below: the brackets should always be included, even when empty) and then the part of code that you've turned into a PROTO. As always, make sure the number of { brackets corresponds to the number of } brackets and note that the code that makes up a PROTO corresponds to the part of code that you could DEFine, e.g. Group, Shape, Material (but not material Material) etc... You can name the PROTO anything you want, as long as you stay away from the reserved terms (such as PROTO itself or Group, etc.). I usually name colours as above; with _mat for material or _app for an appearance, _tex for texture and sometimes _geo for geometry. It helps me remember the names of the PROTOs and keep track of what is what. (I've also noticed that other people and some programs do the same so I can't take credit for the clever idea...) To call on the PROTO you only need the name (blue_mat, box_geo) and the {} that represents the code inside the PROTO brackets. Another example:
#VRML V2.0 utf8 WorldInfo { title "two tables" info ["handcoding vrml - using PROTOs"]}
PROTO Table [ field SFColor leg_color 0.4 0.2 0.1 field SFColor top_color 0.5 0.1 0.1 ] { Group { children [ Transform { translation -0.5 0.5 0.5 children [ DEF table_leg Shape { appearance Appearance { material Material { diffuseColor IS leg_color }} geometry Box { size 0.08 1 0.08 }} ]} Transform { translation 0.5 0.5 0.5 children [ USE table_leg ]} Transform { translation -0.5 0.5 -0.5 children [ USE table_leg ]} Transform { translation 0.5 0.5 -0.5 children [ USE table_leg ]} #table top Transform { translation 0 1 0 children [ Shape { appearance Appearance { material Material { diffuseColor IS top_color }} geometry Box { size 1.1 0.1 1.1 }} ]} ]} #(end group) } #end of PROTO
Table {} Transform { translation 1.5 0 0 children [ Table { top_color 0.1 0.1 0.5 } ]} | |
The table in the above PROTO is the same as I've used before (in "Group, Switch & Referencing"). But as you can see I've now added a couple of fields in between those first [] brackets. There are other fields than colour, which can be included here, but I refer you to a vrml reference manual or something for those. I don't really have the hang of them myself... Anyway, colours are easy enough. You tell the computer you will define something by writing "field" and then what type of field it will be - "SFColor" (note the three caps in a row). Then you give a name to your colour, e.g. top_color, and the RGB values that will produce said colour. In the appearance nodes then, you type
diffuseColor IS top_color and this will tell the computer that unless some other colour is specified when the PROTO is called, the table should have this colour. In this case brown legs and a red top. Then, when you call the PROTO, you can choose to define another colour, as is done in the last row of code, above. Notice how all you have to do now, is write the name of the colour you want to change, and the RGB values, inside the {} brackets of the PROTO? No need to rebuild the table top.
A tip and a note: You can use a previously defined PROTO within a subsequent PROTO. It's a good idea to define colours and textures first, appearances later (because they can call on the colours and textures) and then shapes (that can call on appearances). You can also use DEF/USE
within a PROTO but you can't USE something in the rest of the file or a subsequent PROTO that was DEFined in another.
EXTERNPROTOs are basically the same thing as a PROTO, only it's located in a file of its own and is called from your file. It can be another file of yours, or it can be from e.g. the Blaxxun Platform. The Cybertown Designer Homes, Avatars and items with SharedEvents (animations that all users in the world can see, regardless of who triggers it) need such Blaxxun EXTERNPROTOs. If you're making a world consisting of multiple files (and hosted on your own server), a separate file with a list of EXTERNPROTOS for materials and items that are used in more than one file can be very useful. If you decide you want to change a colour, for instance, you'd only need to do it in one place, not in every file where that colour was used. Name your file of EXTERNPROTOs something like "protos.wrl" (for example). Then, at the top of the files where you'd otherwise list PROTOs, you'll list the EXTERNPROTOs instead, and to call on it, you use them same code as for an ordinary PROTO:
EXTERNPROTO blue_mat [] "protos.wrl#blue_mat" material blue_mat {} To end this section, here's an excellent use of an EXTERNPROTO:
Bashkirtsev's Particle Tutorial (useful for animated flames, smoke, bingo balls and whatever else you can think of!)