/*	SpatialView.m - Display 3D image
 *	Copyright (C) 1993 Corona Design, Inc. All rights reserved.
 *
 *	Abstract
 *		Manages the dynamic display of a 3D scene.
 *
 *	RCS path: 
 *		$Source: /Users/pkron/Projects/voxel/Pyramid/RCS/SpatialView.m,v $
 *	Modified: $Date: 93/09/15 12:35:17 $ by $Author: pkron $
 *	Current State: $State: Exp $ locked by $Locker:  $
 */

#import 	"SpatialView.h"

#import		"TransformController.h"
#import		<math.h>



#define	SQRT2	1.414214	
#define	SQRT3	1.732051
#define	SQRT6	(SQRT2*SQRT3)

static POINT	moon3D = { .3, .3, .7, 1};
	
@implementation SpatialView


- initFrame: (const NXRect *)newFrame
	{
	float	drawSize = 1.;
	
	[super initFrame: newFrame];

								// draw in a unit space with
								// origin at center	
	[self setDrawSize: drawSize : drawSize];
	[self translate: drawSize/2 : drawSize/2];
	clip = bounds;

								// initial (dummy) transformation
	transform = allocIdentity();
	return( self);
	}
	
- free
	{
	freeMatrix( transform);
	return( [super free]);
	}


#define	DISTANCE	([distance floatValue]+1)

								// react to change in viewing angle
- changePerspective: sender
	{
	[self display];
	return( self);
	}
	

								// draw circle about the moon center
- drawMoon: (NXRect *)moonClip;
	{
	float	radius;

	if ( [showMoon floatValue] )
		{
		radius = .1/(moon[2]);
		project( &moon);
		
		PSsetgray( .8);
		PSmoveto( moon[0], moon[1]);
		PSarc( moon[0], moon[1], radius, 0, 360);
		PSclosepath();
		PSfill();
		
		NXSetRect( moonClip, moon[0] - radius, moon[1] - radius, 
					2*radius, 2*radius
					);
		}
		
	return( self);
	}	
	

- drawSelf: (const NXRect *)rects : (int)count
	{
	BOOL	moonDrawn = NO;
	POINT	origin, zenith, reflectedMoon;
	NXRect	tmpRect;
	
	[super drawSelf: rects : count];
	
								// erase last image
	PSsetrgbcolor( 1, 1, .6);	// pale yellow
	NXRectFill( &clip);

	transform = [transformController transform];

								// map moon to view space
	moon[0] = moon3D[0];	
	moon[1] = moon3D[1];	
	moon[2] = moon3D[2];	
	moon[3] = moon3D[3];
	map( transform, &moon);	

								// cheap hidden moon algorithm
								// doesn't work completely
	origin[0] = 0;
	origin[1] = 0;
	origin[2] = -1;
	origin[3] = 1;
	zenith[0] = 0;
	zenith[1] = 0;
	zenith[2] = 0;
	zenith[3] = 1;
	reflectedMoon[0] = -moon3D[0];
	reflectedMoon[1] = -moon3D[1];
	reflectedMoon[2] = moon3D[2];
	reflectedMoon[3] = 1;
	map( transform, &origin);	
	map( transform, &zenith);	
	map( transform, &reflectedMoon);	

								// if view is from below xy plane
								// or moon is behind its z-axix projection	
	if ( origin[2] LT zenith[2] || moon[2] GT reflectedMoon[2] )
		{
		[self drawMoon: &tmpRect];
		moonDrawn = YES;
		}

								// draw the scene model
	[model drawModel: transform : &clip];

								// if moon in front of view plane	
	if ( !moonDrawn )
		[self drawMoon: &tmpRect];

	if ( 
			[showVanishingPoints intValue] 
			&& [model respondsTo: @selector( drawVanishingPoints::)]
			)
		[model drawVanishingPoints: transform : &clip];
		
	NXUnionRect( &tmpRect, &clip);	
	return( self);
	}
	

								// select a new model for scene
- useModel: anObject
	{
	[model free];
	model = anObject;
	clip = bounds;
	[self display];

	return( self);
	}
	

@end

#ifdef	_LOG
/*
 *	$Log:	SpatialView.m,v $
Revision 1.1  93/09/15  12:35:17  pkron
Created.

 */
#endif		
