3.4. C# Libigl¶
3.4.1. MeshManager.cs¶
-
class
Libigl.MeshManager
: public MonoBehaviour¶ Handles loading EditableMeshes and stores references, notably to the ActiveMesh.
Public Functions
-
LibiglMesh
LoadMesh
(GameObject prefab, bool unloadActiveMesh = true, bool setAsActiveMesh = true, bool performValidityChecks = false)¶ Instantiate a mesh that can be used with libigl
- Parameters
prefab
: Prefab to be created, see meshPrefabsunloadActiveMesh
: Delete the active mesh if it existssetAsActiveMesh
: Set this mesh as the active oneperformValidityChecks
: Check that the prefab can be properly used with libigl.
Meshes from the meshPrefabs list are checked during Start and do not need to be checked again.
- Return
LibiglMesh component on the new instance, null if there was an error
-
void
DestroyMesh
(LibiglMesh libiglMesh)¶ Use this to delete a mesh safely. Handles case when mesh is the active one, ActiveMesh
-
void
RegisterMesh
(LibiglMesh libiglMesh)¶
-
void
UnregisterMesh
(LibiglMesh libiglMesh)¶
Public Members
-
GameObject[]
meshPrefabs
¶
-
readonly List<LibiglMesh>
AllMeshes
= new List<LibiglMesh>()¶ List of all LibiglMeshes that are instantiated
-
GameObject
boundingBoxPrefab
¶
Events
-
event Action
OnActiveMeshChanged
= delegate { }¶ Invoked when the ActiveMesh is changed. Called after initialization, if the mesh is newly instantiated.
Public Static Functions
-
bool
CheckPrefabValidity
(GameObject prefab)¶ Checks if a prefab can be loaded and modified with libigl. Does not modify the prefab only logs errors.
- Return
True if the prefab can be used with libigl
-
void
SetActiveMesh
(LibiglMesh libiglMesh)¶
Public Static Attributes
-
MeshManager
get
¶
-
LibiglMesh
ActiveMesh
¶ The mesh currently loaded and being modified
Private Static Functions
-
void
DestroyActiveMesh
()¶
-
LibiglMesh
3.4.2. LibiglMesh.cs¶
-
class
Libigl.LibiglMesh
: public MonoBehaviour¶ This component needs to be attached to any GameObject that you want to modify with libigl.
Any libigl related code is defined in the LibiglBehaviour class. This class only handles the threading and connection with the Unity Mesh components.
Public Functions
-
bool
IsJobRunning
()¶ - Return
True if a job/worker thread is running on the MeshData
-
bool
IsActiveMesh
()¶ - Return
True if this is the active mesh set by the MeshManager
-
void
Initialize
()¶
-
void
ResetTransformToSpawn
()¶ Move mesh up so it is resting on the spawnPoint, ie min of bounding box is at spawnPoint
- Parameters
mesh
: Needed for bounding box
-
void
SetWireframe
(bool value)¶ Toggles the wireframe shader for the mesh (not the bounding box).
-
void
UpdateBoundingBoxSize
()¶ Adjust the bounding box visual to fit the true bounds of the mesh.
-
void
RepaintBounds
(bool overrideVisible = false, bool primary = false)¶ Shows or hides the wireframe bounding box. Also changes the material accordingly.
- Parameters
overrideVisible
: Override default visibility set in the InputStateprimary
: If overriding visibility, should we highlight this as the primary bounding box
Properties
-
MeshRenderer
MeshRenderer
{ }¶
-
LibiglBehaviour
Behaviour
{ }¶ The libigl behaviour instance that is executing on this mesh
Private Functions
-
void
OnActiveMeshChanged
()¶
-
void
Update
()¶
-
void
ExecuteThread
()¶ Creates a thread with the LibiglBehaviour code
Assert: _workerThread is null (finished and PostExecuteThread has been called)
-
void
PostExecuteThread
()¶ Applies changes and cleans up the threading for re-use once the thread has finished.
Assert: _workerThread is finished executing.
-
void
OnDestroy
()¶
-
void
Dispose
()¶
Private Members
-
MeshFilter
_meshFilter
¶
-
Thread
_workerThread
¶ Expensive operations executed in LibiglBehaviour.Execute are done in this thread
-
MeshRenderer
_boundingBoxRenderer
¶
-
bool
3.4.3. UMeshData.cs¶
-
class
Libigl.UMeshData
: public IDisposable¶ Stores a copy of the Unity Mesh’s arrays. This is purely for the interface between the Libigl Mesh MeshState and the Unity Mesh / what will be rendered. Important: Uses RowMajor as that is how it is stored by Unity and on the GPU.
Public Functions
-
unsafe void
LinkBehaviourState
(LibiglBehaviour behaviour)¶ Initialize the UMeshData with shared data with the behaviour .
-
unsafe void
ApplyDirty
(MeshState *state, MeshInputState inputState)¶ Applies changes to the C++ State to this instance. Use this to copy changes from Col to RowMajor.
Can and should be called from a worker thread. Behind the scenes this tranposes and copies the matrices.
The DirtyState is propagated so ApplyDirtyToMesh (called on the main thread) will apply the changes.
- See
Native.ApplyDirty
-
void
ApplyDirtyToMesh
(Mesh mesh)¶ Apply MeshData changes to the Unity Mesh to see changes when rendered. Uses the DirtyState to detect what needs to be applied.
Must be called on the main thread as it accesses the Unity API.
Assert: IsRowMajor is true.
-
UMeshDataNative
GetNative
()¶ Note: Changes to the dirtyState are not applied to the MeshData instance (not a reference) and needs to be set manually in a C# context.
Important: The struct itself should be treated as
const
as changes have no effect (it’s a copy).- Return
A MeshDataNative instance than can be passed to C++ containing all pointers
-
void
Dispose
()¶
Public Members
-
const bool
IsRowMajor
= true¶
-
uint
DirtyState
= DirtyFlag.None¶
-
uint
DirtySelections
= 0¶
-
uint
DirtySelectionsResized
= 0¶
-
NativeArray<Vector3>
V
¶
-
NativeArray<Vector3>
N
¶
-
NativeArray<Vector2>
UV
¶
-
NativeArray<int>
F
¶
-
NativeArray<uint>
S
¶
-
readonly int
VSize
¶
-
readonly int
FSize
¶
Private Functions
Private Members
-
UMeshDataNative
_native
¶ Stores pointers to the native arrays, we can pass this to C++
-
unsafe void
3.4.3.1. DirtyFlag¶
-
class
Libigl.DirtyFlag
¶ Marks which data has changed in UMeshData as a bitmask and needs to be applied to the mesh.
This is used to selectively update the Unity mesh and is only for data that Unity requires. Use these constants along with the bitwise operators.
Public Members
-
const uint
None
= 0¶
-
const uint
VDirty
= 1¶
-
const uint
NDirty
= 2¶
-
const uint
CDirty
= 4¶
-
const uint
UVDirty
= 8¶
-
const uint
FDirty
= 16¶
-
const uint
DontComputeNormals
= 32¶ Don’t recaluclate normals when VDirty is set, NDirty overrides this.
-
const uint
DontComputeBounds
= 64¶ Don’t recalculate bounds when VDirty is set. Bounds are used for occlusion culling.
-
const uint
DontComputeColorsBySelection
= 128¶ Don’t recompute colors if a visible selection has changed.
-
const uint
VDirtyExclBoundary
= 256¶ Use this when the vertex positions have changed, but the boundary conditions are unaffected. VDirty overrides this.
-
const uint
All
= uint.MaxValue - DontComputeNormals - DontComputeBounds¶
-
const uint
3.4.3.2. UMeshDataNative.cs¶
-
struct
Libigl.UMeshDataNative
¶ Stores pointers to the native arrays in UMeshData so we can pass this to C++. Pointers are to the first element in the respective NativeArray.
Important: As Native arrays are not managed memory, the underlying array is fixed and will not move due to Garbage Collection. So an instance’s pointers will remain valid.
Public Functions
-
UMeshDataNative
(float *vPtr, float *nPtr, float *cPtr, float *uvPtr, int *fPtr, int vSize, int fSize)¶
-
3.4.4. LibiglBehaviour.cs¶
-
class
Libigl.LibiglBehaviour
: public IDisposable¶ This is where the behaviour that interfaces with libigl is. It follows a Pre/Post/Execute threading pattern. This is a
partial
class, meaning it is split between several files.Input: This handles collecting data from the main thread for the worker thread. It sets up the MeshInputState for the Actions. This is where we decide what to execute on the worker thread.
Actions: This handles executing things on the worker thread. Actions, in this context, are things that can be executed on the worker thread. They are the entry points to the C++ code (mostly). These actions correspond to the Do* variables in the MeshInputState
Transform: This handles anything related to transformations of the mesh or selections. This is only used for calculating which transformation to do for the selections. The code for applying the transformation to selections is in Actions
See also Libigl.LibiglMesh which handles the threading and calls the Pre/Post/Execute callbacks.
Public Functions
-
LibiglBehaviour
(LibiglMesh libiglMesh)¶ Create a behaviour for the Mesh MonoBehaviour component. Every Mesh has one behaviour.
-
void
Update
()¶ Called every frame, the normal Unity Update. Use this to update UI, input responsively. Do not call any expensive libigl methods here, use Execute instead
Be careful not to modify the shared state if there is a job running Libigl.LibiglMesh.IsJobRunning. Consider making a copy of certain data, using PreExecute or using atomics/Interlocked. Update is called just before PreExecute.
-
void
PreExecute
()¶ Called just before a new thread is started in which Execute is called. Use this to update the input state, set flags and access any Unity API from the main thread.
Called on the main thread.
-
void
Execute
()¶ Perform expensive computations here. This is called similarly to Update. Called on a worker thread from which any Unity API function, with a few exceptions such as
Debug.Log
, cannot be called.There is one worker thread per Libigl.LibiglMesh. You should call
_libiglMesh.DataRowMajor.ApplyDirty(_state)
here to apply changes to the RowMajor UMeshData outside the main thread.
-
void
PostExecute
()¶ Called after Execute to apply changes to the mesh.
Called on the main thread.
Use
Mesh.DataRowMajor.ApplyDirtyToMesh
to apply changes
-
void
Dispose
()¶ This is the destructor. Ensure all C++ owned data is deleted. Calls Native.DisposeMesh
-
void
SetActiveSelection
(int value)¶ Changes the active selection and triggers OnActiveSelectionChanged.
-
void
SetActiveSelectionIncrement
(int increment)¶ Increments the active selection and safely loops.
Public Members
-
MeshState*
State
¶ A pointer to the C++ state. This is allocated and deleted in C++ within Native.InitializeMesh and Native.DisposeMesh.
-
MeshInputState
Input
¶ The input state on the main thread. This is copied to the thread input state
State.Input
at the end of PreExecute and is then immediately consumed by MeshInputState.Consume.
-
readonly LibiglMesh
Mesh
¶ Reference to the Libigl.LibiglMesh used to apply changes to the Libigl.LibiglMesh.DataRowMajor and the Unity UnityEngine.Mesh
Events
Private Functions
-
void
ActionTransformSelection
()¶ Transforms the selections based on the TransformDeltas given in the MeshInputState It also decides which selections should be translated, storing this in _currentTranslateMaskL
-
void
FindBrushSelectionMask
(ref uint maskId, Vector3 brushPos)¶ Finds which selections are inside the brush and updates the maskId
-
void
ActionTransformSelectionGeneric
(ref TransformDelta transformDelta, uint maskId)¶ Does the actual translation, but is independent of the hands (L or R)
-
void
ActionSelect
()¶ Selects what is inside the brushes of the hands.
-
void
ActionSelectGeneric
(bool doSelect, Vector3 brushPos, bool alternateSelectMode)¶ Does the actual selection, but is independent of the hands (L or R)
-
void
ActionHarmonic
()¶ Runs the
igl::harmonic
Biharmonic Deformation
-
void
ActionArap
()¶ Runs the
igl::arap
As-Rigid-As-Possible Deformation
-
void
ActionUi
()¶ Applies various actions triggered from the UI or other input
-
void
UpdateInputTransform
()¶ Input for the transform tool
-
void
UpdateInputSelect
()¶ Gathering input for the select tool
-
void
PreExecuteInput
()¶ Updates the Input just before the worker thread is started. This copies the shared InputManager.State to the Input
-
void
UpdateTransform
()¶ Updates the current transformation state from the input, regardless of what the worker thread is doing. Decides when a transformation is started/stopped (changes in the finite state machine FSM). Applies the transformation immediately if we are transforming the mesh (as this is done by Unity). Call this in Update() every frame.
-
void
ApplyTransformToMesh
()¶ Gets and consumes the transformation, applying it to the LibiglMesh Transform.
-
void
ApplyTransformToSelection
()¶ Save and consume the transformation, which will later be applied to the selection on the worker thread.
-
void
PreExecuteTransform
()¶
-
void
ResetTransformStartPositions
()¶
-
void
GetTransformDelta
(bool consumeInput, ref TransformDelta transformDelta, Space space, bool withRotate, bool isTwoHanded, bool primaryHand)¶ Find out the TransformDelta that should be done. Independent of what we are transforming, mesh or selection.
- Parameters
consumeInput
: Should we reset the starting positions/rotations of the hands. This is unrelated to the MeshInputState.Consume function which is for the worker threadtransformDelta
: Where we should add our transformation to.
-
void
GetTransformOneHanded
(bool isRight, ref TransformDelta transformDelta, bool withRotate = true)¶ Finds out the transformation when using one hand
-
void
GetTransformTwoHanded
(ref TransformDelta transformDelta, bool withRotate = true)¶ Finds out the transformation when using both hands
Private Members
-
uint
_currentTranslateMaskL
¶ The selections which are currently being translated by the left hand. This is set by the worker thread.
-
uint
_currentTranslateMaskR
¶
-
MeshInputState
_executeInput
¶ The input state on the worker thread. When inside an Actions or anywhere on the worker thread you should exclusively access this input state.
-
readonly UiMeshDetails
_uiDetails
¶ The corresponding UI panel. It is initialized from here.
-
bool
_firstTransformHand
¶ The first hand to start a transformation. True = Right
-
bool
_isTwoHandedTransformation
¶ Are we using both hands in the transformation
-
bool
_isTwoHandedTransformationPrev
¶
-
bool
_doTransformL
¶
-
bool
_doTransformPrevL
¶
-
bool
_doTransformR
¶
-
bool
_doTransformPrevR
¶
-
Vector3
_transformStartHandPosL
¶ Where the hand was when the TransformDelta was started. Or the hand position at the last time the transformation was consumed.
-
Vector3
_transformStartHandPosR
¶
-
Quaternion
_transformStartHandRotL
¶
-
Quaternion
_transformStartHandRotR
¶
-
const float
GrabPressThreshold
= 0.1f¶ At which point do we consider the button as pressed
-
3.4.4.1. TransformDelta¶
-
struct
Libigl.TransformDelta
¶ Stores information about a single transformation.
Public Functions
-
void
Add
(TransformDelta other)¶ (experimental) Combines two transformations, does not consider the pivot.
Public Static Functions
-
TransformDelta
Identity
()¶
-
void
3.4.5. MeshInputState.cs¶
-
struct
Libigl.MeshInputState
¶ Struct for storing the current input for a mesh. (This is a value type so assigning will copy). Anything that may change as we are executing should be in the InputState, as it is copied in PreExecute. Anything that is the same between all meshes may be put into the InputState. Anything related to what should be executed on the worker thread should be put here (e.g. DoSelect).
Variables that correspond to triggering Actions start with
Do
e.g.DoSelect
Public Functions
-
void
Consume
()¶ Consumes and resets flags raised. Should be called in PreExecute after copying to the State.
Public Members
-
bool
DoTransformL
¶
-
bool
DoTransformR
¶
-
bool
DoTransformLPrev
¶
-
bool
DoTransformRPrev
¶
-
bool
PrimaryTransformHand
¶
-
TransformDelta
TransformDeltaJoint
¶
-
TransformDelta
TransformDeltaL
¶
-
TransformDelta
TransformDeltaR
¶
-
int
ActiveSelectionId
¶
-
uint
VisibleSelectionMask
¶
-
bool
VisibleSelectionMaskChanged
¶
-
uint
SCountUi
¶ For UI, will be copied to the state in PreExecute. This is used when we create a selection in the UI on the main thread.
-
bool
DoSelectL
¶
-
bool
DoSelectLPrev
¶
-
bool
DoSelectR
¶
-
bool
DoSelectRPrev
¶
-
bool
AlternateSelectModeL
¶ Inverts the selection mode between SelectionMode.Add and SelectionMode.Subtract
-
bool
AlternateSelectModeR
¶
-
uint
DoClearSelection
¶ A Mask of the selections that should be cleared
-
Vector3
BrushPosL
¶
-
Vector3
BrushPosR
¶
-
float
BrushRadiusLocal
¶
-
bool
DoHarmonic
¶ Trigger execution once
-
bool
DoHarmonicRepeat
¶ Trigger execution every frame
-
bool
HarmonicShowDisplacement
¶
-
bool
DoArap
¶
-
bool
DoArapRepeat
¶
-
bool
ResetV
¶
Public Static Functions
-
MeshInputState
GetInstance
()¶ - Return
An instance with the default values
Private Functions
-
void
ConsumeTransform
()¶ Consumes the state for the transformations
-
void
3.4.6. MeshState.cs¶
-
struct
Libigl.MeshState
¶ The C++ state for a mesh in column major. This is linked to Unity and the RowMajor version via UMeshData. It stores only pointers to the Eigen data so this can be shared between C++ and C#. The mesh data is allocated in C++ during the Native.InitializeMesh function using UMeshDataNative.
The DirtyState indicates what has been changed and needs to be applied to the Unity mesh.
As this struct is shared between a managed (C#) and native (C++) context, you must consider Marshalling when adding new variables.
void*
usually represents an Eigen matrix, but can be anything.Public Members
-
uint
DirtySelections
¶ Tells us which selections have been modified, as a bitmask. Each bit represents one selection.
-
uint
DirtySelectionsResized
¶ Less stricter version than DirtySelections, where we only consider a selection dirty if the selected vertices size changes, see SSizes.
-
readonly void*
VPtr
¶
-
readonly void*
NPtr
¶
-
readonly void*
CPtr
¶
-
readonly void*
UVPtr
¶
-
readonly void*
FPtr
¶
-
readonly int
VSize
¶
-
readonly int
FSize
¶
-
readonly void*
SPtr
¶
-
uint
SSize
¶ Amount of selections enabled
-
readonly uint*
SSizes
¶ uint[32], vertices selected per selection
-
readonly uint
SSizesAll
¶ Total vertices selected
Private Members
-
readonly void*
Native
¶ Native only state
-
uint
3.4.7. Native.cs¶
-
class
Libigl.Native
¶ Contains all C++ function declarations. C# to C++
Handles initialization of the DLL and works with the UnityNativeTool for easy reloading/recompilation.
Convention: Pass the MeshState as the first argument if the function modifies a mesh.
Public Functions
-
unsafe MeshState*
InitializeMesh
(UMeshDataNative data, string name)¶
-
unsafe void
ApplyDirty
(MeshState *state, UMeshDataNative data, uint visibleSelectionMask)¶
-
unsafe void
ReadOFF
(string path, bool setCenter, bool normalizeScale, float scale, out float *VPtr, out int VSize, out float *NPtr, out int NSize, out uint *FPtr, out int FSize, bool calculateNormalsIfEmpty)¶
-
unsafe void
TransformSelection
(MeshState *state, Vector3 translation, float scale, Quaternion rotation, Vector3 pivot, uint maskId)¶
Public Static Functions
-
void
Initialize
()¶ Initializes the native library and sets up callbacks/delegates for C++ -> C# calls. Note: this may not be called on the main thread. So Unity functions may not be available.
In the editor, this is triggered each time the dll has been loaded.
-
void
Destroy
()¶ Clean up native part if required, called just before unloading of the dll.
Public Static Attributes
-
readonly VertexAttributeDescriptor[]
VertexBufferLayout
¶ Contains the vertex buffer layout (on the GPU) for editable meshes. There will be a copy of the mesh on the CPU which may not have the same layout. This was initially intended to be done for more a efficient applying of mesh data, but it allows for slightly more control over how meshes are stored on the GPU.
Private Functions
-
void
Initialize
(NativeCallbacks.StringCallback debugCallback, NativeCallbacks.StringCallback debugWarningCallback, NativeCallbacks.StringCallback debugErrorCallback)
Private Members
-
const string
DllName
= “__libigl-interface”¶ Name of the dll without the extension. Use this with the DllImportAttribute. This is set such that in the editor we can use the UnityNativeTool and in the build we use the library directly.
In Editor:
libigl-interface
In Build and Actual Name:
__libigl-interface
Private Static Functions
-
static
Native
()¶ In a build, Initialize in the static ctor. This is called once just before the first function is called in this class.
Please read up on static constructors before modifying this.
-
unsafe MeshState*
3.4.8. NativeCallbacks.cs¶
-
class
Libigl.NativeCallbacks
¶ Contains all callbacks from the native context. C++ to C#
Callbacks should be annotated with the MonoPInvokeCallbackAttribute so that IL2CPP builds will compile properly. Each callback needs to have a corresponding delegate (/type).
Public Functions
-
delegate void
StringCallback
(string message)¶ Based on https://answers.unity.com/questions/30620/how-to-debug-c-dll-code.html The ‘function pointer type’ passed to C++
- Parameters
message
: String or char* to be printed
-
delegate void