22 Commits
v0.3.1 ... dev

Author SHA1 Message Date
25eafaab12 workflow_dispatch 2025-03-29 18:42:37 +04:00
04a2f5b8f2 Update action to use macos-11 2025-03-29 18:39:21 +04:00
41ab98ff76 Merge pull request #3 from Bradbev/fs_support
Add support for fs.FS file system support
2025-03-29 18:38:07 +04:00
bf172f60cd Merge branch 'dev' into fs_support 2025-03-29 17:13:47 +13:00
6b65d26014 Update README.md 2024-12-16 17:54:55 +04:00
4e56ab3c9b Merge pull request #4 from BhaumikTalwar/fix-linux-linking
Fix: Linux Linking Error
2024-12-16 17:53:47 +04:00
38aa4923bc fix:Linux-Linking-Error README UPDATE 2024-12-16 13:17:24 +05:30
c8ec2b30b5 fix: Linux Linking Error 2024-12-15 04:10:21 +05:30
41995b60bb Update README.md 2024-12-12 11:52:04 +04:00
e6f5dca6da Update README.md 2024-12-12 11:51:33 +04:00
f50b60e8eb Add support for fs.FS file system support 2024-12-12 20:23:41 +13:00
0bc81ac5ba Fix bug in parseNodes 2022-10-01 06:35:29 +04:00
6bb760fc0a Protect against aiString being empty 2022-10-01 06:20:53 +04:00
362558c877 Use darwin_amd64 built by mac 10.15 2022-01-27 05:22:58 +04:00
7e82370f34 Edit text 2022-01-27 04:58:35 +04:00
58e13d1c5a Add badge 2022-01-27 04:58:03 +04:00
bfa7357ea2 Add github action to run on intel mac 2022-01-27 04:55:58 +04:00
dd346de9de Add intel mac assimp dylib 2022-01-27 04:24:08 +04:00
babf9c3926 Fix readme typo 2022-01-27 03:31:03 +04:00
0fdd5d479c Update readme 2022-01-22 08:16:26 +04:00
7efa9c31f4 Remove unneeded libs+add obj.obj test model 2022-01-22 07:33:42 +04:00
02fd276728 Support apple silicon 2022-01-22 07:31:02 +04:00
14 changed files with 341 additions and 42 deletions

21
.github/workflows/run-assimp-go.yml vendored Executable file
View File

@ -0,0 +1,21 @@
name: Build-AssImp
on:
workflow_dispatch:
create:
jobs:
Run-assimp-go-macos:
runs-on: macos-11
steps:
- name: Install golang 1.17
uses: actions/setup-go@v2
with:
go-version: '^1.17'
- name: Clone assimp-go
run: git clone https://github.com/bloeys/assimp-go
- name: Copy dylib
working-directory: assimp-go
run: sudo mkdir -p /usr/local/lib && sudo cp asig/libs/libassimp_darwin_amd64.dylib /usr/local/lib/libassimp.5.dylib
- name: Run assimp-go
working-directory: assimp-go
run: go run .

6
.gitignore vendored
View File

@ -11,8 +11,12 @@
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# Custom
vendor/
.DS_Store
*.obj
!obj.obj
*.fbx
*.glb
!libassimp_darwin_arm64.dylib
!libassimp_darwin_amd64.dylib

View File

@ -1,5 +1,7 @@
# assimp-go
[![Build](https://github.com/bloeys/assimp-go/actions/workflows/run-assimp-go.yml/badge.svg)](https://github.com/bloeys/assimp-go/actions/workflows/run-assimp-go.yml)
A Handcrafted Open Asset Import Library (AssImp) wrapper for Go.
## Features
@ -25,19 +27,53 @@ Unimplemented (yet) AssImp Scene objects:
To run the project you need:
* A 64-bit machine (32-bit machines should be supportable if we get help adding the needed libs)
* A recent version of [Go](https://golang.org/) installed (1.17+)
* A C/C++ compiler installed and in your path
* Windows: [MingW](https://www.mingw-w64.org/downloads/#mingw-builds) or similar
* Mac/Linux: Should be installed by default, but if not try [GCC](https://gcc.gnu.org/) or [Clang](https://releases.llvm.org/download.html)
* Download the appropriate DLL for your version and put it in the root of your Go project
* **Windows**: [MingW](https://www.mingw-w64.org/downloads/#mingw-builds) or similar
* **Mac/Linux**: Should be installed by default, but if not try [GCC](https://gcc.gnu.org/) or [Clang](https://releases.llvm.org/download.html)
Then simply clone and use `go run .`
Now to be able to run assimp-go you will need the AssImp shared libraries (DLLs/DyLibs), which you can
download from the GitHub releases page.
### Installing on Windows
Download the **.dll** of the [release you want](https://github.com/bloeys/assimp-go/releases), and place it in the **root** of your Go project.
### Installing on MacOS
First, download the appropriate **.dylib** for your device (`_amd64` for Intel CPUs and `_arm64` for Apple CPUs).
Next you will need to rename the lib to `libassimp.5.dylib` and move it to `/usr/local/lib` or `/usr/lib`.
You can use this command to do it: `sudo mkdir -p /usr/local/lib && sudo cp libassimp_darwin*.dylib /usr/local/lib/libassimp.5.dylib`
### Installing on Linux
Download the the AssImp package for your distro, or build from source and add it to your path.
> NOTE: Insatall assimp >= 3.1 for bindings to work as expected.
> Though getting the latest version is always recommended.
#### Installing on Ubuntu
You can install the Asset-Importer-Lib via apt:
```
sudo apt-get update
sudo apt-get install libassimp-dev
```
#### Installing on Arch
You can install the Asset-Importer-Lib via pacman
```
sudo pacman -S assimp
```
#### Building From Source
To build the Asset Importer Package from sorce read the [sorce build guide](https://github.com/assimp/assimp/blob/master/Build.md)
### Running assimp-go
Use `go run .` to run the simple example in `main.go` ;)
> Note: that it might take a while to run the first time because of downloading/compiling dependencies.
`assimp-go` dynamically links (e.g. through a DLL) AssImp using platform dependent libraries, which are made available with the GitHub releases.
Currently only `Windows` libraries are available, but more should be easy to add by compiling AssImp on the wanted platform. (Make a PR if you can help us get those binaries!)
### Getting Started
```Go
@ -85,14 +121,13 @@ While `asig` functions should NOT be called on a Scene (or its objects) after th
## Developing assimp-go
We link against assimp libraries that are built for each platform and the `*.a` files are added to the `asig/libs` package.
Depending on the platform we select one of them and link against it when doing `go build`.
We link against assimp libraries that are built for each platform and the `.a`/`.dylib` files are added to the `asig/libs` package.
At build time, the `#cgo` directive choose the appropriate libs and links against them.
The general steps are:
* Copy assimp includes into `asig/assimp`
* Copy `zlib.h`, `zconf.h` and `irrXML.h` into `asig/zlib` and `asig/irrxml` respectively.
* Copy static libraries and DLL import libraries into `asig/libs`
* Copy libraries and DLL import libraries into `asig/libs`
> Note: When dealing with libraries the compiler will probably (e.g. MinGW does this) ignore `lib` prefixes and `.a`/`.lib` suffixes.
So if your lib name is `libassimp.a` you need to pass it to CGO as `-l assimp`, otherwise you will get an error about library not found.
@ -111,3 +146,9 @@ Now assuming you are using MinGW on windows:
* Run `cmake --build . --parallel 6`
* Copy the generated `*.lib` (or `*.a`) files from the `lib` folder and into `asig/libs`, and copy the generated dll from AssImp `bin` folder into the root of `assimp-go`.
* Copy the generated `libzlibstatic.a` file from `contrib/zlib` and into the `asig/libs` folder.
**MacOS**:
* Clone wanted release of assimp and run `cmake CMakeLists.txt -D ASSIMP_BUILD_ZLIB=ON -D ASSIMP_BUILD_ASSIMP_TOOLS=OFF` in the root folder
* Run `cmake --build . --parallel 6`
* Copy the generated `*.dylib` files from the `bin` folder and into both `asig/libs` and `/usr/local/lib`

View File

@ -1,16 +1,24 @@
package asig
/*
//Note: We don't link directly to libIrrXML and libzlib libraries in `./libs`, but they are required by assimp. Removing them will error on compilation.
#cgo CFLAGS: -I .
#cgo LDFLAGS: -L ./libs -l assimp_windows_amd64
#cgo linux CFLAGS:
#cgo windows,amd64 CFLAGS: -I .
#cgo darwin,amd64 CFLAGS: -I .
#cgo darwin,arm64 CFLAGS: -I .
#include <wrap.cxx>
#include <stdlib.h> //Needed for C.free
#cgo linux LDFLAGS: -lassimp
#cgo windows,amd64 LDFLAGS: -L libs -l assimp_windows_amd64
#cgo darwin,amd64 LDFLAGS: -L libs -l assimp_darwin_amd64
#cgo darwin,arm64 LDFLAGS: -Wl,-rpath,/usr/local/lib
#include "wrap.h"
*/
import "C"
import (
"errors"
"io"
"io/fs"
"runtime"
"unsafe"
"github.com/bloeys/gglm/gglm"
@ -156,6 +164,121 @@ func ImportFile(file string, postProcessFlags PostProcess) (s *Scene, release fu
return s, func() { s.releaseCResources() }, nil
}
//export go_aiFileOpenProc
func go_aiFileOpenProc(io *C.struct_aiFileIO, name *C.char, flags *C.char) *C.struct_aiFile {
fsWrapper := (*fsWrapper)(unsafe.Pointer(io.UserData))
file, err := fsWrapper.fsys.Open(C.GoString(name))
if err != nil {
return nil
}
fsWrapper.Pin(&file)
ret := &C.struct_aiFile{
ReadProc: (C.aiFileReadProc)(C.cgo_aiFileReadProc),
WriteProc: (C.aiFileWriteProc)(C.cgo_aiFileWriteProc),
TellProc: (C.aiFileTellProc)(C.cgo_aiFileTellProc),
FileSizeProc: (C.aiFileTellProc)(C.cgo_aiFileFileSizeProc),
SeekProc: (C.aiFileSeek)(C.cgo_aiFileSeekProc),
FlushProc: (C.aiFileFlushProc)(C.cgo_aiFileFlushProc),
UserData: (*C.char)(unsafe.Pointer(&file)),
}
fsWrapper.Pin(ret)
return ret
}
//export go_aiFileCloseProc
func go_aiFileCloseProc(io *C.struct_aiFileIO, file *C.struct_aiFile) {
f := *(*fs.File)(unsafe.Pointer(file.UserData))
f.Close()
}
//export go_aiFileReadProc
func go_aiFileReadProc(file *C.struct_aiFile, buffer *C.char, size C.size_t, count C.size_t) C.size_t {
f := *(*fs.File)(unsafe.Pointer(file.UserData))
slice := unsafe.Slice((*byte)(unsafe.Pointer(buffer)), size*count)
n, err := f.Read(slice)
if err != nil {
return (C.size_t)(0)
}
return (C.size_t)(n)
}
//export go_aiFileWriteProc
func go_aiFileWriteProc(file *C.struct_aiFile, buffer *C.char, size C.size_t, count C.size_t) C.size_t {
panic("aiFileWrite not supported")
}
//export go_aiFileFileSizeProc
func go_aiFileFileSizeProc(file *C.struct_aiFile) C.size_t {
f := *(*fs.File)(unsafe.Pointer(file.UserData))
info, err := f.Stat()
if err != nil {
return 0
}
return (C.size_t)(info.Size())
}
//export go_aiFileFlushProc
func go_aiFileFlushProc(file *C.struct_aiFile) {
panic("aiFileFlush not supported")
}
//export go_aiFileTellProc
func go_aiFileTellProc(file *C.struct_aiFile) C.size_t {
panic("aiFileTell not supported")
}
//export go_aiFileSeekProc
func go_aiFileSeekProc(file *C.struct_aiFile, offset C.size_t, origin C.enum_aiOrigin) C.enum_aiReturn {
f := *(*fs.File)(unsafe.Pointer(file.UserData))
if s, ok := f.(io.Seeker); ok {
_, err := s.Seek(int64(offset), int(origin))
if err == nil {
return aiReturnSuccess
}
}
return aiReturnFailure
}
type fsWrapper struct {
pinnedMemory runtime.Pinner
fsys fs.FS
}
func (fws *fsWrapper) Pin(pointer interface{}) {
fws.pinnedMemory.Pin(pointer)
}
func ImportFileEx(file string, postProcessFlags PostProcess, fsys fs.FS) (s *Scene, release func(), err error) {
cstr := C.CString(file)
defer C.free(unsafe.Pointer(cstr))
wrapper := &fsWrapper{
pinnedMemory: runtime.Pinner{},
fsys: fsys,
}
wrapper.Pin(wrapper)
defer wrapper.pinnedMemory.Unpin()
cio := &C.struct_aiFileIO{
OpenProc: (C.aiFileOpenProc)(C.cgo_aiFileOpenProc),
CloseProc: (C.aiFileCloseProc)(C.cgo_aiFileCloseProc),
UserData: (*C.char)(unsafe.Pointer(wrapper)),
}
wrapper.Pin(cio)
cs := C.aiImportFileEx(cstr, C.uint(postProcessFlags), cio)
if cs == nil {
return nil, func() {}, getAiErr()
}
s = parseScene(cs)
return s, func() { s.releaseCResources() }, nil
}
func getAiErr() error {
return errors.New("asig error: " + C.GoString(C.aiGetErrorString()))
}
@ -213,7 +336,7 @@ func parseNodes(cNodesIn **C.struct_aiNode, parent *Node, parentChildrenCount ui
}
//Parse node's children
nodes[i].Children = parseNodes(n.mChildren, nodes[i], parentChildrenCount)
nodes[i].Children = parseNodes(n.mChildren, nodes[i], uint(n.mNumChildren))
}
return nodes
@ -517,6 +640,10 @@ func parseVertexWeights(cWeights *C.struct_aiVertexWeight, count uint) []VertexW
}
func parseAiString(aiString C.struct_aiString) string {
if aiString.length == 0 {
return ""
}
return C.GoStringN(&aiString.data[0], C.int(aiString.length))
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,27 +1,17 @@
package asig
/*
#cgo CFLAGS: -I .
#cgo LDFLAGS: -L ./libs -l assimp_windows_amd64 -l IrrXML_windows_amd64 -l zlib_windows_amd64
#cgo linux CFLAGS:
#cgo windows,amd64 CFLAGS: -I .
#cgo darwin,amd64 CFLAGS: -I .
#cgo darwin,arm64 CFLAGS: -I .
#include <stdlib.h> //Needed for C.free
#cgo linux LDFLAGS: -lassimp
#cgo windows,amd64 LDFLAGS: -L libs -l assimp_windows_amd64
#cgo darwin,amd64 LDFLAGS: -L libs -l assimp_darwin_amd64
#cgo darwin,arm64 LDFLAGS: -L libs -l assimp_darwin_arm64
#include <assimp/scene.h>
//Functions
unsigned int aiGetMaterialTextureCount(const struct aiMaterial* pMat, enum aiTextureType type);
enum aiReturn aiGetMaterialTexture(
const struct aiMaterial* mat,
enum aiTextureType type,
unsigned int index,
struct aiString* path,
enum aiTextureMapping* mapping,
unsigned int* uvindex,
ai_real* blend,
enum aiTextureOp* op,
enum aiTextureMapMode* mapmode,
unsigned int* flags);
#include "wrap.h"
*/
import "C"
import (

50
asig/wrap.c Executable file
View File

@ -0,0 +1,50 @@
#include "wrap.h"
#include <stdio.h>
extern C_STRUCT aiFile *go_aiFileOpenProc(C_STRUCT aiFileIO *io, char *name, char *flags);
C_STRUCT aiFile *cgo_aiFileOpenProc(C_STRUCT aiFileIO *io, const char *name, const char *flags)
{
return go_aiFileOpenProc(io, (char *)name, (char *)flags);
}
extern void go_aiFileCloseProc(C_STRUCT aiFileIO *io, C_STRUCT aiFile *file);
void cgo_aiFileCloseProc(C_STRUCT aiFileIO *io, C_STRUCT aiFile *file)
{
go_aiFileCloseProc(io, file);
}
extern size_t go_aiFileWriteProc(C_STRUCT aiFile *file, const char *buffer, size_t size, size_t count);
size_t cgo_aiFileWriteProc(C_STRUCT aiFile *file, const char *buffer, size_t size, size_t count)
{
return go_aiFileWriteProc(file, (char *)buffer, size, count);
}
extern size_t go_aiFileReadProc(C_STRUCT aiFile *, char *, size_t, size_t);
size_t cgo_aiFileReadProc(C_STRUCT aiFile *file, char *buffer, size_t size, size_t count)
{
return go_aiFileReadProc(file, buffer, size, count);
}
extern size_t go_aiFileTellProc(C_STRUCT aiFile *file);
size_t cgo_aiFileTellProc(C_STRUCT aiFile *file)
{
return go_aiFileTellProc(file);
}
extern size_t go_aiFileFileSizeProc(C_STRUCT aiFile *file);
size_t cgo_aiFileFileSizeProc(C_STRUCT aiFile *file)
{
return go_aiFileFileSizeProc(file);
}
extern void go_aiFileFlushProc(C_STRUCT aiFile *file);
void cgo_aiFileFlushProc(C_STRUCT aiFile *file)
{
go_aiFileFlushProc(file);
}
extern C_ENUM aiReturn go_aiFileSeekProc(C_STRUCT aiFile *file, size_t offset, C_ENUM aiOrigin origin);
C_ENUM aiReturn cgo_aiFileSeekProc(C_STRUCT aiFile *file, size_t offset, C_ENUM aiOrigin origin)
{
return go_aiFileSeekProc(file, offset, origin);
}

View File

@ -1,3 +0,0 @@
#include <assimp/cimport.h> // Plain-C interface
#include <assimp/scene.h> // Output data structure
#include <assimp/postprocess.h>

20
asig/wrap.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef WRAP_H
#define WRAP_H
#include <assimp/cimport.h> // Plain-C interface
#include <assimp/cfileio.h> // Plain-C interface
#include <assimp/scene.h> // Output data structure
#include <assimp/postprocess.h>
#include <stdlib.h>
C_STRUCT aiFile *cgo_aiFileOpenProc(C_STRUCT aiFileIO *io, const char *name, const char *flags);
void cgo_aiFileCloseProc(C_STRUCT aiFileIO *io, C_STRUCT aiFile *file);
size_t cgo_aiFileWriteProc(C_STRUCT aiFile *, const char *, size_t, size_t);
size_t cgo_aiFileReadProc(C_STRUCT aiFile *, char *, size_t, size_t);
size_t cgo_aiFileTellProc(C_STRUCT aiFile *);
size_t cgo_aiFileFileSizeProc(C_STRUCT aiFile *);
void cgo_aiFileFlushProc(C_STRUCT aiFile *);
C_ENUM aiReturn cgo_aiFileSeekProc(C_STRUCT aiFile *, size_t, C_ENUM aiOrigin);
#endif

View File

@ -4,13 +4,16 @@ import (
"bytes"
"fmt"
"image/png"
"os"
"github.com/bloeys/assimp-go/asig"
)
func main() {
scene, release, err := asig.ImportFile("obj.fbx", asig.PostProcessTriangulate|asig.PostProcessJoinIdenticalVertices)
//scene, release, err := asig.ImportFile("obj.obj", asig.PostProcessTriangulate|asig.PostProcessJoinIdenticalVertices)
fsys := os.DirFS(".")
scene, release, err := asig.ImportFileEx("obj.obj", asig.PostProcessTriangulate|asig.PostProcessJoinIdenticalVertices, fsys)
if err != nil {
panic(err)
}

46
obj.obj Executable file
View File

@ -0,0 +1,46 @@
# Blender v2.92.0 OBJ File: ''
# www.blender.org
mtllib obj.mtl
o Cube
v 2.275618 1.000000 0.349413
v 3.520138 -1.000000 0.102233
v 2.275618 1.000000 0.752820
v 3.520138 -1.000000 1.000000
v 0.244520 1.000000 0.349413
v -1.000000 -1.000000 0.102233
v 0.244520 1.000000 0.752820
v -1.000000 -1.000000 1.000000
vt 0.806168 0.568832
vt 0.693832 0.681168
vt 0.693832 0.568832
vt 0.375000 1.000000
vt 0.375000 0.750000
vt 0.375000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.250000
vt 0.375000 0.500000
vt 0.125000 0.750000
vt 0.125000 0.500000
vt 0.806168 0.681168
vt 0.625000 0.931168
vt 0.625000 0.068832
vn 0.0000 1.0000 0.0000
vn 0.0000 0.1227 0.9924
vn -0.8490 0.5283 0.0000
vn 0.0000 -1.0000 0.0000
vn 0.8490 0.5283 0.0000
vn 0.0000 0.1227 -0.9924
usemtl Material
s off
f 5/1/1 3/2/1 1/3/1
f 3/2/2 8/4/2 4/5/2
f 8/6/3 5/7/3 6/8/3
f 2/9/4 8/10/4 6/11/4
f 1/3/5 4/5/5 2/9/5
f 5/7/6 2/9/6 6/8/6
f 5/1/1 7/12/1 3/2/1
f 3/2/2 7/13/2 8/4/2
f 8/6/3 7/14/3 5/7/3
f 2/9/4 4/5/4 8/10/4
f 1/3/5 3/2/5 4/5/5
f 5/7/6 1/3/6 2/9/6