-1

I am trying to have a gameobject in unity react with sound if another object is inside it. I want the gameobject to use the entering objects location to then see what voxel is closest and then play audio based on the voxel intensity/colour. Does anyone have any ideas? I am working with a dataset that is 512x256x512 voxels. I want it to work if the object is resized as well. Any help is much appreciated :).

The dataset I'm working with is a 3d .mhd medical scan of a body. Here is how the texture is added to the renderer on start:

for (int k = 0; k < NumberOfFrames; k++) {
    string fname_ = "T" + k.ToString("D2");
    Color[] colors = LoadData(Path.Combine (imageDir, fname_+".raw"));
    _volumeBuffer.Add (new Texture3D (dim [0], dim [1], dim [2], TextureFormat.RGBAHalf, mipmap));

    _volumeBuffer[k].SetPixels(colors);
    _volumeBuffer [k].Apply ();
}
GetComponent<Renderer>().material.SetTexture("_Data", _volumeBuffer[0]);

The size of the object is defined by using the mdh header files spacing as well as voxel dimensions:

transform.localScale = new Vector3(mhdheader.spacing[0] * volScale, mhdheader.spacing[1] * volScale * dim[1] / dim[0], mhdheader.spacing[2] * volScale * dim[2] / dim[0]);

I have tried making my own function to get the index from the world by offsetting it to the beginning of the render mesh (not sure if this is right). Then, scaling it by the local scale. Then, multiplying by the amount of voxels in each dimension. However, I am not sure if my logic is right whatsoever... Here is the code I tried:

public Vector3Int GetIndexFromWorld(Vector3 worldPos)
{
    Vector3 startOfTex = gameObject.GetComponent<Renderer>().bounds.min;
    Vector3 localPos = transform.InverseTransformPoint(worldPos);
    Vector3 localScale = gameObject.transform.localScale;
    Vector3 OffsetPos = localPos - startOfTex;

    Vector3 VoxelPosFloat = new Vector3(OffsetPos[0] / localScale[0], OffsetPos[1] / localScale[1], OffsetPos[2] / localScale[2]);
    VoxelPosFloat = Vector3.Scale(VoxelPosFloat, new Vector3(voxelDims[0], voxelDims[1], voxelDims[2]));
    Vector3Int voxelPos = Vector3Int.FloorToInt(VoxelPosFloat);
    return voxelPos;
}

2 Answers2

0

You can try setting up a large amount of box colliders and the OnTriggerEnter() function running on each. But a much better solution is to sort your array of voxels and then use simple math to clamp the moving objects position vector to ints and do some maths to map the vector to an index in the array. For example the vector (0,0,0) could map to voxels[0]. Then just fetch that voxels properties as you like. For a voxel application this would be a much needed faster calculation than colliders.

0

I figured it out I think. If anyone sees any flaw in my coding, please let me know :).

public Vector3Int GetIndexFromWorld(Vector3 worldPos)
{
    Vector3 deltaBounds = rend.bounds.max - rend.bounds.min;
    Vector3 OffsetPos = worldPos - rend.bounds.min;
    Vector3 normPos = new Vector3(OffsetPos[0] / deltaBounds[0], OffsetPos[1] / deltaBounds[1], OffsetPos[2] / deltaBounds[2]);

    Vector3 voxelPositions = new Vector3(normPos[0] * voxelDims[0], normPos[1] * voxelDims[1], normPos[2] * voxelDims[2]);

    Vector3Int voxelPos = Vector3Int.FloorToInt(voxelPositions);
    return voxelPos;
}