Thanks for doing that really appreciate it. So now hoping I can post this.
The following modification to OBI Rope works seamlessly. I will do the same for cloth soon.
I was hoping that you could maybe merge this method into Obi Rope / Cloth / SoftBody etc... with some kind of flag to enable / disable it.
Note: the strategy I used is to disable the primary mesh renderer on the Obi Rope
Then create a child object parented to OBI Rope in this case with zero local rotation and position.
This child object is destroyed (destroyimmediate) and re created on each frame.
The meshfilter, and the mesh renderer are added to the child each time it is created, the materials are set on the renderer. And a new mesh is created with a clone of the geometry of your normal mesh.
Essentially all we are doing is creating a pipeline to feed custom geometry into Octane.
Before anyone stares at this in absolute horror, Octane render is for creating animations, not for realtime rendering. One 1080P frame can take a few seconds to a few minutes to render depending on scene complexity. Therefore the garbage overhead of destroying and creating objects each frame is really a non issue here. We are not doing this 30 times per second. We are doing this one time per many seconds or minutes.
Note: in the code below OBI_OctaneMode is linking to a singleton helper that I created to allow me to control the two modes of all the ropes from a single place.
The following modification to OBI Rope works seamlessly. I will do the same for cloth soon.
I was hoping that you could maybe merge this method into Obi Rope / Cloth / SoftBody etc... with some kind of flag to enable / disable it.
Note: the strategy I used is to disable the primary mesh renderer on the Obi Rope
Then create a child object parented to OBI Rope in this case with zero local rotation and position.
This child object is destroyed (destroyimmediate) and re created on each frame.
The meshfilter, and the mesh renderer are added to the child each time it is created, the materials are set on the renderer. And a new mesh is created with a clone of the geometry of your normal mesh.
Essentially all we are doing is creating a pipeline to feed custom geometry into Octane.
Before anyone stares at this in absolute horror, Octane render is for creating animations, not for realtime rendering. One 1080P frame can take a few seconds to a few minutes to render depending on scene complexity. Therefore the garbage overhead of destroying and creating objects each frame is really a non issue here. We are not doing this 30 times per second. We are doing this one time per many seconds or minutes.
Note: in the code below OBI_OctaneMode is linking to a singleton helper that I created to allow me to control the two modes of all the ropes from a single place.
Code:
[HideInInspector] [NonSerialized] public Mesh extrudedMesh;
[HideInInspector] [NonSerialized] public Mesh extrudedMeshOctane;
[HideInInspector] [NonSerialized] public MeshRenderer PrimaryRenderer;
[HideInInspector] [NonSerialized] public Material[] PrimaryRendererMaterials;
[HideInInspector] [NonSerialized] public GameObject OctaneRenderGO;
private bool OBI_OctaneMode
{
get
{
if (OBIParams.Instance== null) { return false; }
return OBIParams.Instance.OBI_OctaneMode;
}
}
private void CreateMeshIfNeeded()
{
if (extrudedMesh == null)
{
extrudedMesh = new Mesh();
extrudedMesh.name = "extrudedMesh";
extrudedMesh.MarkDynamic();
GetComponent<MeshFilter>().mesh = extrudedMesh;
}
}
private void ClearMeshData()
{
extrudedMesh.Clear();
vertices.Clear();
normals.Clear();
tangents.Clear();
uvs.Clear();
vertColors.Clear();
tris.Clear();
}
private void CommitMeshData()
{
extrudedMesh.SetVertices(vertices);
extrudedMesh.SetNormals(normals);
extrudedMesh.SetTangents(tangents);
extrudedMesh.SetColors(vertColors);
extrudedMesh.SetUVs(0, uvs);
extrudedMesh.SetTriangles(tris, 0, true);
#region Octane Brute Force Method
// This brute force method works
// But this is really bad brute force and should not be needed.
if (OBI_OctaneMode && Application.isPlaying)
{
if (PrimaryRenderer == null)
{
PrimaryRenderer = GetComponent<MeshRenderer>();
PrimaryRendererMaterials = PrimaryRenderer.sharedMaterials;
}
PrimaryRenderer.enabled = false;
if (OctaneRenderGO != null)
{
GameObject.DestroyImmediate(OctaneRenderGO);
OctaneRenderGO = null;
}
OctaneRenderGO = new GameObject();
OctaneRenderGO.transform.parent = transform;
OctaneRenderGO.transform.localPosition = Vector3.zero;
OctaneRenderGO.transform.localRotation = Quaternion.Euler(Vector3.zero);
extrudedMeshOctane = new Mesh();
extrudedMeshOctane.name = "ExtrudedMeshOctane";
extrudedMeshOctane.MarkDynamic();
extrudedMeshOctane.SetVertices(vertices);
extrudedMeshOctane.SetNormals(normals);
extrudedMeshOctane.SetTangents(tangents);
extrudedMeshOctane.SetColors(vertColors);
extrudedMeshOctane.SetUVs(0, uvs);
extrudedMeshOctane.SetTriangles(tris, 0, true);
MeshFilter NewFilter;
NewFilter = OctaneRenderGO.AddComponent<MeshFilter>();
NewFilter.mesh = extrudedMeshOctane;
MeshRenderer NewRenderer;
NewRenderer = OctaneRenderGO.AddComponent<MeshRenderer>();
NewRenderer.sharedMaterials = PrimaryRendererMaterials;
}
#endregion
}