Working on mats&textures+better release handling+readme

This commit is contained in:
bloeys
2021-11-19 17:29:01 +04:00
parent 32c5def787
commit 3b31e8d677
4 changed files with 118 additions and 9 deletions

View File

@ -1,5 +1,14 @@
# assimp-go # assimp-go
## Using assimp-go
The `release()` function is used to free underlying C resources and should be called after all processing that requires C code is done.
`release()` Will not affect the returned Go structs like `Scene` or `Mesh`. Returned Go data will remain valid.
`asig.X` functions call into C and therefore should not be used on released objects. Calling any `asig.X` function after `release()` is **undefined**.
While `asig` functions should NOT be called on a Scene (or its objects) after they have been released, methods on structs (e.g. `myScene.XYZ`, `myMesh.ABCD()`) are **safe** even after release.
## Developing assimp-go ## Developing assimp-go
We link against static assimp libraries that are built for each platform and added to the `asig/libs` package. We link against static assimp libraries that are built for each platform and added to the `asig/libs` package.
@ -21,11 +30,11 @@ For platform specific steps:
**Windows**: **Windows**:
> Note: You must compile with the same C/C++ compiler you use with Go (e.g. if you use MinGW with Go, then compile assimp with MinGW by sepcifying the correct `-G` option) > Note: You must compile with the same C/C++ compiler you use with Go (e.g. if you use MinGW with Go, then compile assimp with MinGW by sepcifying the correct `-G` option)
---
> Note: If you get compilation errors with things like `File too big` or `can't write 166 bytes to section` then cmake isn't detecting you are using MinGW, so add this flag `-D CMAKE_COMPILER_IS_MINGW=TRUE` > Note: If you get compilation errors with things like `File too big` or `can't write 166 bytes to section` then cmake isn't detecting you are using MinGW, so add this flag `-D CMAKE_COMPILER_IS_MINGW=TRUE`
Now assuming you are using MinGW on windows: Now assuming you are using MinGW on windows:
- Clone wanted release of assimp and run `cmake CMakeLists.txt -D BUILD_SHARED_LIBS=OFF -D ASSIMP_BUILD_ZLIB=ON -D ASSIMP_BUILD_ASSIMP_TOOLS=OFF -D ASSIMP_BUILD_TESTS=OFF -G "MinGW Makefiles"` in the root folder - Clone wanted release of assimp and run `cmake CMakeLists.txt -D BUILD_SHARED_LIBS=OFF -D ASSIMP_BUILD_ZLIB=ON -D ASSIMP_BUILD_ASSIMP_TOOLS=OFF -D ASSIMP_BUILD_TESTS=OFF -G "MinGW Makefiles"` in the root folder
- Run `cmake --build . --parallel 6` - Run `cmake --build . --parallel 6`
- Copy the generated `*.lib` file into `asig/lib` - Copy the generated `*.lib` (or `*.a`) files into `asig/lib`

View File

@ -28,7 +28,59 @@ type Node struct {
type Animation struct { type Animation struct {
} }
type Texel struct {
R, G, B, A byte
}
type Texture struct { type Texture struct {
/** Width of the texture, in pixels
*
* If mHeight is zero the texture is compressed in a format
* like JPEG. In this case mWidth specifies the size of the
* memory area pcData is pointing to, in bytes.
*/
Width uint
/** Height of the texture, in pixels
*
* If this value is zero, pcData points to an compressed texture
* in any format (e.g. JPEG).
*/
Height uint
/** A hint from the loader to make it easier for applications
* to determine the type of embedded textures.
*
* If mHeight != 0 this member is show how data is packed. Hint will consist of
* two parts: channel order and channel bitness (count of the bits for every
* color channel). For simple parsing by the viewer it's better to not omit
* absent color channel and just use 0 for bitness. For example:
* 1. Image contain RGBA and 8 bit per channel, achFormatHint == "rgba8888";
* 2. Image contain ARGB and 8 bit per channel, achFormatHint == "argb8888";
* 3. Image contain RGB and 5 bit for R and B channels and 6 bit for G channel, achFormatHint == "rgba5650";
* 4. One color image with B channel and 1 bit for it, achFormatHint == "rgba0010";
* If mHeight == 0 then achFormatHint is set set to '\\0\\0\\0\\0' if the loader has no additional
* information about the texture file format used OR the
* file extension of the format without a trailing dot. If there
* are multiple file extensions for a format, the shortest
* extension is chosen (JPEG maps to 'jpg', not to 'jpeg').
* E.g. 'dds\\0', 'pcx\\0', 'jpg\\0'. All characters are lower-case.
* The fourth character will always be '\\0'.
*/
FormatHint string
/** Data of the texture.
*
* Points to an array of mWidth * mHeight aiTexel's.
* The format of the texture data is always ARGB8888 to
* make the implementation for user of the library as easy
* as possible. If mHeight = 0 this is a pointer to a memory
* buffer of size mWidth containing the compressed texture
* data. Good luck, have fun!
*/
Texels []Texel
Filename string
} }
type Light struct { type Light struct {
@ -41,7 +93,8 @@ type Metadata struct {
} }
type Scene struct { type Scene struct {
Flags SceneFlag cScene *C.struct_aiScene
Flags SceneFlag
RootNode *Node RootNode *Node
Meshes []*Mesh Meshes []*Mesh
@ -52,27 +105,39 @@ type Scene struct {
Cameras []*Camera Cameras []*Camera
} }
func ImportFile(file string, postProcessFlags PostProcess) (*Scene, error) { func (s *Scene) releaseCResources() {
C.aiReleaseImport(s.cScene)
}
//
// Assimp API
//
func ImportFile(file string, postProcessFlags PostProcess) (s *Scene, release func(), err error) {
cstr := C.CString(file) cstr := C.CString(file)
defer C.free(unsafe.Pointer(cstr)) defer C.free(unsafe.Pointer(cstr))
cs := C.aiImportFile(cstr, C.uint(postProcessFlags)) cs := C.aiImportFile(cstr, C.uint(postProcessFlags))
if cs == nil { if cs == nil {
return nil, getAiErr() return nil, func() {}, getAiErr()
} }
defer C.aiReleaseImport(cs)
return parseScene(cs), nil s = parseScene(cs)
return s, func() { s.releaseCResources() }, nil
} }
func getAiErr() error { func getAiErr() error {
return errors.New("asig error: " + C.GoString(C.aiGetErrorString())) return errors.New("asig error: " + C.GoString(C.aiGetErrorString()))
} }
//
// Parsers
//
func parseScene(cs *C.struct_aiScene) *Scene { func parseScene(cs *C.struct_aiScene) *Scene {
s := &Scene{} s := &Scene{cScene: cs}
s.Flags = SceneFlag(cs.mFlags) s.Flags = SceneFlag(cs.mFlags)
s.Meshes = parseMeshes(cs.mMeshes, uint(cs.mNumMeshes)) s.Meshes = parseMeshes(cs.mMeshes, uint(cs.mNumMeshes))
s.Materials = parseMaterials(cs.mMaterials, uint(cs.mNumMaterials)) s.Materials = parseMaterials(cs.mMaterials, uint(cs.mNumMaterials))
@ -350,6 +415,7 @@ func parseMaterials(cMatsIn **C.struct_aiMaterial, count uint) []*Material {
for i := 0; i < int(count); i++ { for i := 0; i < int(count); i++ {
mats[i] = &Material{ mats[i] = &Material{
cMat: cMats[i],
Properties: parseMatProperties(cMats[i].mProperties, uint(cMats[i].mNumProperties)), Properties: parseMatProperties(cMats[i].mProperties, uint(cMats[i].mNumProperties)),
AllocatedStorage: uint(cMats[i].mNumAllocated), AllocatedStorage: uint(cMats[i].mNumAllocated),
} }

View File

@ -1,6 +1,32 @@
package asig package asig
/*
#cgo CFLAGS: -I .
#cgo LDFLAGS: -L ./libs -l assimp_windows_amd64 -l IrrXML_windows_amd64 -l zlib_windows_amd64
#include <stdlib.h> //Needed for C.free
#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);
*/
import "C"
type Material struct { type Material struct {
cMat *C.struct_aiMaterial
/** List of all material properties loaded. */ /** List of all material properties loaded. */
Properties []*MaterialProperty Properties []*MaterialProperty
@ -38,3 +64,7 @@ type MaterialProperty struct {
*/ */
Data []byte Data []byte
} }
func GetMaterialTextureCount(m *Material, texType TextureType) int {
return int(C.aiGetMaterialTextureCount(m.cMat, uint32(texType)))
}

View File

@ -8,7 +8,9 @@ import (
func main() { func main() {
scene, err := asig.ImportFile("tex-cube.fbx", asig.PostProcessTriangulate) scene, release, err := asig.ImportFile("tex-cube.fbx", asig.PostProcessTriangulate)
defer release()
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -28,6 +30,8 @@ func main() {
p := scene.Materials[i].Properties[j] p := scene.Materials[i].Properties[j]
fmt.Printf("Data Type: %v; Len Bytes: %v; Texture Type: %v\n", p.TypeInfo.String(), len(p.Data), p.Semantic.String()) fmt.Printf("Data Type: %v; Len Bytes: %v; Texture Type: %v\n", p.TypeInfo.String(), len(p.Data), p.Semantic.String())
fmt.Println("Texture count:", asig.GetMaterialTextureCount(scene.Materials[i], asig.TextureTypeDiffuse))
} }
} }
} }