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\IsoController.cs" />
<Compile Include="Assets\IsoTools\Scripts\IsoObject.cs" />
<Compile Include="Assets\IsoTools\Scripts\IsoUtils.cs" />
<Compile Include="Assets\IsoTools\Scripts\IsoWorld.cs" />
<Reference Include="UnityEngine.UI">
<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\IsoController.cs" />
<Compile Include="Assets\IsoTools\Scripts\IsoObject.cs" />
<Compile Include="Assets\IsoTools\Scripts\IsoUtils.cs" />
<Compile Include="Assets\IsoTools\Scripts\IsoWorld.cs" />
<Reference Include="UnityEngine.UI">
<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 {
public int Index;
public IsoObject IsoObject;
public Vector3 MinSector;
public Vector3 MaxSector;
public bool Visited;
public int BeginDepend;
public int EndDepend;
public ObjectInfo(IsoObject obj) {
IsoObject = obj;
public ObjectInfo(int index, IsoObject iso_object, Vector3 minSector, Vector3 maxSector) {
Index = index;
IsoObject = iso_object;
MinSector = minSector;
MaxSector = maxSector;
}
public void Reset(int first_depend) {
public void Init(int first_depend) {
Visited = false;
BeginDepend = first_depend;
EndDepend = first_depend;
}
}
bool _dirty = true;
TileTypes _lastTileType = TileTypes.Isometric;
float _lastTileSize = 0.0f;
float _lastMinDepth = 0.0f;
float _lastMaxDepth = 0.0f;
class SectorInfo {
public Vector3 Position = Vector3.zero;
public List<int> Objects = new List<int>();
public List<int> Depends = new List<int>();
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]
public TileTypes _tileType = TileTypes.Isometric;
@@ -53,7 +75,7 @@ namespace IsoTools {
public float TileSize {
get { return _tileSize; }
set {
_tileSize = value;
_tileSize = Math.Max(value, Mathf.Epsilon);
ChangeSortingProperty();
}
}
@@ -80,6 +102,17 @@ namespace IsoTools {
}
}
[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>
/// Marks world for resorting.
@@ -173,71 +206,127 @@ namespace IsoTools {
}
void FixAllTransforms() {
var objects = ScanObjects();
foreach ( var obj in objects ) {
obj.IsoObject.FixTransform();
}
ApplyToAllIsoObjects(obj => obj.FixTransform());
}
void ChangeSortingProperty() {
MarkDirty();
FixAllTransforms();
_lastTileType = TileType;
_lastTileSize = TileSize;
_lastMinDepth = MinDepth;
_lastMaxDepth = MaxDepth;
_lastTileType = TileType;
_lastTileSize = TileSize;
_lastMinDepth = MinDepth;
_lastMaxDepth = MaxDepth;
_lastSectorSize = SectorSize;
}
bool IsDepends(IsoObject obj_ao, IsoObject obj_bo) {
if ( obj_ao != obj_bo ) {
var max_ax = obj_ao.Position.x + obj_ao.Size.x;
var max_ay = obj_ao.Position.y + obj_ao.Size.y;
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;
}
}
}
return false;
}
IList<ObjectInfo> ScanObjects() {
return ScanObjects(p => true);
}
IList<ObjectInfo> ScanObjects(Func<IsoObject, bool> filter) {
void ApplyToAllIsoObjects(Action<IsoObject> act) {
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));
}
act(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;
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 depends;
}
void ManualSort(IList<ObjectInfo> objects) {
var depends = ScanDepends(objects);
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 ) {
PlaceObject(info, objects, depends, ref depth);
foreach ( var info in _objects ) {
depth = PlaceObject(info, depth);
}
}
@@ -246,22 +335,26 @@ namespace IsoTools {
trans.position = new Vector3(trans.position.x, trans.position.y, depth);
}
void PlaceObject(ObjectInfo info, IList<ObjectInfo> objects, IList<int> depends, ref float depth) {
if ( !info.Visited ) {
info.Visited = true;
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;
float PlaceObject(ObjectInfo info, float depth) {
if ( info.Visited ) {
return depth;
}
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() {
if ( _dirty ) {
ManualSort(ScanObjects(p => p.Sorting));
SetupSectors();
SetupSectorDepends();
SetupObjectDepends();
SetupAllObjects();
_dirty = false;
}
}
@@ -273,10 +366,11 @@ namespace IsoTools {
void LateUpdate() {
if ( Application.isEditor ) {
if ( _lastTileType != _tileType ) TileType = _tileType;
if ( !Mathf.Approximately(_lastTileSize, _tileSize) ) TileSize = _tileSize;
if ( !Mathf.Approximately(_lastMinDepth, _minDepth) ) MinDepth = _minDepth;
if ( !Mathf.Approximately(_lastMaxDepth, _maxDepth) ) MaxDepth = _maxDepth;
if ( _lastTileType != _tileType ) TileType = _tileType;
if ( !Mathf.Approximately(_lastTileSize, _tileSize ) ) TileSize = _tileSize;
if ( !Mathf.Approximately(_lastMinDepth, _minDepth ) ) MinDepth = _minDepth;
if ( !Mathf.Approximately(_lastMaxDepth, _maxDepth ) ) MaxDepth = _maxDepth;
if ( !Mathf.Approximately(_lastSectorSize, _sectorSize ) ) SectorSize = _sectorSize;
}
StepSort();
}
@@ -286,10 +380,7 @@ namespace IsoTools {
}
void OnDisable() {
var objects = ScanObjects();
foreach ( var obj in objects ) {
obj.IsoObject.ResetIsoWorld();
}
ApplyToAllIsoObjects(obj => obj.ResetIsoWorld());
}
}
} // namespace IsoTools

View File

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

View File

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

View File

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