p2p/stingray_sdk/plugin_foundation/scene_tree.h
Lucas Schwiderski 2c9ce46dd2
chore: Rework project structure
There likely won't be much need for multiple separate crates.
2023-05-26 23:42:01 +02:00

490 lines
12 KiB
C++

#pragma once
#include "matrix4x4.h"
#include "allocator.h"
#include "hash_function.h"
#include "hash_function_string.h"
#include "vector.h"
#include "hash_map.h"
#include "id_string.h"
namespace stingray_plugin_foundation {
enum ChannelType {
CT_FLOAT1 = 0,
CT_FLOAT2,
CT_FLOAT3,
CT_FLOAT4,
CT_MATRIX4x4,
CT_QUATERNION,
CT_FLOAT3_CMP_11_11_10,
CT_HALF1,
CT_HALF2,
CT_HALF3,
CT_HALF4,
CT_UBYTE4,
CT_SHORT1,
CT_SHORT2,
CT_SHORT3,
CT_SHORT4,
CT_COUNT
};
uint32_t channel_size(ChannelType type);
const char *Parameter_LocalTransform();
const char *Channel_LocalTransform();
const char *Channel_BlendShapeWeight();
// General container for storing data
struct Stream {
ALLOCATOR_AWARE;
Stream(Allocator &a) : data(a), channels(a), size(0), stride(0) { }
// Structure describing a single data channel in the stream
struct Channel {
ALLOCATOR_AWARE;
Channel(Allocator &a) : name(a) { }
// Semantic name of channel
DynamicString name;
// Semantic index of channel
unsigned index;
// Data contained within channel
ChannelType type;
};
// List of channels describing the contents of this stream
Vector<Channel> channels;
// Number of elements in stream
unsigned size;
// Stride in bytes between two elements
unsigned stride;
// Stream data
Array<char> data;
};
bool operator==(const Stream::Channel &lhs, const Stream::Channel &rhs);
bool operator!=(const Stream::Channel &lhs, const Stream::Channel &rhs);
typedef Vector<Stream> Streams;
// Structure that represents a scene node
struct Node {
ALLOCATOR_AWARE;
Node(Allocator &a) : parent(a), children(a), geometries(a), viewport_visible(true), has_local_mirroring(false) { }
// Name of parent (can be empty)
DynamicString parent;
// List with names of this nodes children
Vector<DynamicString> children;
// Local transformation matrix
Matrix4x4 local;
// List with names of geometries attached to this node
Vector<DynamicString> geometries;
// Initial visibility preference (overridden by renderables section of .unit)
bool viewport_visible;
// We keep this information here to avoid computing the local transform determinant
// every time we want to know whether the transform is mirrored or not.
// NOTE: we neither serialize this information but compute it from local once read.
bool has_local_mirroring;
void swap(Node &o) {
parent.swap(o.parent);
children.swap(o.children);
std::swap(local, o.local);
geometries.swap(o.geometries);
std::swap(viewport_visible, o.viewport_visible);
std::swap(has_local_mirroring, o.has_local_mirroring);
}
};
// Structure that represents mesh topology
struct Indices {
ALLOCATOR_AWARE;
Indices(Allocator &a) : streams(a), n_indices(0), type(TRIANGLE_LIST) { }
// Number of indices
unsigned n_indices;
// Primitive type - currently we are only handling TRIANGLE_LIST
enum PrimitiveType { TRIANGLE_LIST };
PrimitiveType type;
struct Stream {
ALLOCATOR_AWARE;
Stream(Allocator &a) : indices(a) { }
Array<unsigned> indices;
};
// List of indices for each stream in a mesh
Vector<Stream> streams;
};
// Structure describing a Skin modifier
struct Skin {
ALLOCATOR_AWARE;
Skin(Allocator &a) : joints(a), max_affecting_bones(0) { }
// Describes a skin joint
struct Joint {
ALLOCATOR_AWARE;
Joint(Allocator &a) : name(a) { }
// Name of joint
DynamicString name;
// Inverse bind matrix for joint
Matrix4x4 inv_bind_matrix;
};
// Formerly "Bind shape matrix for skin".
// This information is actually stored by cluster in FBX and there is no such
// global bind matrix anymore there. Nevertheless, it is used in BSI exporters
// so we keep it for backward-compatibility there and remove it from anywhere
// else, namely the engine.
#ifdef BSI_PLUGIN
Matrix4x4 bind_matrix;
#endif
// Maximum number of influences
unsigned max_affecting_bones;
// Skin joints
Vector<Joint> joints;
};
// Structure describing a mesh instance
struct GeometryInstance {
ALLOCATOR_AWARE;
GeometryInstance(Allocator &a) : geometry(a), materials(a) { }
DynamicString geometry;
Vector<DynamicString> materials;
};
// Structure describing a mesh
struct Geometry {
ALLOCATOR_AWARE;
Geometry(Allocator &a) : name(a), streams(a), indices(a), materials(a), skin(a), primitive_smoothing(a), blend_shape_targets(a), shadow_caster(true), vertex_position_remapping(a), vertex_normal_remapping(a) { }
DynamicString name;
// List of vertex data streams
Streams streams;
// Indices of mesh
Indices indices;
// Name of skin if mesh is skinned
DynamicString skin;
// Structure describing a mesh material
struct Material {
ALLOCATOR_AWARE;
Material(Allocator &a) : name(a), primitives(a) { }
// Material name
DynamicString name;
// List of primitive indices that the material is assigned to
Array<unsigned> primitives;
};
// List of materials assigned to this mesh
Vector<Material> materials;
// Per primitive smoothing group information
Array<unsigned> primitive_smoothing;
// Structure describing a blend shape target
struct BlendShapeTarget {
ALLOCATOR_AWARE;
BlendShapeTarget(Allocator &a) : name(a), streams(a) { }
// Name of blend_shape target
DynamicString name;
// Blend Shape Target vertex data streams
Streams streams;
};
// BlendShape targets
Vector<BlendShapeTarget> blend_shape_targets;
// Initial shadow preference (overridden by renderables section of .unit)
bool shadow_caster;
Array<unsigned> vertex_position_remapping;
Array<unsigned> vertex_normal_remapping;
};
// Structure describing a light
struct Light {
enum DefinitionType { // same enum values as found in: source\engine\engine\scene\light.h
OMNI = 0,
SPOT = 1,
BOX = 2,
DIRECTIONAL = 3
};
DefinitionType type;
float color[4];
float falloff_start; // units are meters
float falloff_end; // units are meters
float spot_angle_start; // radians
float spot_angle_end; // radians
bool cast_shadow;
};
// Structure describing a camera
struct Camera {
enum DefinitionType { // same enum values as found in source\engine\engine\scene\camera.h
ORTHOGRAPHIC,
PERSPECTIVE
};
DefinitionType type;
float near_plane; // units are meters
float far_plane; // units are meters
float vertical_fov; // units are radians
};
// Structure describing a animation.
// there are 4 types of animation curve :
// NODE_LOCAL_TRANSFORM : in this case, parameter == "local_tm". The animation has 1 channel of CT_MATRIX4x4 of name "matrix".
// NODE_PROPERTY : in this case, parameter is the name of the animated property. The animation has up to 4 channels of CT_FLOAT1 named "0","1","2","3"
// NODE_BLENDSHAPECHANNEL : in this case, parameter is the name of the blend shape channel. The animation has 1 channel of CT_FLOAT1 named "weight"
// MATERIAL_PROPERTY : in this case, parameter is the name of the animated property. The animation has up to 4 channels of CT_FLOAT1 named "0","1","2","3"
struct Animation {
ALLOCATOR_AWARE;
Animation(Allocator &a) : node(a), parameter(a), times(a), data(a) { }
bool is_local_transform_anim() const { return data.channels.size() == 1 && data.channels[0].type == CT_MATRIX4x4 && parameter == Parameter_LocalTransform() && data.channels[0].name == Channel_LocalTransform(); }
// Name of node this animation affects, or name of the material
DynamicString node;
// Name of affected parameter
DynamicString parameter;
// List of time keys
Array<float> times;
// Data stream containing the animation data (1:1 mapping with 'times' indices)
Stream data;
};
// Structure describing an animation take
struct AnimationTake {
ALLOCATOR_AWARE;
AnimationTake(Allocator &a) : animations(a), start_time(0), end_time(0), nb_samples(0) { }
// infos
float start_time;
float end_time;
unsigned nb_samples;
// animations for each node
Vector<Animation> animations;
};
// Structure describing a surface material
struct SurfaceMaterial {
ALLOCATOR_AWARE;
SurfaceMaterial(Allocator& a) : type(LAMBERT), properties(a), nb_influences(0) { }
// Type of definition
enum DefinitionType {
LAMBERT = 0,
PHONG = 1,
SHADER = 2
};
DefinitionType type;
// Next version, we should consider adding a Datatype attribute so we know what kind of data is stored
// by the property. This will help representing shaders parameters since they can be: bool, ints, enums,
// floats, etc...
struct Property {
ALLOCATOR_AWARE;
Property(Allocator& a) : n_integers(0), n_floats(0), name(a), value_string(a), textures(a) { }
unsigned n_integers;
int integer;
unsigned n_floats;
float floats[4];
DynamicString name;
DynamicString value_string;
// reference to textures attached to this property
Vector<DynamicString> textures;
};
typedef Vector<Property> Properties;
Properties properties;
// number of bones influences [0..4]
unsigned nb_influences;
};
// Structure describing a texture
struct Texture {
ALLOCATOR_AWARE;
Texture(Allocator& a) : file_path(a), relative_path(a), embedded(false), uv_rotation(0)
{
uv_offset.x = uv_offset.y = 0;
uv_scale.x = uv_scale.y = 1;
}
DynamicString file_path;
DynamicString relative_path;
// was embedded in source .fbx file
bool embedded;
Vector2 uv_offset;
Vector2 uv_scale;
float uv_rotation;
};
// Structure describing a Level of Details
struct LevelOfDetail {
ALLOCATOR_AWARE;
LevelOfDetail(Allocator& a) : orientation_node(a), bounding_volume(a), requires_predefined_pct(0), steps(a) { }
DynamicString orientation_node;
DynamicString bounding_volume;
bool requires_predefined_pct;
struct Step {
ALLOCATOR_AWARE;
Step(Allocator& a) : nodes(a), min_pct(0.0f), max_pct(1.0f) {}
Vector<DynamicString> nodes;
float min_pct;
float max_pct;
};
Vector<Step> steps;
};
// Structure describing how a scene is interpreted when importing
struct SceneImportOptions {
SceneImportOptions() :
combine_meshes(false),
combine_meshes_by_material(false),
reverse_forward_axis(false),
skip_create_extra_root(false),
skip_textures(false),
skip_lights(false),
skip_cameras(false),
create_missing_uvs(false),
tangents(TANGENTS_IMPORT)
{ }
enum TangentsOption {TANGENTS_IMPORT, TANGENTS_MIKKTSPACE};
bool combine_meshes;
bool combine_meshes_by_material;
bool reverse_forward_axis;
bool skip_create_extra_root;
bool skip_textures;
bool skip_lights;
bool skip_cameras;
bool create_missing_uvs;
TangentsOption tangents;
};
// Structure describing a scene
struct SceneDatabase {
SceneDatabase(Allocator &a) : nodes(a), roots(a), geometry_instances(a), geometries(a), lights(a), cameras(a), skins(a), materials(a), textures(a), lods(a), anim_takes(a), source_path(a), properties(a), geometry_entries(a) { }
Allocator &allocator() const {return nodes.allocator();}
typedef HashMap<DynamicString, Node, string_hash> Nodes;
Nodes nodes;
Vector<DynamicString> roots;
typedef HashMap<DynamicString, GeometryInstance, string_hash> GeometryInstances;
GeometryInstances geometry_instances;
typedef Vector<Geometry> Geometries;
Geometries geometries;
typedef HashMap<DynamicString, Light, string_hash> Lights;
Lights lights;
typedef HashMap<DynamicString, Camera, string_hash> Cameras;
Cameras cameras;
typedef HashMap<DynamicString, Skin, string_hash> Skins;
Skins skins;
typedef HashMap<DynamicString, SurfaceMaterial, string_hash> Materials;
Materials materials;
typedef HashMap<DynamicString, Texture, string_hash> Textures;
Textures textures;
typedef HashMap<DynamicString, LevelOfDetail, string_hash> Lods;
Lods lods;
typedef HashMap<DynamicString, AnimationTake, string_hash> AnimTakes;
AnimTakes anim_takes;
DynamicString source_path;
SceneImportOptions import_options;
typedef HashMap<DynamicString, DynamicString, string_hash> Properties;
Properties properties;
//////////////////////////////////////////////////////////////////////////
typedef HashMap<IdString32, unsigned, idstring_hash> GeometryEntries;
GeometryEntries geometry_entries;
Geometry *find_geometry(const char *name) {
const IdString32 id(name);
auto it = geometry_entries.find(id);
return it != geometry_entries.end() ? &geometries[it->second] : nullptr;
}
Geometry &add_geometry(const char *name) {
const IdString32 id(name);
geometry_entries.insert(id, geometries.size());
Geometry &geom = geometries.extend();
geom.name = name;
return geom;
}
};
}
#include "scene_tree.inl"