Alternate Python bindings for the Open Asset Import Library (ASSIMP)

Overview

Impasse

Python Test Status codecov

A simple Python wrapper for assimp using cffi to access the library. Requires Python >= 3.7.

It's a fork of PyAssimp, Assimp's official Python port. In contrast to PyAssimp, it strictly targets modern Python 3 and provides type hints. It also aims to allow mutating scenes before exporting by having all wrapper classes operate directly on the underlying C data structures.

Usage

Complete example: 3D viewer

impasse comes with a simple 3D viewer that shows how to load and display a 3D model using a shader-based OpenGL pipeline.

Screenshot

To use it:

python ./scripts/3d_viewer.py <path to your model>

You can use this code as starting point in your applications.

Writing your own code

To get started with impasse, examine the simpler sample.py script in scripts/, which illustrates the basic usage. All Assimp data structures are wrapped using ctypes. All the data+length fields in Assimp's data structures (such as aiMesh::mNumVertices, aiMesh::mVertices) are replaced by list-like wrapper classes, so you can call len() on them to get their respective size and access members using [].

For example, to load a file named hello.3ds and print the first vertex of the first mesh, you would do (proper error handling substituted by assertions ...):

from impasse import load

scene = load('hello.3ds')

assert len(scene.meshes)
mesh = scene.meshes[0]

assert len(mesh.vertices)
print(mesh.vertices[0])

Another example to list the 'top nodes' in a scene:

from impasse import load

scene = load('hello.3ds')
for c in scene.root_node.children:
    print(str(c))

All of assimp's coordinate classes are returned as NumPy arrays, so you can work with them using library for 3d math that handles NumPy arrays. Using transforms.py to modify the scene:

import math

import numpy
import transformations
import impasse

# assimp returns an immutable scene, we have to copy it if we want to change it
scene = impasse.load('hello.3ds').copy_mutable()
transform = scene.root_node.transformation
# Rotate the root node's transform by 180 deg on X
transform = numpy.dot(transformations.rotation_matrix(math.pi, (1, 0, 0)), transform)
scene.root_node.transformation = transform
impasse.export(scene, 'whatever.obj', 'obj')

Installing

Install impasse by running:

pip install impasse

or, if you want to install from the source directory:

pip install -e .

Impasse requires an assimp dynamic library (DLL on Windows, .so on linux, .dynlib on macOS) in order to work. The default search directories are:

  • the current directory
  • on linux additionally: /usr/lib, /usr/local/lib, /usr/lib/ -linux-gnu

To build that library, refer to the Assimp master INSTALL instructions. To look in more places, edit ./impasse/helper.py. There's an additional_dirs list waiting for your entries.

Progress

All features present in PyAssimp are now present in Assimp (plus a few more!) Since the API largely mirrors PyAssimp's, most existing code should work in Impasse with minor changes.

Note that Impasse is not complete. Many assimp features are still missing, mostly around mutating scenes. Notably, anything that would require a new or delete in assimp's C++ API is not supported.

Performance

Impasse tries to avoid unnecessary copies or conversions of data owned by C, and most classes are just thin layers around the underlying CFFI structs. NumPy arrays that directly map to the underlying structs' memory are used for the coordinate structs like Matrix4x4 and Vector3D.

Testing with a similar quicktest.py script against assimp's test model directory:

Impasse

** Loaded 169 models, got controlled errors for 28 files, 0 uncontrolled

real	0m1.460s
user	0m1.676s
sys	0m0.571s

PyAssimp

** Loaded 165 models, got controlled errors for 28 files, 4 uncontrolled

real	0m7.607s
user	0m7.746s
sys	0m0.579s
Comments
  • Nicer way of referring to material property keys

    Nicer way of referring to material property keys

        ('$mat.twosided', 0): [0]
        ('$mat.refracti', 0): [1.]
        ('$mat.bumpscaling', 0): [1.]
        ('$clr.specular', 0): [1. 1. 1.]
    

    Those keys are in the data returned by assimp, but I'm not sure if the prefix is that meaningful. PyAssimp strips off everything before the first .. If they're meaningful or there are collisions without those prefixes, we should keep a string enum of common ones that's easier to refer to.

    enhancement 
    opened by SaladDais 3
  • Rebase on top of original assimp sources to keep PyAssimp's commit history intact

    Rebase on top of original assimp sources to keep PyAssimp's commit history intact

    Now that I think of it, it's preferable to keep the commit history for assimp even if most of it's unrelated to PyAssimp. Make a commit deleting all assimp sources and moving PyAssimp to the repo root, then rebase impasse on top of that.

    Rewriting history isn't nice since I've already based my sources on top of a squashed commit, but impact should be mininal since nobody's using this yet.

    opened by SaladDais 1
  • Make mapping classes mix-ins

    Make mapping classes mix-ins

    Other than name collisions with keys / values, I don't think there's any reason to keep the explicit as_mapping() method rather than just putting them on a mixin for the SerializeableStructs. Can define manual renames for any of those.

    This'd give us a closer API to what PyAssimp already has

    enhancement 
    opened by SaladDais 1
  • Add accessors for mesh and texture that return instances rather than indexes

    Add accessors for mesh and texture that return instances rather than indexes

    All of the struct wrapper have a _scene member that should allow them to transparently look up the texture / material by the index in the attr they wrap.

    enhancement 
    opened by SaladDais 1
  • Get scene mutability working

    Get scene mutability working

    Per the C api you have to create a copy of the scene to get a non-const version: https://github.com/assimp/assimp/blob/master/include/assimp/cexport.h#L109-L123 . Right now all the structs we return have wrappers enforcing the const-ness of scene returned from the the aiImportFile() function. Need to expose the copying functions so people can get a scene they can modify before export.

    enhancement 
    opened by SaladDais 1
  • Package assimp shared library so assimp isn't required to be on the system

    Package assimp shared library so assimp isn't required to be on the system

    Would be nice so people don't have to do some weird conda thing if they want to install the package including assimp.

    I think it should be enough to have osx aarch64, osx x64, linux x64 and windows x64 packages. We don't need to do python version-specific builds, since we'll just be building the assimp library itself and binding against it with cffi. It should be provided in an optional, separate package with the shared library in the package data for the given platform's build.

    enhancement 
    opened by SaladDais 0
  • Add ability to alloc new structs, append to sequences

    Add ability to alloc new structs, append to sequences

    This is tricky since assimp makes liberal use of new[] and delete[] on types that have non-trivial destructors (like aiTexture.) malloc()ing and free()ing those is technically possible but inadvisable, and requires knowledge of the platform / compiler's C++ ABI.

    Likewise, assimp's C API doesn't appear to expose a wrapper around those new[] and delete[] calls. Adding functions to assimp to do those would be the least nasal demon-y approach but wouldn't be available in stable distros' libs.

    A third approach would be to have Scenes keep track of the original values of mutated ptrs, then put everything back in place when the GC happens so anything that'd been internally alloc'd with new could be deleted by assimp. Would also have to keep a list of things we'd malloc()d in our own code to manually free(). Can see a lot of nasty corner cases with this one.

    enhancement help wanted 
    opened by SaladDais 0
Releases(v5.2.0)
Owner
Salad Dais
Code as craft
Salad Dais
Python-based tools for document analysis and OCR

ocropy OCRopus is a collection of document analysis programs, not a turn-key OCR system. In order to apply it to your documents, you may need to do so

OCRopus 3.2k Jan 04, 2023
PSD (Photoshop, Krita, Gimp...) -> Godot.

limage v0.2.2 Features Getting Started Tags Settings Todo Customizer Changes Solutions WARNING: Requires Python to be installed PSD (Photoshop, Krita,

21 Nov 10, 2022
A utility for quickly cropping large collections of images.

Crop Tool A utility for quickly cropping large collections of images. Inspired by Derrick Schultz's dataset-tools. Setup It's suggested that you use A

dusk (they/them) 6 Nov 14, 2021
Pure Python bindings for the pure C++11/OpenCL Qrack quantum computer simulator library

pyqrack Pure Python bindings for the pure C++11/OpenCL Qrack quantum computer simulator library (PyQrack is just pure Qrack.) IMPORTANT: You must buil

vm6502q 6 Jul 21, 2022
Generate meme GIFs in which an image you choose can be viewed by the user only after they wait a whole hour.

Generate meme GIFs in which an image you choose can be viewed by the user only after they wait a whole hour.

Feliks Maak 1 Jan 31, 2022
This Github Action automatically creates a GIF from a given web page to display on your project README

This Github Action automatically creates a GIF from a given web page to display on your project README

Pablo Lecolinet 28 Dec 15, 2022
Paper backup of files using QR codes

Generate paper backups for Linux. Currently command-linux Linux only. Takes any file, and outputs a "paper backup": a printable black-and-white pdf fu

Zachary Vance 27 Dec 28, 2022
starfish is a Python library for processing images of image-based spatial transcriptomics.

starfish: scalable pipelines for image-based transcriptomics starfish is a Python library for processing images of image-based spatial transcriptomics

199 Dec 08, 2022
PyLibTiff - a wrapper to the libtiff library to Python using ctypes

PyLibTiff is a package that provides: a wrapper to the libtiff library to Python using ctypes. a pure Python module for reading and writing TIFF and L

Pearu Peterson 105 Dec 21, 2022
Python Image Morpher (PIM) is a program that can take two images and blend them to whatever extent or precision that you like

Python Image Morpher (PIM) is a program that can take two images and blend them to whatever extent or precision that you like! It is designed to emulate some of Python's OpenCV image processing from

David Dowd 108 Dec 19, 2022
BeeRef — A Simple Reference Image Viewer

BeeRef — A Simple Reference Image Viewer BeeRef lets you quickly arrange your reference images and view them while you create. Its minimal interface i

Rebecca 245 Dec 25, 2022
Generate waves art for an image

waves-art Generate waves art for an image. Requirements: OpenCV Numpy Example Usage python waves_art.py --image_path tests/test1.jpg --patch_size 15 T

Hamza Rawal 18 Apr 04, 2022
Photini - A free, easy to use, digital photograph metadata (Exif, IPTC, XMP) editing application for Linux, Windows and MacOS.

A free, easy to use, digital photograph metadata (Exif, IPTC, XMP) editing application for Linux, Windows and MacOS. "Metadata" is said to mea

Jim Easterbrook 120 Dec 20, 2022
A Python package implementing various CFA (Colour Filter Array) demosaicing algorithms and related utilities.

Colour - Demosaicing A Python package implementing various CFA (Colour Filter Array) demosaicing algorithms and related utilities. It is open source a

colour-science 218 Dec 04, 2022
PIX is an image processing library in JAX, for JAX.

PIX PIX is an image processing library in JAX, for JAX. Overview JAX is a library resulting from the union of Autograd and XLA for high-performance ma

DeepMind 294 Jan 08, 2023
Small wrapper around 3dmol.js and html2canvas for creating self-contained HTML files that display a 3D molecular representation.

Description Small wrapper around 3dmol.js and html2canvas for creating self-contained HTML files that display a 3D molecular representation. Double cl

David Meijer 1 Dec 02, 2021
Multi-view 3D reconstruction using neural rendering. Unofficial implementation of UNISURF, VolSDF, NeuS and more.

Multi-view 3D reconstruction using neural rendering. Unofficial implementation of UNISURF, VolSDF, NeuS and more.

Jianfei Guo 683 Jan 04, 2023
A python based library to help you create unique generative images based on Rarity for your next NFT Project

Generative-NFT Generate Unique Images based on Rarity A python based library to help you create unique generative images based on Rarity for your next

Kartikay Bhutani 8 Sep 21, 2022
display: a browser-based graphics server

display: a browser-based graphics server Installation Quick Start Usage Development A very lightweight display server for Torch. Best used as a remote

Szymon Jakubczak 205 Oct 17, 2022
Craft PNG files that appear completely different in Apple software

Ambiguous PNG Packer Craft PNG files that appear completely different in Apple software

David Buchanan 1k Dec 29, 2022