home *** CD-ROM | disk | FTP | other *** search
-
- C I N E C H E M
- Molecular Rendering and Animation with HyperChem and 3D Studio
-
- --- with ---
-
- S T I N G R A Y
- Stingy Ray Tracer
-
- Distribution Notes
- Release 0.3 -- 13th October 1992
-
-
- CONTENTS OF THE DISTRIBUTION
- ============================
-
- When you copy the CINECHEM release disc or unpack the ZIPped archive,
- you should find the following files:
-
- Cinechem:
- CINECHEM.EXE CINECHEM 386 DOS Extender executable
- CINECHEM.DOC CINECHEM user documentation
-
- Sample input files:
- C60.HIN Sample molecule for still rendering (Buckminsterfullerine)
- PADAM.HIN Sample molecule for animation (Adamantine)
- PADAM.SNP Sample snapshot file for animation
- GAUDY.CFG Sample configuration file
-
- StingRay:
- STINGRAY.EXE STINGRAY 386 DOS Extender executable
- NFF.DOC SringRay input file format documentation
-
- Piclab:
- PICLAB.ZIP PICLAB public domain image processor archive
-
- And last but not least:
- README.DOC This document
-
-
- SAMPLE MOLECULE AND ANIMATION
- =============================
-
- In case you don't have a copy of HyperChem but would still like to try
- CINECHEM, I've included two ready to render sample molecules: one for
- a still rendering and the other an animation.
-
- To demonstrate still rendering, try:
-
- CINECHEM C60
-
- This will create C60.3DS, a 3D Studio model of the ubiquitous
- Buckminsterfullerine molecule. Try loading this model into 3D Studio
- and rendering it in various ways. This is a "space filling"
- representation of the molecule; for a "stick and ball" rendering, try:
-
- CINECHEM -S C60
-
- Next, try an creating an animation from the sample molecular dynamics
- simulation included. This is a totally physically unrealistic
- simulation of the relaxation of a molecule of adamantine (which can be
- thought of as the smallest possible diamond), when one of the bonds to
- a surface hydrogen has been stretched by Kelvin's Atomic Tweezers.
- The HyperChem-generated snapshots of the simulation are stored in the
- files PADAM.HIN and PADAM.SNP. Create the animation from these files
- with the command:
-
- CINECHEM -S PADAM
-
- Molecular dynamics simulations generally look better when rendered as
- stick and ball models. Load the resulting PADAM.3DS file into 3D
- Studio, move to the Keyframer, convert one of the viewports into a
- Camera viewport by clicking it then pressing "C" on the keyboard, and
- try moving the frame number slider along the bottom of the screen.
- Neat, huh? Finally, go ahead and make an animation of the simulation,
- if you like.
-
- Each atom in a snapshot animation (and in a simple model, if you
- specify the "-K" option when you call CINECHEM) is made a child object
- to a dummy Keyframer object representing the molecule. Thus, it's
- very easy to manually animate the components of multi-molecule
- systems, for example to detach a molecule from its binding site on
- another for an "exploded view" of the site.
-
-
- DEVELOPMENT LOG
- ===============
-
- Changes in CINECHEM 0.3
- -----------------------
-
- Major code cleanup and ANSI-compilance fixes all over StingRay.
- StingRay now builds without warnings and runs correctly on the Sun
- SPARCStation, including the ability to create Microsoft .BMP files in
- the correct (Intel) byte order. Building StingRay on the Sun requires
- ACC.
-
- When generating a StingRay format (.NFF) output file, I added comments
- to the "f" (material properties) statements which identify each atom's
- element type by chemical symbol and each bond by the bond letter code
- followed by a "-B" ("S-B" for single bond, "D-B" for double bond,
- "T-B" for triple bond, and "A-B" for aromatic bond). StingRay's input
- language lacks the nice macro facilties we exploit in 3D Studio (when
- the "-M" option is specified) and in POV to permit easy after-the-fact
- experimentation with different material types. But, by including
- these guaranteed-unique comment strings in the .NFF file, a clever
- user can use a text editor or a utility like AWK to scan the file and
- selectively replace the material property definitions for a given
- element and/or bond type.
-
- I modified StingRay so that when it's generating either a Targa or a
- Microsoft BMP file, it always writes the complete pixel area of the
- file at the start, filling it with grey pixels, then returns to fill
- in the actual pixels as they are calculated. This has two salutary
- benefits. First of all, if there isn't enough disc space to write the
- output image file, it's a lot better to discover this right at the
- outset instead of 60 hours into a ray-trace; writing the file at the
- beginning guarantees that space is reserved for it on the disc.
- Second, taking advantage of the fact that we don't compress either
- form of file, partially completed files are 100% valid throughout the
- process of generation. This permits the user with a multi-tasking
- system to "vulch" on the process of ray-tracing: view the file, as it
- is being created, with any .TGA or .BMP display program. This allows
- "quick looks" at the file which can on occasion avert tragedy.
- Second, if something terrible happens and the trace is aborted, at
- least the portion completed will remain on the disc in viewable form.
-
- There was bug in StingRay's .BMP file output which caused the image to
- be shifted up one pixel, with the bottom pixel row left black. Fixed.
-
- Viewpoint calculation for RenderMan was *still* screwed up--in some
- cases the camera roll angle had the wrong sign. (Do these renderer
- makers make up such weird ways of specifying the viewing transform
- just to give their users fits? No two renderers I know of share the
- same kind of projection and viewpoint specifications!). Fixed (I
- think).
-
- I added a new "-K" switch to CINECHEM which forces keyframe data to be
- created even if the input is a static model (.HIN-only) file rather
- than a snapshot (.HIN/.SNP pair). This option affects only 3D Studio
- output. By creating the keyframe data for a void animation, the
- hierarchy of atoms and bonds to molecules can be established. This
- allows easy after-the-fact animations to be created by specifying
- keyframe data for the various molecules. For example, you might show
- a molecule bound to the active site of a receptor molecule, then move
- it outward for a close-up of the binding site.
-
- I took a run at CINECHEM with SMARTALLOC and MALLOC_DEBUG and
- discovered that when the "-K" option was specified, OUT3DS was freeing
- three buffers it never allocated (plus closing a file it never
- opened), and that PURGESYS forgot to release molecule names and the
- header for the entire system. All fixed.
-
- Still more fixes to viewpoints and keyframer information for 3DS
- format, both to logic in CINECHEM and to correct bugs in 3DSLIB
- itself. CINECHEM was calculating the relationship between "lens
- length" and camera field of view (needed because 3D Studio can't make
- up its mind which format it prefers; lens length is used in the 3D
- Editor, but field of view is specified in the Keyframer) by performing
- the correct geometrical calculation as described in the book
- "RenderMan Companion". Unfortunately, 3D Studio uses a totally bogus
- linear interpolation of this highly nonlinear (tangent) function, so
- the accurate numbers I was generating didn't agree with those used in
- 3DS. I converted my code to call the new 3DSLIB routine FOVToLens
- (note that the function is *not* called FOVToLens_3ds, as documented
- to be on page 28 of the 3DSLIB manual), which reproduces the erroneous
- values used in 3D Studio.
-
- The very confusion in 3DS about whether it's lens length or field of
- view tripped up the camera motion specification function in the 3DSLIB
- module CAMM_3DS.C. When it was creating the initial (frame 0) motion
- key for the camera, it retrieved the lens length from the camera's
- record for the 3D Editor and jammed it into a cell that was supposed
- to be a field of view. You have to add the code:
-
- /* ***FIX*** Translate camera "lens length" into field of view as
- used in the keyframer. */
- { double dstfov;
- LensToFOV(*stfov, &dstfov);
- *stfov = dstfov;
- }
-
- right before the return from the internal function InitCamState to
- correct this. Note that LensToFOV() returns its result in a double,
- unlike FOVToLens() which expects a pointer to a float. Is this
- obscure or what?
-
- The dummy objects I created to link the atoms to their parent
- molecules weren't being treated as dummy objects. Turns out DUMMYNAME
- in 3DS.H was defined as "$$DUMMY" instead of "$$$DUMMY" as 3D Studio
- expects. This is also documented incorrectly on pages 36 and 43 of
- the 3DSLIB manual in the descriptions of the header definitions and
- the KF_MESH structure, but is correctly given on page 75 of the same
- manual in the documentation of the NODE_HDR chunk.
-
- When animating a snapshot, the "active segment" in the Keyframer is
- set to run from frame 1 through the number of snapshots. This avoids
- the user's seeing the weird basic geometry of the bonds in frame 0.
- But when creating a keyframe hierarchy for manual animation (with the
- -K switch), we want the segment to start at frame 0 so the basic
- geometry is accessible. I added a special case for that, and set the
- initial animation length to 30 frames, just as 3D Studio assumes.
-
- Note that the SetCurrent_3ds() and SetSegment_3ds() functions are both
- incorrectly documented on page 32 of the 3DSLIB manual; to reproduce
- the default animation created by 3D Studio from a model, you have to
- start both the segment and set the current frame number to 0. The
- manual says the range of valid frame numbers is 1-32000, but in fact
- the functions correctly accept frame number 0.
-
- As soon as I implemented the object hierarchy for molecules,
- everything went totally weird, and it took me the better part of a
- week to chase down the 3DSLIB bug that was causing it. The author of
- 3DSLIB was tripped up by some additional bizarre behaviour in 3D
- Studio. When you're creating the keyframer data for a mesh object
- with ObjectMotion_3ds(), an initial rotation key must be generated for
- frame 0 (regardless of whether you've specified any rotation keys of
- your own). The code that created this key, in OBJM_3DS.C, was:
-
- strot.angle = PI * 0.5;
- strot.x = 1.0;
- strot.y = 0.0;
- strot.z = 0.0;
-
- Now that looks pretty weird to start with, 'cause on page 77 of the
- 3DSLIB manual, the angle field of the ROT_TRACK_TAG chunk is
- documented as being "Rotation angle in degrees". Okay, so I changed
- the PI * 0.5 to 90. Things got *much* worse. After a lengthy period
- of cybernetic psychoanalysis, I finally established that the correct
- code to set the angle should be the following:
-
- strot.angle = (strcmp(obj->name, DUMMYNAME) == 0) ? 0 : (PI / 2);
-
- Why is the initial rotation of objects imported from the 3D Editor 90
- degrees (in radians, of course), but zero for dummy objects? Beats
- the shit out of me, but go and make some of your own in 3D Studio and
- look at the Key data it generates for them. That's how I finally
- figured it out.
-
- Note also that the documentation of the KF_ROT structure on page 43 of
- the 3DSLIB manual (which is what we're talking about initialising
- above) doesn't mention whether the rotation angle should be specified
- in degrees or radians. It's degrees, notwithstanding the fact that
- the internal database stores it in radians, notwithstanding the fact
- that page 77 documents it as degrees.
-
- As I mentioned in the notes for CINECHEM 0.2, I defy anybody who
- attempts to use 3DSLIB to generate non-trivial camera placements or
- camera motion without having access to the following code:
-
-
- /* CAMUPVECTOR -- Calculate camera up vector used by 3D Studio
- given camera location, target point, and bank
- angle. This code kindly provided by Dan
- Silva, (dsilva@Autodesk.com). */
-
- static void CamUpVector(
- point cam, /* camera position */
- point targ, /* target position */
- double bnkang, /* bank angle (radians) */
- point up /* output: up vector */
- ) {
- double x, y, z, A, B, C, cA, cB, cC, sA, sB, sC;
-
- x = targ[X] - cam[X];
- y = targ[Y] - cam[Y];
- z = targ[Z] - cam[Z];
-
- if (y == 0 && x == 0) {
- /* Camera is pointed directly along the Z axis. */
- A = 0;
- } else {
- A = atan2(y, x); /* yaw */
- }
- B = atan2(-z, sqrt(x * x + y * y)); /* pitch */
- C = bnkang; /* roll */
- cA = cos(A); sA = sin(A);
- cB = cos(B); sB = sin(B);
- cC = cos(C); sC = sin(C);
-
- /* Then the Up vector is (let's hope) */
-
- up[X] = cC * sB *cA + sC * sA;
- up[Y] = cC * sB *sA - sC * cA;
- up[Z] = cB * cC;
- }
-
- This code, accompanied by a thorough tutorial-style introduction in
- how to use it in the manual, absolutely belongs as part of 3DSLIB.
- Without it, application developers will simply give up and require the
- user to place the camera himself in 3DS, or else one by one request
- this algorithm from Autodesk. This is the 3D Studio equivalent of
- AutoCAD's "arbaxis" algorithm, and you simply have to know how it
- works to get your code right.
-
- Any while we're at it, campers, here's the code that turns a
- rationally specified camera (in terms of camera and target points,
- plus normalised world-space camera up and right vectors) into the
- weird stuff that 3D Studio expects, using the function above.
-
- Given:
- point camera, target, up, right; /* All 3-vectors of doubles */
-
- Then proceed as follows:
- double xzlen, yrot, eyr, a, zrot, fa, fb;
- point p, eax, cup, cx;
- DPOINT p1, p2;
-
- Cpoint(p1, camera); /* Copy doubles to floats for 3DS */
- Cpoint(p2, target);
-
- vecsub(p, target, camera);
- vecnorm(p, p);
-
- /* Calculate rotation about the Y axis to turn the Z
- axis (camera view direction) to the proper azimuth
- in the X-Z plane. */
-
- xzlen = sqrt(p[X] * p[X] + p[Z] * p[Z]);
- if (xzlen == 0.0) {
- yrot = (p[Y] < 0) ? 180.0 : 0.0;
- } else {
- yrot = todeg(acos(p[Z] / xzlen));
- }
-
- /* Calculate rotation about Z axis to align the X axis of
- the co-ordinate system (still in the X-Z plane)
- with the "right" vector of the camera. */
-
- eyr = p[X] > 0 ? -yrot : yrot;
- Spoint(eax, cos(torad(eyr)), 0, sin(torad(eyr)));
- a = vecdot(eax, right);
- zrot = todeg(acos(a));
- if ((p[X] * right[X]) < 0) {
- zrot = -zrot;
- }
- CamUpVector(camera, target, 0.0, cup);
- veccross(cx, cup, up);
- fa = vecmag(cx);
- fb = todeg(asin(fa));
- twist = fb * ((cx[Z] * p[Z]) > 0 ? 1 : -1);
- AddCamera_3ds("Camera1", p1, p2, twist, lens, TRUE);
-
- SMARTALLOC revealed that INIT_3DS.C is allocating a temporary buffer
- for the file name but not bothering to release it. In INIT_3DS.C,
- change the file open code to:
-
- mainfp = fopen( cp, "w+b" );
- free(cp);
- if (mainfp == NULL)
- return FAIL_3DS;
-
-
- Changes in CINECHEM 0.2
- -----------------------
-
- The definitions of the GOLD and COPPER material types for triple and
- aromatic bonds when the "-M" option was specified were incorrect and
- unaesthetic. I fixed them to correspond closely to the GOLD and
- COPPER material definitions in the 3D Studio standard material
- library.
-
- CINECHEM got all shook up if the generation of atoms were suppressed
- while generating an animation (for example, you turn off hydrogens or
- water molecules for a less cluttered animation of a simulation).
- Fixed.
-
- Support was added for the following new output file formats and
- renderers:
-
- NFF StingRay
- RIB Autodesk RenderMan
- POV Persistence of Vision Raytracer
-
- StingRay is now included in the CINECHEM distribution.
-
- Since the DOS Extender version now works in the Windows DOS box, any
- system which can run HyperChem should be able to execute CINECHEM and
- StingRay in a DOS window. Consequently, the real-mode DOS versions of
- these programs have been discontinued. Note that thanks to the gentle
- ministrations of DPMI, you can run CINECHEM from the DOS shell of 3D
- Studio.
-
- Thanks to Dan Silva, who gave me the code that 3D Studio uses to
- calculate the default camera up vector, correct twist angles are now
- generated based on the viewing transform found in the .HIN file (at
- least for all the cases I've tried!).
-