Skip to content

Commit

Permalink
Merge pull request #82 from atteneder/feature/skins
Browse files Browse the repository at this point in the history
Feature/skins
  • Loading branch information
atteneder authored Sep 5, 2020
2 parents 6768ca0 + 351d1b0 commit a83c230
Show file tree
Hide file tree
Showing 32 changed files with 2,331 additions and 856 deletions.
9 changes: 9 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [2.0.0] - 2020-09-05
### Added
- Support for skinning
- Instantiation can now be customized via injection
### Changed
- Complete refactor to allow more optimization by using Unity's new Mesh API (introduced in 2019.1)
- Required Unity version was raised to 2019.1 or newer

## [1.2.0] - 2020-09-05
### Added
- Material generator (IMaterialGenerator) is now properly exposed and can be injected ( thanks [@p-skakun](https://github.com/p-skakun) for #80 )
Expand Down Expand Up @@ -40,6 +48,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- Support for Draco mesh compression is now optional (install DracoUnity package to enable it)
- Support for KTX2/Basis Universal textures is now optional (install KtxUnity package to enable it)
- Faster mesh creation due to using the advanced Mesh API on Unity 2019.3 and newer.

## [0.11.0] - 2020-03-07
### Added
Expand Down
6 changes: 3 additions & 3 deletions Documentation~/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,14 @@
- [x] Implicit (no) indices
- [x] Per primitive material
- [ ] Multiple texture coordinates sets ([issue](../issues/34))
- [ ] Joints
- [ ] Weights
- [x] Joints (up to 4 per vertex)
- [x] Weights (up to 4 per vertex)
- [x] Texture sampler
- [x] Filtering (see ([limitations](#knownissues)))
- [x] Wrap modes
- [ ] Morph targets ([issue](../issues/8))
- [ ] Sparse accessors
- [ ] Skinning ([issue](../issues/13))
- [x] [Skins](https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#skins) (sponsored by [Embibe](https://www.embibe.com))
- [ ] Animation

<sup>1</sup>: Untested due to lack of demo files.
Expand Down
36 changes: 28 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ Try the [WebGL Demo](https://atteneder.github.io/glTFastWebDemo) and check out t

glTFast supports runtime loading of all sorts of glTF 2.0 files. It runs on WebGL, iOS, Android, Windows, macOS and Linux and supports the majority of glTF's features and official extensions.

Most notable restrictions
It is planned to become feature complete. Most notable missing features are:

- Just for static scenes. No animations, skinning/rigs or morph targets supported.
- No animations
- No morph targets
- Unity's built-in render pipeline only (URP and HDRP are planned)

See the [list of features/extensions](./Documentation~/features.md) for details and limitations.
Expand Down Expand Up @@ -85,11 +86,12 @@ The simplest way to load a glTF file is to add a `GltfAsset` component to a Game

### Via Script

Loading via script can have additional benefits
Loading via script is slightly more overhead but gives you more customization options

- Add custom listeners to loading events
- Load glTF once and instantiate it many times
- Access data of glTF scene (for example get material)
- React to loading events by [adding event listeners](#custom-loading-event-listeners)
- Customize [instantiation](#Instantiation)
- Load glTF once and instantiate it many times (see example [below](#custom-loading-event-listeners))
- Access data of glTF scene (for example get material; see example [below](#custom-loading-event-listeners))
- Tweak and optimize loading performance

#### Simple example
Expand Down Expand Up @@ -128,7 +130,21 @@ void YourCallbackMethod(GltfAssetBase gltfAsset, bool success) {

#### Instantiation

This section is under construction.
Creating actual GameObjects (or Entities) from the imported data (Meshes, Materials) is called instantiation.

You can customize it by providing an implementation of `IInstantiator` ( see [source](./Runtime/Scripts/IInstatiator.cs) and the reference implementation [`GameObjectInstantiator`](./Runtime/Scripts/GameObjectInstantiator.cs) for details).

Inject your custom instantiation like so

```csharp
public class YourCustomInstantiator : GLTFast.IInstantiator {
// Your code here
}

// Within the `onLoadComplete` event listener, use it like this
gltfAsset.Instantiate( new YourCustomInstantiator() );
```

#### Tune loading performance

Expand Down Expand Up @@ -197,7 +213,7 @@ If you use Unity older than 2019.1, you additionally have to add `KTX_UNITY` to
Besides speed, the focus at the moment is on users that:

- control the content (are able to create compatible glTFs)
- use it for static content (no animation, skinning or morphing)
- use it for static content (no animation or morphing)

I try to keep an up-to-date, detailed roadmap in the [milestones](https://github.com/atteneder/glTFast/milestones)
section.
Expand Down Expand Up @@ -232,6 +248,10 @@ Also, you can show your appreciation and...

[![Buy me a coffee](https://az743702.vo.msecnd.net/cdn/kofi1.png?v=0)](https://ko-fi.com/C0C3BW7G)

## Supporters

Thanks to [Embibe](https://www.embibe.com) for sponsoring the development of skin support! ❤️

## License

Copyright (c) 2019 Andreas Atteneder, All Rights Reserved.
Expand Down
16 changes: 15 additions & 1 deletion Runtime/Scripts/AccessorData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
//

using System.Runtime.InteropServices;
using UnityEngine;
using Unity.Collections;

namespace GLTFast
{
Expand All @@ -26,11 +28,13 @@ enum AccessorUsage {
Normal,
Tangent,
UV,
Color
Color,
InverseBindMatrix
}

abstract class AccessorDataBase {
public abstract void Unpin();
public abstract void Dispose();
}

class AccessorData<T> : AccessorDataBase {
Expand All @@ -40,5 +44,15 @@ class AccessorData<T> : AccessorDataBase {
public override void Unpin() {
gcHandle.Free();
}
public override void Dispose() {}
}

class AccessorNativeData<T> : AccessorDataBase where T: struct
{
public NativeArray<T> data;
public override void Unpin() {}
public override void Dispose() {
data.Dispose();
}
}
}
111 changes: 111 additions & 0 deletions Runtime/Scripts/GameObjectInstantiator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// Copyright 2020 Andreas Atteneder
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

using System.Collections.Generic;
using UnityEngine;

namespace GLTFast {
public class GameObjectInstantiator : IInstantiator {

Transform parent;

GameObject[] nodes;

public GameObjectInstantiator(Transform parent) {
this.parent = parent;
}

public void Init(int nodeCount) {
nodes = new GameObject[nodeCount];
}

public void CreateNode(
uint nodeIndex,
Vector3 position,
Quaternion rotation,
Vector3 scale
) {
var go = new GameObject();
go.transform.localScale = scale;
go.transform.localPosition = position;
go.transform.localRotation = rotation;
nodes[nodeIndex] = go;
}

public void SetParent(uint nodeIndex, uint parentIndex) {
if(nodes[nodeIndex]==null || nodes[parentIndex]==null ) {
Debug.LogError("Invalid hierarchy");
return;
}
nodes[nodeIndex].transform.SetParent(nodes[parentIndex].transform,false);
}

public void SetNodeName(uint nodeIndex, string name) {
nodes[nodeIndex].name = name ?? "Node";
}

public void AddPrimitive(
uint nodeIndex,
string meshName,
UnityEngine.Mesh mesh,
UnityEngine.Material[] materials,
int[] joints = null,
bool first = true
) {

GameObject meshGo;
if(first) {
// Use Node GameObject for first Primitive
meshGo = nodes[nodeIndex];
} else {
meshGo = new GameObject( meshName ?? "Primitive" );
meshGo.transform.SetParent(nodes[nodeIndex].transform,false);
}

Renderer renderer;

if(joints==null) {
var mf = meshGo.AddComponent<MeshFilter>();
mf.mesh = mesh;
var mr = meshGo.AddComponent<MeshRenderer>();
renderer = mr;
} else {
var smr = meshGo.AddComponent<SkinnedMeshRenderer>();
var bones = new Transform[joints.Length];
for (int j = 0; j < bones.Length; j++)
{
var jointIndex = joints[j];
bones[j] = nodes[jointIndex].transform;
}
smr.bones = bones;
smr.sharedMesh = mesh;
renderer = smr;
}

renderer.sharedMaterials = materials;
}

public void AddScene(string name, uint[] nodeIndices) {
var go = new GameObject(name ?? "Scene");
go.transform.SetParent( parent, false);

foreach(var nodeIndex in nodeIndices) {
if (nodes[nodeIndex] != null) {
nodes[nodeIndex].transform.SetParent( go.transform, false );
}
}
}
}
}
11 changes: 11 additions & 0 deletions Runtime/Scripts/GameObjectInstantiator.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit a83c230

Please sign in to comment.