In the continuation of the
articleThe first
article has already used the very first primitive, which can be called simply “arbitrary shape”.
Before describing the primitive objects, I repeat once again two basic requirements-comments from our system:
- Each primitive must contain a vertex vector and an index vector (vertex, indices).
- Each primitive is constructed by indices through triangles (TRIANGLE), that is, every 3 points form an independent triangle.
')
In addition to the requirements for each primitive, we can connect the
matrix . Once connected, you can easily perform the following manipulations:
- Move along any of the axes. Move to a certain number of units or move to any point in space
- Rotate around any point. When the matrix is connected, we become aware of the center, respectively, we can rotate the primitive around any point by specifying a point or around our own center.
The primitives themselves can be divided:
- Simple. Consist of only one primitive.
- Compound-composite. Consist of several primitives
Simple primitives
Plain
Description
This primitive is a flat rectangle. To build enough 2 triangles. The necessary minimum of input data we need to get is the center of our shape, its width and height. At the output, we must get at least 2 arrays: an array of vertices, an array of indices. Each vertex is calculated through the center, width and height, so the upper left vertex is the point at which x is offset from the center by half the width to the left, and y is half the height up, z is not shifted - the figure is flat. In the same way we find all the other vertices.
[this.frontCenter[0] - width / 2, this.frontCenter[1] + height / 2, this.frontCenter[2], this.frontCenter[0] + width / 2, this.frontCenter[1] + height / 2, this.frontCenter[2], this.frontCenter[0] + width / 2, this.frontCenter[1] - height / 2, this.frontCenter[2], this.frontCenter[0] - width / 2, this.frontCenter[1] - height / 2, this.frontCenter[2]];
In the array of indices, we define how our points will be combined. In this primitive 2 triangles
Upper left point, upper right point, lower left point. In the array of vertices, these are elements - 0,1,3
Upper right point, lower right point, lower left point. In the array of vertices, these are elements - 1,2,3
Accordingly, an array of indices looks like this:
[0,1,3,1,2,3,];
The order of the indices will not change, but with the peaks there may be some changes. In order to easily manipulate our primitive, we will translate an array of vertices into a matrix.
this.matrix = new botuMatrix(this.vertex,3);
Operations with primitive
When manipulating the
matrix, the array passed as an input parameter will change, in this case, the array of vertices. When describing the
matrix , possible manipulations with the matrix were indicated. Let's connect these manipulations to our primitive.
moveByX:function(value){ this.matrix.move(value,0); }, moveByY:function(value){ this.matrix.move(value,1); }, moveByZ:function(value){ this.matrix.move(value,2); }, testToPoint:function(value){ this.matrix.toPoint(value); }, rotateAroundCenter:function(angle,xyzType) { this.matrix.rotate(angle,this.matrix.center,xyzType); }, rotateAroundMaxPoint:function(angle,xyzType) { this.matrix.rotate(angle,this.matrix.maxval,xyzType); }, rotateAroundPoint:function(angle,point,xyzType) { this.matrix.rotate(angle,point,xyzType); },
- moveByX, moveByY, moveByZ - move the primitive along X, Y and Z, respectively. The only input parameter is the number of units. Example, obj.moveByX (50) - move obj 50 units to the right.
- testToPoint - move the primitive (focusing on the cent) to a certain point. Incoming parameter - vector point. Example, obj.testToPoint ([0,50,10]);
- rotateAroundCenter, rotateAroundMaxPoint - turn around the center or around the maximum coordinates. (in the example with a rectangle, the maximum coordinates coincide with the right upper point, however, the maximum coordinates do not always coincide with any point of the primitive. If roughly every three-dimensional object is packaged into a cube, then the maximum coordinate is the upper far point of this cube.). The incoming parameter is the angle of the turn and the axis along which the turn should be. Example: obj.rotateAroundCenter (45, “byX”) - turn around the X axis by 45 degrees. The angle is specified in degrees, the axes are “byX”, “byY”, “byZ”.
- rotateAroundPoint - turn around an arbitrary point in space. Example, obj.rotateAroundPoint (45, [0,0,0], "byZ");
These operations are not dependent on the primitive, so in the future we will connect them without comment.
Cub
This primitive is a hexahedron. Almost a cube, only faces can be both squares and rectangles.
The description will be the same as the rectangle, just add another input parameter - depth.
The cube will have 8 vertices, as if the far and near rectangle. From the simple rectangle described above, the difference will be in calculating the Z coordinate, which in the near rectangle will decrease by half the depth, and in the far one will also increase by half the depth.
To do this, just take two centers.
this.frontCenter=[centerPoint[0],centerPoint[1],centerPoint[2] - depth / 2]; this.backCenter=[centerPoint[0],centerPoint[1],centerPoint[2] + depth / 2];
And in the array we will create 2 rectangles, the first with the center frontCenter, the second with the center backCenter.
this.frontCenter[0] - width / 2, this.frontCenter[1] + height / 2, this.frontCenter[2], this.frontCenter[0] + width / 2, this.frontCenter[1] + height / 2, this.frontCenter[2], this.frontCenter[0] + width / 2, this.frontCenter[1] - height / 2, this.frontCenter[2], this.frontCenter[0] - width / 2, this.frontCenter[1] - height / 2, this.frontCenter[2], this.backCenter[0] - width / 2, this.backCenter[1] + height / 2, this.backCenter[2], this.backCenter[0] + width / 2, this.backCenter[1] + height / 2, this.backCenter[2], this.backCenter[0] + width / 2, this.backCenter[1] - height / 2, this.backCenter[2], this.backCenter[0] - width / 2, this.backCenter[1] - height / 2, this.backCenter[2]
Concerning the vertices of the indices. There are 6 faces in a cube, each of which consists of 2 triangles.
/ * the rectangle nearest to us, the only one that we see, before the cube manipulations * /
0,1,3,
1,2,3,
/ * left edge * /
0,4,7,
0,3,7,
/ * bottom line * /
3,7,6,
6.3,2,
/ * right edge * /
2,6,1,
1,5,6,
/ * upper bound * /
0,4,5,
0.5.1,
/ * back edge * /
7,4,5,
7.5,6
Difficult-composite primitives
Simple primitives. which we created consist of triangles, and before creating this primitive, we mentally split it into triangles. Complex primitives will consist of any other geometric, two-dimensional shape. This article will consider the only "complex primitive" - the ball. Which will consist of rectangles.
Ball
What you need to know to draw a ball - coordinates and radius? Yes. But I will add one more small parameter - detailing.
Here is the same circle, with the same radius, only different details. The fact that in the description of the primitive will be understood under the detail - a little later.

Detailing - 35

Detailing - 10
Algorithm:
- We build a rectangle tangentially, that is, the center of the rectangle is the center of the circle offset along the Z axis by the radius value. The height and width of the rectangle is the circumference, which is calculated through the radius divided by the details. The greater the detail, the smaller the height-width of the rectangles, the larger the rectangles themselves.
- On top we add one more rectangle, developed at an angle equal to 360 * / (the number of rectangles that was found at the previous step).
- I repeat the previous stage n-times. Where n is the number of rectangles. The result is a wheel.

- Make a copy of this wheel with a turn along the Y axis by an angle equal to 360 * / (the length of the circle divided by the width).
- Repeat the previous operation n-times, where n is the length of the circle divided by the width.
To implement this algorithm
- Create an object to which you can connect other objects. From the point of view of code, arrays of vertices and indices of various objects are added to arrays of vertices and indices.
function botuGroupedObject(){ this.vertex = []; this.indices = []; } botuGroupedObject.prototype = { addObject:function(obj){ this.vertex.size = obj.vertex.size; var next = Math.max(this.vertex.length / this.vertex.size,0); this.vertex = this.vertex.concat(obj.vertex); this.indices = this.indices.concat(obj.indices.map(function(i){return i + next})); this.vertex.size = obj.vertex.size; } }
- Create a helper function to create a copy of an object in a new object.
function makeCopy(object,type){ var vertex = object.vertex.slice(0); var indices = object.indices.slice(0); return new type(vertex,indices); }
- To the primitive Plain add method
connectUP:function(anotherPlain){ var downLeftPoint = anotherPlain.getDownLeft(); var dvPoint = downLeftPoint.map(function(value,index){return value - this.getUpperLeft()[index]},this); this.testToPoint(dvPoint); }
that the primitive builds - plain close to the upper boundary of another primitive plain. getDownLeft () is the lower left point, that is, an element from the array of vertices with index 3. (see above in the description of the Plain primitive). getUpperLeft () is the upper left point, that is, an element from the array of vertices with index 0.
An example of work.