FAQ
We will try to post frequently asked questions from previous versions of the project and from new questions on here.
Questions from Ed (past years and current)
Make stuff disappear/appear
Using the `visible` property of node models
It is often better to recycle objects by hiding and showing them in this way than to try creating and deleting objects. The function nodeModel.release() is designed to essentially delete a node from the scene, and should trigger the view being released as well. Just be a little careful here, and consider recycling resources instead for two reasons:
- First, allocating resources on the graphics card very frequently can make your program slow.
- Second, while javascript has garbage collection, resources on the GPU need to be be released explicitly. AniGraph does most of this in most cases, but depending on how you customize things, you could create GPU memory leaks. Just be wary of this.this
Group Nodes
Group Nodes in AniGraph
How to change render window size?
Editing style.ts
.anigraphcontainer{
max-height: 95%;
max-width: 95%;
aspect-ratio: 1;
border: black;
border-radius: 3px;
border-style: solid;
}
Changing them from 95% to something smaller will make the drawing window smaller.
Change the background
Setting the background color or texture
// We can also set a background texture.
// It is important to use "await" when loading a texture here if you plan to use it right away. This is because
// loading happens asynchronously, so if you don't add "await" you may try to reference the texture before it
// has finished loading, which is cause an error.
await this.model.loadTexture(`./images/SpaceBG.jpg`, "Space");// Load the texture with the scene model
this.view.setBackgroundTexture(this.model.getTexture("Space"));// Set the texture as your background
Rendering Lines
Creating and rendering line geometry
First, note that you will need to create a line material. This can be done once in your view class and used for all of your lines.
this.lineMaterial = ALineMaterialModel.GlobalInstance.CreateMaterial();
Then, to create a graphic element that is a sequence of lines,
// for VertexArray2D, CreateForRendering(...) will create position and color attributes for the geometry by default
let verts = VertexArray2D.CreateForRendering();
// When we add vertices we can now provide a color for each vertex
verts.addVertex(V2(-5,0), Color.FromRGBA(1.0,0.0,0.0,1.0));
verts.addVertex(V2(5,5), Color.FromRGBA(0.0,1.0,0.0,1.0));
verts.addVertex(V2(-5,-5), Color.FromRGBA(0.0,0.0,1.0,1.0));
verts.addVertex(V2(5,-5), Color.FromRGBA(0.0,0.0,0.0,1.0));
// Now lets make a new line graphic
let line = new ALineGraphic();
// set its geometry and material
line.init(verts, this.lineMaterial);
// add it to the view
this.registerAndAddGraphic(line);
The vertices in this case will be interpreted as defining a sequence of line segments. The code above renders something that looks like this:

The Role of Materials When Rendering Objects in AniGraph:
Materials in AniGraph
For example, the LabCatFloatingHeadModel class in Example2 uses a custom material that colors geometry in using a texture of Lab Cat's face. But let's look at some more general examples to see how materials operate at a high level.
Materials Example
Here I provide a simplefied example of rendering with three different materials to hopefully clarify the role that materials play overall. Note that there are often multiple ways to accomplish the same effect in AniGraph, as with most graphics systems. The choice may depend on what you are trying to do. With this in mind, different examples in the code may demonstrate different approaches to the same problem, and you may find looking over these variations useful when solving problems in your project.
In the code below we see two materials used: one that simply assigns a solid color to the object being rendered, and another that interpolates colors defined at every vertex of the geometry. Read through the comments for more detail.
initScene(){
let appState = GetAppState();
// Lets create a polygon object and set it to have color data.
// It will have color data by default if we create it with CreateForRendering, but we will be explicit here.
let squareGeometry = Polygon2D.CreateForRendering(true);
// Alternatively, we could create the polygon geometry and initialize attributes one at a time:
// let squareGeometry = new Polygon2D();
// squareGeometry.initColorAttribute(); // initialize the color attribute
// You can add geometry one vertex at a time
squareGeometry.addVertex(V2(0,0), Color.Random());
squareGeometry.addVertex(V2(2,0), Color.Random());
squareGeometry.addVertex(V2(2,2), Color.Random());
squareGeometry.addVertex(V2(0,2), Color.Random());
// The rgba material will use the colors assigned to each vertex
let rgbaMaterial = appState.CreateRGBAShaderMaterial();
// The basic material will just assign one global color to the object
let basicMaterial = appState.CreateBasicMaterial(Color.FromRGBA(0.0,1.0,0.0,1.0));
// Let's make two polygon models
let polygonRGBA = new Polygon2DModel();
let polygonBasicShader = new Polygon2DModel();
// Same geometry for both
polygonRGBA.setVerts(squareGeometry)
polygonBasicShader.setVerts(squareGeometry);
// Different materials. We will use the RGBA material for one and the basic material for the other
polygonRGBA.setMaterial(rgbaMaterial)
polygonBasicShader.setMaterial(basicMaterial);
// Let's put the rgba one on the bottom left and the basic one on the top right
polygonRGBA.setTransform(new NodeTransform2D(V2(-2,-2)))
polygonBasicShader.setTransform(new NodeTransform2D(V2(2,2)));
// Add them to our scene
this.addNode(polygonRGBA);
this.addNode(polygonBasicShader);
}
The above code renders to the image below. Note that the colors of the bottom left shape are randomized, so they may be different every time you run things:

Textured Materials
Let's say we want to add a textured object to the code above. To do this, we will need to load two things: a material model that we can use to render textures (don't worry too much about this for now), and a texture to actually render. We can load these in PreloadAssets functions, which you will find in SceneModel and NodeModel various classes. Here we will add it to this function in our scene model class:
export class MainSceneModel extends Creative1SceneModel{
static exampleTexture:ATexture;
async PreloadAssets(){
await super.PreloadAssets();
// Load the material model. This only needs to be called in one `PreloadAssets()` call anywhere in your program, so depending on what else you load, it may already be called elsewhere. It should be fine to call multiple times, though.
await GetAppState().loadShaderMaterialModel(DefaultMaterials.TEXTURED2D_SHADER);
// Load your texture here by providing a path to your image relative to the public folder.
// png and jpeg should both work
MainSceneModel.exampleTexture = await ATexture.LoadAsync("./images/calvin-and-hobbes.jpg");
}
...
...
Now, when we initialize our scene, we can create a material that expects a texture and give it our loaded texture. For example, if we add the code below to the initScene function we wrote in the previous example:
initScene(){
let appState = GetAppState();
// Create the textured material
let texturedMaterial = appState.CreateShaderMaterial(DefaultMaterials.TEXTURED2D_SHADER);
// Set the texture to the one we loaded
texturedMaterial.setTexture("color", MainSceneModel.exampleTexture)
// Set the geometry to geometry with texture coordinates. We will learn more about this later in the course.
let texturedSquareGeometry = Polygon2D.SquareXYUV();
// Create the model
let texturedQuad = new Polygon2DModel();
// Set the geometry and material.
texturedQuad.setVerts(texturedSquareGeometry);
texturedQuad.setMaterial(texturedMaterial);
// Set its transformation
texturedQuad.transform.position = V2(3,-3);
texturedQuad.transform.scale = V2(3,2);
// Add the quad
this.addNode(texturedQuad);
...
The scene would render as follows:

Note that we scaled our geometry to have the same aspect ratio as our image so that the image wouldn't appear distorted. If we did not perform this scale then our image would look a bit squished, as the entire image maps to the entire geometry.
Switching Textures
You can change the texture of a material on the fly.
nodeModel.material.setDiffuseTexture(loadedTexture)
Where loadedTexture is a loaded ATexture object.
Procedural Noise
Using simplex noise in Anigraph.
// A helping in anigraph for seeded random generators
import {SeededRandom} from "../../../../anigraph";
// Simplex noise based on a seeded random generator
import {makeNoise2D} from "fast-simplex-noise";
// Create a seeded random function, you can think of this as what determines the unique landscape
let rand:SeededRandom = new SeededRandom(0);
// Create an instance of the noise function, based on your seeded random function
let simplexNoise = makeNoise2D(rand.rand);
// Sample, assuming that the noise grid is at integer values
let sample = simplexNoise(1.2, 3.4)
Where loadedTexture is a loaded ATexture object.