x


RaycastHit, triangleIndex, and submeshes - which submesh?

A raycast hit will give you the triangle index hit. What if the mesh has submeshes? There is no submesh index.

Is it ok to assume that the triangle list is sorted such that the submesh is the one modulo the number of vertices in preceding lists?

In other words, lets say submesh 0 has 10 verts, submesh 1 has 15 verts, and submesh 2 has 12 verts. And the raycast hit says 'triangle index 12'

Does that mean submesh 1? IOW submesh 0 is from 0-9, submesh 1 is 10-24, and submesh2 is 25-37?

How do I map a material to the submesh?

more ▼

asked Jul 28 '12 at 01:16 AM

artie gravatar image

artie
192 6 7 10

(comments are locked)
10|3000 characters needed characters left

1 answer: sort voted first
  • main mesh contains all triangles of this mesh and also all that can be accessed via submeshes.
  • submeshes contains tris that can be accessed also via main mesh
  • submeshes are always exists in any mesh, at least one
  • sum of all submeshes tris is equal to main mesh tris
  • submeshes are used to apply different materials to tris

so finally, when you got from raycast hit to triangle index 50, you should search it in main mesh (it contains all tris including triangle 50), then get vertices for this triangle, and find triangle with those vertices in submeshes

bonus: MeshAnaliser.cs

using UnityEngine;
using System.Collections;
public class MeshAnaliser : MonoBehaviour
{
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            RaycastHit hit;
            if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit))
            {
                Mesh m = GetMesh(gameObject);
                if (m)
                {
                    int[] hittedTriangle = new int[] 
                    {
                        m.triangles[hit.triangleIndex * 3], 
                        m.triangles[hit.triangleIndex * 3 + 1], 
                        m.triangles[hit.triangleIndex * 3 + 2] 
                    };
                    for (int i = 0; i < m.subMeshCount; i++)
                    {
                        int[] subMeshTris = m.GetTriangles(i);
                        for (int j = 0; j < subMeshTris.Length; j += 3)
                        {
                            if (subMeshTris[j] == hittedTriangle[0] &&
                                subMeshTris[j + 1] == hittedTriangle[1] &&
                                subMeshTris[j + 2] == hittedTriangle[2])
                            {
                                Debug.Log(string.Format("triangle index:{0} submesh index:{1} submesh triangle index:{2}", hit.triangleIndex, i, j / 3));
                            }
                        }
                    }
                }
            }
        }
    }
    static Mesh GetMesh(GameObject go)
    {
        if (go)
        {
            MeshFilter mf = go.GetComponent<MeshFilter>();
            if (mf)
            {
                Mesh m = mf.sharedMesh;
                if (!m) { m = mf.mesh; }
                if (m)
                {
                    return m;
                }
            }
        }
        return (Mesh)null;
    }
}
more ▼

answered Jul 28 '12 at 11:23 AM

ScroodgeM gravatar image

ScroodgeM
7.6k 2 6

Well that helps some. At least I could find which submesh tri list it's in. How does the submesh index correspond to the material? Is there some mapping somewhere? My own tests show that the first submesh is NOT necessarily the first material in the list

Jul 31 '12 at 11:51 PM artie

This line:

MeshFilter mf = go.GetComponent();

should probably work better like this:

MeshFilter mf = go.GetComponent<MeshFilter>();

Damn that Qato!

Aug 01 '12 at 12:13 AM DaveA

@DaveA, you are right 8) thanks. Qato thinks that it was a tag 8)

Aug 01 '12 at 05:24 AM ScroodgeM

@art , how did you test material-to-submesh mapping? all materials with submeshes are mapped one-to-one. of course, if submeshes quantity and materials quantity are the same. if materials quantity is more then submeshes, all extra materials are drawn with last submesh. if materials quantity less then submeshes, submeshes are not drawn.

Aug 01 '12 at 05:28 AM ScroodgeM

I put a GUIText in and set the text of it to the triangle index (from the raycast hit, which comes from mouse position then screen-to-world) So mouse-over will tell me what triangle index I'm hitting. I also used Debug.DrawLine to hilight the triangle. I can see that if I'm on triangle 0, that it is not the first material in the list. I'll post screen shots tomorrow.

Aug 01 '12 at 06:58 AM artie
(comments are locked)
10|3000 characters needed characters left
Your answer
toggle preview:

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Topics:

x1535
x1366
x20

asked: Jul 28 '12 at 01:16 AM

Seen: 841 times

Last Updated: Aug 01 '12 at 04:36 PM