334 lines
8.5 KiB
Dart
334 lines
8.5 KiB
Dart
import 'dart:math';
|
|
import 'dart:typed_data';
|
|
|
|
import '../../thermion_dart.dart';
|
|
|
|
class GeometryHelper {
|
|
static Geometry sphere({bool normals = true, bool uvs = true}) {
|
|
int latitudeBands = 20;
|
|
int longitudeBands = 20;
|
|
|
|
List<double> verticesList = [];
|
|
List<double> normalsList = [];
|
|
List<double> uvsList = [];
|
|
List<int> indices = [];
|
|
|
|
for (int latNumber = 0; latNumber <= latitudeBands; latNumber++) {
|
|
double theta = latNumber * pi / latitudeBands;
|
|
double sinTheta = sin(theta);
|
|
double cosTheta = cos(theta);
|
|
|
|
for (int longNumber = 0; longNumber <= longitudeBands; longNumber++) {
|
|
double phi = longNumber * 2 * pi / longitudeBands;
|
|
double sinPhi = sin(phi);
|
|
double cosPhi = cos(phi);
|
|
|
|
double x = cosPhi * sinTheta;
|
|
double y = cosTheta;
|
|
double z = sinPhi * sinTheta;
|
|
|
|
verticesList.addAll([x, y, z]);
|
|
normalsList.addAll([x, y, z]);
|
|
|
|
uvsList.addAll([longNumber / longitudeBands, latNumber / latitudeBands]);
|
|
}
|
|
}
|
|
|
|
for (int latNumber = 0; latNumber < latitudeBands; latNumber++) {
|
|
for (int longNumber = 0; longNumber < longitudeBands; longNumber++) {
|
|
int first = (latNumber * (longitudeBands + 1)) + longNumber;
|
|
int second = first + longitudeBands + 1;
|
|
|
|
indices.addAll([first, second, first + 1, second, second + 1, first + 1]);
|
|
}
|
|
}
|
|
|
|
Float32List vertices = Float32List.fromList(verticesList);
|
|
Float32List? _normals = normals ? Float32List.fromList(normalsList) : null;
|
|
Float32List? _uvs = uvs ? Float32List.fromList(uvsList) : null;
|
|
|
|
return Geometry(vertices, indices, normals: _normals, uvs: _uvs);
|
|
}
|
|
|
|
static Geometry cube({bool normals = true, bool uvs = true}) {
|
|
final vertices = Float32List.fromList([
|
|
// Front face
|
|
-1, -1, 1,
|
|
1, -1, 1,
|
|
1, 1, 1,
|
|
-1, 1, 1,
|
|
|
|
// Back face
|
|
-1, -1, -1,
|
|
-1, 1, -1,
|
|
1, 1, -1,
|
|
1, -1, -1,
|
|
|
|
// Top face
|
|
-1, 1, -1,
|
|
-1, 1, 1,
|
|
1, 1, 1,
|
|
1, 1, -1,
|
|
|
|
// Bottom face
|
|
-1, -1, -1,
|
|
1, -1, -1,
|
|
1, -1, 1,
|
|
-1, -1, 1,
|
|
|
|
// Right face
|
|
1, -1, -1,
|
|
1, 1, -1,
|
|
1, 1, 1,
|
|
1, -1, 1,
|
|
|
|
// Left face
|
|
-1, -1, -1,
|
|
-1, -1, 1,
|
|
-1, 1, 1,
|
|
-1, 1, -1,
|
|
]);
|
|
|
|
final _normals = normals ? Float32List.fromList([
|
|
// Front face
|
|
0, 0, 1,
|
|
0, 0, 1,
|
|
0, 0, 1,
|
|
0, 0, 1,
|
|
|
|
// Back face
|
|
0, 0, -1,
|
|
0, 0, -1,
|
|
0, 0, -1,
|
|
0, 0, -1,
|
|
|
|
// Top face
|
|
0, 1, 0,
|
|
0, 1, 0,
|
|
0, 1, 0,
|
|
0, 1, 0,
|
|
|
|
// Bottom face
|
|
0, -1, 0,
|
|
0, -1, 0,
|
|
0, -1, 0,
|
|
0, -1, 0,
|
|
|
|
// Right face
|
|
1, 0, 0,
|
|
1, 0, 0,
|
|
1, 0, 0,
|
|
1, 0, 0,
|
|
|
|
// Left face
|
|
-1, 0, 0,
|
|
-1, 0, 0,
|
|
-1, 0, 0,
|
|
-1, 0, 0,
|
|
]) : null;
|
|
|
|
final _uvs = uvs ? Float32List.fromList([
|
|
// Front face
|
|
1/3, 1/3,
|
|
2/3, 1/3,
|
|
2/3, 2/3,
|
|
1/3, 2/3,
|
|
|
|
// Back face
|
|
2/3, 2/3,
|
|
2/3, 1,
|
|
1, 1,
|
|
1, 2/3,
|
|
|
|
// Top face
|
|
1/3, 0,
|
|
1/3, 1/3,
|
|
2/3, 1/3,
|
|
2/3, 0,
|
|
|
|
// Bottom face
|
|
1/3, 2/3,
|
|
2/3, 2/3,
|
|
2/3, 1,
|
|
1/3, 1,
|
|
|
|
// Right face
|
|
2/3, 1/3,
|
|
2/3, 2/3,
|
|
1, 2/3,
|
|
1, 1/3,
|
|
|
|
// Left face
|
|
0, 1/3,
|
|
1/3, 1/3,
|
|
1/3, 2/3,
|
|
0, 2/3,
|
|
]) : null;
|
|
|
|
final indices = [
|
|
// Front face
|
|
0, 1, 2, 0, 2, 3,
|
|
// Back face
|
|
4, 5, 6, 4, 6, 7,
|
|
// Top face
|
|
8, 9, 10, 8, 10, 11,
|
|
// Bottom face
|
|
12, 13, 14, 12, 14, 15,
|
|
// Right face
|
|
16, 17, 18, 16, 18, 19,
|
|
// Left face
|
|
20, 21, 22, 20, 22, 23
|
|
];
|
|
return Geometry(vertices, indices, normals: _normals, uvs: _uvs);
|
|
}
|
|
|
|
static Geometry cylinder({double radius = 1.0, double length = 1.0, bool normals = true, bool uvs = true }) {
|
|
int segments = 32;
|
|
List<double> verticesList = [];
|
|
List<double> normalsList = [];
|
|
List<double> uvsList = [];
|
|
List<int> indices = [];
|
|
|
|
// Create vertices, normals, and UVs
|
|
for (int i = 0; i <= segments; i++) {
|
|
double theta = i * 2 * pi / segments;
|
|
double x = radius * cos(theta);
|
|
double z = radius * sin(theta);
|
|
|
|
// Top circle
|
|
verticesList.addAll([x, length / 2, z]);
|
|
normalsList.addAll([x / radius, 0, z / radius]);
|
|
uvsList.addAll([i / segments, 1]);
|
|
|
|
// Bottom circle
|
|
verticesList.addAll([x, -length / 2, z]);
|
|
normalsList.addAll([x / radius, 0, z / radius]);
|
|
uvsList.addAll([i / segments, 0]);
|
|
}
|
|
|
|
// Create indices
|
|
for (int i = 0; i < segments; i++) {
|
|
int topFirst = i * 2;
|
|
int topSecond = (i + 1) * 2;
|
|
int bottomFirst = topFirst + 1;
|
|
int bottomSecond = topSecond + 1;
|
|
|
|
// Top face (counter-clockwise)
|
|
indices.addAll([segments * 2, topSecond, topFirst]);
|
|
// Bottom face (counter-clockwise when viewed from below)
|
|
indices.addAll([segments * 2 + 1, bottomFirst, bottomSecond]);
|
|
// Side faces (counter-clockwise)
|
|
indices.addAll([topFirst, bottomFirst, topSecond]);
|
|
indices.addAll([bottomFirst, bottomSecond, topSecond]);
|
|
}
|
|
|
|
// Add center vertices, normals, and UVs for top and bottom faces
|
|
verticesList.addAll([0, length / 2, 0]); // Top center
|
|
normalsList.addAll([0, 1, 0]);
|
|
uvsList.addAll([0.5, 0.5]); // Center of top face
|
|
|
|
verticesList.addAll([0, -length / 2, 0]); // Bottom center
|
|
normalsList.addAll([0, -1, 0]);
|
|
uvsList.addAll([0.5, 0.5]); // Center of bottom face
|
|
|
|
// Add top and bottom face normals and UVs
|
|
for (int i = 0; i <= segments; i++) {
|
|
normalsList.addAll([0, 1, 0]); // Top face normal
|
|
normalsList.addAll([0, -1, 0]); // Bottom face normal
|
|
|
|
double u = 0.5 + 0.5 * cos(i * 2 * pi / segments);
|
|
double v = 0.5 + 0.5 * sin(i * 2 * pi / segments);
|
|
uvsList.addAll([u, v]); // Top face UV
|
|
uvsList.addAll([u, v]); // Bottom face UV
|
|
}
|
|
|
|
Float32List vertices = Float32List.fromList(verticesList);
|
|
Float32List? _normals = normals ? Float32List.fromList(normalsList) : null;
|
|
Float32List? _uvs = uvs ? Float32List.fromList(uvsList) : null;
|
|
|
|
return Geometry(vertices, indices, normals: _normals, uvs: _uvs);
|
|
}
|
|
|
|
static Geometry conic({double radius = 1.0, double length = 1.0, bool normals = true, bool uvs = true}) {
|
|
int segments = 32;
|
|
List<double> verticesList = [];
|
|
List<double> normalsList = [];
|
|
List<double> uvsList = [];
|
|
List<int> indices = [];
|
|
|
|
// Create vertices, normals, and UVs
|
|
for (int i = 0; i <= segments; i++) {
|
|
double theta = i * 2 * pi / segments;
|
|
double x = radius * cos(theta);
|
|
double z = radius * sin(theta);
|
|
|
|
// Base circle
|
|
verticesList.addAll([x, 0, z]);
|
|
|
|
// Calculate normal for the side
|
|
double nx = x / sqrt(x * x + length * length);
|
|
double nz = z / sqrt(z * z + length * length);
|
|
double ny = radius / sqrt(radius * radius + length * length);
|
|
normalsList.addAll([nx, ny, nz]);
|
|
|
|
// UV coordinates
|
|
uvsList.addAll([i / segments, 0]);
|
|
}
|
|
// Apex
|
|
verticesList.addAll([0, length, 0]);
|
|
normalsList.addAll([0, 1, 0]); // Normal at apex points straight up
|
|
uvsList.addAll([0.5, 1]); // UV for apex
|
|
|
|
// Create indices
|
|
for (int i = 0; i < segments; i++) {
|
|
// Base face (fixed to counterclockwise)
|
|
indices.addAll([segments + 1, i + 1, i]);
|
|
// Side faces (already correct)
|
|
indices.addAll([i, segments, i + 1]);
|
|
}
|
|
|
|
// Add base face normals and UVs
|
|
for (int i = 0; i <= segments; i++) {
|
|
normalsList.addAll([0, -1, 0]); // Base face normal
|
|
double u = 0.5 + 0.5 * cos(i * 2 * pi / segments);
|
|
double v = 0.5 + 0.5 * sin(i * 2 * pi / segments);
|
|
uvsList.addAll([u, v]); // Base face UV
|
|
}
|
|
|
|
Float32List vertices = Float32List.fromList(verticesList);
|
|
Float32List? _normals = normals ? Float32List.fromList(normalsList) : null;
|
|
Float32List? _uvs = uvs ? Float32List.fromList(uvsList) : null;
|
|
|
|
return Geometry(vertices, indices, normals: _normals, uvs: _uvs);
|
|
}
|
|
|
|
static Geometry plane({double width = 1.0, double height = 1.0, bool normals = true, bool uvs = true}) {
|
|
Float32List vertices = Float32List.fromList([
|
|
-width / 2, 0, -height / 2,
|
|
width / 2, 0, -height / 2,
|
|
width / 2, 0, height / 2,
|
|
-width / 2, 0, height / 2,
|
|
]);
|
|
|
|
Float32List? _normals = normals ? Float32List.fromList([
|
|
0, 1, 0,
|
|
0, 1, 0,
|
|
0, 1, 0,
|
|
0, 1, 0,
|
|
]) : null;
|
|
|
|
Float32List? _uvs = uvs ? Float32List.fromList([
|
|
0, 0,
|
|
1, 0,
|
|
1, 1,
|
|
0, 1,
|
|
]) : null;
|
|
|
|
List<int> indices = [
|
|
0, 2, 1,
|
|
0, 3, 2,
|
|
];
|
|
|
|
return Geometry(vertices, indices, normals: _normals, uvs: _uvs);
|
|
}
|
|
} |