Приз за первое место:
– годовая подписка MSDN Premium + Visual Studio Team System 2008 Team Suite
.jpg)
Подробности можно прочесть здесь ...
using System;
namespace TestObjectInterface
{
class Program
{
static Unit[] unit;
static object[] unitobj;
static iUnit[] uniti;
static int count;
static void Main(string[] args)
{
count = 10000000;
unit = new Unit[count];
unitobj = new object[count];
uniti = new iUnit[count];
Init();
double tf = TestFields();
double tp = TestProperties();
double tfo = TestFieldsObject();
double tpo = TestPropertiesObject();
double tpi = TestPropertiesInterface();
Console.WriteLine("testFields = "
+ tf.ToString() + " mc, k = 1");
Console.WriteLine("testProperties = "
+ tp.ToString() + " mc, k = "
+ (tp / tf).ToString());
Console.WriteLine("testFieldsObject = "
+ tfo.ToString() + " mc, k = "
+ (tfo / tf).ToString());
Console.WriteLine("testPropertiesObject = "
+ tpo.ToString() + " mc, k = "
+ (tpo / tf).ToString());
Console.WriteLine("testPropertiesInterface = "
+ tpi.ToString() + " mc, k = "
+ (tpi / tf).ToString());
//Console.ReadKey();
}
static void Init()
{
for (int i = 0; i < count; i++)
{
unit[i] = new Unit(i, i * 2);
uniti[i] = (iUnit)unit[i];
unitobj[i] = (object)unit[i];
}
}
static double TestFields()
{
DateTime dtStart = DateTime.Now;
int n;
for (int i = 0; i < count; i++)
{
n = unit[i].x + unit[i].y; // 0
n = unit[i].x + unit[i].y; // 1
n = unit[i].x + unit[i].y; // 2
n = unit[i].x + unit[i].y; // 3
n = unit[i].x + unit[i].y; // 4
n = unit[i].x + unit[i].y; // 5
n = unit[i].x + unit[i].y; // 6
n = unit[i].x + unit[i].y; // 7
n = unit[i].x + unit[i].y; // 8
n = unit[i].x + unit[i].y; // 9
}
DateTime dtEnd = DateTime.Now;
return (dtEnd - dtStart).TotalMilliseconds;
}
static double TestProperties()
{
DateTime dtStart = DateTime.Now;
int n;
for (int i = 0; i < count; i++)
{
n = unit[i].X + unit[i].Y; // 0
n = unit[i].X + unit[i].Y; // 1
n = unit[i].X + unit[i].Y; // 2
n = unit[i].X + unit[i].Y; // 3
n = unit[i].X + unit[i].Y; // 4
n = unit[i].X + unit[i].Y; // 5
n = unit[i].X + unit[i].Y; // 6
n = unit[i].X + unit[i].Y; // 7
n = unit[i].X + unit[i].Y; // 8
n = unit[i].X + unit[i].Y; // 9
}
DateTime dtEnd = DateTime.Now;
return (dtEnd - dtStart).TotalMilliseconds;
}
static double TestFieldsObject()
{
DateTime dtStart = DateTime.Now;
int n;
for (int i = 0; i < count; i++)
{
n = ((Unit)unitobj[i]).x + ((Unit)unitobj[i]).x; // 0
n = ((Unit)unitobj[i]).x + ((Unit)unitobj[i]).x; // 1
n = ((Unit)unitobj[i]).x + ((Unit)unitobj[i]).x; // 2
n = ((Unit)unitobj[i]).x + ((Unit)unitobj[i]).x; // 3
n = ((Unit)unitobj[i]).x + ((Unit)unitobj[i]).x; // 4
n = ((Unit)unitobj[i]).x + ((Unit)unitobj[i]).x; // 5
n = ((Unit)unitobj[i]).x + ((Unit)unitobj[i]).x; // 6
n = ((Unit)unitobj[i]).x + ((Unit)unitobj[i]).x; // 7
n = ((Unit)unitobj[i]).x + ((Unit)unitobj[i]).x; // 8
n = ((Unit)unitobj[i]).x + ((Unit)unitobj[i]).x; // 9
}
DateTime dtEnd = DateTime.Now;
return (dtEnd - dtStart).TotalMilliseconds;
}
static double TestPropertiesObject()
{
DateTime dtStart = DateTime.Now;
int n;
for (int i = 0; i < count; i++)
{
n = ((Unit)unitobj[i]).X + ((Unit)unitobj[i]).Y; // 0
n = ((Unit)unitobj[i]).X + ((Unit)unitobj[i]).Y; // 1
n = ((Unit)unitobj[i]).X + ((Unit)unitobj[i]).Y; // 2
n = ((Unit)unitobj[i]).X + ((Unit)unitobj[i]).Y; // 3
n = ((Unit)unitobj[i]).X + ((Unit)unitobj[i]).Y; // 4
n = ((Unit)unitobj[i]).X + ((Unit)unitobj[i]).Y; // 5
n = ((Unit)unitobj[i]).X + ((Unit)unitobj[i]).Y; // 6
n = ((Unit)unitobj[i]).X + ((Unit)unitobj[i]).Y; // 7
n = ((Unit)unitobj[i]).X + ((Unit)unitobj[i]).Y; // 8
n = ((Unit)unitobj[i]).X + ((Unit)unitobj[i]).Y; // 9
}
DateTime dtEnd = DateTime.Now;
return (dtEnd - dtStart).TotalMilliseconds;
}
static double TestPropertiesInterface()
{
DateTime dtStart = DateTime.Now;
int n;
for (int i = 0; i < count; i++)
{
n = uniti[i].iX + uniti[i].iY; // 0
n = uniti[i].iX + uniti[i].iY; // 1
n = uniti[i].iX + uniti[i].iY; // 2
n = uniti[i].iX + uniti[i].iY; // 3
n = uniti[i].iX + uniti[i].iY; // 4
n = uniti[i].iX + uniti[i].iY; // 5
n = uniti[i].iX + uniti[i].iY; // 6
n = uniti[i].iX + uniti[i].iY; // 7
n = uniti[i].iX + uniti[i].iY; // 8
n = uniti[i].iX + uniti[i].iY; // 9
}
DateTime dtEnd = DateTime.Now;
return (dtEnd - dtStart).TotalMilliseconds;
}
}
interface iUnit
{
int iX {get;}
int iY {get;}
}
public class Unit : iUnit
{
public int x;
public int X { get { return x; } }
int iUnit.iX { get { return x; } }
public int y;
public int Y { get { return y; } }
int iUnit.iY { get { return y; } }
public Unit(int inX, int inY)
{
x = inX;
y = inY;
}
}
}
public struct Vector3
{
public float X;
public float Y;
public float Z;
...
private static Vector3 _one;
public static Vector3 One
{
get
{
return _one;
}
}
...
public Vector3(float x, float y, float z)
{
this.X = x;
this.Y = y;
this.Z = z;
}
...
static Vector3()
{
...
_one = new Vector3(1f, 1f, 1f);
...
}
}
using System;
using Microsoft.Xna.Framework;
namespace TestFields
{
class Program
{
static int count;
static void Main(string[] args)
{
count = 10000000;
Console.WriteLine("testStandartVector3 = " +
TestStandartVector3().ToString() +
" mc");
Console.WriteLine("testMyVector3 = " +
TestMyVector3().ToString() +
" mc");
}
static double TestStandartVector3()
{
DateTime dtStart = DateTime.Now;
Vector3 vec;
for (int i = 0; i < count; i++)
{
vec = Vector3.One; // 0
vec = Vector3.One; // 1
vec = Vector3.One; // 2
vec = Vector3.One; // 3
vec = Vector3.One; // 4
vec = Vector3.One; // 5
vec = Vector3.One; // 6
vec = Vector3.One; // 7
vec = Vector3.One; // 8
vec = Vector3.One; // 9
}
DateTime dtEnd = DateTime.Now;
return (dtEnd - dtStart).TotalMilliseconds;
}
static double TestMyVector3()
{
DateTime dtStart = DateTime.Now;
gVector3 vec;
for (int i = 0; i < count; i++)
{
vec = gVector3.One; // 0
vec = gVector3.One; // 1
vec = gVector3.One; // 2
vec = gVector3.One; // 3
vec = gVector3.One; // 4
vec = gVector3.One; // 5
vec = gVector3.One; // 6
vec = gVector3.One; // 7
vec = gVector3.One; // 8
vec = gVector3.One; // 9
}
DateTime dtEnd = DateTime.Now;
return (dtEnd - dtStart).TotalMilliseconds;
}
}
public struct gVector3
{
public float X;
public float Y;
public float Z;
public static readonly gVector3 One;
public gVector3(float x, float y, float z)
{
X = x;
Y = y;
Z = z;
}
static gVector3()
{
One = new gVector3(1, 1, 1);
}
}
}
using System;
using Microsoft.Xna.Framework;
namespace Test
{
public class TestMath2
{
public TestMath2()
{
// вершины треугольника
Vector3 A = new Vector3(1f, -1f, 0f);
Vector3 B = new Vector3(3f, -4f, 0f);
Vector3 C = new Vector3(5f, -1f, 0f);
// текстурные координаты вершин
Vector2 tA = new Vector2(1f, 1f);
Vector2 tB = new Vector2(3f, 4f);
Vector2 tC = new Vector2(5f, 1f);
// точка в плоскости треугольника ограниченная его гранями
Vector3 D = new Vector3(3f, -2f, 0f);
// B
// .
// / \
// / \
// / \
// / .D \
// / \
// .-----------.
// A C
// расчет
Vector2 tD = CalculationDuvFromABC( A, tA,
B, tB,
C, tC,
D);
}
///
/// Нахождение текстурных координат точки D
///
/// Позиция точки A
/// Текстурные координаты точки A
/// Позиция точки B
/// Текстурные координаты точки B
/// Позиция точки C
/// Текстурные координаты точки C
/// Позиция точки D
/// Текстурные координаты точки D
private Vector2 CalculationDuvFromABC( Vector3 A, Vector2 tA,
Vector3 B, Vector2 tB,
Vector3 C, Vector2 tC,
Vector3 D)
{
Vector3 E = PointOfLinesCrossing(A, B, C, D);
float kAEC = (E - A).Length() / (C - A).Length();
Vector2 tE = tA + (tC - tA) * kAEC;
float kBDE = (D - B).Length() / (E - B).Length();
return (Vector2)(tB + (tE - tB) * kBDE);
}
///
/// Нахождение позиции точки пересечения двух прямых,
/// проходящих через точки AC и BD
///
/// Позиция точки A
/// Позиция точки B
/// Позиция точки C
/// Позиция точки D
/// Позиция точки E, полученной пересечением двух прямых AC и BD
private Vector3 PointOfLinesCrossing(Vector3 A, Vector3 B, Vector3 C, Vector3 D)
{
Vector3 vecAC = C - A;
Vector3 vecBD = D - B;
float Tac = Math.Abs( Matrix2x2Determinant( vecBD.X, A.X - B.X,
vecBD.Y, A.Y - B.Y)
/
Matrix2x2Determinant( vecBD.X, vecAC.X,
vecBD.Y, vecAC.Y));
return Vector3.Add(A, Vector3.Multiply(vecAC, Tac));
}
///
/// Определитель матрицы 2х2
///
/// a00
/// a01
/// a10
/// a11
/// Определитель
private float Matrix2x2Determinant( float a00, float a01,
float a10, float a11)
{
return (float)(a00 * a11 - a10 * a01);
}
}
}
namespace gEngine.gProgressiveLandscape
{
public struct gplVertexPositionNormalTexture
{
public Vector3 Position;
public Vector3 PositionGeomorphing;
public Vector3 Normal;
public Vector3 NormalGeomorphing;
public Vector2 TextureCoordinate;
public float IndexDetailedLayer;
public static readonly VertexElement[] VertexElements;
static gplVertexPositionNormalTexture()
{
VertexElements = new VertexElement[6];
short offset = 0;
// Position
VertexElements[0] = new VertexElement(0, offset,
VertexElementFormat.Vector3,
VertexElementMethod.Default,
VertexElementUsage.Position, 0);
offset += (short)Marshal.SizeOf(new Vector3());
// PositionGeomorphing
VertexElements[1] = new VertexElement(0, offset,
VertexElementFormat.Vector3,
VertexElementMethod.Default,
VertexElementUsage.Position, 1); // !
offset += (short)Marshal.SizeOf(new Vector3());
// Normal
VertexElements[2] = new VertexElement(0, offset,
VertexElementFormat.Vector3,
VertexElementMethod.Default,
VertexElementUsage.Normal, 0);
offset += (short)Marshal.SizeOf(new Vector3());
// NormalGeomorphing
VertexElements[3] = new VertexElement(0, offset,
VertexElementFormat.Vector3,
VertexElementMethod.Default,
VertexElementUsage.Normal, 1); // !
offset += (short)Marshal.SizeOf(new Vector3());
// TextureCoordinate
VertexElements[4] = new VertexElement(0, offset,
VertexElementFormat.Vector2,
VertexElementMethod.Default,
VertexElementUsage.TextureCoordinate, 0);
offset += (short)Marshal.SizeOf(new Vector2());
// NamberDetailedLayer
VertexElements[5] = new VertexElement(0, offset,
VertexElementFormat.Single,
VertexElementMethod.Default,
VertexElementUsage.TextureCoordinate, 1); // !
}
public gplVertexPositionNormalTexture( Vector3 position,
Vector3 positionGeomorphing,
Vector3 normal,
Vector3 normalGeomorphing,
Vector2 textureCoordinate,
float indexDetailedLayer)
{
this.Position = position;
this.PositionGeomorphing = positionGeomorphing;
this.Normal = normal;
this.NormalGeomorphing = normalGeomorphing;
this.TextureCoordinate = textureCoordinate;
this.IndexDetailedLayer = indexDetailedLayer;
}
public static int SizeInBytes
{
get
{
return (int)( Marshal.SizeOf(new Vector3()) +
Marshal.SizeOf(new Vector3()) +
Marshal.SizeOf(new Vector3()) +
Marshal.SizeOf(new Vector3()) +
Marshal.SizeOf(new Vector2()) +
sizeof(float));
}
}
}
}
float4x4 matWorld : WORLD;
float4x4 matWVP : WORLDVIEWPROJECTION;
float3 vLightPosition;
float3 vEyePosition;
float layerRadius[7];
float fogBegin = 200.0f;
float fogEnd = 400.0f;
struct VS_INPUT
{
float3 Position : POSITION0;
float3 PositionGeomorphing : POSITION1;
float3 Normal : NORMAL0;
float3 NormalGeomorphing : NORMAL1;
float2 Texcoord : TEXCOORD0;
float IndexDetailedLayer : TEXCOORD1;
};
struct VS_OUTPUT
{
float4 Position : POSITION0;
float2 Texcoord : TEXCOORD0;
float3 Light : TEXCOORD1;
float3 Normal : TEXCOORD2;
float Fog : TEXCOORD3;
};
VS_OUTPUT VS(VS_INPUT In)
{
VS_OUTPUT Out = ( VS_OUTPUT ) 0;
float Distance = length ( In.Position - vEyePosition );
float K = clamp ((( Distance / layerRadius[In.IndexDetailedLayer] - 0.5f ) * 2.0f ), 0.0f, 1.0f );
Out.Position = mul ( float4(In.Position + In.PositionGeomorphing * K, 1.0f ), matWVP );
Out.Fog = clamp ((( 1.0f - (Distance - fogBegin) / fogEnd) - 0.5f) * 2.0f, 0.0f, 1.0f);
//Out.Fog = 1.0f;
Out.Texcoord = In.Texcoord;
Out.Light = normalize ( mul(vLightPosition, matWorld) );
Out.Normal = normalize ( mul( In.Normal + In.NormalGeomorphing * K, matWorld ) );
return Out;
}
texture tex;
sampler2D sTexture = sampler_state
{
Texture = (tex);
};
float spec = 0.5f;
float4 PS(VS_OUTPUT In) : COLOR0
{
float4 specColor = tex2D( sTexture, In.Texcoord ) * spec;
float4 diffColor = clamp( tex2D( sTexture, In.Texcoord ) * dot( In.Normal, In.Light ), 0.0f, 1.0f );
float4 color = float4(1.0f, 1.0f, 1.0f, 1.0f) * (1.0f - In.Fog) + (diffColor + specColor) * In.Fog;
return color;
}
technique TerrainGeomorphing
{
pass Pass1
{
VertexShader = compile vs_3_0 VS();
PixelShader = compile ps_3_0 PS();
}
}
Код метода:
///
/// Рекурсивная сборка индексов отдельной ветки дерава уровней детализации ландшафта
///
private void InitNodeIndex (gplNode inNode, ref int inIndex)
{
// --- уровень детализации ---------------------------------------
int l = inNode.Level;
// --- индекс активной ветки --------------------------------------
int i = inNode.Index;
// --- размеры активного уровня детализации -----------------------
int w = levelInfo[l].W;
int h = levelInfo[l].H;
// --- признаки соединение со слоем более низкой детализации ------
bool bLeft = false;
bool bRight = false;
bool bUp = false;
bool bDown = false;
// --- индексные направления слоя для псевдодвухмерной карты ------
gxplTrends trends = new gxplTrends();
trends.NewTrends(i, w);
// --- если ветка не разбита ----------------------------------------------------------------------------------------
if (inNode.NodeChildren == null)
{
// --------------------------------------------------------------------------------------------------------------
#region --- собираем два треугольника ---------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------
// - 1й треугольник -----------------------
indices[inIndex + 0] = trends.Center;
indices[inIndex + 1] = trends.Right;
indices[inIndex + 2] = trends.Down;
// - 2й треугольник -----------------------
indices[inIndex + 3] = trends.Down;
indices[inIndex + 4] = trends.Right;
indices[inIndex + 5] = trends.DownRight;
inIndex += 6;
// --------------------------------------------------------------------------------------------------------------
#endregion ------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------
}
// --- если разбита -------------------------------------------------------------------------------------------------
else
{
// --------------------------------------------------------------------------------------------------------------
#region --- определение режима соединения с соседними ветками ---------------------------------------------------
// --------------------------------------------------------------------------------------------------------------
// --- check left join --------------------------------------------
//if (!bNoLeft)
bLeft = (inNode.Coord.X > levelInfo[l].SX0) ?
map[trends.Left].NodeChildren == null : true;
// --- check right join -------------------------------------------
//if (!bNoRight)
bRight = (inNode.Coord.X < levelInfo[l].SX0 + levelInfo[l].W - 1) ?
map[trends.Right].NodeChildren == null : true;
// --- check up join ----------------------------------------------
//if (!bNoUp)
bUp = (inNode.Coord.Y > levelInfo[l].SY0) ?
map[trends.Up].NodeChildren == null : true;
// --- check down join --------------------------------------------
//if (!bNoDown)
bDown = (inNode.Coord.Y < levelInfo[l].SY0 + levelInfo[l].H - 1) ?
map[trends.Down].NodeChildren == null : true;
// --------------------------------------------------------------------------------------------------------------
#endregion ------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------
#region --- сборка всех треугольников с учетом связей различных слоев детализации -------------------------------
// --------------------------------------------------------------------------------------------------------------
// --- индексные направления слоя +1 для псевдодвухмерной карты -------------------------
gxplTrends trends4x3 = new gxplTrends(inNode.NodeChildren[3].Index, levelInfo[l + 1].W);
// --------------------------------------------------------------------------------------------------------------
#region --- если с лева соединение с более высокой детализацией --------------------------------------------------
// --------------------------------------------------------------------------------------------------------------
if (bLeft)
{
indices[inIndex + 0] = trends.Center;
indices[inIndex + 1] = trends4x3.Center;
indices[inIndex + 2] = trends.Down;
inIndex += 3;
// --- если с верху нет! соединения с более высокой детализацией (добавочный треугольник)
if (!bUp)
{
indices[inIndex + 0] = trends.Center;
indices[inIndex + 1] = trends4x3.Up;
indices[inIndex + 2] = trends4x3.Center;
inIndex += 3;
}
// --- если с низу нет! соединения с более высокой детализацией (добавочный треугольник)
if (!bDown)
{
indices[inIndex + 0] = trends.Down;
indices[inIndex + 1] = trends4x3.Center;
indices[inIndex + 2] = trends4x3.Down;
inIndex += 3;
}
}
else // если нет соединение с более высокой детализацией, то переходим к следующему уровню детализации
{
if (!bUp) // Х0
InitNodeIndex(inNode.NodeChildren[0], ref inIndex); // 00
if (!bDown) // 00
InitNodeIndex(inNode.NodeChildren[2], ref inIndex); // Х0
}
// --------------------------------------------------------------------------------------------------------------
#endregion ------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------
#region --- если с права соединение с более высокой детализацией ------------------------------------------------
// --------------------------------------------------------------------------------------------------------------
if (bRight)
{
indices[inIndex + 0] = trends.Right;
indices[inIndex + 1] = trends.DownRight;
indices[inIndex + 2] = trends4x3.Center;
inIndex += 3;
// --- если с верху нет! соединения с более высокой детализацией (добавочный треугольник)
if (!bUp)
{
indices[inIndex + 0] = trends4x3.Center;
indices[inIndex + 1] = trends4x3.Up;
indices[inIndex + 2] = trends.Right;
inIndex += 3;
}
// --- если с низу нет! соединения с более высокой детализацией (добавочный треугольник)
if (!bDown)
{
indices[inIndex + 0] = trends4x3.Center;
indices[inIndex + 1] = trends.DownRight;
indices[inIndex + 2] = trends4x3.Down;
inIndex += 3;
}
}
else // если нет соединение с более высокой детализацией, то переходим к следующему уровню детализации
{
if (!bUp) // 0Х
InitNodeIndex(inNode.NodeChildren[1], ref inIndex); // 00
if (!bDown) // 00
InitNodeIndex(inNode.NodeChildren[3], ref inIndex); // 0Х
}
// --------------------------------------------------------------------------------------------------------------
#endregion ------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------
#region --- если с верху соединение с более высокой детализацией ------------------------------------------------
// --------------------------------------------------------------------------------------------------------------
if (bUp)
{
indices[inIndex + 0] = trends.Center;
indices[inIndex + 1] = trends.Right;
indices[inIndex + 2] = trends4x3.Center;
inIndex += 3;
// --- если с лева нет! соединения с более высокой детализацией (добавочный треугольник)
if (!bLeft)
{
indices[inIndex + 0] = trends.Center;
indices[inIndex + 1] = trends4x3.Center;
indices[inIndex + 2] = trends4x3.Left;
inIndex += 3;
}
// --- если с права нет! соединения с более высокой детализацией (добавочный треугольник)
if (!bRight)
{
indices[inIndex + 0] = trends4x3.Center;
indices[inIndex + 1] = trends.Right;
indices[inIndex + 2] = trends4x3.Right;
inIndex += 3;
}
}
// --------------------------------------------------------------------------------------------------------------
#endregion ------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------
#region --- если с низу соединение с более высокой детализацией -------------------------------------------------
// --------------------------------------------------------------------------------------------------------------
if (bDown)
{
indices[inIndex + 0] = trends.Down;
indices[inIndex + 1] = trends4x3.Center;
indices[inIndex + 2] = trends.DownRight;
inIndex += 3;
// --- если с лева нет! соединения с более высокой детализацией (добавочный треугольник)
if (!bLeft)
{
indices[inIndex + 0] = trends4x3.Center;
indices[inIndex + 1] = trends.Down;
indices[inIndex + 2] = trends4x3.Left;
inIndex += 3;
}
// --- если с права нет! соединения с более высокой детализацией (добавочный треугольник)
if (!bRight)
{
indices[inIndex + 0] = trends4x3.Center;
indices[inIndex + 1] = trends4x3.Right;
indices[inIndex + 2] = trends.DownRight;
inIndex += 3;
}
}
//else
//{
//
//}
// --------------------------------------------------------------------------------------------------------------
#endregion ------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------
#endregion ------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------
}
}