-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 9109c40
Showing
57 changed files
with
11,667 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 ); | ||
} | ||
} | ||
} |
Oops, something went wrong.