1
0
forked from cgvr/DeltaVR

scale spawned object to match given bounding sphere diameter

This commit is contained in:
2026-02-07 14:10:12 +02:00
parent 9fd4188d55
commit 7384a21d58
3 changed files with 59 additions and 10 deletions

View File

@@ -76,7 +76,7 @@ public class ModelGenerationUtils : MonoBehaviour
}
}
throw new System.Exception("Failed to generate 3D model!");
throw new Exception("Failed to generate 3D model!");
}
});
}
@@ -96,22 +96,22 @@ public class ModelGenerationUtils : MonoBehaviour
return await SpawnModel(gltf, objectName);
}
throw new System.Exception("Failed to load GameObject from model" + modelPath);
throw new Exception("Failed to load GameObject from model" + modelPath);
}
public async Task<GameObject> SpawnModel(byte[] modelBinary)
public async Task<GameObject> SpawnModel(byte[] modelBinary, float boundingSphereDiameter = 0)
{
var gltf = new GltfImport();
bool loadSuccess = await gltf.Load(modelBinary);
if (loadSuccess)
{
return await SpawnModel(gltf, "GeneratedModel");
return await SpawnModel(gltf, "GeneratedModel", boundingSphereDiameter);
}
throw new System.Exception("Failed to load GameObject from binary!");
throw new Exception("Failed to load GameObject from binary!");
}
public async Task<GameObject> SpawnModel(GltfImport gltfImport, string objectName)
public async Task<GameObject> SpawnModel(GltfImport gltfImport, string objectName, float boundingSphereDiameter = 0)
{
GameObject spawningParent = new GameObject("Parent-" + objectName);
@@ -125,11 +125,54 @@ public class ModelGenerationUtils : MonoBehaviour
MeshRenderer renderer = spawnedObjectBody.GetComponent<MeshRenderer>();
renderer.material.SetFloat("metallicFactor", 0);
AdjustScale(spawnedObjectBody, collider, boundingSphereDiameter);
spawnedObjectBody.name = objectName;
return spawnedObjectBody;
}
throw new System.Exception("Failed to spawn GameObject " + objectName);
throw new Exception("Failed to spawn GameObject " + objectName);
}
private async void AdjustScale(GameObject obj, MeshCollider collider, float boundingSphereDiameter)
{
// Wait one frame to ensure collider cooking & bounds are valid
await Task.Yield();
// --- Compute current bounding sphere diameter (from world AABB) ---
Bounds b = collider.bounds; // world-space AABB
float currentDiameter = 2f * b.extents.magnitude;
if (boundingSphereDiameter <= 0f)
{
UnityEngine.Debug.Log("Not adjusting scale");
return;
}
if (currentDiameter <= Mathf.Epsilon)
throw new Exception("Spawned mesh has zero-sized bounds; cannot scale to target diameter.");
// --- Compute and apply uniform scale ---
float scaleFactor = boundingSphereDiameter / currentDiameter;
obj.transform.localScale *= scaleFactor;
// Give Unity a moment to recompute bounds after scaling, then do a corrective pass
await Task.Yield();
// Corrective pass (optional): re-measure and nudge scale to reduce residual error
Bounds b2 = collider.bounds;
float newDiameter = 2f * b2.extents.magnitude;
// Only correct if off by more than a tiny epsilon (1%)
const float tolerance = 0.01f; // 1%
float err = Mathf.Abs(newDiameter - boundingSphereDiameter) / boundingSphereDiameter;
if (err > tolerance && newDiameter > Mathf.Epsilon)
{
float correction = boundingSphereDiameter / newDiameter;
obj.transform.localScale *= correction;
// No need to wait again unless you need to read back the final diameter immediately
}
}

View File

@@ -13,6 +13,7 @@ public class CafeWaiterNPC : NPCController
public Transform backRoom;
public Transform plate;
public float backRoomMovingTime = 5f;
public float spawnedFoodDiameter = 0.5f;
public int ignorePlayerCollisionLayer = 2;
@@ -135,7 +136,7 @@ public class CafeWaiterNPC : NPCController
Sprite sprite = ModelGenerationUtils.CreateSprite(GeneratedTexture);
string encodedTexture = Convert.ToBase64String(GeneratedTexture.EncodeToJPG());
byte[] encodedModel = await TrellisClient.Instance.GenerateModel(encodedTexture);
GameObject spawnedObject = await ModelGenerationUtils.Instance.SpawnModel(encodedModel);
GameObject spawnedObject = await ModelGenerationUtils.Instance.SpawnModel(encodedModel, spawnedFoodDiameter);
// Come back
transform.DOMove(startingPosition, backRoomMovingTime).OnComplete(() =>
@@ -160,6 +161,7 @@ public class CafeWaiterNPC : NPCController
spawnedObjectCollider.convex = true;
spawnedObject.layer = ignorePlayerCollisionLayer;
spawnedObject.AddComponent<XRGrabInteractable>();
XRGrabInteractable grabComponent = spawnedObject.AddComponent<XRGrabInteractable>();
grabComponent.useDynamicAttach = true;
}
}