Virtual Calit2 Building
The goal the Virtual Calit2 Building is to provide an accurate and accessible virtual replica of the Calit2 building that can be used by any researcher or scientist to conduct projects or tests that require the need for a detailed architectural layout.
Contents |
Proposed Projects Using the Virtual Calit2 Building
Contributors
Daniel Rohrlick continues making further additions to the existing model. The first floor of the Calit2 building is coming closer to completion.
Philip Weber provided excellent assistance with model loading techniques.
Mabel Zhang is adding the first set of interactive dynamic elements to make the model more realistic.
General Structure
As dynamic elements were added, a more object-oriented structure is needed to maintain the model files.
The entire model is saved as one Max file, then from an individual or multiple layers, smaller files are saved again for final export. Currently, the entire model is organized into these parts:
- A loader to run the model and allows turning on and off layers to allow for maximum speed; manual VRML script.
- Main model, this is the exterior of the building and miscellaneous parts; this inlines inlineDoorAnimated.wrl, inlineElevInit.wrl, and inlineLightSwitScript.wrl for corresponding dynamic effects.
- Floor 1 in the main building and furnitures; exported directly from 3ds Max file's corresponding layers.
- Floor 1 New Media Arts Wing rooms; exported directly from 3ds Max file's corresponding layers.
- Floor 2; exported directly from 3ds Max file's corresponding layers.
- Floor 3; exported directly from 3ds Max file's corresponding layers.
- Floor 4; exported directly from 3ds Max file's corresponding layers.
- Floor 5; exported directly from 3ds Max file's corresponding layers.
- Floor 6; exported directly from 3ds Max file's corresponding layers.
- All animated doors; this file contains only those doors that are animated; physical door objects are exported directly from 3ds Max, partial VRML code is added from modifying exported code.
- Elevator initializer; initialize and create 3 elevators from a script PROTOtype (see below); mostly manual VRML script.
- Elevator prototype; include code for 1 set of elevator's movement, audio, and other operations; the initializer creates 3 copies of this prototype to create 3 independent sets of elevators; physical objects are exported directly from Max with 1 line of code changed to link to the script, core logic is done by manual VRML script with JavaScript.
- Light switch; include code for light object's on and off controlled by 2 separate switches; physical objects are Max-exported, logic is manual VRML script with JavaScript.
- (Elevator physical objects; not directly required for run-time, but contains elevator objects exported from Max; the entire content of this file is pasted into the Elevator prototype file in order for the logic to link to objects.)
- (Light switch physical objects; not directly required for run-time, but contains light objects exported from Max; the entire content of this file is pasted into the Light switch file in order for the logic to link to objects.)
- (A readme file prepared for future maintenance; include most, if not all, of the necessary changes that need to be made to a directly Max-exported file for all the parts to run correctly.)
Modeling in Autodesk 3ds Max
Modeling in Max with VRML export in mind
Because the final version of the model is in VRML format, during the modeling process in 3ds Max, the most important thing to keep in mind is that not all effects will export to VRML. 3ds Max comes with a detailed user reference that includes some useful tips and exporting rules on VRML. Not all materials are exported, not all lights are exported, different geometry types export to files of significantly different sizes, etc.
Post-exporting
From many websites focusing on projects using 3ds Max + VRML, it is suggested that the Max-exported VRML file should be checked and edited manually for the final version. For a static model, this is quite simple; the most often hand operation would probably be commenting out automatically generated looping timers and interpolations, which will continuously generate polygons during run-time. However, for a model with logic scripts, the exported code must be combined with the manual script into a single file for the effect to work; simply inlining the exported object file or the script will not suffice, because VRML requires that the script and the objects be in the same file for the linking to take effect, otherwise syntax errors will result. This means that either the exported file contents will need to be pasted into the script file, or vise versa, so a clear structure and documentation is even more important.
....more to come
Dynamic Elements
Automatic Doors
These are probably among the simplest dynamic elements to implement; nevertheless, they are a nice addition.
Key elements:
- VRML97 Proximity Sensor (to detect user entrance to the area around the door)
- VRML97 Time Sensor (to control animation of door's opening or closing)
The method is very straight forward. For each set of door(s), first we create the door's opening animation in Max by turning on AutoKey, scrolling to a frame (e.g. 30), rotating the door about its axis, then copying frame 0 to a later frame (e.g. 60). Now create a proximity sensor around the door(s), extending the sensor's length and width as far as desired. Then we created two time sensors, one for the door opening animation (frame 0-30), the other for the closing animation (frame 30-60). The time sensors' controlled frames can be set in 3ds Max Modify Panel. Finally, link the proximity sensor to the time sensor in 3ds Max (This appears as a ROUTEing in exported VRML code), and now the door(s) will open as the user enters the space enclosed by the proximity sensor.
To close the doors when the user leaves the space, although we have seen a few discussions online that suggest that it can be done within 3ds Max, we could not find a way in Max. Thus we accomplished the automatic door closing by manually editing the exported code. The code we need to change is at the very end of the exported wrl file. For a door with the above linking done, its corresponding code at the end of the wrl file looks similar to:
ROUTE sensor_prox_floor1aud3.enterTime TO sensor_time_floor1aud3_1-TIMER.startTime
where sensor_prox_floor1aud3 is a proximity sensor of a door named floor1aud3, sensor_time_floor1aud3_1-TIMER is the time sensor controlling this door's opening animation (indicated by the suffix _1). To make the door automatically close, copy the above line and replace 2 places so that the new additional line looks like:
ROUTE sensor_prox_floor1aud3.exitTime TO sensor_time_floor1aud3_0-TIMER.startTime
where the proximity sensor's enterTime is changed to exitTime, and the time sensor's name's suffix is changed from _1 to _0 because our naming strategy is _1 for the sensor controlling opening animation, _0 for the one controlling closing.
Keep both lines and do the same with the rest of the ROUTEing lines at the end of the exported file. (The other ROUTEing codes in the file are for the time sensors, door objects, etc., not related to the proximity sensor.)
Now the door will open when the user approaches it and close when the user leaves it.
....will have gif
Working Elevators
We used the German Mailand Mercedes car dealership model's elevator core code as a reference and built our own set of code to fit the Calit2 elevators.
The elevator has 2 parts, an intializer and a user-defined PROTOtype file. (PROTO is a keyword in VRML, stands for PROTOtype, and just means a user-defined data type.) The PROTO file defines one set of elevator, including its physical objects and all necessary scripts. The initializer creates 3 instances of this PROTOtype at the corresponding locations of the 3 main elevators in the building.
Detail documentation is included in the actual files.
A drawback of the current approach is that it cannot simulate the exact logic of the elevators in the real building. The virtual elevators currently operate independently, while the real ones are dependent. For example, in reality, there are 2 sets of buttons to call the elevator, and when a user calls the elevator from a floor, whichever elevator cab that is the most "convenient" will come to the user; in the virtual building, there are 3 sets of call buttons, and each elevator responds only to the set of buttons linked to it, meaning that the user controls whichever elevator will come by pressing on the corresponding set of buttons. We took the current approach because it involves less logic and linking and is less time-consuming; it only requires 1 set of definitions that can be initialized 3 times to generate 3 elevators. However, simulating the realistic logic will make the model more intelligent and believable.
Light Effects
....more to come
VRML Scripting + JavaScript in General
To use JavaScript in a VRML wrl file, create a script node, and use an inline url to include the javascript:
DEF WhateverScriptName Script { eventIn SFWhateverType WhateverName1 eventOut SFWhateverType WhateverName2 field SFWhateverType WhateverName3 # JavaScript begins here url "javascript: function WhateverFunctionName (Param1, Param2) { // Function definition } " # JavaScript ends here } # ... # Usually at the end of the file ROUTE WhateverObjectName1.WhateverFieldName1 TO WhateverObjectName2.WhateverFieldName2
A Script node can have however many eventIns, eventOuts, and fields. eventIn is used to ROUTE some outside node into the script, where the necessary logic is handled; eventOut is used to ROUTE some value set within the script to some outside node, usually to trigger an action; field is the local variables in the Script node. For a list of data types and detail information, see the Official VRML Specs Website.
Each eventIn should have a corresponding function with the same name as the eventIn field. The first parameter of the function is the value ROUTEd in to the eventIn. The second parameter (optional) is the currentTime time stamp when the event is ROUTEd in. To trigger a function in the script, ROUTE some node (e.g. a TimeSensor) outside the script to an eventIn corresponding to the function (same name as the function) in the script.
Once an eventOut is given a value (usually from within a function), the eventOut automatically ROUTEs out from the Script node to whatever they are ROUTEd to. To trigger an outside action from within the script, set the value of an eventOut, and ROUTE that eventOut to some node (e.g. a PositionInterpolator, a TimeSensor) outside the script.
ROUTEing scripts are usually placed at the end of the file.
Hints:
- Putting the functions and the ROUTEing codes in a logical order helps in the debugging process, especially when the actions involve a long process that goes back and forth between the Script node and the outside (like the elevator code).
- Use VRML style commenting (# single-line) anywhere in the file except in the inlined url JavaScript section - use JavaScript style commenting (// single-line, /* */ multi-line).
- If there are hand-written scripts, use a VRML text editor to find syntax or symmantic errors before running the wrl file in a browser. There aren't many VRML editors, but a good one to use is VrmlPad. It's a shareware and is not too useful when need to save large files (the shared version only allows 64K max), but it's very handy in finding syntax or symmantic errors. VrmlPad's status bar shows the type of present errors in the lower right corner in highlighted background colors; double-click on the highlighted error type, and it will take you to the next line with the chosen error, which will be dot-underlined in color. There is also a "Next Error" button on the toolbar, the icon is a hammer with a curved arrow.
....more to come?
Optimization
The difference between a very nicely and smoothly rendered architectural scene and a real-time 3D model is that the former allows for rendering ahead of the time, and the latter requires rendering on the fly. Because of this, in order to reach the maximum navigation speed in the architectural model, some details need to be sacrificed; this includes the smoothness of surfaces, details in objects, resolution of textures, etc. The VRML language itself already has some features to enable fast real-time rendering such as the lack of shadows so that no shadows will need to be calculated for rendering; this is also part of the reason that VRML does not support all of the effects from 3ds Max, and the non-supported features are not exported to VRML files when using the 3ds Max exporter.
Our main approach was to reduce the polygon count, to shrink texture file size, to reuse textures, and some other more minor methods.
Reducing polygon count in 3ds Max
3 Max modifiers to help reduce polygons and vertices:
- MultiRes
- Optimize
- Vertex Weld
These can be found in the Modify Panel > Modifier dropdown list
MultiRes is the most extensively used method in the Calit2 virtual building. It allows directly typing in the desired percentage of vertex count, then automatically generates the image according to the set percentage. It is officially better than the Optimize modifier, as stated in the 3ds Max 9 User Reference from the Help menu.
Optimize sometimes can have an effect when MultiRes does not. However, most of the time, MultiRes reduces more polygons and gives better images that aren't distorted.
Vertex Weld combines nearby vertices according to the user-defined distance between vertices so that the mesh is clean. This works even when the Merge Vertex option in MultiRes modifier does not have an effect.
In this model, MultiRes usually reduces quite a large amount of polygons (reduction ranges from around 10% to 80% of the original), but sometimes we use MultiRes in combination with Vertex Weld. The Optimize modifier is seldom used in this model.
Recreate meshes as primitives when possible
VRML defines meshes by listing the coordinates for each vertex, which can be in terms of thousands when the mesh is even a bit complicated. On the other hand, it defines primitives by a built-in node type like Box and defines its few fields. According to the 3ds Max User Reference, spheres, cylinders, and cones also export as primitives. There might be others.
Thus, creating primitives instead of meshes can reduce file size. A primitive can be converted to a mesh at two mouse-clicks, but converting backwards is not as easy. We remade some cylinders and boxes that were originally meshes as primitives so that the exported file is much smaller. Making identical objects as "instances" of these new primitives will reduce file size even more. See the instances section.
Shrinking texture image sizes
....more to come
Reusing textures
We need to manually edit the exported VRML file to use DEFs/USEs keyword for ImageTexture nodes so that texture memory can be conserved.
3ds Max exporter does not do this for us; instead, it uses a url field for all ImageTexture nodes, which results in a reload of a fresh copy of the texture file every time it is used. So if a texture file is being used 100 times in the model, the Max-exported VRML code will freshly reload that file everytime it is used, instead of just loading it once and using the copy in memory. This results in 100 times more memory use than necessary.
To edit the code, use any text editor with multiline replace function. We used NoteTab.
#old syntax example for all original Max-exported ImageTexture nodes texture ImageTexture { url "SomeMapsDirectory/SomePic.tif" }
#new memory-efficient syntax for ImageTexture node of the 1st appearance of the texture file texture DEF SomePicName ImageTexture { url "SomeMapsDirectory/SomePic.tif" ) #new memory-efficient syntax for ImageTexture node of the 2nd-and-on appearances of the texture file texture USE SomePicName
The DEF keyword gives the first appearance of the file a name; and then the USE keyword in later appearances of the map file references that name so that the texture map does not have to be reloaded into memory again.
(Re)Making identical objects as instances
This reduces file size by 3ds Max automatically using DEFs/USEs for -FACES and other nodes.
....more to come
Misc. Debugging Ideas and Tricky Surprises
Like anything else, the 3ds Max VRML exporter is not always perfect; it sometimes generates unwanted results that needs to be manually taken care of.
Automatically Generated INTERPs and TIMERs
Symptom: In the Terminal running OpenCOVER, the line showing the polygon and vertex count keeps flying up the screen, and the two numbers of counts keeps increasing.
If there are grouped objects in a scene, after exporting the scene, open the VRML file and search for "INTERP" or "-TIMER". It is very likely that a ...-TIMER object has been automatically generated below the group name DEFinition, and its characteristic is that its definition is single-lined, its loop is TRUE, and its CycleInterval is the 3ds Max animation track bar time divided by 30 fps (if using the default track bar, 0-100 frames, then the CycleInterval will be 3.333). Along with the timer, sometimes a corresponding INTERP is generated and is ROUTEd by the timer. These timers and interpolations are the culprit of continuously generated polygons during run-time in OpenCOVER. The solution is to simply comment out the timer's definition and the corresponding ROUTEing lines; there are usually 3 in a set. If it seems that the interpolation is not routed to by anything else, it might be harmless to delete the entire definition, since it is often many lines long; but we have not test this thoroughly as to guarentee it.
On the other hand, if there are mesh animations in the scene, then these INTERPs and -TIMERs are necessary for the animation; leave them as they are in the file. Mesh animations are animations that involve sub-object level changes such as vertex or polygon generations. Simple translations, rotations, and scaling do not fall into this category; these usually do not need the automatic generated INTERPs mentioned above, which can be commented out in the usual case.
....more to come
Light Attenuation
Symptom: 3ds Max exporter simply does not export the correct attenuation.
A third-party exporter called Mark's shows a comparison of the 3ds Max exported attenuation effect with the supposed effect.
Unfortunately, the said exporter seems to only support up to Max version 4. Thus, to solve this problem, we can manually play with the attenuation field of the light node by trial-and-error. The attenuation field is a three-value vector, and in OpenCOVER, it seems that using any positive number for the second or the third value would just result in no lighting at all. For the first value, the larger the number is, the stronger the attenuation, and thus the dimmer the light. We have not experiment with negative numbers in these fields.
Attenuation field does not exist for directional light; it exists for both point light and spotlight.
...more to come
Future Work
Elevators
Implement functions to simulate the building's:
- Arrow light lighting up when cab arrives at user's floor
- Sound effect when cab arrives at user's floor
- Sound effect recorded from building's elevator (current ones are taken from another model; they aren't fully tested yet)
Realistic Environment
- Stylized people walking along defined paths in the building
- Realistic sensor information obtained from building's temperature, CO2, humidity, etc. sensors
....more to come
More Images
The Calit2 building viewed in wireframe mode.
The Calit2 Building shown with photo-realistic textures.
A view of the interior lobby of Calit2.
....more to come
Links and References
VRML Specs main page (links to VRML 1.0 specs and zip files)
Lighthouse 3D Tutorials: TimeSensor Specs
Lighthouse 3D Tutorials: VRML Lighting Nodes
Mark Callow's VRML97-X3D 3ds max Export Plug-in