A flutter package that displays large 3D datasets on a transparent canvas
****** Important ******
- Original project can be found ditredi.
- Add layers and sort z-index by figures, to fix rendering problems when two figures are close enough to each other.
- Rendering priority from high to low would be layers, figure’s z-index, and face’s z-index in each figure.
DiTreDi (D 3D)
A flutter package that displays large 3D datasets on a transparent canvas.
Preface
DiTreDi was created to efficiently display datasets and meshes in 3D space. It wasn’t intended to create a 3D game engine and is rather useful for displaying static meshes.
Table of Contents
Getting started
Add imports for ditredi
and vector_math_64
:
import 'package:ditredi/ditredi.dart';
import 'package:vector_math/vector_math_64.dart';
Add DiTreDi
widget to your tree:
DiTreDi(
figures: [
Cube3D(2, Vector3(0, 0, 0)),
],
)
And voilà, a single cube will be displayed:
Note:
DiTreDi
takes full available size. Wrap inSizedBox
orExpanded
to control its constraints and size.
Controller
DiTreDiController
controls a scene rotation, scale, light.
To set up a controller, keep its reference in a state and pass to the controller
parameter.
// in a state
@override
void initState() {
super.initState();
controller = DiTreDiController();
}
DiTreDi(
figures: [
Cube3D(2, Vector3(0, 0, 0)),
],
controller: controller,
)
Once ready, update controller state by calling:
controller.update(rotationY: 30, rotationX: 30);
To handle input gestures use GestureDetector
or DiTreDiDraggable
:
DiTreDiDraggable(
controller: controller,
child: DiTreDi(
figures: [Cube3D(1, vector.Vector3(0, 0, 0))],
controller: controller,
),
);
Config
DiTreDiConfig
defines component “defaults” – mesh color, lines and points width (if not specified).
// in a state
DiTreDi(
figures: [
Cube3D(2, Vector3(0, 0, 0)),
],
config: DiTreDiConfig(
supportZIndex: false,
),
)
If a huge dataset is displayed and you don’t bother about paint order, it’s recommended to disable z-index which boosts drawing speed (supportZIndex = false
).
Shapes
DiTreDi
out-of-the-box supports shapes like:
Cube3D
Just a cube.
DiTreDi(
figures: [
Cube3D(2, Vector3(0, 0, 0)),
],
)
Face3D
Face (aka triangle).
DiTreDi(
figures: [
Face3D(
Triangle.points(
Vector3(0, 0 - 1, 0 - 1),
Vector3(0, 0 - 1, 0 + 1),
Vector3(0, 0 + 1, 0 + 1),
),
),
],
)
Group3D
Groups a list of figures.
DiTreDi(
figures: [
Group3D([
Cube3D(1, Vector3(0, 0, 0)),
Cube3D(1, Vector3(3, 3, 3)),
]),
],
)
An alternative method to display multiple shapes, it to put a few figures
:
DiTreDi(
figures: [
Cube3D(1, Vector3(0, 0, 0)),
Cube3D(1, Vector3(-3, 0, 0)),
Cube3D(1, Vector3(3, 0, 0)),
Cube3D(1, Vector3(0, -3, 0)),
Cube3D(1, Vector3(0, 3, 0)),
Cube3D(1, Vector3(0, 0, -3)),
Cube3D(1, Vector3(0, 0, 3)),
],
)
Line3D
A line.
DiTreDi(
figures: [
Line3D(Vector3(0, 1, 0), Vector3(2, 1, 4), width: 8),
Line3D(Vector3(0, 2, 0), Vector3(2, 2, 4), width: 6),
Line3D(Vector3(0, 3, 0), Vector3(2, 3, 4), width: 4),
Line3D(Vector3(0, 4, 0), Vector3(2, 4, 4), width: 2),
Line3D(Vector3(0, 5, 0), Vector3(2, 5, 4), width: 1),
],
)
Mesh3D
A mesh made of faces (triangles).
You could use ObjParser
to load it from .obj file contents.
Currently, only material (mtl) as colours are supported.
Load from a string obj content:
DiTreDi(
figures: [
Mesh3D(await ObjParser().parse(meshLines)),
],
)
Load from a flutter resource:
DiTreDi(
figures: [
Mesh3D(await ObjParser().loadFromResources("assets/model.obj")),
],
)
Load from a file:
DiTreDi(
figures: [
Mesh3D(await ObjParser().loadFromFile(Uri.parse("files/model.obj"))),
],
)
Plane3D
A plane facing x (left/right), y (bottom/up) or z (near/far) axis.
DiTreDi(
figures: [
Plane3D(5, Axis3D.y, false, Vector3(0, 0, 0), color: Colors.green),
],
)
Point3D
A point (exactly a square).
DiTreDi(
figures: [
Plane3D(5, Axis3D.y, false, Vector3(0, 0, 0), color: Colors.green),
],
)
PointPlane3D
A plane made of points (e.g. to show an object) scale.
DiTreDi(
figures: [
PointPlane3D(1, Axis3D.y, 0.1, Vector3(0, 0, 0), pointWidth: 5),
Cube3D(0.1, Vector3(0, 0, 0)),
],
)
Transformations
Points and wireframes
Each figure could be changed to points or lines (wireframe).
DiTreDi(
figures: [
...Plane3D(5, Axis3D.z, false, Vector3(0, 0, 0)).toPoints(),
],
)
DiTreDi(
figures: [
...Plane3D(5, Axis3D.z, false, Vector3(0, 0, 0)).toLines(),
],
)
Matrix transformation
Figures might be rotated, translated, and scaled with TransformModifier3D
and Matrix4
.
Each transformation is made for 0,0,0
coordinates.
DiTreDi(
figures: [
TransformModifier3D(
Cube3D(2, Vector3(1, 1, 1)),
Matrix4.identity()
..setRotationX(10)
..setRotationY(10)
..setRotationZ(10)),
],
)
To rotate the figure around its “own” position, you must translate, rotate and translate back.
DiTreDi(
figures: [
Cube3D(2, Vector3(0, 0, 0)),
TransformModifier3D(
Cube3D(2, Vector3(2, 2, 2)),
Matrix4.identity()
..translate(2.0, 2.0, 2.0)
..rotateZ(10)
..rotateX(10)
..translate(-2.0, -2.0, -2.0)),
],
)
Transform Group3D
to apply a matrix to each figure.
DiTreDi(
figures: [
Cube3D(2, Vector3(0, 0, 0)),
TransformModifier3D(
Group3D([
Cube3D(2, Vector3(2, 2, 2)),
Cube3D(2, Vector3(4, 4, 4)),
]),
transformation,
),
],
)
Benchmarks
TBD