This is BBRotator.m in view mode; [Download] [Up]
/* BBRotator.m
*
* Rotates the world. Moves the camera. Will change a lot!!
*
* For more interface-info see the header file. More in depth information
* can be found in the source-code.
*
* Written by: Thomas Engel
* Created: 22.12.1993 (Copyleft)
* Last modified: 17.11.1994
*/
#import "BBRotator.h"
#import "../BBBeakerCamera.h"
#import "../BBMoleculeShape.h"
#import "BBSlider.h"
#import "../BBAppManager.h"
#import "../Preferences.subproj/BBPreferencesManager.h"
#import "../Preferences.subproj/BBDefaultApp.h"
#import "Misc3DDeviceServer.h"
#import "Misc3DDeviceDriver.h"
#import <misckit/MiscString.h>
#import <misckit/MiscRtMatrix.h>
#import <remote/NXProxy.h>
@implementation BBRotator
- makeKeyAndOrderFront:sender
{
// If there hasnĀt been a Rotator-Panel yet. LetĀs do some init stuff.
if( !panel )
{
// To get the right Slider behaviour we will use our own slider class.
[BBSlider poseAs:[Slider class]];
if( [NXApp loadNibSection:"Rotator.nib" owner:self] == nil )
NXRunAlertPanel( NULL, "Couldn't load Rotator.nib",
"OK", NULL, NULL );
}
[panel makeKeyAndOrderFront:self];
return self;
}
- setTarget:anObject
{
target = anObject;
return self;
}
- setCamera:anObject
{
camera = anObject;
return self;
}
- check3DMouse:sender
{
// If there is a mouse and the preferences tell us to use a mouse...we will
// use it.
// We will check for the servers name and if we should use the mouse.
// If anything has changed we will try to reconnect.
// If the sender is 'nil' we will DISCONNECT !!!
// The mouse preferences are a property of the app itself!
id ourPrefs;
id thePortName;
BOOL useMouse;
ourPrefs = [[[NXApp delegate] preferences] findDefaultFor:NXApp];
useMouse = [ourPrefs use3DMouseIfPossible];
// ok now if we got 'nil' as the sender we will definitly NOT use the
// mouse too. In those cases we will simply do a nice cleanup.
if( sender == nil || useMouse == NO )
[self _disconnectFrom3DServer];
// Otherwise let's try to connect to the 3DDeviceServer.
// If we fail it should not matter...same as no mouse.
else
{
thePortName = [ourPrefs mouseServerPortName];
// if the desired portname and our currentName don't match
// we will have to clear all the old refs and setup the new server
// connection.
if( deviceServerName == nil ||
[thePortName compareTo:deviceServerName caseSensitive:NO] != 0 )
{
[self _disconnectFrom3DServer];
[self _connectTo3DServer:thePortName];
}
// otherwise we will free the old server name anyway.
// We will take the prefs Sting object as our own.
else [deviceServerName free];
deviceServerName = thePortName;
// Now if we really have a valid server and a refernce to the mouse
// ...we will tell the mouse to use as as its target.
if( deviceServer && mouse3D )
{
[mouse3D setProtocolForProxy:
@protocol(Misc3DDeviceDriverProtocol)];
[mouse3D setTarget:self];
[mouse3D enableEvents];
[mouse3D setUseExternalSync:YES];
}
// puuuh. Well this get a little boring right now
// but what we have to do is to disconnect again if we did not manage
// to form a connection. Makes reconnecting with the same names
// possible.
else [self _disconnectFrom3DServer];
}
// Looks like we got it all...
return self;
}
- _connectTo3DServer:thePortName
{
// Prepare the host entries and other names and establish
// the connection..
id sepString;
id theHostName;
sepString = [MiscString newWithString:"/"];
theHostName = [thePortName subStringLeft:sepString];
// DO don't accept the 'localhost' as a valid hostname..so we have to take
// care of that.
if( [theHostName casecmp:"localhost"] == 0 )
[theHostName setStringValue:""];
deviceServer = [NXConnection connectToName:[thePortName stringValue]
onHost:[theHostName stringValueAndFree]];
ourPort = [deviceServer connectionForProxy];
[ourPort runFromAppKit];
[sepString free];
mouse3D = [deviceServer mouse];
return self;
}
- _disconnectFrom3DServer
{
// We will completely disconnect from the 3DmouseServer.
if( mouse3D )
{
[mouse3D setTarget:nil];
// [mouse3D free]; I don't know if this is wise...
// we don't own that object.
}
mouse3D = nil;
// if( deviceServer ) [deviceServer free] I'm not sure about freeing...
deviceServer = nil;
// if( ourPort ) [ourPort free]; we shouldn't free anything..
ourPort = nil;
if( deviceServerName ) [deviceServerName free];
deviceServerName = nil;
return self;
}
- xRotation:sender;
{
float angle;
RtPoint xAxis = {1.0,0.0,0.0};
angle = [sender floatValue] - lastSliderValue;
[rotValue setIntValue:[sender intValue]];
if( angle != 0.0 )
{
[target rotateAngle:angle axis:xAxis];
[camera display];
NXPing();
}
lastSliderValue = [sender floatValue];
return self;
}
- yRotation:sender;
{
float angle;
RtPoint yAxis = { 0.0, 1.0, 0.0 };
angle = [sender floatValue] - lastSliderValue;
[rotValue setIntValue:[sender intValue]];
if( angle != 0.0 )
{
[target rotateAngle:angle axis:yAxis];
[camera display];
NXPing();
}
lastSliderValue = [sender floatValue];
return self;
}
- zRotation:sender;
{
float angle;
RtPoint zAxis = { 0.0, 0.0, 1.0 };
angle = [sender floatValue] - lastSliderValue;
[rotValue setIntValue:[sender intValue]];
if( angle != 0.0 )
{
[target rotateAngle:angle axis:zAxis];
[camera display];
NXPing();
}
lastSliderValue = [sender floatValue];
return self;
}
- xTranslation:sender
{
// xTranslation will move our camera AND its toPoint across the xAxis.
RtPoint fromPoint;
RtPoint toPoint;
float angle;
float delta;
delta = ( [sender floatValue] - lastSliderValue );
[transValue setIntValue:[sender intValue]];
if( delta != 0.0 )
{
[camera getEyeAt:&fromPoint toward:&toPoint roll:&angle];
fromPoint[0] -= delta;
toPoint[0] -= delta;
[camera setEyeAt:fromPoint toward:toPoint roll:angle];
[camera display];
NXPing();
}
lastSliderValue = [sender floatValue];
return self;
}
- yTranslation:sender
{
// yTranslation will move our camera AND its toPoint across the yAxis.
RtPoint fromPoint;
RtPoint toPoint;
float angle;
float delta;
delta = ( [sender floatValue] - lastSliderValue );
[transValue setIntValue:[sender intValue]];
if( delta != 0.0 )
{
[camera getEyeAt:&fromPoint toward:&toPoint roll:&angle];
fromPoint[1] -= delta;
toPoint[1] -= delta;
[camera setEyeAt:fromPoint toward:toPoint roll:angle];
[camera display];
NXPing();
}
lastSliderValue = [sender floatValue];
return self;
}
- zTranslation:sender
{
// zTranslation will ONLY move our camera across the zAxis.
// So our focus will always remain at z=0 !!!
RtPoint fromPoint;
RtPoint toPoint;
float angle;
float delta;
delta = ( [sender floatValue] - lastSliderValue );
[transValue setIntValue:[sender intValue]];
if( delta != 0.0 )
{
[camera getEyeAt:&fromPoint toward:&toPoint roll:&angle];
fromPoint[2] -= delta;
[camera setEyeAt:fromPoint toward:toPoint roll:angle];
[camera display];
NXPing();
}
lastSliderValue = [sender floatValue];
return self;
}
- benchMark:sender
{
// We will use this method to trigger a redraw and then to estimate the
// time consumpt.
struct timezone tzone;
struct timeval realtime1;
struct timeval realtime2;
double myTime;
gettimeofday(&realtime1,&tzone);
[camera display];
NXPing();
gettimeofday(&realtime2,&tzone);
myTime = ((realtime2.tv_sec + realtime2.tv_usec / 1.0E6 ) -
(realtime1.tv_sec + realtime1.tv_usec / 1.0E6 ));
[benchTime setDoubleValue:myTime];
return self;
}
- fastStyle:sender
{
[self transformationWillStart:self];
return self;
}
- niceStyle:sender
{
[self transformationDidEnd:self];
return self;
}
/*
* Here comes the part where we implement the Misc3DMouseTarget protocol.
* Together with the connectTo3DMouse method it provides the whole bunch of
* code necessary to support any kind of 3D mouse.
*/
- (BOOL)worldIsRightHanded
{
return NO;
}
- (oneway void)transformationEvent:(bycopy id)aMatrix
{
// This method tries to aply the 3dmouse matrix to our data.
// This method should ONLY be use by the 3DDriver mouse !!
// Otherwise there might be problems with the sync. (I could solve
// that by using som kind of internal flag...but..this object will need
// a complete redesign anyway..)
//
// Only the rotation will be applied to the mol. Translation will be
// extracted and set seperatly at our camera.
// This is not perfect in any way. But it should be enough for a while.
//
// There is a problem when move the camera to the positiv z area.
// The the transformation won't fit the reality. This is because of our
// 'hacked' rotation stuff.
// I should really apply the rotation to the world this camera does see.
// This is not a bug in the 3DDeviceServer. Remember that you always to
// transformation from the cameras point of view!! And the camera should be
// on the negativ z-axis in a left-handed world; and on the positiv z-axis
// in a right handed world!!
RtMatrix m;
float x, y, z;
RtPoint fromPoint;
RtPoint toPoint;
float angle;
[aMatrix getTransformMatrix:m];
x = -m[3][0];
y = -m[3][1];
z = -m[3][2]; // This is because the camera has to move differently
// to show us the intended move of the object!
// This will change later.
m[3][0] = 0;
m[3][1] = 0;
m[3][2] = 0;
if( x != 0 || y != 0 || z != 0 )
{
[camera getEyeAt:&fromPoint toward:&toPoint roll:&angle];
fromPoint[0] += x;
fromPoint[1] += y;
fromPoint[2] += z;
toPoint[0] += x;
toPoint[1] += y;
[camera setEyeAt:fromPoint toward:toPoint roll:angle];
}
if( [aMatrix doesRotate] )
[target concatTransformMatrix:m premultiply:NO];
[camera display];
NXPing();
[mouse3D syncEvents];
return;
}
- (oneway void)transformationWillStart:sender
{
[[camera worldShape] rotationStyleOn:YES];
// [camera setHider:N3D_InOrderRendering];
[camera setHider:N3D_HiddenRendering];
[camera display];
NXPing();
return;
}
- (oneway void)transformationDidEnd:sender
{
// If the sender is one of our sliders we will reset it to the
// Zero point.
if( sender == aSlider ||
sender == bSlider ||
sender == cSlider )
{
[sender setFloatValue:0];
[rotValue setIntValue:0];
lastSliderValue = 0;
}
else if( sender == xSlider ||
sender == ySlider ||
sender == zSlider )
{
[sender setFloatValue:0];
[transValue setIntValue:0];
lastSliderValue = 0;
}
[[camera worldShape] rotationStyleOn:NO];
[camera setHider:N3D_HiddenRendering];
[camera display];
NXPing();
return;
}
- (oneway void)keyEvent:(char *)theKeys
{
return;
}
@end
/*
* History: 21.11.94 Programmed around NeXT bug with the DO not accepting
* localhost as a useful machine name..
*
* 17.11.94 Moved the 3DMosue support right here where it belongs.
*
* 07.05.94 Switched to BB..., and moved the PDO part to the main
* AppManager.
*
* 12.04.94 Included 3DDeviceServer support.
*
* 15.01.94 Added the zoom mode.
*
* 22.12.93 First code written.
*
*
* Bugs: - Well not really a bug. But there might be problems when check3DMouse
* is called when the program is not the active app. Which might cause
* to stop events being deliverd to the currently active app.
*/These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.