Skip to content

Commit

Permalink
feat: 3d model performance upgrade
Browse files Browse the repository at this point in the history
  • Loading branch information
jvenin committed Mar 2, 2024
1 parent 33735c6 commit 9c6753e
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 66 deletions.
12 changes: 4 additions & 8 deletions lib/classes/model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:paraworld_gsf_viewer/classes/bouding_box.dart';
import 'package:paraworld_gsf_viewer/classes/rotation.dart';
import 'package:paraworld_gsf_viewer/classes/texture.dart';
import 'package:paraworld_gsf_viewer/classes/triangle.dart';
import 'package:paraworld_gsf_viewer/classes/vertex.dart';
Expand All @@ -27,9 +28,8 @@ class Model {
Uint16List triangleIndices,
Float32List normals,
}) getDrawingData(
Rotation rotation,
Size size, {
required double yRotationAngle,
required double zRotationAngle,
ModelTexture? texture,
bool showNormals = false,
}) {
Expand All @@ -47,10 +47,7 @@ class Model {
final List<double> normals = [];
final List<int> indices = [];
for (final triangle in triangles) {
final shouldShow = triangle.shouldShowTriangle(
yRotation: yRotationAngle,
zRotation: zRotationAngle,
);
final shouldShow = triangle.shouldShowTriangle(rotation);

for (int j = 0; j < triangle.points.length; j++) {
final vertexIndice = triangle.indices[j];
Expand All @@ -73,8 +70,7 @@ class Model {
heightOffset: heightOffset,
maxWidth: maxFactor,
maxHeight: maxFactor,
yRotation: yRotationAngle,
zRotation: zRotationAngle,
rotation: rotation,
);
normals.addAll([
projected.pointProjection.x,
Expand Down
29 changes: 29 additions & 0 deletions lib/classes/rotation.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import 'package:vector_math/vector_math.dart';

class Rotation {
Rotation(): matrix = Matrix3.zero();

Matrix3 matrix;

void setMatrix(
double xRotation,
double yRotation,
double zRotation,
) {
matrix = Matrix3.rotationZ(xRotation) *
Matrix3.rotationY(yRotation) *
Matrix3.rotationZ(zRotation);
}

@override
String toString() {
return matrix.toString();
}

@override
bool operator ==(Object other) =>
other is Rotation && other.matrix == matrix;

@override
int get hashCode => matrix.hashCode;
}
16 changes: 5 additions & 11 deletions lib/classes/triangle.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:paraworld_gsf_viewer/classes/rotation.dart';
import 'package:paraworld_gsf_viewer/classes/vertex.dart';
import 'package:vector_math/vector_math.dart';

Expand All @@ -12,17 +13,10 @@ class ModelTriangle {
final List<Vertex> points;
final List<int> indices;

bool shouldShowTriangle({
double xRotation = 0,
double yRotation = 0,
double zRotation = 0,
}) {
final p0 = points[0].transform(
xRotation: xRotation, yRotation: yRotation, zRotation: zRotation);
final p1 = points[1].transform(
xRotation: xRotation, yRotation: yRotation, zRotation: zRotation);
final p2 = points[2].transform(
xRotation: xRotation, yRotation: yRotation, zRotation: zRotation);
bool shouldShowTriangle(Rotation rotation) {
final p0 = points[0].transform(rotation);
final p1 = points[1].transform(rotation);
final p2 = points[2].transform(rotation);
final normal = (p1 - p0).cross(p2 - p0);

// we place our eye at center far from camera, hence -100 in z
Expand Down
62 changes: 27 additions & 35 deletions lib/classes/vertex.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:paraworld_gsf_viewer/classes/bouding_box.dart';
import 'package:paraworld_gsf_viewer/classes/rotation.dart';
import 'package:paraworld_gsf_viewer/test.dart';
import 'package:vector_math/vector_math.dart';

Expand All @@ -8,6 +9,7 @@ class Vertex {
Vertex(
this.positions, {
required this.box,
required this.offset,
this.normal,
this.textureCoordinates,
}) {
Expand All @@ -17,14 +19,15 @@ class Vertex {
}

late Vector3 positions;
late BoundingBox box;
final Vector3 offset;
(Vector3, Matrix3)? lastTransformation;
BoundingBox box;
Vector2? textureCoordinates;
Vertex? normal;
int? _normalSphereIndice;

// Because web compiles int as int32 we need to force big int for 64bit integers even in web
Vertex.fromModelBytes(BigInt sequence, int textureSequence, BoundingBox bb) {
box = bb;
Vertex.fromModelBytes(BigInt sequence, int textureSequence, this.box) : offset = box.center {
positions = Vector3(
((_k13BytesRatioValue * (sequence.toInt() & 0x1FFF)) *
(box.x.max - box.x.min) +
Expand All @@ -43,6 +46,7 @@ class Vertex {
normal = Vertex(
readFromSphere(256 * sphereCoef + _normalSphereIndice!),
box: BoundingBox.zero(),
offset: box.center,
);

normal!.positions += positions;
Expand All @@ -52,18 +56,14 @@ class Vertex {
((textureSequence >> 8) & 0xFF).toDouble() / 256);
}

Vector3 transform({
double xRotation = 0,
double yRotation = 0,
double zRotation = 0,
}) {
Vector3 transform(Rotation rotation) {
if (lastTransformation != null &&
lastTransformation!.$2 == rotation.matrix) {
return lastTransformation!.$1;
}
Vector3 copy = Vector3.copy(positions);
copy -= box.center;
copy.applyMatrix3(
Matrix3.rotationZ(xRotation) *
Matrix3.rotationY(yRotation) *
Matrix3.rotationZ(zRotation),
);
copy -= offset;
copy.applyMatrix3(rotation.matrix);
return copy;
}

Expand All @@ -73,35 +73,27 @@ class Vertex {
required double heightOffset,
required double maxWidth,
required double maxHeight,
double xRotation = 0,
double yRotation = 0,
double zRotation = 0,
required Rotation rotation,
}) {
final transformedPoint = transform(
xRotation: xRotation,
yRotation: yRotation,
zRotation: zRotation,
);
final transformedPoint = transform(rotation);
lastTransformation = (transformedPoint, rotation.matrix);

double perpectiveFactor = 1.0;

return (
pointProjection: Vector2(
transformedPoint.x * maxWidth * perpectiveFactor + widthOffset,
-transformedPoint.y * maxHeight * perpectiveFactor + heightOffset,
),
normalProjection: normal != null
? normal!
.project(
widthOffset: widthOffset,
heightOffset: heightOffset,
maxWidth: maxWidth,
maxHeight: maxHeight,
xRotation: xRotation,
yRotation: yRotation,
zRotation: zRotation,
)
.pointProjection
: null,
normalProjection: normal
?.project(
widthOffset: widthOffset,
heightOffset: heightOffset,
maxWidth: maxWidth,
maxHeight: maxHeight,
rotation: rotation,
)
.pointProjection
);
}

Expand Down
14 changes: 8 additions & 6 deletions lib/test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -225,12 +225,14 @@ List<Vertex> readFullSphere() {
for (int i = 0; i < bytesList.length; i += 12) {
final vertData = ByteData.sublistView(bytesList, i, i + 12);
verts.add(Vertex(
Vector3(
vertData.getFloat32(0, Endian.little),
vertData.getFloat32(4, Endian.little),
vertData.getFloat32(8, Endian.little),
),
box: BoundingBox.zero()));
Vector3(
vertData.getFloat32(0, Endian.little),
vertData.getFloat32(4, Endian.little),
vertData.getFloat32(8, Endian.little),
),
box: BoundingBox.zero(),
offset: Vector3.zero(),
));
}
assert(verts.length == 511);
return verts;
Expand Down
7 changes: 5 additions & 2 deletions lib/widgets/viewer/model_drawer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:paraworld_gsf_viewer/classes/model.dart';
import 'package:paraworld_gsf_viewer/classes/rotation.dart';
import 'package:paraworld_gsf_viewer/classes/texture.dart';
import 'package:paraworld_gsf_viewer/widgets/utils/mouse_movement_notifier.dart';
import 'dart:math' as math;
Expand All @@ -20,6 +21,8 @@ class ModelDrawer extends CustomPainter {
final ModelTexture? texture;
final bool showNormals;

final Rotation rotation = Rotation();

final Paint _paint = Paint()
..color = const Color.fromRGBO(0, 0, 0, 1)
..strokeWidth = 2
Expand Down Expand Up @@ -65,11 +68,11 @@ class ModelDrawer extends CustomPainter {
2 *
math.pi /
size.height;
rotation.setMatrix(0, yRotationAngle, zRotationAngle);

final data = model.getDrawingData(
rotation,
size,
yRotationAngle: yRotationAngle,
zRotationAngle: zRotationAngle,
texture: texture,
showNormals: showNormals,
);
Expand Down
8 changes: 4 additions & 4 deletions lib/widgets/viewer/viewer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class Viewer extends StatelessWidget {
@override
Widget build(BuildContext context) {
final List<Vertex> vertices = [];
final byteArray = convertToByteArray(cubeTest, true);
final byteArray = convertToByteArray(verticesTest);
final boundingBox = BoundingBox(
x: (min: -0.565, max: 1.130),
y: (min: -0.993, max: 1.982),
Expand All @@ -35,14 +35,14 @@ class Viewer extends StatelessWidget {
final vert = Vertex.fromModelBytes(
vertexValue,
int.parse(byteArray[i + 7] + byteArray[i + 6], radix: 16),
BoundingBox.zero(),
//boundingBox,
//BoundingBox.zero(),
boundingBox,
);
vertices.add(vert);
}

final List<ModelTriangle> triangles = [];
final triangleByteArray = convertToByteArray(cubeTriangles);
final triangleByteArray = convertToByteArray(trianglesTest);
for (int i = 0; i < triangleByteArray.length; i += 6) {
final List<int> indices = [];

Expand Down

0 comments on commit 9c6753e

Please sign in to comment.