home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / macraysh.sit / Code / Source / macmodify.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-13  |  35.3 KB  |  1,206 lines

  1. /*
  2.  * Maceditor.c
  3.  */
  4.  
  5. #include <MacHeaders>
  6. #include <Windows.h>
  7. #include <QuickDraw.h>
  8. #include <Controls.h>
  9. #include <Dialogs.h>
  10. #include <Lists.h>
  11. #include <Types.h>
  12.  
  13. #include "texture.h"
  14. #include "geom.h"
  15. #include "surface.h"
  16. #include "light.h"
  17.  
  18. #include "list.h"
  19. #include "grid.h"
  20. #include "blob.h"
  21. #include "sphere.h"
  22. #include "box.h"
  23. #include "disc.h"
  24. #include "cone.h"
  25. #include "poly.h"
  26. #include "plane.h"
  27. #include "cylinder.h"
  28. #include "sampling.h"
  29. #include "csg.h"
  30. #include "instance.h"
  31. #include "triangle.h"
  32. #include "torus.h"
  33.  
  34. #include "point.h"
  35. #include "infinite.h"
  36. #include "spot.h"
  37. #include "jittered.h"
  38. #include "extended.h"
  39.  
  40. #include "macmodify.h"
  41. #include "maceditor.h"
  42. #include "macdialog.h"
  43.  
  44. extern DialogPtr editorDialog ;
  45. extern Surface *Surfaces ;        /* Named surface instances */
  46. extern Geom *Objects ;            /* Named objects */
  47. extern Geom *World;
  48. extern Light *Lights;
  49.  
  50. extern Light *CreateProtoLight(short type);
  51. Surface *EditSurface(Geom *obj) ;
  52.  
  53. static Surface tmpsurf ;
  54. static ListHandle surfList ;
  55.  
  56.  
  57. pascal void ColourChoose(WindowPtr window, short itemno)
  58. {
  59.     ControlHandle itemHandle ;
  60.     Rect itemRect ;
  61.     short itemType ;
  62.     GrafPtr currPort ;
  63.     Color col ;
  64.     RGBColor maccol, oldcol ;
  65.     
  66.     switch(itemno) {
  67.         case ambienceUI:
  68.             col = tmpsurf.amb ;
  69.             break ;
  70.         case diffuseUI:
  71.             col = tmpsurf.diff ;
  72.             break ;
  73.         case specularUI:
  74.             col = tmpsurf.spec ;
  75.             break ;
  76.         case difftransUI:
  77.             col = tmpsurf.translu ;
  78.             break ;
  79.         case spectransUI:
  80.             col = tmpsurf.body ;
  81.             break ;
  82.         default:
  83.             return;
  84.             break ;
  85.     }
  86.     GetPort(&currPort) ;
  87.     SetPort(window) ;
  88.     GetForeColor(&oldcol) ;
  89.     GetDItem(window, itemno, &itemType, &itemHandle, &itemRect);
  90.     EraseRect(&itemRect) ;
  91.     FrameRect(&itemRect) ;
  92.     InsetRect(&itemRect,2,2) ;
  93.     maccol.red = (unsigned short) (65535. * col.r) ;
  94.     maccol.green = (unsigned short) (65535. * col.g) ;
  95.     maccol.blue = (unsigned short) (65535. * col.b) ;
  96.     RGBForeColor(&maccol) ;
  97.     PaintRect(&itemRect) ;
  98.     RGBForeColor(&oldcol) ;
  99.     SetPort(currPort) ;
  100. }
  101.  
  102. pascal void DrawSurfaceList(WindowPtr window, short item)
  103. {
  104.     GrafPtr        currPort ;
  105.     PenState    saveState;
  106.     short        itemType;
  107.     Handle        itemHandle;
  108.     Rect        itemBox;
  109.  
  110.     GetPort(&currPort) ;
  111.     SetPort(window) ;
  112.     GetPenState(&saveState);
  113.     GetDItem(window, item, &itemType, &itemHandle, &itemBox);
  114.     PenNormal() ;
  115.     InsetRect(&itemBox,-1,-1) ;
  116.     FrameRect(&itemBox);
  117.     LUpdate(window->visRgn, surfList) ;
  118.     SetPenState(&saveState);
  119.     SetPort(currPort) ;
  120. }
  121.  
  122. extern Surface predefined_surfaces[128];
  123.  
  124. Surface *EditSurface(Geom *obj)
  125. {
  126.     ControlHandle itemHandle ;
  127.     Rect itemRect, bounds ;
  128.     DialogPtr surfDialog ;
  129.     GrafPtr currPort;
  130.     register short i;
  131.     short hitItem = 0, theItem, itemType, loop;
  132.     Vector norm, pos ;
  133.     char exit = 0 ;
  134.     Surface *surf, *psurf ;
  135.     char buffer[255], doubleClick;
  136.     Point mousePoint, cellSize ;
  137.     Cell cell = {0,0}, myCell;
  138.  
  139.     if(obj->surf == NULL)
  140.         obj->surf = SurfaceCreate() ;
  141.     else {
  142.         for(surf = Surfaces ; surf ; surf = surf->next) {
  143.             if(surf == obj->surf)        /* Uh Oh ! Named surface. Lets warn the user */
  144.                 RLerror(RL_WARN,"This surface is a named instance !\rAll other instances will be affected by any changes you make.",0,0,0) ;
  145.         }
  146.     }
  147.     if(obj->surf != NULL) {
  148.         surf = obj->surf ;
  149.         tmpsurf = *surf ;
  150.         surfDialog = GetNewDialog(surfdialogR, 0L, (WindowPtr)-1) ;
  151.  
  152.         /* Turn our user item into a texture list */
  153.         GetDItem(surfDialog, surflistUI, &itemType, &itemHandle, &itemRect);
  154.         SetDItem(surfDialog, surflistUI, itemType, (ProcPtr) DrawSurfaceList, &itemRect);
  155.         SetRect(&bounds,0,0,1,0) ;
  156.         itemRect.right -= 15;
  157.         cellSize.v = cellSize.h = 0;
  158.         surfList = LNew(&itemRect,&bounds,cellSize,0,surfDialog,TRUE,FALSE,FALSE,TRUE) ;
  159.         LAddRow(111,0,surfList) ;
  160.         /* Insert some values */
  161.         for(loop = 0 ; loop<111 ; loop++) {
  162.             psurf = &predefined_surfaces[loop];
  163.             sprintf(buffer,"%s", psurf->name) ;
  164.             for(i = strlen(buffer) ; i < 255 ; i++) buffer[i] = ' ';
  165.             cell.v = loop;
  166.             LSetCell(buffer,255,cell,surfList);
  167.         }
  168.  
  169.         GetDItem(surfDialog, ambienceUI, &itemType, &itemHandle, &itemRect);
  170.         SetDItem(surfDialog, ambienceUI, itemType, (ProcPtr) ColourChoose, &itemRect);
  171.         GetDItem(surfDialog, diffuseUI, &itemType, &itemHandle, &itemRect);
  172.         SetDItem(surfDialog, diffuseUI, itemType, (ProcPtr) ColourChoose, &itemRect);
  173.         GetDItem(surfDialog, specularUI, &itemType, &itemHandle, &itemRect);
  174.         SetDItem(surfDialog, specularUI, itemType, (ProcPtr) ColourChoose, &itemRect);
  175.         GetDItem(surfDialog, difftransUI, &itemType, &itemHandle, &itemRect);
  176.         SetDItem(surfDialog, difftransUI, itemType, (ProcPtr) ColourChoose, &itemRect);
  177.         GetDItem(surfDialog, spectransUI, &itemType, &itemHandle, &itemRect);
  178.         SetDItem(surfDialog, spectransUI, itemType, (ProcPtr) ColourChoose, &itemRect);
  179.  
  180.         SetFloatEditText(surfDialog,specpowET,tmpsurf.srexp);
  181.         SetFloatEditText(surfDialog,attenuationET,tmpsurf.statten);
  182.         SetFloatEditText(surfDialog,refracindexET,tmpsurf.index);
  183.         SetFloatEditText(surfDialog,reflectivityET,tmpsurf.reflect);
  184.         SetFloatEditText(surfDialog,transmittanceET,tmpsurf.transp);
  185.         SetFloatEditText(surfDialog,translucencyET,tmpsurf.translucency);
  186.  
  187.         DrawDialog(surfDialog) ;
  188.         GetPort(&currPort);
  189.         SetPort(surfDialog);
  190.         
  191.         DrawHilite(surfDialog,surfokBU) ;
  192.  
  193.         
  194.         do {
  195.             ModalDialog(NULL, &hitItem) ;
  196.             switch(hitItem) {
  197.                 case surflistUI:
  198.                     GetMouse(&mousePoint);
  199.                     doubleClick = LClick(mousePoint,0,surfList) ;
  200.                     if(doubleClick) {
  201.                         myCell = LLastClick(surfList) ;
  202.                         if(myCell.v>=0 && myCell.v < 111) {
  203.                             psurf = tmpsurf.next;
  204.                             tmpsurf = predefined_surfaces[myCell.v];
  205.                             tmpsurf.next = psurf;
  206.                             SetFloatEditText(surfDialog,specpowET,tmpsurf.srexp);
  207.                             SetFloatEditText(surfDialog,attenuationET,tmpsurf.statten);
  208.                             SetFloatEditText(surfDialog,refracindexET,tmpsurf.index);
  209.                             SetFloatEditText(surfDialog,reflectivityET,tmpsurf.reflect);
  210.                             SetFloatEditText(surfDialog,transmittanceET,tmpsurf.transp);
  211.                             SetFloatEditText(surfDialog,translucencyET,tmpsurf.translucency);
  212.                             InvalRect(&surfDialog->portRect);
  213.                         }
  214.                     }
  215.                     break;
  216.                 case ambienceUI:
  217.                     PickColour(&tmpsurf.amb) ;
  218.                     DrawHilite(surfDialog,surfokBU) ;
  219.                     break ;
  220.                 case diffuseUI:
  221.                     PickColour(&tmpsurf.diff) ;
  222.                     DrawHilite(surfDialog,surfokBU) ;
  223.                     break ;
  224.                 case specularUI:
  225.                     PickColour(&tmpsurf.spec) ;
  226.                     DrawHilite(surfDialog,surfokBU) ;
  227.                     break ;
  228.                 case difftransUI:
  229.                     PickColour(&tmpsurf.translu) ;
  230.                     DrawHilite(surfDialog,surfokBU) ;
  231.                     break ;
  232.                 case spectransUI:
  233.                     PickColour(&tmpsurf.body) ;
  234.                     DrawHilite(surfDialog,surfokBU) ;
  235.                     break ;
  236.                 case surfokBU:
  237.                     if(    GetFloatEditText(surfDialog,specpowET,&tmpsurf.srexp) &&
  238.                             GetFloatEditText(surfDialog,attenuationET,&tmpsurf.statten) &&
  239.                             GetFloatEditText(surfDialog,refracindexET,&tmpsurf.index) &&
  240.                             GetFloatEditText(surfDialog,reflectivityET,&tmpsurf.reflect) &&
  241.                             GetFloatEditText(surfDialog,transmittanceET,&tmpsurf.transp) &&
  242.                             GetFloatEditText(surfDialog,translucencyET,&tmpsurf.translucency)) {
  243.                         *surf = tmpsurf ;
  244.                         exit = 1 ;
  245.                     }
  246.                     else
  247.                         SysBeep(1) ;
  248.                     break ;
  249.                 case surfcancelBU:
  250.                     exit = 1 ;
  251.                     break ;
  252.             }
  253.         } while (!exit) ;
  254.         LDispose(surfList) ;
  255.         SetPort(currPort);
  256.         DisposDialog(surfDialog) ;
  257.     }
  258.     else
  259.         RLerror(RL_WARN,"Surface creation error",0,0,0) ;
  260.     return surf ;
  261. }
  262.  
  263. /* Blob has a maximum number of metaballs set to 30 */
  264.  
  265. #define MAXMETABALLS 30
  266.  
  267. void doBlobModify(Geom *obj)
  268. {
  269.     GrafPtr currPort;
  270.     ControlHandle theHandle ;
  271.     DialogPtr blobDialog ;
  272.     short hitItem = 0, theItem;
  273.     Blob *tblob, *rblob ;
  274.     MetaList *mlist ;
  275.     MetaVector mvec ;
  276.     char exit = 0 ;
  277.     short i, what, ballnr ;
  278.     Float T ;
  279.     Point p ;
  280.     int num ;
  281.     
  282.     if(ObjectType(obj) != BLOB) return ;
  283.     rblob = (Blob *) obj->obj ;
  284.     if(rblob->num > MAXMETABALLS) return ;
  285.     
  286.     /* Create a 30 metaball blob */
  287.     
  288.     mlist = Malloc(MAXMETABALLS * sizeof(MetaList)) ;
  289.     if(!mlist) return ;
  290.     
  291.     /* First build an initialised meta list */
  292.     
  293.     for(i = 0 ; i < MAXMETABALLS ; i++) {
  294.         mlist[i].next = (i != MAXMETABALLS-1) ? &mlist[i+1] : NULL ;
  295.         mlist[i].mvec.x = 0 ;
  296.         mlist[i].mvec.y = 0 ;
  297.         mlist[i].mvec.z = 0 ;
  298.         mlist[i].mvec.rs = 1. ;
  299.         mlist[i].mvec.c0 = 1. ;
  300.     }
  301.     /* Create the blob with thresh 1 */
  302.     tblob = BlobCreate(1.,mlist,MAXMETABALLS) ;
  303.     /* Copy info from real blob across to temporary blob */
  304.     for(i = 0 ; i < rblob->num ; i++) {
  305.         tblob->list[i] = rblob->list[i];
  306.         if(tblob->list[i].rs>0) tblob->list[i].rs = sqrt(tblob->list[i].rs);
  307.     }
  308.     tblob->num = rblob->num ;
  309.     tblob->T = rblob->T ;
  310.     
  311.     /* ballnr tells us which metaball we are currently editting */
  312.     ballnr = 0 ;
  313.     blobDialog = GetNewDialog(blobdialogR, 0L, (WindowPtr)-1) ;
  314.     
  315.     SetCtlMax(SnatchHandle(blobDialog,blobmetaballchooseCI),MAXMETABALLS-1);
  316.     SetFloatEditText(blobDialog,blobxET,tblob->list[ballnr].x) ;
  317.     SetFloatEditText(blobDialog,blobyET,tblob->list[ballnr].y) ;
  318.     SetFloatEditText(blobDialog,blobzET,tblob->list[ballnr].z) ;
  319.     SetFloatEditText(blobDialog,blobstrengthET,tblob->list[ballnr].c0) ;
  320.     SetFloatEditText(blobDialog,blobradiusET,tblob->list[ballnr].rs) ;
  321.     SetFloatEditText(blobDialog,blobthreshET,tblob->T) ;
  322.     SetIntEditText(blobDialog,blobsizeET,tblob->num) ;
  323.     SetIntStringText(blobDialog,blobmetaballnrST,"Meta-Ball",0) ;
  324.  
  325.     mvec = tblob->list[ballnr] ;
  326.     T = tblob->T ;
  327.     num = tblob->num ;
  328.     
  329.     DrawDialog(blobDialog) ;
  330.     GetPort(&currPort);
  331.     SetPort(blobDialog);
  332.     DrawHilite(blobDialog,blobuseBU) ;
  333.     do {
  334.         ModalDialog(NULL, &hitItem) ;
  335.         switch(hitItem) {
  336.             case blobuseBU:
  337.                 if(GetFloatEditText(blobDialog,blobxET,&mvec.x) &&
  338.                     GetFloatEditText(blobDialog,blobyET,&mvec.y) &&
  339.                     GetFloatEditText(blobDialog,blobzET,&mvec.z) &&
  340.                     GetFloatEditText(blobDialog,blobradiusET,&mvec.rs) &&            
  341.                     GetFloatEditText(blobDialog,blobstrengthET,&mvec.c0) &&
  342.                     GetFloatEditText(blobDialog,blobthreshET,&T) &&
  343.                     GetIntEditText(blobDialog,blobsizeET,&num) &&
  344.                     (num > 0) && (num < MAXMETABALLS)) {
  345.  
  346.                     tblob->T = T ;
  347.                     tblob->num = num ;
  348.                     tblob->list[ballnr] = mvec ;
  349.  
  350.                     /* Completely purge and rebuild the blob */
  351.                     if(rblob->list)  Free(rblob->list) ;
  352.                     if(rblob->ilist) Free(rblob->ilist) ;
  353.                     if(rblob->iarr)  Free(rblob->iarr) ;
  354.                     if(obj->obj)     Free(obj->obj) ;
  355.                 
  356.                     /* We build a metalist from the info stored in tblob */
  357.                     mlist = Malloc(tblob->num * sizeof(MetaList)) ;    
  358.                     for(i = 0 ; i < tblob->num ; i++) {
  359.                         mlist[i].next = (i != tblob->num-1) ? &mlist[i+1] : NULL ;
  360.                         mlist[i].mvec = tblob->list[i];
  361.                     }
  362.                     /* Shove it into the new blob */
  363.                     obj->obj = BlobCreate(tblob->T,mlist,tblob->num) ;
  364.                     /* Now destroy our tblob */
  365.                     if(tblob->list)  Free(tblob->list) ;
  366.                     if(tblob->ilist) Free(tblob->ilist) ;
  367.                     if(tblob->iarr)  Free(tblob->iarr) ;
  368.                     if(tblob)        Free(tblob) ;
  369.                     exit = 1 ;
  370.                 }
  371.                 else
  372.                     SysBeep(1) ;
  373.                 break ;
  374.             case blobmetaballchooseCI:
  375.                 GetMouse(&p) ;
  376.                 theHandle = SnatchHandle(blobDialog,blobmetaballchooseCI) ;
  377.                 what = TestControl(theHandle,p); 
  378.                 if(GetFloatEditText(blobDialog,blobxET,&mvec.x) &&
  379.                     GetFloatEditText(blobDialog,blobyET,&mvec.y) &&
  380.                     GetFloatEditText(blobDialog,blobzET,&mvec.z) &&
  381.                     GetFloatEditText(blobDialog,blobradiusET,&mvec.rs) &&            
  382.                     GetFloatEditText(blobDialog,blobstrengthET,&mvec.c0)) {
  383.                     tblob->list[ballnr] = mvec ;
  384.                     switch(what) {
  385.                         case inDownButton:
  386.                         case inPageDown:
  387.                             SetCtlValue(theHandle,GetCtlValue(theHandle)+1) ; break;
  388.                         case inUpButton:
  389.                         case inPageUp:
  390.                             SetCtlValue(theHandle,GetCtlValue(theHandle)-1) ; break;
  391.                     }
  392.                     ballnr = GetCtlValue(theHandle) ;
  393.                     mvec = tblob->list[ballnr];
  394.                     SetFloatEditText(blobDialog,blobxET,tblob->list[ballnr].x) ;
  395.                     SetFloatEditText(blobDialog,blobyET,tblob->list[ballnr].y) ;
  396.                     SetFloatEditText(blobDialog,blobzET,tblob->list[ballnr].z) ;
  397.                     SetFloatEditText(blobDialog,blobstrengthET,tblob->list[ballnr].c0) ;
  398.                     SetFloatEditText(blobDialog,blobradiusET,tblob->list[ballnr].rs) ;
  399.                     SetIntStringText(blobDialog,blobmetaballnrST,"Meta-Ball",ballnr) ;
  400.                 }
  401.                 else
  402.                     SysBeep(1) ;
  403.                 break ;
  404.             case blobcancelBU:
  405.                 exit = 1 ;
  406.                 break ;
  407.         }
  408.     } while (!exit) ;
  409.     SetPort(currPort);
  410.     DisposDialog(blobDialog) ;
  411. }
  412.  
  413.  
  414. void doPlaneModify(Geom *obj)
  415. {
  416.     ControlHandle theHandle ;
  417.     DialogPtr planeDialog ;
  418.     short hitItem = 0, theItem;
  419.     Vector norm, pos ;
  420.     Plane *plane ;
  421.     char exit = 0 ;
  422.  
  423.     if(ObjectType(obj) != PLANE) return ;
  424.     plane = (Plane *)obj->obj ;
  425.     pos = plane->pos ;
  426.     norm = plane->norm ;
  427.  
  428.     planeDialog = GetNewDialog(planedialogR, 0L, (WindowPtr)-1) ;
  429.  
  430.     SetFloatEditText(planeDialog,planenormalx,norm.x) ;
  431.     SetFloatEditText(planeDialog,planenormaly,norm.y) ;
  432.     SetFloatEditText(planeDialog,planenormalz,norm.z) ;
  433.     SetFloatEditText(planeDialog,planepointx,pos.x) ;
  434.     SetFloatEditText(planeDialog,planepointy,pos.y) ;
  435.     SetFloatEditText(planeDialog,planepointz,pos.z) ;
  436.  
  437.     DrawDialog(planeDialog) ;
  438.     DrawHilite(planeDialog,planeokBU) ;
  439.     do {
  440.         ModalDialog(NULL, &hitItem) ;
  441.         switch(hitItem) {
  442.             case planeokBU:
  443.                 if(GetFloatEditText(planeDialog,planenormalx,&norm.x) &&
  444.                     GetFloatEditText(planeDialog,planenormaly,&norm.y) &&
  445.                     GetFloatEditText(planeDialog,planenormalz,&norm.z) &&
  446.                     GetFloatEditText(planeDialog,planepointx,&pos.x) &&
  447.                     GetFloatEditText(planeDialog,planepointy,&pos.y) &&
  448.                     GetFloatEditText(planeDialog,planepointz,&pos.z)) {
  449.                     if (VecNormalize(&norm) == 0.) {
  450.                         RLerror(RL_WARN, "Degenerate plane normal.\n",0,0,0);
  451.                         break;
  452.                     }
  453.                     plane->norm = norm;
  454.                     plane->pos = pos;
  455.                     plane->d = dotp(&plane->norm, &pos);
  456.                 }
  457.                 exit = 1 ;
  458.                 break ;
  459.             case planecancelBU:
  460.                 exit = 1 ;
  461.                 break ;
  462.         }
  463.     } while (!exit) ;
  464.     DisposDialog(planeDialog) ;
  465. }
  466.  
  467.  
  468. void doSphereModify(Geom *obj)
  469. {
  470.     ControlHandle theHandle ;
  471.     DialogPtr sphereDialog ;
  472.     Rect theRect ;
  473.     short hitItem = 0, theItem;
  474.     long theType ;
  475.     Sphere *sphere, tmpsphere ;
  476.     Str255 number ;
  477.     char exit = 0 ;
  478.     Float r,x,y,z ;
  479.  
  480.     if(ObjectType(obj) != SPHERE) return ;
  481.  
  482.     sphere = obj->obj ;
  483.     tmpsphere = *sphere;
  484.  
  485.     sphereDialog = GetNewDialog(spheredialogR, 0L, (WindowPtr)-1) ;
  486.     SetFloatEditText(sphereDialog,sphereradius,tmpsphere.r) ;
  487.     SetFloatEditText(sphereDialog,spherecentrex,tmpsphere.x) ;
  488.     SetFloatEditText(sphereDialog,spherecentrey,tmpsphere.y) ;
  489.     SetFloatEditText(sphereDialog,spherecentrez,tmpsphere.z) ;
  490.     DrawDialog(sphereDialog) ;
  491.     DrawHilite(sphereDialog,sphereokBU) ;
  492.     do {
  493.         ModalDialog(NULL, &hitItem) ;
  494.         switch(hitItem) {
  495.             case sphereokBU:
  496.                 if(    GetFloatEditText(sphereDialog,spherecentrex,&tmpsphere.x) &&
  497.                         GetFloatEditText(sphereDialog,spherecentrey,&tmpsphere.y) &&
  498.                         GetFloatEditText(sphereDialog,spherecentrez,&tmpsphere.z) &&
  499.                         GetFloatEditText(sphereDialog,sphereradius,&tmpsphere.r)) {
  500.                     *sphere = tmpsphere;
  501.                     sphere->rsq = sphere->r * sphere->r ;
  502.                     exit = 1 ;                    
  503.                 }
  504.                 else
  505.                     SysBeep(1) ;
  506.                 break ;
  507.             case spherecancelBU: 
  508.                 exit = 1 ;
  509.                 break ;
  510.         }
  511.     } while (!exit) ;
  512.     DisposDialog(sphereDialog) ;
  513. }
  514.  
  515. void doBoxModify(Geom *obj)
  516. {
  517.     ControlHandle theHandle ;
  518.     DialogPtr boxDialog ;
  519.     Float bounds[2][3] ;
  520.     Box *box ;
  521.     Str255 number ;
  522.     short hitItem = 0, theItem;
  523.     register short i,j ;
  524.     char exit = 0 ;
  525.  
  526.     if(ObjectType(obj) != BOX) return ;
  527.     box = obj->obj ;
  528.     for(i = 0 ; i < 2 ; i++)
  529.         for(j = 0 ; j < 3 ; j++)
  530.             bounds[i][j] = box->bounds[i][j] ;
  531.             
  532.     boxDialog = GetNewDialog(boxdialogR, 0L, (WindowPtr)-1) ;
  533.  
  534.     SetFloatEditText(boxDialog,boxbound1x,bounds[0][0]) ;
  535.     SetFloatEditText(boxDialog,boxbound1y,bounds[0][1]) ;
  536.     SetFloatEditText(boxDialog,boxbound1z,bounds[0][2]) ;
  537.     SetFloatEditText(boxDialog,boxbound2x,bounds[1][0]) ;
  538.     SetFloatEditText(boxDialog,boxbound2y,bounds[1][1]) ;
  539.     SetFloatEditText(boxDialog,boxbound2z,bounds[1][2]) ;
  540.     DrawDialog(boxDialog) ;
  541.     DrawHilite(boxDialog,boxokBU) ;
  542.     do {
  543.         ModalDialog(NULL, &hitItem) ;
  544.         switch(hitItem) {
  545.             case boxokBU:
  546.                 if( GetFloatEditText(boxDialog,boxbound1x,&bounds[0][0]) &&
  547.                         GetFloatEditText(boxDialog,boxbound1y,&bounds[0][1]) &&
  548.                         GetFloatEditText(boxDialog,boxbound1z,&bounds[0][2]) &&
  549.                         GetFloatEditText(boxDialog,boxbound2x,&bounds[1][0]) &&
  550.                         GetFloatEditText(boxDialog,boxbound2y,&bounds[1][1]) &&
  551.                         GetFloatEditText(boxDialog,boxbound2z,&bounds[1][2])) {
  552.                     for(i = 0 ; i < 2 ; i++)
  553.                         for(j = 0 ; j < 3 ; j++)
  554.                             box->bounds[i][j] = bounds[i][j] ;
  555.                     exit = 1 ;
  556.                 }
  557.                 else
  558.                     SysBeep(1) ;
  559.                 break ;
  560.             case boxcancelBU:
  561.                 exit = 1 ;
  562.                 break ;
  563.         }
  564.     } while (!exit) ;
  565.     DisposDialog(boxDialog) ;
  566. }
  567.  
  568. void doDiscModify(Geom *obj)
  569. {
  570.     ControlHandle theHandle ;
  571.     DialogPtr discDialog ;
  572.     short hitItem = 0, theItem;
  573.     Str255 number ;
  574.     Disc *disc ;
  575.     Float radius ;
  576.     Vector norm, pos ;
  577.     char exit = 0 ;
  578.  
  579.     if(ObjectType(obj) != DISC) return ;
  580.  
  581.     disc = (Disc *) obj->obj ;
  582.     pos = disc->pos ;
  583.     norm = disc->norm ;
  584.     radius = disc->radius ;
  585.     discDialog = GetNewDialog(discdialogR, 0L, (WindowPtr)-1) ;
  586.     SetFloatEditText(discDialog,discnormalx,norm.x) ;
  587.     SetFloatEditText(discDialog,discnormaly,norm.y) ;
  588.     SetFloatEditText(discDialog,discnormalz,norm.z) ;
  589.     SetFloatEditText(discDialog,disccentrex,pos.x) ;
  590.     SetFloatEditText(discDialog,disccentrey,pos.y) ;
  591.     SetFloatEditText(discDialog,disccentrez,pos.z) ;
  592.     SetFloatEditText(discDialog,discradius,radius) ;
  593.     DrawDialog(discDialog) ;
  594.     DrawHilite(discDialog,discokBU) ;
  595.     do {
  596.         ModalDialog(NULL, &hitItem) ;
  597.         switch(hitItem) {
  598.             case discokBU:
  599.                 if( GetFloatEditText(discDialog,discnormalx,&norm.x) &&
  600.                         GetFloatEditText(discDialog,discnormaly,&norm.y) &&
  601.                         GetFloatEditText(discDialog,discnormalz,&norm.z) &&
  602.                         GetFloatEditText(discDialog,disccentrex,&pos.x) &&
  603.                         GetFloatEditText(discDialog,disccentrey,&pos.y) &&
  604.                         GetFloatEditText(discDialog,disccentrez,&pos.z) &&
  605.                         GetFloatEditText(discDialog,discradius,&radius)) {
  606.                     disc->pos = pos ;
  607.                     disc->norm = norm ;
  608.                     disc->radius = radius ;
  609.                     exit = 1 ;
  610.                 }
  611.                 else
  612.                     SysBeep(1) ;
  613.                 break ;
  614.             case disccancelBU:
  615.                 exit = 1 ;
  616.                 break ;
  617.         }
  618.     } while (!exit) ;
  619.     DisposDialog(discDialog) ;
  620. }
  621.  
  622. void doCylinderModify(Geom *obj)
  623. {
  624.     ControlHandle theHandle ;
  625.     DialogPtr cylinderDialog ;
  626.     Cylinder *cyl ;
  627.     Str255 number ;
  628.     short hitItem = 0, theItem;
  629.     char exit = 0 ;
  630.     Vector dummy, bottom, top, axis ;
  631.     Float radius, length ;
  632.  
  633.     if(ObjectType(obj) != CYLINDER) return ;
  634.     cyl = (Cylinder *) obj->obj ;
  635.     
  636.     /* We have to be a bit more clever when determining the shape of a cylinder since everything
  637.      * has been converted into normalized coordinates
  638.      */
  639.     
  640.     /* Top and bottom of our normalized cylinder */
  641.     bottom.x = bottom.y = bottom.z = 0. ;
  642.     top.x = top.y = 0. ; top.z = 1. ;
  643.     /* Dummy is a point on the edge of our normalized cylinder */
  644.     dummy.x = 1.0 ; dummy.y = dummy.z = 0. ;
  645.  
  646.     /* Now transform these points */
  647.     PointTransform(&top,&cyl->trans.trans) ;
  648.     PointTransform(&bottom,&cyl->trans.trans) ;
  649.     PointTransform(&dummy,&cyl->trans.trans) ;
  650.     
  651.     /* The radius value is the distance between bottom and dummy */
  652.     VecSub(bottom,dummy,&dummy) ;
  653.     radius = VecNormalize(&dummy) ;
  654.  
  655.     cylinderDialog = GetNewDialog(cylinderdialogR, 0L, (WindowPtr)-1) ;
  656.     
  657.     SetFloatEditText(cylinderDialog,cylindertopx,top.x) ;
  658.     SetFloatEditText(cylinderDialog,cylindertopy,top.y) ;
  659.     SetFloatEditText(cylinderDialog,cylindertopz,top.z) ;
  660.     SetFloatEditText(cylinderDialog,cylinderbottomx,bottom.x) ;
  661.     SetFloatEditText(cylinderDialog,cylinderbottomy,bottom.y) ;
  662.     SetFloatEditText(cylinderDialog,cylinderbottomz,bottom.z) ;
  663.     SetFloatEditText(cylinderDialog,cylinderradius,radius) ;
  664.     DrawDialog(cylinderDialog) ;
  665.     DrawHilite(cylinderDialog,cylinderokBU) ;
  666.     do {
  667.         ModalDialog(NULL, &hitItem) ;
  668.         switch(hitItem) {
  669.             case cylinderokBU:
  670.                 if(GetFloatEditText(cylinderDialog,cylindertopx,&top.x) &&
  671.                         GetFloatEditText(cylinderDialog,cylindertopy,&top.y) &&
  672.                         GetFloatEditText(cylinderDialog,cylindertopz,&top.z) &&
  673.                         GetFloatEditText(cylinderDialog,cylinderbottomx,&bottom.x) &&
  674.                         GetFloatEditText(cylinderDialog,cylinderbottomy,&bottom.y) &&
  675.                         GetFloatEditText(cylinderDialog,cylinderbottomz,&bottom.z) &&
  676.                         GetFloatEditText(cylinderDialog,cylinderradius,&radius)) {
  677.                     VecSub(top, bottom, &axis);
  678.                     length = VecNormalize(&axis);
  679.                     CoordSysTransform(&bottom, &axis, radius, length, &cyl->trans);
  680.                     exit = 1 ;
  681.                 }
  682.                 else
  683.                     SysBeep(1) ;
  684.                 break ;
  685.             case cylindercancelBU:
  686.                 exit = 1 ;
  687.                 break ;
  688.         }
  689.     } while (!exit) ;
  690.     DisposDialog(cylinderDialog) ;
  691. }
  692.  
  693. void doConeModify(Geom *obj)
  694. {
  695.     ControlHandle theHandle ;
  696.     DialogPtr coneDialog ;
  697.     Cone *cone ;
  698.     Str255 number ;
  699.     short hitItem = 0, theItem;
  700.     char exit = 0 ;
  701.     Vector bottomr, bottom, apex ;
  702.     Float br, ar ;
  703.  
  704.     if(ObjectType(obj) != CONE) return ;
  705.     cone = (Cone *) obj->obj ;
  706.     
  707.     /* We have to be a bit more clever when determining the shape of a cone since everything
  708.      * has been converted into normalized coordinates
  709.      */
  710.     
  711.     /* apex and bottom of our normalized cone */
  712.     bottom.x = bottom.y = 0 ; bottom.z = 1. ;
  713.     apex.x = apex.y = 0. ; apex.z = cone->start_dist ;
  714.     /* Point on the edge of our normalized cone */
  715.     bottomr.x = 1.0 ; bottomr.y = 0 ; bottomr.z = 1. ;
  716.  
  717.     /* Now transform these points */
  718.     PointTransform(&apex,&cone->trans.trans) ;
  719.     PointTransform(&bottom,&cone->trans.trans) ;
  720.     PointTransform(&bottomr,&cone->trans.trans) ;
  721.     
  722.     /* Now calculate the radii */
  723.     VecSub(bottom,bottomr,&bottomr) ;
  724.     br = VecNormalize(&bottomr) ;
  725.     ar = cone->start_dist * br ;
  726.  
  727.     coneDialog = GetNewDialog(conedialogR, 0L, (WindowPtr)-1) ;
  728.     SetFloatEditText(coneDialog,coneapexx,apex.x) ;
  729.     SetFloatEditText(coneDialog,coneapexy,apex.y) ;
  730.     SetFloatEditText(coneDialog,coneapexz,apex.z) ;
  731.     SetFloatEditText(coneDialog,conebottomx,bottom.x) ;
  732.     SetFloatEditText(coneDialog,conebottomy,bottom.y) ;
  733.     SetFloatEditText(coneDialog,conebottomz,bottom.z) ;
  734.     SetFloatEditText(coneDialog,conebottomr,br) ;
  735.     SetFloatEditText(coneDialog,coneapexr,ar) ;
  736.     DrawDialog(coneDialog) ;
  737.     DrawHilite(coneDialog,coneokBU) ;
  738.     do {
  739.         ModalDialog(NULL, &hitItem) ;
  740.         switch(hitItem) {
  741.             case coneokBU:
  742.                 if(GetFloatEditText(coneDialog,coneapexx,&apex.x) &&
  743.                         GetFloatEditText(coneDialog,coneapexy,&apex.y) &&
  744.                         GetFloatEditText(coneDialog,coneapexz,&apex.z) &&
  745.                         GetFloatEditText(coneDialog,conebottomx,&bottom.x) &&
  746.                         GetFloatEditText(coneDialog,conebottomy,&bottom.y) &&
  747.                         GetFloatEditText(coneDialog,conebottomz,&bottom.z) &&
  748.                         GetFloatEditText(coneDialog,conebottomr,&br) &&
  749.                         GetFloatEditText(coneDialog,coneapexr,&ar)) {
  750.                     Float tantheta, lprime, tlen, len, dtmp;
  751.                     Vector axis, base, tmp;
  752.  
  753.                     if(equal(ar,br)) {
  754.                         RLerror(RL_WARN, "Top and bottom radii can not be equal",0,0,0) ;
  755.                         break;
  756.                     }
  757.                     else if(ar < br) {
  758.                         tmp = bottom;
  759.                         bottom = apex;
  760.                         apex = tmp;
  761.                         dtmp = br;
  762.                         br = ar;
  763.                         ar = dtmp;
  764.                     }
  765.                     VecSub(apex, bottom, &axis);
  766.                     len = VecNormalize(&axis);
  767.                     if (len < EPSILON) {
  768.                         RLerror(RL_WARN, "Degenerate cone.\n",0,0,0);
  769.                         break ;
  770.                     }
  771.                     tantheta = (ar - br) / len;
  772.                     lprime = br / tantheta;
  773.                     VecScale(-lprime, axis, &base);
  774.                     VecAdd(base, bottom, &base);
  775.                     tlen = lprime + len;
  776.                     cone->start_dist = lprime / tlen;
  777.                     CoordSysTransform(&base, &axis, ar, tlen, &cone->trans);
  778.                     exit = 1 ;
  779.                 }
  780.                 else
  781.                     SysBeep(1) ;
  782.                 break ;
  783.             case conecancelBU:
  784.                 exit = 1 ;
  785.                 break ;
  786.         }
  787.     } while (!exit) ;
  788.     DisposDialog(coneDialog) ;
  789. }
  790.  
  791. #define POLYPOINTS 30
  792.  
  793. void doPolygonModify(Geom *obj)
  794. {
  795.     GrafPtr currPort;
  796.     ControlHandle theHandle ;
  797.     DialogPtr polyDialog ;
  798.     short hitItem = 0, theItem, what, polynr,loop;
  799.     Str255 number ;
  800.     Point p;
  801.     Float radius ;
  802.     Vector vec ;
  803.     RPolygon *tpoly, *poly;
  804.     PointList *plist[POLYPOINTS], *next, *this;
  805.     char exit = 0 ;
  806.     int points;
  807.  
  808.     if(ObjectType(obj) != POLYGON) return ;
  809.  
  810.     /* Create a dummy polygon first */
  811.     for(loop = POLYPOINTS-1 ; loop >= 0 ; loop--) {
  812.         plist[loop] = Malloc(sizeof(PointList));
  813.         plist[loop]->next = plist[loop+1];
  814.         plist[loop]->vec.x = (Float)loop;
  815.         plist[loop]->vec.y = (Float)loop*(Float)loop;
  816.         plist[loop]->vec.z = 0;
  817.     }
  818.     plist[POLYPOINTS-1]->next = NULL;
  819.     tpoly = PolygonCreate(plist[0],POLYPOINTS,FALSE);
  820.     
  821.     /* Now copy our poly into the temporary store */
  822.     poly = obj->obj;
  823.     for(loop = 0 ; loop < poly->npoints; loop++)
  824.         tpoly->points[loop] = poly->points[loop];
  825.  
  826.     polynr = 0;
  827.     polyDialog = GetNewDialog(polydialogR, 0L, (WindowPtr)-1) ;
  828.     SetCtlMax(SnatchHandle(polyDialog,polychooseCI),POLYPOINTS-1);
  829.     SetFloatEditText(polyDialog,polyxET,tpoly->points[polynr].x) ;
  830.     SetFloatEditText(polyDialog,polyyET,tpoly->points[polynr].y) ;
  831.     SetFloatEditText(polyDialog,polyzET,tpoly->points[polynr].z) ;
  832.     SetIntEditText(polyDialog,polyverticesET,poly->npoints) ;
  833.     SetIntStringText(polyDialog,polyvertexST,"Vertex",polynr) ;
  834.     
  835.     GetPort(&currPort);
  836.     SetPort(polyDialog);
  837.     DrawDialog(polyDialog) ;
  838.     DrawHilite(polyDialog,polyuseBU) ;
  839.     do {
  840.         ModalDialog(NULL, &hitItem) ;
  841.         switch(hitItem) {
  842.             case polychooseCI:
  843.                 GetMouse(&p) ;
  844.                 theHandle = SnatchHandle(polyDialog,polychooseCI) ;
  845.                 what = TestControl(theHandle,p); 
  846.                 if(GetFloatEditText(polyDialog,polyxET,&vec.x) &&
  847.                     GetFloatEditText(polyDialog,polyyET,&vec.y) &&
  848.                     GetFloatEditText(polyDialog,polyzET,&vec.z)) {
  849.                     tpoly->points[polynr] = vec ;
  850.                     switch(what) {
  851.                         case inDownButton:
  852.                         case inPageDown:
  853.                             SetCtlValue(theHandle,GetCtlValue(theHandle)+1) ; break;
  854.                         case inUpButton:
  855.                         case inPageUp:
  856.                             SetCtlValue(theHandle,GetCtlValue(theHandle)-1) ; break;
  857.                     }
  858.                     polynr = GetCtlValue(theHandle) ;
  859.                     vec = tpoly->points[polynr];
  860.                     SetFloatEditText(polyDialog,polyxET,tpoly->points[polynr].x) ;
  861.                     SetFloatEditText(polyDialog,polyyET,tpoly->points[polynr].y) ;
  862.                     SetFloatEditText(polyDialog,polyzET,tpoly->points[polynr].z) ;
  863.                     SetIntStringText(polyDialog,polyvertexST,"Vertex",polynr) ;
  864.                 }
  865.                 else
  866.                     SysBeep(1) ;
  867.                 break ;
  868.             case polyuseBU:
  869.                 if(GetFloatEditText(polyDialog,polyxET,&vec.x) &&
  870.                         GetFloatEditText(polyDialog,polyyET,&vec.y) &&
  871.                         GetFloatEditText(polyDialog,polyzET,&vec.z) &&
  872.                         GetIntEditText(polyDialog,polyverticesET,&points) &&
  873.                         (points <= POLYPOINTS) && points) {
  874.  
  875.                     /* Store the last edited point */
  876.                     polynr = GetCtlValue(SnatchHandle(polyDialog,polychooseCI)) ;
  877.                     tpoly->points[polynr] = vec ;
  878.                     
  879.                     /* Copy our data into a new pointlist */
  880.                     for(loop = (short)points-1 ; loop >= 0 ; loop--) {
  881.                         plist[loop] = Malloc(sizeof(PointList));
  882.                         plist[loop]->next = plist[loop+1];
  883.                         plist[loop]->vec = tpoly->points[loop];
  884.                     }
  885.                     plist[points-1]->next = NULL;
  886.                     
  887.                     /* Remove the old and temporary polygons */
  888.                     Free(poly->points);
  889.                     Free(poly);
  890.                     Free(tpoly->points);
  891.                     Free(tpoly);
  892.                     
  893.                     /* create a new poly with the new points */
  894.                     obj->obj=PolygonCreate(plist[0],points,FALSE);
  895.                     exit = 1 ;
  896.                 }
  897.                 else
  898.                     SysBeep(1);
  899.                 break ;
  900.             case polycancelBU:
  901.                 exit = 1 ;
  902.                 break ;
  903.         }
  904.     } while (!exit) ;
  905.     SetPort(currPort);
  906.     DisposDialog(polyDialog) ;
  907. }
  908.  
  909. void doTriangleModify(Geom *obj)
  910. {
  911.     ControlHandle theHandle ;
  912.     DialogPtr triangleDialog ;
  913.     short hitItem = 0, theItem;
  914.     Str255 number ;
  915.     Triangle *tri ;
  916.     Float d ;
  917.     char exit = 0 ;
  918.     Vector p1,p2,p3, n1,n2,n3, ptmp, anorm;
  919.  
  920.     if(ObjectType(obj) != TRIANGLE) return ;
  921.  
  922.     tri = (Triangle *) obj->obj ;
  923.     p1 = tri->p[0];
  924.     p2 = tri->p[1];
  925.     p3 = tri->p[2];
  926.     triangleDialog = GetNewDialog(triangledialogR, 0L, (WindowPtr)-1) ;
  927.     SetFloatEditText(triangleDialog,triv1xET,p1.x) ;
  928.     SetFloatEditText(triangleDialog,triv1yET,p1.y) ;
  929.     SetFloatEditText(triangleDialog,triv1zET,p1.z) ;
  930.     SetFloatEditText(triangleDialog,triv2xET,p2.x) ;
  931.     SetFloatEditText(triangleDialog,triv2yET,p2.y) ;
  932.     SetFloatEditText(triangleDialog,triv2zET,p2.z) ;
  933.     SetFloatEditText(triangleDialog,triv3xET,p3.x) ;
  934.     SetFloatEditText(triangleDialog,triv3yET,p3.y) ;
  935.     SetFloatEditText(triangleDialog,triv3zET,p3.z) ;
  936.     if(tri->vnorm) {
  937.         n1 = tri->vnorm[0];
  938.         n2 = tri->vnorm[1];
  939.         n3 = tri->vnorm[2];
  940.         SetFloatEditText(triangleDialog,trin1xET,n1.x) ;
  941.         SetFloatEditText(triangleDialog,trin1yET,n1.y) ;
  942.         SetFloatEditText(triangleDialog,trin1zET,n1.z) ;
  943.         SetFloatEditText(triangleDialog,trin2xET,n2.x) ;
  944.         SetFloatEditText(triangleDialog,trin2yET,n2.y) ;
  945.         SetFloatEditText(triangleDialog,trin2zET,n2.z) ;
  946.         SetFloatEditText(triangleDialog,trin3xET,n3.x) ;
  947.         SetFloatEditText(triangleDialog,trin3yET,n3.y) ;
  948.         SetFloatEditText(triangleDialog,trin3zET,n3.z) ;
  949.     }
  950.     SetCtlValue(SnatchHandle(triangleDialog,triphongCB), (short)tri->type) ;
  951.     DrawDialog(triangleDialog) ;
  952.     DrawHilite(triangleDialog,triuseBU) ;
  953.     do {
  954.         ModalDialog(NULL, &hitItem) ;
  955.         switch(hitItem) {
  956.             case triphongCB:
  957.                 if(GetCtlValue(SnatchHandle(triangleDialog,triphongCB))==1)
  958.                     SetCtlValue(SnatchHandle(triangleDialog,triphongCB),0);
  959.                 else
  960.                     SetCtlValue(SnatchHandle(triangleDialog,triphongCB),1) ;
  961.                 break;
  962.             case triuseBU:
  963.                 if(GetFloatEditText(triangleDialog,triv1xET,&p1.x) &&
  964.                     GetFloatEditText(triangleDialog,triv1yET,&p1.y) &&
  965.                     GetFloatEditText(triangleDialog,triv1zET,&p1.z) &&
  966.                     GetFloatEditText(triangleDialog,triv2xET,&p2.x) &&
  967.                     GetFloatEditText(triangleDialog,triv2yET,&p2.y) &&
  968.                     GetFloatEditText(triangleDialog,triv2zET,&p2.z) &&
  969.                     GetFloatEditText(triangleDialog,triv3xET,&p3.x) &&
  970.                     GetFloatEditText(triangleDialog,triv3yET,&p3.y) &&
  971.                     GetFloatEditText(triangleDialog,triv3zET,&p3.z)) {
  972.                     
  973.                     if ((tri->type == PHONGTRI) &&
  974.                         (!GetFloatEditText(triangleDialog,trin1xET,&n1.x) ||
  975.                          !GetFloatEditText(triangleDialog,trin1zET,&n1.z) ||
  976.                          !GetFloatEditText(triangleDialog,trin2xET,&n2.x) ||
  977.                          !GetFloatEditText(triangleDialog,trin2yET,&n2.y) ||
  978.                          !GetFloatEditText(triangleDialog,trin2zET,&n2.z) ||
  979.                          !GetFloatEditText(triangleDialog,trin3xET,&n3.x) ||
  980.                          !GetFloatEditText(triangleDialog,trin3yET,&n3.y) ||
  981.                          !GetFloatEditText(triangleDialog,trin3zET,&n3.z))) {
  982.                         SysBeep(1);
  983.                         break;
  984.                     }
  985.  
  986.                     VecSub(p2, p1, &tri->e[0]);
  987.                     VecSub(p3, p2, &tri->e[1]);
  988.                     VecSub(p1, p3, &tri->e[2]);
  989.  
  990.                     /* Find plane normal. */
  991.                     VecCross(&tri->e[0], &tri->e[1], &ptmp);
  992.                     tri->nrm = ptmp;
  993.                     if (VecNormalize(&tri->nrm) == 0.) {
  994.                         RLerror(RL_ADVISE, "Degenerate triangle.\n",0,0,0);
  995.                         break;
  996.                     }
  997.                     tri->d = dotp(&tri->nrm, &p1);
  998.                     tri->p[0] = p1;
  999.                     tri->p[1] = p2;
  1000.                     tri->p[2] = p3;
  1001.                     
  1002.                     tri->type = (int) GetCtlValue(SnatchHandle(triangleDialog,triphongCB));
  1003.                     if (tri->type == PHONGTRI) {
  1004.                         if (VecNormalize(&n1) == 0. || VecNormalize(&n2) == 0. ||
  1005.                                 VecNormalize(&n3) == 0.) {
  1006.                             RLerror(RL_WARN, "Degenerate vertex normal.\n",0,0,0);
  1007.                             break;
  1008.                         }
  1009.                         if(!tri->vnorm) tri->vnorm = (Vector *)Malloc(3 * sizeof(Vector));
  1010.                         tri->vnorm[0] = n1;
  1011.                         tri->vnorm[1] = n2;
  1012.                         tri->vnorm[2] = n3;
  1013.                         if (dotp(&tri->vnorm[0], &tri->nrm) < 0.) {
  1014.                             /*
  1015.                              * Reverse direction of surface normal on Phong
  1016.                              * triangle if the surface normal points "away"
  1017.                              * from the first vertex normal.
  1018.                              * Note that this means that we trust the vertex
  1019.                              * normals rather than trust that the user gave the
  1020.                              * vertices in the correct order.
  1021.                              */
  1022.                             RLerror(RL_ADVISE, "Inconsistant triangle normals.\n",0,0,0);
  1023.                             VecScale(-1., tri->nrm, &tri->nrm);
  1024.                             VecScale(-1., ptmp, &ptmp);
  1025.                             tri->d = -tri->d;
  1026.                             VecScale(-1., tri->e[0], &tri->e[0]);
  1027.                             VecScale(-1., tri->e[1], &tri->e[1]);
  1028.                             VecScale(-1., tri->e[2], &tri->e[2]);
  1029.                         }
  1030.                     }
  1031.                     /*
  1032.                      * Find "dominant" part of normal vector.
  1033.                      */
  1034.                     anorm.x = fabs(ptmp.x);
  1035.                     anorm.y = fabs(ptmp.y);
  1036.                     anorm.z = fabs(ptmp.z);
  1037.  
  1038.                     /*
  1039.                      * Scale edges by dominant part of normal.  This makes intersection
  1040.                      * testing a bit faster.
  1041.                      */ 
  1042.                     if (anorm.x > anorm.y && anorm.x > anorm.z) {
  1043.                         tri->index = XNORMAL;
  1044.                         d = 1. / ptmp.x;
  1045.                     } else if (anorm.y > anorm.z) {
  1046.                         tri->index = YNORMAL;
  1047.                         d = 1. / ptmp.y;
  1048.                     } else {
  1049.                         tri->index = ZNORMAL;
  1050.                         d = 1. /ptmp.z;
  1051.                     }
  1052.  
  1053.                     VecScale(d, tri->e[0], &tri->e[0]);
  1054.                     VecScale(d, tri->e[1], &tri->e[1]);
  1055.                     VecScale(d, tri->e[2], &tri->e[2]);
  1056.  
  1057.                     exit=1;
  1058.                 }
  1059.                 else
  1060.                     SysBeep(1);
  1061.                 break ;
  1062.             case tricancelBU:
  1063.                 exit = 1 ;
  1064.                 break ;
  1065.         }
  1066.     } while (!exit) ;
  1067.     DisposDialog(triangleDialog) ;
  1068. }
  1069.  
  1070. void doTorusModify(Geom *obj)
  1071. {
  1072.     ControlHandle theHandle ;
  1073.     DialogPtr torDialog ;
  1074.     Torus *torus;
  1075.     Str255 number ;
  1076.     short hitItem = 0, theItem;
  1077.     char exit = 0 ;
  1078.     Vector centre, normal ;
  1079.     Float a,b;
  1080.  
  1081.     if(ObjectType(obj) != TORUS) return ;
  1082.     torus = (Torus *) obj->obj ;
  1083.     
  1084.     /* Stick in the canonical centre and normal */
  1085.     centre.x = centre.y = centre.z =0.;
  1086.     normal.x = normal.y = 0.; normal.z = 1.;
  1087.  
  1088.     /* Now transform these points */
  1089.     PointTransform(¢re,&torus->trans.trans) ;
  1090.     PointTransform(&normal,&torus->trans.trans) ;
  1091.     VecNormalize(&normal);
  1092.  
  1093.     a = torus->a;
  1094.     b = torus->b;
  1095.  
  1096.     torDialog = GetNewDialog(torusdialogR, 0L, (WindowPtr)-1) ;
  1097.     SetFloatEditText(torDialog,torposxET,centre.x) ;
  1098.     SetFloatEditText(torDialog,torposyET,centre.y) ;
  1099.     SetFloatEditText(torDialog,torposzET,centre.z) ;
  1100.     SetFloatEditText(torDialog,tornormxET,normal.x) ;
  1101.     SetFloatEditText(torDialog,tornormyET,normal.y) ;
  1102.     SetFloatEditText(torDialog,tornormzET,normal.z) ;
  1103.     SetFloatEditText(torDialog,torsweptET,b) ;
  1104.     SetFloatEditText(torDialog,tortubeET,a) ;
  1105.     DrawDialog(torDialog) ;
  1106.     DrawHilite(torDialog,toruseBU) ;
  1107.     do {
  1108.         ModalDialog(NULL, &hitItem) ;
  1109.         switch(hitItem) {
  1110.             case toruseBU:
  1111.                 if(GetFloatEditText(torDialog,torposxET,¢re.x) &&
  1112.                         GetFloatEditText(torDialog,torposyET,¢re.y) &&
  1113.                         GetFloatEditText(torDialog,torposzET,¢re.z) &&
  1114.                         GetFloatEditText(torDialog,tornormxET,&normal.x) &&
  1115.                         GetFloatEditText(torDialog,tornormyET,&normal.y) &&
  1116.                         GetFloatEditText(torDialog,tornormzET,&normal.z) &&
  1117.                         GetFloatEditText(torDialog,torsweptET,&b) &&
  1118.                         GetFloatEditText(torDialog,tortubeET,&a)) {
  1119.                     Free(torus);
  1120.                     obj->obj = TorusCreate(a,b,¢re,&normal);
  1121.                     exit = 1 ;
  1122.                 }
  1123.                 else
  1124.                     SysBeep(1) ;
  1125.                 break ;
  1126.             case torcancel:
  1127.                 exit = 1 ;
  1128.                 break ;
  1129.         }
  1130.     } while (!exit) ;
  1131.     DisposDialog(torDialog) ;
  1132. }
  1133.  
  1134.  
  1135. void doObjectModify(Geom *obj)
  1136. {
  1137.     extern void GeomBounds(Geom *obj, Float bounds[2][3]) ;
  1138.     Geom *obj2 ;
  1139.     GrafPtr currPort;
  1140.     DialogPtr objectDialog ;
  1141.     short hitItem = 0, theItem;
  1142.     char exit = 0 ;
  1143.  
  1144.     if(!obj) return ;
  1145.     for(obj2 = Objects ; obj2 ; obj2 = obj2->next) {
  1146.         if(obj == obj2)
  1147.             RLerror(RL_WARN,"This object is a named instance !\rAll other instances will be affected by any changes you make.",0,0,0) ;
  1148.     }
  1149.  
  1150.     objectDialog = GetNewDialog(objectdialogR, 0L, (WindowPtr)-1) ;
  1151.     DrawDialog(objectDialog) ;
  1152.     DrawHilite(objectDialog,objectdoneBU) ;
  1153.     GetPort(&currPort);
  1154.     SetPort(objectDialog);
  1155.     do {
  1156.         ModalDialog(NULL, &hitItem) ;
  1157.         switch(hitItem) {
  1158.             case objectdoneBU:
  1159.                 exit=1;
  1160.                 break;
  1161.             case objecttransformsBU:
  1162.                 EditTransforms(obj) ;
  1163.                 SetPort(editorDialog);
  1164.                 InvalRect(&editorDialog->portRect);
  1165.                 SetPort(objectDialog);
  1166.                 DrawHilite(objectDialog,objectdoneBU) ;
  1167.                 break ;
  1168.             case objectsurfaceBU:
  1169.                 EditSurface(obj) ;
  1170.                 SetPort(editorDialog);
  1171.                 InvalRect(&editorDialog->portRect);
  1172.                 SetPort(objectDialog);
  1173.                 DrawHilite(objectDialog,objectdoneBU) ;
  1174.                 break ;
  1175.             case objecttextureBU:
  1176.                 EditTexture(obj) ;
  1177.                 DrawHilite(objectDialog,objectdoneBU) ;
  1178.                 break ;
  1179.             case objecteditBU:
  1180.                 switch(ObjectType(obj)) {
  1181.                     case -1:        return ;
  1182.                     case PLANE:        doPlaneModify(obj) ;        break;
  1183.                     case SPHERE:    doSphereModify(obj) ;        break;
  1184.                     case CONE:        doConeModify(obj) ;            break;
  1185.                     case BOX:        doBoxModify(obj) ;            break;
  1186.                     case BLOB:        doBlobModify(obj) ;            break;
  1187.                     case DISC:        doDiscModify(obj) ;            break;
  1188.                     case CYLINDER:    doCylinderModify(obj);        break;
  1189.                     case POLYGON:    doPolygonModify(obj);        break;
  1190.                     case TORUS:        doTorusModify(obj);            break;
  1191.                     case TRIANGLE:    doTriangleModify(obj);        break;
  1192.                     case HF:
  1193.                     default:
  1194.                         RLerror(RL_WARN,"No editor exists for this object\r",0,0,0);
  1195.                         break;
  1196.                 }
  1197.                 SetPort(editorDialog);
  1198.                 InvalRect(&editorDialog->portRect);
  1199.                 SetPort(objectDialog);
  1200.                 DrawHilite(objectDialog,objectdoneBU) ;
  1201.                 break;
  1202.         }
  1203.     } while(!exit);
  1204.     SetPort(currPort);
  1205.     DisposDialog(objectDialog);
  1206. }