fix geometry normals/UVs
This commit is contained in:
@@ -52,7 +52,7 @@ class GeometryHelper {
|
|||||||
return Geometry(vertices, indices, normals: _normals, uvs: _uvs);
|
return Geometry(vertices, indices, normals: _normals, uvs: _uvs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Geometry cube({bool normals = false, bool uvs = false}) {
|
static Geometry cube({bool normals = true, bool uvs = true}) {
|
||||||
final vertices = Float32List.fromList([
|
final vertices = Float32List.fromList([
|
||||||
// Front face
|
// Front face
|
||||||
-1, -1, 1,
|
-1, -1, 1,
|
||||||
@@ -251,18 +251,26 @@ static Geometry cube({bool normals = false, bool uvs = false}) {
|
|||||||
return Geometry(vertices, indices, normals: _normals, uvs: _uvs);
|
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}) {
|
static Geometry conic({double radius = 1.0, double length = 1.0, bool normals = true, bool uvs = true}) {
|
||||||
int segments = 32;
|
int segments = 32;
|
||||||
List<double> verticesList = [];
|
List<double> verticesList = [];
|
||||||
List<double> normalsList = [];
|
List<double> normalsList = [];
|
||||||
List<double> uvsList = [];
|
List<double> uvsList = [];
|
||||||
List<int> indices = [];
|
List<int> indices = [];
|
||||||
|
|
||||||
int vertexOffset = 0;
|
|
||||||
|
|
||||||
// Create side vertices (base circle + apex)
|
// Create side vertices (base circle + apex)
|
||||||
|
// Add apex vertex first
|
||||||
|
verticesList.addAll([0, length, 0]);
|
||||||
|
if (normals) {
|
||||||
|
normalsList.addAll([0, 1, 0]);
|
||||||
|
}
|
||||||
|
if (uvs) {
|
||||||
|
uvsList.addAll([0.5, 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now add base circle vertices
|
||||||
for (int i = 0; i <= segments; i++) {
|
for (int i = 0; i <= segments; i++) {
|
||||||
double theta = i * 2 * pi / segments;
|
double theta = (i % segments) * 2 * pi / segments;
|
||||||
double x = radius * cos(theta);
|
double x = radius * cos(theta);
|
||||||
double z = radius * sin(theta);
|
double z = radius * sin(theta);
|
||||||
|
|
||||||
@@ -271,12 +279,25 @@ static Geometry cube({bool normals = false, bool uvs = false}) {
|
|||||||
|
|
||||||
if (normals) {
|
if (normals) {
|
||||||
// Calculate normal for the side (perpendicular to the cone surface)
|
// Calculate normal for the side (perpendicular to the cone surface)
|
||||||
// The normal is perpendicular to the line from the edge point to the apex
|
// For a cone, the normal is perpendicular to the slant height
|
||||||
double nx = x;
|
// We calculate it directly without using cross product
|
||||||
double nz = z;
|
|
||||||
double ny = radius;
|
|
||||||
|
|
||||||
// Normalize the normal vector
|
// Calculate the slant height vector (from base point to apex)
|
||||||
|
double slantX = -x; // Vector from base point to apex
|
||||||
|
double slantY = length;
|
||||||
|
double slantZ = -z;
|
||||||
|
|
||||||
|
// Calculate tangent vector around the circle (perpendicular to radius)
|
||||||
|
double tangentX = -z;
|
||||||
|
double tangentY = 0;
|
||||||
|
double tangentZ = x;
|
||||||
|
|
||||||
|
// Cross product of tangent and slant gives the normal
|
||||||
|
double nx = (tangentY * slantZ) - (tangentZ * slantY);
|
||||||
|
double ny = (tangentZ * slantX) - (tangentX * slantZ);
|
||||||
|
double nz = (tangentX * slantY) - (tangentY * slantX);
|
||||||
|
|
||||||
|
// Normalize
|
||||||
double normalLength = sqrt(nx * nx + ny * ny + nz * nz);
|
double normalLength = sqrt(nx * nx + ny * ny + nz * nz);
|
||||||
nx /= normalLength;
|
nx /= normalLength;
|
||||||
ny /= normalLength;
|
ny /= normalLength;
|
||||||
@@ -291,58 +312,42 @@ static Geometry cube({bool normals = false, bool uvs = false}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add apex vertex
|
|
||||||
verticesList.addAll([0, length, 0]);
|
|
||||||
vertexOffset = segments + 1;
|
|
||||||
|
|
||||||
if (normals) {
|
|
||||||
// Apex normal points up
|
|
||||||
normalsList.addAll([0, 1, 0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uvs) {
|
|
||||||
// UV for apex
|
|
||||||
uvsList.addAll([0.5, 1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create side faces indices
|
// Create side faces indices
|
||||||
|
// Apex is at index 0
|
||||||
for (int i = 0; i < segments; i++) {
|
for (int i = 0; i < segments; i++) {
|
||||||
|
int current = i + 1; // +1 because apex is at index 0
|
||||||
|
int next = ((i + 1) % segments) + 1; // +1 for the same reason
|
||||||
|
|
||||||
// Create triangular faces from edge to apex
|
// Create triangular faces from edge to apex
|
||||||
indices.addAll([i, (i + 1) % (segments + 1), vertexOffset]);
|
// Using counter-clockwise winding when viewed from outside
|
||||||
|
indices.addAll([0, current, next]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create base circle vertices (duplicate for proper normals and UVs)
|
// Create base vertices separately (for proper normals)
|
||||||
int baseStartIndex = verticesList.length ~/ 3;
|
int baseStartIndex = verticesList.length ~/ 3;
|
||||||
|
|
||||||
// Center vertex for base
|
// Center vertex for base
|
||||||
verticesList.addAll([0, 0, 0]);
|
verticesList.addAll([0, 0, 0]);
|
||||||
|
|
||||||
if (normals) {
|
if (normals) {
|
||||||
// Base center normal points down
|
|
||||||
normalsList.addAll([0, -1, 0]);
|
normalsList.addAll([0, -1, 0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uvs) {
|
if (uvs) {
|
||||||
// UV for base center
|
|
||||||
uvsList.addAll([0.5, 0.5]);
|
uvsList.addAll([0.5, 0.5]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add base edge vertices
|
// Add base edge vertices
|
||||||
for (int i = 0; i <= segments; i++) {
|
for (int i = 0; i < segments; i++) {
|
||||||
double theta = i * 2 * pi / segments;
|
double theta = i * 2 * pi / segments;
|
||||||
double x = radius * cos(theta);
|
double x = radius * cos(theta);
|
||||||
double z = radius * sin(theta);
|
double z = radius * sin(theta);
|
||||||
|
|
||||||
// Base circle vertex (duplicate for proper normal/UV)
|
|
||||||
verticesList.addAll([x, 0, z]);
|
verticesList.addAll([x, 0, z]);
|
||||||
|
|
||||||
if (normals) {
|
if (normals) {
|
||||||
// Base normal points down
|
|
||||||
normalsList.addAll([0, -1, 0]);
|
normalsList.addAll([0, -1, 0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uvs) {
|
if (uvs) {
|
||||||
// UV for base edge
|
|
||||||
double u = 0.5 + 0.5 * cos(theta);
|
double u = 0.5 + 0.5 * cos(theta);
|
||||||
double v = 0.5 + 0.5 * sin(theta);
|
double v = 0.5 + 0.5 * sin(theta);
|
||||||
uvsList.addAll([u, v]);
|
uvsList.addAll([u, v]);
|
||||||
@@ -351,8 +356,11 @@ static Geometry cube({bool normals = false, bool uvs = false}) {
|
|||||||
|
|
||||||
// Create base faces indices
|
// Create base faces indices
|
||||||
for (int i = 0; i < segments; i++) {
|
for (int i = 0; i < segments; i++) {
|
||||||
// Fan triangulation from center to edge
|
int current = baseStartIndex + 1 + i;
|
||||||
indices.addAll([baseStartIndex, baseStartIndex + i + 1, baseStartIndex + i + 2]);
|
int next = baseStartIndex + 1 + ((i + 1) % segments);
|
||||||
|
|
||||||
|
// Using clockwise winding for base faces (since they face down)
|
||||||
|
indices.addAll([baseStartIndex, next, current]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert to Float32List
|
// Convert to Float32List
|
||||||
|
|||||||
Reference in New Issue
Block a user