forked from bartvdbraak/blender
OpenSubdiv: Support for multiple materials in solid shading mode
Implementation is less optimal compared to non-opensubdiv drawing but it is now as good as we can do it without affecting on how patches are being created by OpenSubdiv.
This commit is contained in:
parent
50917edad5
commit
f1e68474e0
@ -135,8 +135,8 @@ void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl,
|
||||
/* Draw patches which corresponds to a given partition. */
|
||||
void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
|
||||
int fill_quads,
|
||||
int start_partition,
|
||||
int num_partitions);
|
||||
int start_patch,
|
||||
int num_patches);
|
||||
|
||||
/* ** Utility functions ** */
|
||||
int openSubdiv_supportGPUDisplay(void);
|
||||
|
@ -574,6 +574,17 @@ int openSubdiv_topologyRefinerGetNumFaces(
|
||||
return base_level.GetNumFaces();
|
||||
}
|
||||
|
||||
int openSubdiv_topologyRefinerGetNumFaceVerts(
|
||||
const OpenSubdiv_TopologyRefinerDescr *topology_refiner,
|
||||
int face)
|
||||
{
|
||||
using OpenSubdiv::Far::TopologyLevel;
|
||||
using OpenSubdiv::Far::TopologyRefiner;
|
||||
const TopologyRefiner *refiner = (const TopologyRefiner *)topology_refiner;
|
||||
const TopologyLevel &base_level = refiner->GetLevel(0);
|
||||
return base_level.GetFaceVertices(face).size();
|
||||
}
|
||||
|
||||
int openSubdiv_topologyRefnerCompareConverter(
|
||||
const OpenSubdiv_TopologyRefinerDescr *topology_refiner,
|
||||
OpenSubdiv_Converter *converter)
|
||||
|
@ -94,7 +94,7 @@ void openSubdiv_deleteTopologyRefinerDescr(
|
||||
OpenSubdiv_TopologyRefinerDescr *topology_refiner);
|
||||
|
||||
/* TODO(sergey): Those calls are not strictly related on conversion.
|
||||
* needs some dedicated fiel perhaps.
|
||||
* needs some dedicated file perhaps.
|
||||
*/
|
||||
|
||||
int openSubdiv_topologyRefinerGetSubdivLevel(
|
||||
@ -109,6 +109,10 @@ int openSubdiv_topologyRefinerGetNumEdges(
|
||||
int openSubdiv_topologyRefinerGetNumFaces(
|
||||
const OpenSubdiv_TopologyRefinerDescr *topology_refiner);
|
||||
|
||||
int openSubdiv_topologyRefinerGetNumFaceVerts(
|
||||
const OpenSubdiv_TopologyRefinerDescr *topology_refiner,
|
||||
int face);
|
||||
|
||||
int openSubdiv_topologyRefnerCompareConverter(
|
||||
const OpenSubdiv_TopologyRefinerDescr *topology_refiner,
|
||||
OpenSubdiv_Converter *converter);
|
||||
|
@ -575,46 +575,41 @@ static void finish_patchDraw(bool fill_quads)
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void draw_partition_patches_range(PartitionedGLMeshInterface *mesh,
|
||||
GLuint program,
|
||||
int start_partition,
|
||||
int num_partitions)
|
||||
int start_patch,
|
||||
int num_patches)
|
||||
{
|
||||
/* Glue patches from all partitions in the range together. */
|
||||
int patch_index = -1, start_element = -1, num_elements = 0;
|
||||
for (int partition = start_partition;
|
||||
partition < start_partition + num_partitions;
|
||||
++partition)
|
||||
{
|
||||
OsdDrawContext::PatchArrayVector const &patches =
|
||||
mesh->GetPatchArrays(partition);
|
||||
int traversed_patches = 0, num_remained_patches = num_patches;
|
||||
const OpenSubdiv::Osd::PatchArrayVector& patches =
|
||||
mesh->GetPatchTable()->GetPatchArrays();
|
||||
for (int i = 0; i < (int)patches.size(); ++i) {
|
||||
OsdDrawContext::PatchArray const &patch = patches[i];
|
||||
OsdDrawContext::PatchDescriptor desc = patch.GetDescriptor();
|
||||
OpenSubdiv::FarPatchTables::Type patchType = desc.GetType();
|
||||
if (patchType == OpenSubdiv::FarPatchTables::QUADS) {
|
||||
if (start_element == -1) {
|
||||
patch_index = patch.GetPatchIndex();
|
||||
start_element = patch.GetVertIndex();
|
||||
}
|
||||
const OpenSubdiv::Osd::PatchArray& patch = patches[i];
|
||||
OpenSubdiv::Far::PatchDescriptor desc = patch.GetDescriptor();
|
||||
OpenSubdiv::Far::PatchDescriptor::Type patchType = desc.GetType();
|
||||
|
||||
assert(patch.GetVertIndex() == start_element + num_elements);
|
||||
num_elements += patch.GetNumIndices();
|
||||
}
|
||||
else {
|
||||
assert(!"Discontinuitied are not supported yet.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Perform actual draw. */
|
||||
if (patchType == OpenSubdiv::Far::PatchDescriptor::QUADS) {
|
||||
const int num_block_patches = patch.GetNumPatches();
|
||||
if (start_patch >= traversed_patches &&
|
||||
start_patch < traversed_patches + num_block_patches)
|
||||
{
|
||||
const int num_control_verts = desc.GetNumControlVertices();
|
||||
const int start_draw_patch = start_patch - traversed_patches;
|
||||
const int num_draw_patches = std::min(num_remained_patches,
|
||||
num_block_patches - start_draw_patch);
|
||||
perform_drawElements(program,
|
||||
patch_index,
|
||||
num_elements,
|
||||
start_element);
|
||||
i,
|
||||
num_draw_patches * num_control_verts,
|
||||
patch.GetIndexBase() + start_draw_patch * num_control_verts);
|
||||
num_remained_patches -= num_draw_patches;
|
||||
}
|
||||
if (num_remained_patches == 0) {
|
||||
break;
|
||||
}
|
||||
traversed_patches += num_block_patches;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void draw_all_patches(PartitionedGLMeshInterface *mesh,
|
||||
GLuint program)
|
||||
@ -637,8 +632,8 @@ static void draw_all_patches(PartitionedGLMeshInterface *mesh,
|
||||
|
||||
void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
|
||||
int fill_quads,
|
||||
int start_partition,
|
||||
int num_partitions)
|
||||
int start_patch,
|
||||
int num_patches)
|
||||
{
|
||||
PartitionedGLMeshInterface *mesh =
|
||||
(PartitionedGLMeshInterface *)(gl_mesh->descriptor);
|
||||
@ -649,18 +644,11 @@ void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
|
||||
/* Setup GLSL/OpenGL to draw patches in current context. */
|
||||
GLuint program = preapre_patchDraw(mesh, fill_quads != 0);
|
||||
|
||||
if (start_partition != -1) {
|
||||
#if 0
|
||||
if (start_patch != -1) {
|
||||
draw_partition_patches_range(mesh,
|
||||
program,
|
||||
start_partition,
|
||||
num_partitions);
|
||||
#else
|
||||
(void)num_partitions;
|
||||
if(start_partition == 0) {
|
||||
draw_all_patches(mesh, program);
|
||||
}
|
||||
#endif
|
||||
start_patch,
|
||||
num_patches);
|
||||
}
|
||||
else {
|
||||
draw_all_patches(mesh, program);
|
||||
|
@ -215,6 +215,12 @@ bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss, bool use_osd_glsl);
|
||||
void ccgSubSurf_drawGLMesh(CCGSubSurf *ss, bool fill_quads,
|
||||
int start_partition, int num_partitions);
|
||||
|
||||
/* Get number of base faces in a particular GL mesh. */
|
||||
int ccgSubSurf_getNumGLMeshBaseFaces(CCGSubSurf *ss);
|
||||
|
||||
/* Get number of vertices in base faces in a particular GL mesh. */
|
||||
int ccgSubSurf_getNumGLMeshBaseFaceVerts(CCGSubSurf *ss, int face);
|
||||
|
||||
/* Controls whether CCG are needed (Cmeaning CPU evaluation) or fully GPU compute
|
||||
* and draw is allowed.
|
||||
*/
|
||||
|
@ -308,6 +308,31 @@ void ccgSubSurf_drawGLMesh(CCGSubSurf *ss, bool fill_quads,
|
||||
}
|
||||
}
|
||||
|
||||
int ccgSubSurf_getNumGLMeshBaseFaces(CCGSubSurf *ss)
|
||||
{
|
||||
const OpenSubdiv_TopologyRefinerDescr *topology_refiner;
|
||||
if (ss->osd_topology_refiner != NULL) {
|
||||
topology_refiner = ss->osd_topology_refiner;
|
||||
}
|
||||
else {
|
||||
topology_refiner = openSubdiv_getGLMeshTopologyRefiner(ss->osd_mesh);
|
||||
}
|
||||
return openSubdiv_topologyRefinerGetNumFaces(topology_refiner);
|
||||
}
|
||||
|
||||
/* Get number of vertices in base faces in a particular GL mesh. */
|
||||
int ccgSubSurf_getNumGLMeshBaseFaceVerts(CCGSubSurf *ss, int face)
|
||||
{
|
||||
const OpenSubdiv_TopologyRefinerDescr *topology_refiner;
|
||||
if (ss->osd_topology_refiner != NULL) {
|
||||
topology_refiner = ss->osd_topology_refiner;
|
||||
}
|
||||
else {
|
||||
topology_refiner = openSubdiv_getGLMeshTopologyRefiner(ss->osd_mesh);
|
||||
}
|
||||
return openSubdiv_topologyRefinerGetNumFaceVerts(topology_refiner, face);
|
||||
}
|
||||
|
||||
void ccgSubSurf_setSkipGrids(CCGSubSurf *ss, bool skip_grids)
|
||||
{
|
||||
ss->skip_grids = skip_grids;
|
||||
|
@ -2622,24 +2622,72 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)
|
||||
#ifdef WITH_OPENSUBDIV
|
||||
if (ccgdm->useGpuBackend) {
|
||||
CCGSubSurf *ss = ccgdm->ss;
|
||||
DMFlagMat *faceFlags = ccgdm->faceFlags;
|
||||
int new_matnr;
|
||||
bool draw_smooth;
|
||||
const DMFlagMat *faceFlags = ccgdm->faceFlags;
|
||||
const int level = ccgSubSurf_getSubdivisionLevels(ss);
|
||||
const int face_side = 1 << level;
|
||||
const int grid_side = 1 << (level - 1);
|
||||
const int face_patches = face_side * face_side;
|
||||
const int grid_patches = grid_side * grid_side;
|
||||
const int num_base_faces = ccgSubSurf_getNumGLMeshBaseFaces(ss);
|
||||
int i, current_patch = 0;
|
||||
int mat_nr = -1;
|
||||
bool draw_smooth = false;
|
||||
int start_draw_patch = -1, num_draw_patches = 0;
|
||||
if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, setMaterial != NULL) == false)) {
|
||||
return;
|
||||
}
|
||||
/* TODO(sergey): Single matierial currently. */
|
||||
if (setMaterial == NULL) {
|
||||
ccgSubSurf_drawGLMesh(ss,
|
||||
true,
|
||||
-1,
|
||||
-1);
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < num_base_faces; ++i) {
|
||||
const int num_face_verts = ccgSubSurf_getNumGLMeshBaseFaceVerts(ss, i);
|
||||
const int num_patches = (num_face_verts == 4) ? face_patches
|
||||
: num_face_verts * grid_patches;
|
||||
int new_matnr;
|
||||
bool new_draw_smooth;
|
||||
if (faceFlags) {
|
||||
draw_smooth = (faceFlags[0].flag & ME_SMOOTH);
|
||||
new_matnr = (faceFlags[0].mat_nr + 1);
|
||||
new_draw_smooth = (faceFlags[i].flag & ME_SMOOTH);
|
||||
new_matnr = (faceFlags[i].mat_nr + 1);
|
||||
}
|
||||
else {
|
||||
draw_smooth = true;
|
||||
new_draw_smooth = true;
|
||||
new_matnr = 1;
|
||||
}
|
||||
if (setMaterial && setMaterial(new_matnr, NULL)) {
|
||||
if (new_draw_smooth != draw_smooth || new_matnr != mat_nr) {
|
||||
if (num_draw_patches != 0) {
|
||||
bool do_draw = setMaterial == NULL ||
|
||||
setMaterial(mat_nr, NULL);
|
||||
if (do_draw) {
|
||||
glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT);
|
||||
ccgSubSurf_drawGLMesh(ss, true, -1, -1);
|
||||
ccgSubSurf_drawGLMesh(ss,
|
||||
true,
|
||||
start_draw_patch,
|
||||
num_draw_patches);
|
||||
}
|
||||
}
|
||||
start_draw_patch = current_patch;
|
||||
num_draw_patches = num_patches;
|
||||
mat_nr = new_matnr;
|
||||
draw_smooth = new_draw_smooth;
|
||||
}
|
||||
else {
|
||||
num_draw_patches += num_patches;
|
||||
}
|
||||
current_patch += num_patches;
|
||||
}
|
||||
if (num_draw_patches != 0) {
|
||||
bool do_draw = setMaterial(mat_nr, NULL);
|
||||
if (do_draw) {
|
||||
glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT);
|
||||
ccgSubSurf_drawGLMesh(ss,
|
||||
true,
|
||||
start_draw_patch,
|
||||
num_draw_patches);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -4528,8 +4576,7 @@ static void set_ccgdm_gpu_geometry(CCGDerivedMesh *ccgdm, DerivedMesh *dm)
|
||||
|
||||
for (index = 0; index < totface; index++) {
|
||||
faceFlags->flag = mpoly ? mpoly[index].flag : 0;
|
||||
/* faceFlags->mat_nr = mpoly ? mpoly[index].mat_nr : 0; */
|
||||
faceFlags->mat_nr = 0;
|
||||
faceFlags->mat_nr = mpoly ? mpoly[index].mat_nr : 0;
|
||||
faceFlags++;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user