Hello all: I am using vuforia to instantiate a 3d object once it finds a proper imageTarget (info not completely relevant since the problem is not related to Vuforia).
My questions is this: Once I instantiate a Prefab (clone) of an object, I need it to fit inside the boxcollider of the gameObject representing the image Target.
Unfortunately I can’t control the quality of the imported objects to standarize the size because they are created by different users in different systems, all I get is the .OBJ file.
Therefore, whenever I run the app, some of my 3d models appear insanely large, others very small.
I’ve read all the available answers about this issue but I just can’t seem to find the right solution to my problem. Any help will be greatly appreciated.
More than likely the source files were created in centimeters or inches and then exported without taking the scale unit of unity (meters) into account. First identify if this is the case, then you could write code that would check the scale of the import and adjust it if necessary. Conversely you could mandate a process for your contributors that uses meters and proper scale.
No, there is almost certainly a way to code for a scale correction. You would first have to know what a potentially wrong scale would be. Perhaps a line of code that checks to see if the character’s scale falls out of a particular range. You may have to use something like a raycast to measure the modle to find its relative height then scale appropriately. For further info you should post some screen shots or something more to go on.
Screenshots - ok. The first creenshot shows the CloudReco object, on top of it is the BoxCollider delimiting the ideal size of the 3d object, and leftmost is the object I want to fit inside the cube.
private void OnTrackingFound()
{
Renderer[] rendererComponents = GetComponentsInChildren<Renderer>(true);
Collider[] colliderComponents = GetComponentsInChildren<Collider>(true);
Debug.Log("Trackable " + mTrackableBehaviour.TrackableName + " found");
if (controladorPanel.panelVisibile)
{
return;
}
infoUnit pregunta = valoresEstaticos.currentProject.getInfoUnitByTargetName (mTrackableBehaviour.Trackable.Name);
if (pregunta == null) //no tenemos ninguna infoUnit acerca de este trackable
return;
if (pregunta.vuforiaTargetName == mTrackableBehaviour.Trackable.Name)
{
print ("TrackableName: " + mTrackableBehaviour.Trackable.Name);
//ve por la pregunta y despliega el panel con la pregunta.
GameObject modelo = (GameObject) Instantiate (Resources.Load ("Prefabs/" + pregunta.modelName), PuntoAparicion.transform.position, PuntoAparicion.transform.rotation); //PuntoAparicion = an object at the center of the boxcollider
modelo.transform.SetParent (mTrackableBehaviour.transform);
modelo.transform.localScale += mTrackableBehaviour.transform.lossyScale; // new Vector3 (1f, 1f, 1f);
//modelo.transform.localScale += Vector3.one * height / 8f;
modelo.SetActive (true);
modelo.name = "modelo";
}
}
Screenshot 2: shows the actual screen when the image target is found. You can only see the inner elements of the 3d model, because its size is immense.
So what is the scale of that object when it is imported? Look at the model panel of the inspector window. If the model was created in centimeters and exported without the correction to the FBX then the scale will be exactly 100 times the correct size. Scale it down to .01 and if that fixes it then you know what to do with your code to make future corrections.
If you have a really variable set of models where you have no idea if they are ever going to modeled correctly or not I suppose you could put a function in start() that raycasts from the camera and if it detects the model before it detects the bounding box then it scales the model down. Again, it would be better if you just had a standardized modeling practice, but that would be a viable hack.
The scale of this particular object is 0.00345 — but the scale of others is 2 (for example).
Like I said, I have no control over the 3d models, they are created by different teams, different programs… I got them all to agree on the OBJ format, I doubt I can convince 50 different teams to utilize same scale and metric systems
My problem is not manually scaling them, my problem is that when I spawn them they appear with localScale 0.0.0 and “scaling” them according to the scale of the boxCollider gives the result you saw in screenshot 2 - on the other hand, It’s not practical to “hardcode” the appropiate scale for each model.
The models are not in scene until the user identifies an augmented reality target, and then they are spawned…I am not experienced enough to create that raycast method you are describing
Thanks for your valuable input, I hope we can find a solution to my dilemma.
Say you have targetArea which is the box you want to fit things into, and model which is the box you’re putting in there. Then it’d be something like:
var targetCollider = targetArea.GetComponent<BoxCollider>();
var modelMesh = model.GetComponent<MeshRenderer>().sharedMesh;
var targetScale = targetCollider.bounds.size;
var modelScale = modelMesh.bounds.size,
// we want to re-size the model to fit in the target. But since we don't know the shape of the model,
// and we don't want to stretch it, we want to resize it to the smallest of the x, y and z differences in
// scale between the target and the model
var xFraction = modelScale / targetScale;
var yFraction = modelScale / targetScale;
var zFraction = modelScale / targetScale;
var fraction = Mathf.Min(xFraction, yFraction, zFraction);
//Honestly it's late and I'm too tired to see if you need to multiply or divide here. It's one of those. :P
model.transform.localScale /= fraction;
You’ll need to do some adjustments for your case, but that’s the basic idea. Note that collider.bounds and mesh.bounds is the same concept, an axis alligned box that fits the entire thing, just for colliders or bounds.
If you’re going long term, you’ll want something more complex. This solution will make things that have a shape that’s closer to the square be scaled up larger, while oblong things will be scaled smaller. You can experiment with using the average of the fractions or whatnot.
Final piece of advice - you should really use English for variable and method names, so other non-Spanish people can read your code. You’ll have a lot of trouble getting help or advice - I have no idea what half your code’s supposed to do, since I can’t read it.