Skip to content

Commit

Permalink
Initial checkin
Browse files Browse the repository at this point in the history
  • Loading branch information
benvanik committed May 26, 2009
0 parents commit 9109c40
Show file tree
Hide file tree
Showing 57 changed files with 11,667 additions and 0 deletions.
254 changes: 254 additions & 0 deletions Razmotron.Silverlight/Camera.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Razmotron
{
public class Camera
{
public float NearZ = 0.1f;
public float FarZ = 100.0f;

public Matrix Projection;
public Matrix View;
public Matrix ViewProjection;

public Vector3 Position;
public Vector3 Angles; // yaw, pitch, roll

public float Acceleration = 16.0f;
public Vector3 PositionImpulse;
public Vector3 PositionVelocity;
public Vector3 AngularImpulse;
public Vector3 AngularVelocity;

private DateTime LastUpdate = DateTime.Now;

public void SetPerspective( float fovY, float aspectRatio )
{
float f = 1.0f / ( float )Math.Tan( fovY / 2.0f );
Projection = new Matrix(
f * aspectRatio, 0, 0, 0,
0, f, 0, 0,
0, 0, FarZ / ( NearZ - FarZ ), 1 / 100.0f,
0, 0, ( NearZ * FarZ ) / ( NearZ - FarZ ), 0 );
}

public void Calculate()
{
DateTime sample = DateTime.Now;
float delta = ( float )( sample - LastUpdate ).TotalSeconds;
LastUpdate = sample;

Quaternion rotation;
Quaternion.CreateFromYawPitchRoll( Angles.X, Angles.Y, Angles.Z, out rotation );
Vector3 normal = PositionVelocity * delta;
if( normal.LengthSquared != 0.0f )
normal.Normalize();
Vector3 ahead;
Vector3.Transform( ref normal, ref rotation, out ahead );
Vector3.Multiply( ref ahead, delta, out ahead );
Position += ahead;
Angles += ( AngularVelocity * delta );

this.ApplyPhysics( delta );

// NOTE: math is inverse!
Matrix translation = Matrix.Identity;
translation.M41 = -Position.X;
translation.M42 = -Position.Y;
translation.M43 = -Position.Z;
Matrix rotx = Matrix.Identity;
rotx.M22 = ( float )Math.Cos( Angles.Y );
rotx.M23 = -( float )Math.Sin( Angles.Y );
rotx.M32 = ( float )Math.Sin( Angles.Y );
rotx.M33 = ( float )Math.Cos( Angles.Y );
Matrix roty = Matrix.Identity;
roty.M11 = ( float )Math.Cos( Angles.X );
roty.M13 = ( float )Math.Sin( Angles.X );
roty.M31 = -( float )Math.Sin( Angles.X );
roty.M33 = ( float )Math.Cos( Angles.X );
Matrix rotz = Matrix.Identity;
rotz.M11 = ( float )Math.Cos( Angles.Z );
rotz.M12 = -( float )Math.Sin( Angles.Z );
rotz.M21 = ( float )Math.Sin( Angles.Z );
rotz.M22 = ( float )Math.Cos( Angles.Z );

// view = translation * rotx * roty * rotz
Matrix temp;
Matrix.Multiply( ref translation, ref roty, out View );
Matrix.Multiply( ref View, ref rotx, out temp );
Matrix.Multiply( ref temp, ref rotz, out View );

Matrix.Multiply( ref View, ref Projection, out ViewProjection );
}

private void ApplyPhysics( float delta )
{
Vector3 direction = new Vector3( 1, 1, 1 );

Vector3 velocityDelta;
Vector3.Multiply( ref PositionImpulse, ( Acceleration * delta ), out velocityDelta );
Vector3.Add( ref PositionVelocity, ref velocityDelta, out PositionVelocity );
PositionVelocity = MathHelper.Clamp( PositionVelocity, new Vector3( -10, -10, -10 ), new Vector3( 10, 10, 10 ) );
PositionVelocity = this.Decelerate( PositionImpulse, PositionVelocity, Acceleration, delta );

Vector3.Multiply( ref AngularImpulse, ( Acceleration * delta ), out velocityDelta );
Vector3.Add( ref AngularVelocity, ref velocityDelta, out AngularVelocity );
AngularVelocity = MathHelper.Clamp( AngularVelocity, new Vector3( -3, -3, -3 ), new Vector3( 3, 3, 3 ) );
AngularVelocity = this.Decelerate( AngularImpulse, AngularVelocity, Acceleration, delta );
}

private Vector3 Decelerate( Vector3 impulse, Vector3 velocity, float acceleration, float delta )
{
Vector3 newVelocity = velocity;
if( impulse.X == 0.0f )
{
if( velocity.X > 0.0f )
{
newVelocity.X -= acceleration * delta;
if( newVelocity.X < 0.0f ) newVelocity.X = 0.0f;
}
else
{
newVelocity.X += acceleration * delta;
if( newVelocity.X > 0.0f ) newVelocity.X = 0.0f;
}
}
if( impulse.Y == 0.0f )
{
if( velocity.Y > 0.0f )
{
newVelocity.Y -= acceleration * delta;
if( newVelocity.Y < 0.0f ) newVelocity.Y = 0.0f;
}
else
{
newVelocity.Y += acceleration * delta;
if( newVelocity.Y > 0.0f ) newVelocity.Y = 0.0f;
}
}
if( impulse.Z == 0.0f )
{
if( velocity.Z > 0.0f )
{
newVelocity.Z -= acceleration * delta;
if( newVelocity.Z < 0.0f ) newVelocity.Z = 0.0f;
}
else
{
newVelocity.Z += acceleration * delta;
if( newVelocity.Z > 0.0f ) newVelocity.Z = 0.0f;
}
}
return newVelocity;
}

public bool HandleKeyDown( Key key, int platformCode )
{
bool handled = false;
switch( key )
{
case Key.A:
PositionImpulse.X = 1.0f;
handled = true;
break;
case Key.D:
PositionImpulse.X = -1.0f;
handled = true;
break;
case Key.S:
PositionImpulse.Z = -1.0f;
handled = true;
break;
case Key.W:
PositionImpulse.Z = 1.0f;
handled = true;
break;
case Key.Z:
PositionImpulse.Y = -1.0f;
handled = true;
break;
case Key.Q:
PositionImpulse.Y = 1.0f;
handled = true;
break;

case Key.Left:
AngularImpulse.X = 1.0f;
handled = true;
break;
case Key.Right:
AngularImpulse.X = -1.0f;
handled = true;
break;
case Key.Down:
AngularImpulse.Y = 1.0f;
handled = true;
break;
case Key.Up:
AngularImpulse.Y = -1.0f;
handled = true;
break;
}
return handled;
}

public bool HandleKeyUp( Key key, int platformCode )
{
bool handled = false;
switch( key )
{
case Key.A:
PositionImpulse.X = 0.0f;
handled = true;
break;
case Key.D:
PositionImpulse.X = 0.0f;
handled = true;
break;
case Key.S:
PositionImpulse.Z = 0.0f;
handled = true;
break;
case Key.W:
PositionImpulse.Z = 0.0f;
handled = true;
break;
case Key.Z:
PositionImpulse.Y = 0.0f;
handled = true;
break;
case Key.Q:
PositionImpulse.Y = 0.0f;
handled = true;
break;

case Key.Left:
AngularImpulse.X = 0.0f;
handled = true;
break;
case Key.Right:
AngularImpulse.X = 0.0f;
handled = true;
break;
case Key.Down:
AngularImpulse.Y = 0.0f;
handled = true;
break;
case Key.Up:
AngularImpulse.Y = 0.0f;
handled = true;
break;
}
return handled;
}
}
}
128 changes: 128 additions & 0 deletions Razmotron.Silverlight/Controls/RenderSurfaceControl.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Razmotron.Rasterization;
using System.Threading;

namespace Razmotron.Controls
{
public class RenderSurfaceControl : UserControl
{
private Image _image;
#if WPF
private WriteableBitmap _bitmap;
#else
private BitmapImage _bitmap;
#endif
private RasterBuffer _buffer;

public RasterBuffer RasterBuffer { get { return _buffer; } }

public RenderSurfaceControl()
{
_image = new Image();
_image.IsHitTestVisible = false;
#if WPF
_bitmap = null;
#else
_bitmap = new BitmapImage();
_image.Source = _bitmap;
#endif
this.Content = _image;

this.Loaded += new RoutedEventHandler( RenderSurfaceControl_Loaded );
}

#region Dependency Properties

public ColorMode ColorMode
{
get { return ( ColorMode )GetValue( ColorModeProperty ); }
set { SetValue( ColorModeProperty, value ); }
}
public static readonly DependencyProperty ColorModeProperty =
DependencyProperty.Register( "ColorMode", typeof( ColorMode ), typeof( RenderSurfaceControl ), new PropertyMetadata( ColorMode.RGB, BufferPropertyChanged ) );

private static void BufferPropertyChanged( DependencyObject obj, DependencyPropertyChangedEventArgs e )
{
RenderSurfaceControl control = obj as RenderSurfaceControl;
control.ResetBuffer( ( int )control.Width, ( int )control.Height );
}

#endregion

private void RenderSurfaceControl_Loaded( object sender, RoutedEventArgs e )
{
}

private void ResetBuffer( int width, int height )
{
if( _buffer == null )
_buffer = new RasterBuffer( this.ColorMode );

// Save palette
byte[] palette = _buffer.GetPalette();

// Perform resize
bool didChange = _buffer.Resize( width, height );

// Restore palette (if needed)
if( didChange == true )
_buffer.SetPalette( palette );

#if WPF
_bitmap = new WriteableBitmap( _buffer.Width, _buffer.Height, 72, 72, PixelFormats.Rgb24, null );
_image.Source = _bitmap;
#endif
}

public void BeginUpdate()
{
if( _buffer == null )
this.ResetBuffer( ( int )this.Width, ( int )this.Height );
}

public void EndUpdate()
{
if( _buffer == null )
return;
#if WPF
// NOT efficient - would be better to have the rasterbuffer write directly into the backbuffer of the bitmap
PixelBuffer pb;
_buffer.LockPixels( out pb );
_bitmap.Lock();
unsafe
{
fixed( byte* ptr = &pb.Buffer[ pb.Offset ] )
{
for( int y = 0; y < pb.Height; y++ )
{
int sourceOffset = ( y * pb.Stride );
_bitmap.WritePixels( new Int32Rect( 0, y, pb.Width, 1 ), new IntPtr( ptr + sourceOffset ), pb.Width * pb.BytesPerPixel, pb.Width * pb.BytesPerPixel );
}
}
}
_bitmap.Unlock();
_buffer.UnlockPixels();
#else
_bitmap.SetSource( _buffer.GetStream() );
#endif
}

protected override Size ArrangeOverride( Size finalSize )
{
this.ResetBuffer( ( int )finalSize.Width, ( int )finalSize.Height );
return base.ArrangeOverride( finalSize );
}
}
}
Loading

0 comments on commit 9109c40

Please sign in to comment.