ply_viewer 0.0.3 copy "ply_viewer: ^0.0.3" to clipboard
ply_viewer: ^0.0.3 copied to clipboard

A highly customizable 3D PLY point cloud & mesh viewer widget for Flutter, supporting local files, assets, raw bytes, and network URLs using WebGL and Three.js.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:ply_viewer/ply_viewer.dart';

void main() {
  runApp(const PlyViewerExampleApp());
}

class PlyViewerExampleApp extends StatelessWidget {
  const PlyViewerExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '3D Multi-Format Viewer Example',
      theme: ThemeData.dark(useMaterial3: true),
      home: const PlyViewerHomePage(),
    );
  }
}

class SampleModelItem {
  final String name;
  final String url;
  final Model3DFormat format;
  final double initialRotationX;
  final double initialRotationZ;

  const SampleModelItem({
    required this.name,
    required this.url,
    required this.format,
    this.initialRotationX = 0.0,
    this.initialRotationZ = 0.0,
  });
}

class PlyViewerHomePage extends StatefulWidget {
  const PlyViewerHomePage({super.key});

  @override
  State<PlyViewerHomePage> createState() => _PlyViewerHomePageState();
}

class _PlyViewerHomePageState extends State<PlyViewerHomePage> {
  final PlyViewerController _controller = PlyViewerController();

  static const List<SampleModelItem> _sampleModels = [
    SampleModelItem(
      name: '02site.ply (GitHub PLY)',
      url:
          'https://raw.githubusercontent.com/rithamto/ply_viewer/main/02site.ply',
      format: Model3DFormat.ply,
      initialRotationZ: -90.0,
    ),
    SampleModelItem(
      name: 'Astronaut (GLB)',
      url:
          'https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/main/2.0/Astronaut/glTF-Binary/Astronaut.glb',
      format: Model3DFormat.glb,
      initialRotationX: 0.0,
    ),
    SampleModelItem(
      name: 'Damaged Helmet (glTF)',
      url:
          'https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/main/2.0/DamagedHelmet/glTF/DamagedHelmet.gltf',
      format: Model3DFormat.gltf,
      initialRotationX: 0.0,
    ),
  ];

  late SampleModelItem _selectedModel;

  @override
  void initState() {
    super.initState();
    _selectedModel = _sampleModels.first;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(_selectedModel.name),
        actions: [
          PopupMenuButton<SampleModelItem>(
            icon: const Icon(Icons.folder_open),
            tooltip: 'Switch 3D Model',
            onSelected: (model) {
              setState(() {
                _selectedModel = model;
              });
            },
            itemBuilder: (context) => _sampleModels
                .map(
                  (m) => PopupMenuItem<SampleModelItem>(
                    value: m,
                    child: Text(m.name),
                  ),
                )
                .toList(),
          ),
          IconButton(
            icon: const Icon(Icons.rotate_90_degrees_cw),
            tooltip: 'Rotate Axis 90°',
            onPressed: () => _controller.rotateAxis90(),
          ),
          IconButton(
            icon: const Icon(Icons.refresh),
            tooltip: 'Reset View',
            onPressed: () => _controller.resetView(),
          ),
          IconButton(
            icon: const Icon(Icons.grid_on),
            tooltip: 'Toggle Grid',
            onPressed: () => _controller.toggleGrid(true),
          ),
        ],
      ),
      body: PlyViewer(
        key: ValueKey(_selectedModel.url),
        source: PlySource.network(
          _selectedModel.url,
          format: _selectedModel.format,
        ),
        controller: _controller,
        config: PlyViewerConfig(
          backgroundColor: const Color(0xFF141414),
          accentColor: Colors.orange,
          showGrid: true,
          showToolbar: true,
          showDPad: true,
          showElevationControls: true,
          showViewToggle: true,
          showOrientationToggle: true,
          initialRotationX: _selectedModel.initialRotationX,
          initialRotationZ: _selectedModel.initialRotationZ,
        ),
        onLoadProgress: (progress) {
          debugPrint(
              '3D Load progress: ${(progress * 100).toStringAsFixed(1)}%');
        },
        onLoaded: () {
          debugPrint(
              '3D Model (${_selectedModel.format.name}) Loaded Successfully!');
        },
        onError: (error) {
          debugPrint('3D Model Load Error: $error');
        },
      ),
    );
  }
}
2
likes
160
points
170
downloads

Documentation

API reference

Publisher

verified publisherrithamto.site

Weekly Downloads

A highly customizable 3D PLY point cloud & mesh viewer widget for Flutter, supporting local files, assets, raw bytes, and network URLs using WebGL and Three.js.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter, flutter_inappwebview

More

Packages that depend on ply_viewer