sector optimization work!

This commit is contained in:
2015-03-01 02:50:32 +06:00
parent d97e8e1b50
commit 2dba66810e
11 changed files with 1914 additions and 597 deletions

View File

@@ -50,6 +50,7 @@
<Compile Include="Assets\IsoTools\Examples\Scripts\IsoAutoController.cs" /> <Compile Include="Assets\IsoTools\Examples\Scripts\IsoAutoController.cs" />
<Compile Include="Assets\IsoTools\Examples\Scripts\IsoController.cs" /> <Compile Include="Assets\IsoTools\Examples\Scripts\IsoController.cs" />
<Compile Include="Assets\IsoTools\Scripts\IsoObject.cs" /> <Compile Include="Assets\IsoTools\Scripts\IsoObject.cs" />
<Compile Include="Assets\IsoTools\Scripts\IsoUtils.cs" />
<Compile Include="Assets\IsoTools\Scripts\IsoWorld.cs" /> <Compile Include="Assets\IsoTools\Scripts\IsoWorld.cs" />
<Reference Include="UnityEngine.UI"> <Reference Include="UnityEngine.UI">
<HintPath>/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll</HintPath> <HintPath>/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll</HintPath>

View File

@@ -50,6 +50,7 @@
<Compile Include="Assets\IsoTools\Examples\Scripts\IsoAutoController.cs" /> <Compile Include="Assets\IsoTools\Examples\Scripts\IsoAutoController.cs" />
<Compile Include="Assets\IsoTools\Examples\Scripts\IsoController.cs" /> <Compile Include="Assets\IsoTools\Examples\Scripts\IsoController.cs" />
<Compile Include="Assets\IsoTools\Scripts\IsoObject.cs" /> <Compile Include="Assets\IsoTools\Scripts\IsoObject.cs" />
<Compile Include="Assets\IsoTools\Scripts\IsoUtils.cs" />
<Compile Include="Assets\IsoTools\Scripts\IsoWorld.cs" /> <Compile Include="Assets\IsoTools\Scripts\IsoWorld.cs" />
<Reference Include="UnityEngine.UI"> <Reference Include="UnityEngine.UI">
<HintPath>/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll</HintPath> <HintPath>/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll</HintPath>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e55e1f5dda065443787b1627ccd4d252
timeCreated: 1425063966
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,90 @@
using UnityEngine;
using System;
using System.Collections;
namespace IsoTools {
public class IsoUtils {
public static void LookUpCube(Vector3 min, Vector3 max, Action<Vector3> act) {
for ( var z = min.z; z < max.z; ++z ) {
for ( var y = min.y; y < max.y; ++y ) {
for ( var x = min.x; x < max.x; ++x ) {
act(new Vector3(x, y, z));
}
}
}
}
public static Vector3 Vec3Ceil(Vector3 v) {
return new Vector3(
Mathf.Ceil(v.x),
Mathf.Ceil(v.y),
Mathf.Ceil(v.z));
}
public static Vector3 Vec3Floor(Vector3 v) {
return new Vector3(
Mathf.Floor(v.x),
Mathf.Floor(v.y),
Mathf.Floor(v.z));
}
public static Vector3 Vec3Round(Vector3 v) {
return new Vector3(
Mathf.Round(v.x),
Mathf.Round(v.y),
Mathf.Round(v.z));
}
public static Vector3 Vec3Div(Vector3 a, float b) {
return new Vector3(
a.x / b,
a.y / b,
a.z / b);
}
public static Vector3 Vec3Div(Vector3 a, Vector3 b) {
return new Vector3(
a.x / b.x,
a.y / b.y,
a.z / b.z);
}
public static Vector3 Vec3DivCeil(Vector3 a, float b) {
return Vec3Ceil(Vec3Div(a, b));
}
public static Vector3 Vec3DivCeil(Vector3 a, Vector3 b) {
return Vec3Ceil(Vec3Div(a, b));
}
public static Vector3 Vec3DivFloor(Vector3 a, float b) {
return Vec3Floor(Vec3Div(a, b));
}
public static Vector3 Vec3DivFloor(Vector3 a, Vector3 b) {
return Vec3Floor(Vec3Div(a, b));
}
public static Vector3 Vec3DivRound(Vector3 a, float b) {
return Vec3Round(Vec3Div(a, b));
}
public static Vector3 Vec3DivRound(Vector3 a, Vector3 b) {
return Vec3Round(Vec3Div(a, b));
}
public static Vector3 Vec3Min(Vector3 a, Vector3 b) {
return new Vector3(
Mathf.Min(a.x, b.x),
Mathf.Min(a.y, b.y),
Mathf.Min(a.z, b.z));
}
public static Vector3 Vec3Max(Vector3 a, Vector3 b) {
return new Vector3(
Mathf.Max(a.x, b.x),
Mathf.Max(a.y, b.y),
Mathf.Max(a.z, b.z));
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: f29a64a36f9c44116b903088d23812f9
timeCreated: 1425142474
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -14,27 +14,49 @@ namespace IsoTools {
} }
class ObjectInfo { class ObjectInfo {
public int Index;
public IsoObject IsoObject; public IsoObject IsoObject;
public Vector3 MinSector;
public Vector3 MaxSector;
public bool Visited; public bool Visited;
public int BeginDepend; public int BeginDepend;
public int EndDepend; public int EndDepend;
public ObjectInfo(IsoObject obj) { public ObjectInfo(int index, IsoObject iso_object, Vector3 minSector, Vector3 maxSector) {
IsoObject = obj; Index = index;
IsoObject = iso_object;
MinSector = minSector;
MaxSector = maxSector;
} }
public void Reset(int first_depend) { public void Init(int first_depend) {
Visited = false; Visited = false;
BeginDepend = first_depend; BeginDepend = first_depend;
EndDepend = first_depend; EndDepend = first_depend;
} }
} }
bool _dirty = true; class SectorInfo {
TileTypes _lastTileType = TileTypes.Isometric; public Vector3 Position = Vector3.zero;
float _lastTileSize = 0.0f; public List<int> Objects = new List<int>();
float _lastMinDepth = 0.0f; public List<int> Depends = new List<int>();
float _lastMaxDepth = 0.0f; public SectorInfo(Vector3 position) {
Position = position;
}
}
bool _dirty = true;
List<SectorInfo> _sectors = new List<SectorInfo>();
Vector3 _sectorsNum = Vector3.zero;
List<ObjectInfo> _objects = new List<ObjectInfo>();
List<int> _depends = new List<int>();
TileTypes _lastTileType = TileTypes.Isometric;
float _lastTileSize = 0.0f;
float _lastMinDepth = 0.0f;
float _lastMaxDepth = 0.0f;
float _lastSectorSize = 0.0f;
[SerializeField] [SerializeField]
public TileTypes _tileType = TileTypes.Isometric; public TileTypes _tileType = TileTypes.Isometric;
@@ -53,7 +75,7 @@ namespace IsoTools {
public float TileSize { public float TileSize {
get { return _tileSize; } get { return _tileSize; }
set { set {
_tileSize = value; _tileSize = Math.Max(value, Mathf.Epsilon);
ChangeSortingProperty(); ChangeSortingProperty();
} }
} }
@@ -79,6 +101,17 @@ namespace IsoTools {
ChangeSortingProperty(); ChangeSortingProperty();
} }
} }
[SerializeField]
public float _sectorSize = 5.0f;
/// <summary>Sorting sector size.</summary>
public float SectorSize {
get { return _sectorSize; }
set {
_sectorSize = Mathf.Max(value, 1.0f);
ChangeSortingProperty();
}
}
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/// <summary> /// <summary>
@@ -173,95 +206,155 @@ namespace IsoTools {
} }
void FixAllTransforms() { void FixAllTransforms() {
var objects = ScanObjects(); ApplyToAllIsoObjects(obj => obj.FixTransform());
foreach ( var obj in objects ) {
obj.IsoObject.FixTransform();
}
} }
void ChangeSortingProperty() { void ChangeSortingProperty() {
MarkDirty(); MarkDirty();
FixAllTransforms(); FixAllTransforms();
_lastTileType = TileType; _lastTileType = TileType;
_lastTileSize = TileSize; _lastTileSize = TileSize;
_lastMinDepth = MinDepth; _lastMinDepth = MinDepth;
_lastMaxDepth = MaxDepth; _lastMaxDepth = MaxDepth;
_lastSectorSize = SectorSize;
} }
bool IsDepends(IsoObject obj_ao, IsoObject obj_bo) { void ApplyToAllIsoObjects(Action<IsoObject> act) {
if ( obj_ao != obj_bo ) { var iso_objects = GameObject.FindObjectsOfType<IsoObject>();
var max_ax = obj_ao.Position.x + obj_ao.Size.x; foreach ( var iso_object in iso_objects ) {
var max_ay = obj_ao.Position.y + obj_ao.Size.y; act(iso_object);
if ( obj_bo.Position.x < max_ax && obj_bo.Position.y < max_ay ) { }
var max_bz = obj_bo.Position.z + obj_bo.Size.z; }
if ( obj_ao.Position.z < max_bz ) {
return true; int SectorIndex(Vector3 num_pos) {
return Mathf.RoundToInt(
num_pos.z * _sectorsNum.x * _sectorsNum.y +
num_pos.y * _sectorsNum.x +
num_pos.x);
}
Vector3 SectorNumPos(int index) {
var z = Mathf.FloorToInt(index / (_sectorsNum.x * _sectorsNum.y));
var y = Mathf.FloorToInt((index - (z * _sectorsNum.x * _sectorsNum.y)) / _sectorsNum.x);
var x = index - (z * _sectorsNum.x * _sectorsNum.y) - (y * _sectorsNum.x);
return new Vector3(x, y, z);
}
void SetupSectors() {
var iso_objects = GameObject.FindObjectsOfType<IsoObject>();
var min = Vector3.zero;
var max = Vector3.one;
foreach ( var iso_object in iso_objects ) {
min = IsoUtils.Vec3Min(min, iso_object.Position);
max = IsoUtils.Vec3Max(max, iso_object.Position + iso_object.Size);
}
_sectorsNum = IsoUtils.Vec3DivCeil(max - min, SectorSize);
_sectors.Clear();
_sectors.Capacity = Mathf.CeilToInt(_sectorsNum.x * _sectorsNum.y * _sectorsNum.z);
while ( _sectors.Count < _sectors.Capacity ) {
var num_pos = SectorNumPos(_sectors.Count);
_sectors.Add(new SectorInfo(num_pos * SectorSize));
}
_objects.Clear();
foreach ( var iso_object in iso_objects ) {
var max_size = IsoUtils.Vec3Max(iso_object.Size, Vector3.one);
var min_sector = IsoUtils.Vec3DivFloor(iso_object.Position - min, SectorSize);
var max_sector = IsoUtils.Vec3DivCeil(iso_object.Position + max_size - min, SectorSize);
var obj_info = new ObjectInfo(_objects.Count, iso_object, min_sector, max_sector);
_objects.Add(obj_info);
IsoUtils.LookUpCube(min_sector, max_sector, p => {
var index = SectorIndex(p);
_sectors[index].Objects.Add(obj_info.Index);
});
}
}
void SetupSectorDepends() {
foreach ( var sec_a in _sectors ) {
for ( var i = 0; i < _sectors.Count; ++i ) {
var sec_b = _sectors[i];
if ( sec_a == sec_b || IsDepends(sec_a.Position, sec_b.Position, SectorSize) ) {
sec_a.Depends.Add(i);
} }
} }
} }
return false; }
void SetupObjectDepends() {
_depends.Clear();
foreach ( var obj_a in _objects ) {
obj_a.Init(_depends.Count);
var obj_ao = obj_a.IsoObject;
IsoUtils.LookUpCube(obj_a.MinSector, obj_a.MaxSector, p => {
var index = SectorIndex(p);
foreach ( var sec_i in _sectors[index].Depends ) {
var sec = _sectors[sec_i];
foreach ( var obj_bi in sec.Objects ) {
var obj_bo = _objects[obj_bi].IsoObject;
if ( obj_ao != obj_bo && IsDepends(obj_ao.Position, obj_ao.Size, obj_bo.Position, obj_bo.Size) ) {
_depends.Add(obj_bi);
++obj_a.EndDepend;
}
}
}
});
}
}
bool IsDepends(Vector3 a_pos, Vector3 b_pos, float size) {
return IsDepends(
a_pos, new Vector3(size, size, size),
b_pos, new Vector3(size, size, size));
}
bool IsDepends(Vector3 a_min, Vector3 a_size, Vector3 b_min, Vector3 b_size) {
var a_max = a_min + a_size;
var b_max = b_min + b_size;
return
a_max.x > b_min.x && a_min.x < b_max.x + 1.0f &&
a_max.y > b_min.y && a_min.y < b_max.y + 1.0f &&
b_max.z > a_min.z && b_min.z < a_max.z + 1.0f;
}
void SetupAllObjects() {
var depth = MinDepth;
foreach ( var info in _objects ) {
depth = PlaceObject(info, depth);
}
} }
IList<ObjectInfo> ScanObjects() {
return ScanObjects(p => true);
}
IList<ObjectInfo> ScanObjects(Func<IsoObject, bool> filter) {
var iso_objects = GameObject.FindObjectsOfType<IsoObject>();
var objects = new List<ObjectInfo>(iso_objects.Length);
foreach ( var iso_object in iso_objects ) {
if ( filter(iso_object) ) {
objects.Add(new ObjectInfo(iso_object));
}
}
return objects;
}
IList<int> ScanDepends(IList<ObjectInfo> objects) {
var depends = new List<int>(objects.Count);
foreach ( var obj_a in objects ) {
obj_a.Reset(depends.Count);
var obj_ao = obj_a.IsoObject;
for ( int i = 0; i < objects.Count; ++i ) {
var obj_bo = objects[i].IsoObject;
if ( IsDepends(obj_ao, obj_bo) ) {
depends.Add(i);
++obj_a.EndDepend;
}
}
}
return depends;
}
void ManualSort(IList<ObjectInfo> objects) {
var depends = ScanDepends(objects);
var depth = MinDepth;
foreach ( var info in objects ) {
PlaceObject(info, objects, depends, ref depth);
}
}
void PlaceObject(IsoObject obj, float depth) { void PlaceObject(IsoObject obj, float depth) {
var trans = obj.gameObject.transform; var trans = obj.gameObject.transform;
trans.position = new Vector3(trans.position.x, trans.position.y, depth); trans.position = new Vector3(trans.position.x, trans.position.y, depth);
} }
void PlaceObject(ObjectInfo info, IList<ObjectInfo> objects, IList<int> depends, ref float depth) { float PlaceObject(ObjectInfo info, float depth) {
if ( !info.Visited ) { if ( info.Visited ) {
info.Visited = true; return depth;
for ( int i = info.BeginDepend; i < info.EndDepend && i < depends.Count; ++i ) {
var object_index = depends[i];
var obj = objects[object_index];
PlaceObject(obj, objects, depends, ref depth);
}
PlaceObject(info.IsoObject, depth);
depth += (MaxDepth - MinDepth) / objects.Count;
} }
info.Visited = true;
for ( var i = info.BeginDepend; i < info.EndDepend && i < _depends.Count; ++i ) {
var obj_index = _depends[i];
var obj = _objects[obj_index];
depth = PlaceObject(obj, depth);
}
PlaceObject(info.IsoObject, depth);
return depth + (MaxDepth - MinDepth) / _objects.Count;
} }
void StepSort() { void StepSort() {
if ( _dirty ) { if ( _dirty ) {
ManualSort(ScanObjects(p => p.Sorting)); SetupSectors();
SetupSectorDepends();
SetupObjectDepends();
SetupAllObjects();
_dirty = false; _dirty = false;
} }
} }
@@ -273,10 +366,11 @@ namespace IsoTools {
void LateUpdate() { void LateUpdate() {
if ( Application.isEditor ) { if ( Application.isEditor ) {
if ( _lastTileType != _tileType ) TileType = _tileType; if ( _lastTileType != _tileType ) TileType = _tileType;
if ( !Mathf.Approximately(_lastTileSize, _tileSize) ) TileSize = _tileSize; if ( !Mathf.Approximately(_lastTileSize, _tileSize ) ) TileSize = _tileSize;
if ( !Mathf.Approximately(_lastMinDepth, _minDepth) ) MinDepth = _minDepth; if ( !Mathf.Approximately(_lastMinDepth, _minDepth ) ) MinDepth = _minDepth;
if ( !Mathf.Approximately(_lastMaxDepth, _maxDepth) ) MaxDepth = _maxDepth; if ( !Mathf.Approximately(_lastMaxDepth, _maxDepth ) ) MaxDepth = _maxDepth;
if ( !Mathf.Approximately(_lastSectorSize, _sectorSize ) ) SectorSize = _sectorSize;
} }
StepSort(); StepSort();
} }
@@ -286,10 +380,7 @@ namespace IsoTools {
} }
void OnDisable() { void OnDisable() {
var objects = ScanObjects(); ApplyToAllIsoObjects(obj => obj.ResetIsoWorld());
foreach ( var obj in objects ) {
obj.IsoObject.ResetIsoWorld();
}
} }
} }
} // namespace IsoTools } // namespace IsoTools

View File

@@ -17,7 +17,7 @@ Global
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection
GlobalSection(MonoDevelopProperties) = preSolution GlobalSection(MonoDevelopProperties) = preSolution
StartupItem = Assembly-CSharp.csproj StartupItem = Assembly-CSharp.csproj
Policies = $0 Policies = $0
$0.TextStylePolicy = $1 $0.TextStylePolicy = $1

View File

@@ -17,7 +17,7 @@ Global
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection
GlobalSection(MonoDevelopProperties) = preSolution GlobalSection(MonoDevelopProperties) = preSolution
StartupItem = Assembly-CSharp.csproj StartupItem = Assembly-CSharp.csproj
Policies = $0 Policies = $0
$0.TextStylePolicy = $1 $0.TextStylePolicy = $1

View File

@@ -2,8 +2,8 @@
<MonoDevelop.Ide.Workspace ActiveConfiguration="Debug" PreferredExecutionTarget="MonoDevelop.Default" /> <MonoDevelop.Ide.Workspace ActiveConfiguration="Debug" PreferredExecutionTarget="MonoDevelop.Default" />
<MonoDevelop.Ide.Workbench ActiveDocument="Assets/IsoTools/Scripts/IsoWorld.cs"> <MonoDevelop.Ide.Workbench ActiveDocument="Assets/IsoTools/Scripts/IsoWorld.cs">
<Files> <Files>
<File FileName="Assets/IsoTools/Scripts/IsoWorld.cs" Line="272" Column="4" /> <File FileName="Assets/IsoTools/Scripts/IsoWorld.cs" Line="351" Column="3" />
<File FileName="Assets/IsoTools/Scripts/IsoObject.cs" Line="104" Column="29" /> <File FileName="Assets/IsoTools/Scripts/IsoUtils.cs" Line="6" Column="25" />
</Files> </Files>
</MonoDevelop.Ide.Workbench> </MonoDevelop.Ide.Workbench>
<MonoDevelop.Ide.DebuggingService.Breakpoints> <MonoDevelop.Ide.DebuggingService.Breakpoints>