# Qt Quick 3D - Custom Geometry Example

```// Copyright (C) 2023 The Qt Company Ltd.

import QtQuick
import QtQuick3D.Helpers

ProceduralMesh {
property int rings: 50
property int segments: 50
positions: meshArrays.verts
normals: meshArrays.normals
uv0s: meshArrays.uvs
indexes: meshArrays.indices

function generateTorus(rings: int, segments: int, radius: real, tubeRadius: real) : var {
let verts = []
let normals = []
let uvs = []
let indices = []

for (let i = 0; i <= rings; ++i) {
for (let j = 0; j <= segments; ++j) {
const u = i / rings * Math.PI * 2;
const v = j / segments * Math.PI * 2;

const centerX = radius * Math.cos(u);
const centerZ = radius * Math.sin(u);

const posX = centerX + tubeRadius * Math.cos(v) * Math.cos(u);
const posY = tubeRadius * Math.sin(v);
const posZ = centerZ + tubeRadius * Math.cos(v) * Math.sin(u);

verts.push(Qt.vector3d(posX, posY, posZ));

const normal = Qt.vector3d(posX - centerX, posY, posZ - centerZ).normalized();
normals.push(normal);

uvs.push(Qt.vector2d(i / rings, j / segments));
}
}

for (let i = 0; i < rings; ++i) {
for (let j = 0; j < segments; ++j) {
const a = (segments + 1) * i + j;
const b = (segments + 1) * (i + 1) + j;
const c = (segments + 1) * (i + 1) + j + 1;
const d = (segments + 1) * i + j + 1;

// Generate two triangles for each quad in the mesh
// Adjust order to be counter-clockwise
indices.push(a, d, b);
indices.push(b, d, c);
}
}
return { verts: verts, normals: normals, uvs: uvs, indices: indices }
}
}```