1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
|
//-----------------------------------------------------------------------------
// Name: detailobjectsurface.h
// Developer: Wolfire Games LLC
// Description:
// License: Read below
//-----------------------------------------------------------------------------
//
//
// Copyright 2022 Wolfire Games LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-----------------------------------------------------------------------------
#pragma once
#include <Math/vec2.h>
#include <Math/vec4.h>
#include <Asset/Asset/objectfile.h>
#include <Asset/Asset/image_sampler.h>
#include <Utility/flat_hash_map.hpp>
#include <Graphics/drawbatch.h>
#include <vector>
#include <set>
#include <map>
class Model;
class LightProbeCollection;
class SceneGraph;
// One instance of a detail object
struct DetailInstance {
// mat4 transform; // Transformation matrix for this detail object - note: now stored separately for better bulk memory transfer patterns
vec2 tex_coord0; // Base texture coordinates for color/light matching - note: reduced to one coord because the other was not being used in drawing
float embed; // How embedded it is in the ground
float height_scale; // How much the height has been scaled
};
struct BatchVertex {
GLfloat px, py, pz; // position (0-12 bytes)
GLfloat nx, ny, nz; // normal (12-24 bytes)
GLfloat tx, ty, tz; // tangent (24-36 bytes)
GLfloat bx, by, bz; // bitangent (36-48 bytes)
GLfloat tu, tv; // texcoords (48-56 bytes)
float padding[2]; // (to reach 64 bytes)
};
// A patch containing many detail object instances
struct DOPatch {
bool calculated;
std::vector<int> tris;
std::vector<vec3> verts;
std::vector<vec3> normals;
std::vector<vec2> tex_coords;
std::vector<vec2> tex_coords2;
std::vector<DetailInstance> detail_instances;
std::vector<mat4> detail_instance_transforms;
std::vector<float> detail_instance_origins_x;
std::vector<float> detail_instance_origins_y;
std::vector<float> detail_instance_origins_z;
vec3 sphere_center;
float sphere_radius;
DOPatch();
};
// A comparable array of three ints
struct TriInt {
int val[3];
TriInt(int a = 0, int b = 0, int c = 0);
bool operator<(const TriInt &other) const;
bool operator==(const TriInt &other) const;
};
namespace std
{
template <>
struct hash<TriInt>
{
size_t operator()(const TriInt& k) const
{
// Compute individual hash values for first, second and third
// http://stackoverflow.com/a/1646913/126995
size_t res = 17;
res = res * 31 + hash<float>()( (const float)k.val[0] );
res = res * 31 + hash<float>()( (const float)k.val[1] );
res = res * 31 + hash<float>()( (const float)k.val[2] );
return res;
}
};
}
struct CalculatedPatch {
TriInt coords;
mutable float last_used_time;
bool operator<(const CalculatedPatch &other) const;
bool operator==(const CalculatedPatch &other) const;
};
namespace std
{
template <>
struct hash<CalculatedPatch>
{
size_t operator()(const CalculatedPatch& k) const
{
// Compute individual hash values for first, second and third
// http://stackoverflow.com/a/1646913/126995
size_t res = 17;
res = res * 31 + hash<TriInt>()(k.coords);
res = res * 31 + hash<float>()(k.last_used_time);
return res;
}
};
}
const unsigned batch_size = 40;
// A model that contains "batch_size" copies of a model to reduce draw calls
struct BatchModel {
bool created;
float height; // The height is important for controlling how embedded it is in the base surface
VBOContainer vboc; // The vbo containing the batch vertex, normal, and uv information
VBOContainer vboc_el; // The vbo containing the batch triangle indices
unsigned instance_num_faces; // The number of faces in each instance, so we can control how many instances we draw
void Create(const Model& model);
void Draw( const std::vector<DetailInstance> &di_vec, const std::vector<mat4> &di_vec_transforms );
BatchModel();
void StartDraw();
void StopDraw();
};
class DetailObjectSurface {
std::vector<DetailInstance> draw_detail_instances;
std::vector<mat4> draw_detail_instance_transforms;
BatchModel bm;
ObjectFileRef ofr;
const Model* base_model_ptr;
int detail_model_id;
std::vector<float> triangle_area;
typedef ska::flat_hash_map<TriInt, DOPatch> PatchesMap;
PatchesMap patches;
int bounding_box[6];
DrawBatch batch;
TextureAssetRef base_color_ref;
TextureAssetRef base_normal_ref;
ImageSamplerRef weight_map;
typedef ska::flat_hash_set<CalculatedPatch> CalculatedPatchesSet;
CalculatedPatchesSet calculated_patches;
float density;
float normal_conform;
float min_embed;
float max_embed;
float min_scale;
float max_scale;
float view_dist;
float overbright;
float jitter_degrees;
CollisionType collision_type;
bool double_sided;
public:
float tint_weight;
enum DetailObjectShaderType {TERRAIN, ENVOBJECT};
void AttachTo( const Model& model, mat4 transform );
void SetBaseTextures( const TextureAssetRef& color_ref, const TextureAssetRef& normal_ref );
void LoadDetailModel(const std::string &path);
void PreDrawCamera( const mat4 &transform );
//void GetTrisInSphere( const vec3 ¢er, float radius );
void Cluster();
void Draw( const mat4 &transform, DetailObjectShaderType shader_type, vec3 color_tint, const TextureRef& light_cube, LightProbeCollection* light_probe_collection, SceneGraph *scenegraph);
TriInt GetTriInt( const vec3 &pos );
void GetTrisInPatches( mat4 transform );
void CalcPatchInstances( const TriInt &coords, DOPatch &patch, mat4 transform );
void ClearPatch( DOPatch &patch );
void SetDensity( float _density );
void SetColorTint( const vec3& tint );
void SetNormalConform( float _normal_conform );
void SetMinEmbed( float _min_embed );
void SetMaxEmbed( float _max_embed );
void SetMinScale( float _min_scale );
void SetMaxScale( float _max_scale );
void LoadWeightMap( const std::string &weight_path );
void SetViewDist( float _view_dist );
void SetJitterDegrees( float _jitter_degrees );
void SetOverbright( float _overbright );
void SetCollisionType( CollisionType _collision );
};
|