Add different material to top face of mesh with varying CSG subtractions

r145

Hi, these forums and SO have been incredibly helpful so far, but I’m stuck on the final piece of a personal project.

I start with a mesh using THREE.BoxGeometry where I use an array of materials (one for the top face and another for all other faces).

I then use manthrax’s THREE-CSGMesh to create a new non-indexed mesh by subtracting a smaller mesh from my starter mesh.

Below are the desired results that I have so far, but I’ve hardcoded (through trial and error) the vertex indices when using geometry.addGroup().

const vertices = csg_result.geometry.getAttribute('position').array
const vert_count = vertices.length

//successful trial and error vertex indices for one cube subtraction
const start = 84
const mid = 30
const end = 114

//vertex indices for two cube subtractions
//const start = 150
//const mid = 60
//const end = 210

csg_result.geometry.clearGroups()
csg_result.geometry.addGroup( 0, start, 0 )
csg_result.geometry.addGroup( start, mid, 1 )
csg_result.geometry.addGroup( end, vert_count, 0 )

const materials = [
        dirt_material,
        pdf_material,
    ]

csg_result.material = materials

2022-10-11_16-13-27

With constant variables, the top material will not be applied correctly if I were to make more cube subtractions or subtractions using different geometry types (which makes sense).

I’m using the y-up coordinate system and I assumed the vertices that create the triangles on the top face would always have a local position.y value of 7.5. However, the log below shows the vertex data at the current working indices (84 - 114) and that doesn’t seem to be the case.

Sorry for the novel…Does anyone have any ideas on how I can parse geometry.getAttribute('position').array to identify the correct range of vertices for only the top face? There’s a good chance I’m missing something here or doing something wrong, so let me know if that’s the case.

Thanks.

I figured it out. I realized geometry.getAttribute('position').array provides the XYZ coordinates in a one-dimensional array. My mistake was not iterating in sets of three for the vertices and then again for the triangles to test the y-values.

const vertex_data = csg_result.geometry.getAttribute('position').array
const data_count = vertex_data.length
let group_start_index = null
let group_end_index = null
let start_status = false

for (let i = 8; i <= data_count; i+=9) {
    const v1 = [vertex_data[i - 8], vertex_data[i - 7], vertex_data[i - 6]]
    const v2 = [vertex_data[i - 5], vertex_data[i - 4], vertex_data[i - 3]]
    const v3 = [vertex_data[i - 2], vertex_data[i - 1], vertex_data[i - 0]]

    if (group_start_index == null && v1[2] == 7.5 && v2[2] == 7.5 && v3[2] == 7.5) { // top of mesh always at position.y 7.5
        group_start_index = (i - 8) / 3
        start_status = true
    }

    if (start_status && group_end_index == null) {
        if (v1[2] != 7.5 || v2[2] != 7.5 || v3[2] != 7.5) {
            group_end_index = (i - 8) / 3
        }
    }
}

csg_result.geometry.clearGroups()
csg_result.geometry.addGroup( 0, group_start_index, 0 )
csg_result.geometry.addGroup( group_start_index, group_end_index - group_start_index, 1 )
csg_result.geometry.addGroup( group_end_index, data_count / 3, 0 )

const materials = [
    dirt_material,
    pdf_material,
];

csg_result.material = materials