1           ~      "                                                                  #                              From John Foust

>Re:  gfx_file_selector():  good question, I'm working on a PICT reader/writer.  
>Problem is, I'd like to allow more than one possible extension, because Mac 
>files don't have them and some people might pick .PCT or .PIC.  The default 
>extension comes from the name of the BXP itself, so the user can rename the 
>BXP if they have their own standard.

>Re: Creating Objects:  Presumably, in PXPs.  (You're right in general, there 
>is a lack of examples of the direct method.)  I've only used the direct method.  
>I went blind trying to use the packet method.  (And the packet method examples 
>are goto-happy, which gave me BASIC flashbacks.)

>I set the PXP_MESH type, a name, the number of verts and faces I want, the 
>matrix, the bounding box, and call pxp_create_item().  It works.  For loading 
>points and faces, I decided to do it one at a time, to avoid the occasional lack 
>of memory from preventing it from working.  It's fast enough for import/export.  
>I tried creating the points all at once, but it didn't work, and I didn't investigate why.

>For 'matrix', I fill it with an identity: itd.item.m.matrix[0][0], [1][1], [2][2] = 1.0; 
>[3][] = 0.  In XVData, u and v are texture mapping coordinates, I'd guess they're 
>unitized 0 .. 1.0 across the face of the triangle.

>The XFData edge flags mark which sides of the triangles are visible in the editor. 
>It has nothing to do with rendering.  It's the way 3DS fakes the appearance of a 
>multi-sided polygon when in fact it's actually made up of triangles.  (Hudson 
>migrated this concept from his Atari ST program.  User thinks they edit polygons,
>but the triangles speed the rendering.)

>You can learn a lot of relevant info from the 3DS file format docs. However, they 
>are woefully inadequate in spots, particularly some of the spots you mention.  
>I wrote my own 3DS read/write libraries, so I learned plenty about the file format 
>that wasn't documented clearly.

>Literal bits and bytes are easy, but broad sweeping explanations were nowhere 
>to be found, such as the interrelationship between the object locations and the 
>matrices mentioned above.  It took weeks for me to be able to correctly create 
>3DS models that looked right in both the 3D Editor and the Keyframer.

>As for KXPs creating objects: no kidding.  I wish I could do KXP things in PXPs, 
>and PXP things in KXPs.  Did you catch my message about how my loader/savers 
>need to use APP_DATA to intercommunicate between KXPs and PXPs, in order
>to be able to both create a series of objects (PXP) as well as link them in the proper
>hierarchy (KXP)?

>And I don't see a way to create a new material definition.  With only 255 available, 
>and more than half of those typically in use, I need a str If not, what are these 
>numbers used for?
---------------------------
From: John Foust

 >> Another alternative would be for our routine to create a separate
 >> .MLI file of the materials.  That's in place already.

I guess that's a valid alternative. I was thinking about that option. You create the objects, apply mapping and give them materials whose names are found in a new library you just created. Problem is, the user can't load the library prior to creating (importing) the object as it doesn't exist. If you create the object with a bunch of materials not present in the current library, 3DS will get pretty confused. I have to try that one myself to see what would happen.


----------------------------

FROM:    Martin Enthed, 100277,1272
TO:      Jonas Ruikis, 73172,1351
DATE:    02/21/94 at  7:21

SUBJECT: FeelSub ?

I have a dialog with several fileselection's. I would like to have the same
feelfunction for them all. As they change values in the other fields as well
as in there own, I have to know wich fileselction it was that was changed.
As I see it there is no way to determin wich identifier who entered the
feelfunction. Maybe my explanation of my problem is a little fussiy so I'll
try to make a simple version of my problem:
 
.------.      .-----------------------.   .-----------------.
: File :      :                       :   : Size........    :
'------'      :      Image...         :   : Colors..........:
              :                       :   : Etc ............:
              :                       :   '-----------------'
              '-----------------------'
 
.------.      .-----------------------.   .-----------------.
: File :      :                       :   : Size........    :
'------'      :      Image...         :   : Colors..........:
              :                       :   : Etc ............:
              :                       :   '-----------------'
              '-----------------------'
 
.------.      .-----------------------.   .-----------------.
: File :      :                       :   : Size........    :
'------'      :      Image...         :   : Colors..........:
              :                       :   : Etc ............:
              :                       :   '-----------------'
              '-----------------------'
The identifiers:
#define FILE01 1
#define FILE02 2
#define FILE03 3
 
All these "fileselectors" use the same feelfunction, but should someway be
seperated so that I can update the right image and info window. The only
variable I get into the feelfunction is (Dialog *d) and there seems to be no
way to get the identifier!?
 
                              -M.E
-------------
Answered by Development Team

It would be nice if this was easier but...
The only thing you can use to idenitfy which object generated the feel 
function call is the Dialog *d the index can be derived from:
(d - dialog_root_pointer)/sizeof(Dialog)
     
 Well, because the Dialogue structure is navigated as a heirarchy, there is no index around during the do_dialogue phase.  One could be derived from the base address of the array minus the address of the current structure, divided by the size of Dialog structure.  You could also identify the unique dialog from its x,y location.  

---------------
From Martin Enthed

>How do I get the state variable saved when finished an IPAS that uses the new 
>type of user dialog. I have set the variables in there proper feel funktions but 
>when reentering the IPAS program I still get the default values in the state 
>variables, not the ones from the previous session? What have I forgotten?!

 From Development Team

There is no state variables when you use the new style dialog.  See the doc or any examples with a new style dialog.  If he wants to same them from session to session, he should make them global variables.  I'm pretty sure this will work.

QA also responded with a reference to ClientGetStateVar and ClientSetStateVar for state variables.
----------------------
From: Martin Enthed

>They are used in the ORBIT_I.KXP sample C file and in that KXP they seem to
>be saved when exiting the function ClientDoCustomDialog(). If the
>"dlgResult"==1 its saved otherwice not. The thing is that I am making a PXP
>and there are no sample C files that saves there settings. I have made sure
>that i set the state variables myself in the dialog so they have the right
>settings when leaving the PXP, but they dont get saved anyway!!

>DLGTEST,EDTEST,GAMMA and INFO none of them do or should save their settings
>to the next session! I have included a part of the sourcecode from
>ORBIT_I.PXP that does save its settings!!

>----End of ClientDoCustomDialog----raw 394-406 of ORBIT.C ---------

>/* if the user cancelled, terminate. */
>       if( !dlgResult ) {
>               return 0;
>       }
>
>       /* save the results from the dialog. */
>       state.frames      = atoi( mainedit[0].string );
>       state.keys        = atoi( mainedit[1].string );
>       state.tiltLR      = slid[0].value;
>       state.tiltFB      = slid[1].value;

>       return 1;
>}
---------------------------------------------
From: QA

If he wants to same them from session to session, he should
make them global variables.  I'm pretty sure this will work.-Jim

-----------------------
From Martin Enthed

>How do I make global variables?

--------------------
From: QA

If you are using a new style dialog the following sequence occurs.
This is for a PXP from start to finish.

ClientGetState
ClientResetState
ClientUsesCustomDialog
ClientDoCustomDialog
ClientGetState
ClientStartup
ClientUserCode
ClientTerminate


From: QA:

I was wrong about this.  There are state variables, but they are used differently 
from the old style dialog.  With the new style dialog, the values from the dialog 
have to be saved to the state struct.    I use the old style dialog(less overhead 
and easier to follow) in my PXP's and everything from the previous session is 
always saved in the dialog.  What I mean by global is global to his IPAS routine.  
Put them at the top of his routine.  I think this will work.  

-------------------------------------
FROM:    John Foust - Syndesis Corporation, 76004,1763

>1.  The 3DE.EXE dialog editor program causes a QEMM illegal instruction 
>error on my system, although I'm able to run 3DS without trouble.

QA:we don't support 3de.exe

>2.  Is there an official registry for the VERSION numbers for the static 
>DlgEntry cdialog[]?  Must these be unique amongst all the other IPAS 
>routines available on the system?  If not, what are these numbers used for?

Development Team:
No need, these are variables in your program, 3DS doesn't know about them.
These numbers are matched against the IPAS routine name, so they must 
be unique among each routine.  They should be changed whenever the state 
date's layout is changed, so you don't end up loading the new version of the 
routine, with old data that is organized incorrectly.

>3.  Are there functions or packet commands to set materials within a PXP, 
>or any type of IPAS for that matter?  I see the EXP_MATERIAL packet, which
>can return a material name from a number, or a number from a name.  But no 
>material attributes such as color, etc. can be set or retrieved.  Without a way 
>to do this, my conversion tools are limited to "geometry only" and ignore 
>materials completely.

Development Team:
Nope.
. 
>4. If there is no longer any support for Weitek coprocessors, then why is the 
>"_I" suffix still required for IPAS routines?  It eats up two of the eight filename 
>characters for no reason.

Development Team:
Because _W routines still exist, and they even work on a Weitek/Intel equipped system

>5.  In "exprtn.h", there is some indication that a PXP can be called "from another 
>module".  What does that mean?  Line 525:

Development Team:
#define PXP_MAGIC_2        0xBC51AFFE      /* Used when PXP is called from other module */

A general routine, like say an image browser, that didn't use module 
specific funtions (KXP, PXP, etc. functions) can be called from any 
module (3D Editor, 2D Shaper, Material Editor etc.).

QA:use ClientIsUniversal()

>6.  I've had several instances where I make an absolutely insignificant change 
>to a PXP, re-compile, re-link, and when I select it and click OK in the 3D Editor, 
>I get a protection fault.  Does the link order and total code size have some effect 
>on what happens when 3DS loads an IPAS?

QA:NO

hmmm. Link order shouldn't matter. I haven't had these problems and I'm 
always making insignificant changes to my code :).

-------------------------

FROM:    John Foust - Syndesis Corporation, 76004,1763 

>1.  The default memory model for Metaware is "small", aka -Ms.  And previous 
>IPAS routines didn't specify the memory model.  So the #pragma 
>Memory_model(Small) isn't really necessary, is it?  Why was it introduced?

QA:use it as documented we are exchanging data between to protected mode apps and expect things to be a certain way.Because you never know when Metaware is going to change 
the defaults on you, and it doesn't hurt to be explicit about what you want

>1.A When they say "small model", it's not the same thing as 16-bit compilers with 
>64K segment, 64K total code and data restrictions, right?  But if their segments are 
>actually 4 gig or so, what's the point of "small" at all?  How large can my code get 
>before I need to prepend "far" modifiers to all my function declarations?

QA:small is not the same as 16-bit/64k segments 4 gigs
Small in the 32-bit world is 4 gigs.  Far pointers have very little to do with size of data in 32-bit compilation.In 32-bit mode, "far" modifiers create 42 bit pointers (seg+address).   3D Studio
runs in a different segment than the IPAS routine, so it uses far pointers to communicate.  I suggest reading intel's 486 manuals for more info on protected mode memory management.

>2.  As for the #pragma Align_members(1), I believe I am free to do this in any code under >Metaware:

>#pragma Push_align_members(1);
>#include "pxp.h"
>#pragma Pop_align_members;

>to allow my code to have its own structure packing.  Do you see any problems with this?

QA:yes, see above.
--------
From Grant(member of the development team):

<Stuff about Metaware's alignment pragma>

To my experience, the alignment pragma effects more than the structure packing.  
When it comes to function arguments, it will expand datatypes to whatever the 
nearest alignment is.  For example, with a 4 byte alignment, chars will be dumped 
onto the stack as 32 bit values, and far * as 8 bit ones (instead of 6).    Watcom's 
packing directive doesn't appear to effect the stack arguments.  Since packing is 
a non-ansi feature, its not surprising that there is differences.

You may have to wrap the appropriate function calls (not the prototypes) with 
alignment directives, as the compiler may only be sensitive to the alignment 
directive when it is emitting code, not when it is type checking.

-------------------------------
From: John Foust

>I'm going to ask Metaware about this, too.  Thanks for the background. Right now, 
>I wrapped the #pragma push/pop calls around the IPAS includes within my glue code.  
>I'm try to avoid changing the structure alignment within the megabytes of the rest of 
>my conversion code.  I believe I've been careful to assume 16-bit alignment in my 
>structs, but I'd hate to change a fundamental assertion like this.  It would certainly 
>generate a nasty bug that might be very easy to catch, or it might not be easy to 
>catch.

>Maybe the best way would be to put the pragma push/pop around my #includes 
>within the glue code where I'm #including both the IPAS and Syndesis #includes...  
>I presume everywhere else could have the Syndesis structure alignment.

=========
From John Foust

>Perhaps my "insignificant link, crash" error comes from recompiling within a DOS 
>shell created by using "Dos Window" from within 3DS itself.  I was not re-starting 3DS, 
>I'd simply copy my PXP to the process directory, exit DOS, and re-load the PXP from 
>the PXP list in the 3D Editor. That's not kosher, huh?  If 3DS doesn't keep any links to 
>the PXP, and re-loads it every time, where's the problem? Does it have to do with PharLap >virtual memory that may be paging in the wrong code?

------
From QA:

<< Perhaps my "insignificant link, crash" error comes from recompiling within a 
DOS shell created by using "Dos Window" from within 3DS itself. >>

I tried this at one point, but it didn't work.  I didn't write it up as a bug because its 
totally risky.  You're going several layers on top of other things and then recompiling.  
After it didn't work once, I figured that it didn't work that one time, I just stayed away 
from it.  It would be nice if it did work, but its probably not a good idea.  As far as 
what's actually going on (memory models and going into other code segments) 
I don't know.

/Jim
===
From John Foust

>I think it works "sometimes."  I was ready to blame my crashes on the pragma for 
>structure alignment, assuming this setting affects function call setup as well as 
>structure alignment, but I'm glad to hear it could be something else, too.

>I'm going to call Metaware to find out about this structure alignment number changing 
>the way things are placed on the stack.  It doesn't make much sense to me at this time. 
>I thought this setting only affected the compiler's notions of offsets of items that were 
>declared as structures, not the setup of parameters during code generation of function 
>calls.
====
FROM:    Don Hanson

>Well now, the new dialog library and 3de.exe are very cool and will doubtless be the 
>way of the future.  There are however some annoying traits, and some things about 
>which I must ask you.

>Comments:  3de.exe makes it very tedious to build menus as you work.  Each time 
>another button/string/etc. is added, the defined numbers in the .3de file usually all 
>change.  This means you must write them down, hunt through your .c program and 
>change the define numbers to match.Note that this is NOT the case for editable 
>fields, ie. when you add another integer field to a menu the define numbers all 
>change, but the mainedit[x] simply adds the new variable to the END of the mainedit 
>list. If possible, I would recommend that the define numbers be calculated in the 
>same manner as the mainedit[x] fields to ease programming.

----------
From Development Team:

That would be a nice feature, but we are not actually doing any work on 3DE. It's a 
use at your own risk application.
--------

>Question:  In orbit.c there are four defined state variable indexes,1-4,(32-35) These 
>are defined as ST_variablename.  The State structure definition (73-79) does not 
>include the ST_ prefix.  In >the ClientSetStateVar and ClientGetStateVar the case 
>ST_ version calls the non-ST_ version.  I am unclear why this must be done.  Is it 
>to avoid confusion with the "real" define numbers called in the .3de file? 

-----------
QA:the old style dialog used state struct not the new.

From Development Team

The ST_ was just a naming convention I used to name the state variable 
indices. The client get state var function gives an index and requests a 
value. That's all thats going on there.
----------

>Would you just add a see_view call to the end of the radio buttons custom feel functions?

---------
QA: Sure.
---------

>Question/Comment:  The description of the functions is very good, but the 
>real-world use of buttons/sliders/editable fields/etc. appears lacking. Some 
>pseudo code in the manual showing all the necessary statements to support 
>that editable field would be nice/very useful.

>ie. 1)  make integer field in 3de.
>2) record label of field.
>3) look in .3de file and record define number of integer field.
>4) look in .3de file and use (void*) lines to determine which editable
>field belongs to your integer field.
>5) in .c program add define using ST_variable name.
>6) declare integer field name in State structure w/o ST_ label. 7) explain ClientSet and >ClientGet declaration proceedure.
>8) explain sprintf and init_editable lines necessary after    
>ready_dialog    command, but before do_dialog command.
>9) explain how to save results from dialog to state variable w/ atoi.

>Whew!  all done adding ONE integer field.  The really confusing part is that parts 
>8 & 9 change for different types of buttons/fields etc. I don't think this is covered 
>at all/very well in the manual.

-----------------
QA:don't use 3de.  look at dlgtst for examples.

From Development Team

All I can say is that 3DE is very difficult and awkward.  We almost killed it for that 
reason as we didn't have the engineering time to spend on it.  It is much more tedious 
to create Dialogue structures by hand, but then again, you might actually understand 
them better if you do.

The initial slider values need to be set to whatever values are in the 
state.slid is declared as a local variable in the ClientDoCustomDialog function. 
It is declared as a 2 element array of Slider structures.
-------------------

>Question:  In orbit.c please explain what is going on in lines 369-373. state.tiltLR 
>is the state structure variable.  Why must slid[0] and main_slid[0] both be updated with >state.tiltLR?  What is slid[0]? Where is it declared? (.3de file?)

----------
From Development Team

slid is declared at the beginning of the ClientDoCustomDialog function and is used as a temporary variable. 
--------

>Question: regarding using appropriate key type in kxp_get_key_by_number, I'm afraid I'm still >lost.  It was stated:
>KXPKey   avec;
>KXPVecKey *akey = (KXPVecKey *)&avec;
>So we now use akey as type KXPVecKey.  How is the data accessed under akey?  >akey.avec.e[0]?  akey.x? Is avec still used? avec.e[0]?
>Why the heck can't we go KXPVecKey akey; ???

-------------------
From Development Team

It's done that way because all keys, regardless of content, must be the same size 
for 3D Studio to deal with them.  If you notice, in the final release, I stuck place 
holders in the KXP*Key structures so that they are all the same size now, so you 
don't have to pay any attention to this pointer casting nonsense .
-------------------

>Question: When using a KXPKey to put information to a KXPVecKey to create a 
>new key, we use:
>veckey.x = key.e[0];
>veckey.y = key.e[1];  (2)
>veckey.z = key.e[2];  (3)
>Is this correct?  Our code correctly creates a keyframe every frame over a pre-existing 
>path.  If we switch lines 2 and 3, the path is rotated about the axis accordingly.  
>However, when we add a perturbation to line 2, the path is "jittered" in the Z axis!  
>When we add the perturbation to line 3, the path is "correctly" jittered in the Y axis!  
>Any suggestions here?  If I understood the above question section, I think/hope this 
>one would go away.  (I have code if needed)

---------------
From Development Team

The function kxp_get_key touches all 4 floats of the KxpKey structure. 
Even when you request something like a vector which uses only 3.
So, whatever pointer you pass to this function better have room for 4 
floats.
One sloution is:
KXPKey key
KXPVecKey *vkey = (KXPVecKey *)&key;
     
Reference the variable with vkey.
     
Another sloution would be
     
KXPVecKey *vkey = (KXPVecKey *)malloc( 4 * sizeof(float));
---------------

>Comment: I think the KEYHEAD info should be included/returned in the InterpData >structure/command.

----------------
From Development Team

I agree, that would be nice, should we get an opportunity to change the internal workings 
of 3D Studio, we will consider it.      
----------------

>Question: Do you have any working examples of app_data being used in a program?  
>There is an example of searching for an app_data header in the manual, but the 
>manual also states that each program must read the headers, and then write ALL 
>of them back to the file.  A practical working example would be invaluable.

--------------
QA:see info_i.c (PXP).

Try looking at the INFO.C that ships with the final release.  It has a set of functions for working with app_data.
------------------


>  Q: Could an editable field be used to affect the realtime viewport? 
>  Could tiltLR be replaced with a limited integer field and still update 
>  the viewport realtime?  If so, how would this be done?

----------
From Development Team

A lot of work, because you have to replicate the default edit_feel's functionality
so you could add the dialogue graphic updates. 

The problem with this is that an editable's feel function is called only in 
response to mouse clicks. Keyboard activity is handled directly
---------

>  Q: Is there any way to make sliders that show floating point numbers? 
>  ie. 1.0,1.1,1.2 ... 2.0?  (other than going 10-20 on the slider and 
>  dividing by 10 in the program)

--------
From Development Team

You have to write your own slider function.
--------

> Q: Suppose I have a large main menu with a realtime updated viewport 
> on the far right.  If I have a button that calls a small sub-menu, so 
> the viewport is still visable, can those sub-menu controls update the 
> viewport while the sub-menu is still called?  Or would I have to make 
> the sub-menu equally sized to the main menu and place an identical 
> viewport over the same spot as the main menu viewport to make it look 
> continuous?
> - Would restore_under_dialog give me problems here? 
> - If instead of using the standard dialog flow of: 
>   center_dialog(
>   save_under_dialog(
>   draw_dialog(
>   do_dialog(
>    restore_under_dialog(
>    the feel_function which calls the sub-menu used: 
>    center_dialog( DialogSub
>    draw_dialog(   DialogSub
>    do_dialog(     DialogSub
>    draw_dialog(   DialogMain
>  would I be able to simulate a continuous viewport that didn't  
>  "jump" when the user returned from the sub-menu?
>
----------
From Development Team

This would work if you made sure the sub dialog was positioned right, 
ie don't call center_dialog.But, and this is a big but, the only controls 
that would be active would be the controls of the sub dialog.
Of cource you can draw any where on the screen at all times.

Sure.   There is nothing keeping a sub-menu function from changing 
the appearence of any area on the screen.  It's just that 3DE won't be 
able to understand this relationship, so you might have to doctor its 
output a bit, and explicitly grab the "viewport" item from the main dialogue 
definition so you know its location.
-----------

> Big Question: Is it possible to make a viewport that "runs" 
> continuously while the user sits there at the main menu, not clicking
> anything?ie. could I have a viewport showing a wireframe vortex that 
> "ran" w/o any of the menu buttons being pushed?  I think this would be 
> very cool. This would be a best case scenario, our fallback is a 
> button(s) that when pushed runs n frames. (yech!)

--------
From Development Team

No, not with the functions in the dialogue library, however, you do have access 
to all the keyboard, mouse events, and gfx calls, so you could write your own 
polling loop that also updates the screen while waiting for valid events.

There is a inner loop in the dialog library that waits for input. You'd 
have to add a function call in there to update your frame. Of course I 
guess you'd need source to the library.
---------

>  Random Question: Is the render by N frames info available to an AXP?

--------
No.  
--------
      
> How would the dialog direct-call library be used to write multiple 
> menu IPAS programs? code example?

--------
From Development Team

Gee, that would take a major effort in documentation to describe how to do that.
I can't really answer that one.
--------------

From Danny Mercurio

>Could you guys tell me, have the pxp_change_item Item Flags been enabled yet?

---------------
From Product Support

I sent you mail showing how to change a mesh object to blue.

ItemData idata; // for a mesh object
pxp_get_item(1,&idata,status);
idata.item.m.color=3; // change to blue
pxp_change_item(&idata,status);
pxp_erase_item(idata.name); // must erase and redraw
pxp_draw_item(idata.name);

What do you mean by enabled?
------------------

From Danny Mercurio

>I'm not referring to changing an object's colours, etc.  That stuff works.  I'm talking 
>about the the ItemMesh flags.

>eg. 	MESH_FROZEN
>	MESH_SELECTED
>	MESH_MATTE, etc.

>I saw in the documentation that this might be fixed in a point release of 
>3D Studio. I take it that this is still the case and that it won't be available 
>in the SDK release.

---------
From QA

For ItemMesh, the flags don't work due to a bug in 3D Studio, see the note on page 62 of the doc.

For ItemCamera, there is only one flag, and it works.  I've used it.

That stuff is in 3ds.exe and can't be fixed in the SDK.

---------

> From: Gus Grubba. 

> feel_xxxx()
>
> If  I  substitute a feel_xxxx() function, I would expect to
> be able to call the  default  function for normal handling and
> then do something  with  the results. This works fine with a
> substituted feel_radio() function. In other words,I have my own
> feel_myradio() and the first line in that function  I call
> feel_radio() (the default function). When feel_radio() is
> done, I  can   select different sets of options accordingly.
>
>   Now,  if  I  try to substitute a feel_edit() function as in
> example  above,   that   doesn't  work.  I  have  a  substitution
> declared  at  the  FeelSub main_feel[] and in my feel_myedit(),
> I have a call to feel_edit() right  in   the  first line. I
> would expect to have the editing handled by the  default
> function and when returned, I could check for some validity
> the API doesn't handle  (as in date and time). I don't want
> to replace the entire  function just for that.


--------
From Development Team

Here's whats happening. Your function is being called
for mouse clicks only. So, the default feel function
returns right away, _not_ after the user stops typing.
---------

> draw_radio_group()
>
> The  function draw_radio_group() doesn't seem to do anything.
> At  least  a   better  description  of what it does would be in
> order.   In  one  of  the   routines  I  wrote, I have to update
> the state and values of several  radio buttons  according to
> changes done in different sets of  options.  After  I change
> the state, I would expect that draw_radio_group() would do  it.
> It doesn't  do  anything.  What  I  found to work  was  to
> use  the  function draw_item_number() for each button of the
> radio group.

--------
From Development Team

hmm. Hard to say whats happening here but the function
does work.
--------

> gfx_file_selector()
>
> When  using  gfx_file_selector(),  the function  description
> tells  us  to provide a list of extensions. How do I know
> the supported BXP extensions if I want to include all possible
> image types? Will BXP provided extensions be added  automatically?
> If  not,  there should  be  a  function  that  would automatically
> fill the extension structure with all possible image types.

-------
From Development Team

I beleive what will happen here is that the user would
have to type the file name knowing that the file was
supported through a BXP. Everything else is transparent
to the IPAS programmer.,
-------

> Show Path
> How  can  I show a path in the keyframer from within a KXP?
> Once a path  is   created  (keys added) it would be good if I
> could "unhide" the keys  before   terminating.

------
From Development Team

Sorry, can't do it.
-------

> Creating Objects
>
> There  are no examples of how to create an object using the
> direct  method.   In  fact,  the  whole process of creating
> objects is somewhat obscure.  For instance,  what  is the
> definition of the item "matrix" from  the  ItemMesh structure?
> How is it used?

--------
From Development Team

a matrix is a 4x3 array of floats.
--------

>  In  the  structure ItemCamera, what do "nearplane" and
> "farplane" represent in terms of units? Are they distances,
> angles, vectors, or something else?

-------
From Development Team

Distances
-------

>   In the structure XVData, what do "u" and "v" stand for?

-------
From Development Team

Just variable names. Since this structure is used for all types of
interpolation I don't think there is a good generic name.
-------

> In  the structure XFData, the edge visibility flags are well
>defined.  What isn't  defined is what edge visibility means.
> It would be a  good  idea  to further explain.

-------
From Development Team

If an edge is flagged as visible, it is drawn when a wire frame
is drawn in a viewport. It has no effect on rendering.
--------


> KXP Creating Objects
>
>  I  know  KXP's  are  meant to handle nodes of existing objects.
> But,  what  prevents a KXP from creating objects from scratch?
> If I can do that through the   menus   in  the  Keyframer,
> I  see  no  reason  I  can't   use   the pxp_create_object()
> from  a KXP.  Of course I simply  tried  that  and  it locked
> up the system. It would be a great feature if I could  just
> create a light object or a camera object based in external
> data. As it is, I have to ask the user to create those
> objects first and then apply the KPX.

--------
From Development Team

The PXP direct call functions can _not_ be used from a KXP.
--------

>
> gfx_get_path()
>
> The function gfx_get_path() returns the meshes directory
> when asked for the 3DS home directory (GFX_3DS_PATH). The
> interesting part is that there is no option to get the
> meshes directory!

-------
From Development Team

hmmm. I'l look in to this.
-------
-----------
From Doug Holt

>The flags variable in the FaceIO type is an unsigned long (32 bits), the only valid 
>values for that are 1 | 2 | 4, only 3 bits, shouldn't an unsigned char be used instead?  
>Just curious but there are more of these types of, well, wasted space, and I was 
>wondering if there was actually more data in those vars than is documented.  Basically, 
>can I use the shorter types in my code without worrying?

>typedef struct {
>unsigned int face;
>int a, b, c;
>unsigned long flags;  // these are the ones I was talking about unsigned long sm_groups;
>unsigned int material; // this is another one
>} FaceIO;

>flags only needs 3 bits of information to store the possible info: 1 | 2 | 4   to 
>set the visibility of each edge: AB BC CA but an unsigned long type carries 
>32 bits. I could use a char or an unsigned char (8 bits) and have room to spare.

>also the material is an unsigned int (16 bits) but the valid range is 0-255 (8 bits 
>with an unsigned char).  Will there be more materials available at any given time 
>in the future? (if so it would make sense to stick with an unsigned int in this case)

>anyway I wasn't trying to complain but was curious as to whether I can use the 
>shorter types and save memory and time in my routines.

----------------------------
Answered by Grant:

No, the internal code to 3DS expects the data to be at that size. If you change the type definitions to more efficient sizes, 3DS will not be able to make sense of the data.

---------------------------
Answered by Grant

Only the low order byte of the flags field, and the low order byte of the materials field, 
are actually used by 3D Studio.  The internal code to 3D Studio actually casts them 
to these values anyway.  

-----------------------------------------------------------------

FROM:    Don Hanson 
>I'm using Metaware 3.04.

>Ok, I'm going back to the previous beta version.  I noticed a number of small changes 
>in the .3de file and the include statements, but I don't think that was the problem. ie. 
>I tried similiar changes and still didn't work.  What's the difference between include 
><blah.h> and include "blah.h"?

---------------
Answered by Jim, QA

I'm pretty sure that the difference in the include statements (<blah.h> and "blah.h") is a 
standard c thing.  The way that I've always understood it, if you use the <>, these header 
files are found in the compilers include directory, set by an environment variable.  The other
 ones ("") are header files that the programmer writes and includes locally or in his/her own
 directory.  Again, he should probably check his compiler manual, but I'm pretty sure this 
is how it works.  Grant, if this isn't right, please let me know.

/Jim
--------------
From: John Foust

>Yes, actually, ANSI C compilers are not specifically required to have an actual #include file 
>for the standard #include <stdio.h> headers...  they're actually free to implement the 
>declarations in the standard packages in "some other way."
----------------------------
From: Danny 

>In the EXPRTN.H file there is a reference to EXP_SELECT_INPUT_OBJ that states that it is >available to both PXP and AXP routines.

>The command is defined as follows:

>#define EXP_SELECT_INPUT_OBJ    0x2020  /* Use specified named obj as input */

>However, when I try and use this command in my PXP, I get the following error message 
>from 3DS:

>Undefined EXP Code:2020

>It seems that it can't be used with a PXP after all.  Trouble is, this would appear to be the only >way to select an object in the editor without using EXP_PICK_OBJECT.

>Does anyone have a suggestions regarding the use of this command or any other way to 
>select the input object with user intervention?

>How does one go about scanning all the objects in the editor?

>I'm trying to perform an EXP_OBJ_EXTENTS on all mesh items in the editor and putting the 
>relevent info in a database. Unfortunately, the only way I've found to set the current input object
 >is with EXP_PICK_OBJECT.  There has to be another way to set the current input object
 >without requiring user intervention.

>PXP_GET_ITEM works great since I can just increment the index number but it doesn't 
>give me the center values for X, Y, & Z of the object.

>Is there a way to set the current input object in OBJECTIO without resorting to an >EXP_PICK_OBJECT?

-------------
From: Grant

It has been suggested by Jim LaFleur that pxp_get_item should be used to scan the 3DS object list.  You'll have to skip past the items you don't want, like cameras and lights.  If the Min/Max values are not what you expect, try adding the last three floats of the matrix to the numbers as you might be getting transformed values. 
----------

>I didn't realize that the I could use values from the matrix.  Works fine now. <g>

>Danny...

--------------
From Gus

>I'm not sure what you're trying to get but if it's the center of the object, it's easily obtained 
>by interpolating the bounding box (ItemMesh.mins[] and ItemMesh.maxs[]).

-------------
From Danny,

>Hi Gus,

>The trouble with trying to use ItemMesh.mins[] and ItemMesh.maxs[] is that they return 
>the extents of the objects itself, with the origin being the center of the object - not the world
>origin.  In other words, this returns the size of the object but not its position.  Using this 
>approach always returns 0,0,0 for the X,Y,Z centers of the object.  Unless I'm doing 
>something wrong...

>ExtInfo.min, ExtInfo.max, & ExtInfo.center return the extents and position of the object 
>relative to the world origin.  Unfortunately, you can only perform an EXP_OBJ_EXTENTS 
>on the current input object.  Without user intervention, the only way to change the input 
>object would appear to be with EXP_SELECT_INPUT_OBJ.  Problem is, this command 
>doesn't appear to work with PXPs.  

>I wish there were a direct call pxp command like PXP_GET_EXTENTS, or >PXP_GET_CENTERS. <g>
------------
From John F.

>Does he mean the center of the object, or the pivot point?

From: Gus

>I guess he means the center of the object. 
------------
From Danny

>Has anyone noticed that the min, max, & center values for the Y and Z axis components 
>of EXP_OBJ_EXTENTS (ExtInfo) are flipped?

>I've tried this with several different types of objects and the miny, maxy, and centery 
>components are always exchanged with the minz, maxz, and centerz components.

>It's not a really big deal since I can always just switch the Y and Z entries in my code 
>but I was wondering if anyone else had run into this.

--------------------------
From: Grant

<Question about the appearent flipping of the Y and Z axis in ipas>

The labels on the 3D editor display are user configurable inside the 3ds.set file.  Because of this, you can change your axis lables to anything.  Internal to 3D Studio, the axis are like this:

X axis is width
Y axis is depth
Z axis is height 

The default axis in the 3ds.set file switch the Y and the Z.    Regardless of the axis labels, 
the viewports will be constructed like this:

XZ, front/back views 
XY, top/bottom views
YZ, left/right views

----------------------
From Danny

>Is anyone getting tired of my constant questions yet? <g>  If not...  

>Does anyone have some sample code or code snippets that demonstrate how to perform 
>a pxp_create_item using pxp_put_vert and pxp_put_face?

>I can create objects in the editor using the burst mode commands but I'm finding the 
>direct call method a bit confusing.

>I've been trying to get this to work for a couple of hours now, with no success.  The best 
>I've been able to accomplish is to create an "invisible" object that crashes 3DS when I try 
>to select it!  (No, it's not hidden. <g>)

----------
From John Foust

>Did you see my reply to Gus when this section first got lively? I've made faces via the 
>function call interface, and I uploaded a few snippets. Is that what you're looking for?

Offhand, I'd recommend to explicitly initialize all fields of the structs you're passing to the functions. After you've loaded the object, you need to draw it via pxp_draw_item()  Do you do that?  My first few attempts crashed, too.

-------------------
From John Foust
I'm sure they've scrolled, I posted them in public.  I tell you, though, there's nothing special about them, I did exactly what I said: init everything, fill in what you have, then call the function. Maybe you should upload snippets of what you're doing instead, and then we can all stare at it.  Mine didn't work until I filled in a valid bounding box, for example.
-------------------
From Danny

I figured it out last night.  I was not addressing the XVData and XFData structures properly.  Anyhow, after I figured out what I was doing wrong, I managed to build my app in about 3 hours.

I now have a functional PXP Metaball Generator.  All I have left to do is tidy up the code and add some functionality to the dialog box.  Once that's done, I'll tackle the KXP version to allow dynamic intrinsic surface generation in animations.
------------------
QA submitted the following code to show some of the PXP direct call routines.

From QA
objt.c

/************************************************************************** 

OBJT.C will be a test of the pxp_ direct call routines.  Three objects will
have to already have been created in the drawing: a box, a camera, and a spot
light.  The box will have to have the same name as the object to be deleted
prompt from the dialog.

Once this is done, call the pxp, and follow the prompts.   The box will be 
deleted first, then recreated, then the camera will be deleted and recreated
with its cone visible, then the spot light will be deleted with its cone 
visible.

**You may get tired of seeing so many continue boxes with different messages
  that you're not interested.  Just take them out if you want to see what
  happens a little quicker.

  
IMPORTANT - Make sure that the object you create and the name you enter in
			the dialog - "object to delete" are the same.  Otherwise there
			will be problems.

Be sure to include "tools.h"


Author      J LaFleur
Created     2/9/94

***************************************************************************/


#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include "pxp.h"
#include "tools.h"      //my header file - include full path if not in ipas3\inc\

/* Function Prototypes From tools.h */
/* More explanation in tools.h on these functions */

void NextStep(EXPbuf *b, int uc, int s);    // moves from case to case

int StatusCheck(int s, int stp, int m);     // checks the status


/* Variable definitions */

int i;          // counter variable
int status;     // status variable for error checking
char message[256];

/* first set is for initial object and copy data is for recreating it */

static ItemData idata,copydata;         // for mesh object
static ItemData camdata,copycamdata;    // for camera dataa
static ItemData litedata,copylitedata;  // for light creation

static XFData facedata[12];      /* must be set to actual number of */
static XVData vertdata[8];       /* faces and vertices */

/************************/

/* Dialog description */

DlgEntry cdialog[]={
	0,"TITLE=\"OBJT for pxps - old style dialog\"",
	0,"TITLE=\"by J LaFleur\"",
	0,"TITLE=\"\"",
	0,"TITLE=\"Make sure that the following objects already exists in the drawing\"",
	0,"TITLE=\"\"",
	0,"TITLE=\"A BOX *MUST* EXIST AND *MUST* BE THE SAME AS THE OBJECT TO DELETE\"",
	0,"TITLE=\"ADD A CAMERA TO DELETE AND REDRAW\"",
	0,"TITLE=\"ADD A LIGHT OBJECT TO DELETE AND RE-ADD\"",
	0,"TITLE=\"\"",
	0,"TITLE=\"Make sure that you add the objects to the drawing in the above order!\"",
	2,"STRING=\"Object Name To Delete\",11,11",
	0,"TITLE=\"\"",
	0,NULL
	};

/* Version test value */

#define VERSION 0x5555
	
typedef struct {
	ulong version;
	char objname[11];
	} State;

/* the "state" struct MUST start with a "ulong" which is the version#,
	to prevent using data from old versions of this program.
	This verification is performed automatically. */

static State init_state = { VERSION,"testobj" };
static State state = { VERSION,"testobj" };

/*----------------------------------------------------------------*/

int ClientUsesInitDialog(void) {
	return(1);
	}

void ClientSetStateVar(int id, void *ptr) {
	OVL o;
	ulong *ul;
	char *s;

	ul=(ulong *)ptr;
	s=(char *)ptr;
	o.ul = *ul;
	switch(id) {
	case 2: strcpy(state.objname,s);
		}
	}

ulong ClientGetStateVar(int id) {
	OVL o;
	switch(id) {
		case 2: o.s=state.objname;
		}
	return(o.ul);
	}

int ClientVarSize(int id)
	{
	switch(id)
		{
		default:
			return(1);
		}
	}

char  *ClientGetState(int *size) {
	*size = sizeof(State);
	return((char *)&state);
	}

void ClientResetState() {   
	state = init_state; 
	}

void ClientStartup(EXPbuf *buf) {
	int j=0;

		/* gets the item count and prints to continue box */
		pxp_get_item_count(j);
			sprintf(message,"# of Items is %d",j);
				gfx_continu_line(message);

	
	NextStep(buf,0x0200,1);     // kicks things down to ClientUserCode
	}

/**************************************************************************/

void ClientUserCode(EXPbuf *buf)
	{
	switch(buf->usercode)
		{
		
		case 0x0200:
			/* select object and check name */
			gfx_continu_line("Starting the test, make sure object exists");
				pxp_get_item(1,&idata,status);    // gets the item index is hardcoded
					StatusCheck(status,0x0200,1);
						
						sprintf(message,"Object picked %s",idata.name);
						gfx_prompt(message);
			
/* next, change the color of the object in 3D Editor only 
   this demonstrates the pxp_change_item, or at least the order of istructions */

			idata.item.m.color=3;
				pxp_change_item(&idata,status);
					StatusCheck(status,0x0201,1);

						gfx_continu_line("color changed to 3");
						
/* for the color to be seen, the object has to be erased and drawn */

					pxp_erase_item(idata.name);
						pxp_draw_item(idata.name);
							gfx_continu_line("Object redrawn");


					sprintf(message,"COLOR = %d",idata.item.m.color);
					gfx_continu_line(message);

/* this copies the structs, but the name will be changed.  The object can
   be recreated using the same verts and faces */

				copydata=idata;     // copy item data for re-creation later
				strcpy(copydata.name,"copyobj"); // new object name               



				NextStep(buf,0x0210,status);    // moves down to next case
			
			break;

		case 0x0210:        
			/* fill in the verts of the object to store and recreate */
			gfx_continu_line("Now getting verts and filling vertdata[]");
				pxp_get_verts(state.objname,0,8,&vertdata,status);
					StatusCheck(status,0x0210,1);

/* next section was not needed, but you can uncomment it if you want. 
   all it does is print out the verts on the prompt line and wait so they 
   can be checked */

						/*
						for(i=0;i<=7;i++)   // prints out points after get_vert
						{
						gfx_continu_line("PROMPT IS GET VERTS @ BEGINNING");
						sprintf(message,"VERT # %d PT %f %f %f",i,vertdata[i].x,vertdata[i].y,vertdata[i].z);
						gfx_prompt(message);
						}
						*/

				NextStep(buf,0x0220,status);    // moves down to next case
			
			break;
		
			  
		case 0x0220:
			/* fill in the faces of the object for recreation later */
			gfx_continu_line("Now getting faces and filling facedata[]");
				pxp_get_faces(state.objname,0,12,&facedata,status);
					StatusCheck(status,0x0220,1);
					
/* again, this is not needed.  It prints out the face data to a continue box */                    
					
					/*
					for(i=0;i<=11;i++)
					{
					sprintf(message,"FACES %d %d %d",facedata[i].a,facedata[i].b,facedata[i].c);
					gfx_continu_line(message);
					}
					*/
				
				NextStep(buf,0x0230,status);    // moves down to next case
			
			break;

		case 0x0230:
			/* structs filled. now going to delete object */
			gfx_continu_line("Object will now be deleted");
				pxp_delete_item(state.objname,status);
					StatusCheck(status,0x0230,1);

						gfx_redraw();        //  redraws the screen
						gfx_continu_line("Object should be gone");

				NextStep(buf,0x0240,status);    // moves down to next case
			
			break;

		case 0x0240:
			/* will now recreate call to pxp_create_item */
			gfx_continu_line("Now recreating using pxp_create_item");
				pxp_create_item(&copydata,status); 
					StatusCheck(status,0x0240,1);

				NextStep(buf,0x0250,status);    // moves down to next case
			
			break;

		case 0x0250:
			/* now putting verts back into drawing */
			gfx_continu_line("Now putting verts back");
				
/* in for loop, the message commented out will print the vert info to the
   prompt line */

				for(i=0;i<=7;i++){
					pxp_put_verts(copydata.name,0,8,&vertdata,status);
						StatusCheck(status,0x0250,1);
					/* sprintf(message,"Putting vert # %d X=%f Y=%f Z=%f",i,vertdata[i].x,vertdata[i].y,vertdata[i].z);
						gfx_prompt(message); */
				}

				gfx_continu_line("Finished putting verts");

				NextStep(buf,0x0260,status);    // moves to next case
			
			break;

		case 0x0260:
			/* now putting faces back into drawing */
			gfx_continu_line("Now putting faces back");

				for(i=0;i<=11;i++){
					pxp_put_faces(copydata.name,0,12,&facedata,status);
						StatusCheck(status,0x0260,1);
				}

				gfx_continu_line("Finished putting faces back");

				NextStep(buf,0x0270,status);    // moves to next case
				
			break;

		case 0x0270:
			/* now drawing object using pxp_draw_item */
			gfx_continu_line("Redrawing object using pxp_draw_item");

			pxp_draw_item(copydata.name);   // puts object back

			gfx_continu_line("Object should be redrawn");

			StatusCheck(status,0x0270,1);

			gfx_redraw();   // redraws the whole screen

				NextStep(buf,0x0280,status);    // moves to next case

			break;

		case 0x0280:
			/* use pxp_erase_item and the redraw */

			pxp_erase_item(copydata.name);
				gfx_continu_line("object should be gone");

			pxp_draw_item(copydata.name);
				gfx_continu_line("object should now be visible again");

				NextStep(buf,0x0290,status);    // moves to next case

			break;


		case 0x0290:
			/* Camera deleted and recreated with different name */
			gfx_continu_line("Now getting camera");
			
/* notice that the index is 1 again.  This is because the first object was
   the box, but it was deleted and recreated, so the next object is the camera
   and it slides into the 1 index position.  0 is always the ambient object */

			pxp_get_item(1,&camdata,status);
				StatusCheck(status,0x0290,1);
					copycamdata=camdata;    // copy camera data
						
						/* camera copied back with its cone visible */
						strcpy(copycamdata.name,"copycam");
						copycamdata.item.c.flags=0x0001;

			gfx_continu_line("Camera will now be deleted");
				pxp_delete_item(camdata.name,status);
					StatusCheck(status,0x0291,1);

				gfx_redraw();

				gfx_continu_line("Camera will now be recreated");

				pxp_create_item(&copycamdata,status);    // camera recreated
					StatusCheck(status,0x0292,1);

				gfx_continu_line("camera will now be drawn");
					pxp_draw_item(copycamdata.name);
				
				gfx_continu_line("camera should now be redrawn");
					gfx_redraw();
				
				pxp_view_redraw(copycamdata.name);

				NextStep(buf,0x0300,status);    // moves to next case

			break;
		
		case 0x0300:
			/* delete light and recreate it */
			gfx_continu_line("Now getting light");
			
/* again, because the index of the objects in a drawing acts like a queue
   when they are created and deleted again, the index stays 1 for the light */
			
			pxp_get_item(1,&litedata,status);
				StatusCheck(status,0x0300,1);
				
				copylitedata=litedata;    // copy lite data
				strcpy(copylitedata.name,"copylite");
				
				copylitedata.item.l.flags=0x0008;   // this is the cone flag
				
			gfx_continu_line("Light will now be deleted");
				pxp_delete_item(litedata.name,status);
					StatusCheck(status,0x0301,1);

				gfx_redraw();

				gfx_continu_line("Light will now be recreated");

			pxp_create_item(&copylitedata,status);
				StatusCheck(status,0x0302,1);

			gfx_continu_line("Light will now be drawn");
				pxp_draw_item(copylitedata.name);
					gfx_continu_line("Light should now be redrawn");

				gfx_redraw();

				NextStep(buf,0x0320,status);    // moves to next case

			break;


		case 0x0320:        
			/* standard termination */
			
			gfx_continu_line("END OF OBJT PXP - TERMINATING NEXT");
			buf->opcode=buf->usercode=EXP_TERMINATE;
			buf->status=0;
			break;
		
		
		default:
			buf->opcode=buf->usercode=EXP_TERMINATE;
			buf->status=0;
			break;
		}
	}

void ClientTerminate(void) { 
	/* free any data structures, etc. */
	}

DlgEntry *ClientDialog(int n) { 
	return(&cdialog[n]); 
	}

/* Format your floating-point strings */

void ClientFormatString(int id,float value,char *string)
{
switch(id)
 {
 }
}

/* This function should return 1 if the PXP can function in any module, */
/* otherwise, it should return 0.                                       */

int ClientIsUniversal(void)
{
return(0);
}
----------------------------------
From QA
objt.h
/* 
   This header file should go in the inc\ directory
   Header file containing tools for testing. Small functions that help
   move things along.

   Created by  Jim LaFleur
*/

/*************************************************************************/
/* NextStep eliminates the if statement for looping with case statements */
/* b is usually buf, uc is the usercode-basically the next step, and s is status */

void NextStep(EXPbuf* b, int uc, int s)
{   
	b->usercode=uc;
	b->opcode=EXP_NOP;
	b->status=s;
}

/*************************************************************************/
/* InRange captures mouse clicks and checks to see if  it is in a range */
/* set by the user.  the parameters are a far pointer to GFXComm, and the */
/* x upper and lower points, and the y upper and lower points */
/* it returns 1 if in range and 0 if not. */

int InRange(GFXComm _far *g, int x_up, int x_low, int y_up, int y_low)
{
	int xclick, yclick;  /* easier to read user clicks */
	
	xclick=g->mouse_x;
	yclick=g->mouse_y;

	if((xclick<=x_up && xclick>=x_low) && (yclick<=y_up && yclick>=y_low))
		return(1);
	else
		return(0);
}


/************************************************************************/
/* this function prints out a 2 line continue box containing */
/* the status s, usually passed back from a function and stp, which is */
/* the step of the case statement where it occured. */

int StatusCheck(int s, int stp, int m)
{
	char stepmess[45];  /* message saying where status returned 0 */
	char statmess[25];  /* message saying what status was at the time */
	int r=0;            /* return flag */
	
	stepmess[0]=statmess[0]='\0';

	if(s!=1) 
		{
		r=0;
			if(m==1)
			{
			sprintf(stepmess,"ERROR - BAD STATUS RETURNED AT STEP %x",stp);
			sprintf(statmess,"STATUS RETURNED AS %d",s);
			gfx_continu_2line(stepmess,statmess);
			}
		}
	
	else if(s==1)       
		{
		r=1;
		}
	
	else
		{
		sprintf(stepmess,"ERROR - SERIOUS PROBLEM AT STEP %x",stp);
		}

return(r);

}


-----------------------------------
From QA 
obj.bat

@echo off
rem Compiles example routine "objt.pxp" using the Metaware High C/C++ 3.0
rem compiler and the Pharlap 386/Dos-Extender SDK.

rem Uses one optional command parameter "debug" which sets the
rem environment variables to create a "debugging" executible

rem The "ipasmw30.bat" file should be customized to reflect the location
rem of the executibles.
set ipaserr=
call c:\3ds\ipas3\examples\ipasmw30.bat %1
if not %ipaserr%.==. goto error

if exist %profile%  goto compile
echo Creating %profile%
echo #pragma Memory_model(Small); > %profile%
echo #pragma Align_members(1); >> %profile%

:compile
echo Compiling objt.obj
@echo on
hc386 %cflags% -Hpro=%profile% objt.c -o objt.obj
@if errorlevel 1 goto error
@echo off

rem If the main routine "pxp.obj" doesn't exist, compile it
if exist pxp.obj goto link
echo Compiling pxp.obj
@echo on
hc386 %cflags% -Hpro=%profile% c:\3ds\ipas3\examples\pxp\pxp.c -o pxp.obj
@if errorlevel 1 goto error
@echo off

:link
if exist %linkcmd% goto dolink

echo Creating %linkcmd%
echo -386 >%linkcmd%
echo -maxdata 0 >>%linkcmd%
echo -nomap >>%linkcmd%
if %xpdebug%.==1. echo -fullsym >>%linkcmd%
echo -lib %libname% >>%linkcmd%
echo -lib %metaware%\small\hc386.lib >>%linkcmd%
echo -lib %metaware%\small\hc387.lib >>%linkcmd%

:dolink
echo Linking objt.pxp
@echo on
386link objt.obj pxp.obj @%linkcmd% -exe objt_i.pxp
@if errorlevel 1 goto error
@echo off

goto end
:error
@echo off
echo Error Abort
set ipaserr=1

:end 

rem Clear out the environment settings
call c:\3ds\ipas3\examples\usetmw30.bat
echo off
---------------------------------
n(   ~  w       ~                                                                                                      B               5            L        %  '  u    1           ^  h                                                                                                
FROM:    Don Hanson

> I'm using Metaware.  What do you mean lets hope my shipping version will
> fix this?  To date, none of my stuff will "just recompile" w/ SDK3.
> Since we're working on a couple of KXPs first, we'll be getting to
> flock/etc. in a month or so.  I still haven't received my physical disks
> for the SDK release.  Remember, the e-mail zip of the final release
> wouldn't compile.  I was getting errors on a ready_dialog call, I looked
> in the /inc files and I think they changed its required parameters.  
> So anyway, I went back to the SDKbetaB for my KXP stuff, and the AXP will
> wait till we can do the major overhaul.

> Got my first unexplainable customer failure.  :)
> Whenever Peter simply host Bubbles/Flock/Vortex on an object,
> f10'ing to DOS crashes his system.  I had him also try waves and 
> rain, which of course both worked flawlessly.

> First system: 486-50, 32 meg ram, big HD, 3DS v3, Liquid Speed,
> Quarterdeck 1.02, DOS 5.  

> The Quarterdeck 1.02 is what scares me, but he said he try'd it on a
> second system, dos 6, no memory management and similiar things happened.
> What do you think is happening?
---------------------------
From Grant

There is no good way to fix the Dos shell bug for R2.  You should definitely risk recompiling
with the new libraries.  If you are really nervous about it, then use 386LIB to extract the init.obj
module from the new library, and link your application with it.  The init.obj is functionally the same as in R2, only it contains some fixes for the dos shell bug and the must open twice bug.
-----------------------
From Danny

> Does anyone know whether it's possible to use something like 'pxp_put_verts' and 
> 'pxp_put_faces' from within a KXP? 

> I was going through the documentation for KXPs and saw that there were references to 
> 'kxp_get_verts' and 'kxp_get_faces', but nothing that referred to 'putting' mesh object info.

> I'm trying to write a program that will change the shape of an object from frame to frame in an > animation.  Can this be done with a KXP or do I have to use some other approach?
---------------------
From Product Support

QA has tried to do this but has not been successful. Grant says
it *could/may* be made to work by someone.. the pxp structures aren't
currently initialized. There will be no changes supported by Autodesk
in this area.
---------------------
From Grant

I doubt seriously that you can get anywhere with modifing geometry using a KXP.  Mostly because the Keyframer would have no way of knowing that anything was changed and might even crash.  

If you want to make this work, though, take a look at the code in pxp.c that sets EXP_PXP_INFO as that's the call that sets up the PXP direct calls.   Fit that code into kxp.c, and you will be able to do PXP direct calls from your KXP.   Calls where you mearly get information seem to be okay, create and modify objects at your own risk.
---------------------
From John Foust

> I'm going to investigate this further, but I thought I'd make an early request, too...

> What sorts of program activity will cause an unreasonable number of page faults?  I don't want > my IPAS routine to throw 3DS / Pharlap into a page-swapping frenzy.  Apparently my first 
> batch of IPAs file format translators do just that.

> At this time, I have a memory allocating wrapper function (for portability) that's just calling 
> Metaware's 'malloc()' function. My translator might end up making thousands of small requests > for relatively small amounts of memory, total of about 2-3 megs for a typical translation, in 
> pieces ranging from several hundred K in size to tinier pieces of just a dozen or two bytes. And > some of those might be due to realloc()-style calls.
------------------
From Grant

Allocating more memory than is physically available will cause page faults, but you knew that.  

IPAS routines are really second programs running at the same time as 3D Studio. The problem is not unlike running AA Pro from a Dos Window.   If 3D Studio has already used up the physical memory before running your IPAS routine, then any memory allocation from your routine will result in a page fault.  

To minimize page faults while your routine is running, you may want to set your maxdata linker setting up to the expected memory usage, as this will increase the amount of heap upon loading and get all the page faults out of the way in the beginning.   You may also want to cfig386 3DS.EXE -maxdata xxxxxxx to keep 3DS from gobbling up all the free memory.  
------------------
From John Foust

> I don't think my routine was trying to allocate more memory than physical memory was 
> available. My maxdata was set to zero, like the examples. (I'd never looked into what it was 
> used for.) The beta tester's 3DS Current Status Report looks like this:

> Memory (K Bytes)

> Available:    30,972 Used:            696 Swap File:    257984 Page Faults: 1067316
------------------
From John Foust

> You must mean '-maxreal' for the 'cfig386' program, not 'maxdata' the linker option.  I thought > 'maxdata' only applied to conventional (below 640K) memory?  What does this have to do with > IPAS? Or did you mean -extlow and -exthigh, which will lead to even more questions from me.  > :-)

> I am not familiar with the constraints of running things from the DOS shell.  I've got a 16 meg 
> machine with the default settings for 'cfig386'.
--------------------
From Grant Blaha

The Pharlap switches I was really thinking about were -maxextmem, -maxvcpimem, and -maxxmsmem (Why isn't there one switch for all three?)  They control the maximum amount of physical memory that 3DS uses, by lowing these values to something less than the amount of physical memory available, you leave memory for the IPAS routine to use without needing to swap.  

My suggestion to increase the linker setting "-maxdata" to a reasonable amount is still needed.  With -maxdata set to 0, only a single page of heap memory is set aside for the IPAS routine when it is loaded.  Subsequent requests for heap memory beyond that amount cause a request to pharlap from the heap manager to increase the size of the data segment.   If there is no free physical memory, then the segment increase must be paged faulted.  If your program needs lots of memory, then there will be a lot of page faults.  It is more efficient for the program to request its memory all at once, so there will be only one "BIG" page fault at load time, as opposed to tons of tiny ones.  The best way to do this is to set "-maxdata" to the amount of memory you expect to use during the execution of the program.  

The reason why we have "-maxdata 0" in the examples is that most of them don't use a lot of memory, and we were too lazy, er, busy to figure out what real memory usage for them anyway.  It's better to have a '0' maxdata than the default of 4 gigs anyway.  
-----------------------
From John Foust

> Thank you, that helps a lot.  Are there other strategies that might help if I don't know the 
> expected memory usage at link time, but I might have an idea about it at run time?  For 
> example, perhaps a single large allocation, immediately freed, would serve the same purpose.
-----------------------
From Doug Holt

>    When you are making calls to malloc and realloc, are you also calling free?  I have found 
> with some of my routines, I'll use 16m RAM and swap 30m+, but if I call free on ALL of the 
> variables that I can after using them in each subroutine that I do not use *ANY* extra available > memory.  Meaning that a check of the current stats shows no extra memory usage!  Don't 
> know if this helps...
------------------
From John Foust

> The Softimage IPAS is about 211K.  The Wavefront IPAS is about 100K.  As I said, I don't  
> think the dynamic memory requirements are extensive...  maybe a couple megs.

> Uhm, Autodesk tech support...  Can I hear a better explanation of memory use and 
> constraints, as relating to IPAS?  When they malloc(), whose memory pool does it come from, > and what are maxreal and minreal really doing in cfig386?  Are there any words of advice 
> about memory use (ex., frequent realloc() causes fragmentation and page faults) from the 
> Yost Group?
-----------------------
From John Foust

> I called Metaware to ask about the pragma for structure element alignment.  The tech I talked > to said that changing the structure alignment had no effect on code generation for function 
> calls. He did say there are other pragmas / command-line switches for changing the way 
> arguments are placed on the stack.

> He did say that the default structure alignment was the largest element, which surprised me...  > meaning if there's a long in the struct, alignment happens on 4-byte boundaries. I didn't try to 
> confirm this in the docs.
------------------------
From John Foust

> I know I asked this once before, but I'd like a longer clarification. What is the purpose of the 
> VERSION number in the required cdialog[]? When must it be unique?  When is it checked, 
> and what might 3DS do if it doesn't like what it sees there?
-----------------------
From Grant

First, I assume you are not really talking about cdialog, but State.

The purpose of the VERSION number is to keep 3D Studio from loading old state data into a new version of a plug-in.  For example, say you have a state struct:

struct 
{
   ulong version;
   int tigers;
   int bears;
} circus = {1, 25, 15};

Everytime 3DS would check the version before setting the state in the plug-in, and if the version matched, it would go ahead and set the state.

If you later reved your state structure to:

struct 
{
   ulong version;
   int lions;
   int tigers;
   int bears;
} circus = {2, 5, 25, 15};

3DS would check the version, see that the structure had changed, and would call ClientResetState.  If it didn't, it would be trying to stuff the value for tigers into the new lions field, causing unanticipated results.   

So, change the version number whenever the state struct changes, or the meaning of that data changes in such a way that any old values would cause trouble.  

The examples seem to indicate that version numbers must be unique among all plug-ins.  This is
wrong, it must only be unique among all versions of a state struct that occur among plug-ins with the same filename.    Plug-ins need not worry about the state structures of other routines.
-----------------------
From John Foust

> Yes, I was thinking of State.  Thanks for the example.  I thought it had some other role in 
> preventing collisions between IPASes.
-----------------------
From Don Hanson
Answered by Grant 

>      Questions:
>      1) Does anyone know if the Exp_Select_Input_Object command lets the 
>      AXP write VData and FData back to the selected object?
>      ie. Can AXPs finally modify other objects in the scene? (please, 
>      please,please!)

Not that I know of.  Just do what tuber does, and read all the objects and generate a composite one.     

>      2) Anything to watch out for with Exp_Dont_Unload?
>      Can variable names between different routines clash?ie. if 2 different 
>      routines use a variable named frames, will they overwrite the same 
>      variable?    what about an instanced AXP'd object? anything different?

EXP_DONT_UNLOAD really doesn't do anything.  Plug-ins never get unloaded anyway. The variable names among different routines will not clash.  An instance of an AXP 
simply repeats whatever the original instance generates.

>      3) What's the status of 3DE, besides unsupported?
>      You mentioned that those who know such things were working on a 
>      partial(unsupported) fix - do you have a time line for this?

We are making no promises of updating 3DE.  We would like to do it, but at this time we are not sure we can.

>      4) Re: Documentation identifying and explaining how to construct a 
>      direct call dialog union data structure w/o 3DE.  Is this 
>      forthcomming? If so, when?  If not, what is the political status of 
>      3DE?

We have no plans to expand upon the plug-in documentation.

>      5) The funtions in 3d.h are not explained anywhere I can find, yet 
>      they are used extensively (exclusively) in the the demo programs to 
>      draw interactive "viewports".  Although I can guess their general 
>      function,explanations must be asked for.In particular: RelScaleRow, 
>      ComputePlaneEqn, TMPreTranslate.Also, info on which way the TMatrix 
>      spins things. ie. w/ an object facing you, "head" pointing out of the 
>      scene in the front view, will a positive Y rotation movew its "head" 
>      or "tail" down?

We do not offer any information or support for the 3d.h functions. 

>      6) We often print variable info out to a fubar.dat file 
>      /fopen/fprint/fclose.  This function does not work for us anywhere in 
>      our kxps.  Is this because of the direct call dialog stuff also in the 
>      code?

Are you using the latest versions of the toolkit?  The old versions had a problem
in this area.

>      7) Did you pass on my flic to archives?  
>      Is there someone else I should bother with/for this type of stuff? 

Yes. The proper person to send flics and Archive Consent Forms is Chris Allis. The
address is 2320 Marinship Way, Saulsalito, California 94965

      
>      8) Still having problems w/ KXPVecKey vs KXPKey, but I must admit I 
>      haven't gotten that far today, so I must beg off for the moment on 
>      this one.  (basically problems malloc'ing KXPVecKey & how you access 
>      the silly thing once its declared)  :) 

In the release version of the toolkit, filler variables were added to "pad out" all the key structures to the same size. You no longer have to worry about this "KXPKey" nonsense.

>      9) Re: the following code example.  
>      Description: The test code builds a list of interp'd nodes between
>      existing nodes, then creates nodes, to mimic the old path as precisely 
>      as possible.  We then add a sinusoidal "jitter" amount to the Y axis 
>      using KXPKey .e[0]=X, .e[1]=Y, .e[2]=Z. (lines 424-426).
>      If line 425 has the jitterY variable commented out like lines 
>      424,426,then the code simply puts the exact path read in, back out.  
>      If the code is changed to read .e[1]=Z & .e[2]=Y (425,426), then 
>      path is flipped in the Y and Z axis, as expected. 
>      
>      Now, when our jitterY variable is added to .e[1] (425), nominally 
>      the Y axis, the path is displaced in the Z axis!
>      If the jitterY variable is added to .e[2] (426), nominally the Z 
>      axis, the path is "correctly" jitter in the Y axis!
>      
>      This blows my mind!  Can you explain whats going on to me?  

It's the labels that are confusing you.  If you want to see something that makes sense, try editing the label lines in the 3DS.SET file from:

H-LABEL = Y
W-LABEL = D
D-LABEL = Z

to:

H-LABEL = Z
W-LABEL = D
D-LABEL = Y

The second set of labelings accurately reflect the values used by IPAS.  
---------------------------------
From Danny
Answered by QA

>In the EXPRTN.H file there is a reference to EXP_SELECT_INPUT_OBJ that states that it is >available to both PXP and AXP routines.

>The command is defined as follows:

>#define EXP_SELECT_INPUT_OBJ    0x2020  /* Use specified named obj 
>as input */

>However, when I try and use this command in my PXP, I get the following error message from >3DS:

>Undefined EXP Code:2020

>It seems that it can't be used with a PXP after all.  Trouble is, this would appear to be the only >way to select an object in the editor without using EXP_PICK_OBJECT.

Don't know about this.  I'd have to look into it.

>Does anyone have a suggestions regarding the use of this command or any other way to select >the input object with user intervention?

It kind of depends on what he wants to do with the object.  There are a few direct call pxp function that allow the object to be selected, either by index or by name.  Again it depends on what is going to happen to the object.  It is OK to use these with the old style packet commands, also.  They would just go into one of his case statements.

/Jim
-----------
From Danny

> Does IPAS3 have a problem with using realloc?  

> The reason I ask is that I'm trying to dynamically expand arrays and structures as 
> more triangles are generated.  When performing reallocs on structures I define 
> inside my code, there's no problem.  However, when I try and use realloc on 
> XVData and XFData structures, I get memory protection faults.

> Here's a sample of the code I'm using:

> XVData *vertdata;
> int pmax;
> int psize;
> ...


> /* allocate memory for vertex assignment table */
> pmax = 1000;
> psize = 0;
> vertdata = malloc(pmax * sizeof(XVData));
> if (vertdata == NULL){
>   sprintf(message, "Abort!  Insufficient memory for vertices.");
>    gfx_prompt(message);
>    return 0;
> }
> ...

> /* allocate more memory for the vertex assignment table */
> for (i = 0; i < vsize; i++) { 
>   ++psize;
>    if(psize > pmax){
>       /* table not big enough, expand it */
>       pmax = pmax + 100;
>       vertdata = realloc(vertdata, pmax * sizeof(XVData));
>       if (vertdata == NULL){
>          sprintf(message, "Abort!  Insufficient memory for vertices.");
>          gfx_prompt(message);
>          return 0;
>       }
> }

> Is this problem caused by the structure residing in far memory or is it something 
> else?  Should I be using farrealloc?  As always, any help would be appreciated.

> BTW, What's the status of the MESH_SELECTED question I posted?
--------------------
From Gus 
> I found a bug a while ago where using either "realloc" to grow a buffer, or by simply freeing a 
> buffer and allocating a larger one right after ( free() and malloc()) the malloc function would 
> get mangled trying to figure the heap and crash. This was pretty consistent. My work around 
> was to allocate the largest possible buffer, free it and then go on with business. This works ok > for small buffers (up to, say, 200k). If a very large buffer is required, I would talk to PharLap 
> directly and bypass the malloc() function all together. I also suggest if you do lots of small 
> mallocs (very inefficient, by the way), get your own malloc function and don't trust the one in 
> Metaware's run time library. I didn't investigate any further and I can't tell if the bug is in 
> malloc() or in the heap allocation at init time. I also haven't done any testing with the new 
> IPAS3 stuff. I simply kept my practice of malloc(big), free(big), malloc(needed) or talking 
> straight to PharLap.
--------------------
From Danny

> I get the memory protection fault when I execute a pxp_draw_item().  If I remove the realloc 
> on XVData & XFData, everthing works OK.  Executing reallocs on two of my own structures 
> doesn't cause a problem.

> BTW, I'm using the shipping version of the toolkit that was distributed by Chris Allis.
-------------------
From Grant

<realloc on XVDATA leads to protection fault>

Danny,  

I am mystified.  realloc() is just a front end to malloc(), free(), and memmove().  Maybe you should write your own realloc?

Wanna try something for me?  Set your linker maxdata to something really large, say 5 megs, and see if the problem clears up.  I strongly suspect that neither Metaware or Watcom were meant to run with a maxdata of 0, it works okay for a while, but maybe the realloc rubs the memory allocators the wrong way.

-------------------
From Danny

> OK, so you can't set the flags variable of a mesh object....

> Can you determine whether an object is selected?  When I try to access 'idata.item.m.flags', 
> all I get is zero.  Does this mean that you can't access the flags at all?

> If that's the case, how can one determine whether objects in the editor are selected or not?  I 
> would like to be able to perform an operation on selected objects only.  Something like:

> if( idata.type == 0 ){
> 	if( idata.item.m.flags == MESH_SELECTED ){
> 		do something;
> 	}else{
> 		ignore this object;
> 	}
> }
--------------------
Answered by QA.

I don't know about setting the flags.  If I have time I could try it - I mean setting the flags myself (if selected, set flag to 1).  Another work around could be getting something else in the ItemData structure and using it as a flag for selected objects.  He  could get the index of an object and save this in an array, or he could get the name and save it in an array of char*s or something.  There would be some additional overhead, but I don't think it would be that big of a deal.

/Jim
------------------------
From Danny

>> He  could get the index of an object and save this in an array, or he could get 
>> the name and save it in an array of char*s or something.

> I don't have a problem saving the item's selection status.  I could do this with an 
> array as Jim suggests.  The problem I have is determining whether an object in the 
> editor is selected or not.  

> In other words,  the user selects objects in the editor using the standard 3DS 
> menu option, then runs the IPAS routine.  The IPAS routine scans the mesh 
> objects in the editor to determine which are selected.

> Question is: how does the IPAS routine figure out if a mesh object is selected or 
> not?
-------------------------
Answered by Grant

<< Question is: how does the IPAS routine figure out if a mesh object is selected or 
not? >>

It's not possible to do it at this time.
----------------------
From Doug

>    I don't know about anyone else, but this is a major disadvantage!
> My pxp's are designed to possibly modify all of the objects in any given scene, is the only way > to duplicate the 'Select Objects by Name' dialog box?  (the one with tag/untag/all/none...)
> Has anyone already duplicated this dialog in ipas???  I plan to start on it tonight if no one > has...
----------------------
From Danny

> It's not possible to do it at this time.

I guess we'll just have to build our own version then. <g>
-----------------------
From Doug

>    Do you think if we get enough people to beat them up about the ItemMesh flags that we 
> could get a better response than 'can't do that!'?
> I'm at least as frustrated as you are.  Have you built a dialog similar to the 'Select Objects by 
> Name' dialog?  I am going to start tonight, but don't want to waste any more time than 
> necessary.  If you know of someone who might want to make a deal...
---------------------------
From Danny

>>  Do you think if we get enough people to beat them up about the ItemMesh flags that we 
>> could get a better response than 'can't do that!'?

> Well, I think it's too late to get anyone to make any significant changes to the toolkit at this 
> point.

> I'm just sorry I got involved with the beta so late in the game.  There are several things that I 
> would like to see changed, improved, added, etc.  Unfortunately, sometimes beta programs 
> are limited to "testing" only.  There isn't always any provision made for beta testers to affect 
> the feature set of a program. :-(

> I think the best we can do in the case of the MESH_SELECT, KXP object manipulation, etc. 
> problems is to place them on the wishlist for IPAS4.  (Assuming there is an IPAS4. <g>)

> On the other hand, the level of support and response time I've experienced here put many 
> other, much larger, beta programs I've been involved with to shame.
--------------------------
From Danny

>> Have you built a dialog similar to the 'Select Objects by Name' dialog?

> No.  But I think we need more than just the selection dialog.  I think we need to implement 
> three things;

> 1)  "Select Objects by Name" Dialog
> 2)  "Select Objects by Clicking On Them" PXP function
> 3)  "Select Objects by Drawing Marquee" PXP function

> The combination of these three features in a PXP would make object selection very easy.  
> They should be designed to resemble, as closely as possible, similar features already present > in 3DS so as to maintain a consistant look and feel for users.

> I would like to propose a joint mini development effort among the beta testers.  We could 
> easily come up with these features in a couple of days and post the code here for anyone to 
> use freely in their projects.

> I volunteer to create item 2 or 3.  I hope you will volunteer to create item 1 since you've 
> already mentioned your intention of doing so.  If you agree, all we need is one other person to > take item 2 or 3.  Do we have any other takers?  Any other suggestions for other features to 
> make object selection easier?
--------------------------
From Doug

>   I agree, I have had good response up here.  As for item 1, I'm into it right now...  I like the 
> other items as well, maybe others would handle vertex and face selection as well.  ( I could
> use vertex selection myself right now. )  Hope to have something up here soon, (I work full 
> time during the day (for Intel) and double time at night (on the really important stuff)).  Talk to > ya soon.
--------------------------
From Doug

> Jonas (or anyone...),

>    Thanks for the downloadables!  I have another question though:  Is there any way to invoke > an 'EXP_PICK_OBJECT' type function from the Direct Call libraries?  I didn't see anything 
> like: pxp_pick_item() but my documentation is Feb 4.  Is the only way to access this by 
> chopping my direct call dialog up and having ClientUserCode initiate an EXP_PICK_OBJECT?  > (I sure hope not...)  If anyone has any ideas, I could use 'em.

> ps Got the Select Objects by Name dialog up.  Just making sure I like the way it does 
> everything...  I will be uploading that soon.

> thanks again,
> doug 
-----------------------------
From Doug

> Grant,
>   Aha!  Well, I can relate to the importance of writing future products.  I have written a 'Select 
> Objects by Name' dialog (mimicking the standard 3DS dialog in every way except making the > text black).  By the way, is there a way to make the text black? (I might be blind you know.)  I 
> can reuse that box to actually set the flags for use with any other ipas routines (assuming that > the flags stay there after modifying the object, haven't tried that yet.)  I am considering posting > that code up here after I'm satisfied that it has enough bugs in it.(haha)
> Wish me luck and thanks again,  doug
-----------------------------

FROM:    Gus J Grubba 70673,1605

> Chris Allis sent me the new IPAS code (in theory, the shipping version) and I
> found a problem with one of my KXP's after using it. Once I use the KXP.C and
> link with the new library (Metaware 3.11), I get an: "Invalid KXP Opcode"
> message. The message reads:

> Invalid KXP opcode: 0x0000

> Which is odd to say the least (0x0000 is a valid, EXP_TERMINATE, opcode). Note
> that if I use the old stuff this doesn't happen. In this KXP I return with
> an opcode 3 times. Twice to pick two objects and the last time with an
> EXP_TERMINATE opcode. The error message occurs after the two "Pick Object"
> opcodes but before I return with the "Terminate" opcode. Tracing my own code,
> both my "Pick Object" opcodes are processed successfully. It's somewhere on the
> way back from 3D Studio (or the IPAS library) that this thing is happening.
------------------------------
From Gus:

> When creating rotational keys in the keyframer, how do I compound angles using
> the vectors you ask for? If I want to rotate an object 15 degrees in the Z
> axis, all I have to do is to set the angle to 15 and the vectors to 0,0,1. What
> formula is expected to be used when I want to compound two or three axis? I
> could not reverse engineer what 3D Studio does when I rotate the object by
> hand and go check the keys.

> An example I run over and over:

>          105 deg Y rot.         105 deg Y and 10 deg X
>    X     0                       -0.25386
>    Y     0                       -0.19479
>    Z     1                        9.94742
>    Ang 105                    107.9669

> And please, pretty please, don't give me the "sqrt(x^2+y^2+z^2)" smart answer.
> That's pretty obvious. I want to know how did you (3D Studio) derive those
> components and came up with that resulting angle.

> This is urgent. I sent this morning a KXP that needs this. I couldn't figure
> this one out but decided to send it in any way. What I am doing for now is
> creating a separate key for each axis I need rotated. Let me just say that
> several tons of high tech machinery crashed and this KXP will be used to
> recreate the incident.
----------------------------
> Ok, more stuff on the rotation world front...

> Up to now, I was actually creating a key for each frame. If I turn down the sample rate (from 
> 30 samples a second to 1 sample a second) I will be generating a rotation key for each 30 
> frames. In fact, I am generating both position keys and rotation keys for each 30 frames. The 
> whole process runs anywhere from 5,000 to 10,000 frames.

> The problem is that now, my model spins 360's between keys. This only happens in the Z axis > (parallel to the "Top" view). That view (axis) is weird to begin with as "0" degrees is at "90" 
> (east looking straight down the "Top" view) when dealing with rotation but not when dealing 
> with positioning. I have to keep subtracting 90 degrees (1/2 PI) in order for the model to keep 
> the right orientation (Yaw). I don't have to do that when plotting 3D vector coordinates which I > gather from navigation data and speed. Why the discrepancy? What causes the model to spin > around?

> The doc says the angle can't be less than 0. If negative, add 2PI. This works fine for X and Y. I > am doing the same for Z but it doesn't seem to work. If I go and edit the key by hand within the > keyframer I find, for instance, a 359.08 degrees. It should be -0.02 (if I put -0.02 by hand, the 
> model correctly rotates the -0.02 degree instead of spinning 359.08 degrees).

> Can anybody give me a clue what this is all about?
----------------------------------
> Hey, so far I'm enjoying this self conversation thang. I've probably really gone mad... At any 
> rate, still need to know how to use those compounded rotation angles. Generating a key for 
> each axis is making the thing to have hick ups every frame. I have to go back to 3DS docs 
> and see if I can figure what all those "tens, cont, bias, easeTo, and easeFrom" mean. I'm just
 > plugging the values ORBIT.C uses without any regard to knowing what they mean.

> The spinning mystery of the day: Just disregard the stuff written in the docs. Don't pay 
> attention to that "don't use negative angle" stuff. I got rid of the lines fixing up (adding 2PI if 
> angle < 0.0) and everything is working fine. In other words, I'm feeding negative radians when > the rotation is negative and the stuff is working. When I do what the docs tell me to do the 
> object spins. Go figure... Oh well, I'm still using docs I got last 02/04!!! Where is the new 
> (shipping) stuff?
------------------
From: Grant

Gus writes: "And please, pretty please, don't give me the "sqrt(x^2+y^2+z^2)" smart answer. That's pretty obvious. I want to know how did you (3D Studio) derive those components and came up with that resulting angle."

Okay, it's not very useful anyway.  

The rotational keys are quaternians discussed in Ken Shoemaker's siggraph paper of a few years back.  I'll try to dig up the reference for you.  

Alternatively, I can send you the source to the quat.h routines, but only with the provision that you ask me no questions about that code as its "production code" and is very mysterious and otherwise unsupportable.  (That's why a lot of toolkit source is not in the kit, it was just too mysterious).  
-------------
From Gus

> Please, pretty please send me whatever you got! <g> Mysterious? Are you kidding? If you 
> think that's mysterious, guess how I felt reading through the documentation and seeing no 

> clearer explanation! I understand quartenations. Well, let me rephrase that, I know about it and
> I know how they are used (I would have to dig stuff up before being able to apply any of it). But 
> as far as I can remember, you end up with a 4x4 matrix. How is that then converted back to a 
> 3 axis and derived angle is another story. That's the mysterious stuff I know very little about.
-----------------------------
From Gus. 3-18-94

 >> Are you going to upload a snippet into the libs for us all?

> Yeah, the minute I find how to rotate an object more than 180 degrees! I was able to deduce 
> the data required by the KXPRot structure. I built all three rotation matrices, compounded 
> them and converted to what I believe is a quartenian (x,y,z,w). Then I derived the 3 axis and 
> angle. I was able to match the numbers I see when I rotate an object manually and go check 
> the key info. This is only true, however, for rotations up to 180 degrees. When I have 
> something rotating more than that, it gets clipped by 180 (i.e. 195 becomes 15). As I just 
> "deduced" the equations, not really understood what I did, I still am working on that.

> By the way, after spending 30 straight hours writing my own matrix multiplication routines, 
> matrix to quartenian conversion routines and quartenian derivation routines, I found out that all > those functions are included in the IPAS libraries but they are not documented. Just take a 
> look at 3D.H and QUAT.H for the function prototypes. All kinds of goodies. Not that it matters 
> much for me as I probably wouldn't know what to do with them hadn't I gone through the 
> process of developing my own. The only thing they served was to prove my equations as the 
> results are identical.

> I developed this whole process of thought through MathCad. I guess the easiest way to "share" > that would be to upload that document as it includes not only notes, but it also includes several > equations I wouldn't know how to represent using straight ASCII. I can upload as a post script 
> file if that makes anyone's life easier... I'm open to suggestions! And I'm also open to 
> suggestions on my problems. So far I haven't heard a beep...
---------------
From Don

> Gus,
	
> Rotation hell, sounds familiar!  I asked about those wonderful equations in 3D.H - they are 
> officially not supported, but thoughtfully provided!  I've been working on getting my first 
> "viewport" up and dancing.

> Are you going to NAB?
---------------------------
From John Foust

> I've often heard that 3D programmers turn to quaternions as a way to *prevent* the sort of flip > you were seeing when your rotations cross the poles.  But it was late when I read your 
> autobiographies, :-), so I'm not sure if this applies. Maybe a Yostie will jump in here to help.
---------------------------
From Grant

<Martin wonders how to get the screen size out of IPAS>

Sorry Martin, there are no hooks into the API to determine screen size. 

If you want to have a fun time, you can dig the information out of the 3DS.SET file.  

-------------------------
Yup, AXP's are pretty durn powerful.  Now that I've been using skin.axp, I don't think I'll ever go back to using unskinned objects.  Eventually I could imagine a slew of axp's representing all of the objects in your scene, with none of them actually rendering as mesh geometry.

Get back to work!

		- G
--------------------------
From Gus

> Oook, I'm finding more surprizes as I go along. I couldn't find a KXP structure to control a 
> camera FOV or ROLL. Am I right to assume I can move a camera around but I cannot change > FOV or ROLL? How can I feed data from a motion control [real life] camera? Gary said 
> something like that a while ago but I did not compute as I wasn't tuned to this thing. Now I 
> actually started to code this KXP thinking all along that camera FOV and ROLL structures 
> where there just like any other KXP structure and to my surprize I didn't find them. Please, tell > me I'm wrong...
-------------------------
From John 

> I don't think you're wrong.  But I do think we should all definitely take a few hours to write up 
> our personal wish-lists for IPAS r4. I think it needs to be much more orthogonal and much 
> more comprehensive.  There's a lot of places it should reach so we can make those whizzy 
> add-ons we dream of.
--------------------------

FROM:    Gus J Grubba 70673,1605
SUBJECT: KXPRot Struct

> I didn't get the SIGGRAPH papers from John. When he said it was over 10 pages,
> I told him to hold on and bring it to Vegas. In fact, I got the quartenian
> deal out of my way. I got them to work by just looking what 3D Studio did to
> the axis and angles when you rotate something manually (and check the key).
> The problems I was having turned out to be more mundane (I always do that. I
> get so caught up with this major exoteric things and end up messing up with
> the simple things underneath). In other words, I got the rotation thing to
> work right. I'm now playing around with camera focal length. I will be off the
> computer for a couple of days but I should be back at it next Wednesday.
-----------------------------

FROM:    Gus J Grubba 70673,1605
SUBJECT: KXPRot Struct

> I finally got mail from Rolf today. He explained (not that I understood
> much <g>) the camera (fov, tilt, and pan) deal. I had finally gotten my
> rotation algorithms working last night (7am this morning actually) so that was
> out of my way. I will be playing around with this camera stuff today and
> tomorrow (I'm off to Vegas Sunday) and I will get back to you with what I
> find.
-----------------------
From Martin

> How can I get the hole of an object,camera or lights position in keyframer. I know how to get 
> the positionkeys for a node, but if that node is linked to another node that is moving I wont get > the right position for the linked node. It can be soo that the linked object hasn't got a key at all!

> Is there a way?

                              -M.E
-----------------------------
From Gus

> I'm just guessing here but I became pretty good in just guessing my way around lately <g>...

> I can think of two ways: First, find the object's parent (if any) and get its position. It would be 
> messy as you would have to scan the objects in search of their children (I could not find any 
> "kxp_get_parent()" function) hopping to find the object you're interested in. Then you would 
> have to adjust the position based on the difference between both objects.

> The second, great if works, would be just interpolating the object (the camera in this case) 
> position. I would think that if you interpolate an object's position, 3D Studio would return the 
> position where the object would be at a point in time (frame) taking in consideration the object > is linked to some other object. This is easy to try. Just call kxp_interpolate_key() for a camera > that doesn't have any key other than its initial key but linked to an object moving around.
-----------------------------
From Martin

> I have thought of both these ways, the first will be somewhat messy even if one has that 
> "kxp_get_parent()" function. Though it would be a great feature for IPAS4 wishlist!!

> I haven't tried "kxp_interpolate_key()" I just assumed that it does what it says in the 
> manual<bg>! But I will try it out, one never can tell what is luring inside this wonderful 3D 
> world 3D Studio provides! That is what makes it exciting<g>!!
-----------------------------
From Martin Enthed

> Sorry, "KXP_Interpolate_key" gets only the objects own position dissregarding the possibility of > being influensed by parent objects.

> Anyone else having an idea of how to get a node's actual position in 3D space? 
> "kxp_get_pivot" thogether with "kxp_get_bound_box" with world coordinates?! 
> "kxp_get_bound_box" only works with objects, and I want to get the camera and light position
> too!

> What does "kxp_get_xform" retreive? Does it solve my problem?

> Ps All these questions have to do with the next version of KEYDXF.KXP as I think you notice 
> by the questions<g>.
-------------------------
From Doug

> Don,

>   Just a thought, are you putting commas in a text string *anywhere*?
> This will cause 3de to screw up on the load.  Also the 'right arrow' does the same (but 3DS 
> doesn't support that anyway I found out!).  I'm going to put my happy helmet back on now...
----------------------------
From Don

>   Nope, I've just been using "letters",  except <g> I follow the BUT_OK naming convention.  So > the button names (all?) have an underscore in them.  This brings me to a question I've had:  
> has anyone sucessfully loaded a menu w/ 10+ things on it?  I simply accepted that you can't, 
> on the other hand I'll translate the text to german if that would help. <g>
----------------------------
From Doug

>  This may be a stupid question, but is there a way to toggle the cursor while in a direct call 
> dialog interface?  I am exiting the interface to pick an object (a Pick Object button) and when it > returns from the pick the cursor is still in the pick mode.  If anyone know how to fix this it would > be nice (not absolutly necessary but, well, you know, it would look alot better to have the arrow > back!)
----------------------------
FROM:    Don Hanson [BLACKBOX]
SUBJECT: copyright notice?

> quick one for ya: when submitting .flcs to the Autodesk Archives, should I
> put a small tastefull copyright notice on the .flc?  I noticed a section
> labelled "If you want a copyright notice to appear on the work" on the
> archive submittal form.  Does this mean Autodesk wants to do the notice,
> or is it in case your work doesn't have a notice on it at time of
> submittal?
---------------------------
FROM:    Don Hanson [BLACKBOX]

> New Random Question: Do you have any information on hardware key services?
> Stuff like who to call, who to avoid, rough prices?  We're looking ahead a
> bit here, but info searches take time so I'm starting now.
---------------------
From Don Hanson

> Just one problem today:

>  I need to know what's different in how axp.c is called on a slave node
> vs. a "master" mode.  I guess the difference would be one doesn't call
> the dialog, while the other does.  Now how does that affect which case
> statements are run in axp.c?  
>   Basically I'm trying to set up a demo/real mode, where demo mode "runs
> correctly" on a slave rendering station.  (This is the last hitch.)
---------------------
From Don Hanson

> I've probably missed the easy way here, but what I'm trying to do is
> create single buttons which turn red(on) and grey(off).
>     What I have below works w/ one exception:  the buttons always begin in
> the grey(off) color/state.  Is there an easier way, or what should I
> change here?

> under feel_xxxx function
>   drive[0]+=1;
>   if (drive[0]>1) drive[0]=0;
>   if (drive[0]==0) {
>     button_in(d,15,6);
>     button_out(d,15,6);
>   }
>   if (drive[0]==1) {
>     button_in(d,15,4);
>     button_out(d,15,4);
>   }

> I've tried initializing drive[0] to both 0 and 1, nyet.
---------------------------
FROM:    Don Hanson [BLACKBOX]

> Ok, ok, I've got slip in _one_ question:  Any news on how to draw buttons
> which you want to be _active_ (highlighted) when you first enter an ipas
> routine?  ( <-actually a big concern of ours)
---------------------------
From: Product Support

Check out Iscan.c and Dlgtst. Both of then start with some of the buutons 
in the red state.
----------------------
FROM:    Don Hanson [BLACKBOX]

> Shoot, I was just running through Iscan and Dlgtst: no go on the red
> button there. :(   Both programs are using groups of two radio buttons for
> each button which starts in the "on" position.  I'm trying to make three
> buttons, one for each axis, each controlled seperately so 0,1,2 or all 3
> can be turned on.  So I can't use a radio button setup because there'd be
> no "other" button to turn an axis off (w/o three extra off buttons).
> I'm using a feel_function for each which turns each on on and off, but
> they always start out in the "off" state.  

> Hey, I put the Vibrant driver in 256 color mode for the
> Editor/Keyframer/etc. and it doesn't come up garbled, a little slower but
> no more flipping to Material Editor and back every time on start up!
-----------------------
FROM:    Don Hanson [BLACKBOX]
SUBJECT: kxp_update_path/kxp_prep_node

> Can you tell me when kxp_update_path and kxp_prep_node should be used?
> More importantly: why? what exactly to they do and which order should they
> be used?

> Currently I use a prep_node just before I switch key_types for anything,
> ie. KT_POSITION, etc.  and use an update_path only at the end of things. 
> I'm getting some funky results (when aren't we?<g>), but I think knowing a
> little more about these two calls should help me out.
f anyone know how to fix this it w   ^  w       ^                                                                                                      B                  ,  r      Q          H          D  b   b  d        8  D  F              H  o  q    +  -         	  	  S	  	  	  	  
  
  
  
  
    (  ?  P  R      l
   l
  
  
  	      d  f  z                                i          !  #  7  H  J  p  r      
     2  4             1             --------------
From Gus (Oct 10th, 93)
>> Hi Gus,
>>
>> What is the procedure for debugging IPAS with MetaWare?

Debugging IPAS using Metaware High C/C++ and PharLap's 386LINK

----------------------------------------------------------------
=> Metaware "Program" page 135 section 10.6 or
=> PharLap "Utilities Reference Manual" page 50 Table 4-1

Compiler Option: -g
----------------------------------------------------------------
=> PharLap "Utilities Reference Manual" page 50 section 4.2

Linker Options: -fullsym
----------------------------------------------------------------
=> Read the entire PharLap 386|SRCBug Reference Manual

Invoking the debuger:

sb386 -symfile \mypath\myipas.pxp -comX -baud 9600 3ds.exe

where:

 - mypath\myipas.pxp is the full filespec of the IPAS being debugged.
 - comX is the comm port being used (com1 or com2)

When you reach your breakpoint, you have to switch the base selector
around so the symbols point to the right place. PharLap's hardwired
CS is 000Ch and DS is 0014h. Your IPAS will come up with a different
CS and DS. To switch:

xr C ?  (replace "?" with your current CS)
xr 14 ? (replace "?" with your current DS)

---
Note: Please don't take this in any way personally. Read the last sentence 3
times before proceeding <g>. I really don't mind answering questions here but,
because I _pay_ to read any message, take my own time to research and think
about the answer and then _pay_ to put an answer back, my time would be best
utilized with questions people can't figure by themselves. All these answers
are readily available in the manuals and in the SDK. If you are having problems
with things as basic as these, I would suggest reading all the documents
included in the PharLap SDK. There are several aspects of the DOS extender
that I just take for granted but it may take a while for someone new to this
environment to get used to (hardwired selectors for instance).
----------------
Answered by Product Suport
Mark,

Regarding PXP routines under IPAS3: (welcome aboard!!)

> 1) Is there a way to retrieve the location of the axis as set by the
> Modify/Axis/Place command?

I don't know about this one. I'll ask around. 

> 2) Is there any sample code using the direct call pxp_ ... functions
> other than info.c (which seems to only use the app data functions)?

Check out iscan.c. Check out the example code submitted by Jim of
QA in IPAS3Q.zip in lib 14.
 
> 3) It seems that to _change_ a mesh object using the direct call 
> mechanism, one cannot change the min and max values used by the > mesh object.  Thusly if one was to scale or rotate the objects, the 
> change function could not be used.  Is this so?  If yes, it the correct 
> way to copy, erase, delete and create a new object?

Again. See the example code in IPAS3Q.ZIP. Jim deletes cameras,
lights and objects and then recreates them.
----------------------
From Doug

   How's things?  I've got a bit of a problem:  when I use pxp_draw_item,
to draw a new/changed mesh, and Display/Geometry/Backface is active, for some strange reason all I get are the vertices!  If I am in a user view and press an arrow key it redraws correctly and stay correct.  If I have Seethrough active it behaves correctly.  If I change a view to another type (ie. from Top to Front) it redraws correctly and is also correct if I switch back to the previous view.  I'm going nuts here!  I've check and quadruple checked the XFData flags and everything else I can think of, but to no avail.  I have lost, oh, about 6 hours on this so far today and think maybe it's not me?!?  Has ANYONE seen this? HEELLPP!!

Also, has anyone had any luck making gfx_key_hit() work?  It just returns a 0 to me no matter how hard I bang away on the keyboard (my keyboard is probably not too happy with me right now...).

Does anyone know of a way to execute a EXP_PICK_OBJECT and return to a dialog even if the user cancels the pick?

enough for now, sleep, yes, beautiful sleep...
---------------------
From Danny

Hi Doug,

Sorry to hear you're having trouble with the faces in the user view.  I haven't run into this problem myself so I don't think I can help you, other than to ask whether you've got the face edge flag set to make all edges visible. 

(i.e.	facedata[i].flags = FC_ABLINE | FC_BCLINE | FC_CALINE;)

How's the selection dialog coming?  

I would have finished the pick object routine by now but my hard disk decided to take a vacation last week.  I lost about 75% of my stuff on that disk, and it took me most of the weekend just to restore and re-install everything.

Anyhow, I should be back up to speed tonight and I'll start on that routine.
------------------------
From Danny

I'm sorry to hear that you're still having these face problems Doug.  I can think of two things that may or may not be affecting your objects.  

First, are you welding the vertices?  I had a problem, when I started writing the blob code, that had to do with assigning more than one vertex to a particular point in space.  I wrote a subroutine that analyzes all the vertices and discards any that share the same space, reassigning the faces to the proper vertex.

Second, (and less likey), are you using the pxp functions in the right order?  I'm probably reaching here because I don't even know what would happen if you used them in the wrong order.  They probably just wouldn't work at all.  But just in case, here's the order I use with the blob code:

	pxp_create_item(&blobdata.name, status);

	pxp_set_verts(blobdata.name, vsize, 0, status);
	pxp_put_verts(blobdata.name, 0, vsize, &vertdata, status);

	pxp_set_faces(blobdata.name, fsize, status);
	pxp_put_faces(blobdata.name, 0, fsize, &facedata, status);

	pxp_draw_item(blobdata.name);

I don't know if these suggestions will help you.  Let me know if you get this problem figured out.

Thanks for the selection code.  I'll take a look at it as soon as I send this message.  I hope to have the pick object code finished soon and I'll send it to you.
------------------------
From Doug

   I've got the 'Select Objects by Name' attached (selbynam.zip).  It has a few extra handy functions that I use all the time.  They are in xpxp.c and xdialog.c  (for xtra pxp and xtra dialog).  The tstsel_i.pxp is ready to run and test out, and the .c files are ready to compile into your code, I'm not sure how you would like me to make this available, so I am sending it to you and Danny Mercurio for now.
-------------------------
From Doug

Danny,

>> hard drive taking a dump...

   Ouch, not something that makes you sleep well I'm sure...  I had a friend that had spent about 6 months on a MAJOR project and lost his drive, and his latest backup was more that 2 months old!  (I haven't heard much from him after that, wonder if he commited suicide! <joke>)

  Yes, my face flags are all completely valid, that's what I've checked and quadruple checked (over and over and over and over) among other things... Aaahhhh!  The problem isn't the mesh or the flags!  It seems that pxp_draw_item is not calculating backface correctly!  This doesn't only happen in the user view, it happens in all views, if it is a camera view, the object is not redrawn at all (the vertices in backface do not show up in camera views) but if I type 'C' in the camera viewport (to refresh the camera) it redraws correctly!!!!!!! I'm at a major loss to understand what's going on here, I know that the flags are used for more than just edge visibility but I there aren't any other bits set when this happens!  I will check everything that I can think of, including the ItemData struct for calling pxp_change_item, but as far as I can tell right now, it is perfectly fine as well.

  The Select Objects by Name dialog is finished.  I am attaching a zip file for you called selbynam.zip.  It has a few extra utils that I use all the time.  They are in xpxp.c and xdialog.c (include their .h components)  I haven't written a whole lot of docs but hopefully enough
to get started.  Tstsel_i.pxp is ready to run and the .c files are ready to compile, refer to testsel.c for general usage.  I hope you like it, if you have any suggestions, please feel free to yell!
-------------------
From Doug

>> no visible indication of what was tagged...

You mean in the Test box?  Yeah, I didn't care to make the test that
friendly.  It does however return to the user a list of indexes and 
the number tagged, all documented in the source...
-------------------
From John Ellis

As you mentioned the issue of NDA with regard to posting messages in Sect 14, I wonder if you could expand on this a little. How does non disclosure work with regard to this section of the forum? I have a project that I would like to develop and I wonder to what extent I can be open with regard to my intentions. My interest is using IPAS 3 is as an interface for DOS functions and I think I understand that I will need to build my own menu. Considering that I'm starting at square one maybe you could direct me or give me some insight into the best approach. If these questions should be directed elsewhere please advise.
-------------------
From John,

<< As you mentioned the issue of NDA with regard to posting messages in Sect 14, I wonder if you could expand on this a little. How does non disclosure work with regard to this section of the forum? I have a project that I would like to develop and I wonder to what extent I can be open with regard to my intentions. >>

The threads that I want to share with the world (section #14) will deal
with "IPAS3 - the tool". If you discuss details of a project on #17,
I will edit out those references. To make it very easy, I would recommend  that you e-mail me project specifics and limit discussion on the net to programming IPAS3 details. 

Can you(all of you) live with this?

jonas  

------------------
From John E.

>> To make it very easy, I would recommend that you e-mail me project specifics and limit discussion on the net to programming IPAS3 details. <<

This seems like it will put a lot of burden on you, but I can certainly live with it. On the other hand I would be happy to sign a general NDA agreement if ADESK thought that this was feasible so that we could all exchange freely. We all have an NDA with Autodesk, but it does not include exchange between developers. Whatever the consensus is I'll be committed to abide by.
----------------------------------
John,

<< section #17 >> 

I expect ~300 participants[lurkers] in this section by year end. 

jonas[adesk]
----------------------------------
Jonas,

>> I expect ~300 participants[lurkers} in this section by years end. <<

Which takes me back to the NDA and the burden it will put on you! Sheesh!

I guess we'll just see how it goes, if I can help please just let me know. I suspect like others I will have a lot of questions.
-----------------------------------
From Product Support

John,

<<  I think I understand that I will need to build my own menu. >>

The best place to start would be with \examples\pxp\dlgtst and
\examples\pcp\iscan. Yost/Rolf/Gus/Doug/Don/others... use the
3de.exe to help them build dialogs. See Don's comments in 
the IPAS3Q downloads for insights to their frustrations in using
3de. Don is trying to get a dialog up with 30 entries through 3de.
Maybe he'll share his experience with us? I had one individual call
me and state that he was able to get 35 nested dialogs to work
before it crashed for him. (a wee bit deep...) 

Good luck.

jonas[adesk]
----------------------------------
From John E.

First thing I did was download IPAS3Q per your suggestion.

Thanks, it makes for some intresting reading. (Only because I'm really interested in seeing what I can do with IPAS 3. <g> )
-----------------------------------
Answered by Tina.

<<  How do we handle copy right and archive consent forms? >>

We recently added that line into the Archive agreement because many times companies sent us files - and we had no idea if the artist himself or if the company he works for deserved the credits - this is when they appear in print (like a magazine).  We always provide credits with images when we send them to magazines and it simply helps us know how those credits should read.  Copyright notices are something entirely different from credits and frankly - I don't know much about copyright laws.  If an artist really wants to protect his work - I highly recommened putting their name and a copyright notice directly on the image (or flic) itself = but in many cases this can spoil the look of the image.

I hope this helps somewhat... at least answers the question as to why that line appears on our Archive Consent and Release forms now.
--------- 
From John Foust

Uhm, have you forgotten my bug report that I can't even get 3DE.EXE to run on my system?  It generates a QEMM error. Can I do anything on this end to help discover the problem?
---------
John,

<< 3de and QEMM.. >>

I wish I knew where to start... What version of QEMM are you running?

jonas[adesk]
----------
From John Foust

New as of December or January, meaning 7.01?
----------
From Gus

I'm using QEMM 7.03 and have no problems running 3DE. These are the two lines
of my Config.sys that matters:

DEVICE=C:\QEMM7\QEMM386.SYS EMB=73728 X=B000-B0FF X=F000-FFFF FRAME=NONE RAM FEMS R:1
DEVICE=C:\QEMM7\LOADHI.SYS C:\QEMM7\QDPMI.SYS SWAPFILE=DPMI.SWP SWAPSIZE=10240
----------
From John Ellis

This is somewhat of an aside Gus but I've been checking with the Phar Lap and Programmers shop and what with the notes I've been able to ascertain on about IPAS development, what I need is the Metaware Hi C/C++ and the 386 DOS extender from Phar Lap. Phar Lap sells a kit called the 32 Bit Power Pack and the Programmers Shop sell the aforementioned. Both are roughly around $995. Does this sound right? Is there anything else I might need?

FYI, I tracked down the COPY thing with DOS 6.2 Even Microsoft tech support didn't know about this. But there is a set command you can implement which will overide the Y/N/A when doing a copy. Can you believe it?!

Thanks, any pertinent info (and come to think of it irrelevant comments) will be appreciated. I think I'm going to bite hard and jump into this, pun intended. <g>

-JE

----------
From John Foust

Yes, the $1000 package is what you'll need.
----------
From Ed
WATCOM is selling the V9.5 (the latest), compiler for $199 until 8:00 p.m. today, with the purchase of VXREXX at $99: (800) 265 4555.

VXREXX is an OS/2 visual development tool for REXX. The C compiler alone can be found at $300-350 (according to WATCOM). The WATCOM compiler v 9.5 is supported, and was tested, for IPAS 3 development (reference pg 5).

If you don't need VXREXX, then give it to me <g>.
------------
Friends and Neighbors,

   I have just uploaded a file: SELBYNAM.zip to the Software Dev. Kits
Library.  It is the source code for a Select Objects by Name dialog in
your r3 IPAS routines.  Please check it out and if there are any
comments/suggestions please direct them to me.  Hope you find it useful.

Thanks,
doug 
 --------------
From Martin Enthed

There seams to be a bug in the doc on page 90 in the IPAS3 doc. When trying to set the "Strings" display- and total-length as described one get the opposite result. They seem to have swapped places!

                              -M.E
----------------
Martin,

<< IPAS3 doc error. >>

Thanks. I'll save your comment in the next IPASQ.zip and I have 
forwarded your comment to out tech publication department as 
well as quality assurance. 

jonas[adesk]
-----------------
Gary,

Have an idea how developers are going to port their IPAS over to the SGI so that it will work in the Slave mode?

-JE
----------------
We're currently researching the issue, John.

		- G
----------------
Mark,

<< Does anyone have a C function to increment an object name in the same way that 3ds does when it creates new objects?  Are you willing to share it? >>

Do you mean as an IPAS3 module? Do you currently have the IPAS3 
Software Developer Kit?  Have you looked at Selbyn.zip in the "software
dev. kits" section of the library?  Doug Holt uploaded the IPAS3 source
code as a shareware routine which creates a 3DS Select Object by
Name dialog. You could look at this source and get ideas.

jonas[adesk]
-----------------
Mark, 

   Actually, I do have a pxp_get_next_name() function that returns the next valid incremented name based on the one passed in.  It requires a list of mesh names from the scene, (to make things faster), I have written a function called pxp_get_object_names() that returns the list of all mesh names in the scene.  I have some tidying up to do, (I have alot of utils that might not be useful to anyone else) but I will upload probably this weekend.  (send me a reply to remind me!)
Wait, is the pxp_get_next_name function in the selbyn.zip? I forgot...
Oh, well, I'll check it after 'work'.

later,
doug
 --------------------
Doug,

I downloaded your routines.  They are just what I need.  I will attempt to incorporate them into my code later today.  Thank you sir.

Regarding xpxp.c 
>> This program contains extra function that should have come with IPAS R3. <<
I agree!

BTW, Do you happen to know of a way for a pxp to detect the GUI display resolution?  I've got a dialog box which is too large for 640x480 and I would rather warn the user that 800x600 is required rather than crash 3ds!

Thanks again for your code.

Mark :)
----------------
Mark,

  What I would do, (since there is no direct way), is to create a dummy dialog (say a box 10x10), call center_dialog and get the sx and sy coordinates of the box, add 5x and 5y (half of the box's size) and double the new sx and sy!  That is the current screens resolution.  I was going to write a function that will do just that, but hey, if your up to it, I'm interested!  It would actually be nicer to create a box of 0x0 and call center_dialog but since I haven't tested it I don't know if a box of no width/height would crash or not...

Hope that helps!
doug 
----------------
Has anyone had a chance to explore mapping coordinates in IPAS3?

I'd like to be able to create a mesh in an AXP or a PXP and have the mesh retain the mapping coordinates of a texture mapped material from the source or stand-in object.

So far, I've only been able to get the material number transferred to the new mesh.  Is there something I've overlooked in the manual?

Any suggestions or code samples would be appreciated.

Thanks,

Danny...
-------------------
Danny, 

  Do you mean that the u and v coordinates of the XVData struct do not work?  I was just going to start looking into texture mapping myself, but alas, so much code, so little time...  If you hear anything I would be obliged!

Later,
doug 
--------------------
Hi Doug,

Actually,  I'm trying to use mapping coords with an AXP.

I haven't figured out how to do that.  I'm probably just being dense and overlooking the obvious.  I start to get that way after having spent too much time staring at the same lines of code.

If I hear anything thoug, I'll let you know.

See ya,

Danny...
-------------------
I have written a SXP that change depending on wich framenumber. This routine work fine when used on one object or several objects with the same settings and material. But when having it in several materials and objects with different settings it seams to use just one of the settings? I know that 3DS look to see if an SXP already is loaded with the same settings. If there is, it uses the already loaded one! When I make 2 copies of my SXP with diifernt names and use them in differnt materials with differnt settings they work OK!!

It seams like 3DS doesn't notice that it should load different versions of the SXP because of it's different settings. How can I check if this is the case? I have all settings in the "state"-variable soo it should see the difference!?

                              -M.E

Ps I'm using WATCOM C 9.5 Ds
-------------
Martin,

   Have you changed the VERSION number in your state variable?  Don't know if that's it, but I thought I'd take a stab.

Interested to know,
doug
---------
<< did you see grant's earlier explanation of version in IPAS3Q.zip >>

No I hadn't but this just clarify that my workaround works with multiple
names of the same SXP, to get them to use different sets of statevariables.
But how do I get 3DS to see that I'm using the same IPAS with different
statevariables? Shouldn't it do that by itself?

3DS r4 wishlist is to be able to se wich texturemapfiles and sxp is beeing
 loaded and how many times that they are loaded, an SXP or map used in
several materials with the same settings should only be loaded once! Could
be implemented as a button in the render dialog!

                              -M.E
-------------------
Hi Jonas,

Well, I've rewritten this e-mail a couple of times, each a little further
along than the last, but now it is time to call for help.

My problems arise in a kxp_interpolate_key call on a KT_ROTATE key type,
but I'd still like any info on 'prep_node and 'update_paths.  :)

English version:  I'm not doing the interp call on the rotate keys
correctly because the object rotates around like a mad dog. 
(see 1-jitter.prj) I moved each of the four boxes on frame 30, and rotated
each box in the Left viewport a little on frame 15.  
The left two boxes (Left viewport) rotate 90+ degrees each frame from 0 -
15.  The third box from the left I manually added rotation keys to in
Studio.  The large difference between the two makes me wonder if I
understand what it is I'm supposed to be doing.

techno "where the problem is" version:  
"difficult" kxp_interpolate_key - line 938
for loop where we build interpolated list of keys - lines 936 to 953
2nd loop where we put the interp'd list one by one - lines 956 to 966

Note: if you compile/run the program just choose OK on the main menu, then
pick on an object.  The code behind the menu is very, very rough, as in
"ok I understand this part, now how do we hook the next part"  <g>.

Don
------------
Hi Jonas,

Imagine my surprise when I find no easeFrom number in the Key Info screen
after doing some KXPVecKey and KXPRotKey manipulations!

I've spent the past week+ getting the multiple menu control system
working, so I was pretty surprised to find I was messing up something so
basic. <g>

What happens is that after creating some vec and rot keys, no number
appears in the slider for easeFrom in the Key Info panel.  Also, no Cont.
number shows up.  I believe this is where my random rotation wierdness is
comming from.  Have you heard this one before?  Any suggestions?

Don
--------------
From Don

Sirs,

Could anyone explain to me the _when_ and _why_ you should use
kxp_prep_node and kxp_update_paths?

I've found that unless I use a prep_node before I switch key types the viewports in Studio are NOT updated, but once I go into track info for the object and come back out (in Studio), then the viewports show the correct display.

I'm picking up unwanted rotation of the picked objects and the above oddity (and others) makes me realize I need to know a bit more about what prep_node specifically does, and when I ought to be using it.  :)

Don 
---------------- 

Mark Meier asks: 

"BTW, Do you happen to know of a way for a pxp to detect the GUI display resolution?  I've got a dialog box which is too large for 640x480 and I would rather warn the user that 800x600 is required rather than crash 3ds!"

I was looking at the GFXInfo structure, which manifests itself in exptrn.h as the global "extern GFXInfo *GI" and it has the fields "sc_width" and "sc_height" which contain the screen size.  The center_dialog function in fact uses these fields to computer the center of the screen.  

I may have said something different last month.  I apologize, its been a rough year.

Grant Blaha - Autodesk Multimedia
-------------
From Eric Lundquist

I am using 3D Studio Release 3 IPAS 3 Toolkit to create a KXP process that imports camera movements from a motion controlled camera.  I have the following questions:

On page 36 of the toolkit manual it says that Focal Length = 2400/FOV.  This is only true for a small range of lenses.   If you use the Calculate Button in the 3D Studio Camera Definition box you get different answers than 2400/FOV.  Try an  FOV of 115 or 2.   Also, what is the FOV?  The 2400 suggests that the FOV is related to the 42mm diagonal of  35mm film.  If the image rendered in 3D Studio can be any width, height or aspect ratio how does one figure out the FOV?  This question is really the same question as asking: how do you align a photo-montage in 3D Studio knowing the camera lens you used to take the background picture,  the size film you used, and where  and how you stood when you took the picture?

If you can, how do you add or remove frames from an animation using a KXP routine.  Also how can you set up a hold button for 3D Studio Hold Buffer in an IPAS  dialog box?   On a more general level, is there any method to access  the 3D Studio Icon Panels and/or  Menus during an IPAS routine?

I do not have to do this for my current project, but I am curious if you can directly combine IPAS processes such as  (PXP and SXP) or (PXP and KXP) for example.  Except getting to SXP routines through the Material Dialog box called by another IPAS routine, it seems that you cannot.

Thanks for you help.  I am an experienced ADS programmer but a neophyte when it comes to IPAS programming, so any help will be appreciated.
-----------
>>camera FOV...

Hello Eric,

Whenever someone hollers "camera", "FOV", or "focal length" I go into auto mode and send them a thread I started/collected on 3DS camera stuff, whether they ask for it or not!  So check your email. If it won't help, it'll at least keep you busy reading... <g>

                                          J K J
-------------
Eric,

<< many good questions.. >> 

I'll add them to the list of open questions that have been posted
on IPAS3. Regarding cameras.... in the utility called cine.exe
in section #9, there is a small interesting self discussion by
John Walker when he is trying to implement a hyperchem file
structure to 3DS2 converter. In it it shares some code donated
by Dan Silva, one of the Yost programmers, and he considers it
invaluable. It may not have relevance but as JKJ says, interesting
reading.

jonas[adesk]
  ------------------
Hi Jonas,

Do you, or anyone else, know if it's possible to access the objects in the 3D Editor prior to render time in an AXP?

In order to build an object heirarchy, the user needs to manipulate an object list from within the custom dialog.  I need to go out and get a list of objects in the scene BEFORE rendering so I can present a valid list of objects to the user.  AXPs only seem to have access to the objects in a scene at render time.

I'm essentially trying to build a routine with the modeler access of a PXP and the renderer access of an AXP.  If I can't access the modeler info from within an AXP, is it possible to have a PXP assign an AXP with preset variables to an object?  Perhaps through the 3ds file?

Thanks,

Danny...
-------------------
Danny,

Since Gary's programming crew was in town they were nice enough
to review and answer the following.

<<   I posted a message about a week ago asking for help with mapping coordinates in an AXP.  Here it is again in a nutshell;  is it possible to assign a material requiring material mapping to an object generated inside an AXP? >>

<< I know I can ask the user to map the material to the stand-in object(s) but how do I translate this to a generated object that might be very different in shape to the stand-ins?  Are there any short cuts to this? >>

Basically, if you're going to apply a material that requires mapping
coordinates to an AXP object, you must generate the UV coordinates
procedurally to the objects you've generated.  The user would apply the
material itself to the stand-in, but the programmer must give the generated objects uv's.
-----------
Danny,

<< AXP's and object list... >>

(yes.. Gary's guys say.. )

Yes, you can access the object list in an AXP -- It's something that kind of "fell out" of our design naturally.  All you need to do is make the
EXP_PXP_INFO call in your AXP call just like the PXPs do in PXP.C and set up the pointers to the PXP direct-call entrypoint.  You can then use PXP direct-call code to get a list of all objects in the Editor.
-------------
From Jonas

   I tried compiling with metaware 3.04 and linking with Pharlap TNT 
   and the -FULLSYM switch...
      
    When sb386 -SYMFILE dlgtst_i.pxp -SWAPMON 3ds.exe
                 g
                 choose DLGTST <OK>
                 r eip eip+1
                 xr C 0f
                 xr 14 17
                 bp do_user_interaction 
                 g
     
     sb386 seems to ignore any breakpoints that I set.
     When sb386 -SYMFILE dlgtst_i.pxp -SWAPMON 3ds.exe 

                 g
                 choose DLGTST <OK>
                 r eip eip+1
                 xr C 0f
                 xr 14 17
                 n
      
      gives me a Memory protection fault at 0008:000000AF 
      Processor error code = 00000000
      
 The above procedure is per the README file. :-(

The solution:
To properly use the xr command for TNT's sb386 and IPAS3. First notice the segment that for the INT 3 instruction that breaks into the debugger when the IPAS routine is loaded, say it is D7. Then you use xr to change 0c and 0f to D7:

xr 0c D7
xr 0f D7

XR makes the change when the command is executed, so if you make a mistake, (like xr 0c 17), and want to correct it you must use the new value, (to correct: xr 17 D7).

The warm-fuzzy feed-back to look for is symbols appearing in the disassembly from the current instructions. Execute:

u cs:eip

and look for some meaningful names. If you don't see any, you probably got it wrong.

This dual monitor system (one mono card required) works real nice. FWIW

jonas[adesk]
------------------------
Jonas,

  How's things?  Got a quick (maybe quick) question.  I have found that with certain meshes my pxp is paging somewhat.  With all the calculations that I have made, my code could only be generating about 6mb of usage at any given time and free's up the memory as soon as it is no longer necessary.  We have absolutely proven that fact!  Does 3DS allow calls to free to actually free up the memory at the time of the call or does it only free up after the ipas 'terminates'?  On objects that do not page, there is absolutely no memory use according to Current Status in 3DS, but if it pages at all, it's a lost cause.  Any one know of any Metaware compiler/ PharLap linker settings that could affect this?  Any thing else that I could have missed?  

Thanks so much for your time,
doug
-----------------------------
Dave,

Glad to see a new IPAS3 programmer. Welcome. 

<<   What KXPKey structure do I pass to kxp_create_key to set the FOV and/or ROLL of a camera? >>

I see your point. There are no structures listed in the docs under
Direct Call KXP Structures that would imply supporting roll or FOV. 
It looks like roll & fov is supported in the PXP_create_item. I'll forward 
this to all involved to see what's what.

<< when I use kxp_create_key, can I overwrite existing keys, or do they need to be detected and deleted before kxp_create_key is called? >>

If you're in position, try it both ways and post your results. 

<< KXPScalarKey structure in the IPAS header file does not agree with the prorotype listed on page 58 of the IPAS 3 Toolkit reference. >>

I'll pass this on to the Tech Pubs department. 

<< When I set the X, Y, Z values of an object in a KXP IPAS process, the Y and Z values end up being reversed on the screen.  Is this just a labeling problem in my 3ds.set file?  Why don't X, Y, Z values inside of an IPAS agree with what I see in the Keyframer? >>

Have you read the IPAS3Q.zip file in the "software dev kits" section
of the libs? This was covered in there twice.

<< Is this the correct forum for this message? >>

Nope. Take this to the "Software Dev Kits" section of this forum.

You'll find that because of IPAS3's infancy, I don't have all of the
answers. I will try to get your answers and I hope that other IPAS3 
programmers chime in when they can. Keep posting your successes 
and questions. 

jonas[adesk]
--------------------------
<< Jonas should have a doc somewhere the discusses the proper relationships to everything.  The basic solution should resolve the real world camera placement into an position, target, rotation about the position/target vector (another wierd thing to worry about) and the FOV. You then get the focal length from there.  >>

Here's the doc that Grant is refering to.

jonas[adesk]
--------------------------------------------------------------------------------------------

                           C I N E C H E M
    Molecular Rendering and Animation with HyperChem and 3D Studio

                             --- with ---

                           S T I N G R A Y
                          Stingy Ray Tracer

                          Distribution Notes
                  Release 0.3  --  13th October 1992
                            John Walker


............(many paragraphs deleted regarding Stingray and other non camera
              related topics. See original readme.doc in cine.exe found in section #9
              of the ASOFT forum.)......jonas[adesk]


Still  more  fixes  to  viewpoints  and  keyframer information for 3DS
format, both to logic in  CINECHEM  and  to  correct  bugs  in  3DSLIB
itself.   CINECHEM  was  calculating  the  relationship  between "lens
length" and camera field of view (needed because 3D Studio can't  make
up  its  mind  which  format it prefers; lens length is used in the 3D
Editor, but field of view is specified in the Keyframer) by performing
the   correct   geometrical  calculation  as  described  in  the  book
"RenderMan Companion".  Unfortunately, 3D Studio uses a totally  bogus
linear  interpolation  of this highly nonlinear (tangent) function, so
the accurate numbers I was generating didn't agree with those used  in
3DS.  I converted my code to call the  new  3DSLIB  routine  FOVToLens
(note  that  the function is *not* called FOVToLens_3ds, as documented
to be on page 28 of the 3DSLIB manual), which reproduces the erroneous
values used in 3D Studio.

The  very  confusion in 3DS about whether it's lens length or field of
view tripped up the camera motion specification function in the 3DSLIB
module  CAMM_3DS.C.  When it was creating the initial (frame 0) motion
key for the camera, it retrieved the lens  length  from  the  camera's
record  for  the 3D Editor and jammed it into a cell that was supposed
to be a field of view.  You have to add the code:

    /* ***FIX***  Translate camera "lens length" into field of view as
                  used in the keyframer. */
   {    double dstfov;
        LensToFOV(*stfov, &dstfov);
        *stfov = dstfov;
   }

right before the return from the  internal  function  InitCamState  to
correct  this.   Note that LensToFOV() returns its result in a double,
unlike FOVToLens() which expects  a  pointer  to  a  float.   Is  this
obscure or what?

The dummy objects  I  created  to  link  the  atoms  to  their  parent
molecules weren't being treated as dummy objects.  Turns out DUMMYNAME
in  3DS.H  was defined as "$$DUMMY" instead of "$$$DUMMY" as 3D Studio
expects.   This  is  also documented incorrectly on pages 36 and 43 of
the 3DSLIB manual in the descriptions of the  header  definitions  and
the  KF_MESH  structure, but is correctly given on page 75 of the same
manual in the documentation of the NODE_HDR chunk.

........ deleted......


As   soon  as  I  implemented  the  object  hierarchy  for  molecules,
everything went totally weird, and it took me the  better  part  of  a
week  to chase down the 3DSLIB bug that was causing it.  The author of
3DSLIB was tripped up by  some  additional  bizarre  behaviour  in  3D
Studio.   When  you're  creating  the keyframer data for a mesh object
with ObjectMotion_3ds(), an initial rotation key must be generated for
frame  0  (regardless of whether you've specified any rotation keys of
your own).  The code that created this key, in OBJM_3DS.C, was:

    strot.angle = PI * 0.5;
    strot.x = 1.0;
    strot.y = 0.0;
    strot.z = 0.0;

Now that looks pretty weird to start with, 'cause on page  77  of  the
3DSLIB   manual,  the  angle  field  of  the  ROT_TRACK_TAG  chunk  is
documented as being "Rotation angle in degrees".  Okay, so  I  changed
the  PI * 0.5 to 90.  Things got *much* worse.  After a lengthy period
of cybernetic psychoanalysis, I finally established that  the  correct
code to set the angle should be the following:

    strot.angle = (strcmp(obj->name, DUMMYNAME) == 0) ?  0 : (PI / 2);

Why  is the initial rotation of objects imported from the 3D Editor 90
degrees  (in  radians,  of course), but zero for dummy objects?  Beats
the shit out of me, but go and make some of your own in 3D Studio  and
look  at  the  Key  data  it generates for them.  That's how I finally
figured it out.

Note also that the documentation of the KF_ROT structure on page 43 of
the  3DSLIB  manual  (which  is  what we're talking about initialising
above) doesn't mention whether the rotation angle should be  specified
in  degrees  or  radians.  It's degrees, notwithstanding the fact that
the internal database stores it in radians, notwithstanding  the  fact
that page 77 documents it as degrees.

As I mentioned in the notes for  CINECHEM  0.2,  I  defy  anybody  who
attempts  to  use  3DSLIB to generate non-trivial camera placements or
camera motion without having access to the following code:


    /*  CAMUPVECTOR  --  Calculate camera up vector used by 3D  Studio
                         given camera location, target point, and bank
                         angle.  This  code  kindly  provided  by  Dan
                         Silva, (dsilva@Autodesk.com).  */

    static void CamUpVector(
                            point cam,        /* camera position */
                            point targ,       /* target position */
                            double bnkang,    /* bank angle (radians) */
                            point up          /* output: up vector */
    ) {
        double x, y, z, A, B, C, cA, cB, cC, sA, sB, sC;

        x = targ[X] - cam[X];
        y = targ[Y] - cam[Y];
        z = targ[Z] - cam[Z];

        if (y == 0 && x == 0) {
            /* Camera is pointed directly along the Z axis. */
            A = 0;
        } else {
            A = atan2(y, x);                /* yaw */
        }
        B = atan2(-z, sqrt(x * x + y * y)); /* pitch */
        C = bnkang;                         /* roll */
        cA = cos(A); sA = sin(A);
        cB = cos(B); sB = sin(B);
        cC = cos(C); sC = sin(C);

        /* Then the Up vector is (let's hope) */

        up[X] = cC * sB *cA + sC * sA;
        up[Y] = cC * sB *sA - sC * cA;
        up[Z] = cB * cC;
    }

This  code,  accompanied  by a thorough tutorial-style introduction in
how to use it in the manual, absolutely belongs  as  part  of  3DSLIB.
Without it, application developers will simply give up and require the
user  to  place  the camera himself in 3DS, or else one by one request
this algorithm from Autodesk.  This is the  3D  Studio  equivalent  of
AutoCAD's  "arbaxis"  algorithm,  and  you  simply have to know how it
works to get your code right.

Any  while  we're  at  it,  campers,  here's  the  code  that  turns a
rationally specified camera (in terms of  camera  and  target  points,
plus  normalised  world-space  camera  up  and right vectors) into the
weird stuff that 3D Studio expects, using the function above.

    Given:
        point camera, target, up, right; /* All 3-vectors of doubles */

    Then proceed as follows:
        double xzlen, yrot, eyr, a, zrot, fa, fb;
        point p, eax, cup, cx;
        DPOINT p1, p2;

        Cpoint(p1, camera);               /* Copy doubles to floats for 3DS */
        Cpoint(p2, target);

        vecsub(p, target, camera);
        vecnorm(p, p);

        /* Calculate rotation about the Y axis to turn the Z
           the co-ordinate system (still in the X-Z plane)
           with the "right" vector of the camera. */

        eyr = p[X] > 0 ? -yrot : yrot;
        Spoint(eax, cos(torad(eyr)), 0, sin(torad(eyr)));
        a = vecdot(eax, right);
        zrot = todeg(acos(a));
        if ((p[X] * right[X]) < 0) {
            zrot = -zrot;
        }
        CamUpVector(camera, target, 0.0, cup);
        veccross(cx, cup, up);
        fa = vecmag(cx);
        fb = todeg(asin(fa));
        twist = fb * ((cx[Z] * p[Z]) > 0 ? 1 : -1);
        AddCamera_3ds("Camera1", p1, p2, twist, lens, TRUE);

SMARTALLOC  revealed  that INIT_3DS.C is allocating a temporary buffer
for the file name but not bothering to  release  it.   In  INIT_3DS.C,
change the file open code to:

    mainfp = fopen( cp, "w+b" );
    free(cp);
    if (mainfp == NULL)
        return FAIL_3DS;

Thanks  to  Dan  Silva,  who  gave  me the code that 3D Studio uses to
calculate the default camera up vector, correct twist angles  are  now
generated  based  on  the viewing transform found in the .HIN file (at
least for all the cases I've tried!). .....John Walker. 


--------------------------
From: Grant Blaha
Eric G. Lundquist writes:

"On page 36 of the toolkit manual it says that Focal Length = 2400/FOV.  This is only true for a small range of lenses."

This is true in the real world, however in 3D Studio, the ratio is always true.  It is an error in thinking that was implemented in Release 1 and still exists in the current release.  This misunderstanding about optics doesn't have much effect on 3D Studio's output because it really uses FOV in all its calculations and is only doing a simple perspective projection (not trying to simulate optical artifacts.)   Most folks don't pay attention to the lens size anyway, they just adjust the camera until it "looks" right.

"If you use the Calculate Button in the 3D Studio Camera Definition box you get different answers than 2400/FOV.  Try an  FOV of 115 or 2."

When Release 1 came out, a small number of people complained that the camera lens behaviour didn't quite match up with real world behaviour.  No doubt the people who used real cameras and not virtual ones.  Usually they were trying to match the rendering to a site photo.  With all good intentions, the 2400/FOV relationship was kept internal (and in the ipas interface) but the dialog box code was written to convert the value to something closer to reality and back again.  
That's why the dialog doesn't display the 2400/FOV relationship anymore.

Incidentally, the dialog still isn't right, but its better.  

"Also, what is the FOV?"

FOV is the angle from the camera to the width of the image.  

"This question is really the same question as asking: how do you align a photo-montage in 3D Studio knowing the camera lens you used to take the background picture,  the size film you used, and where  and how you stood when you took the picture?"

Jonas should have a doc somewhere the discusses the proper relationships to everything.  The basic solution should resolve the real world camera placement into an position, target, rotation about the position/target vector (another wierd thing to worry about) and the FOV.  You then get the focal length from there.  

"If you can, how do you add or remove frames from an animation using a KXP routine."

I'm not sure what you mean.  You mean change the animation length or remove an animation key? 

"Also how can you set up a hold button for 3D Studio Hold Buffer in an IPAS  dialog box?"

Can't do that.  That is to say, there is no API function for saving/loading a mesh file (which is all the hold button really does).   If you are concerned about saving old state before you change it, you might be able to do that depending on the kind of state you want to change.  Keeping in mind that there is some state in 3DS that can be changed by an IPAS routine, but not queried.

"On a more general level, is there any method to access  the 3D Studio Icon Panels and/or  Menus during an IPAS routine?"

The plug-in API doesn't provide any access to 3DS menus. Sorry.

"I am curious if you can directly co
------------------
Grant,

<< FOV.. >>

It looks like your post got chopped. :-( Eric, JKJ and Micheal are 
interested in precise and accountable camera placement. They have 
engineers using 3DS as an engineering tool and wont take the 
"until it looks right" answer with a <g>.

jonas[adesk]  
----------------
Hi,
I am experimenting with particle systems and need some help !  I can't figure out how to recycle a particle after it has reached the end of its life.  I'm using the frame number to move the particle in the y direction but after it gets a certian distance I want to bring it back to its starting point and start over.  Any ideas or suggestions would be appreciated

			Thanks in advance
			Bruce Coy
------------------
As requested by Jonas, here is my April 1 list of IPAS improvement requests...

---- More orthogonality in functions

From my perspective as a maker of foreign file import and export routines, I want enough IPAS functions to create a complete object including geometry, hierarchy and materials.  (I'll leave motions out of the discussion for now.)

For a file exporter, I need to access both the hierarchy information as well as the geometry at the same time, so my routine can make a proper object for another file format.

The brick wall between the functionality of the Keyframer and the 3D Editor makes it very difficult to assemble links between objects you've just made in the 3D Editor.  Far too often while reading the IPAS docs, I got the feeling that IPAS functions were added only as needed to accomodate specific new IPAS ideas.  Instead, new IPAS functionality should be added in general, extensible contexts.

In general, I'd recommend adding more IPAS functions to make access to the internal data more orthogonal: every item of data inside the program (as created through the actions of the user) should be able to be examined, set, created or destroyed from within IPAS functions.


Orthogonal example with materials

For example, there should functions for manipulating materials:

1.  Iterate through the list of materials in 3DS at the moment. Retrieve each name.  (You can do this now.)  Expand this include a mechanism to retrieve all other values associated with the material.

2.  Add a new material given a name.  (You can do this now, but you can't set any material attributes.)

To avoid a big struct and for future expansion of material definitions, make a function that's passed a struct containing the name or index of the material to change or retrieve, plus a union pun that can hold any data that defines a material.  Each element within a material (various RGB values, specular coefficients, map filenames, etc.) would be assigned a unique #define enumeration, and 3DS would reset the element based on the proper value.

3.  The limit of 255 materials per scene is tough.  With our import and export conversions, this was a major obstacle.  However, the user faces this purely within 3DS, too.  Loading a series of objects with varied materials soon overflows the list of materials.  If IPAS routines could iterate through the material list, we could write our own routine that mapped excess materials to the list of 255.  But this is a tough routine to write.  If 3DS had an official method to map excess materials, we could follow that rule.  Otherwise, we'd need to invent our own.


IPAS descriptions

The user should see a better description of each IPAS routine.  DOS filenames are bad enough, restricting them to six characters (because of the _I or _W suffixes) makes it worse.  Instead, the user should see an English descriptive name.  One possible way to do this would be to require a database-like file that contains basic information about each IPAS: a description, version numbers, date stamp, etc. The file would have a standard extension, and 3DS could examine them on startup when it builds the list of available IPAS routines.


Automatic recognition

Depending on filename extensions for loading alternate bitmap formats is a good idea.  But what about PICT files, for example, which do not have a standard filename extension?

An alternative would be a scheme that, when the user has selected a file that isn't recognized by 3DS's internal GIF/TIF loaders, would query all available BXPs to see if they can recognize the file type. They would be passed the filename, and perhaps a buffer of the first few bytes of the file, and if one says it can recognize it, then it should load it.

You could do this with 3D files, too: our InterChange loaders all contain a subroutine that can attempt to "autorecognize" any 3D file format.  I have a lot of experience with developing APIs that handle this kind of extensible loading and recognition of file types, if you need some free advice, I'm here to help.

With a better organized loader/saver scheme, the list of available formats would be present in the Load and Save dialogs.  For example, our after-market export IPAS would appear in a list of available export formats, in the Save As dialog.


Future IPAS

Also, I'm curious about how IPAS will be adapted to WinNT and the SGI. We've adapted our translators to several platforms, including DLLs under Win32s / Windows NT.
------------
Sorry Jonas,

I'm the one who deleted those messages.  I did a save file on them and then hit delete, thinking it would dump them from my in box.  Obviously, it dumped them from the forum.

I managed to use the EXP_PXP_INFO stuff.  I now have a modified AXP.C that allows PXP calls from within an AXP!

Unfortunately, since the AXP.C file belongs to Autodesk, I can't post a copy of it here. :-( (I talked to someone at Adesk yesterday.)

I haven't tried the material mapping stuff yet but I did go through the manual again looking for references.  As usual, there was practically nothing there.

Someone described working with the toolkit like this; "Working with the IPAS3 SDK is a little like writing with one hand tied behind your back, a boxing glove on the other hand, and a blindfold over your eyes." <g>

Thanks again for all your help here Jonas, it's been invaluable!

Take care,

Danny...
--------------------------
Jonas,

<< IPAS3/4 wishes..>>

Here's a couple of wishes;

1) Documentation for the internal commands of the SDK.

This is vital for anyone wanting to create "hybrid" routines.  I could really have used that for the stuff I'm working on.  As it is, I basically had to reverse-engineer the toolkit to get my app to do what I wanted.

2) Better memory support.

This PharLap limitation is for the birds!  After going through the trouble of releasing memory after my routine terminates, it's a pain knowing that the memory is not necessarily available to 3DS because of the way the PharLap segments memory.

3) Fix the current bugs!

The item mesh flags for example.  I know this requires a fix to the 3DS core code but it has to be done.

4) Longer IPAS routine naming support.

Let us use names that are longer than six characters or at least let us add a short description of the routine that is visible from the IPAS routine list.  I don't know about anyone else, but I have at least twenty to thirty different IPAS routines and it's difficult to remember what they all do from looking at their short names in the list.

5) Enhance and support 3DE.

I think more and more people are going to need this tool as their dialogs become more complicated.

That's all I can think of right now.  If I come up with more, I'll post them here.

Regards,

Danny...
---------------------