/* don't call inside a loop */ static int dm_tessface_to_poly_index(DerivedMesh *dm, int tessface_index) { if (tessface_index != ORIGINDEX_NONE) { /* double lookup */ const int *index_mf_to_mpoly; if ((index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX))) { const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); return DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, tessface_index); } } return ORIGINDEX_NONE; }
static void get_ccgdm_data(DerivedMesh *lodm, DerivedMesh *hidm, const int *index_mf_to_mpoly, const int *index_mp_to_orig, const int lvl, const int face_index, const float u, const float v, float co[3], float n[3]) { MFace mface; CCGElem **grid_data; CCGKey key; float crn_x, crn_y; int grid_size, S, face_side; int *grid_offset, g_index; lodm->getTessFace(lodm, face_index, &mface); grid_size = hidm->getGridSize(hidm); grid_data = hidm->getGridData(hidm); grid_offset = hidm->getGridOffset(hidm); hidm->getGridKey(hidm, &key); face_side = (grid_size << 1) - 1; if (lvl == 0) { g_index = grid_offset[face_index]; S = mdisp_rot_face_to_crn(mface.v4 ? 4 : 3, face_side, u * (face_side - 1), v * (face_side - 1), &crn_x, &crn_y); } else { int side = (1 << (lvl - 1)) + 1; int grid_index = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, face_index); int loc_offs = face_index % (1 << (2 * lvl)); int cell_index = loc_offs % ((side - 1) * (side - 1)); int cell_side = (grid_size - 1) / (side - 1); int row = cell_index / (side - 1); int col = cell_index % (side - 1); S = face_index / (1 << (2 * (lvl - 1))) - grid_offset[grid_index]; g_index = grid_offset[grid_index]; crn_y = (row * cell_side) + u * cell_side; crn_x = (col * cell_side) + v * cell_side; } CLAMP(crn_x, 0.0f, grid_size); CLAMP(crn_y, 0.0f, grid_size); if (n != NULL) interp_bilinear_grid(&key, grid_data[g_index + S], crn_x, crn_y, 0, n); if (co != NULL) interp_bilinear_grid(&key, grid_data[g_index + S], crn_x, crn_y, 1, co); }
/* compute uv coordinates of mouse in face */ static void imapaint_pick_uv(Scene *scene, Object *ob, unsigned int faceindex, const int xy[2], float uv[2]) { DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); MTFace *tf_base, *tf; Material *ma; TexPaintSlot *slot; int numfaces = dm->getNumTessFaces(dm), a, findex; float p[2], w[3], absw, minabsw; MFace mf; MVert mv[4]; float matrix[4][4], proj[4][4]; GLint view[4]; /* compute barycentric coordinates */ /* double lookup */ const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); if (index_mf_to_mpoly == NULL) { index_mp_to_orig = NULL; } /* get the needed opengl matrices */ glGetIntegerv(GL_VIEWPORT, view); glGetFloatv(GL_MODELVIEW_MATRIX, (float *)matrix); glGetFloatv(GL_PROJECTION_MATRIX, (float *)proj); view[0] = view[1] = 0; mul_m4_m4m4(matrix, matrix, ob->obmat); mul_m4_m4m4(matrix, proj, matrix); minabsw = 1e10; uv[0] = uv[1] = 0.0; /* test all faces in the derivedmesh with the original index of the picked face */ for (a = 0; a < numfaces; a++) { findex = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a) : a; if (findex == faceindex) { dm->getTessFace(dm, a, &mf); ma = dm->mat[mf.mat_nr]; slot = &ma->texpaintslot[ma->paint_active_slot]; dm->getVert(dm, mf.v1, &mv[0]); dm->getVert(dm, mf.v2, &mv[1]); dm->getVert(dm, mf.v3, &mv[2]); if (mf.v4) dm->getVert(dm, mf.v4, &mv[3]); if (!slot->uvname || !(tf_base = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, slot->uvname))) tf_base = CustomData_get_layer(&dm->faceData, CD_MTFACE); tf = &tf_base[a]; p[0] = xy[0]; p[1] = xy[1]; if (mf.v4) { /* the triangle with the largest absolute values is the one * with the most negative weights */ imapaint_tri_weights(matrix, view, mv[0].co, mv[1].co, mv[3].co, p, w); absw = fabsf(w[0]) + fabsf(w[1]) + fabsf(w[2]); if (absw < minabsw) { uv[0] = tf->uv[0][0] * w[0] + tf->uv[1][0] * w[1] + tf->uv[3][0] * w[2]; uv[1] = tf->uv[0][1] * w[0] + tf->uv[1][1] * w[1] + tf->uv[3][1] * w[2]; minabsw = absw; } imapaint_tri_weights(matrix, view, mv[1].co, mv[2].co, mv[3].co, p, w); absw = fabsf(w[0]) + fabsf(w[1]) + fabsf(w[2]); if (absw < minabsw) { uv[0] = tf->uv[1][0] * w[0] + tf->uv[2][0] * w[1] + tf->uv[3][0] * w[2]; uv[1] = tf->uv[1][1] * w[0] + tf->uv[2][1] * w[1] + tf->uv[3][1] * w[2]; minabsw = absw; } } else { imapaint_tri_weights(matrix, view, mv[0].co, mv[1].co, mv[2].co, p, w); absw = fabsf(w[0]) + fabsf(w[1]) + fabsf(w[2]); if (absw < minabsw) { uv[0] = tf->uv[0][0] * w[0] + tf->uv[1][0] * w[1] + tf->uv[2][0] * w[2]; uv[1] = tf->uv[0][1] * w[0] + tf->uv[1][1] * w[1] + tf->uv[2][1] * w[2]; minabsw = absw; } } } } dm->release(dm); }
/* compute uv coordinates of mouse in face */ void imapaint_pick_uv(Scene *scene, Object *ob, unsigned int faceindex, const int xy[2], float uv[2]) { DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); MTFace *tface = dm->getTessFaceDataArray(dm, CD_MTFACE), *tf; int numfaces = dm->getNumTessFaces(dm), a, findex; float p[2], w[3], absw, minabsw; MFace mf; MVert mv[4]; /* double lookup */ const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); if (index_mf_to_mpoly == NULL) { index_mp_to_orig = NULL; } minabsw = 1e10; uv[0] = uv[1] = 0.0; /* test all faces in the derivedmesh with the original index of the picked face */ for (a = 0; a < numfaces; a++) { findex = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a) : a; if (findex == faceindex) { dm->getTessFace(dm, a, &mf); dm->getVert(dm, mf.v1, &mv[0]); dm->getVert(dm, mf.v2, &mv[1]); dm->getVert(dm, mf.v3, &mv[2]); if (mf.v4) dm->getVert(dm, mf.v4, &mv[3]); tf = &tface[a]; p[0] = xy[0]; p[1] = xy[1]; if (mf.v4) { /* the triangle with the largest absolute values is the one * with the most negative weights */ imapaint_tri_weights(ob, mv[0].co, mv[1].co, mv[3].co, p, w); absw = fabsf(w[0]) + fabsf(w[1]) + fabsf(w[2]); if (absw < minabsw) { uv[0] = tf->uv[0][0] * w[0] + tf->uv[1][0] * w[1] + tf->uv[3][0] * w[2]; uv[1] = tf->uv[0][1] * w[0] + tf->uv[1][1] * w[1] + tf->uv[3][1] * w[2]; minabsw = absw; } imapaint_tri_weights(ob, mv[1].co, mv[2].co, mv[3].co, p, w); absw = fabsf(w[0]) + fabsf(w[1]) + fabsf(w[2]); if (absw < minabsw) { uv[0] = tf->uv[1][0] * w[0] + tf->uv[2][0] * w[1] + tf->uv[3][0] * w[2]; uv[1] = tf->uv[1][1] * w[0] + tf->uv[2][1] * w[1] + tf->uv[3][1] * w[2]; minabsw = absw; } } else { imapaint_tri_weights(ob, mv[0].co, mv[1].co, mv[2].co, p, w); absw = fabsf(w[0]) + fabsf(w[1]) + fabsf(w[2]); if (absw < minabsw) { uv[0] = tf->uv[0][0] * w[0] + tf->uv[1][0] * w[1] + tf->uv[2][0] * w[2]; uv[1] = tf->uv[0][1] * w[0] + tf->uv[1][1] * w[1] + tf->uv[2][1] * w[2]; minabsw = absw; } } } } dm->release(dm); }