Lagrange
Loading...
Searching...
No Matches
Scene.h
1/*
2 * Copyright 2023 Adobe. All rights reserved.
3 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License. You may obtain a copy
5 * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 *
7 * Unless required by applicable law or agreed to in writing, software distributed under
8 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 * OF ANY KIND, either express or implied. See the License for the specific language
10 * governing permissions and limitations under the License.
11 */
12#pragma once
13
14#include <lagrange/SurfaceMesh.h>
15#include <lagrange/common.h>
16#include <lagrange/fs/filesystem.h>
17#include <lagrange/internal/SafeVector.h>
18#include <lagrange/internal/constants.h>
19#include <lagrange/scene/SceneExtension.h>
20#include <lagrange/scene/api.h>
21#include <lagrange/utils/invalid.h>
22
23#include <Eigen/Geometry>
24
25#include <optional>
26#include <string>
27#include <vector>
28
29namespace lagrange {
30
35enum class AttributeValueType : uint8_t;
36
37} // namespace lagrange
38
39namespace lagrange::scene {
40
41using ElementId = size_t;
42constexpr ElementId invalid_element = lagrange::invalid<ElementId>();
43
44// Used in Node, it pairs a mesh with its materials (zero, one, or more).
45struct LA_SCENE_API SceneMeshInstance
46{
47 // Mesh index. Has to be a valid index in the scene.meshes vector.
48 ElementId mesh = invalid_element;
49
50 // Material indices in the scene.materials vector. This is typically a single material index.
51 // When a single mesh uses multiple materials,
52 // the AttributeName::material_id facet attribute should be defined.
53 SafeVector<ElementId> materials;
54};
55
56// Represents a node in the scene hierarchy.
57struct LA_SCENE_API Node
58{
59 // Note that the node name may not be unique, and can be empty.
60 std::string name;
61
62 // Transform of the node, relative to its parent (maps node coords -> parent coords).
63 Eigen::Affine3f transform = Eigen::Affine3f::Identity();
64
65 // parent index. May be invalid if the node has no parent (e.g. the root).
66 ElementId parent = invalid_element;
67
68 // children indices. May be empty.
69 SafeVector<ElementId> children;
70
71 // List of meshes contained in this node.
72 // Node that some file formats only allow 1 mesh per node (gltf). In this case we treat
73 // multiple meshes as one mesh with multiple primitives, and only one material per mesh is
74 // allowed.
75 SafeVector<SceneMeshInstance> meshes;
76
77 // List of cameras contained in this node.
78 SafeVector<ElementId> cameras;
79
80 // List of lights contained in this node.
81 SafeVector<ElementId> lights;
82
83 Extensions extensions;
84};
85
89struct LA_SCENE_API ImageBufferExperimental
90{
92 size_t width = 0;
93
95 size_t height = 0;
96
98 size_t num_channels = 4;
99
102
104 std::vector<unsigned char> data;
105
109 size_t get_bits_per_element() const;
110};
111
115struct LA_SCENE_API ImageExperimental
116{
118 std::string name;
119
122
125 fs::path uri;
126
129};
130
131
132// Pair of texture index (which texture to use) and texture coordinate index (which set of UVs to
133// use).
134struct LA_SCENE_API TextureInfo
135{
137 ElementId index = invalid_element;
138
141 int texcoord = 0;
142};
143
144// PBR material, based on the gltf specification.
145// This is subject to change, to support more material models.
146struct LA_SCENE_API MaterialExperimental
147{
148 // Note that material name may not be unique, and can be empty.
149 std::string name;
150
151 Eigen::Vector4f base_color_value = Eigen::Vector4f::Ones();
152 TextureInfo base_color_texture;
153
154 Eigen::Vector3f emissive_value = Eigen::Vector3f::Zero();
155 TextureInfo emissive_texture;
156
157 // metalness and roughness are packed together in a single texture.
158 // green channel has roughness, blue channel has metalness.
159 TextureInfo metallic_roughness_texture;
160 float metallic_value = 1.f;
161 float roughness_value = 1.f;
162
163 // The alpha mode specifies how to interpret the alpha value of the base color.
164 enum class AlphaMode {
165 Opaque, // Alpha is ignored, and rendered output is opaque
166 Mask, // Output is either opaque or transparent depending on the alpha value and the
167 // alpha_cutoff value.
168 Blend // Alpha value is used to composite source and destination.
169 };
170 AlphaMode alpha_mode = AlphaMode::Opaque;
171 float alpha_cutoff = 0.5f;
172
173
174 // normal = normalize(<sampled tex value> * 2 - 1) * vec3(scale, scale, 1)
175 float normal_scale = 1.f;
176 TextureInfo normal_texture;
177
178 // color = lerp(color, color * <sampled tex value>, strength)
179 float occlusion_strength = 1.f;
180 TextureInfo occlusion_texture;
181
182 bool double_sided = false;
183
184 Extensions extensions;
185};
186
187struct LA_SCENE_API Texture
188{
189 std::string name;
190 ElementId image = invalid_element; // index of image in scene.images vector
191
192 enum TextureFilter : int {
193 Undefined = 0,
194 Nearest = 9728,
195 Linear = 9729,
196 NearestMipmapNearest = 9984,
197 LinearMipmapNearest = 9985,
198 NearestMipmapLinear = 9986,
199 LinearMipmapLinear = 9987
200 };
201 // Texture magnification filter, used when texture appears larger on screen than the source
202 // image. Allowed values are UNDEFINED, NEAREST, LINEAR
203 TextureFilter mag_filter = TextureFilter::Undefined;
204
205 // Texture minification filter, used when the texture appears smaller on screen than the source
206 // image. Allowed values are: UNDEFINED, NEAREST, LINEAR, NEAREST_MIPMAP_NEAREST,
207 // LINEAR_MIPMAP_NEAREST, NEAREST_MIPMAP_LINEAR, LINEAR_MIPMAP_LINEAR
208 TextureFilter min_filter = TextureFilter::Undefined;
209
210 enum class WrapMode {
211 Wrap, // u|v becomes u%1|v%1
212 Clamp, // coordinates outside [0, 1] are clamped to the nearest value
213 Decal, // If the texture coordinates for a pixel are outside [0, 1], the texture is not
214 // applied
215 Mirror
216 };
217 WrapMode wrap_u = WrapMode::Wrap;
218 WrapMode wrap_v = WrapMode::Wrap;
219
220 Eigen::Vector2f scale = Eigen::Vector2f::Ones();
221 Eigen::Vector2f offset = Eigen::Vector2f::Zero();
222 float rotation = 0.0f;
223
224 Extensions extensions;
225};
226
227struct LA_SCENE_API Light
228{
229 std::string name;
230
231 enum class Type { Undefined, Directional, Point, Spot, Ambient, Area };
232 Type type = Type::Undefined;
233
234 // note that the light is part of the scene graph, and has an associated transform in its node.
235 // The values below (position, up, look_at) are relative to the coordinate system defined by the
236 // node.
237 Eigen::Vector3f position = Eigen::Vector3f::Zero();
238 Eigen::Vector3f direction = Eigen::Vector3f(0, 1, 0);
239 Eigen::Vector3f up = Eigen::Vector3f(0, 0, 1);
240
241 // Attenuation factor. Intensity of light at a given distance 'd' is:
242 // intensity / (attenuation_constant
243 // + attenuation_linear * d
244 // + attenuation_quadratic * d * d
245 // + attenuation_cubic * d * d * d)
246 float intensity = 1.f;
247 float attenuation_constant = 1.f;
248 float attenuation_linear = 0.f;
249 float attenuation_quadratic = 0.f;
250 float attenuation_cubic = 0.f;
251
252 // Range is defined for point and spot lights. It defines a distance cutoff at which the
253 // light intensity is to be considered zero, so the light does not affects objects beyond this
254 // range. When the value is 0, range is assumed to be infinite.
255 float range = 0.0;
256
257 // Colors
258 Eigen::Vector3f color_diffuse = Eigen::Vector3f::Zero();
259 Eigen::Vector3f color_specular = Eigen::Vector3f::Zero();
260 Eigen::Vector3f color_ambient = Eigen::Vector3f::Zero();
261
262 // inner and outer angle of a spot light's light cone
263 // they are both 2PI for point lights, and undefined for directional lights.
264 float angle_inner_cone;
265 float angle_outer_cone;
266
267 // size of area light source
268 Eigen::Vector2f size = Eigen::Vector2f::Zero();
269
270 Extensions extensions;
271};
272
273struct LA_SCENE_API Camera
274{
275 // note that the camera is part of the scene graph, and has an associated transform in its node.
276 // The values below (position, up, look_at) are relative to the coordinate system defined by the
277 // node.
278 std::string name;
279 Eigen::Vector3f position = Eigen::Vector3f::Zero();
280 Eigen::Vector3f up = Eigen::Vector3f(0, 1, 0);
281 Eigen::Vector3f look_at = Eigen::Vector3f(0, 0, -1);
282
283 // Distance of the near clipping plane. This value cannot be 0.
284 float near_plane = 0.1f;
285
286 // Distance of the far clipping plane. Required for orthographic cameras, optional for
287 // perspective ones.
288 std::optional<float> far_plane = 1000.f;
289
290 enum class Type { Perspective, Orthographic };
291 Type type = Type::Perspective;
292
293 // Half width of the orthographic view box. Or horizontal magnification.
294 //
295 // This is only defined when the camera type is orthographic, otherwise it should be 0.
296 float orthographic_width = 0.f;
297
298 // Screen aspect ratio. This is the value of width / height of the screen.
299 //
300 // aspect_ratio = tan(horizontal_fov / 2) / tan(vertical_fov / 2)
301 //
302 // So we can compute any of those 3 variables from any 2. We store 2 (aspect_ratio and
303 // horizontal_fov) and provide utilities below to compute any of them from the other 2.
304 float aspect_ratio = 1.f;
305
306 // horizontal field of view angle, in radians.
307 //
308 // This is the angle between the left and right borders of the viewport.
309 // It should not be greater than Pi.
310 //
311 // fov is only defined when the camera type is perspective, otherwise it should be 0.
312 float horizontal_fov = (float)lagrange::internal::pi_2;
313
314 // convenience methods to get or set the vertical fov instead.
315 // make sure aspect_ratio is set before calling those!
316 float get_vertical_fov() const
317 {
318 return 2.f * std::atan(std::tan(horizontal_fov * 0.5f) / aspect_ratio);
319 }
320 void set_horizontal_fov_from_vertical_fov(float vfov)
321 {
322 horizontal_fov = 2.f * std::atan(std::tan(vfov * 0.5f) * aspect_ratio);
323 }
324 void set_aspect_ratio_from_fov(float vfov, float hfov)
325 {
326 aspect_ratio = std::tan(hfov * 0.5f) / std::tan(vfov * 0.5f);
327 }
328
329 Extensions extensions;
330};
331
332struct LA_SCENE_API Animation
333{
334 std::string name;
335 // TODO
336
337 Extensions extensions;
338};
339
340struct LA_SCENE_API Skeleton
341{
342 // This skeleton is used to deform those meshes.
343 // This will typically contain one value, but can have zero or multiple meshes.
344 // The value is the index in the scene meshes.
345 SafeVector<ElementId> meshes;
346 // TODO
347
348 Extensions extensions;
349};
350
351template <typename Scalar, typename Index>
352struct Scene
353{
354 using MeshType = SurfaceMesh<Scalar, Index>;
355
356 // Name of the scene
357 std::string name;
358
359 // Scene nodes. This is a list of nodes, the hierarchy information is contained by each
360 // node having a list of children as indices to this vector.
361 SafeVector<Node> nodes;
362
363 // Root nodes. This is typically one. Must be at least one.
364 SafeVector<ElementId> root_nodes;
365
366 // Scene meshes.
367 SafeVector<MeshType> meshes;
368
369 // Images.
370 SafeVector<ImageExperimental> images;
371
372 // Textures. They can reference images;
373 SafeVector<Texture> textures;
374
375 // Materials. They can reference textures.
376 SafeVector<MaterialExperimental> materials;
377
378 // Lights in the scene.
379 SafeVector<Light> lights;
380
381 // Cameras. The first camera (if any) is the default camera view.
382 SafeVector<Camera> cameras;
383
384 // Scene skeletons.
385 SafeVector<Skeleton> skeletons;
386
387 // Unused for now.
388 SafeVector<Animation> animations;
389
390 // Extensions.
391 Extensions extensions;
392
393public:
402 template <typename T>
403 ElementId add(T&& value);
404
412 void add_child(ElementId parent_id, ElementId child_id);
413};
414
415template <typename Scalar, typename Index>
416template <typename T>
417ElementId Scene<Scalar, Index>::add(T&& value)
418{
419 using ElementType = std::decay_t<T>;
420 if constexpr (std::is_same_v<ElementType, Node>) {
421 nodes.emplace_back(std::forward<T>(value));
422 return nodes.size() - 1;
423 } else if constexpr (std::is_same_v<ElementType, MeshType>) {
424 meshes.emplace_back(std::forward<T>(value));
425 return meshes.size() - 1;
426 } else if constexpr (std::is_same_v<ElementType, ImageExperimental>) {
427 images.emplace_back(std::forward<T>(value));
428 return images.size() - 1;
429 } else if constexpr (std::is_same_v<ElementType, Texture>) {
430 textures.emplace_back(std::forward<T>(value));
431 return textures.size() - 1;
432 } else if constexpr (std::is_same_v<ElementType, MaterialExperimental>) {
433 materials.emplace_back(std::forward<T>(value));
434 return materials.size() - 1;
435 } else if constexpr (std::is_same_v<ElementType, Light>) {
436 lights.emplace_back(std::forward<T>(value));
437 return lights.size() - 1;
438 } else if constexpr (std::is_same_v<ElementType, Camera>) {
439 cameras.emplace_back(std::forward<T>(value));
440 return cameras.size() - 1;
441 } else if constexpr (std::is_same_v<ElementType, Skeleton>) {
442 skeletons.emplace_back(std::forward<T>(value));
443 return skeletons.size() - 1;
444 } else if constexpr (std::is_same_v<ElementType, Animation>) {
445 animations.emplace_back(std::forward<T>(value));
446 return animations.size() - 1;
447 } else {
448 static_assert(StaticAssertableBool<T>::False, "Unsupported type");
449 }
450}
451
452using Scene32f = Scene<float, uint32_t>;
453using Scene32d = Scene<double, uint32_t>;
454using Scene64f = Scene<float, uint64_t>;
455using Scene64d = Scene<double, uint64_t>;
456
457} // namespace lagrange::scene
A general purpose polygonal mesh class.
Definition SurfaceMesh.h:66
AttributeValueType
Enum describing at runtime the value type of an attribute.
Definition AttributeValueType.h:25
constexpr T invalid()
You can use invalid<T>() to get a value that can represent "invalid" values, such as invalid indices ...
Definition invalid.h:40
Main namespace for Lagrange.
Definition Scene.h:333
Definition Scene.h:274
Definition SceneExtension.h:194
Minimalistic image data structure that stores the raw image data.
Definition Scene.h:90
size_t height
Image height.
Definition Scene.h:95
size_t width
Image width.
Definition Scene.h:92
size_t get_bits_per_element() const
Get the size of an element in bits.
Definition Scene.cpp:32
AttributeValueType element_type
The scalar type of the elements in the buffer.
Definition Scene.h:101
std::vector< unsigned char > data
Raw buffer of size (width * height * num_channels * num_bits_per_element / 8) bytes containing image ...
Definition Scene.h:104
size_t num_channels
Number of image channels (must be 1, 3, or 4).
Definition Scene.h:98
Image structure that can store either image data or reference to an image file.
Definition Scene.h:116
Extensions extensions
Image extensions.
Definition Scene.h:128
ImageBufferExperimental image
Image data.
Definition Scene.h:121
std::string name
Image name. Not guaranteed to be unique and can be empty.
Definition Scene.h:118
fs::path uri
Image file path.
Definition Scene.h:125
Definition Scene.h:228
Definition Scene.h:58
Definition Scene.h:353
void add_child(ElementId parent_id, ElementId child_id)
Add a child node to a given parent node.
Definition Scene.cpp:19
ElementId add(T &&value)
Add an element to the scene.
Definition Scene.h:417
Definition Scene.h:341
Definition Scene.h:188
Definition Scene.h:135
int texcoord
Index of UV coordinates.
Definition Scene.h:141
ElementId index
Texture index. Index in scene.textures vector.
Definition Scene.h:137