1
0
forked from cgvr/DeltaVR

shape scanner supports multiple object scanning, always destroys colliding objects on config completion

This commit is contained in:
2026-03-01 11:30:33 +02:00
parent dfdb47b94a
commit 95e67b9870
14 changed files with 90 additions and 97 deletions

View File

@@ -15,8 +15,6 @@
* kui kõik configurationid tehtud, siis midagi juhtub: uks avaneb, quest marker läheb ukse juurde, professor ütleb "thank you" * kui kõik configurationid tehtud, siis midagi juhtub: uks avaneb, quest marker läheb ukse juurde, professor ütleb "thank you"
* peab mängijale kuidagi selgitama, kuidas scale'ida prinditud objekte * peab mängijale kuidagi selgitama, kuidas scale'ida prinditud objekte
* prinditud objekti scale'imisele min ja max size limiit * prinditud objekti scale'imisele min ja max size limiit
* shape scanner mitte lihtsalt ontriggerenter ja -exit, sest kui mitu objekti lähevad samal ajal sisse
* shape scanneris prinditud objektid mõnikord ei kao ära kui config success
* archery range: * archery range:
* mikrofon peaks lõpetama protsessimise ka siis kui mängija läheb ära mikri juurest * mikrofon peaks lõpetama protsessimise ka siis kui mängija läheb ära mikri juurest
* võiks jääda kordama viimast instruktsiooni, kui mängija ei progressi edasi * võiks jääda kordama viimast instruktsiooni, kui mängija ei progressi edasi

View File

@@ -426,7 +426,6 @@ GameObject:
- component: {fileID: 5559886958032571103} - component: {fileID: 5559886958032571103}
- component: {fileID: 5954212323650350193} - component: {fileID: 5954212323650350193}
- component: {fileID: 2317701697644582190} - component: {fileID: 2317701697644582190}
- component: {fileID: 5652247538039532239}
m_Layer: 0 m_Layer: 0
m_Name: ShapeScanner m_Name: ShapeScanner
m_TagString: Untagged m_TagString: Untagged
@@ -549,6 +548,7 @@ MonoBehaviour:
rayParent: {fileID: 6811284554916002137} rayParent: {fileID: 6811284554916002137}
currentConfigurationDisplay: {fileID: 2482954631852020050} currentConfigurationDisplay: {fileID: 2482954631852020050}
correctPercentageDisplay: {fileID: 496206569825438079} correctPercentageDisplay: {fileID: 496206569825438079}
interactionManager: {fileID: 0}
requiredAndActive: {fileID: 2100000, guid: dccb608b252977047bd5848d6a497bfb, type: 2} requiredAndActive: {fileID: 2100000, guid: dccb608b252977047bd5848d6a497bfb, type: 2}
requiredAndPassive: {fileID: 2100000, guid: c0707507abffb6149b19e60299403e82, type: 2} requiredAndPassive: {fileID: 2100000, guid: c0707507abffb6149b19e60299403e82, type: 2}
notRequiredAndActive: {fileID: 2100000, guid: 991fa2870324ba04aba7bec9e1168afa, notRequiredAndActive: {fileID: 2100000, guid: 991fa2870324ba04aba7bec9e1168afa,
@@ -718,27 +718,6 @@ MonoBehaviour:
m_StartingSingleGrabTransformers: [] m_StartingSingleGrabTransformers: []
m_StartingMultipleGrabTransformers: [] m_StartingMultipleGrabTransformers: []
m_AddDefaultGrabTransformers: 1 m_AddDefaultGrabTransformers: 1
--- !u!65 &5652247538039532239
BoxCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4393714733752105576}
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_IsTrigger: 1
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 3
m_Size: {x: 1.5, y: 1.5, z: 1.5}
m_Center: {x: 0, y: 0, z: 0}
--- !u!1 &5905737949616845505 --- !u!1 &5905737949616845505
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0

View File

@@ -11,7 +11,6 @@ public class Printer3D : MonoBehaviour
private bool isPrinting = false; private bool isPrinting = false;
private EventInstance printingSound; private EventInstance printingSound;
private GameObject GeneratedModel;
// Start is called before the first frame update // Start is called before the first frame update
void Start() void Start()
@@ -39,12 +38,6 @@ public class Printer3D : MonoBehaviour
GameObject spawnedObject = await ModelGenerationUtils.Instance.SpawnModel(encodedModel, printedObjectSize); GameObject spawnedObject = await ModelGenerationUtils.Instance.SpawnModel(encodedModel, printedObjectSize);
InitializeSpawnedObject(spawnedObject); InitializeSpawnedObject(spawnedObject);
if (GeneratedModel != null)
{
// Destroy previous generated object (first move out of ShapeScanner to trigger OnTriggerExit
GeneratedModel.transform.position = Vector3.zero;
}
GeneratedModel = spawnedObject;
printingSound.setParameterByName("3DPrinterPrintingJob", 1); printingSound.setParameterByName("3DPrinterPrintingJob", 1);
isPrinting = false; isPrinting = false;

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using TMPro; using TMPro;
using UnityEngine; using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
[Serializable] [Serializable]
@@ -29,26 +30,25 @@ public class ShapeScanner : MonoBehaviour
public Transform rayParent; public Transform rayParent;
public TextMeshProUGUI currentConfigurationDisplay; public TextMeshProUGUI currentConfigurationDisplay;
public TextMeshProUGUI correctPercentageDisplay; public TextMeshProUGUI correctPercentageDisplay;
public XRInteractionManager interactionManager;
public Material requiredAndActive; public Material requiredAndActive;
public Material requiredAndPassive; public Material requiredAndPassive;
public Material notRequiredAndActive; public Material notRequiredAndActive;
public Material notRequiredAndPassive; public Material notRequiredAndPassive;
private List<GameObject> existingRays; private List<ShapeScannerRay> existingRays;
private float raySpawnDistanceX; private float raySpawnDistanceX;
private float raySpawnDistanceZ; private float raySpawnDistanceZ;
private int currentConfiguration; private int currentConfiguration;
private int rayCount; private int rayCount;
private int correctRayStates; private int correctRayStates;
private GameObject currentlyScannableObject;
// Start is called before the first frame update // Start is called before the first frame update
void Start() void Start()
{ {
existingRays = new List<GameObject>(); existingRays = new List<ShapeScannerRay>();
raySpawnDistanceX = raySpawnCorner2.localPosition.x - raySpawnCorner1.localPosition.x; raySpawnDistanceX = raySpawnCorner2.localPosition.x - raySpawnCorner1.localPosition.x;
raySpawnDistanceZ = raySpawnCorner2.localPosition.z - raySpawnCorner1.localPosition.z; raySpawnDistanceZ = raySpawnCorner2.localPosition.z - raySpawnCorner1.localPosition.z;
@@ -62,34 +62,15 @@ public class ShapeScanner : MonoBehaviour
} }
private void OnTriggerEnter(Collider other)
{
if (other.tag == rayPrefab.scannableTag)
{
currentlyScannableObject = other.gameObject;
}
}
private void OnTriggerExit(Collider other)
{
if (other.tag == rayPrefab.scannableTag)
{
currentlyScannableObject = null;
}
}
private void InitializeConfiguration() private void InitializeConfiguration()
{ {
// Delete all existing rays first // Delete all colliding objects and then all existing rays
foreach (GameObject ray in existingRays) DestroyCollidingObjects();
foreach (ShapeScannerRay ray in existingRays)
{ {
Destroy(ray); Destroy(ray.gameObject);
}
if (currentlyScannableObject != null)
{
currentlyScannableObject.transform.position = Vector3.zero;
Destroy(currentlyScannableObject);
} }
existingRays.Clear();
ShapeScannerConfiguration configuration = configurations[currentConfiguration]; ShapeScannerConfiguration configuration = configurations[currentConfiguration];
int rayRowCount = configuration.rows.Count; int rayRowCount = configuration.rows.Count;
@@ -103,7 +84,7 @@ public class ShapeScanner : MonoBehaviour
Vector3 rayPos = new Vector3(rayPosX, 0, rayPosZ); Vector3 rayPos = new Vector3(rayPosX, 0, rayPosZ);
ShapeScannerRay ray = Instantiate(rayPrefab, rayParent); ShapeScannerRay ray = Instantiate(rayPrefab, rayParent);
ray.transform.localPosition = rayPos; ray.transform.localPosition = rayPos;
existingRays.Add(ray.gameObject); existingRays.Add(ray);
bool rayCollisionRequired = configuration.rows[i].cells[j]; bool rayCollisionRequired = configuration.rows[i].cells[j];
if (rayCollisionRequired) if (rayCollisionRequired)
@@ -122,6 +103,31 @@ public class ShapeScanner : MonoBehaviour
UpdateDisplay(calculateCorrectPercentage()); UpdateDisplay(calculateCorrectPercentage());
} }
private void DestroyCollidingObjects()
{
HashSet<GameObject> allCollidingObjects = new HashSet<GameObject>();
foreach (ShapeScannerRay ray in existingRays)
{
allCollidingObjects.UnionWith(ray.GetCollidingObjects());
}
foreach (GameObject collidingObject in allCollidingObjects)
{
// Release player holding it
var grab = collidingObject.GetComponent<XRGrabInteractable>();
if (grab != null && grab.isSelected)
{
var interactor = grab.firstInteractorSelecting; // the hand/controller currently holding it
if (interactor != null)
{
// Transfer ownership: tell the manager to stop the selection
interactionManager.SelectExit(interactor, grab);
}
}
collidingObject.transform.position = Vector3.zero;
Destroy(collidingObject);
}
}
private float calculateCorrectPercentage() private float calculateCorrectPercentage()
{ {
return Mathf.RoundToInt((float)correctRayStates / rayCount * 100); return Mathf.RoundToInt((float)correctRayStates / rayCount * 100);

View File

@@ -10,11 +10,13 @@ public class ShapeScannerRay : MonoBehaviour
private ShapeScanner _scanner; private ShapeScanner _scanner;
private MeshRenderer[] meshRenderers; private MeshRenderer[] meshRenderers;
private HashSet<GameObject> collidingObjects;
private bool _collisionRequired; private bool _collisionRequired;
void Awake() void Awake()
{ {
meshRenderers = GetComponentsInChildren<MeshRenderer>(); meshRenderers = GetComponentsInChildren<MeshRenderer>();
collidingObjects = new HashSet<GameObject>();
} }
// Update is called once per frame // Update is called once per frame
@@ -39,6 +41,10 @@ public class ShapeScannerRay : MonoBehaviour
private void OnTriggerEnter(Collider other) private void OnTriggerEnter(Collider other)
{ {
if (other.gameObject.tag == scannableTag) if (other.gameObject.tag == scannableTag)
{
collidingObjects.Add(other.gameObject);
// Only activate when this was the first object that entered collision
if (collidingObjects.Count == 1)
{ {
foreach (MeshRenderer meshRenderer in meshRenderers) foreach (MeshRenderer meshRenderer in meshRenderers)
{ {
@@ -47,17 +53,21 @@ public class ShapeScannerRay : MonoBehaviour
if (_collisionRequired) if (_collisionRequired)
{ {
_scanner.IncrementCorrectRayCount(); _scanner.IncrementCorrectRayCount();
} else }
else
{ {
_scanner.DecrementCorrectRayCount(); _scanner.DecrementCorrectRayCount();
} }
}
} }
} }
private void OnTriggerExit(Collider other) private void OnTriggerExit(Collider other)
{ {
if (other.gameObject.tag == "ShapeScannable") if (other.gameObject.tag == "ShapeScannable")
{
collidingObjects.Remove(other.gameObject);
if (collidingObjects.Count == 0)
{ {
foreach (MeshRenderer meshRenderer in meshRenderers) foreach (MeshRenderer meshRenderer in meshRenderers)
{ {
@@ -66,10 +76,17 @@ public class ShapeScannerRay : MonoBehaviour
if (_collisionRequired) if (_collisionRequired)
{ {
_scanner.DecrementCorrectRayCount(); _scanner.DecrementCorrectRayCount();
} else }
else
{ {
_scanner.IncrementCorrectRayCount(); _scanner.IncrementCorrectRayCount();
} }
} }
} }
}
public HashSet<GameObject> GetCollidingObjects()
{
return collidingObjects;
}
} }