Posts: 11
Threads: 3
Joined: Aug 2022
Reputation:
0
13-09-2022, 12:01 AM
(This post was last modified: 13-09-2022, 12:30 AM by woffles.)
Hello there,
I've been working quite a lot with softbodies recently, trying to figure out the basis of the engine and how everything works and functions. One of the things I seemingly can't wrap my head around is the prospect of using Obi for 2D.
I'm aware that this is possible, due to this ( http://obi.virtualmethodstudio.com/forum...-2668.html) thread here, and I've also been able to replicate things shown, by utilizing the in-built Unity quad primitive, which worked just fine.
However, in the above mentioned thread, I saw that a flat circular mesh was used, which yielded results identical to that of what I achieved with the quad. I've since tried to replicate such a 'mesh' in blender, making a flat plane and exporting to Unity. However, particles don't seem to generate properly (and the mesh is only visible on one side within the Unity editor) and the softbody collapses and deforms at runtime, even after skinning.
How would I make such a flat mesh that is usable in Obi?
Thank you.
regards,
-woffles
UPDATE:
I was messing around with the solver settings, and found that it could work just fine when setting solver mode to 3D (which resulted in the quad being deformed and not working properly instead). However, when in 2D, the mesh still fails to work. Still not sure why, but I will keep investigating.
Posts: 6,326
Threads: 24
Joined: Jun 2017
Reputation:
400
Obi Owner:
15-09-2022, 07:37 PM
(This post was last modified: 15-09-2022, 07:42 PM by josemendez.)
(13-09-2022, 12:01 AM)woffles Wrote: I've since tried to replicate such a 'mesh' in blender, making a flat plane and exporting to Unity. However, particles don't seem to generate properly and the softbody collapses and deforms at runtime, even after skinning.
I was messing around with the solver settings, and found that it could work just fine when setting solver mode to 3D (which resulted in the quad being deformed and not working properly instead). However, when in 2D, the mesh still fails to work. Still not sure why, but I will keep investigating.
Hi!
Make sure the mesh is properly exported. More specifically, make sure it has sane scale values in Unity. If it's scaled x100 or some other large value, you will be able to see it in the scene view, but not when editing the mesh alone since it will be extremely small in absence of its transform (that scales it up x100). Also make sure to set " max anisotropy" to its minimum value in the blueprint, since in 2D particles cannot have anisotropy values > 1.
(13-09-2022, 12:01 AM)woffles Wrote: and the mesh is only visible on one side within the Unity editor
This does not have anything to do with Obi, it's probably backface culling. This is a very basic concept in 3D graphics: triangles/faces have an associated normal vector, that determines which side is facing "outwards". Once a triangle is facing away from the camera, it's not rendered anymore to save resources.
Unity performs backface culling by default. In 3D modeling software like Blender it's optional (disabled by default), because it is sometimes useful to see the inside of objects while modeling.
If you want two-facing geometry in Unity, you can:
- Use a shader with no culling: https://docs.unity3d.com/2020.1/Document...Depth.html
- Use two materials, one for front-facing geometry and another for backfaces.
- Bruteforce it and duplicate all triangles, flipping their normals (not recommended, duplicates memory usage and hampers performance).
Keep in mind that Obi is a moderately complex engine, aimed at intermediate/advanced users. I'd suggest to familiarize yourself with these basic 3D concepts first, otherwise chances are you'll have a hard time using Obi.
let me know if you need further help,
kind regards
Posts: 11
Threads: 3
Joined: Aug 2022
Reputation:
0
(15-09-2022, 07:37 PM)josemendez Wrote: Hi!
Make sure the mesh is properly exported. More specifically, make sure it has sane scale values in Unity. If it's scaled x100 or some other large value, you will be able to see it in the scene view, but not when editing the mesh alone since it will be extremely small in absence of its transform (that scales it up x100). Also make sure to set "max anisotropy" to its minimum value in the blueprint, since in 2D particles cannot have anisotropy values > 1.
This does not have anything to do with Obi, it's probably backface culling. This is a very basic concept in 3D graphics: triangles/faces have an associated normal vector, that determines which side is facing "outwards". Once a triangle is facing away from the camera, it's not rendered anymore to save resources.
Unity performs backface culling by default. In 3D modeling software like Blender it's optional (disabled by default), because it is sometimes useful to see the inside of objects while modeling.
If you want two-facing geometry in Unity, you can:
- Use a shader with no culling: https://docs.unity3d.com/2020.1/Document...Depth.html
- Use two materials, one for front-facing geometry and another for backfaces.
- Bruteforce it and duplicate all triangles, flipping their normals (not recommended, duplicates memory usage and hampers performance).
Keep in mind that Obi is a moderately complex engine, aimed at intermediate/advanced users. I'd suggest to familiarize yourself with these basic 3D concepts first, otherwise chances are you'll have a hard time using Obi.
let me know if you need further help,
kind regards
hello!
i've read about backface culling before, just wasn't exactly sure if that was controlled by Unity or within the obi simulation. thanks for the clarification!
I got the flat '2D' mesh working after messing around with the solver and a model for a few hours. The anisotropy setting seems to have helped in preventing the softbody from collapsing on itself. When I am performing a ObiSoftbody.Teleport(), it seems to work as intended but the function complains about an ArgumentOutOfRange exception, with some index inside the BatchCount bounds to blame. Not really sure why this is happening since the moving seems to work fine.
I am supplying a Vector3.zero and softbody.transform.rotation to the function.
thanks :)
Posts: 6,326
Threads: 24
Joined: Jun 2017
Reputation:
400
Obi Owner:
(16-09-2022, 02:49 AM)woffles Wrote: i've read about backface culling before, just wasn't exactly sure if that was controlled by Unity or within the obi simulation. thanks for the clarification!
Hi there!
Backface culling is performed by the GPU during rendering, Obi does not perform any rendering of its own since it's a physics engine.
(16-09-2022, 02:49 AM)woffles Wrote: I got the flat '2D' mesh working after messing around with the solver and a model for a few hours. The anisotropy setting seems to have helped in preventing the softbody from collapsing on itself. When I am performing a ObiSoftbody.Teleport(), it seems to work as intended but the function complains about an ArgumentOutOfRange exception, with some index inside the BatchCount bounds to blame. Not really sure why this is happening since the moving seems to work fine.
I am supplying a Vector3.zero and softbody.transform.rotation to the function.
Tested this, could reproduce when teleporting an object with multiple constraint batches, thanks for reporting this! Line 202 in the ObiSoftbody.cs script should be:
Code: sc.batches[i].orientations[batchOffset + j] = rotOffset * sc.batches[i].orientations[batchOffset + j];
instead of:
Code: sc.batches[j].orientations[batchOffset + i] = rotOffset * sc.batches[i].orientations[batchOffset + j];
let me know if I can be of further help,
Posts: 11
Threads: 3
Joined: Aug 2022
Reputation:
0
(17-09-2022, 10:06 AM)josemendez Wrote: Hi there!
Backface culling is performed by the GPU during rendering, Obi does not perform any rendering of its own since it's a physics engine.
Tested this, could reproduce when teleporting an object with multiple constraint batches, thanks for reporting this! Line 202 in the ObiSoftbody.cs script should be:
Code: sc.batches[i].orientations[batchOffset + j] = rotOffset * sc.batches[i].orientations[batchOffset + j];
instead of:
Code: sc.batches[j].orientations[batchOffset + i] = rotOffset * sc.batches[i].orientations[batchOffset + j];
let me know if I can be of further help,
hey!
I did end up changing line 202 to what you outlined. Sadly the problem still persists, with the same error as before:
ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection. Seems to still originate from the Teleport function at line 205 (closing bracket of the function).
Posts: 6,326
Threads: 24
Joined: Jun 2017
Reputation:
400
Obi Owner:
(18-09-2022, 03:44 AM)woffles Wrote: hey!
I did end up changing line 202 to what you outlined. Sadly the problem still persists, with the same error as before:
ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection. Seems to still originate from the Teleport function at line 205 (closing bracket of the function).
Hi!
That’s very strange, there cannot be an out of bounds error in a line that only contains a closing bracket. Make sure you changed the correct file/line, and that you saved the file before recompiling.
Kind regards,
Posts: 11
Threads: 3
Joined: Aug 2022
Reputation:
0
(18-09-2022, 08:54 AM)josemendez Wrote: Hi!
That’s very strange, there cannot be an out of bounds error in a line that only contains a closing bracket. Make sure you changed the correct file/line, and that you saved the file before recompiling.
Kind regards,
yep, double and triple checked that it was ObiSoftbody.cs (with the red jelly icon). Recompiled successfully.
Posts: 6,326
Threads: 24
Joined: Jun 2017
Reputation:
400
Obi Owner:
(18-09-2022, 10:15 AM)woffles Wrote: yep, double and triple checked that it was ObiSoftbody.cs (with the red jelly icon). Recompiled successfully.
I’m unable to reproduce this. Could you please send a small repro project/scene to support(at)virtualmethodstudio.com so that I can take a closer look? Thanks!
Posts: 11
Threads: 3
Joined: Aug 2022
Reputation:
0
(18-09-2022, 11:19 AM)josemendez Wrote: I’m unable to reproduce this. Could you please send a small repro project/scene to support(at)virtualmethodstudio.com so that I can take a closer look? Thanks!
No problem, I've sent it to the address you specified. :)
While the project is with you, I've been trying to apply a force opposite to the direction of the softbody's collision. I've read through the collision scripting API and documentation and structured my own script to take the contact normal and use ObiSoftbody.AddForce(). However, it seems as though this has no effect.
Thank you as always!
Posts: 6,326
Threads: 24
Joined: Jun 2017
Reputation:
400
Obi Owner:
18-09-2022, 01:03 PM
(This post was last modified: 18-09-2022, 01:05 PM by josemendez.)
(18-09-2022, 11:46 AM)woffles Wrote: No problem, I've sent it to the address you specified.
While the project is with you, I've been trying to apply a force opposite to the direction of the softbody's collision. I've read through the collision scripting API and documentation and structured my own script to take the contact normal and use ObiSoftbody.AddForce(). However, it seems as though this has no effect.
Thank you as always!
Hi!
Took a look at your project, there's multiple issues with it so I will go over them one by one:
1) Lines 201-203 in your ObiSoftbody.cs look like this:
Code: for (int j = 0; j < ac.batches[i].activeConstraintCount; ++j)
{; //<-- stray semicolon!
sc.batches[i].orientations[batchOffset + j] = rotOffset * sc.batches[i].orientations[batchOffset + j];
}
There's a semicolon immediately after the first { in the for loop.
2) You're calling Teleport() in your GameManager's Start(). By that time the solver hasn't created all constraints yet so attempting to teleport them will fail. You must wait for the solver to fully load the actor's constraints, this is done at the end of each frame where an actor has been loaded. So a simple fix would be:
Code: public void ResetPosition()
{
StartCoroutine(ResetCoroutine());
}
public IEnumerator ResetCoroutine()
{
yield return new WaitForEndOfFrame(); // if this is the first frame, this makes sure constraint initialization has finished.
respawnPS.Play();
//GetComponent<Rigidbody>().velocity = Vector2.zero;
gameObject.transform.position = Vector3.zero;
softbody.Teleport(Vector3.zero, softbody.transform.rotation);
}
Also, there's no use on teleporting the softbody to the center during Start() so remove line 22 in SoftbodyBall.cs.
3) You're using a softbody for the ball, but it only has 2 triangles:
You won't get any meaningful deformation from this mesh, it will look just like a rigidbody. You need the mesh to have more subdivisions for it to be able to squish/deform, otherwise there's no point in using softbody simulation for this.
4) In your SoftbodyBouncySurface.cs, the "apply" boolean value is always false. As a result, no force is applied to the softbody.
The OnCollisionEnter2D callback only works for built-in colliders. Obi actors will ignore it, so you can delete the entire method. Here's a working script:
Code: using System;
using System.Collections;
using Obi;
using UnityEngine;
public class SoftbodyBouncySurface : MonoBehaviour
{
public ObiSolver solver;
public SoftbodyBall softbody;
public float bounceStrength = 1000f;
private bool apply;
private Vector3 direction;
private void OnEnable()
{
solver.OnCollision += Solver_OnCollision;
}
private void OnDisable()
{
solver.OnCollision -= Solver_OnCollision;
}
private void Solver_OnCollision(object sender, ObiSolver.ObiCollisionEventArgs e)
{
// don't do anything if the force has not been applied yet.
if (apply) return;
var world = ObiColliderWorld.GetInstance();
// just iterate over all contacts in the current frame:
foreach (Oni.Contact contact in e.contacts)
{
// if this one is an actual collision:
if (contact.distance < 0.01)
{
ObiColliderBase col = world.colliderHandles[contact.bodyB].owner;
if (col.CompareTag("Paddle"))
{
direction = contact.normal;
apply = true;
return;
}
}
}
}
private void Update()
{
if (apply)
{
AudioManager.instance.PlaySound(3);
softbody.ApplyForce(direction * bounceStrength);
apply = false;
}
}
}
Keep in mind that impulses are affected by mass, since your ball weights 36 kg you must use a rather large bounceStrength value, try 1000-2000.
kind regards,
|