geometry

Note: This documentation is for the old 0.3.0 version of A-Frame. Check out the documentation for the current 1.6.0 version

The geometry component provides a basic shape for an entity. The general geometry is defined by the primitive property. Geometric primitives, in computer graphics, means an extremely basic shape. With the primitive defined, additional properties are used to further define the geometry. A material component is usually defined to provide a appearance alongside the shape to create a complete mesh.

Base Properties

Every geometry type will have these properties:

Property Description Default Value
buffer Transform geometry into a BufferGeometry to reduce memory usage at the cost of being harder to manipulate. true
mergeTo A selector to an entity to merge the entity’s geometry to. None
primitive Name of a geometry (e.g., one of the geometries listed below). Determines the geometry type and what other properties are available. box
skipCache Disable retrieving the shared geometry object from the cache. false

mergeTo

Merging geometries reduces the number of draw calls, greatly improving performance under certain circumstances. Geometries that are merged will inherit the material of the target geometry. Thus, it’s useful when we have entities that share the same material.

Once merged, the individual geometry can no longer be manipulated independently.

For geometry merging to be able to work, we will have to turn off buffer and turn on skipCache.

<a-entity id="target" geometry="primitive: box; buffer: false; skipCache: true" material="color: red"></a-entity>
<a-entity geometry="primitive: box; buffer: false; skipCache: true; mergeTo: #target"
material="color: red" position="1 2 3"></a-entity>

Built-in Geometries

box

The box geometry defines boxes (i.e., any quadilateral, not just cubes).

<a-entity geometry="primitive: box; width: 1; height: 1; depth: 1"></a-entity>
Property Description Default Value
width Width (in meters) of the sides on the X axis. 1
height Height (in meters) of the sides on the Y axis. 1
depth Depth (in meters) of the sides on the Z axis. 1

circle

The circle geometry creates flat two-dimensional circles. These can be complete circles or partial circles (like Pac-Man). Note that because it is flat, only a single side of the circle will be rendered if “side: double” is not specified on the material component.

<a-entity geometry="primitive: circle; radius: 1" material="side: double"></a-entity>
Property Description Default Value
radius Radius (in meters) of the circle. 1
segments Number of triangles to construct the circle, like pizza slices. A higher number of segments means the circle will be more round. 32
thetaStart Start angle for first segment. Can be used to define a partial circle. 0
thetaLength The central angle (in degrees). Defaults to 360, which makes for a complete circle. 360

thetaLength and thetaStart Properties

In degrees, thetaStart defines where to start a circle or arc and thetaLength defines where a circle or arc ends. If we wanted to make a ( shape, we would start the circle halfway through and define the length as half of a circle. We can do this with thetaStart: 180; thetaLength: 180. Or if we wanted to make a ) shape, we can do thetaStart: 0; thetaLength: 180.

Useful cases might be to animating thetaStart to create a spinner effect or animating thetaLength on a fuse-based cursor for visual feedback.

cone

The cone geometry is a cylinder geometry that have different top and bottom radii.

<a-entity geometry="primitive: cone; radiusBottom: 1; radiusTop: 0.1"></a-entity>
Property Description Default Value
height Height of the cone. 2
openEnded Whether the ends of the cone are open (true) or capped (false). false
radiusBottom Radius of the bottom end of the cone. 1
radiusTop Radius of the top end of the cone. 1
segmentsRadial Number of segmented faces around the circumference of the cone. 36
segmentsHeight Number of rows of faces along the height of the cone. 18
thetaStart Starting angle in degrees. 0
thetaLength Central angle in degrees. 360

cylinder

The cylinder geometry creates cylinders in the traditional sense like a Coca-Cola™ can, but it can also define shapes such as tubes and curved surfaces.

We can create a basic cylinder using height and radius:

<a-entity geometry="primitive: cylinder; height: 3; radius: 2"></a-entity>

We can create a tube by making the cylinder open-ended, which removes the top and bottom surfaces of the cylinder such that the inside is visible. Then a double-sided material will be needed to render properly:

<!-- Tube -->
<a-entity geometry="primitive: cylinder; openEnded: true" material="side: double"></a-entity>

We can create a cured surfaces by specifying the arc via thetaLength such that the cylinder doesn’t curve all the way around, making the cylinder open-ended, and then making the material double-sided:

<!-- Curved surface -->
<a-entity geometry="primitive: cylinder; openEnded: true; thetaLength: 180"
material="side: double"></a-entity>
Property Description Default Value
radius Radius of the cylinder. 1
height Height of the cylinder. 2
segmentsRadial Number of segmented faces around the circumference of the cylinder. 36
segmentsHeight Number of rows of faces along the height of the cylinder. 18
openEnded Whether the ends of the cylinder are open (true) or capped (false). false
thetaStart Starting angle in degrees. 0
thetaLength Central angle in degrees. 360

We can create prisms by changing the number of radial segments (i.e., sides). For example, to make a hexagonal prism:

<!-- Hexagonal prism -->
<a-entity geometry="primitive: cylinder; segmentsRadial: 6"></a-entity>

dodecahedron

The dodecahedron geometry creates a polygon with twelve equally-sized faces.

<a-entity geometry="primitive: dodecahedron; radius: 2"></a-entity>
Property Description Default Value
radius Radius (in meters) of the dodecahedron. 1

octahedron

The octahedron geometry creates a polygon with eight equilateral triangular faces.

<a-entity geometry="primitive: octahedron"></a-entity>
Property Description Default Value
radius Radius (in meters) of the tetrahedron. 1

plane

The plane geometry creates a flat surface. Because it is flat, only a single side of the plane will be rendered unless side: double is specified on the material component.

<a-entity geometry="primitive: plane; height: 10; width: 10" material="side: double"></a-entity>
Property Description Default Value
width Width along the X axis. 1
height Height along the Y axis. 1

ring

The ring geometry creates a flat ring, like a CD. Because it is flat, only a single side of the ring will be rendered unless side: double is specified on the material component.

<a-entity geometry="primitive: ring; radiusInner: 0.5; radiusOuter: 1"
material="side: double"></a-entity>
Property Description Default Value
radiusInner Radius of the inner hole of the ring. 1
radiusOuter Radius of the outer edge of the ring. 1
segmentsTheta Number of segments. A higher number means the ring will be more round. 32
segmentsPhi Number of triangles within each face defined by segmentsTheta. 8
thetaStart Starting angle in degrees. 0
thetaLength Central angle in degrees. 360

sphere

The sphere geometry creates spheres (e.g., balls). We can create a basic sphere:

<a-entity geometry="primitive: sphere; radius: 2"></a-entity>

We can create various polyhedrons and abstract shapes by specifying the number of horizontal angles and faces:

<a-entity geometry="primitive: sphere; segmentsWidth: 2; segmentsHeight: 8"></a-entity>
Property Description Default Value
radius Radius of the sphere. 1
segmentsWidth Number of horizontal segments. 18
segmentsHeight Number of vertical segments. 36
phiStart Horizontal starting angle. 0
phiLength Horizontal sweep angle size. 360
thetaStart Vertical starting angle. 0
thetaLength Vertical sweep angle size. 360

tetrahedron

The tetrahedron geometry creates a polygon with four triangular faces.

<a-entity geometry="primitive: tetrahedron; radius: 2"></a-entity>
Property Description Default Value
radius Radius (in meters) of the tetrahedron. 1

torus

The torus geometry creates a donut or curved tube shape:

<!-- Half donut -->
<a-entity geometry="primitive: torus; radius: 2; radiusTubular: 0.5; arc: 180"></a-entity>
Property Description Default Value
radius Radius of the outer edge of the torus. 1
radiusTubular Radius of the tube. 0.2
segmentsRadial Number of segments along the circumference of the tube ends. A higher number means the tube will be more round. 36
segmentsTubular Number of segments along the circumference of the tube face. A higher number means the tube will be more round. 32
arc Central angle. 360

torusKnot

The torus knot geometry creates a pretzel shape, the particular shape of which is defined by a pair of coprime integers, p and q. If p and q are not coprime the result will be a torus link:

<a-entity geometry="primitive: torusKnot; p: 3; q:7"></a-entity>
Property Description Default Value
radius Radius that contains the torus knot. 1
radiusTubular Radius of the tubes of the torus knot. 0.2
segmentsRadial Number of segments along the circumference of the tube ends. A higher number means the tube will be more round. 36
segmentsTubular Number of segments along the circumference of the tube face. A higher number means the tube will be more round. 32
p How many times the geometry winds around its axis of rotational symmetry. 2
q How many times the geometry winds around a circle in the interior of the torus. 3

Register a Custom Geometry

We can register our own geometries using AFRAME.registerGeometry and creating an object that is an instance of THREE.Geometry. All built-in geometries in A-Frame are registered using this API.

Here is how the box geometry is registered.

AFRAME.registerGeometry('box', {
schema: {
depth: {default: 1, min: 0},
height: {default: 1, min: 0},
width: {default: 1, min: 0},
segmentsHeight: {default: 1, min: 1, max: 20, type: 'int'},
segmentsWidth: {default: 1, min: 1, max: 20, type: 'int'},
segmentsDepth: {default: 1, min: 1, max: 20, type: 'int'}
},

init: function (data) {
this.geometry = new THREE.BoxGeometry(data.width, data.height, data.depth);
}
});

Like with registering components, we provide a name, a schema that will expose the properties of the geometry, and lifecycle methods. Then the geometry needs to be created and set on this.geometry through the init and update lifecycle methods.

When a geometry component sets its primitive property to the custom geometry name, the properties of the custom geometry can be set on the geometry component. Say we registered a custom geometry:

AFRAME.registerGeometry('example', {
schema: {
vertices: {
default: ['-10 10 0', '-10 -10 0', '10 -10 0'],
}
},

init: function (data) {
var geometry = new THREE.Geometry();
geometry.vertices.push.call(
geometry.vertices,
data.vertices.map(function (vertex) {
var points = vertex.split(' ').map(parseInt);
return new THREE.Vector3(points[0], points[1], points[2]);
});
);
geometry.faces.push(new THREE.Face3(0, 1, 2));
this.geometry = geometry;
}
});

We can then use that custom geometry in HTML:

<a-entity geometry="primitive: example; vertices: 1 1 1, 2 2 2, 3 3 3"></a-entity>