home *** CD-ROM | disk | FTP | other *** search
- // copyright 1993 Michael B. Johnson; some portions copyright 1994, MIT
- // see COPYRIGHT for reuse legalities
- //
-
-
- /* this camera is intended to be used in conjunction with some other
- camera "sourceCamera" for controlling that camera's lights. This
- camera has a notion of the "sceneShape", which is the world shape from
- the other camera. It interrogates this shape for it's bounding box
- and uses it to draw a box where the shape is. It draws this box (in
- wireframe) and then it draws a plane twice the size of the box in each
- of the three orthogonal axes.
- */
-
- #import "WW3DLight.h"
- #import "WW3DShader.h"
- #import "WWLightInspectorCamera.h"
- #import "WWLightInspectorShape.h"
- #import "WWDADLightView.h"
-
- @implementation WWLightInspectorCamera
-
- + initialize { return [WWLightInspectorCamera setVersion:1], self; }
-
- - initFrame:(const NXRect *)r
- {
- RtPoint fromP = {5, 5, -10.0}, toP = {0, 0, 0};
- id aShape, secondLevelShape, thirdLevelShape;
- const char *WDRAG_PBTYPE[] = { NXAsciiPboardType, NULL};
-
-
- [super initFrame:r];
- [self registerForDraggedTypes:WDRAG_PBTYPE count:1];
-
- renderStyle = N3D_SmoothSolids;
- movingRenderStyle = N3D_WireFrame;
-
- scaleUpFactor = 1.05;
- scaleDownFactor = 0.95;
- translateXFactor = 0.025;
- translateYFactor = 0.025;
- translateZFactor = 0.05;
- epsilon = 4.0;
- selectionWidthEpsilon = 8.0;
- selectionHeightEpsilon = 8.0;
- showSelectedShape = NO;
- drawOriginForSelectedShape = NO;
-
- // setup 3D camera stuff
- [self setEyeAt:fromP toward:toP roll:0.0];
-
- //[self setupDefaultLights];
- // !!! need to get lights from sourceCamera
- // here in init, though, we probably don't have any...
-
- // setup some initial global rendering state
- // note that this fucks up the 3DWell - yikes!
- //[self setSurfaceTypeForAll:renderStyle chooseHider:YES];
- lowRezTesselationVector[0] = lowRezTesselationVector[1] = 4.0;
- tesselationVector[0] = tesselationVector[1] = 8.0;
- //RiGeometricApproximation(RI_TESSELATION, RI_PARAMETRIC, tesselationVector, RI_NULL);
-
- // stick in a reasonable shader
- theShader=[[WW3DShader alloc] init];
- [theShader setUseColor:YES];
- [theShader setColor:ribColor];
- [(N3DShader *)theShader setShader:"plastic"];
-
- // stick in a reasonable reference shape
- aShape = [[N3DShape alloc] init];
- [aShape setShapeName:NXCopyStringBuffer("lightWorld")];
- [[self setWorldShape:aShape] free]; // free the default world shape
-
- secondLevelShape = [[N3DShape alloc] init];
- [[self worldShape] linkDescendant:secondLevelShape];
- thirdLevelShape = [[WWLightInspectorShape alloc] init];
- [aShape setShapeName:NXCopyStringBuffer("boundingBoxOfWellWorld")];
- //[aShape calculateBoundingBox];
- [secondLevelShape linkDescendant:thirdLevelShape];
-
- // now when we add lights as descendants of the worldShape, they
- // will illuminate the bounding box of the well world...
-
- [self setSurfaceTypeForAll:N3D_SmoothSolids chooseHider:YES];
-
- theRotator = [[N3DRotator alloc] initWithCamera:self];
- [theRotator setRotationAxis:N3D_AllAxes];
- trackballAffects = WW_TRACKBALL_CAMERA;
-
- return self;
- }
-
- // the receptor gets sent this message when the object is dragged into
- // the File window, and when it is unarchived from the nib file.
- - awake
- {
- const char *WDRAG_PBTYPE[] = { NXAsciiPboardType, NULL};
-
-
- [super awake];
- [self registerForDraggedTypes:WDRAG_PBTYPE count:1];
-
- // everything else has just been unarchived...
-
- theRotator = [[N3DRotator alloc] initWithCamera:self];
- [theRotator setRotationAxis:N3D_AllAxes];
- trackballAffects = WW_TRACKBALL_CAMERA;
-
- return self;
- }
-
- - free
-
- {
- [self unregisterDraggedTypes];
- return [super free];
- }
-
-
- ///////////////////////
- // 3D stuff
- ///////////////////////
- #define ACTIVEBUTTONMASK (NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK|NX_ALTERNATEMASK|NX_CONTROLMASK|NX_COMMANDMASK)
- - mouseDown:(NXEvent *)theEvent
- {
- int oldMask;
- //NXPoint p, last, start;
- //NXRect visibleRect, oldRegion;
- NXPoint start;
- RtPoint myEyePoint,
- previousEyePoint, previousViewPoint;
- float previousRoll;
-
-
- dMouse.x = 0.0;
- dMouse.y = 0.0;
-
- // track the mouse until a mouseUp event occurs, updating the display
- // as tracking happens.
- [self lockFocus];
- oldMask = [window addToEventMask:ACTIVEBUTTONMASK];
-
- // switch to the N3D_WireFrame surface type
- [self setSurfaceTypeForAll:movingRenderStyle chooseHider:YES];
- RiGeometricApproximation(RI_TESSELATION, RI_PARAMETRIC, lowRezTesselationVector, RI_NULL);
-
- oldMouse = theEvent->location;
- [self convertPoint:&oldMouse fromView:nil];
- start = oldMouse;
-
- // when the alt key is depressed, we scale the worldShape up or down, depending on mouse movement.
- // otherwise, we rotate the worldShape using the virtual trackball
-
- while (1)
- { newMouse = theEvent->location;
- [self convertPoint:&newMouse fromView:nil];
- dMouse.x = newMouse.x - oldMouse.x;
- dMouse.y = newMouse.y - oldMouse.y;
- if (dMouse.x != 0.0 || dMouse.y != 0.0)
- { if (theEvent->flags & NX_ALTERNATEMASK)
- { switch (trackballAffects)
- { case WW_TRACKBALL_WORLD_SHAPE:
- [worldShape translate:0.0 :0.0 :(translateZFactor * dMouse.y)];
- break;
- case WW_TRACKBALL_CAMERA:
- // need to change Eye point
- [self moveEyeBy:0.0 :0.0 :(-1. * (translateZFactor * dMouse.y))];
- break;
- }
- }
- else
- {
- if (theEvent->flags & NX_COMMANDMASK)
- { switch (trackballAffects)
- { case WW_TRACKBALL_WORLD_SHAPE:
- [worldShape translate:(translateXFactor * dMouse.x)
- :(translateYFactor * dMouse.y) :0.0];
- break;
- case WW_TRACKBALL_CAMERA:
- [self moveEyeBy:(-1. * (translateXFactor * dMouse.x))
- :(-1. * (translateYFactor * dMouse.y)) :0.0];
- break;
- }
- }
- else
- { [theRotator trackMouseFrom:&oldMouse to:&newMouse rotationMatrix:rmat andInverse:irmat];
- switch (trackballAffects)
- { case WW_TRACKBALL_WORLD_SHAPE:
- [worldShape concatTransformMatrix:rmat premultiply:YES];
- break;
- case WW_TRACKBALL_CAMERA:
- [self getEyeAt:&previousEyePoint toward:&previousViewPoint roll:&previousRoll];
- myEyePoint[0] = previousEyePoint[0] + (-1. * (translateXFactor * dMouse.x));
- myEyePoint[1] = previousEyePoint[1] + (-1. * (translateYFactor * dMouse.y));
- myEyePoint[2] = previousEyePoint[2];
- [self setEyeAt:myEyePoint toward:previousViewPoint roll:previousRoll];
-
- break;
- }
- }
- }
- [self display];
- NXPing();
- }
- theEvent = [NXApp getNextEvent:ACTIVEBUTTONMASK];
- if (theEvent->type == NX_MOUSEUP)
- { break;
- }
- else
- { oldMouse = newMouse;
- }
- }
-
- // check to see if we should go off and render (need a minimum image size, like 16x16)...
-
- [self setSurfaceTypeForAll:renderStyle chooseHider:YES];
- RiGeometricApproximation(RI_TESSELATION, RI_PARAMETRIC, tesselationVector, RI_NULL);
-
- [self display];
- [self unlockFocus];
- [window setEventMask:oldMask];
- [window flushWindow];
-
- return self;
- }
-
- - (BOOL)acceptsFirstResponder { return YES; }
-
- - (BOOL)acceptsFirstMouse { return YES; }
-
- - (int)trackballAffects { return trackballAffects; }
- - takeTrackballAffectsFromMatrix:sender
- {
- int newVal = [[sender selectedCell] tag];
-
-
- switch (newVal)
- { case WW_TRACKBALL_WORLD_SHAPE:
- trackballAffects = newVal;
- [self setUsePreTransformMatrix:NO];
- break;
- case WW_TRACKBALL_CAMERA:
- // we assume that [self usesPreTransformMatrix] returns YES...
- trackballAffects = newVal;
- [self setUsePreTransformMatrix:YES];
- break;
- default:
- NXLogError("%d is an invalid value for trackballAffects.\n", newVal);
- }
-
-
- return self;
- }
-
- - (int)trackballXYZ
- {
- N3DAxis theAxis = [theRotator rotationAxis];
- int theAxisInt = -1;
-
-
- if (theAxis == N3D_AllAxes) { theAxisInt = 0; }
-
- if (theAxis == N3D_XAxis) { theAxisInt = 1; }
- if (theAxis == N3D_YAxis) { theAxisInt = 2; }
- if (theAxis == N3D_ZAxis) { theAxisInt = 3; }
-
- if (theAxis == N3D_XYAxes) { theAxisInt = 4; }
- if (theAxis == N3D_XZAxes) { theAxisInt = 5; }
- if (theAxis == N3D_YZAxes) { theAxisInt = 6; }
-
- return theAxisInt;
- }
-
- - takeTrackballXYZFromMatrix:sender
- {
- int newVal = [[sender selectedCell] tag];
-
- switch (newVal)
- { case 0:
- [theRotator setRotationAxis:N3D_AllAxes];
- break;
- case 1:
- [theRotator setRotationAxis:N3D_XAxis];
- break;
- case 2:
- [theRotator setRotationAxis:N3D_YAxis];
- break;
- case 3:
- [theRotator setRotationAxis:N3D_ZAxis];
- break;
- case 4:
- [theRotator setRotationAxis:N3D_XYAxes];
- break;
- case 5:
- [theRotator setRotationAxis:N3D_XZAxes];
- break;
- case 6:
- [theRotator setRotationAxis:N3D_YZAxes];
- break;
- default:
- NXLogError("%d is an invalid value for trackballXYZ.\n", newVal);
- }
- return self;
- }
-
-
- - (NXColor) backgroundColor { return backgroundColor; }
- - setBackgroundColor:(NXColor)c { backgroundColor = c; [self display]; return self; }
-
- ////////////////////////////////////////////////////////////////////
- // Dragging stuff
- ///////////////////////////////////////////////////////////////////
-
-
- - (NXDragOperation)draggingEntered:(id <NXDraggingInfo>)sender
- {
- if ([[sender draggingSource] respondsTo:@selector(lightType)])
- { return NX_DragOperationCopy;
- }
- return NX_DragOperationNone;
- }
-
- - (NXDragOperation)draggingUpdated:(id <NXDraggingInfo>)sender
- {
- if ([[sender draggingSource] respondsTo:@selector(lightType)])
- { return NX_DragOperationCopy;
- }
- return NX_DragOperationNone;
- }
-
- - draggingExited:sender { return self; }
- - (BOOL)prepareForDragOperation:sender { return YES; }
-
- - (BOOL)performDragOperation:sender
- {
- RtPoint fromPoint = {1, 1, -1};
- RtPoint toPoint = {0, 0, 0};
- RtFloat coneAngle = 30.0,
- coneDelta = 5.0,
- beamDistribution = 2.0,
- intensity = 0.7;
- id newLight;
- NXEvent *event = [NXApp currentEvent];
- NXPoint locationInWindow;
- NXRect myFrame;
-
-
- locationInWindow.x = event->location.x;
- locationInWindow.y = event->location.y;
- NXLogError("locationInWindow == (%f %f)\n", locationInWindow.x, locationInWindow.y);
- [self convertPoint:&locationInWindow fromView:[[self window] contentView]];
- NXLogError("location in this view == (%f %f)\n", locationInWindow.x, locationInWindow.y);
- [self getFrame:&myFrame];
- NXLogError("my frame is (%f %f) and starts at (%f %f)\n",
- myFrame.size.width, myFrame.size.height, myFrame.origin.x, myFrame.origin.y);
- NXLogError("normalized, the drop happened at (%f %f)\n",
- (locationInWindow.x/myFrame.size.width), (locationInWindow.y/myFrame.size.height));
-
- if ([[sender draggingSource] respondsTo:@selector(lightType)])
- { // send lightType, malloc up a new one, figure out where the mouse is and drop the light there
- switch ((int)[[sender draggingSource] lightType])
- { case ((int)N3D_PointLight): newLight = [[WW3DLight alloc] init];
- [newLight makePointFrom:fromPoint intensity:intensity];
- [newLight translate:N3D_XComp(fromPoint) :N3D_YComp(fromPoint) :N3D_ZComp(fromPoint)];
- [[self worldShape] linkDescendant:newLight];
- break;
- case ((int)N3D_DistantLight): newLight = [[WW3DLight alloc] init];
- [newLight makeDistantFrom:fromPoint to:toPoint intensity:intensity];
- [newLight translate:N3D_XComp(fromPoint) :N3D_YComp(fromPoint) :N3D_ZComp(fromPoint)];
- [[self worldShape] linkDescendant:newLight];
- break;
- case ((int)N3D_SpotLight): newLight = [[WW3DLight alloc] init];
- [newLight makeSpotFrom:fromPoint to:toPoint
- coneAngle:coneAngle coneDelta:coneDelta
- beamDistribution:beamDistribution
- intensity:intensity];
- [newLight translate:N3D_XComp(fromPoint) :N3D_YComp(fromPoint) :N3D_ZComp(fromPoint)];
- [[self worldShape] linkDescendant:newLight];
- break;
- default: newLight = [[WW3DLight alloc] init];
- [[self worldShape] linkDescendant:newLight];
- break;
- }
- return YES;
- }
- return NO;
- }
-
-
- - concludeDragOperation:sender { return self; }
-
- #define typeVector "fff[2f][2f]"
- #define typeValues &translateXFactor, &translateYFactor, &translateZFactor, &lowRezTesselationVector, &tesselationVector
-
-
- - read:(NXTypedStream *)stream {
- int version;
- [super read:stream];
-
- version = NXTypedStreamClassVersion(stream,"WWLightCamera");
- if (version == 0) NXReadTypes(stream,"i",&version), version=1;
- if (version == 1)
- { NXReadTypes(stream, typeVector, typeValues);
- backgroundColor = NXReadColor(stream);
- }
- return self;
- }
-
- - write:(NXTypedStream *)stream
- {
- [super write:stream];
- NXWriteTypes(stream, typeVector, typeValues);
- NXWriteColor(stream, backgroundColor);
- return self;
- }
-
-
- @end
-