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.