Skip to content

Commit

Permalink
Merge pull request MonoGame#312 from slygamer/develop3d
Browse files Browse the repository at this point in the history
Develop3d - Changes to fix/optimize texture loading, complete bounding frustum/sphere test, and some platform-specific changes
  • Loading branch information
kjpou1 committed Feb 22, 2012
2 parents b898684 + 2955b95 commit 5188860
Show file tree
Hide file tree
Showing 16 changed files with 457 additions and 258 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
[submodule "ThirdParty/Libs"]
path = ThirdParty/Libs
url = https://github.com/kungfubanana/MonoGame-Dependencies.git
ignore = all
[submodule "Tests"]
path = Tests
url = https://github.com/kungfubanana/MonoGame-Tests.git
ignore = all
[submodule "Samples"]
path = Samples
url = https://github.com/CartBlanche/MonoGame-Samples.git
ignore = all
127 changes: 62 additions & 65 deletions MonoGame.Framework/BoundingFrustum.cs
Original file line number Diff line number Diff line change
Expand Up @@ -210,71 +210,68 @@ public ContainmentType Contains(BoundingSphere sphere)

public void Contains(ref BoundingSphere sphere, out ContainmentType result)
{
float val;
ContainmentType contained;

// We first check if the sphere is inside the frustum
this.Contains(ref sphere.Center, out contained);

// The sphere is inside. Now we need to check if it's fully contained or not
// So we see if the perpendicular distance to each plane is less than or equal to the sphere's radius.
// If the perpendicular distance is less, just return Intersects.
if (contained == ContainmentType.Contains)
{
val = PlaneHelper.PerpendicularDistance(ref sphere.Center, ref this.bottom);
if (val < sphere.Radius)
{
result = ContainmentType.Intersects;
return;
}

val = PlaneHelper.PerpendicularDistance(ref sphere.Center, ref this.far);
if (val < sphere.Radius)
{
result = ContainmentType.Intersects;
return;
}

val = PlaneHelper.PerpendicularDistance(ref sphere.Center, ref this.left);
if (val < sphere.Radius)
{
result = ContainmentType.Intersects;
return;
}

val = PlaneHelper.PerpendicularDistance(ref sphere.Center, ref this.near);
if (val < sphere.Radius)
{
result = ContainmentType.Intersects;
return;
}

val = PlaneHelper.PerpendicularDistance(ref sphere.Center, ref this.right);
if (val < sphere.Radius)
{
result = ContainmentType.Intersects;
return;
}

val = PlaneHelper.PerpendicularDistance(ref sphere.Center, ref this.top);
if (val < sphere.Radius)
{
result = ContainmentType.Intersects;
return;
}

// If we get here, the sphere is fully contained
result = ContainmentType.Contains;
return;
}
//duff idea : test if all corner is in same side of a plane if yes and outside it is disjoint else intersect
// issue is that we can have some times when really close aabb



// If we're here, the the sphere's centre was outside of the frustum. This makes things hard :(
// We can't use perpendicular distance anymore. I'm not sure how to code this.
throw new NotImplementedException();
float dist;
result = ContainmentType.Contains;

Vector3.Dot(ref bottom.Normal, ref sphere.Center, out dist);
dist += bottom.D;
if (dist > sphere.Radius)
{
result = ContainmentType.Disjoint;
return;
}
if (Math.Abs(dist) < sphere.Radius)
result = ContainmentType.Intersects;

Vector3.Dot(ref top.Normal, ref sphere.Center, out dist);
dist += top.D;
if (dist > sphere.Radius)
{
result = ContainmentType.Disjoint;
return;
}
if (Math.Abs(dist) < sphere.Radius)
result = ContainmentType.Intersects;

Vector3.Dot(ref near.Normal, ref sphere.Center, out dist);
dist += near.D;
if (dist > sphere.Radius)
{
result = ContainmentType.Disjoint;
return;
}
if (Math.Abs(dist) < sphere.Radius)
result = ContainmentType.Intersects;

Vector3.Dot(ref far.Normal, ref sphere.Center, out dist);
dist += far.D;
if (dist > sphere.Radius)
{
result = ContainmentType.Disjoint;
return;
}
if (Math.Abs(dist) < sphere.Radius)
result = ContainmentType.Intersects;

Vector3.Dot(ref left.Normal, ref sphere.Center, out dist);
dist += left.D;
if (dist > sphere.Radius)
{
result = ContainmentType.Disjoint;
return;
}
if (Math.Abs(dist) < sphere.Radius)
result = ContainmentType.Intersects;

Vector3.Dot(ref right.Normal, ref sphere.Center, out dist);
dist += right.D;
if (dist > sphere.Radius)
{
result = ContainmentType.Disjoint;
return;
}
if (Math.Abs(dist) < sphere.Radius)
result = ContainmentType.Intersects;
}

public ContainmentType Contains(Vector3 point)
Expand Down
29 changes: 17 additions & 12 deletions MonoGame.Framework/Content/ContentManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public partial class ContentManager : IDisposable
private IServiceProvider serviceProvider;
private IGraphicsDeviceService graphicsDeviceService;
protected Dictionary<string, object> loadedAssets = new Dictionary<string, object>();
List<IDisposable> disposableAssets = new List<IDisposable>();
bool disposed;

private static object ContentManagerLock = new object();
Expand Down Expand Up @@ -420,9 +421,14 @@ protected T ReadAsset<T>(string assetName, Action<IDisposable> recordDisposableO
{
throw new ContentLoadException("Could not load " + originalAssetName + " asset!");
}

if ( recordDisposableObject != null && result is IDisposable )
recordDisposableObject(result as IDisposable);

if (result is IDisposable)
{
if (recordDisposableObject != null)
recordDisposableObject(result as IDisposable);
else
disposableAssets.Add(result as IDisposable);
}

return (T)result;
}
Expand All @@ -434,8 +440,6 @@ protected void ReloadContent()
ReloadAsset(asset.Key, asset.Value);
}
}



protected void ReloadAsset(string originalAssetName, object currentAsset)
{
Expand All @@ -460,11 +464,14 @@ protected void ReloadAsset(string originalAssetName, object currentAsset)

Stream stream = null;
//bool loadXnb = false;
try {
try
{
//try load it traditionally
stream = OpenStream(assetName);
stream.Close();
} catch (ContentLoadException ex) {
}
catch (ContentLoadException ex)
{
//MonoGame try to load as a non-content file

assetName = TitleContainer.GetFilename(Path.Combine (_rootDirectory, assetName));
Expand Down Expand Up @@ -516,20 +523,18 @@ protected void ReloadAsset(string originalAssetName, object currentAsset)
{
}
}


}

public virtual void Unload()
{
// Look for disposable assets.
foreach (var pair in loadedAssets)
foreach (var disposable in disposableAssets)
{
var disposable = pair.Value as IDisposable;
if (disposable != null )
if (disposable != null)
disposable.Dispose();
}
RemoveContentManager(this);
disposableAssets.Clear();
loadedAssets.Clear();
}

Expand Down
91 changes: 65 additions & 26 deletions MonoGame.Framework/Content/ContentReaders/Texture2DReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,37 +132,76 @@ protected internal override Texture2D Read(ContentReader reader, Texture2D exist
int levelWidth = width >> level;
int levelHeight = height >> level;
//Convert the image data if required
switch(surfaceFormat) {
switch (surfaceFormat)
{
#if IPHONE || ANDROID
//no Dxt in OpenGL ES
case SurfaceFormat.Dxt1:
levelData = DxtUtil.DecompressDxt1(levelData, levelWidth, levelHeight);
break;
case SurfaceFormat.Dxt3:
levelData = DxtUtil.DecompressDxt3(levelData, levelWidth, levelHeight);
break;
case SurfaceFormat.Dxt5:
levelData = DxtUtil.DecompressDxt5(levelData, levelWidth, levelHeight);
break;
//no Dxt in OpenGL ES
case SurfaceFormat.Dxt1:
levelData = DxtUtil.DecompressDxt1(levelData, levelWidth, levelHeight);
break;
case SurfaceFormat.Dxt3:
levelData = DxtUtil.DecompressDxt3(levelData, levelWidth, levelHeight);
break;
case SurfaceFormat.Dxt5:
levelData = DxtUtil.DecompressDxt5(levelData, levelWidth, levelHeight);
break;
#endif
case SurfaceFormat.NormalizedByte4:
int pitch = levelWidth * 4;
for (int y = 0; y < levelHeight; y++)
{
for (int x = 0; x < levelWidth; x++)
{
int color = BitConverter.ToInt32(levelData, y*pitch+x*4);
levelData[y*pitch+x*4] = (byte)(((color >> 16) & 0xff)); //R:=W
levelData[y*pitch+x*4+1] = (byte)(((color >> 8 ) & 0xff)); //G:=V
levelData[y*pitch+x*4+2] = (byte)(((color ) & 0xff)); //B:=U
levelData[y*pitch+x*4+3] = (byte)(((color >> 24) & 0xff)); //A:=Q
case SurfaceFormat.Bgr565:
{
/*
// BGR -> BGR
int offset = 0;
for (int y = 0; y < levelHeight; y++)
{
for (int x = 0; x < levelWidth; x++)
{
ushort pixel = BitConverter.ToUInt16(levelData, offset);
pixel = (ushort)(((pixel & 0x0FFF) << 4) | ((pixel & 0xF000) >> 12));
levelData[offset] = (byte)(pixel);
levelData[offset + 1] = (byte)(pixel >> 8);
offset += 2;
}
}
*/
}
}
break;
break;
case SurfaceFormat.Bgra4444:
{
// Shift the channels to suit GLES
int offset = 0;
for (int y = 0; y < levelHeight; y++)
{
for (int x = 0; x < levelWidth; x++)
{
ushort pixel = BitConverter.ToUInt16(levelData, offset);
pixel = (ushort)(((pixel & 0x0FFF) << 4) | ((pixel & 0xF000) >> 12));
levelData[offset] = (byte)(pixel);
levelData[offset + 1] = (byte)(pixel >> 8);
offset += 2;
}
}
}
break;
case SurfaceFormat.NormalizedByte4:
{
int bytesPerPixel = surfaceFormat.Size();
int pitch = levelWidth * bytesPerPixel;
for (int y = 0; y < levelHeight; y++)
{
for (int x = 0; x < levelWidth; x++)
{
int color = BitConverter.ToInt32(levelData, y * pitch + x * bytesPerPixel);
levelData[y * pitch + x * 4] = (byte)(((color >> 16) & 0xff)); //R:=W
levelData[y * pitch + x * 4 + 1] = (byte)(((color >> 8) & 0xff)); //G:=V
levelData[y * pitch + x * 4 + 2] = (byte)(((color) & 0xff)); //B:=U
levelData[y * pitch + x * 4 + 3] = (byte)(((color >> 24) & 0xff)); //A:=Q
}
}
}
break;
}

texture.SetData(level, null, levelData, 0, levelData.Length);

texture.SetData(level, null, levelData, 0, levelData.Length);
}

return texture;
Expand Down
17 changes: 15 additions & 2 deletions MonoGame.Framework/Content/ContentTypeReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ public abstract class ContentTypeReader
#region Private Member Variables

private Type targetType;
#if ANDROID
// Keep this static so we only call Game.Activity.Assets.List() once
// No need to call it for each file if the list will never change
static string[] files = null;
#endif

#endregion Private Member Variables

Expand Down Expand Up @@ -91,7 +96,10 @@ internal static string Normalize(string fileName, string[] extensions)
file = fileName.Substring(index + 1, fileName.Length - index - 1);
path = fileName.Substring(0, index);
}
string[] files = Game.Activity.Assets.List(path);

// Only read the assets file list once
if (files == null)
files = Game.Activity.Assets.List(path);

if (files.Any(s => s == file))
return fileName;
Expand All @@ -102,7 +110,12 @@ internal static string Normalize(string fileName, string[] extensions)
return null;
}

return Path.Combine(path, files.FirstOrDefault(s => extensions.Any(ext => s.ToLower() == (file.ToLower() + ext))));
// FirstOrDefault returns null as the default if the file is not found. This crashed Path.Combine so check
// for it first.
string file2 = files.FirstOrDefault(s => extensions.Any(ext => s.ToLower() == (file.ToLower() + ext)));
if (String.IsNullOrEmpty(file2))
return null;
return Path.Combine(path, file2);
}
#else
public static string Normalize(string fileName, string[] extensions)
Expand Down
1 change: 1 addition & 0 deletions MonoGame.Framework/Game.cs
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ public void ResetElapsedTime()
// consolidate this logic back into the Game class.
// Regardless, an empty implementation is not correct.
_platform.ResetElapsedTime();
_lastUpdate = DateTime.Now;
}

public void Run()
Expand Down
Loading

0 comments on commit 5188860

Please sign in to comment.