==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Thursday, January 22, 1998 5:17 AM To: CTGPROG @ MAXIS-SM,EAHQ Subject: Major check-ins; stuff should compile I hope! I've completed some extensive framework surgery, and checked everything back in. TDS and Edith and Sims all build, again, I believe. So far I have the new framework running on NT with a placeholder DDD demo, and the stripped down TDS comes up in its own window. The DDD demo doesn't run at the same time as the TDS window, though, since I haven't grafted the TDS application stuff onto the DDD demo stub yet. But I did do a lot of work towards making that possible. Got rid of LineTo and MoveTo macros that were messing with framework methods of the same name. Made the Sims project compile with precompiled headers. Stripped out many dependancies on gHouseWindow, and consolidated several places where there were two names for the same global or class, etc. Collapsed and simplified some viewer related classes. Cleaned up creation and destuction handling for the house window. Made a global gHouseView that many places in the framework were happy to deal with instead of hHouseWindow. Lots of other stuff to TDS, and some random stuff to the framework, like stashing the hInstance arg to WinMain in a global. I still need to hose out the static initialization nightmare in cAnimDeviceSub and friends, as predicted by EDB's 5/7/97 comment, before getting the game to come up smoothly inside of a new framework window. Brain hurts. Must sleep! -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Thursday, February 05, 1998 9:23 AM To: CTG @ MAXIS Cc: Mackraz, Jim; London, Charles; Chin, Eric; Hedman, Eric Subject: Animation problemo solvedo Here's the problem: The animation exporter was not realizing that it should export the translation for the biped pelvis. The biped pelvis has a translation track that is necessary to keep the distance between the center of gravity and the pelvis consistant. If the pelvis doesn't have a translation track, that explains the misbehavior. Sure enough it doesn't, in the new animations. I had some special code in the exporter to recognize that 1) it was a biped skeleton, 2) the bone had a parent, and 3) the parent was the root, so it automatically exports the translation of that bone, assuming it's the pelvis. For some reason it's failing to recognize the pelvis, but I don't know why. I tried very hard to get the exporter to compile under the new compiler, but failed to get it to link. So I couldn't put a breakpoint there, but maybe the test to see if it's biped is screwing up. (It checked to see if the first 3 characters of the node name are "BIP", so maybe it's a case conversion thing). I went back to the old exporter, and tried to get it to export the pelvis translation track. Fortunately there is a tag just for that. You just put a note track on the biped's Pelvis, at any time, with the key "translation=1". Ta-da. Problem solved. Until I can debug and fix the exporter under the new compiler, the artists will unfortunately have to put these rackin fratzin translation tags into the animations. To do that, open up the object outline window, left click the square plus by "Objects" to open the objects, left click the square plus by "Bip01" to open the biped sub-objects, left click the round plus by "Bip01 Pelvis" to open the pelvis properties, left click to select the "Bip01 Pelvis" *label* (not the bullet box beside it), left click the "Add Note Track" icon to add a note track to the pelvis, left click the "Add Keys" icon to go into add keys mode, left click the left button at time 0 of the pelvis notes track to make a new note (or any other time really, just 0 is easier to find), then right click on the new note to edit its text, then type "translation=1" into the note window. Finally, save and re-export the animation, and check the .txt file to see if the skill has "Motion # 1" with "name: PELVIS" and "hasTranslation: 1". For the time being, we probably only need to do this to the animations that have problems, but there are a bunch of them, like the one where he shifts his weight left and right from foot to foot. I hijacked Charles's computer and applied the fix to "adult-bed-makel", and checked it in and tested it, and it works, and you can compare it to "adult-bed-maker" which isn't fixed, to see the difference, which is quite! Also I fixed the twitching problems it was having, relating to the "mixRootTranslation" and "mixRootRotation" flags being mis-applied. I made it actually detect when there would be a twitch in translation or rotation (relating to snapping the translation when sitting in chairs, or rotation when turning around), and supress the mixing of the root translation or rotation as appropriate. No more twitching!! I got the "hello" vitaboy animation demo integrated into the new project and mostly working with the new compiler. Just a repainting clipping problem really, but it worked good enough to diagnose the animation problems! -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Saturday, February 07, 1998 6:50 AM To: CTG @ MAXIS; willw@emf.net Subject: Latest Build I put the latest build with clock/panning/centering/zooming/turning/mode/people pie menus up on the server, in G:\projects\tds\latest build It used to be called "Lastest Build" but I corrected the typo, which was causing it not to run because the .ini file had it spelled right. I made a shortcut called "Play The Sims" that you can click on to run it with the -w option, hopefully! -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Sunday, February 08, 1998 11:47 AM To: CTG @ MAXIS; willw@emf.net Subject: Graphical pie menus! Last night I implemented graphical pie menus, fixed the tracking to work exactly how Will and Jim and I discussed, and added lots of features. You can click the menus up and click again to pop them down. Double right click does a center. Click right, press, and drag does a pan. Click right, move, and press down to select a menu item. Press down, move, and release to select a menu item. Clicked up menus and submenus are now handled properly, triggering on the down press so they are consistant with the panning menu. Menus with 1 item display the item at the top. Menus with 2 items display them at the top and bottom. Menus with 3 or 4 items use the 4 compass directions, Menus with 5, 6, 7, or 8 items use the 8 compass directions. Menus with more than 8 items use the 8 compass directions for the first 8 items, and put the extra items above the top and below the bottom item, alternately. You can select the extra items by pointing at their label. You can now disable any menu item. Graphical menu items are implemented by passing an optional argument to AppendString, that is a cGZWinPushBtn, that you can configure with a bitmap with four different states, of which disabled, up and down are used. The bitmap may have a transparent color. The disabled bitmap can be stippled with the transparent color to appear translucent, and it looks really cool! The pie menus now draw nice little spokes out a small distance from the center to show the edges of the slices. The highlight color is now yellow for text. Menus can have some items text and some items graphical. The right button menu now has only 4 items on it: zoom in, zoom out, rotate left, rotate right. I've made nice bitmaps using the graphics from the panel. When you are at the closest and furthest zoom levels, the zoom in and zoom out items are disabled respectivly, so they look blurred and partially transparent. (It looked good to blur the bitmap before stippling it, to get rid of the high frequencies that would look bad through the 50% checkerboard stipple. Fortunately the diagonal edges lined up nicely with the stipple so they were not cancled out.) As an added bonus, hold down the control key when clicking the right button to get the expert menu! It's got twice as many items, with "Mode...", "Person...", "Next Person", and "Previous Person" on the diagonals. Fixed the code so that when you left click on an object with only one action, it pops up a menu with one item, instead of just doing the action, as per the discussion in the middle of the night with Will. Now you can see what that one action is, without doing it unwittingly. Much nicer now!! That's all I can remember right now, I was kind of on a rampage and now I need to eat and sleep again... Checking the stuff in and compiling an optimized build to put on the server first, though... -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Wednesday, February 18, 1998 10:04 PM To: CTGPROG @ MAXIS-SM,EAHQ Cc: willw@emf.net Subject: Face meshes in the menu center I've made a cut at drawing the live 3d face mesh in the menu center! I just love the idea of the head in the pie menu center smoothly animating, looking up, down, left, right and diagonally from the menu center, like Alice in the center of the Bradey Bunch grid. Here's a method I added to HouseViewer (and turned off since it doesn't quite work yet). It loops over the currently selected person's head meshes (including any hats and hairs, etc), and draws them in front of the camera. I had to add a couple public accessor methods to bust out the XAnimator and the VitaBoy. I don't have the transformation and lighting stuff down yet, but it is drawing a little head-like blob at a fixed place on the screen, that changes when I change people! The lighting needs some work since it's pretty dark, and the scaling and positioning needs some work, and there needs to be a mechanism for the object menu to tell the HouseViewer when to pop up the head, where the menu center is, and which direction to point the head. Once these problems are solved we are well on the way to live 3d heads in the menu center! The final touch would be to stipple a shadow behind the head with a proper z buffer, so the head is drawn in front of the stipple. It would be really cool if, before you move out if the inactive region, the head occasionally turns to glance in the direction of the item that the person wants the most; and when you are pointing at an item, the head would look toward the item, and also nod or shake to feed back how much the person approves of the action! -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Thursday, February 19, 1998 6:03 AM To: CTG @ MAXIS Cc: willw@emf.net Subject: Animation compression to 16% original size! I implemented a simple byte coded floating point compression scheme, that de-interleaves the data so it's continuous and compresses better. That means instead of writing out: vec3[0].x, vec3[0].y, vec3[0].z vec3[1].x vec3[2].y vec3[3].z ... vec3[n].x vec3[n].y vec3[n].z it writes them de-interleaved: vec3[0].x vec3[1].x ... vec3[n].x vec3[0].y vec3[1].y ... vec3[n].y vec3[0].z vec3[1].z ... vec3[n].z first all the x components, then all the y components, then then all the z components, and so forth with w components for 4d quaternions. It's tunably lossy, and uses a 254 element table of floating point deltas that can be vastly tweaked for better performance or accuracy. The two other byte codes represent a 16 bit integer repeat code, and an 32 bit absolute floating point jump code. It would be a lot more efficient to use a second order piecewise linear approximation instead of a simple first order repeat count. Then the compressor could recursively subdivide the stream of floating point values until it was of a given accuracy. But even with this crude un-tuned compressor, the binary floating point files are an average of 16% of their original size!! All the .bin files in total were 7,843,944 bytes and now they total 1,288,900 compressed! Now I need to implement a lru caching scheme to keep uncompressed animation around for a while then delete them when they haven't been used recently, then there should be a nice improvement in the footprint. And I need to upgrade the exporter to write out compressed binary floating point, and might as well make it read and write binary cmx files while I'm at it. Here's the debugging output of compressing all the .bin files: Compressing floating point files... Compressing xskill-adult-approve.cfp ... From 25440 to 3808 (14%). Total 25440 to 3808 (14%). Compressing xskill-adult-bored1.cfp ... From 64024 to 7526 (11%). Total 89464 to 11334 (12%). Compressing xskill-adult-comfortable1start.cfp ... From 12720 to 2245 (17%). Total 102184 to 13579 (13%). ... ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Wednesday, March 18, 1998 1:43 AM To: CTG @ MAXIS Subject: Animation timing Animation is much smoother now, and it's doing a lot less math every frame. (Math is hard.) I folded in the changes to set the milsPerTicks to 50 everywhere, and fixed VitaBoy so Practice::Apply takes a "pose" argument, that tells it to pose the bones or not. If pose is 0 it just moves the origin and delivers events. Render then calls apply with pose true, to actually blend the quats and move the bones. So it can be ticked any number of times without blending the quats, and the events get delivered and the body moved. I had to turn off the sticky foot code for this to work properly. I think we can turn sticky feet on at and slow speeds when it matters and leave it off at high speed when it doesn't matter. -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Thursday, March 19, 1998 3:21 AM To: CTG @ MAXIS; willw@emf.net Subject: Current character highlighting: Smootly blinking motive aura I've added a feature to highlight the current character, by brightning a circle around their head, that also gives some feedback about the overall motives, by tinting the circle red or green. The brightness blinks smoothly (like turning a dimmer) from dark to bright once a second, and during the bright period, the color is tinted either red or green, depending on one of the motives. It blinks one motive red or green each second, cycling through all 16 motives in 16 seconds. The edges of the circle are smoothly feathered into the background, so it looks like a colored spotlight. After the objects are rendered but before the people are rendered, I figure out where the currently selected person's head is, and brighten a circle around it, like the popup menu darkening. So the people are never brightened, just the objects and background, so they look crisp and steady, and the highlight looks like an aura! We could come up with more interesting ways to feedback the emotional state, like synchronizing the color with the feedback animations, and giving the motives higher level control over the aura colors, and implementing multi-colored auras. Now the code that censors the currently selected person looks at the actual bounding box of the person as drawn on the screen, and censors the whole person plus a little border (according to scale). We could hook this up to automatically censor a person if they had a certain highlighting flag on, and make it so tree code could turn the censor effect on and of on a per-person basis. There are several highlighting flags (cXObject::fHiliteMask), and the aura and censoring effects could just fit in as other kind of highlighting. (Is there a primitive to access the highlight flags?) We could have other kinds of censoring effects like hips only, head only, as well as full body. Would we ever want to censor objects as well as people? It's harder to figure out an object's exact bounding box. -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Friday, March 20, 1998 5:42 AM To: CTG @ MAXIS Subject: Animation exporter works under Max 2! Had to wrestle with Visual C++'s configurations and flags a bit, but I got it to work, after adding a new argument to the DoExport method. It now takes a supressPrompts argument to the DoExport function. MaxScript looks really great! The one thing that seems missing is access to note tracks, but there may be a way around that. We can do a whole lot in MaxScript very easily that would be a pain in the wazoo to do in C++. MaxScript can read in excel spreadsheets and maybe even get the access database through OLE. It's trivial to do batch exports, and stuff like that, and no problem to whip up a three line function that recursively controls the visibility of track of a whole tree of objects. (Something that Charles wanted for the sprite exporter). In fact while browsing object properties I noticed one called "inheritVisibility" that might just do the trick -- don't know if it's new or not. -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Friday, March 20, 1998 7:11 AM To: Hopkins, Don; CTG @ MAXIS Cc: Blaha, Grant; McGavran, Christine Subject: Accessing note tracks from MaxScript: solved via MaxScript plug-in! MaxScript happens to have an SDK that you can write new MaxScript primitives with! It didn't have a built-in way to access the note tracks, that we're using for our exporter. So I wrote some plug-in MaxScript primitives to give me access to the note tracks and keys of any Max object, so now MaxScript *DOES* have access to the values of the note track keys! It doesn't have write access yet, just read, but it's a simple feature to add. This proves we can get MaxScript do pretty much whatever we need it to, by writing plug-in MaxScript primitives, which are a lot more flexible than the other kinds of Max plug-ins. We need to buy John Wainwright some beer! MaxScript rules! -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Friday, March 20, 1998 7:23 AM To: wainwright@lyric.com; info@lyric.com Cc: Hopkins, Don Subject: FW: Accessing note tracks from MaxScript: solved via MaxScript plug-in! I really love MaxScript! I made pretty good progress for my first night of hacking after upgrading to 3dsmax2 last evening! Less than 2 hours after realizing there was a MaxScript SDK on the cd, I had my new note tracks primitives working! What do you think would be a good way to suck some data (i.e. a column of max file names to batch export) out of an Access database? Should I indirectly suck it into an Excel spreadsheet, and then read it out of that via OLE? There doesn't seem to be an embeded Access object I can create like the embeded Excel spreadsheet... When do you want to claim your beer? -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Friday, March 20, 1998 7:40 AM To: CTG @ MAXIS; BlahaErath, Grant; McGavran, Christine Cc: wainwright@lyric.com; info@lyric.com Subject: RE: Accessing note tracks from MaxScript: solved via MaxScript plug-in! Here's a MaxScript demo showing the note track plug-in primitives! -Don Welcome to MAXScript. hasnotetracks $bip01 true numnotetracks $bip01 4 getnotetracknumkeys $bip01 0 2 getnotetrackkeytime $bip01 0 0 0 getnotetrackkeynote $bip01 0 0 "beginskill=biped-ed-dishw-open absolute yorigin=-3" getnotetrackkeytime $bip01 0 1 9440 getnotetrackkeynote $bip01 0 1 "endskill=biped-ed-dishw-open " fn notes obj = ( local tracks = numnotetracks obj if tracks != 0 do ( for i = 0 to (numnotetracks obj) - 1 do ( format "track %\n" i local keys = getnotetracknumkeys obj i if keys != 0 do ( for j = 1 to (getnotetracknumkeys obj i) - 1 do ( format " Time % Note:\n%\n" (getnotetrackkeytime obj i j) (getnotetrackkeynote obj i j) ) ) ) ) ) notes() notes $bip01 track 0 Time 9440 Note: endskill=biped-ed-dishw-open track 1 track 2 Time 4320 Note: xevt=0 track 3 Time 4480 Note: xevt=1 Time 4800 Note: xevt=2 Time 5120 Note: xevt=3 Time 5280 Note: xevt=4 OK ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Monday, March 23, 1998 7:55 AM To: 'John Wainwright' Cc: Hopkins, Don Subject: RE: FW: Accessing note tracks from MaxScript: solved viaMaxScript plug-in! I played around with visual basic in access, and got it to use ole to call MaxScript functions I registered in Max! I'd like more of a pull model though. Right now I can run Access and press a button, and it pushes stuff to Max. Instead I'd like to figure out a way to create an ole object in Max and use the database directly from MaxScript. Maybe there's an ActiveX control that wraps the same ole database objects that I'm using from visual basic. What would be really useful, would be a MaxScript interface to an XML parser! There are actually two COM XML parsers that ship with IE4.0, one written in Java (that the source is available to), and one written in C++. There's a distribution you can download from microsoft with the java source and examples of how to read and parse and manipulate xml trees in javascript on web pages. You should be able to use the parser from any language through an IDispatch as well as a direct COM interface. What kinds of ole object can I create, and is there the syntax for specifying a GUID? There should be some way to look up the name of the java package like IE4 does, so you can transparently plug in java classes as ole objects. Here's the syntax used to embed the XML parser on a web page: I don't know how to figure out the guid to ask for, given the name of a java package, but it must be in the registry somewhere. Maybe there's a trick to actually binding to the java vm and .class files, but it might "just work"! -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Thursday, March 26, 1998 2:47 PM To: John Wainwright Cc: Hopkins, Don Subject: Visiting EA Would you like to drop by and visit on Friday afternoon? At 4pm Friday, Peter deVroede is stopping by, and he runs a tool group here at EA and would like to talk about MaxScript! He'd love to meet you. And there's free beer and chips and dip around 5! The database stuff works great now with the new MaxScript! Thanks a lot!! I retooled my animation exporter as a MaxScript primitive, so I can pass it more arguments and get more return values back. Now it has nice English error messages for the artists, telling what went wrong with which file, and returns an array of arrays of strings, describing everything it exported. I've got a nice new MaxScript exporter panel that's driven from the database, has a scrolling list of all animations, fields to display information about the selected animation, a button to load the max file of the selected animation, a button to export the current file, and a button to batch export all animations in the database! The best way to get to EA is to take 101 to 92, and get off towards the San Mateo bridge, and then take the first exit Mariner Island Blvd (staying in the right lane that the exit dumps you in, instead of merging into the main lanes of 92). That exit curls around to the right and then hits an intersection where you turn right, so you go back across 92, EA is the big pyramidish building on the left after you cross 92. Take the next left turn after you cross 92, then the next left turn into the parking lot. There are actually 2 buildings with a fountain in the center. The one I'm in is #1450, Fashion Island Blvd. My office phone number is (650) 513-7723. -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Wednesday, April 01, 1998 11:34 AM To: CTG @ MAXIS Subject: Animation database I worked on the animation database, trying to fill in as many fields as I could and make it consistent with the animations we have. There's a bit more work to be done, but I've put in cmx directory names, cmx file names, and max file names for the ones I could find, and they need to be verified that the correct version is entered. For the ones I couldn't figure out, I put "???" in those fields, to mark them as unknown. All the "Indirect Global" animations refer to a global animation of the same name, so I cleared out the fields of the indirect global ones, since it's bad to have old copies of invalid data sitting around the database, so for indirect global entries you should look up one of the same name that's not marked indirect global to get the information like cmx file name, max file name, etc. I marked those fields with "-" to show that they were not applicable. So when you sort the animations by name, there are repeated names, then all the repeats should be indirect global except for exactly one. The indirect globals should not have file names, and the actual one should. I marked the "Status" field of all indirect global animations "INDIRECT", and the animations whose names I don't know "UNNAMED", and the ones with names as "VERIFY", so somebody needs to look at them and make sure they're refering to the right file names, fill in the missing file names, and change them to "VERIFIED". Animations that I've only spec'ed, are marked "TODO". I spec'ed the new walking animations for the duchess. I believe there are still some animations that we're using, that aren't in the database, and those need to be flushed out too. I filled in some of the start and end poses that I was sure of, but we need to make an official list (maybe another database table) of pose names, like "walking-left" for walking on the left foot, etc, and use them consistently. Maybe we can make an enumerated type and a menu, but some of the animations have their own custom private poses. Probably these should go into the pose list, too, just so we can validate that yes in fact the beginning and end position of the skeletons with the same declared poses are actually in the same place. Eventually I would like to have the exporter write these pose names (or ids) into the cmx files, and the game can check at run time to make sure the trees don't call out any discontiguous animations. PS: Also I registered my 3dsmax2 and cstudio, and entered them into the software database! -Don From: Bowman, Eric Sent: Thursday, April 30, 1998 9:26 AM To: CTGPROG @ MAXIS-SM,EAHQ Subject: freezing when sitting at table? I'm not sure anyone reported this, but in the demo house, when people sit at the table they never get up again. ==== From: Mackraz, Jim Sent: Thursday, April 30, 1998 10:48 AM To: Bowman, Eric; CTGPROG @ MAXIS-SM,EAHQ Subject: RE: freezing when sitting at table? Will and I have both seen this; I mentioned it when I reported the water torture bug. ==== From: Doornbos, Jamie Sent: Thursday, April 30, 1998 2:22 PM To: Mackraz, Jim; Bowman, Eric; CTGPROG @ MAXIS-SM,EAHQ Subject: RE: freezing when sitting at table? This appears to be a Don bug. It is freezing in GotoRoutingSlot because the anaimtor "IsIdle" function for some reason is returning false indefinitely. Perhaps the chair should be stopping the object animation in its sit down tree? ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Thursday, April 30, 1998 4:44 PM To: Doornbos, Jamie; Mackraz, Jim; Bowman, Eric; CTGPROG @ MAXIS-SM,EAHQ Cc: London, Charles; Hedman, Eric Subject: RE: freezing when sitting at table? The problem is that the animation "biped-ed-sit-reach-table" is missing. It's not in the database, so it's not being exported. Anybody know what it's supposed to be called, or if it's just missing? I'll fix the code to print out an error message when the reach animations are missing. -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Thursday, April 30, 1998 5:06 PM To: Hopkins, Don; Doornbos, Jamie; Mackraz, Jim; Bowman, Eric; CTGPROG @ MAXIS-SM,EAHQ Cc: London, Charles; Hedman, Eric Subject: RE: freezing when sitting at table? I'm adding biped-ed-sit-reach-table to the database, and exporting it. I've got to change the tags in the max file so it has the right name. While updating the database, I noticed that the following animations have -3 absolute offset, and I can't figure out why. Does anybody know why, or should we fix them? biped-ed-reach-counterht biped-ed-reach-floorht biped-ed-reach-lfburner biped-ed-reach-seatht biped-ed-reach-tableht biped-ed-foodproc-foodprep adult-floorlamp1-turnon adult-stereo-switchstation adult-phone1-dialphone adult-aquarium1-feed adult-toilet1-raiseseat adult-phone1-gethandset ... and lots more. Just sort the "Origin" column of the database Animation table and you'll see them all. There are a lot of them. Also there are a lot of animations without ID's, just a blank AnimationID field. Is there a way to automatically number these so they're all unique? There are a few gaps in the numbering, and some animations that were added later (like the one I just added) are out of order. Is the animation ID number even necessary? How is it used? -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Wednesday, May 13, 1998 8:50 PM To: CTG @ MAXIS Subject: Better animation previewing in game I merged the vitaboy animation previewer "hello" control panel into Sims with Edith. Now you can bring up an animation inspector from the Edith window's Sims menu. Type "e" to invoke Edith, pull down her Sims menu, and select "Animation Inspector". You get a dialog with scrolling lists of all Skeletons, Suits, Skills, and Active Practices, with lots of dials and buttons to control the vitaboys. Scroll the house view to the right corner (if you haven't rotated), and you'll see two people. They're "ghosts" that the game doesn't know about, but who you can control with the animation inspector. I'll add some controls to move and turn them around, so you can position them along side of any object, and test any animations. I'll also add some controls for clocking to real time or the game rate, and single stepping at the game time interval. At some point we can use this facility to play back and inspect blended animation journals, by implementing a full body record mode on the vitaboy, that creates a new practice that you can single step through to inspect the results of blending the animations the game calls out (as Luc suggested). -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Wednesday, May 13, 1998 10:06 PM To: Mackraz, Jim; London, Charles Cc: Curtin, Claire; Wolosenko, Roxy; Trottier, Chris; Don Hopkins; Wright, Will Subject: RE: GUI implementation details I suggest we leave the vertical lines out of the text. It looks to me like a pair of cursors, one at the beginning and one at the end of the editable text. I think it would just look cleaner and less confusing (and be easier to draw) without lines around the text. First I'll figure out how to make fonts, and fix the pie menus to use a larger nicer one. Tool tips will require modifying the base window class to support an interface that returns a help string, and creating a manager that keeps track of the global state. The button overlapping should be resolved by a mask, so their active area can be defined exactly by the artists, to be what it looks like on the screen. A separate mask is necessary because the highlighted button overlays themselves can't have a transparent background color that could be used to do hit detection, because of the shadow around the outside of the active area. (i.e. it needs to draw the shadow outside the active area, so the image's transparent color won't correspond to the button's active area.) I'll make a simple button class that supports a target mask, and an arbitrary number of states, including a state where it doesn't draw anything (so the background shows through). It'll support our mouse tracking and highlighting requirements, as well as tool tips. The pie menus will benefit from using these new buttons instead of the old ones, and I could enhance them to pop up descriptive tool tips on the pie menu items when you stop moving the mouse. I think it would be a good idea to implement animated buttons by allowing another dimension to the grid of button images. i.e. old buttons take a 1-d horizontal grid of images, but you could give new buttons a 2-d grid of images, as many rows as frames of animation, and they could flip between them at a rate determined by an adjustable button property. This would be useful for implementing blinking time buttons, spinning rotate buttons, growing and shrinking zoom buttons, etc. For the time display and buttons, it would be cool to have an LED time display with a flashing ":", and tape player like controls to pause and play, with a continuous slider to control the speed. The slider and the pause button should be separate "orthogonal" controls, so you don't "lose" your speed when you pause. Maybe the active button could glow green (for play) or red (for pause), and the other could be dim but colored. The LED color could also change from red to green to indicate the paused or playing mode. The slider could have notches and/or plateaus at slow/medium/fast settings, but it would also be nice to be able to smoothly drag it across a wider range of speeds than we currently support. Opinions? For the level select buttons, I think it would be nice if it only displayed the number of levels you actually have. As you add more levels to the house, you get more level select buttons. You would always have at least one level and a roof (which is all we'd have to do for now). Opinions? I'll have to make a tab controller class. But possibly I can just subclass a multi-state button with a handler that looks at the mouse pos and selects the appropriate state, then swaps in the appropriate sub-panel. We can probably get away without writing a gauge class for displaying the motives. Right now it's just a subclass of window that draws all the gauges, and I can build on top of that. In the interest of writing code that does exactly what we need instead of trying to create general purpose widgets. We need to redesign the look and feel of the pop up pie menu for zooming and rotating. It does not disable (but it could) the zoom in and zoom out items when it's all the way in or out. When you select a zoom or rotate command from the pie menu, the view is automatically centered on the location of the mouse where you clicked up the menu. So when you select zoom in or out when zoomed all the way, at least the view will center on the cursor. I think we need an easier way to center, as well as a way to zoom in or out all the way (two notches) and rotate more than 45 degrees at a time. This calls for "pull out" pie menus that select from a set of sub-menu items depending on the distance. This would be quite easy to implement if I taught pie menus to use the new buttons, which will support animation as well as an arbitrary number of states. -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Friday, May 29, 1998 3:10 PM To: CTG @ MAXIS Subject: hiding & animating suits Charles proposed a nice idea that will make it possible to do the "birthday suit" effect, hide skins that are underwater in the bathtub, and animate skins for different hand gestures, etc. The artist could put an event on a bone, say "skinframe=0", that would set the frame number of any skins on that bone. Right now we only need to support frame 0 (the regular skin) and -1 (no skin) so we could turn skins on and off. The birthday suit effect would be done by turning off the skins on all the bones but the head, and dressing a global naked suit. Eventually the exporter and vitaboy could be extended to support multi framed skins, so the hands could have several different gestures like neutral, holding, flashing a peace sign, etc. Each person would have a set of their own hands in their own skin color. People could also have their own flesh colored birthday suits, and animations could dress and undress parts of the body by changing skin frames, like to take just a shirt off. Mesh objects could be held in the hand by setting the appropriate hand frame and dressing a global suit of the object in the hand, all under control of events in the animation stream. We could also make primitives that call the same functions, so tree programs can call them out too. -Don ==== From: Hopkins, Don Sent: Friday, May 29, 1998 10:41 PM To: Mackraz, Jim; Doornbos, Jamie; London, Charles Cc: Hopkins, Don Subject: catalog popup! I've got the catalog popup in! When you click in an item in the catalog, the catalog popup pops up over the catalog book panel. It goes away when you change modes, or click anywhere in the catalog popup panel. It draws the icon it's given (the same as the catalog icon right now), the name it's given (kind of whacked out in several cases), the price it's given (currently mSelector->pHeader->price but that always seems to be always 0!), and the description it's given (several of which have carriage returns that display as boxes, and seem to be truncated). Charles is working on some new graphics for better books and a wider panel. Right now the layout is the same for all objects. We will have several layouts for differently shaped product pictures, which will probably be passed in as an enum arg, that would need to be stored with the object. Issues to resolve: 0) integrate new artwork for nicer catalog buttons, wider catalog background, and popup catalog background. 1) go through and give all objects reasonable names (as opposed to "Stove Expensive") that are short enough to fit in text field width 2) go through and give all objects reasonable descriptions (with no carriage returns) that are short enough to fit in text paragraph rect 3) fix whatever bug causes descriptions to be truncated. They're truncated by the time Product::GetDescription gets the text resource. 4) figure out why the price is coming out 0, and fix Product::GetPrice to get the right value, since mSelector->pHeader->price seems to be 0. 5) make bigger thumbnail pictures to be used in popup catalog, and use those instead of small catalog icons 6) settle on one layout, or a few layouts and a way to record which layout to use in each object. Also: The price stuff might want to be internationalized, since it's using a dollar sign, and putting commas between each group of 3 digits. The text field that displays how much money you have should also be internationalized, and taught to put commas or whatever in. We might want to adjust the font style or sizes a bit, depending on how much room and how much text there is. -Don PS: Here's a picture! For some reason it's stretched in this email but if you double click it will put it into an editor unstretched... ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Friday, May 29, 1998 10:53 PM To: Hopkins, Don; Mackraz, Jim; Doornbos, Jamie; London, Charles Subject: RE: catalog popup! Whoops -- the prices _do_ work, it's just that some items cost $0! I remember an adventure game on the apple ][ written in basic (i think it was the original lounge lizard larry, if it wasn't soft porn adventure), that had a gambling section, and you could bet negative amounts at the blackjack table, then lose, to make lots of money!! -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Tuesday, June 02, 1998 10:37 PM To: Mackraz, Jim; Perry, Michelle; Trottier, Chris; CTGPROG @ MAXIS-SM,EAHQ; Wright, Will Subject: Hitting space in people pies now switches people Now when a pie menu is popped up with a person's head in the middle, you can hit space to advance to the next person! I had to add keyboard notification to the pie menus, and now they send messages to their target when the selection changes, when something's selected, and when a key is pressed. I made a space bar key press handler that switched to the next person and canceled the current pie menu with a magic -2 value, and the object picker tool recognized that, reselected to get the new person, and did a wee goto to fill out and pop up a new pie menu. This unwinding and rewinding a new menun was necessary because the menu items might change depending on who's in the menu center. A good example is to pop up a pie menu on a person, and hit space a few times to see what other people and themself can do to them. I had it re-centering when you hit space but that was much too jarring, so I took that out (it still re-centers when you hit space and the pie menu is not popped up). -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Wednesday, August 12, 1998 3:38 PM To: Mackraz, Jim Cc: Curtin, Claire; Wolosenko, Roxy; Ryan, Kana; Wright, Will; MAXIS CTGPROG @ Maxis Subject: Bizarre object placement behavior Right now, the object placement tool has a special behavior when you're placing an object, but you point at an object of the same type as the object you're placing. The object you're placing disappears (but it's not obvious because you're pointing at an identical object), and you get to rotate the identical object. It does not let you rotate non-identical objects, though. This seems to be extremely bizarre behavior to be, and there is a lot of code that goes into implementing it, but it's not mentioned in the design document. It's really kind of hard to explain what's happening, so I wouldn't expect people to expect it to behave that way or figure it out easily. It seems to be there so that when you're placing (say) chairs, you can go back and rotate one of the chairs you've already placed, but wouldn't it be more convenient if you could go back and rotate *anything* while you were placing *anything*? It will be very difficult to maintain the convoluted code that implements this unspecified behavior, and modify that code to implement the behavior specified in the design document, so I vote for removing it, or at least writing it down it into the design document so we can discuss it. I think the behavior of the "object picking up and moving" tool should be as close as possible to the "object buying and placing" tool. Buying a new object should just create it and start moving it with the normal object moving tool. Moving objects around should not be different in buy mode and architecture mode. Right now the "object picking up and moving" tool is a *sub*class of the "object buying and placing" tool, kind of the opposite of how it should be (since the subclass covers up the buying behavior of the superclass instead of adding to it, sort of like subtractive dis-inheritance). -Don ==== From: Mackraz, Jim Sent: Wednesday, August 12, 1998 4:07 PM To: Hopkins, Don Cc: Curtin, Claire; Wolosenko, Roxy; Ryan, Kana; Wright, Will; MAXIS CTGPROG @ Maxis Subject: RE: Bizarre object placement behavior My assumption is that we'll have to change a lot of code to match the spec, and it's time to do that. I'm not clear from your message whether you reviewed the spec. ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Wednesday, August 12, 1998 4:29 PM To: Mackraz, Jim Cc: Curtin, Claire; Wolosenko, Roxy; Ryan, Kana; Wright, Will; MAXIS CTGPROG @ Maxis Subject: RE: Bizarre object placement behavior I reviewed it and didn't find anything in it about this behavior. The behavior is so subtle I don't know if anyone else realized it's behaving that way. I only noticed because I read the code. Try placing two chairs of one kind, and two chairs of another kind. Now move one chair on top of another chair of the same kind and see what happens when you click. Then move one chair on top of another chair of a different kind and see what happens when you click. Repeat these experiments by buying new chairs instead of moving chairs that already exist, and notice the difference in what you can do. The frustrating thing is that there is no way to move a chair once you place it in buy mode. This seems to be intended to give you a way to at least rotate the last thing you placed when in buy mode, but not move it. This is why I think that object buying mode should create the object, and then behave exactly like normal object movement mode, which should allow you to rotate or move any object, no matter what kind of object it is. This will require changes to the way object movement and buying works, of course. The other issue is how does moving and deleting architecture work? Should it work the same as moving and deleting objects? Can you drag a door or window to the control panel and expect a refund, or at least delete it? Or is there a special tool for deleting architecture? When you delete a wall, does that delete any doors and windows too? Can you move and delete architecture in shopping mode? Can you move and delete objects in architecture mode? -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Friday, August 14, 1998 7:24 PM To: Mackraz, Jim; Wolosenko, Roxy; Curtin, Claire; Wright, Will Cc: Ryan, Kana; Perry, Michelle; Trottier, Chris; London, Charles; MAXIS CTGPROG @ Maxis Subject: RE: The Sims Design Document (deh Review) I've typed in all my notes that I scribbled down on paper, with lots of feedback and suggestions for this rev of the design, plus some far out proposals for later on! (A shopping outing scenario, and moody music.) -Don ==== > Romance in the World UI > > Immediately after any type of social interaction between two > characters finishes, there will be either a friendship or romance > icon that will pop up and flash over the heads of the characters. ( > all social interactions are categorized as Romance or Friendship.) > The friendship icon is TBD but the romance icon is a heart. These > icons will reflect the change in relationship that just occurred as > a result of the interaction. If romance moved up, the heart would > flash on screen and would be followed by another larger heart > etc. (# of sizes tbd). The flashing size technique is visually ambiguous and not very obvious because you have to stare at the screen and wait to see the change, which cycles. As a rule of thumb, if you can.t read the meaning of the icon from a STILL screen snapshot, then it.s not obvious enough. The current design fails this test. Forcing the user to wait through the animation and interpret the changes over time requires a lot more cognitive attention than just using a unique icon for each state that the user can recognize in a glance. If the icons are unique the user can look at the whole screen and take in the information at once in parallel, but if they have to concentrate on individual animations and wait for them to play out, it takes a lot more attention to see what.s going on. Flashing the same size, flashing larger, and flashing smaller require that there are more than two frames to disambiguate, three at the bare minimum, and at the small size of the icon there is not a lot of room to vary the size. Why not use completely different animations? A Broken Heart, animated or not, is instantly recognizable as a negative social factor, and visually distinct from a whole positive heart, for example. The size of the icon is good for showing the intensity of the change, but certainly not the sign of the change (+ or -). Bouquet of Flowers, Dove of Peace, Vulture of Antipathy, Parrot of Piracy, etc. >Friendship icon gets larger and larger = positive relationship points (no romance) >Romance icon gets larger and larger = positive relationship points with romance >Either icon just flashes same size = no net gain or loss >Icons flash increasingly smaller = relationship point loss. >TBD Design . There is an anticipated problem of how to display the >flip from declining romance into friendship when the relationship >points are high. Does the friendship icon display after interaction, >in the middle of interaction, or what? The whole relationship design and implementation (I've looked at the tree code) is Heterosexist and Monosexist. We are going to be expected to do better than that after the SimCopter fiasco and the lip service that Maxis publically gave in response about not being anti-gay. The code tests to see if the sex of the people trying to romantically interact is the same, and if so, the result is a somewhat violent negative interaction, clearly homophobic. We are definitly going to get flack for that. It would be much more realistic to model it by two numbers from 0 to 100 for each person, which was the likelyhood of that person being interested in a romantic interaction with each sex. So you can simply model monosexual heterosexual (which is all we have now), monosexual homosexual (like the guys in SimCopter), bisexual, nonsexual (mother theresa, presumably), and all shades in between (most of the rest of the world's population). It would make for a much more interesting and realistic game, partially influenced by random factors, and anyone offended by that needs to grow up and get a life, and hopefully our game will help them in that quest. Anyone who is afraid that it might offend the sensibilities of other people (but of course not themselves) is clearly homophobic by proxy but doesn.t realize it since they.re projecting their homophobia onto other people. >Same Sex and Opposite Sex relationships > To be outlined in 10/30 Live Mode deliverable. > Currently the game only allows heterosexual romance. This will > not be the only type available -- it just reflects the early > stages of implementation. Will is reviewing the code and will > make recommendations for how to implement homosexual romance as > well. >Rotating an Object This whole rotation scheme is TERRIBLE and should be redesigned. Please don't just accept the current implementation as the definition of the design. The code is really complex and has lots of wrinkles that are hard to describe, that you probalby don't know unless you've read or wrote the code. Try placing two chairs of different types down, then try moving one chair onto the other chair of the same type, and clicking. Then try moving one chair onto a chair of a different type, and clicking. Go figure. There are other features that exist but aren.t in the spec, like holding down shift to 'paint' with an object, that interact with the other behaviors in subtle ways. (i.e. Notice the red x's when you hold down shift and drag out flamingos.) These features were accumulated over time, designed at different times by different people, and the way it works currently should not simply be reverse engineered and called a spec. We really need a fresh design for rotating objects, at the same time as a fresh moving objects design, so that rotation does not interrupt the flow of moving things around, and it not require so many clicks. >To rotate an object, click on the object in the World to select it, >and grab hand with rotate cursor appears. Rotate object by clicking >into desired position. Move cursor off object, get grab hand cursor >and click once to set down. Moving cursor off of the selected object >also brings back the open hand cursor. > < > keys will also rotate selected object. A proposal for rotation: When picking up an object, you can change its direction by pressing and holding the mouse button down and moving in the desired direction. Once you release the mouse button, the object follows the cursor until the next time you click to set it down. When setting down an object, you can also change its direction by pressing and holding the mouse button down and moving in the desired direction. When the button goes down, the item is anchored in its current spot, and if the direction is desireable you just release to begin or end the movement. But if you want to change its direction, just move in the direction you want the front to face. As with pie menus, you don't have to look at the screen to be 100% sure of the direction you're going to turn it, since your control over the direction is ABSOLUTE. This gives you absolute unambiguous control over the direction at both the beginning and the end of the movement gesture. You might want to rotate it before picking it up, as well as after setting it down, and this interface supports optional rotation in both cases, with a minimal number of mouse clicks. When you try to set an object down, but you're not allowed, a temporary dialog could pop up telling you WHY you can't set it down. You could still rotate it around until it was facing the right direction. Another way to rotate an object while you're dragging it, would be to move the mouse around in circles in the direction you want to turn it, and it would start clicking and turning once you completed a whole rotation gesture. You could keep circling the mouse around and the object would keep turning. Circle in the other direction to rotate in the other direction. The current 'Setting the Time on an LED Watch' interface to rotation (clicking again and again until it rotates around to where you want) is horrible. (At least there aren't 60 rotations!) It's not absolute, and it's an arbitrary design decision which direction it does rotate (so if you have to click 3 times because you wanted to rotate the other direction, it's very annoying, since you have to look to be sure which way it turned, since some objects turn funny.) The hoops you have to jump through to switch back and forth between rotating mode and moving more are very inconvenient. The technique of switching from rotating to moving by pointing at an object, then pointing away, then pointing back, is awful, and it has the feel of a BUG that somebody discovered was the only way to do something because of a lack of good design, and then documented. The current design puts rotation at a higher importance than moving. I argue that moving is much more important than rotating, since there are only 4 rotations to choose from, so any rotation has a 25% chance of being right, but there are thousands of positions you can move to, so you need to move an object much more often than you need to rotate it. Rotation is very low res, Position is high (or medium) res. The first command you get by clicking on an object should not be the low res, less useful rotation command (one that requires you to click 3 times to rotate ccw), it should be the much more commonly used movement command. > Thanks to Don, we have a rotating scheme that should work more > easily than previous designs. >Selling an Object This design will require unnecessary mouse movement. The user has just moved the mouse to the bottom of the screen, now you are popping up a modal dialog that is in the middle of the screen. Why not pop up a dialog near the cursor? Or design it so it does not need a modal dialog at all. Perhaps a 'Yes/No' pie menu. Better yet, why not rethink the whole design of selling objects? The original proposal was to drag the object into a small target (i.e. the catalog item that it came from, or a 'Sell' target), but that was thought to be too difficult, so the spec was changed so the target was the whole control panel. But now that is TOO EASY to do it accidentally, so the pop up confirmation dialog was added, whose 'OK' button is just about as small as the original catalog button or buy button we were trying to keep from having to home in on, in the first place. Here are other ways to get rid of objects: drag them out to the curb on heavy trash pick up day. Have a garage sale on the weekend. Put the object in storage (for a monthly fee you could maintain an off-screen storage locker that you could drag possessions in and out of -- this would be really useful!). I think the simplest thing would be simply to have a button on the control panel that ways 'Sell', maybe a small drop target recession that has some icon like a goodwill store or newspaper want ads, that highlights when you drag an object over it, and you're told the price you'll get for it somehow, like a temporary popup tooltip. When you drop it on the Sell button, it's sold, without any 'Are you sure' dialog. You can always use 'Undo' to get it back, so the confirmation dialog is not necessary, but the price feedback is (so it could be displayed as feedback in or by the Sell button when you drag an object over it). Imagine how much you'd hate that far away 'are you sure' dialog, if you wanted to sell 25 items, one after the other (after the 'flock of flamingos lands in your front yard' disaster). How do you place objects on tables? Should you be restricted to only placing certain objects on certain other objects where they belong? Right now many objects like chairs have slots at their origin for people to sit in, but you never want to place another object in that slot or it occupies the same floor tile and intersects. If you put food on the chair, it probably goes underneath, and wouldn't even be visible 'inside' of couch. Maybe you should not even be able to put food on couch. What about putting food on ground? Should that be restricted? Food processors should only go on counters. If you place them on the ground they should not work, so maybe you cant place them on the ground. How does the object placement tool tell you the placement restrictions of an object? The user should have some way of telling where they can place something, be it only on a counter, or only on the floor, or only outside or inside. What if an object has several slots to place something? How do you show that to the user? How do you decide which slot to drop into or to pick up from? How do you change things from slot to slot? There are some undocumented and undesigned keyboard shortcuts for dealing with slots, but they are bizarre and invisible and complex, and not something that I think should be exposed to the user. I think placeable slots should be very rare and/or very smart, to avoid exposing the user to all of these problems. Also, I say we get rid of the inside only and outside only placement flags, and maybe the 'against wall' requirement, because they are only annoying and can be easily defeated by using the wall tool to change the definition to inside and outside. No way we want to program the wall tool to remove objects that don't belong, when it closes or opens a room to the outside. So why bother preventing people from planting trees indoors and putting refregerators outside? I actually KNOW somebody with a fridge outside, and my mom has trees indoors (small ones, though, but sometimes a large one around xmas). Observations from shopping for furniture in the real world: - Used furniture stores and Goodwill are important sources of low cost, funky, one of a kind furniture, already worn. Miscelaneous selection, usually single items. No packaging, or even advertisements (for individual items). Categorized by type. - Garage sales, flea markets, junk and salvage stores. - New furniture stores. - - Very often sell COMPLETE SETS of items: Table with 4 chairs, sofa/loveseat/stool set, bar and stools, matching shelving and tables. - - Also these groups and individual items are grouped together into higher level 'style' groups, like Queen Anne style furniture, Ikea style, building or material. - - At an even higher level, furniture stores are laid out in different sections for different rooms. Another kind of shopping, not to replace what we currently have, but to add another rich interesting realistic way to shop: Shopping could transport you to another place, a shop full of new furniture, goodwill store, garage sale, etc, where you pick objects to buy, collect them into a 'virtual shopping basket' or something, buy them, and have them delivered home to your driveway, for you to then place in the house. Scenario: Watching TV at home, and an ad comes on for a sale at 'Fast Eddie's Used Furniture Store'. Click on the TV to pop up a menu, one item is 'Go Shopping at Fast Eddy's Used Furnature Sale'. The currently selected person walks outside. (After they pass through the front door, the scene cuts to Fast Eddie's, to keep it ambiguous just how they get there, to keep the game moving along, since nobody wants to sit around watching the character wait for the bus or drive a car and look for a parking space.) Cut to entering the front door of Fast Eddie's. You can move around the store with the normal 'go here' menu on the ground. When you're done shopping you can exit the shop by going outside, and go to other shops or back home. There are aisles of items for sale on display. Clicking on an item on sale pops up a menu that has a 'Buy for $XXX' selection. Some items also have an 'Inspect' item, that plays an animation of looking over the object and trying it out, maybe sitting down and reclining in a lazy-boy chair, or kicking the wheels so to speak. Your reaction to it might be based on your personal preferences, so different characters will like or dislike the objects. There should be some way for a group of characters to go shopping. You can derive some entertainment value from the objects, but not too much. For example, you can't cook a meal on a stove and eat, but you could have an entertaining evening by shopping for TV's, looking at them all, listening to sterios, but never buying anything. This way the act of shopping itself can be fun and useful, without actually spending any money! When you inspect an item, a window with an ad or catalog description might pop up. The salesman, Fast Eddie, might notice you looking at something, and walk over and tell you about it, demonstrate its features to you himself, or whatever. If you decide to buy something, and select 'Buy', the item does not disappear, but a big 'Sold' sign can appear on the item, and the 'Buy' menu item changes to 'Return' in case you change your mind not to buy it, so you can see all the items you're going to buy, and change your selection. A virtual 'shopping basket' is another approach, but the items in the basket won't be visible (too complicated to draw, and not appropriate for big items anyway). When you're done shopping, you can check out to finalize your purchases, and leave the store, or just leave without buying anything. You might keep on shopping at a different store, or go home. When you finally go home, it cuts to you in the driveway, waving bye bye to the delivery truck, which is pulling off after unloading all your purchases in the driveway or front yard. Then you go into object placement mode (arch or buy, whatever), and place the object in your house. >Disasters > Fire: do objects have a combustible score? Do objects need a burnt, > charred graphic state? RAT HOLE! This will take a LOT of artwork and programming, and never be very convincing. Fires are hard to simulate, the way they interact with the burning object, which changes over time and effects resulting the flames and smoke. >Other disasters: Blackout, others to be designed Electricity supply and usage model. No wires or plugs, maybe a meter. Power outages and brown outs in the whole house, and monthly power usage bills. Lightning strikes and power surges can zap some sensitive appliences that are operating (computer, tv, lights, etc.) Washing machine can blow up and send power surge throughout household. Water model. No pipes or sewers, maybe a meter. Cold and hot water, water outage in whole house, droughts, water bill every month, hot water heaters with limited capacity, that recharge slowly and use electricity, tub and shower and dishwasher and washing machine compete for hot water. Interesting game of making sure you have enough hot water for everybody in the household to have a hot shower or bath without running out. Cold showers and baths make people crankey and uncomfortable (though less horny). The .testing the tub water. animation can have a wonderful failure reaction to cold water. Somebody taking a long shower can scream when they run out of hot water and jump out of the shower. This is all very easy stuff to implement given the current system. >Events > Events such as marriages, etc. will be included in game, not yet designed. Boyfriend seranades girl outside of window. Girl sneaks out bedroom window late at night. Hillbilly Poppa with shotgun comes over with clergy and forces boy to marry his daughter. Bad husband has to sleep in doghouse. Polygamist weddings in Utah, where the first wife presents the husband to the second wife, who presents him to the third wife, etc. Divorced couple saws house in half. Nondenominational same sex mixed race tatooed amputee weddings in California. >Sound Design > Music > Freshness will be considered for music track. I have some ideas about how the music could effect the game, that I will write up more completely later. In a nutshell, the people in the house could have a cd or record collection to choose from, each record an object that has the sound (audio wave and/or midi) and a 'moody' track synchronized with the music. Playing the music also plays the moods into the environment that the people pick up on. Music can subtly effect how people react to the environment, objects, and each other. It can effect their motives and even their skills temporarily. For example, you might be able to clean the house better and faster if you put on some up temp bouncy music. The player should be able to assume the role of disc jocky on the radio, and play from another larger library of music and commercials, that effect the peoples moods and buying habits. The TV of course is another source of mood altering temporal media, with commercials and shows that should effect different people differently. But the most important part of this idea is instead of the game effecting the music that's played, the music effects how the game plays! The ultimate way for the user to effect the game via music, is to insert one of their own CD's into their real computer's CDROM drive, and the game would recognize it, and start playing it (maybe with a simple cd player interface to select the song). There could be a database associating the unique ID number of the CD with a table of contents and 'moody' tracks that tell how the song effects the peoples emotions over time, with 'percussion' events at dramatic moments of the music that can trigger arbitrary events in the game (like provoking a fight that was brewing, or triggering an orgasm at just the right place in the song). We hire monkeys to listen to well known CD's, and enter time synchronized tracks with semantic meanings in Max (like note tracks, and user defined numeric tracks) or some other timeline editing tool). Put the database up on the web for instant retrieval, so when somebody sticks in a new CD, it downloads our 'moody' tracks that go with it, and it starts playing and effecting their game! Streaming emotions over the net! Eventually there should be an end-user tool so people can record their own responses to music as moody tracks they can use in our games. This mechanism could be used in all kinds of games, to varying degrees of effect. I'm not saying that music should be the only way to control the game -- it's more like a subtle background effect, but there certainly could be a scenario where you try to accomplish some task (like taming a wild beast) by using only your musical taste and timing. The real bottom line benefit is that you get to listen to your OWN cd collection of music you want to hear, instead of being driven crazy by the repetitive music bundled with the game. >Objects in the World UI > Selecting > To select an object in the World, click on it with the open hand > cursor. The selected object displays its monochrome state. The > cursor becomes a grab hand holding the monochrome object. Now the > object can be moved or rotated. Presently instead of the object displaying monochrome, it's displayed with a yellow grid underneath it. Do we lose the yellow grid or not? Also here's a couple arguments for displacing the moved object vertically upwards a bit: If the object is big on the tile, you will still be able to see the yellow grid (or whatever the mouse cursor looks like) underneath it, if it's raised up a bit. If you don't raise the selected object up, the visual cue is ambiguous and misleading, when you place multiple objects by holding down the 'shift' key, after you've placed one object and are now moving another, but holding it the same place as the one you just set down. In reality there is one brand new object there, and an identical object drawn in the same place, plus a yellow cursor underneath, plus red X's showing that the object you're carrying can't be placed there (because there's another one already in the same place). But it looks identical to the situation where you're trying to place the first object but can't for some mysterious reason (you can't tell that there are two object there, since they're drawn in the same place, and there is no positive visual feedback that the first one you placed ever got there. But if you lift the one you're moving up a bit, you can obviously see that there are two object there, one in color in place, and one in monochrome floating above. Another issue is that the red X's are really ugly. They tend to visually break up the multi tile objects. They are often hidden inside of objects by the Z buffer. We need to design a nice visual way of feeding back placement error conditions, that gives the user some idea of what's causing the problem, and what to do to solve the problem. If there is one tile blocking a multi tile object, all red X's are displayed in all the multiple tiles anyway, the feedback does not tell you which tile had a problem. In order to do that we would have to make the CanPlace function try harder and set flags on the objects indicating error status. CanPlace is lazy and once it finds one reason not to place a multi tile object, it says the whole thing is unplaceable instead of trying to find more reasons not to place it. This is good since CanPlace is called A WHOLE LOT. There are some complications about giving error message feedback for placement problems. There may be several reasons why you can't place an object somewhere. CamPlace is lazy about checking if you can place an object, which is good, because it's called A LOT! It bails and returns false on the first problem, even though there may be several problems, some possibly more important to the user than the first. The order it tests for problems may be arbitrary with respect to what the user cares about, so we can only feed back one of several possible problem conditions which may not be the 'most important' one. Multi tile objects magnify this problem, because the user might wonder which tile of the multi tile object is causing a problem. Staircases in particular are a bitch, because you're downstairs placing them, and they have an upstairs tile for the landing that you can't see, since everything upstairs is invisible. The landing has a wall prohibition that keeps you from placing it so you'd have to walk through an upstairs wall, but you can't see the upstairs tile or wall that might be causing the problem. Right now the placement error feedback simply makes all of the tiles of a multi tile object have red X's, giving no indication of which tile is (or tiles are) causing the problem, or even what the problem is. Somehow we need to organize and prioritize the placement failures, and if placement fails, then test for the most important problem and feed that back to the user. >SFX - Buy Mode Control Panel > Sfx of "ka-ching" is played every time an object is bought. When > selling object back by Delete key or by moving it back to CP, the > addition of dollars back into account will play a different, > money-related SFX. Budget highlights momentarily with new amount. Font size could momentarily expand when you were refunded money, and momentarily shrink when you spent money! What does ka-ching sound like backwards? >CP and in the World object SFX will be specified when all game >interface issues are set. Need to work out a good set of sound effects for pie menus, including the view control pie menu. Different sound effects for selecting different items would be really great. Pitch could indicate up and down, pan could indicate left and right. Rotation sounds could pan from left to right or right to left. Zooming in sound could get louder and/or lower, zooming out sound could get softer and/or higher. Speed control slider could play a sound indicating the speed, so you could hear the notches. Quitting the game: See notes above about quitting with the 'X' button, and canceling tools and menus. Quit dialog: Instead of a series of yes/no dialogs (really quit? save game?), collaps quitting confirmation and save into one dialog with three buttons: quit without saving, save and quit, don't quit. Make keyboard shortcuts so you can type "q" or "y" to quit, "s" to save", "n" or esc to cancel, etc. You should be able to quit even if a modal dialog or pie menu is up, since you can always press the "X" button (or type alt-f4). So the quit dialog may have to cancel whatever other modal dialog is up, or properly unwind the stack somehow. This is another reason to avoid modal dialogs. We could simply make the quit dialog (and all others) non-modal. >Deleting Architectural Objects > To delete an architectural object in the game, select the Hand tool > from Arch tools CP, click on the object in the World you wish to > delete to select it, then hit the Delete key or move the object > down into the Sell/delete button on the CP. In Build Mode you can > delete architectural objects as well as all objects bought in Buy > mode. Another way to delete a door or a window, would be to draw a wall over it. If you try to place a new wall on top of an old wall that has a door or window in it, the door or window is destroyed, and the wall either keeps its wallpaper (for user convenience), or gets its wallpaper reset to the drywall state (to simulate knocking out that part of the wall and putting up a new one). ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Wednesday, August 26, 1998 8:05 AM To: MAXIS CTGPROG @ Maxis Subject: GridBlitter! I've implemented a GridBlitter. It draws pixel perfect grid lines, with both white and black edges that meet up to form nice sharp edges, and 12.5% black stipple inside the grid, so it darkens everything underneath. Right now it just draws a grid on flat tiles of the current level that don't have a floor. Soon it will be driven by a new layer of flags for editing constraints and feedback. We should be able to do stuff like turn the grid stipple red to highlight bad tiles (where you're trying to build but can't), just by setting bit flags in the new layer. Also: in ObjectModule.cpp I put some D( ... ) macros around new code what was going << to ctgDump, so they don't cause compile errors in the release build. -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Friday, August 28, 1998 1:51 AM To: MAXIS CTGPROG @ Maxis Subject: Floor tile and wall constraints I've implemented a layer of flag bits, that tracks "floorable" and "outdoors" flags for each tile. The CalculateRooms function now does a flood fill on each level to determine which tiles are outdoors, and then uses that information from the level below to figure out which tiles are floorable. The room code needs to look at one of the room tiles to figure out if a room is indoors or outdoors, and the lighting code needs to not darken outdoor rooms. I optimized the new flood fill code quite a bit from the code I copied it from. We need to go back and rewrite some of that older flood fill code so it's faster and easier to understand. The grid now only draws floorable (but unfloored) tiles on upper floors. In order to be floorable, the terrain underneath it must be flat. On the first floor, all flat terrain is floorable. On the upper floors, a tile is floorable if any of the tiles underneath it are *indoor* rooms. The set of "tiles underneath" is defined by a lookup table "support function". There's a lookup table that defines the shape of the footprint that covers the set of tiles to check underneath for floorability. It's like a paintbrush that's used to widen the "outdoors" mask. The shape is currently a 5x5 square with the corners cut off, so upper levels have floorable tiles out two tiles, except for the corners that are notched out. So if we want to change the number of floor tiles overhang you can have, or the shape of the corners (cut off or not or even more cut off), we can easily change the lookup table. For you signal processing fans, the floorability plane is a kind of boolean-or convolution of the "support function" (a convolution kernel or paintbrush mask) and the inverse of the "outdoor" bit plane. I fixed both the floor tool and the wall tool to respect the floorability plane. With the floor tool, it's still possible to put a tile floating in the air disconnected from the building, since it only checks for floorability, not connectedness to other floor tiles. It would be quite tricky to make it also check for connectedness, because of the way the floor tool works right now, since it allows you to drag out a rectangle of multiple tiles at once. That loops in x and y putting tiles down in a rectangle, but there is no guarentee that it will put them down in the right order so you can drag out two overhanging tiles. It might let you put down two overhanging tiles along one edge, but beep and only let you put down one overhanging tile along the other edge. This is because the connectedness constraint imposes an order on which tile has to put down first (first the one next to the wall, then the one further out). But the order that the floor tool rectanglar fill loop enumerates the tiles, may not be the right order. There is no one right order for the rectangle fill loop to enumerate the tiles, because you might be dragging out a huge rectangle that completely overlaps the house, so some edges would always be put down in the wrong order. The wall tool only checks for floorability on one side or the other of the wall, so you can put walls right up against the floorable edge. It does not check for actually having a floor, although it could, but it would be more limiting about what order you could draw things. It is more convenient if you can put the walls down first and then use the floor tool to flood fill the rooms with just the tiles you want, instead of having to spend time flooring by hand, or extra money reflooring rooms after you build them. Walls that don't enclose rooms don't provide any support for floors upstairs. It's based on there actually being a room in the tiles below, not on the walls between the tiles. So you can use a 1x1 square room as a "pillar", but you can't use just one piece of wall sticking out or standing alone as a support. -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Friday, August 28, 1998 7:52 AM To: MAXIS CTGPROG @ Maxis Subject: Keep on flooding; enter/exit notification The code that flood fills to figure out what's inside and outside now knows to keep on flooding over fences. The room id assigning flood fill code still respects fences as walls, so the fenced in areas get different room ids, but their outside bit is set. (I added the outside bit in the new flags layer, and the inside/outside flood fill just a little while ago). I guess we need gates for doors in fences. I wonder if the door tool should automatically place a gate on a fence, or if the door tool should refuse to place doors on fences, and there is a separate gate tool that only places gates on fences? Anyway, when the lighting code isfixed to recognize the outside bit of rooms and light them with daylight, the outside fenced in areas won't be dark, and you will be able to place trees in them. (I'll fix the ISOUTSIDE macro to check the outside bits, instead of relying on the room id). And now that fenced in areas are outside, you can't build floors and walls over them in the next level as if they were indoor rooms! Also in order to implement the "drop in panel to refund" behavior of the move tool, I have put some notifiers on cpstate and tools. There was a notifier called something like "MouseLeftPanel" that really meant "MouseEnteredView", that was being used to pop down the speed slider, so I changed the name what was really going on, and added the other one, and now cpstate also passes those messages on to the current tool, so it can do whatever shenanigans it needs to when the cursor moves between the control panel and the world view. The current tool now has OnEnterView and OnExitView notifiers that tell it when the cursor goes in and out of the world view window. At first I tried putting an OnMouseEnter and OnMouseExit notifier on the control panel window, but that did not get called. The reason is that the Enter/Exit notification is not sent to every ancestor between the exited and the entered window, like the way most other window systems work. There are a few flavors of "mouse crossing" event that you could track, including entered, exited, passed thru entering descendant, passed through exiting descendant, etc. Basically, we would have to modify the mouse enter/exit tracking code in the framework to crawl up to the common descendant sending mouse exit events to each window along the way up (all but the first would be passed a "crossing" flag of true), and then crawl down to the entered window, sending mouse enter events to each window along the way down (all but the last would be passed a "crossing" flag of false) The "crossing" flag of true tells a window that one of its children (or grandchildren...) is losing or getting the cursor, not the window directly. Currently none of the crossing windows are notified of enter/exit. What I really want to track is OnEnterControlPanel and OnExitControlPanel, but that's hard as described above, because the various subwindows of the control panel are notified instead of the control panel itself, and the notification isn't passed up to parents (and should not be, since that would deliver it in the wrong order, since windows should be notified in the order they were entered). It is possible to track the mouse entering and exiting the view, since it isn't comprised of a bunch of subwindows. Tracking the mouse going in and out of the world view isn't the "opposite" of tracking it going in and out of the control panel, because when you're not in full screen mode, the mouse can go outside of both of them, and it may have to distinguish the cursor being outside the window, from the cursor being inside the control panel. For now, I just based the tool "OnEnterView" and "OnExitView" notification on the GZOnMouseExit and GZOnMouseExit methods of DDDSimsView. I am hoping things don't get screwed up if the notifiers are spuriously called when menus pop up, or when the mouse is over the scrolling cursor hand subwindow, or the mouse is outside the window, and stuff like that. We'll see. Maybe it's worth fixing the enter/exit notification to work the way I expected it to work, so the problem of tracking the mouse entering and exiting the control panel is easy to fix. -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Friday, August 28, 1998 8:57 AM To: MAXIS CTGPROG @ Maxis Subject: ISOUTSIDE semantics changed, now per tile instead of based on room id; outside room lighting works! There used to be a macro called "ISOUTSIDE" that looked at the room id to see if it was zero, since room zero was outside. Then with multiple levels, we needed multiple outsides at different levels, so the room id was expanded to 16 bits and the level was recorded in the upper bits, so ISOUTSIDE could look to see if the lower bits were zero, so there could be an outside for each level. Now we need even more outsides, more than one per level, in fact each tile has an outside bit in the flags layer. Now there is a method on the world called IsOutside that takes a CTilePt, and returns true if that tile is outside. And there is a method on Room called IsOutside that takes no arguments, and returns true if that room (actually the first tile in that room) is outside. And the ISOUTSIDE macro is now called ISWAYOUTSIDE, which is still needed for the floor flood fill code in the case out outside upstairs rooms. I updated all the code that called the old macro to call one of the new methods as appropriate. The result of this is that lighting of outside rooms works right! It figures outsidedness correctly so all outside rooms (now including areas enclosed by fences and upstairs outside tiles like outside on the roof) should now be lit with the outside ambient light! Also the grid is only displayed in arch mode, so the static layer is invalidated going in and out of arch mode. -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Friday, September 18, 1998 10:01 PM To: MAXIS CTGPROG @ Maxis Subject: Deleting windows and doors with the wall tool I've implemented the delete wall & door feature in the wall tool! It was tricky making sure it's deleting the right window or door that's attached to the wall, but that works now. Even trickier was keeping the object undoable and the wall undoable from stepping on each others toes... The object undoable is used to delete and create doors and windows, and they punch holes in the wall. There is a weird problem with the wall undo memory remembering the holes in the walls that the doors and windows punched, that confused the object undoable when it tried to undo and put the door back, where there was still a hole (that the wall undoable had restored from its snapshot). I made doors and windows (portals) allow placement on a wall that already has the right hole punched in it, for now. There may be a better solution that involves moving some code around or patching up the wall undoable's picture of the walls when doors and windows get added and removed. In some conditions I'm getting an assert "big problem" in RoomManager::ProcessDegenerateTile, but that may have more to do with the diagonal walls and the room flood fill, than the wall tool. Also I fixed the view pie menu so it knows it's been clicked up. (There's a flag to popup that tells if the mouse button is up or not, that I changed). So now the menu pops down on the next click, instead of requiring two clicks to cancel after popping up. -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Wednesday, September 23, 1998 6:15 AM To: MAXIS CTGPROG @ Maxis Cc: willw@emf.net Subject: Enforcing placement rules, moving objects, inhibiting terrain tools, and selecting people I've got a lot more of the placement rules implemented and the appropriate bits in the objects set. Placement error feedback is on the way via global gPlacementError codes and tooltips. I made the move object tool only pick up top level objects, not things they contain. We can make it smarter as it's spec'ed. And you can't put lamps on the couch seats any more. And you don't get the sell panel when you drag an object you don't own (from the catalog or a tree, that you haven't bought yet) into the right part of the control panel. If you change modes or do anything that cancels the move tool, it uses the undo manager to move the object back to where it came from, and clears the redo memory so the user will not be able to redo the move that was never finished. I fixed the terrain tool not to effect terrain that had floor tiles or walls or objects requiring flat tiles, on any level above the terrain (1st or 2nd level). I marked the 1 tile tree, tall shrub, duck, and flamingo so they could be placed on slopes. The multi tile apple tree cannot be placed on a slope. If you move a multi tile object over a slope, the tiles display at different heights. Will thinks this looks neat. It's especially cool since you cannot place the object there, so it moves smoothly, and the tiles rise up and down smoothly as you move around, so it looks extra-neat! But the apple tree is a 2x2 multi tile object has its trunk split down the middle into four quarters, so it looks funky when it's on a slope. So I marked it not to allow placing on a slope. But we could offset the trunk from the center slightly, no reason the apple tree has to be in the center of the 2x2 tile. If it were offset, then only the branches would be out of alignment, and it would not look so bad as the trunk. I think we should try that and see if it looks ok, since it's a shame to disallow apple trees on slopes, which we currently do. The terrain tools will raise and lower land that has objects that can be placed on slopes, so the regular trees and tall bush don't effect the terrain tool, and raise and lower with the land. All the trees and the tall bush must be placed outdoors and can be placed on slopes (except the apple tree). The short bush that has a planter can be placed indoors, and it must be placed on level ground. Try placing a short bush on level ground, near a tall bush, then raise the terrain up around them a lot. Notice that the tall bush with the stem in the ground raises up with the terrain, and the bush with the planter maintains a flat footprint underneath it in the terrain, that does not change altitude. Move the planter out and notice how it won't place on the slope, but snaps back into the hole it left behind! Now you can select people by clicking the right button on any part of their bodies, with vocal audio feedback! I figured out a simple way to do pixel perfect hit detection on people. The trick was for XAnimator to look at the z buffer at the cursor location before and after it draws each person, and if the z buffer changes, then the cursor is pointing at that person, so it records the person in a global! The ObjectPickerTool looks at that global to highlight the person you're pointing at. If the person is submerged in the tub you can click on any part of them above the water, naturally! When you click the right button on a person, it selects them, and makes a short vocal hey sound (male or female). [At some point will each person have their own generic vocal sounds? if so we could call out one of those and you could recognize each person's voice. Right now it just does male and female voices.] And right clicking on the selected person (double right clicking on an unselected person) plays a longer hey vocal, and centers on the person as long as you hold the mouse button down, ala the face buttons in the person panel. Now the face buttons also make the vocal sound when you press them, and the sound is panned by location and attenuated by distance, so you can hear the location of the person left to right (do we support 3d sound?), and as you hold the button down and they scroll to the center, you hear the sound center! Nice job on that cSoundPlayer, that "just worked" and did all that stuff without any effort! -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Saturday, September 26, 1998 8:28 PM To: MAXIS CTGPROG @ Maxis Cc: willw@emf.net Subject: Stuff done With the help of Erik I chased down some really henious bugs in the wall undoable, the way it was deleting doors and windows when you put a wall over a door or window (as opposed to deleting a wall with a door or window). Now the door and window tools work properly. You will have to delete old doors and windows and put new ones, since they are now marked with bits that tell the move tool how to treat them. When placing doors or windows, you automatically get another one after you've placed one, unless you're out of money, in which case it boops and reverts to the move tool. When placing a door or window, you can hold down the control key to delete other doors and widows: the one you're placing disappears, and the one you're pointing at turns red, and is deleted when you control-click on it. You can keep holding down control and control-click on any number of doors or windows to delete them (no matter if you're placing a door or window, you can still delete both). When you release the control key, the door or window you were placing reappears and you can finish placing it. The move tool (when not moving doors or windows) completely ignores doors and windows. So you can't pick up doors and windows, only place them and delete them. There are two ways to delete them: one is control-clicking while in the door or window tool, described above. The other is by using the wall tool to put down an empty wall on top of them, or using the wall tool to delete the wall that they're on. When you pick up an object you already own, the "sell" popup pops up immediately, so you're prompted to click on the panel to delete it. When you drop it somewhere in the world the panel goes away. If you try to put an object down in an invalid location, it boops, and displays a pop-up tool tip by the cursor, instantly, for as long as you're holding the mouse button down. This means you can press down, see the error, move around to rotate the object, and when it rotates into a good position, the tooltip disappears and the objects returns to normal color (it's red when it can't be placed). If you keep rotating it back to an invalid position, the tooltip reappears, telling you why it can't be placed again. The tool tip follows the mouse cursor. When you release the button, the tooltip disappears instantly. If the object is in a valid location, it's placed. If it's not, then it snaps to the cursor and the grab point is reset. It resets the grab point after rotating but while still carrying (since you could not rotate into a good position and drop it), since otherwise you end up with the cursor dragging the object from far away (since it rotated from out of under the original grab point. It also resets the grab point of the object you're moving whenever you zoom or rotate the world, as well. In the process I fixed the grab point to be in screen coordinates instead of tile coordinates, which makes more sense. Please check out the placement error tooltip popups, by trying to place objects where they should not be, like a door on the second story where there is no floor, etc. There are a bunch of different error messages, and it may need some tweaking so the appropriate ones come up (several things could go wrong at once and I've arranged the code to test for the most interesting things first, so that will be the error message you get.) Tell me if you get an error message that doesn't make any sense! I took out the test in CheckWallFlags that was setting kPErrMustBeAtTileCenter error, insisting the object must be at the tile center, since it was confusing the portal code, which should have been setting kPErrMustBeAgainstUnusedWall, complaining that the tile could not be placed on a used wall, but kPErrMustBeAtTileCenter was being returned instead. Since the tools prevent the user from causing a kPErrMustBeAtTileCenter, but they cause it themselves (in case it could not be placed for some other reason, it moves the tile away from the center to the exact cursor position), I just took out the test for the error. Now when you try to put a door or window on top of another one, you get a nice "Must be against unused wall." message now! -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Wednesday, November 04, 1998 11:52 PM To: MAXIS CTGPROG @ Maxis; Hedman, Eric; London, Charles; willw@emf.net Subject: Censorship technology! Now that we have naked people, Will pointed out we need to censor just certain parts of the body, so I refined the meaning of the censorship event tag in animations. Now the animators have much finer control over what parts of the body are censored at what times! The "censor=" event tag used to use a 0 or 1 value to turn full body censoring off and on. Now that value is a bit mask, so 0 turns off all censorship, and the other bits censor various body parts: // 0x00: no censorship // 0x01: censor pelvis // 0x02: censor spine if female (for conditionally censoring female breasts but not male chests) // 0x04: censor head // 0x08: censor left hand // 0x10: censor right hand // 0x20: censor left foot // 0x40: censor right foot // 0x80: censor full body The 0x80 full body censorship mode overrides all others, and censors the bounding box of the whole group of all meshes (including pool cues, etc), which is equivalent to the old behavior. The other bit masks add the bounding box of all skins on the corresponding bone to the censor rectangle. So if you censor the left and the right hand, and the person is posing like Jesus on the cross, the censored rectangle will be wide and short and extend across His Holyness's chest. Anything He's holding in His hand will be included in the rectangle, so if He was holding a pool cue vertically in one hand, that would make the censored rectangle very tall. Now we can censor any tobacco products held in the hand (since cigars are now considered obscene). It sure would be funny to see people passing around a censored joint at a party! Or we could even censor the heads of people who are french kissing, or just the hand squeezing the butt cheek during the passionate kiss. It adds an extra border around the bounding box, which I reduced so the effect is tight. I also had to add a y fudge factor to lower it a bit (since the rectangle returned by GetLastRenderDamage seems to be a little high), to prevent the bottom of a female head from getting censored (when censoring her chest). I also made the pixelation size vary with the scale, so the blocky pixels get smaller as you zoom further out. -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Wednesday, January 27, 1999 2:35 PM To: Ryan, Kana; MAXIS CTG @ Maxis Subject: RE: Luc feedback to check into >Heads appear to be turning more than 180 degrees. (I wanna see >this.). Mike, this might be something for you to dig into if no one >has seen the problem yet. You could try to created & show one of the >programmers, Don? Or Patrick? Oops, my bug, now fixed! I was tinkering with the head faking to get it to record properly, and checked it in before I was done. Sorry! The head faking uses a low level matrix rotation applied to the bone's matrix transformation, but the animation recording captures the higher level quaternion rotations and offsets, so recording of head faking doesn't work. I will fix head faking to apply rotations to the quaternion rotations instead, so recording head faking will work, and the math will be cleaner when we want to add vertical head faking (so someone sitting in a seat and someone standing in front of them can look at each other while having a conversation). The nodding and shaking heads in the pie menus use concatinated roll/pitch/yaw matrix rotations instead of mixing quaternions, and I don't think it looks very realistic because of that... You can see the distortion when you make then look up or down and shake their head, or left or right and nod their head. I think mixing quaternion rotations would look better than concatinating rotations, for the head faking and the heads in the pie menus. When you use quaternions to mix an extreme left turned head with an extreme up turned head, the combined rotation is not as extreme and off kilter as when you concatinate those rotations. -Don ==== From: Julia Menapace [SMTP:julia@best.com] Sent: Thursday, February 04, 1999 6:35 PM To: hopkins@toad.com Subject: 3D Studio Max Hey Don! I am hoping to get into a class at College of Marin in 3D Studio Max and one of the first assignments is to interview someone who uses Max in their work. Tomorrow morning I'll know if enough people dropped the class in the first week to promote me from the waiting list. So I am doing the first assignments. If I remember correctly you use Max at Maxis to create environments for Doll House. One of your projects is taking the Max output (what format?) and compressing it further for use in the game. Is this necessary because there is that much more data in dollhouse than in other video games or are you trying to make it network friendly? Your were also talking about hiring a character animator who was using Max to build people and animate them. Or was he using some other program to make the people and using Max to make the rooms and the objects in the rooms? I remember you talking about making the characters dance under various circumstances. I also remember you talking about animating the people using objects found in the houses but I don't remember what the examples were. Aside from compressing the output how else do you augment 3D Studio Max for your work at Maxis? Do you use any special plugins? Is there anything else about Max, 3D modeling or animation that comes to mind? Who else do we know who uses Max professionally and what do they use it for? I also recently went to an open house for the San Francisco State Multimedia Studies Program. I remember you recommended the place to me a while back and onmchecking it out I did get the impression that it would be a good place to learn and to make connections. It turned out that Burt Monroy was teaching the Photoshop seminar at the open house and so I got to learn some cool things I didn't know about Photoshop from him in just half an hour. Tony Bove is timesharing my apartment in San Francisco right now, Sunday night through Thursday, so for now it more convenient not to mention cheaper to take class in College of Marin's Multimedia program. Then maby I can intern and be a lab assistent with the SF State program later if I'm still interested. Hope this isn't a bother. Best, Julia ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Thursday, February 04, 1999 7:46 PM To: 'Julia Menapace' Cc: Hopkins, Don Subject: RE: 3D Studio Max I'd love to tell you all about what I'm doing with Max! Let's discuss it more in person or at least on the phone, since there's so much neat stuff to cover. Right now I'm working on a way for us to import Quake skins and characters in our game! Quake skins use a standard texture map bitmap layout (head here, chest there, back there, arms and legs here and there, etc) so that anyone with a 2d paint program can create and modify their own character textures! Creating your own 3d polygon mesh is a whole lot more difficult, but we at least want to let people drop in their own textures. So we want to make it possible to use quake character textures in our game, so players can draw pictures of their family members, or draw tatoos and naughty bits on the characters supplied, or even have monsters living in their house! Here's a web page I wrote to overview the animation system I created. It's slightly out of date but it does cover the main topics. (Well, at least it touches on them in an outline -- I can explain more in person.) The exporter now supports the compression of low frequency floating point numbers, that represent the smoothly varying rotations and translations (as quaternions and 3d vectors). Since the numbers change very slowly, typical audio compression techniques were not appropriate (since they're only good for much higher frequencies), so I came up with my own ad-hoc compression scheme. We've currently got more than 300 max files of content (animations, 3d characters, and skeletons), and an Access database describing all the objects and content in the game. The exporter reads in the database so it knows what to do, and so it can batch export all the content at once without human intervention. The reason we have our own file format is that we only want to distribute the essential and optimized data that the animation engine needs to do its work. Other formats like max files (which are much to complex to parse easily) and vrml (which is not robust enough for "real world" applications (not even "virtual world" applications, ha ha ha!)) are too general purpose and not optimal for the requirements of the game. Other reasons for our own format are that we need to use certain types data representations, like quaternion rotations, that are best suited to the kind of animation we're doing. (Quaternion rotations are easy to interpolate between, while the typical roll/pitch/yaw representation of rotations sucks rocks for many reason.) So we would not be able to compress the animations efficiently if we used pre-defined file formats. Most games and things like that tend to invent their own file formats for many of the above reasons (as well as NIH syndrome). We're actually using several types of files: All of the original content is stored in "max" files (but there is other information in the access database, like source and destination file names and directories, that's not in the max file). The exporter writes out "cmx", "cfp" and "msh" files. Text "cmx" files represent the actual skills, suits, and skeletons. These files are small, and point to other larger binary files (cfp and msh files). The games reads in all the "cmx" files when it starts, so it knows about all the animation assets, but the cmx files don't contain the raw data, which is only loaded on demand. They just contain the names, properties and measurements of skeletons, skills and skins, as well as pointers and offsets into the raw data files. Binary "msh" files represent 3d polygon meshes, and the format is defined by our own 3d library (called DDD), written on top of DirectX. Texture maps are refered to by name in the "msh" files, and are stored separately as separate "bmp" files. "cfp" files represent low frequency compressed floating point numbers, used to store the raw rotation and translation data. Each animated skill has a certain number of rotations and translations associated with it, divided into per-bone chunks of smoothly varying 4-d (x,w,z,w) rotations and 3-d (x,y,z) translations. The compressor writes the numbers out in column major order for each bone, first all the x's for a bone, then all the y's, etc. This is so consecutive floating point numbers are smoothly varying, which they would not be if it compressed them like "x0 y0 z0 w0 x1 y1 z1 w1 ..." instead of "x0 x1 ... y0 y1 ... z0 z1 ... w0 w1 ..." If I did it again today from scratch, I'd probably write out the CMX file as XML, instead of the simple arbitrary format I came up with. XML is great for representing structured data like hierarchical skeletons, and skill and suit indices, but not for binary data. But the XML file would just refer to binary data by a relative URL or file name, the same way the text CMX files currently refer to the binary .cfp and .msh files. The advantage of using XML is that other programs could read it in and make sense of it, so it would be easy to write programs to take inventory of all the content that's been exported, etc. Currently we're using some perl scripts to do that, but XML would be a great way to describe the whole database, given the right tools (which we don't have yet). Below is a message from John Wainwright, who's the author of MaxScript, the scripting language that's in 3D Studio Max. He was giving a talk about MaxScript, and asked me to describe how I was using it, so he could cite it as an example. I worked with him at Kaleida, where he was the architect of ScriptX, and I like MaxScript because it's similar to ScriptX! The thing that was really missing from ScriptX was a good facility for interfacing with other programming languages, like extending and calling the language from C or C++. But MaxScript has solved that problem nicely. MaxScript has its own plug-in facility, like Max's plug-in facility. Since MaxScript itself a Max plug-in, you effectively have plug-ins with plug-ins! Max has special plug-in interfaces just for writing things like importers and exporters, while MaxScript has plug-ins for implementing new MaxScript primitives, that you can call from the general purpose programming language. I had originally written my exporter as a Max exporter plug-in, but when MaxScript came along, I restructured it so it was a MaxScript primitive instead. So the exporter could be called under program control (so that batch exports were possible!), and passed lots of arguments to the primitive (that it reads from the database, (so it knows what directory and file name to export to, etc), and it can return lots of results (so the exporter can return an array of results that summarize what it did, and error messages that identify exactly what went wrong with which file). MaxScript allows you to script user interface control panels with buttons that call MaxScript functions and other widgets like scrolling lists (that I use to list all the animations in the database, read from Access via OLE automation). So I rewrote the ui of the exporter in MaxScript, that reads the database, and calls the back end exporter primitive. Using MaxScript instead of the standard exporter interface gave me a whole lot of flexability, so the exporter can make sure there are no human errors (which are extremely hard to track down with 300 files involved), and can automate other aspects of the process, like batch export, and checking content out and back into SourceSafe (the source control system we're using). -Don ==== From: John Wainwright [SMTP:johnw@lyric.com] Sent: Tuesday, May 05, 1998 1:31 PM To: Hopkins, Don Subject: CGDC talk Hi, Don. Kinetix has roped me into giving a talk about MAXScript at the Game Developer's Conference in Long Beach on Friday. I wanted to see if its OK to mention your use of MAXScript at Maxis and if so, maybe you could give a few bullet points on what it's OK for me to mention. Of course, I remember the note track key stuff and the Access database interface, but I'm not sure if there were other things and how all that wound up coming together. Thanks, John. ==== You could say I'm using MaxScript to automate an animation content pipeline. The goal was to drive the exporter from the database to minimise the effect of human error, and to support automatic batch exporting. I used OLE to read an Access database table, describing all the animations, and I used the DOSCommand primitive to invoke SourceSafe. I recast my animation exporter as a MaxScript primitive, so it could be called under program control. The MaxScript plug-in interface allowed me to access the Max plug-in interface, and that was sufficient to implement the exporter without any need for the standard Max exporter interface. (The Max exporter interface requires you to implement a bizarre node enumeration callback interface, but it's straightforward to recursively enumerate the nodes yourself from a MaxScript plug-in.) The advantage of a MaxScript primitive over an exporter is that you can pass arguments to it, and it can return error messages and data structures describing the results of successful exporting. The arguments can be read out of the database and the exporter called without any human intervention, then the results of exporting can be validated against the database, and meaningful error messages and feedback can be reported to the artist. I made a MaxScript control panel that allows you to browse all the animations in the database, load the corresponding Max files, check the content in and out of SourceSafe, configure the export directory, automatically export any animation, and batch export the whole database or subsets of it. We're using note tracks to mark up the animations in time, and to insert events into the animation. A note track can be associated with any node, and contains keys in time with text values. The text is formatted as a property list of "name=value" associations. The exporter looks for these notes to figure out what to do. I added note track access primitive in order to automatically insert appropriate note tracks and properties in as specified in the database, and to validate that the required notes are present. The arist can then adjust the position of the notes in time (moving footstep events so they correspond to the time when the foot hits, for example), and edit their textual "name=value" properties (to control parameters of the exporter, and send events to the animation playback engine). If you want to demonstrate an interesting MaxScript programming example, there's a neat function called "defRecordStruct" in the code I posted to the Kinetics MaxScript bboard, that takes an Access RecordSet OLE object, and defines a MaxScript record that corresponds to it, and a MaxScript function that reads it into a record. An interesting exercise would be to extend it to define a MaxScript function that writes the record back into the OLE RecordSet. -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Friday, February 12, 1999 11:44 PM To: MAXIS CTG @ Maxis; Mackraz, Jim Subject: Exporting meshes bound to multiple bones OK, I've got the exporter creating efficient run-time data structures for deformable meshes bound to multiple bones with blended vertices! The exporter sorts all the vertices by bone, so it can do them all efficiently in contiguous chunks. So it has to remap all the vertex indices in the faces and blended vertices, after sorting. At runtime, when you bind a DeformableMesh to a Skeleton, it makes one BoneBinding per bone that's used, each with a pointer to the bone, and they copy and pack all the rigid and blended vertices contiguously into their own vectors, for fast transformation, stashing the extra BlendData(index,weight) in a parallel vector so it stays out of the way. Then it allocates an output vector in the DeformableMesh with room enough for all the transformed vertices. The transformed vertices at the beginning of the output vector are refered to by the faces, so just those need to be sent to DirectX. At the end of that vector are all the blended vertices, which are not referenced by the faces, so they don't need to be sent to DirectX, since they're just blended into the ones before them. First pass it asks each BoneBinding to transform all of its rigid and blended vertices into the output vector of the DeformableMesh. Then it asks each BoneBinding to blend all of its blended vertices back into the DeformableMesh's output vector. It keeps the weights and indexes of the companion vertices in a parallel array, so as not to interrupt the contiguous 3 float vectors during transformation. Here's the result of dumping the run-time BoneBindings, after exporting and binding the suit Chin gave me. Notice that the Vert's are numbered consecutively, as are the BlendedVert's. The "otherIndex" field of the BlendedVerts are the indices of the Verts to blend with the given weight (which by definition is associated with another bone). The x,y,z numbers aren't transformed relative to their bones yet, so don't worry if they look funny, since they're still in the world coordinate system. -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Thursday, February 18, 1999 5:06 PM To: MAXIS CTG @ Maxis Subject: Live SimRadio on the net I've been thinking about how we could enhance the game with music, by putting a real "SimRadio" into the game that receives live audio broadcasts from the internet. Maxis could run several "SimRadioStation" servers that broadcast MP3 music and SimDJ dialog, much like the simulated radio in many games, but run on a server and efficiently broadcast as MP3 via IP multicasting. The technology is in place for us to create our own internet radio and tv stations, and it would be easy to integrate a reciever into the game. It would solve the problem of repeated music loops driving players insane, and it would be a wonderful advertising and distribution channel for plug-in objects, and other Maxis and EA products! The interesting twist, is that the radio stations could take requests, and have real time interactive call-in contests, just like real radio stations! But the contest players would be the Sims in the game (acting autonomously or under control of the player), who would have to run to the phone and try to be the 20'th caller when they hear a song by the Beatles, and lots of other stuff like that! They could actually win SimPrizes like virtual money, furniture, personal growth, interesting visitors ("dinner with Elvis!"), or unique decorative items (like a Jim Morrison or Kermit the Frog poster). Or even real Maxis products: "Win a trip to the big SimCity!" "The first person to answer this trivia question goes to Mars!" Think of it like a game show, where the show is actually an entertaining advertisement for the prizes! The possibilities for advertising and product placement are limitless so I won't even go into them... This would put the game "online", since you would actually be listening to a broadcast and competing against other people at the same time, just like a real radio station! The best thing is that it would not require any major changes to the design of the game or the code. The technology to implement it is well understood, in fact everybody else is jumping onto the internet radio bandwagon these days, but nobody's integrated it into a game like this, that I've ever heard of. One big advantage to going online this way is that it's a great way to gently enforce product registration. (I'm pointing this out in light of Larry Probst's recent message about software piracy.) You could only participate in the contests if your copy of The Sims was registered. Perhaps the demo version would only pick up free broadcast radio and TV stations with lots of ads, but when you registered it, you get "cable TV" and "digital radio", with lots of good music and contests and prizes. The radio station would be a great "in-game" way to advertise and distribute new plug-in objects as prizes and products! Instead of going out of the game and using an unwieldy FTP client to download a file, registered players could respond to contests and advertisements on live radio and TV, to seamlessly download and install new objects, and have them delivered to the front door. The music from the radio station could be encoded with a "moody track", marked up with events that affected people emotionally. Of course different people would react to the musical moods in different ways, but you would actually be able to increase a character's happiness by calling up the radio station and requesting their favorite song. Or turn an unruly crowd into a wild party by turning off the cop show on TV, and switching on the radio to a dance music station. -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Thursday, February 25, 1999 3:46 PM To: 'Jamie Zawinski' Subject: RE: [Fwd: Re: Static Constructors] Hmm, can I see some more context, or do you just like to see me shoot my mouth off without knowing what I'm talking about? (-; The user interface framework we're using has its own cheezy implementation of a com-like thing, that's not really used. So we ripped it out, reducing the number of header files and the compile time signifigantly. If we need to use COM them we'll use COM, and not some pale imitation of its surface features. Most of the classes in the framework were separated into pure virtual interface definitions and separate implementation files. But it was done by a bunch of different undisciplined programmers who didn't understand why they had to do it that way, so AddRef and Release weren't implemented everywhere, and Release was often returning the invalid refCount instance variable *AFTER* deleting this, instead of the constant 0! And of course the header files all got out of date, since whenever somebody added a method to the implementation, it was a pain in the ass to update the interface to include the function, because then the entire project has to be recompiled. So lots of code would just use references to the implementation classes instead of going through the interfaces. Presumably the home-made COM stuff was in there to implement plug-ins. But hell if we want to support a plug-in SDK with all of our own header files and all their dependencies. It's easier for plug-ins to use COM itself, if not just low level DLL's. -Don PS: Last night I found an egregious bug in the 3D Studio Max plug-in, character studio. Character studio consists of two parts: biped (for animating human skeletons) and physique (for pinning meshes to the skeleton, and deforming them to follow the bones). My current task is to implement a deformable mesh exporter (and enhance the engine to draw them): one mesh whose vertices are associated with different bones, that bends smoothly with the skeleton without seams. Some vertices can be blended between two bones, so the joints deform smoothly without buckling or collapsing. The trick is to read out of the Physique plug-in the associations between each vertex and the bones. They just came out with a new version of character studio that included a plug-in interface for reading that information out. Unfortunately they never tested it very well, since it returns the wrong fucking bones! It returns the parent bone, instead of the correct one. Now I have to guess which child it really means. The empirical approach would be to wiggle each child bone in succession, and watch to see which one makes the vertex in question move! I should make it update the display between wiggles, so you can watch the body it twitch all around while it's exporting to work around the bug! But the really hillarious thing about this bug in the physique exporter, is that there is *another* bug in the physique user interface, that lies about the name of the bone that's selected (when you're in sub-object envelope selection mode -- don't ask!). But the user interface bug lies to you that it's one of the CHILD bones, while the exporter bug lies to you that it's the PARENT bone! So go figure!!! Unfortunately these bugs don't cancel each other out... What follows is my bug report, that my manager helped me edit so it was nice and didn't make fun of the flakey software too fecitiously. The lesson here, is that when you ask the developer support people "can this be done?" and they say "yes", you should immediately ask them "well then has anybody actually done it successfully?" ===================================== To: 'jeff.yates@ktx.com' Subject: Physique exporter interface is returning the wrong bones! I've been getting very strange results using the Physique exporter interface to write out deformable meshes. I asked the exporter interface for the bone of the vertex, and it incorrectly return the parent bone. I read over the kinetics support web pages, and the only oblique reference to this problem I found was in the following message: >Topic: [371441] Question on Vertex Weight Export - Rigid Blended (4 of 7), Read 119 times >Conf: 22 - Character Studio/Physique File Formats >From: Jonas Ruikis (ktx_int@ktx.com) >Date: Thursday, August 06, 1998 09:31 AM > >[...] >Did you already notice that in your example, via the API, vertex 16 >is assigned to bone11 and bone12 while in the UI it assigned to >bone10 and bone 11? >[...] >Jonas Ruikis >Developer Consulting Group >Kinetix To which the customer replied "Yes, we did. We were confused about that, too. We assumed it was another inconsistency of some variety..." But nobody made any other mention of this anomaly in the email thread. Jeff, as you know, we've committed to using Physique, and our artists are already spending their time producing content. -Don ==================================== More details: I made an extremely simple mesh called "Triangle Man", that's a pair of texture mapped triangles facing opposite directions, sharing three vertices. Then I attached it to the biped skeleton with Physique, using rigid blended vertices. For some reason, one of the vertices was a "root" vertex, not rigid or blended or attached to the hand it should have been, and another vertex was "deformable" even though I explicitly filled out the physique dialog to only allow rigid blended with 2 bones, but I was able to lock them and edit their effective weights to get them attached to the right bone, in spite of this flakeyness. So now one corner is rigidly attached to the left hand, the other corner is rigidly attached to the right hand, and the third corner is blended between the left foot and the right foot. According to the "Type-in Weights" window, at least. (The vertex colors are red and dark red in spite of what I asked for and how I edited them.) Now when I animate the biped in Max, the "Triangle Man" mesh moves correctly as it's supposed to be pinned between the rigid hands and blended feet. But when I try to export this deformable mesh, both the IPhyRigidVertex and IPhyBlendedRigidVertex interfaces tell me that the vertices are attached to the PARENT bone of one they're really attached to. I'm of course calling ConvertToRigid(TRUE) and AllowBlending(TRUE) on the IPhyContextExport interface. I verified that the vertices were attached to the right bones in the Physique "assign weights" interface. The IPhyVertexExport interface's GetVertexType method is returning just RIGID_TYPE and BLENDED_TYPE|RIGID_TYPE, as expected, and I'm casting the IPhyVertexExport interface to a IPhyRigidVertex or IPhyBlendedRigidVertex as appropriate. But the "GetNode" methods of both of those interfaces always bone that's the PARENT of the actual bone the vertex is connected to!!! The offset also seems to be in the coordinate system of that wrong bone. This would certainly explain all the inexplicable problems people have been having, trying to export deformable meshes relative to biped bones. So am I supposed to try to infer the child bone of the node returned by GetNode, or something? There's no way to work around this problem, because what am I supposed to do if that wrong bone returned by GetNode has more than one child? It's ambiguous what the correct bone really is! The Physique export example that Kinetics provides masks this problem, because it converts all the mesh vertices to world coordinates, not to bone relative coordinates. If you're just taking it out of that bone's coordinate system and into world coordinates, you never notice that it's the wrong bone. But my exporter wants to write out the vertices relative to the bone they're attached to, not in world coordinates. So it's certainly a horrible bug that the exporter interface is not telling the truth about which bones the vertices are attached to. A possible symptom of this problem, is that when I select the physique'd mesh, and go into sub-object edit mode on the envelope, then select the yellow spline along the right calf, the "Physique Selection Status" roll-out says "Bip01 R Foot" instead of "Bip01 R Calf", and when I select the right foot, it says "Bip01 R Toe0". This seems to indicate that Physique user interface is calling the bones by the names of [one of] their *children*, while the exporter interface is calling them by the name of their *parent*. Neither the user interface nor the exporter interface appears to be getting the right bone. It's really funny that one is off by one toward the parent, and the other is off by one toward the child. Since there is an ambiguity with this bug in the user interface, I decided to do an experiment to clarify what's going on... So I selected the physique'd mesh, went into sub object edit mode on the envelope, and tried selecting the biped root node spline (which seems to actually correspond to the "bip01 pelvis", not the "bip01" root). And the "Physique Selection Status" window displayed the name of a non-biped mesh, "hip", that I had attached to the biped pelvis. (That's why I suspect the physique root corresponds to the pelvis not the biped root). So I deleted the hip, and then when I reselected the same spline (the one that hooks up in the crotch), the "Physique Selection Status" window displayed "none"!!! Go figure. I would appreciate some help solving this problem with the exporter. Our artists noticed the user interface problem, and just wrote it off as Physique being weird, since it does not interfere with their work. But the exporter interface problem is a real roadblock, that prevents me from exporting deformable meshes from Physique, and explains why lots of other developers seem to be having problems, too. -Don ==== From: jeff.yates@autodesk.com [SMTP:jeff.yates@autodesk.com] Sent: Thursday, February 25, 1999 8:28 AM To: Hopkins, Don; jeff.yates@autodesk.com Cc: Mackraz, Jim; Chin, Eric; Hedman, Eric; Charvat, Jeff; Bowman, Eric Subject: RE: Physique exporter interface is returning the wrong bones! Don: I'm working the exact answer to this now, but the bottom line is that this is an "error by 1" link reporting issue that relates to Max's bizzare bone notation of using the parent bone to store the childs transformation. Biped hides this from the user since it is so otherwise odd to use, but the export sdk is "literal" and reports the "trueth". I may be off a bit on this explanation, but as I understand it (and will verify), all you need to do is de-reference the child of the reported link. This is more about the different between max bone naming schemes than anything. I will verify the "fix" with the programmer and get back to you guys. Also - I know you have some outstanding issues in max land in general (Jim - got your call). I am offsite all day today and will not have time to respond but will try to forward and follow up personally when I'm back. Jeff ==== From: Hopkins, Don Sent: Thursday, February 25, 1999 4:52 PM To: 'jeff.yates@autodesk.com' Cc: Mackraz, Jim; Chin, Eric; Hedman, Eric; Charvat, Jeff; Bowman, Eric Subject: RE: Physique exporter interface is returning the wrong bones! Thanks for the quick reply, Jeff. I will post an example Max file and some code snippets from the exporter on the kinetics support web site. The problem with the work-around that you suggest is that a bone may have several children, so I have no way of knowing which child to dereference. How is this physique exporter bug related to the physique user interface bug in the opposite direction? At least one of these MUST be a bug, since one is off by one towards the root of the tree, and the other's off by one away from the root. In other words, if I pin a vertex to the calf, the exporter says it's on thigh, while the envelope user interface says it's on the foot! Which of these three bones does Physique really store the information in: the thigh, the calf, or the foot? It couldn't possibly be all three. If Max uses the parent bone to store information about the child, then how does it know which child bone the information is associated with? There needs to be an exporter interface to read that information out, and there is not. And if the information is stored in the parent, why does the envelope user interface display the name of a grandchild of that parent??! I thought the current interface was sufficient as advertised, but this off-by-one "feature" was not documented. Ideally the exporter (as well as the user interface) would hide this bizarre behavior, but they don't. As both a user and a programmer, here is the behaviour I would expect and suggest: when I pin a vertex to the calf bone, the user interface should refer to that as the calf bone, and the exporter interface should also refer to that very same bone as the calf bone. If this off-by-one "behavior" in the physique exporter is correct and expected, then it certainly should be documented. You should include an example with the SDK that explains why the bone returned is not the bone the vertex is attached to, and demonstrates how to disambiguate the child bone. Since the current documentation makes no mention of this bizarre behavior, I'm assuming it's a bug. But if neither of these off-by-one "behaviors" are bugs, then the Character Studio manual should have a warning to artists and programmers that vertex bone assignments are off-by-one in one direction in the exporter, the other direction in the envelope sub-object user interface, but correct in the rest of the physique user interface. -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Thursday, March 04, 1999 10:15 PM To: MAXIS CTGPROG @ Maxis; Hedman, Eric; Chin, Eric; London, Charles Subject: Exporter generating normals, and ddd mesh drawing them! I've got the normal pipeline in working order! The naked deformable mesh guy is correctly lit by a lamp at night! The exporter figures the normals out, and writes them into the file with the bone relative vertices. The normals are transformed along with the vertices, but the normals are just rotated, not translated. I followed a normal all the way down the pipeline and vertified it was the same as the one dynamically generated by ddd! For blended vertices, it also blends the normals by the same weighted average, and renormalizes them. It would also be easy to change it to just chose the heaviest or first. I made the drawing code squirt the data into the low level mesh directly, instead of going through the slower interface that welds vertices. They are already welded, so it's much more efficient to stuff them and the faces right in the low level vectors. It may not be recalculating the bounding box right, just yet. And I still need to move the code around a bit so most of the setup gets done in the beginning, with a minimum amount of work each frame. This code needs to be reasonably fast so we aren't bogged down when running on older versions of DirectX on NT. Bobo is going to graft on some much more efficient triangle drawing code for DirectX 6, and it will check the version of DirectX at runtime to see which branch to take. One optimization I still need to do is for rigid skins meshes (deformable meshes whose bone count is one). Instead of transforming all the points to world coordinates every frame, it could just keep them bone relative, and move the whole mesh around rigidly with the bone transformations (like the old code used to do for rigid meshes). Another optimization that needs to be done is to fix the transformation pipeline to use pure quaternion rotations and translations, instead of matrices. I think this will be pretty straightforward, and it will make the normal transformations much more efficient, since they never have any translation (and currently I'm copying the bone matrix and zeroing out the translation, which is less direct). One bug that needs to be fixed has to do with smoothing groups. Currently the normal calculation in the exporter ignores smoothing groups, however it treats vertices in the same place but with different texture coordinates as being in different smoothing groups. That is, where there is a seam in the texture map, there will also be a seam in the normals. This is undesirable. But control over the smoothing groups is desirable. The bug is because the normal calculation is currently running on the lower level compiled vertices (after the ones with different texture coordinates have been duplicated). I should move the normal calculation upstream into the higher level uncompiled vertices that haven't been split yet, wjocj have room for tag-along data like the smoothing group id. In the process, it will be trivial to read the smoothing group information out of the Max meshes, and respect it in the normal calculation, so the artists can create seams between fabric and flesh, or hair and skin, etc. I installed the new compiler, and got the game to compile in debug, run through the neighborhood screen, then crash on some old content and asserts. I tried to compile the MaxScript plug-in, and it choked in ctglib because it was getting the vc6 stl stuff, instead of the stl from the project. I looked at the settings and it seemed to be including ../stl, so I could not figure out why it was getting the wrong stl, but I have not tried very hard to make it work yet. I'd like to get the maxscript plug-in to work in vc6, since it would be a joy to throw away the old version of the development system. -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Friday, March 05, 1999 6:06 PM To: MAXIS CTGPROG @ Maxis Subject: Deformable meshes about to be integrated; New exporter put up on "r:/pub/dist/MaxScript CMX Exporter"; Pizzas now delivered by naked deformable Fritz! I've upgraded compilers, and gotten the new MaxScript exporter plug-in to compile under VC6! I put the latest exporter maxscript and plug-in in "r:/pub/dist/MaxScript CMX Exporter/". It has the long-awaited rogue Access bug fixed! Access should exit after it sucks the database out of it, and not hang around munching cpu time any more! I've integrated the deformable mesh code, and re-exported all the meshes. After I get some food, I'm going to fix a couple more bugs (enable the selected person hilite, and enable the heads in pie menus), then check in the new content and integrated changes! I put in Chin's deformable mesh, as Fritz's normal suit. I renamed the original "Fritz.max" to "Fritz-orig.max" in SourceSafe, so the exporter would get the new deformable mesh. So the old Fritz is in Fritz-orig.max, and the new deformable, naked mesh is in Fritz.max. And now whenever you order a pizza, Fritz delivers it naked! We can go back to the old clothed Fritz if people don't have the stomach for pizza delivered in the nude, but I though it would be a fun way to demo the new deformable meshes! If you want to watch Fritz's deformable mesh bend its spine smoothly with the test object animation, you will have to make a family member who uses Fritz's suit, so you can control him. -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Friday, March 05, 1999 9:24 PM To: MAXIS CTGPROG @ Maxis Subject: Checked in deformable meshes! I've integrated and checked in the deformable meshes! To see them, order a naked pizza delivered! Currently SourceSafe is slowly and non-permanently deleting the .msh files, since the new meshes are in checked in as .skn files. I fixed the selected person highlight, but not the heads in the pie menus yet, so pie menus will be headless until I do, which I'll do as soon as possible. -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Tuesday, March 09, 1999 8:27 AM To: MAXIS CTG @ Maxis Subject: capturing mouse input in mSimsView I fixed bug #348, "When holding RMB to scroll, releasing the button over the bottom toolbar will lock scroll on". I added a GZSetCapture to the mouse down handlers, and a GZReleaseCapture to the mouse up handlers, in the EdgeDetectScroller. Please be on the lookout for any weird behavior with dragging between the Sims view and the the control panel, since the SetCapture might have some unexpected side-effects. TESTERS: We should verify that all the tools do what we want, when you drag the mouse into the control panel and release. With the SetCapture in there now, the tools should keep working normally when you drag into the control panel and release, and the control panel buttons should not highlight when the captured mouse moves over them, and the capture will cause the mouse-up event to be sent to the tool instead of the control panel, so it won't be missed, and the tool should handle the mouse up event normally. DESIGNERS: The autoscrolling still happens when you drag down into the control panel, before you even hit the bottom of the screen, and that seems to be a little confusing, so we might want to change it to lock out autoscroll when you drag a tool into the control panel. Designers should try pressing down and dragging the various architecture tools into the control panel, as well as the autoscrolling interactions, and see how it now behaves, and decide if that's the desired behavior. Also, please check to see if the behavior of the move tool rotating an object is correct: when you press down and drag to rotate an object, and move the cursor into the control panel and release the button, the object is not sold: it just rotates it in the direction of the cursor. Before, the rotating object would disappeared from its original location, and it would make the boop sound, but continued following the cursor (moving not rotating) once you moved it back in. -Don Description: When holding RMB to scroll, releasing the button over the bottom toolbar will lock scroll on. To stop scrolling, you must click the RMB over the main game screen. Update: I solved the problem (and a related problem with the other mouse button and the tools bound to it) by capturing the mouse input when you press a left or right button in the mSimsView. To fix it, I put a call to mSimsView->GZSetCapture into EdgeDetectScroller::OnMouseDownL, OnMouseDoubleL, OnMouseDownR and OnMouseDoubleR. And a call to mSimsView->GZReleaseCapture into OnMouseUpL and OnMouseUpR. The other bugs I noticed this fixed include inconsistent behavior when rotating an object with the move tool and dragging into the control panel and releasing, and an assert triggered by the wall tool of you drag a wall into the control panel and release. ==== From: Eric Bowman [SMTP:frustum@concentric.net] Sent: Wednesday, March 10, 1999 12:31 PM To: Jim Mackraz; dhopkins@maxis.com; lucb@maxis.com Subject: blending texture coordinates It's seems funny we are not sliding texture coordinates around a little to compensate for the vertex blending. Anybody thought about that problem? I might be imagining it, but it seems noticeable. ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Wednesday, March 10, 1999 2:33 PM To: 'Eric Bowman'; Jim Mackraz; dhopkins@maxis.com; lucb@maxis.com Subject: RE: blending texture coordinates Max blended vertices only have one texture coordinate. It isn't per-sub-vertex (e.i. ghost vertices that are blended in don't have texture coordinates). The same texture coordinates should remain pinned to the vertex, that moves. -Don ==== From: Eric Bowman [SMTP:frustum@concentric.net] Sent: Wednesday, March 10, 1999 2:55 PM To: Hopkins, Don; Jim Mackraz Subject: Re: blending texture coordinates >Max blended vertices only have one texture coordinate. It isn't >per-sub-vertex (e.i. ghost vertices that are blended in don't have >texture coordinates). I know. >The same texture coordinates should remain pinned to the >vertex, that moves. "Should?" I know it *does*, it's the "should" part I'm raising a question about. I don't think there is an axiom somewhere that says, "texture coordinates shall remain unchanged." If the texture coordinate doesn't move a little when the vertex is blended, the texture gets stretched, sometimes in a slightly funny way. What I am proposing is that we think about a scheme that would cause the vertices to slide around on the texture a tiny bit, as they are blended, sort of like how bones move around under the skin. It's probably too high-tech to consider at this point, just thought I'd raise it since the skin looks a little funny at blend points, in my opinion. ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Wednesday, March 10, 1999 4:01 PM To: 'Eric Bowman'; Hopkins, Don; Jim Mackraz Subject: RE: blending texture coordinates If Physique doesn't support a way for the artists to author the content, and its exporter interface doesn't support a way to get that information out of max, then it's going to be very hard to support. There is no way to associate more than one texture vertex with a blended vertex. Physique does do some kind of mesh based skin sliding, but that's one of the more esoteric high-end things it supports, like tendons, that we don't want to use in a game. There isn't even an exporter interface that lets you access any of that kind of information. -Don ==== From: Hopkins, Don [mailto:Hopkins, Don] Sent: Wednesday, March 10, 1999 9:07 PM To: MAXIS CTG @ Maxis Subject: Exporter driven censorship now in! Now the censorship regions are defined by exporting a suit of bounding boxes from Max! ARTISTS: Please get a new exporter from the usual place: R:\pub\DIST\MaxScript CMX Exporter There are two new suits, adult-censor and child-censor. The adult-censor suit is a first cut, and the child-censor suit is just a copy of it with the suit tag renamed, so it's not on the right skeleton, but will work ok for now (since children are smaller). We can adjust the sizes of the bounding boxes in Max, to tweak the area that's censored. All the points of the censor meshes are transformed to screen space, then their bounding box is taken. The censor meshes can be any shape and number of vertices (not just a box), and even span several bones like any deformable mesh, but that's not particularly useful, since we want them to have a minimum number of points. A censorship suit is tagged as "type=1", which means it's used a to compute a censorship bounding box instead of drawn as 3d meshes. We can add more types for other special effects, later. Each skin in the censorship suit is a bounding box, that is tagged with "flags=XXX" where XXX is a bit value 1 for pelvis, 2 for chest, 4 for head, 8 for left hand, 16 for right hand, 32 for left foot, and 64 for right foot. (128 is full body but that's not a box in the suit, it's done differently). These are the same bit fields that you can use in a skill's "censor=XXX" event. You can add those bit fields together to censor multiple body parts. Their bounding boxes are merged, the parts are not censored separately. I added an optional argument to Skeleton::Dress, an integer called "flagMask", defaulting to -1 (for all), that can be used to restrict the skins applied to the skeleton when you dress a suit. Each skin has a bitmask, and you OR together the bits corresponding to the skins you want, and only the skins with those flag bits are dressed. This makes it possible to have one censorship suit, and dress it with different flagMasks to get different subsets of the skins of the suit (to just censor the pelvis of a man, or the pelvis and chest of a woman, for example). I had to change the format of the skin files, so I re-exported all the suits and accessories. -Don ====