Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
T
trees
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
WANDER
trees
Commits
ee7664d8
Commit
ee7664d8
authored
1 year ago
by
Knuiman, Bart
Browse files
Options
Downloads
Patches
Plain Diff
Changed rendering type of trees completely. Now much smoother, but not finished (WIP).
parent
11587a97
Branches
Branches containing commit
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
Runtime/Prefabs/TreeStreamer.prefab
+13
-11
13 additions, 11 deletions
Runtime/Prefabs/TreeStreamer.prefab
Runtime/Scripts/TreeStreamer2.cs
+212
-94
212 additions, 94 deletions
Runtime/Scripts/TreeStreamer2.cs
with
225 additions
and
105 deletions
Runtime/Prefabs/TreeStreamer.prefab
+
13
−
11
View file @
ee7664d8
...
@@ -9,7 +9,7 @@ GameObject:
...
@@ -9,7 +9,7 @@ GameObject:
serializedVersion
:
6
serializedVersion
:
6
m_Component
:
m_Component
:
-
component
:
{
fileID
:
8102445642857089983
}
-
component
:
{
fileID
:
8102445642857089983
}
-
component
:
{
fileID
:
5
786002106602377772
}
-
component
:
{
fileID
:
5
91969842533917131
}
m_Layer
:
0
m_Layer
:
0
m_Name
:
TreeStreamer
m_Name
:
TreeStreamer
m_TagString
:
Untagged
m_TagString
:
Untagged
...
@@ -32,7 +32,7 @@ Transform:
...
@@ -32,7 +32,7 @@ Transform:
m_Children
:
[]
m_Children
:
[]
m_Father
:
{
fileID
:
0
}
m_Father
:
{
fileID
:
0
}
m_LocalEulerAnglesHint
:
{
x
:
0
,
y
:
0
,
z
:
0
}
m_LocalEulerAnglesHint
:
{
x
:
0
,
y
:
0
,
z
:
0
}
---
!u!114
&5
786002106602377772
---
!u!114
&5
91969842533917131
MonoBehaviour
:
MonoBehaviour
:
m_ObjectHideFlags
:
0
m_ObjectHideFlags
:
0
m_CorrespondingSourceObject
:
{
fileID
:
0
}
m_CorrespondingSourceObject
:
{
fileID
:
0
}
...
@@ -41,21 +41,23 @@ MonoBehaviour:
...
@@ -41,21 +41,23 @@ MonoBehaviour:
m_GameObject
:
{
fileID
:
742251135161503034
}
m_GameObject
:
{
fileID
:
742251135161503034
}
m_Enabled
:
1
m_Enabled
:
1
m_EditorHideFlags
:
0
m_EditorHideFlags
:
0
m_Script
:
{
fileID
:
11500000
,
guid
:
acbdecd6bc179f647b5703a55ffdafe7
,
type
:
3
}
m_Script
:
{
fileID
:
11500000
,
guid
:
4643b554a54fe66479884b76c4ca9d39
,
type
:
3
}
m_Name
:
m_Name
:
m_EditorClassIdentifier
:
m_EditorClassIdentifier
:
activeTreeCount
:
0
originRDX
:
220929.6988732884
originRDX
:
220929.6988732884
originRDY
:
450504.48700884776
originRDY
:
450504.48700884776
tileSize
:
860.16
tileSize
:
860.16
treeRoot
:
{
fileID
:
0
}
treeRoot
:
{
fileID
:
0
}
areaName
:
DeMarke
areaName
:
DeMarke
targetCam
:
{
fileID
:
0
}
targetCam
:
{
fileID
:
0
}
numRings
:
5
wgs84Origin
:
{
x
:
52.03894
,
y
:
6.348124
}
wgs84Origin
:
{
x
:
52.03894
,
y
:
6.348124
}
numRings
:
4
requiredTime
:
1
re
quiredTime
:
3
re
moveDelay
:
1
removeDela
y
:
7
enableDisableKe
y
:
49
maxTrees
:
10000
types
:
treePrefab
:
{
fileID
:
9046900170786976767
,
guid
:
65926329d063fb84ea4ac2e63a6fcaa4
,
-
type
:
{
fileID
:
5556296651694026700
,
guid
:
19df7a28074cb284a8aa8562718310f5
,
type
:
3
}
type
:
3
}
maxTrees
:
20000
treenGenerator
:
{
fileID
:
-3667069338063608550
,
guid
:
ac835d606e3e19a48bdf1d8
63a
c
fc
fd0
,
-
type
:
{
fileID
:
9046900170786976767
,
guid
:
65926329d063fb84ea4ac2e
63a
6
fc
aa4
,
type
:
3
}
type
:
3
}
maxTrees
:
20000
This diff is collapsed.
Click to expand it.
Runtime/Scripts/TreeStreamer2.cs
+
212
−
94
View file @
ee7664d8
using
Codice.CM.Client.Differences
;
using
System
;
using
System
;
using
System.Collections.Generic
;
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Linq
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
System.Threading.Tasks
;
using
Unity.Collections
;
using
Unity.Collections
;
using
UnityEditor
;
using
UnityEditor
;
using
UnityEditor.Graphs
;
using
UnityEngine
;
using
UnityEngine
;
using
UnityEngine.AddressableAssets
;
using
UnityEngine.AddressableAssets
;
...
@@ -17,20 +20,21 @@ namespace Wander
...
@@ -17,20 +20,21 @@ namespace Wander
{
{
public
float
originTime
;
public
float
originTime
;
public
float
lastTime
;
public
float
lastTime
;
public
bool
spawned
;
public
List
<
Vector3
>
treeDb
=
new
();
public
List
<
Vector3
>
treeDb
=
new
();
public
int
spawnIndex
;
public
Terrain
terrain
;
public
Terrain
terrain
;
public
bool
triedToObtainTerrain
;
public
bool
triedToObtainTerrain
;
public
List
<
int
>
spawnedTrees
=
new
();
public
int
lod
;
public
Vector3
worldPos
;
public
Dictionary
<
int
,
(
int
offset
,
int
num
)>
offsetAndNumPerType
;
}
}
[
Serializable
]
public
class
TreeType
public
class
TreeType
{
{
public
GameObject
type
;
public
GameObject
type
;
public
int
maxTrees
;
public
int
maxTrees
;
internal
List
<
int
>
freeSlots
;
internal
int
[]
currentCount
;
internal
NativeArray
<
Matrix4x4
>
positions
;
internal
NativeArray
<
Matrix4x4
>
[]
positions
;
}
}
[
ReadOnly
]
public
int
activeTreeCount
;
[
ReadOnly
]
public
int
activeTreeCount
;
...
@@ -41,28 +45,28 @@ namespace Wander
...
@@ -41,28 +45,28 @@ namespace Wander
[
ReadOnly
]
public
string
areaName
=
"Steenbergen"
;
[
ReadOnly
]
public
string
areaName
=
"Steenbergen"
;
public
Camera
targetCam
;
public
Camera
targetCam
;
public
bool
asTreeInstances
=
true
;
public
int
numRings
=
5
;
public
int
numRings
=
5
;
public
Vector2
wgs84Origin
;
public
Vector2
wgs84Origin
;
public
float
requiredTime
=
2
;
public
float
requiredTime
=
2
;
public
float
removeDelay
=
1
;
public
float
removeDelay
=
1
;
public
KeyCode
enableDisableKey
=
KeyCode
.
Alpha1
;
public
List
<
TreeType
>
types
=
new
();
public
List
<
TreeType
>
types
=
new
();
private
bool
allowSpawning
=
true
;
private
bool
allowSpawning
=
true
;
private
Dictionary
<
Vector2Int
,
TreeTile
>
treeDatabase
=
new
();
private
Dictionary
<
Vector2Int
,
TreeTile
>
treeDatabase
=
new
();
private
Dictionary
<
Vector2Int
,
TreeTile
>
activeTiles
=
new
();
private
Dictionary
<
Vector2Int
,
TreeTile
>
activeTiles
=
new
();
private
List
<
int
>
freeTreeSlots
=
new
();
private
Task
updateMatricesTask
;
private
Task
updateMatricesTask
;
private
bool
isDone
;
private
bool
isDone
;
// Variables copied from mainthread so can be accessed in other thread.
// Variables copied from mainthread so can be accessed in other thread.
Vector3
cameraPosition
;
private
Vector3
cameraPosition
;
float
unityTime
;
private
float
unityTime
;
private
System
.
Random
random
;
public
void
SetGPSCoord
(
Dictionary
<
string
,
string
>
boundaryData
)
public
void
SetGPSCoord
(
Dictionary
<
string
,
string
>
boundaryData
)
{
{
var
wgs84Lat
=
double
.
Parse
(
boundaryData
[
"gpsx"
]
);
var
wgs84Lat
=
double
.
Parse
(
boundaryData
[
"gpsx"
]
);
var
wgs84Lon
=
double
.
Parse
(
boundaryData
[
"gpsy"
]
);
var
wgs84Lon
=
double
.
Parse
(
boundaryData
[
"gpsy"
]
);
var
boundsSize
=
float
.
Parse
(
boundaryData
[
"boundsSize"
]
);
var
boundsSize
=
float
.
Parse
(
boundaryData
[
"boundsSize"
]
);
wgs84Origin
=
new
Vector2
(
(
float
)
wgs84Lat
,
(
float
)
wgs84Lon
);
wgs84Origin
=
new
Vector2
(
(
float
)
wgs84Lat
,
(
float
)
wgs84Lon
);
tileSize
=
float
.
Parse
(
boundaryData
[
"tileSize"
]
);
tileSize
=
float
.
Parse
(
boundaryData
[
"tileSize"
]
);
...
@@ -84,6 +88,18 @@ namespace Wander
...
@@ -84,6 +88,18 @@ namespace Wander
await
updateMatricesTask
;
await
updateMatricesTask
;
updateMatricesTask
=
null
;
updateMatricesTask
=
null
;
}
}
foreach
(
var
type
in
types
)
{
if
(
type
.
positions
==
null
)
continue
;
for
(
int
i
=
0
;
i
<
4
;
i
++)
{
if
(
type
.
positions
[
i
]
!=
null
&&
type
.
positions
[
i
].
IsCreated
)
{
type
.
positions
[
i
].
Dispose
();
}
}
}
}
}
private
void
Start
()
private
void
Start
()
...
@@ -91,6 +107,8 @@ namespace Wander
...
@@ -91,6 +107,8 @@ namespace Wander
if
(!
Application
.
isPlaying
)
if
(!
Application
.
isPlaying
)
return
;
return
;
random
=
new
System
.
Random
();
// In case no camera can be found, we have at least a valid position in other thread.
// In case no camera can be found, we have at least a valid position in other thread.
cameraPosition
=
transform
.
position
;
cameraPosition
=
transform
.
position
;
...
@@ -98,7 +116,23 @@ namespace Wander
...
@@ -98,7 +116,23 @@ namespace Wander
if
(
targetCam
==
null
)
if
(
targetCam
==
null
)
{
{
targetCam
=
Camera
.
main
;
targetCam
=
Camera
.
main
;
}
}
// Initially each slot in the matrix arrea is free.
foreach
(
var
type
in
types
)
{
Debug
.
Assert
(
type
.
type
!=
null
,
"No type specified."
);
type
.
currentCount
=
new
int
[
4
];
type
.
positions
=
new
NativeArray
<
Matrix4x4
>[
4
];
for
(
int
i
=
0
;
i
<
4
;
i
++)
{
type
.
positions
[
i
]
=
new
NativeArray
<
Matrix4x4
>(
type
.
maxTrees
,
Allocator
.
Persistent
);
for
(
int
j
=
0
;
j
<
type
.
positions
[
i
].
Length
;
j
++)
{
type
.
positions
[
i
][
j
]
=
Matrix4x4
.
TRS
(
Vector3
.
zero
,
Quaternion
.
identity
,
Vector3
.
zero
);
}
}
}
// Load tree database.
// Load tree database.
Addressables
.
LoadAssetAsync
<
TextAsset
>(
"Assets/"
+
areaName
+
"/trees.csv"
).
Completed
+=
(
operation
)
=>
Addressables
.
LoadAssetAsync
<
TextAsset
>(
"Assets/"
+
areaName
+
"/trees.csv"
).
Completed
+=
(
operation
)
=>
...
@@ -110,17 +144,21 @@ namespace Wander
...
@@ -110,17 +144,21 @@ namespace Wander
}
}
// Cannot acccess .text in other thread, so obtain ptr first.
// Cannot acccess .text in other thread, so obtain ptr first.
var
text
=
operation
.
Result
.
text
;
var
text
=
operation
.
Result
.
text
;
Task
.
Run
(
()
=>
updateMatricesTask
=
Task
.
Run
(
()
=>
{
{
// Read tree database.
try
ReadTreeDb
(
text
);
{
// Read tree database.
// Initially all matrix slots are free.
ReadTreeDb
(
text
);
InitializeFreeMatriceSlots
();
// Update matrices in the background.
// Update matrices in the background.
UpdateLoopOtherThread
();
UpdateLoopOtherThread
();
}
catch
(
Exception
e
)
{
Debug
.
LogException
(
e
);
}
}
);
}
);
};
};
...
@@ -131,7 +169,7 @@ namespace Wander
...
@@ -131,7 +169,7 @@ namespace Wander
if
(!
Application
.
isPlaying
)
if
(!
Application
.
isPlaying
)
return
;
return
;
if
(
Input
.
GetKeyDown
(
KeyCode
.
Alpha1
))
if
(
Input
.
GetKeyDown
(
enableDisableKey
))
{
{
allowSpawning
=
!
allowSpawning
;
allowSpawning
=
!
allowSpawning
;
}
}
...
@@ -141,6 +179,40 @@ namespace Wander
...
@@ -141,6 +179,40 @@ namespace Wander
unityTime
=
Time
.
time
;
unityTime
=
Time
.
time
;
cameraPosition
=
targetCam
.
transform
.
position
;
cameraPosition
=
targetCam
.
transform
.
position
;
}
}
RenderTrees
();
}
void
RenderTrees
()
{
for
(
int
i
=
0
;
i
<
types
.
Count
;
i
++)
{
for
(
int
lod
=
0
;
lod
<
4
;
lod
++)
{
if
(
types
[
i
].
type
.
transform
.
childCount
==
lod
)
break
;
var
tr
=
types
[
i
].
type
.
transform
.
GetChild
(
lod
);
// LOD0;
var
mesh
=
tr
.
GetComponent
<
MeshFilter
>().
sharedMesh
;
var
materials
=
tr
.
GetComponent
<
MeshRenderer
>().
sharedMaterials
;
int
totalNum
=
types
[
i
].
currentCount
[
lod
];
int
offset
=
0
;
while
(
totalNum
>
0
)
{
int
numToRender
=
Math
.
Min
(
1023
,
totalNum
);
for
(
int
j
=
0
;
j
<
mesh
.
subMeshCount
;
j
++)
{
RenderParams
rp
=
new
RenderParams
(
materials
[
j
]);
Graphics
.
RenderMeshInstanced
(
rp
,
mesh
,
j
,
types
[
i
].
positions
[
lod
],
numToRender
,
offset
);
}
totalNum
-=
numToRender
;
offset
+=
numToRender
;
}
}
}
}
}
void
ReadTreeDb
(
string
text
)
void
ReadTreeDb
(
string
text
)
...
@@ -169,36 +241,38 @@ namespace Wander
...
@@ -169,36 +241,38 @@ namespace Wander
Debug
.
LogError
(
"On Line "
+
line
);
Debug
.
LogError
(
"On Line "
+
line
);
}
}
}
}
}
}
void
InitializeFreeMatriceSlots
()
private
void
UpdateLoopOtherThread
()
{
{
// Initially each slot in the matrix arrea is free.
while
(!
isDone
)
foreach
(
var
type
in
types
)
{
{
type
.
freeSlots
=
new
();
LoadDesiredTiles
();
for
(
int
i
=
0
;
i
<
type
.
maxTrees
;
i
++)
SpawnTrees
();
DespawnTrees
();
int
newActiveCount
=
0
;
types
.
ForEach
(
t
=>
{
{
freeTreeSlots
.
Add
(
i
);
for
(
int
i
=
0
;
i
<
4
;
i
++)
}
{
newActiveCount
+=
t
.
currentCount
[
i
];
}
});
activeTreeCount
=
newActiveCount
;
Thread
.
Sleep
(
100
);
}
}
}
}
private
void
UpdateLoopOtherThread
(
)
int
CalcLod
(
Vector3
pos
)
{
{
LoadDesiredTiles
();
float
dist
=
Vector3
.
Distance
(
cameraPosition
,
pos
);
SpawnTrees
();
int
lod
=
Mathf
.
RoundToInt
(
dist
/
400
);
DespawnTrees
();
return
lod
;
activeTreeCount
=
0
;
types
.
ForEach
(
t
=>
{
activeTreeCount
+=
t
.
maxTrees
-
t
.
freeSlots
.
Count
;
}
);
}
}
void
LoadIfIsNewTile
(
Vector2Int
centre
,
int
dx
,
int
dy
)
void
LoadIfIsNewTile
(
Vector2Int
centre
,
int
dx
,
int
dy
,
float
time
)
{
{
var
coord
=
centre
+
new
Vector2Int
(
dx
,
dy
);
var
coord
=
centre
+
new
Vector2Int
(
dx
,
dy
);
if
(!
activeTiles
.
TryGetValue
(
coord
,
out
var
activeTile
))
if
(!
activeTiles
.
TryGetValue
(
coord
,
out
var
activeTile
))
...
@@ -207,15 +281,22 @@ namespace Wander
...
@@ -207,15 +281,22 @@ namespace Wander
{
{
activeTiles
.
Add
(
coord
,
dbTile
);
activeTiles
.
Add
(
coord
,
dbTile
);
activeTile
=
dbTile
;
activeTile
=
dbTile
;
activeTile
.
spawnedTrees
.
Clear
();
activeTile
.
originTime
=
unityTime
;
activeTile
.
spawnIndex
=
0
;
activeTile
.
worldPos
=
new
Vector3
(
dx
,
0
,
dy
)*
tileSize
+
new
Vector3
(
tileSize
,
0
,
tileSize
)
*
0.5f
;
activeTile
.
spawned
=
true
;
activeTile
.
lod
=
-
1
;
activeTile
.
originTime
=
time
;
if
(
activeTile
.
offsetAndNumPerType
==
null
)
{
activeTile
.
offsetAndNumPerType
=
new
Dictionary
<
int
,
(
int
offset
,
int
num
)>();
}
else
{
activeTile
.
offsetAndNumPerType
.
Clear
();
}
}
}
}
}
if
(
activeTile
!=
null
)
if
(
activeTile
!=
null
)
{
{
activeTile
.
lastTime
=
t
ime
;
activeTile
.
lastTime
=
unityT
ime
;
}
}
}
}
...
@@ -257,73 +338,112 @@ namespace Wander
...
@@ -257,73 +338,112 @@ namespace Wander
{
{
float
tpx
=
cameraPosition
.
x
;
float
tpx
=
cameraPosition
.
x
;
float
tpy
=
cameraPosition
.
z
;
float
tpy
=
cameraPosition
.
z
;
float
time
=
unityTime
;
var
rdX
=
Mathf
.
FloorToInt
(
(
float
)((
originRDX
+
tpx
)
*
0.01f
));
var
rdX
=
Mathf
.
FloorToInt
(
(
float
)((
originRDX
+
tpx
)
*
0.01f
));
var
rdY
=
Mathf
.
FloorToInt
(
(
float
)((
originRDY
+
tpy
)
*
0.01f
));
var
rdY
=
Mathf
.
FloorToInt
(
(
float
)((
originRDY
+
tpy
)
*
0.01f
));
var
centreTile
=
new
Vector2Int
(
rdX
,
rdY
);
var
centreTile
=
new
Vector2Int
(
rdX
,
rdY
);
LoadIfIsNewTile
(
centreTile
,
0
,
0
,
time
);
LoadIfIsNewTile
(
centreTile
,
0
,
0
);
for
(
int
c
=
1
;
c
<=
numRings
;
c
++)
for
(
int
c
=
1
;
c
<=
numRings
;
c
++)
{
{
for
(
int
y2
=
-
c
;
y2
<=
c
;
y2
++)
for
(
int
y2
=
-
c
;
y2
<=
c
;
y2
++)
{
{
LoadIfIsNewTile
(
centreTile
,
-
c
,
y2
,
time
);
LoadIfIsNewTile
(
centreTile
,
-
c
,
y2
);
}
}
for
(
int
y2
=
-
c
;
y2
<=
c
;
y2
++)
for
(
int
y2
=
-
c
;
y2
<=
c
;
y2
++)
{
{
LoadIfIsNewTile
(
centreTile
,
c
,
y2
,
time
);
LoadIfIsNewTile
(
centreTile
,
c
,
y2
);
}
}
for
(
int
x2
=
-
c
+
1
;
x2
<=
c
-
1
;
x2
++)
for
(
int
x2
=
-
c
+
1
;
x2
<=
c
-
1
;
x2
++)
{
{
LoadIfIsNewTile
(
centreTile
,
x2
,
c
,
time
);
LoadIfIsNewTile
(
centreTile
,
x2
,
c
);
}
}
for
(
int
x2
=
-
c
+
1
;
x2
<=
c
-
1
;
x2
++)
for
(
int
x2
=
-
c
+
1
;
x2
<=
c
-
1
;
x2
++)
{
{
LoadIfIsNewTile
(
centreTile
,
x2
,
-
c
,
time
);
LoadIfIsNewTile
(
centreTile
,
x2
,
-
c
);
}
}
}
}
}
}
void
RemoveTileFromTypeArrays
(
TreeTile
tile
,
int
oldLod
)
{
if
(
oldLod
==
-
1
)
return
;
foreach
(
var
spawnees
in
tile
.
offsetAndNumPerType
)
{
var
type
=
spawnees
.
Key
;
var
offset
=
spawnees
.
Value
.
offset
;
var
numSpawn
=
spawnees
.
Value
.
num
;
var
numToMove
=
types
[
type
].
currentCount
[
oldLod
]
-
(
offset
+
numSpawn
);
for
(
int
i
=
0
;
i
<
numToMove
;
i
++)
{
types
[
type
].
positions
[
oldLod
][
offset
+
i
]
=
types
[
type
].
positions
[
oldLod
][
offset
+
i
+
numSpawn
];
}
types
[
type
].
currentCount
[
oldLod
]
-=
numSpawn
;
}
tile
.
offsetAndNumPerType
.
Clear
();
}
void
SpawnTrees
()
void
SpawnTrees
()
{
{
foreach
(
var
kvp
in
activeTiles
)
foreach
(
var
kvp
in
activeTiles
)
{
{
var
tile
=
kvp
.
Value
;
var
tile
=
kvp
.
Value
;
if
(
Time
.
time
-
tile
.
originTime
<
requiredTime
)
// Only start spawning trees from tile, if certain time tile is requested.
if
(
unityTime
-
tile
.
originTime
<
requiredTime
)
{
{
continue
;
continue
;
}
}
while
(
tile
.
spawnIndex
<
tile
.
treeDb
.
Count
)
{
if
(
freeTreeSlots
.
Count
==
0
)
break
;
var
treeDb
=
tile
.
treeDb
[
tile
.
spawnIndex
];
tile
.
spawnIndex
++;
var
treeType
=
Mathf
.
RoundToInt
(
treeDb
.
z
);
// Only change trees, when lod has changed of tile.
if
(!(
treeType
>=
0
&&
treeType
<
treenGenerator
.
types
.
Count
))
int
newLod
=
Mathf
.
Clamp
(
CalcLod
(
tile
.
worldPos
),
0
,
3
);
continue
;
if
(
newLod
==
tile
.
lod
)
{
continue
;
}
int
oldLod
=
tile
.
lod
;
tile
.
lod
=
newLod
;
RemoveTileFromTypeArrays
(
tile
,
oldLod
);
var
treePrefab
=
treenGenerator
.
types
[
treeType
].
trees
.
Random
();
// For each tree in tile, see if the type of tree can be spawned as there are max tree counts per type.
if
(
treePrefab
==
null
)
for
(
int
i
=
0
;
i
<
tile
.
treeDb
.
Count
;
i
++)
continue
;
{
var
treeDb
=
tile
.
treeDb
[
i
];
var
type
=
Mathf
.
RoundToInt
(
treeDb
.
z
);
var
treePos
=
new
Vector3
(
(
float
)(
treeDb
.
x
-
originRDX
),
0
,
(
float
)(
treeDb
.
y
-
originRDY
)
);
// If type is invalid, continue to next. Don't spawn this one.
if
(
type
<
0
||
type
>=
types
.
Count
)
{
continue
;
}
// See if free slot available.
if
(
HeightFromTerrains
(
tile
,
treePos
,
out
float
height
))
if
(
types
[
type
].
currentCount
[
newLod
]
<
types
[
type
].
positions
[
newLod
].
Length
)
{
{
var
slot
=
freeTreeSlots
.
Last
();
// Find out offset on type per lod.
freeTreeSlots
.
RemoveAt
(
freeTreeSlots
.
Count
-
1
);
int
offset
=
types
[
type
].
currentCount
[
newLod
]++;
tile
.
spawnedTrees
.
Add
(
slot
);
var
tree
=
treeRoot
.
transform
.
GetChild
(
slot
);
tree
.
transform
.
position
=
treePos
+
new
Vector3
(
0
,
height
-
100
,
0
);
var
lg
=
tree
.
gameObject
.
GetComponent
<
LODGroup
>();
lg
.
ForceLOD
(
-
1
);
}
// Obtain tree position.
var
treePos
=
new
Vector3
(
(
float
)(
treeDb
.
x
-
originRDX
),
20
,
(
float
)(
treeDb
.
y
-
originRDY
)
);
// Set position on type per lod, using offset.
types
[
type
].
positions
[
newLod
][
offset
]
=
Matrix4x4
.
TRS
(
treePos
,
Quaternion
.
Euler
(
0
,
random
.
Next
()%
360
,
0
),
Vector3
.
one
);
// Remember the offset and num spawned per type. Because need to move per type num away, to avoid rendering instances that are not visible (vertex processor is invoked).
if
(!
tile
.
offsetAndNumPerType
.
TryGetValue
(
type
,
out
var
offsetAndType
))
{
tile
.
offsetAndNumPerType
.
Add
(
type
,
(
offset
,
1
)
);
}
else
{
offsetAndType
.
num
++;
}
}
}
}
}
}
}
}
...
@@ -334,25 +454,23 @@ namespace Wander
...
@@ -334,25 +454,23 @@ namespace Wander
foreach
(
var
kvp
in
activeTiles
)
foreach
(
var
kvp
in
activeTiles
)
{
{
var
tile
=
kvp
.
Value
;
var
tile
=
kvp
.
Value
;
if
(
tile
.
lastTime
-
Time
.
time
<
-
removeDelay
)
// Only despawn tile if certain time not desired anymore. This to avoid flipping in and out.
if
(
tile
.
lastTime
-
unityTime
<
-
removeDelay
)
{
{
if
(
tile
.
spawnedTrees
.
Count
!=
0
)
// Remove trees for type arrays.
{
RemoveTileFromTypeArrays
(
tile
,
tile
.
lod
);
for
(
int
i
=
0
;
i
<
tile
.
spawnedTrees
.
Count
;
i
++
)
{
treeRoot
.
transform
.
GetChild
(
tile
.
spawnedTrees
[
i
]
).
gameObject
.
GetComponent
<
LODGroup
>().
ForceLOD
(
4
);
}
freeTreeSlots
.
AddRange
(
tile
.
spawnedTrees
);
tile
.
spawnedTrees
.
Clear
();
if
(
removeList
==
null
)
// Initialize remove list if was not used yet.
removeList
=
new
();
if
(
removeList
==
null
)
removeList
.
Add
(
kvp
.
Key
);
removeList
=
new
();
kvp
.
Value
.
spawned
=
false
;
}
// Add this tile to remove list.
removeList
.
Add
(
kvp
.
Key
);
}
}
}
}
// Remove actual inactive tiles.
removeList
?.
ForEach
(
rm
=>
removeList
?.
ForEach
(
rm
=>
{
{
activeTiles
.
Remove
(
rm
);
activeTiles
.
Remove
(
rm
);
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment