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
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
//a Documentation
#![warn(missing_docs)]
#![warn(rustdoc::missing_doc_code_examples)]

/*!
# TODO

Replace ByteBuffer with T:AsRef<[u8]>

Make Vertices have an option<indices> and update renderable vertices clients

# 3D Model library

This library provides structures and functions to support simple and
complex 3D objects in a reasonably performant system. Its use cases
include 3D modeling tools, games, and 3D user interfaces.

The object model is derived from the Khronos glTF 3D
model/scene description (<https://github.com/KhronosGroup/glTF>),
without explicit support for animation or cameras.

## Overview of the model

The 3D model library is designed to provide for the description of 3D
objects with simple or sophisticated specifications of their vertices;
with materials that might be simple colors or complete PRBS
specifications, and so on.

Once models have been described they can be turned into GL-specific
instantiable structures. It is quite common for graphics libraries to
convert some external data form and to allocate internal memory for
rendering - so that the object description buffers used initially are
no longer required and their memory can be freed.

When an 'instantiable' object exists it can be rendered many times in
a single scene, with different transformations and skeleon poses.

Hence this library provides for [Instantiable] object creation that
first requires memory buffers to be allocated, descriptions of an
object created; from this [Object] the [Instantiable] is made for a
particular graphics library context - allowing the freeing of those
firstt memory buffers. This [Instantiable] can then be instanced a
number of times, and these [Instance] each have their own
[Transformation] and [SkeletonPose].

# Object creation

The first step in using the library is to create the required
[Object]. This requires some binary data buffer(s) containing float
vertex data (position, and possible normals, texture coordinates,
tangents, relevant bones and weights, and so on); also arrays of
unsigned int vertex indices, that indicate how the vertices form
strips of triangles, or lines, etc. In some applications this binary
data might come from a large file, containing the data for many
objecs; as such, different portions of the binary data contain
different parts of the object data.

The library requries that a data buffer support the [ByteBuffer]
trait, and then that data buffer can have [BufferData] views created
onto it - portions of the data buffer. For particular vertex data a
subset of [BufferData] is used to create a [BufferAccessor].

A number of [BufferData] are pulled together to produce a [Vertices]
object - this might describe all the points and drawing indices for a
complete object. Subsets of the [Vertices] object are combined with a
[Material] to help describe a set of elements to render - this might
be a TriangleStrip, for example - this is known as a [Primitive]

A [Component] of an object is a list of [Primitive] and a
[Transformation] (the list of [Primitive] is a [Mesh])

An [Object] has a hierarchy of [Component], and optionally a
[Skeleton]; it also must keep references to the data that it uses - so
it contains arrays of [Vertices] and [Material] references.

Note that the [Vertices] used by one object may be used by others; as
such one might load a single data file that contains many objects for
a game, and the objects all refer to the same buffers and even
[Material] and [Vertices].

## Buffers

Underlying the data model is the [ByteBuffer] trait - any data that is
used for the models must support this trait, and implementations are
provided for slice <> and for Vec<>.

### [BufferData]

A type that borrows a sub slice of[u8], using an explicit offset and
length, and which might have a client reference (e.g. an OpenGL
GlBuffer handle). It is similar to a Gltf BufferView, without a
'stride'.

The base concept for model [BufferData] is that it is an immutable
borrow of a portion of some model data buffer of a type that supports
the [ByteBuffer] trait; the data internally may be floats, ints, etc,
or combinations thereof - from which one creates [BufferAccessor]s, or
which it is itself used as model indices. So it can be the complete
data for a whole set of models.

Each [BufferData] has a related client element (a
[Renderable::Buffer]) which is created when an [Object] has its
client structures created; this may be an Rc of an OpenGL buffer, if
the client is an OpenGL renderer.

Each [BufferData] is use through one or more [BufferAccessor].

### {BufferAccessor]

A [BufferAccessor] is an immutable reference to a subset of a [BufferData]. A [BufferAccessor]
may, for example, be the vertex positions for one or more models; it may
be texture coordinates; and so on. The [BufferData] corresponds on the
OpenGL side to an ARRAY_BUFFER or an ELEMENT_ARRAY_BUFFER; hence it
expects to have a VBO associated with it.

The [BufferAccessor] is similar to a glTF Accessor.

Each [BufferAccessor] has a related client element (a
[Renderable::View]) which is created when an [Object] has its
client structures created; this may be the data indicating the subset
of the [Renderable::Buffer] that the view refers to, or perhaps a
client buffer of its own.

A set of [BufferAccessor]s are borrowed to describe [Vertices], each
[BufferAccessor] providing one piece of vertex information (such as
indices, position or normal). A single [BufferAccessor] may be used by
more than one [Vertices] object.

### [Vertices]

The [Vertices] type borrows at least one [BufferAccessor] for a vertex
indices buffer, and at least one [BufferAccessor] for positions of the
vertices; in addition it borrows more [BufferAccessor], one for each
attribute [VertexAttr] that is part of a mesh or set of meshes.

The [Vertices] object should be considered to be a complete descriptor
of a model or set of models within one or more [ByteBuffer]. In OpenGL
a Vertices object becomes a set of OpenGL Buffers (and subsets
thereof) and for a particular shader class it can be bound into a VAO.

A [Vertices] object is a set of related [BufferAccessor]s, with at least a
view for indices and a view for vertex positions; it may have more
views for additional attributes. It has a lifetime that is no longer
than that of the [BufferData] from which the [BufferAccessor]s are made.

A [Renderable::Vertices] can be constructed from a [Vertices]; this
is a renderer-specific vertices instance that replaces the use of
[BufferAccessor]s with the underlying client types.

## Skeleton and posing

A [Skeleton] consists of a (possibly multi-rooted) hierarchy of
[Bone]s. Each bone has a [Transformation], which is the mapping from
the coordinate space of its parent to the coordinate space of the bone
itself.

Each [Bone] has a 'matrix_index' which indicates which 'Joints' matrix
the bone is referred to by any 'joint's attribute entry in a mesh.

An object instance will have a [SkeletonPose] associated with it; this
allows the object contents to be rendered with adjustments to the
model, such as to make it appear to walk. A [SkeletonPose] is an array
of [BonePose] which reflect the associated [Bone]s in the skeleton;
each has an associated posed [Transformation].

The [SkeletonPose] can be traversed and for each posed bone an
appropriate mesh-to-model-space matrix can be generated; if a mesh is
annotated with bone weights that sum to 1 then a mesh vertex
coordinate can be converted to a posed-model coordinate by summing the
mesh-to-model-space matrices of the bones times their weights times
the mesh vertex coordinate.

A [Skeleton] is similar to a `skin` in GLTF.

/// Each bone has a transformation with respect to its parent that is
/// a translation (its origin relative to its parent origin), scale
/// (in each direction, although a common scale for each coordinates
/// is best), and an orientation of its contents provided by a
/// quaternion (as a rotation).
///
/// A point in this bone's space is then translate(rotate(scale(pt)))
/// in its parent's space. The bone's children start with this
/// transformation too.
///
/// From this the bone has a local bone-to-parent transform matrix
/// and it has a local parent-to-bone transform matrix
///
/// At rest (where a mesh is skinned) there are two rest matrix variants
/// Hence bone_relative = ptb * parent_relative
///
/// The skinned mesh has points that are parent relative, so
/// animated_parent_relative(t) = btp(t) * ptb * parent_relative(skinned)
///
/// For a chain of bones Root -> A -> B -> C:
///  bone_relative = C.ptb * B.ptb * A.ptb * mesh
///  root = A.btp * B.btp * C.btp * C_bone_relative
///  animated(t) = A.btp(t) * B.btp(t) * C.btp(t) * C.ptb * B.ptb * A.ptb * mesh

## Textxures

A texture is a 1D, 2D or 3D object that is indexed by a shader to
provide one of a scalar, vec2, vec3 or vec4 of byte, short, integer,
or float.



## Materials

Materials are types that have the [Material] trait, and which have the
lifetime of the [BufferData] of the object they belong to; this is
because they may contain textures. As such they have an associated
Renderable::Material type, which has a lifetime as defined by the
Renderable.

[Material] is a trait that must be supported by materials, which thus
permits different abstract shading models to be used. It has a
`MaterialClient` parameter, which

Example [Material] instances are:

* [BaseMaterial] -

* [PbrMaterial] -

A [Material] has a make_renderable() method that makes it renderable?

## [Primitive]

A [Primitive] is a small structure that uses a single subset of
[Vertices] with a [Material] wih a drawing type (such as
TriangleStrip). It does not contain direct references to the vertices
or material; rather it uses an index *within* the arrays of [Vertices]
or [Material] held by an [Object].

A [Primitive] contains:

* a [Material] (from an index within the [Object] to which the primitive mesh belongs)

* a set of [Vertices] - the attributes required by the [Mesh] and a
  set of indices, a subset of which are used by the [Primitive] (from
  an index within the [Object] to which the mesh belongs)

* a drawable element type ([PrimitiveType] such as `TriangleStrip`)

* an index offset (within the [Vertices] indices)

* a number of indices

A [Primitive] does *not* contain any transformation information - all
the [Primitive] that belong to a [Mesh] have the same transformation.

## [Mesh]

A [Mesh] is an array of [Primitive]; this is just a way to combine sets
of drawn elements, all using the same transformation (other than bone
poses).

A mesh is part of a [Component] that is part of an [Object].

## [Component] of an Object

A [Component] is part of the hierarchy of an [Object] and has no
meaning without it; the indices and materials used in the [Component]
are provided by the [Object]. The [Component] has a [Transformation]
(relative to its parent) and a [Mesh].

Note that a hierarchy of object [Component]s is implicitly
`renderable` as it contains only indices, not actual references to
[BufferAccessor] data structures.

A hierarchy of object [Component]s can be reduced to a
[RenderRecipe]; this is an array of:

* transformation matrix

* material index (in a [Primitive])

* vertices index (in a [Primitive])

* drawable element type (in a [Primitive])

* index offset (in a [Primitive])

* index count (in a [Primitive])

## [Object]

An Object has an array of [Vertices] and [Materials] references that
its meshes use; both of these will end up being mapped to arrays of
graphic library client handles on a one-to-one basis (each [Vertices]
in the array becomes a graphics library vertices client, for example).

The Object then has a hierarchy of [Component]; this describes everything that it takes to draw the object.

Additionally the Object has an optional [Skeleton].

All of the data from an [Object] can be used to create an
[Instantiable]; this latter does not refer to any of he data buffers
(such as the [Vertices]) and so the original byte buffers can be
dropped once an [Instantiable] exists - all the data will be in the
graphics library.

## [Instantiable] objects

A 3D model [Object] consists of:

*  a hierarchy of [Component]s

*  a [Skeleton]

*  an array of [Vertices]; each of these is a set
of indices within a [BufferData] and attribute [BufferAccessor]s.

*  an array of [Material]

Such an object may have a plurality of render views created for it,
for use with different visualizers (in OpenGL these could be different
shaders, for example).

An object can be turned in to a renderable object within a
Renderable::Context using the `into_instantiable` method.  Once created
(unless the renderable context requires it) the object can be dropped.

The [Instantiable] is created within a specific renderable
context. For simple graphics libraries this probably means that
instances of the instantiated object are to be wih a single shader
program, whose attribute layout an uniforms is known ahead of time. As
such the renerable context might generate a single VAO for the
instantiable with appropriate buffer bindings, at the
into_instantiable invocation. For more complex applications, where an
object may be rendered with more than one layout of attributes, with
many different shader program classes, a VAO could be generated per
shader program class and (e.g.) a 'bind vertex buffers' for the
*object* can be invoked within a VAO prior to the rendering of a
number of the instances of the object with the shader program (each
presumably with its own 'uniform' settings!).

An [Instantiable] can then be drawn by
(theoretically, and given a particular [SkeletonPose]):

* Generating the [BonePose] mesh-to-model-space matrices for each bone in the [Skeleton]

* Traversing the hierarchy, keeping a current node [Transformation] in hand

* Apply the node's Transformation

* Render the node's [Primitive]s using the [Object]s material at the
  correct index, with the [Instantiable] associated with the
  [Vertices] index of the mesh

## Instantiated objects

An instantiated object is created by instantiating an [Instantiable].

The [Instance] has a [Transformation], a [SkeletonPose], and a set of
[Material] overrides; the [Material] overrides are an array of
optional materials.

For efficient rendering the object instance includes an array of the
instance's [SkeletonPose] matrices plus the base instance
[Transformation] matrix.

## Rendering an instance

A Vertices object is then used by a number of [Primitive]s; each of
these borrows the Vertices object, and it owns an array of
Drawables. Each Drawable is an OpenGL element type (such as
TriangleStrip), a number of indices, and an indication as to which
index within the Vertices object to use as the first index. Each Primitive has a single Material associated with it.

An array of Primitive objects is owned by a Mesh object, which corresponds to
the glTF Mesh - hence the Primitive object here corresponds to a glTF
Primitive within a glTF Mesh. A Mesh might correspond to a table leg or the table top in a model.

A number of Mesh objects are borrowed to form Object Nodes; each Node has its own Transformation that is applied to its Mesh. Hence a table can consist of four Object Nodes that borrow the same table leg Mesh, and a further Object Node that is the table top. A Node may also have a BoneSet associated with it, to provide for *skinned* objects.

An Object Node forms part of an Object's Hierarchy - hence the Object
Nodes are owned by the Object. An Object, then, can be a complete
table, for example. It might also be a posable robot; in this case one
would expect the top level node to have a BoneSet, and there to
perhaps be Object Nodes for the body, head, arms and legs, perhaps
sharing the same Mesh for the two arms and anoter Mesh for the two
legs.

It is worth noting at this point that the lifetime of an Object must
be no more than the lifetime of the data buffer containing its data;
even though the Object may be passed in to a GPU memory, the data used
for building the object then not being required by the CPU (using
STATIC_DRAW). It is, then, clearly useful to consider the Object as a
model *construction* type, not necessarily the model *draw* type.

When it comes to rendering an Object, this requires a Shader. The data
required by a Shader to render an Object depends not just on the
Object but also on the Shader's capabilities (such as does it utilize
vertex tangents). However, there is some data that is common for all
the Shaders that might render a single Object instance - such as the
bone poses for the object, and the mesh matrices.

Hence an Object must have two type created for it prior to rendering. The first is a drawable::Instantatiable. This is a drawable object that in itself may have instantiations.
The drawable::Instantiable contains an owned copy of the BoneSet for
the object, and any transformation data required by the meshes for
drawing (given each object node has its own transformation). The drawable::Instantiable is created from the object using its create_instantiable method.

The second type required for rendering is a shader::Instantiable. This
is used by binding the data required for a shader for an object to a
VAO (Vertex Attribute Object) for the shader; this VAO is used in the
rendering of any instances of the shader::Instantiable. The
shader::Instantiable borrows the drawable::Instantiable created for
the Object; it is created using the Object's bind_shader method.

With STATIC_DRAW the lifetime of the shader::Instantiable can be shorter than that of the Object data - it can have a lifetime of the rendering.

Once an Object has had all of its drawable::Instantiable and shader::Instantiable types created, the Object may be dropped.

A renderable instance of an object then requires a drawable::Instance
to be created from the drawable::Instantiable; this instance has its
own transformation and bone poses, and it borrows the
drawable::Instantiable. The Instance can be rendered with a particular
shader using that shader::Instantiable's `gl_draw` method, which takes
a reference to the Instance. This method then has access to all the
matrices required for the mesh, for the posed bones, and so on.

A Shader is created using standard OpenGL calls. It must have the ShaderClass trait.

An instantiable model consists of abstract mesh data and poses of the
elements within its skeleton, if required.

Multiple instances of an instantiable model can be created, each with its own set of poses.

The Hierarchy module provides for a hierarchy of owned elements which
are stored in an array inside the Hierachy structure; the
rerlationship between nodes in the hierarchy are handled by indices
into this array. The Hierarchy is designed to be created, and then
immutably interrogated - although the immutability refers to the
*hierarchy* and the *node array*, not the contents of the nodes - the
node content may be updated at will.

# Graphics libraries

In OpenGL we have

VAO = list of binding from VAO attr number to a buffer; it also has an
'elemeent array buffer' that is the buffer of indices. Note a buffer
here is an offset/stride of a gl buffer.

The VAO is specific to the shader class, as it uses the attribute locations of the shader

A VAO can have the attribute bbuffers bound iini one go with glBindVertexBuffers (or glVertexArrayVertexBuffers to specify the vao without binding it first),

The index buffer can be bound witth glBindElementBuffer.

In theory a single VAO can work for many objects with one shader class
as the attribute layour is specific o the shader class. This requires
all its buffers to be rebound and the element buffer to be rebound. So it keeps some of the VAO.

Uniforms must be set after useProgram

A VBO glBuffer can be a BufferData; an Accessor is the glBuffer with offset and stride.

## OpenGL 4.0

Program has id; attribute list of (AttribLocation, VertexAttr); uniform list of (UniformLocation, UniformId).

UniformId is either ViewMatrix, ModelMatrix, etc, User(x), or Buffer(x)

# Examples

use model3d::{BufferAccessor, MaterialAspect};
use model3d::example_client::Renderable;

# To do

Optimize primitive to fit within 32 bytes

Make Buffer have a client 'reproduce me' element so that if it comes
from a file that file could be reloaded if required. This would allow
the GPU data for an instantiable to be dropped and reloaded, if the
appropriate client code is written.  The Buffer would require this
element at creation time so that its create client method could could
capture it.

Add a String to each component, and extract that for each root component in the hierarchy
Maybe have an 'extract component by name' from object that creates an Instantiable (requires there to be no skeleton for now)

Make only part of an instantiable be drawn (have a Vec of RenderRecipes, one per component in the root by default)

!*/

mod types;
pub use types::BufferElementType;
pub use types::MaterialAspect;
pub use types::ShortIndex;
pub use types::{Mat3, Mat4, Quat, Vec3, Vec4};
pub use types::{PrimitiveType, VertexAttr};

//a To do
//
// Add index size to primitive (it is cache-line sensitive though)

//a Imports and exports
pub mod hierarchy;

mod transformation;
pub use transformation::Transformation;

mod bone;
mod bone_pose;
pub use bone::Bone;
pub use bone_pose::BonePose;

mod skeleton;
mod skeleton_pose;
pub use skeleton::Skeleton;
pub use skeleton_pose::SkeletonPose;

mod buffer_accessor;
mod buffer_data;
mod byte_buffer;
pub use buffer_accessor::BufferAccessor;
pub use buffer_data::BufferData;
pub use byte_buffer::ByteBuffer;

mod traits;
pub use traits::{
    AccessorClient, BufferClient, Material, MaterialClient, Renderable, TextureClient,
    VerticesClient,
};

mod texture;
pub use texture::Texture;

mod material;
pub use material::BaseData as MaterialBaseData;
pub use material::{BaseMaterial, PbrMaterial};

mod vertices;
pub use vertices::Vertices;
mod mesh;
mod primitive;
pub use mesh::Mesh;
pub use primitive::Primitive;

mod component;
pub use component::Component;
mod render_recipe;
pub use render_recipe::RenderRecipe;
mod object;
pub use object::Object;

mod instantiable;
pub use instantiable::Instantiable;
mod instance;
pub use instance::Instance;

pub mod example_objects;
pub use example_objects::ExampleVertices;

pub mod example_client;