Cogs.js is a component based 3D graphics engine for modern web applications. Even if you understand most of this, this can be a bit of a mouthful. So let's explain in detail.
Cogs is a data-driven 3D graphics engine written in C++. While it is developed in C++, it has a C bridge that enables usage in higher level languages with some glue code. So we have things like Cogs.Net and Cogs.js that makes Cogs available for .NET and web developers.
There are more aspects to component based design, but in 3D performance is absolutely crucial. Having a component based design basically improves usage of CPU caches.
In comparison with low-level graphics API's like Direct3D or WebGL, 3D engines enable developers to be more productive by working at higher levels of abstraction. Instead of dealing with triangles directly we can import and use 3D models. Also, Cogs has multiple rendering backends so rendering is decoupled from the rest of the engine. This allows reuse of code between platforms as much as possible.
Today web applications can be as advanced as native applications. While they may not be optimal in all scenarios, the advantages that they bring in terms of cross-platform operation and scalable deployment often make them preferred for new development projects. Web applications can be based on many different frameworks and libraries such as Angular or React, but the underlying platform is always the same common web standards such as HTML, CSS, JavaScript, WebAssembly and WebGL. The last two are the most recent but also the most critical parts to make 3D on the web practical.
For Cogs.js, Cogs is basically compiled from C++ into WebAssembly with OpenGL ES/WebGL for rendering. The compiler toolchain that makes all this possible is Emscripten. There's also some glue code written in ES6 and TypeScript definition files to make Cogs.js more pleasant to use from TypeScript.
As you can see from the above description, there's many buzzwords that can cause confusion here. Luckily there's no need to despair since the point of mentioning these at all was just to explain that Cogs.js is built on top of a set of relatively new technologies. Just as you don't need to understand chip design in order to use a computer, you don't need to know the details of the involved standards in order to take advantage of them via Cogs.js.
You'll of course benefit from having some familiarity 3D graphics concepts such as vector data types (Cogs.js uses glMatrix), various types of meshes and textures. Predefined materials are generally provided, but you can go ahead and write your own shaders if you're up to that.
The web skills you'll need should be the same as for modern web development. Defining exactly what that means is of course the tricky part. Cogs.js can used with only basic knowledge about HTML/CSS/JS, as in our examples. But to scale from relatively small demos and prototypes to actual applications you'll typically need to use more libraries like React and maybe a framework like Angular or Vue. If you're already a framework wizard, it's certainly possible to start experimenting with Cogs.js in that context, but for these docs we'll start more or less at scratch.
At minimum you should first read this introduction and the GettingStarted guide. In the guide we'll help you with setting up your own development environment so you can start experimenting right away. Feel free to borrow code from the examples to incorporate into your own experiment.
FAQ is meant to answer the most obvious questions you may have. Often you'll run into warnings and error messages. In such cases we'd recommend to first check the FAQ and then just ask for help. Such errors can be due to a wide variety of reasons. Often it can be a simple parameter passing problem (ie you doing something unexpected), but it can also be bugs in Cogs and even problems caused by updates in browsers. Even if you solve it yourself we'd like to know about it so we can see what kind of problems that people run into. Then we can update the fAQ and/or make fixes that can help everyone.
HelloWorldAngular may not be very helpful without learning about Angular first. But it can be useful to see Cogs.js used in a small app before working on a larger one.
It will be useful in at least two ways to first outline the basic steps involved in using Cogs.js. Having an overview should make it easier to understand important concepts in the right context without getting bogged down in details. And it will also pay off later since the GettingStarted guide will put these steps into practice for pure javascript, and HelloWorldAngular will do the same for Angular.
Joking aside, these steps actually encapsulate how Cogs.js is used. As highlighted in step 5, the component based design has important advantages beyond performance. It makes it easier to pick up and use a new entity, since the entity will probably have many components that you are already familiar with. Setting up entities is completely data-driven, meaning that you'll mostly just set fields and don't have to call methods for trivial things.
We'll translate the above steps into practice in separate guides. But let's first expand a bit more on the concepts just touched on.
Cogs is built using Components as the main building block as found in modern game engines.
Entities just owns a set of components. There is nothing special in any Entity. The Cogs pre-defined Entities are defined for convenience and because some components require other components to be present, for example MeshComponent requires a MeshRenderComponent for default rendering of the mesh data.
The component is handling the main logic of the Cogs rendering logic. The component will create data structures on the GPU for rendering. Components may use other components in the Entity, for example a physics components may change the transformation to let gravity influence the position and rotation of the entity.
Components of the same type belongs to a System allowing the system to coordinate the rendering, for example the System for point-cloud rendering coordinates rendering of all individual point clouds to ensure that data closest to the camera is fetched first and that the GPU is not overflows with data.
Components contains a set of fields. A field is just a class member like int, float, vec3, vector<float>, texture handle etc.
Setting a field value just copies the value. In addition the component is informed that the field is changed. Update is delayed until the next time the component is rendered so fields can be set in any order. The Cogs interface will trigger a redraw when changing fields.
Entities are created using class Runtime. Factories for all pre-defined entities are stored as members in class Runtime.
const myCube = control.runtime.Cube.create('myCube');
const myCube = control.runtime['Cube'].create('myCube');
The Cogs SceneComponent allows an entity to have children setting up a very basic scene graph there only transformation and visibility of parent is used by the child.
All user created entities are referenced by Cogs. Therefore they must also be destroyed (e.g. de-referenced from Cogs). An entity added as a child will have an additional reference from parent. E.g.:
const group = runtime.Group.create();
const cube = runtime.Cube.create();
group.sceneComponent.children.add(cube);
A) Child destroyed:
// Now only owned by parent.
runtime.destroy(cube);
// Destroy parent - both go away.
runtime.destroy(group);
B) Parent destroyed:
// Cube is now back to being a parent entity.
// Moved back if transformed by parent.
runtime.destroy(group);
// Also destroy cube.
runtime.destroy(cube);
Entities can also be created in Cogs by loading scene graphs using Runtime.loadAssetFromString.
The Asset Entity AssetComponent can also dynamically create entities for display. Use: Asset.assetComponent.asset = runtime.resources.loadAsset(path);
Also note that these children may have dynamic lifetime and may be deleted on next redraw. Don't store references to picked entities in client code.
Entities have a 'id' member. User normally don't handle entity ids as these are handled internally in Cogs.js, but building an entity description from an id is done using:
const entity = control.runtime.Entity.wrap(id: Cogs.EntityId);
We invite you to dive into GettingStarted to start putting the theory into practice.