Skip to content

Commit

Permalink
feat: links
Browse files Browse the repository at this point in the history
  • Loading branch information
jvenin committed May 2, 2024
1 parent 9edd839 commit 35c7cc9
Show file tree
Hide file tree
Showing 10 changed files with 163 additions and 32 deletions.
17 changes: 16 additions & 1 deletion lib/classes/gsf/header2/chunks/link.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import 'dart:typed_data';

import 'package:paraworld_gsf_viewer/classes/bouding_box.dart';
import 'package:paraworld_gsf_viewer/classes/gsf/header2/chunks/chunk.dart';
import 'package:paraworld_gsf_viewer/classes/gsf_data.dart';
import 'package:vector_math/vector_math_64.dart';
import 'package:paraworld_gsf_viewer/classes/vertex.dart';
import 'package:vector_math/vector_math.dart';

typedef LinkModel = ({String fourCC, ModelVertex vertex});

class LinkChunk extends Chunk {
late final Standard4BytesData<int> guid;
Expand Down Expand Up @@ -105,6 +109,17 @@ class LinkChunk extends Chunk {
}
}

LinkModel toModelVertex() {
return (
fourCC: fourccLink.value.value,
vertex: ModelVertex(
position,
box: BoundingBoxModel.zero(),
positionOffset: Vector3.zero(),
),
);
}

@override
int getEndOffset() {
return boneWeights?.offsettedLength ?? fourccLink.offsettedLength;
Expand Down
1 change: 1 addition & 0 deletions lib/classes/gsf/header2/chunks/mesh.dart
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ mixin MeshToModelInterface on Chunk {
cloth: [],
boundingBox: globalBB,
skeletons: [],
links: [],
);
}
}
Expand Down
7 changes: 6 additions & 1 deletion lib/classes/gsf/header2/model_settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:paraworld_gsf_viewer/classes/gsf/header2/chunks/bounding_box.dar
import 'package:paraworld_gsf_viewer/classes/gsf/header2/chunks/chunk.dart';
import 'package:paraworld_gsf_viewer/classes/gsf/header2/chunks/chunk_attributes.dart';
import 'package:paraworld_gsf_viewer/classes/gsf/header2/chunks/cloth.dart';
import 'package:paraworld_gsf_viewer/classes/gsf/header2/chunks/link.dart';
import 'package:paraworld_gsf_viewer/classes/gsf/header2/chunks/mesh.dart';
import 'package:paraworld_gsf_viewer/classes/gsf/header2/chunks/skeleton.dart';
import 'package:paraworld_gsf_viewer/classes/gsf/header2/chunks_table.dart';
Expand Down Expand Up @@ -239,12 +240,15 @@ class ModelSettings extends GsfPart {
) {
final List<ModelMesh> meshes = [];
final List<ModelMesh> cloths = [];
List<List<List<(int?, ModelVertex)>>> skeletons = [];
final List<SkeletonModel> skeletons = [];
final List<LinkModel> links = [];
final List<int> materialIndices =
fallbackTable?.usedMaterialIndexes.map((e) => e.value).toList() ?? [];
for (final chunk in chunksTable?.chunks ?? <Chunk>[]) {
if (chunk.type == ChunkType.skeleton) {
skeletons.add((chunk as SkeletonChunk).toModel());
} else if (chunk.type.isLinkLike()) {
links.add((chunk as LinkChunk).toModelVertex());
} else if (chunk.type.isMeshLike()) {
meshes.add((chunk as MeshChunk).toModelMesh(
ChunkAttributes.fromValue(type, chunk.attributes.value),
Expand Down Expand Up @@ -274,6 +278,7 @@ class ModelSettings extends GsfPart {
cloth: cloths,
boundingBox: boundingBox.toModelBox(),
skeletons: skeletons,
links: links,
);
}

Expand Down
65 changes: 60 additions & 5 deletions lib/classes/model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import 'dart:typed_data';
import 'dart:ui' as ui;

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:paraworld_gsf_viewer/classes/bouding_box.dart';
import 'package:paraworld_gsf_viewer/classes/gsf/header2/chunks/chunk_attributes.dart';
import 'package:paraworld_gsf_viewer/classes/gsf/header2/chunks/link.dart';
import 'package:paraworld_gsf_viewer/classes/gsf/header2/chunks/skeleton.dart';
import 'package:paraworld_gsf_viewer/classes/gsf/header2/material_attribute.dart';
import 'package:paraworld_gsf_viewer/classes/gsf/header2/model_settings.dart';
Expand All @@ -30,6 +32,7 @@ class Model {
required this.cloth,
required this.boundingBox,
required this.skeletons,
required this.links,
});

final ModelType type;
Expand All @@ -38,6 +41,7 @@ class Model {
final List<ModelMesh> cloth;
final BoundingBoxModel boundingBox;
final List<SkeletonModel> skeletons;
final List<LinkModel> links;
// todo skeleton
// todo position links

Expand All @@ -50,9 +54,22 @@ class Model {
..strokeWidth = 2
..strokeCap = StrokeCap.round;

final positionLinkPaint = Paint()
..color = Colors.blue
..strokeWidth = 8
..strokeCap = StrokeCap.round;

final Map<ModelTexture, (int, img.Image)> _texturesOffsets = {};
ui.Image? _composedModelImage;

TextStyle _getTextStyle(double scaleFactor, Color color) {
return TextStyle(
color: color,
fontSize: 12 + scaleFactor,
fontWeight: FontWeight.bold,
);
}

/// When loading a model, we need to load all the textures and compose them into a single image
/// so it allow for a single canvas paint call for z buffering with single image shader
/// Images are being added to the composed image from left to right.
Expand Down Expand Up @@ -145,6 +162,48 @@ class Model {
}
}

void drawPositionLinks(
Transformation transformation,
ui.Size size,
ui.Canvas canvas,
) {
final projectionData = getProjectionData(size);
final pos = <double>[];
final textStyle = _getTextStyle(transformation.scaleFactor, Colors.blue);
for (final link in links) {
final coords = link.vertex.project(
widthOffset: projectionData.widthOffset,
heightOffset: projectionData.heightOffset,
maxWidth: projectionData.maxFactor,
maxHeight: projectionData.maxFactor,
transformation: transformation,
);
pos.addAll([coords.pointProjection.x, coords.pointProjection.y]);
final namePainter = TextPainter(
text: TextSpan(
text: link.fourCC.toString(),
style: textStyle,
),
textDirection: TextDirection.ltr,
)..layout(
minWidth: 0,
maxWidth: size.width,
);
namePainter.paint(
canvas,
Offset(
coords.pointProjection.x,
coords.pointProjection.y,
),
);
}
canvas.drawRawPoints(
ui.PointMode.points,
Float32List.fromList(pos),
positionLinkPaint,
);
}

void drawSkeleton(
Transformation transformation,
ui.Size size,
Expand All @@ -153,11 +212,7 @@ class Model {
) {
final projectionData = getProjectionData(size);
skeletonPaint.color = meshColor;
final textStyle = TextStyle(
color: Colors.pink,
fontSize: 12 + transformation.scaleFactor,
fontWeight: FontWeight.bold,
);
final textStyle = _getTextStyle(transformation.scaleFactor, Colors.pink);
final jointPaint = Paint()
..color = Colors.pink
..strokeWidth = 3 + transformation.scaleFactor / 2;
Expand Down
1 change: 1 addition & 0 deletions lib/widgets/header2/widgets/chunks/submesh.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class SubmeshDisplay extends StatelessWidget {
cloth: [],
boundingBox: modelData.box,
skeletons: [],
links: [],
);
return Flexible(
child: Column(
Expand Down
11 changes: 9 additions & 2 deletions lib/widgets/viewer/model_drawer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class ModelDrawer extends CustomPainter {
required this.attributesFilter,
required this.showCloth,
required this.showSkeleton,
required this.showLinks,
}) : super(repaint: mousePosition);

final ValueNotifier<MouseEventData> mousePosition;
Expand All @@ -35,6 +36,7 @@ class ModelDrawer extends CustomPainter {
final ChunkAttributes attributesFilter;
final bool showCloth;
final bool showSkeleton;
final bool showLinks;

final Transformation transformation = Transformation();

Expand Down Expand Up @@ -202,8 +204,13 @@ class ModelDrawer extends CustomPainter {
meshColor,
);
}

drawAxis(size, canvas);
if (showLinks) {
model.drawPositionLinks(
transformation,
size,
canvas,
);
}
}

@override
Expand Down
8 changes: 8 additions & 0 deletions lib/widgets/viewer/notifier.dart
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,14 @@ class ModelSelectionStateNotifier extends Notifier<ModelViewerSelectionState> {
orElse: () => null);
}

void updateShowLinks(bool showLinks) {
state.maybeMap(
withModel: (withModel) {
state = withModel.copyWith(showLinks: showLinks);
},
orElse: () => null);
}

void updateFilterAttribute(int indice) {
state.maybeMap(
withModel: (withModel) {
Expand Down
1 change: 1 addition & 0 deletions lib/widgets/viewer/state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ class ModelViewerSelectionState with _$ModelViewerSelectionState {
@Default(true) showTexture,
@Default(false) showPartyColor,
@Default(false) showSkeleton,
@Default(true) showLinks,
}) = ModelViewerSelectionStateWithModel;
}
Loading

0 comments on commit 35c7cc9

Please sign in to comment.