forked from bartvdbraak/blender
OpenSubdiv: Initial work to support UV maps in textured OSD viewport
A bit work in progress, currently the following limitations: - Texture shading only, Material shading will come later - No UVs subdivision yet - Always uses active UV and currently changing active UV will not properly update the viewport. Well, need to start somewhere :)
This commit is contained in:
parent
9a0634a253
commit
f0f60d775d
@ -67,6 +67,7 @@
|
||||
|
||||
#include <opensubdiv/osd/glPatchTable.h>
|
||||
#include <opensubdiv/far/stencilTable.h>
|
||||
#include <opensubdiv/far/primvarRefiner.h>
|
||||
|
||||
#include "opensubdiv_intern.h"
|
||||
#include "opensubdiv_topology_refiner.h"
|
||||
@ -143,11 +144,69 @@ typedef Mesh<GLVertexBuffer,
|
||||
GLPatchTable> OsdGLSLComputeMesh;
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
struct FVarVertex {
|
||||
float u, v;
|
||||
void Clear() {
|
||||
u = v = 0.0f;
|
||||
}
|
||||
void AddWithWeight(FVarVertex const & src, float weight) {
|
||||
u += weight * src.u;
|
||||
v += weight * src.v;
|
||||
}
|
||||
};
|
||||
|
||||
static void interpolate_fvar_data(OpenSubdiv::Far::TopologyRefiner& refiner,
|
||||
const std::vector<float> uvs,
|
||||
std::vector<float> &fvar_data) {
|
||||
/* TODO(sergey): Support all FVar channels. */
|
||||
const int channel = 0;
|
||||
/* TODO(sergey): Make it somehow more generic way. */
|
||||
const int fvar_width = 2;
|
||||
|
||||
int max_level = refiner.GetMaxLevel(),
|
||||
num_values_max = refiner.GetLevel(max_level).GetNumFVarValues(channel),
|
||||
num_values_total = refiner.GetNumFVarValuesTotal(channel);
|
||||
if (num_values_total <= 0) {
|
||||
return;
|
||||
}
|
||||
OpenSubdiv::Far::PrimvarRefiner primvarRefiner(refiner);
|
||||
if (refiner.IsUniform()) {
|
||||
/* For uniform we only keep the highest level of refinement. */
|
||||
fvar_data.resize(num_values_max * fvar_width);
|
||||
std::vector<FVarVertex> buffer(num_values_total - num_values_max);
|
||||
FVarVertex *src = &buffer[0];
|
||||
memcpy(src, &uvs[0], uvs.size() * sizeof(float));
|
||||
/* Defer the last level to treat separately with its alternate
|
||||
* destination.
|
||||
*/
|
||||
for (int level = 1; level < max_level; ++level) {
|
||||
FVarVertex *dst = src + refiner.GetLevel(level-1).GetNumFVarValues(channel);
|
||||
primvarRefiner.InterpolateFaceVarying(level, src, dst, channel);
|
||||
src = dst;
|
||||
}
|
||||
FVarVertex *dst = reinterpret_cast<FVarVertex *>(&fvar_data[0]);
|
||||
primvarRefiner.InterpolateFaceVarying(max_level, src, dst, channel);
|
||||
} else {
|
||||
/* For adaptive we keep all levels. */
|
||||
fvar_data.resize(num_values_total * fvar_width);
|
||||
FVarVertex *src = reinterpret_cast<FVarVertex *>(&fvar_data[0]);
|
||||
memcpy(src, &uvs[0], uvs.size() * sizeof(float));
|
||||
for (int level = 1; level <= max_level; ++level) {
|
||||
FVarVertex *dst = src + refiner.GetLevel(level-1).GetNumFVarValues(channel);
|
||||
primvarRefiner.InterpolateFaceVarying(level, src, dst, channel);
|
||||
src = dst;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
|
||||
OpenSubdiv_TopologyRefinerDescr *topology_refiner,
|
||||
int evaluator_type,
|
||||
int level,
|
||||
int /*subdivide_uvs*/)
|
||||
int level)
|
||||
{
|
||||
using OpenSubdiv::Far::TopologyRefiner;
|
||||
|
||||
@ -213,11 +272,21 @@ struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
|
||||
gl_mesh->descriptor = (OpenSubdiv_GLMeshDescr *) mesh;
|
||||
gl_mesh->topology_refiner = topology_refiner;
|
||||
|
||||
if (refiner->GetNumFVarChannels() > 0) {
|
||||
std::vector<float> fvar_data;
|
||||
interpolate_fvar_data(*refiner, topology_refiner->uvs, fvar_data);
|
||||
openSubdiv_osdGLAllocFVar(gl_mesh, &fvar_data[0]);
|
||||
}
|
||||
else {
|
||||
gl_mesh->fvar_data = NULL;
|
||||
}
|
||||
|
||||
return gl_mesh;
|
||||
}
|
||||
|
||||
void openSubdiv_deleteOsdGLMesh(struct OpenSubdiv_GLMesh *gl_mesh)
|
||||
{
|
||||
openSubdiv_osdGLDestroyFVar(gl_mesh);
|
||||
switch (gl_mesh->evaluator_type) {
|
||||
#define CHECK_EVALUATOR_TYPE(type, class) \
|
||||
case OPENSUBDIV_EVALUATOR_ ## type: \
|
||||
|
@ -32,16 +32,19 @@ extern "C" {
|
||||
|
||||
// Types declaration.
|
||||
struct OpenSubdiv_GLMesh;
|
||||
struct OpenSubdiv_GLMeshFVarData;
|
||||
struct OpenSubdiv_TopologyRefinerDescr;
|
||||
|
||||
typedef struct OpenSubdiv_GLMesh OpenSubdiv_GLMesh;
|
||||
|
||||
#ifdef __cplusplus
|
||||
struct OpenSubdiv_GLMeshDescr;
|
||||
|
||||
typedef struct OpenSubdiv_GLMesh {
|
||||
int evaluator_type;
|
||||
OpenSubdiv_GLMeshDescr *descriptor;
|
||||
OpenSubdiv_TopologyRefinerDescr *topology_refiner;
|
||||
OpenSubdiv_GLMeshFVarData *fvar_data;
|
||||
} OpenSubdiv_GLMesh;
|
||||
#endif
|
||||
|
||||
@ -66,8 +69,7 @@ enum {
|
||||
OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
|
||||
struct OpenSubdiv_TopologyRefinerDescr *topology_refiner,
|
||||
int evaluator_type,
|
||||
int level,
|
||||
int subdivide_uvs);
|
||||
int level);
|
||||
|
||||
void openSubdiv_deleteOsdGLMesh(OpenSubdiv_GLMesh *gl_mesh);
|
||||
unsigned int openSubdiv_getOsdGLMeshPatchIndexBuffer(
|
||||
@ -129,8 +131,7 @@ void openSubdiv_evaluateVarying(OpenSubdiv_EvaluatorDescr *evaluator_descr,
|
||||
*
|
||||
* TODO(sergey): Some of the stuff could be initialized once for all meshes.
|
||||
*/
|
||||
void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl,
|
||||
int active_uv_index);
|
||||
void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl);
|
||||
|
||||
/* Draw specified patches. */
|
||||
void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
|
||||
@ -138,6 +139,10 @@ void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
|
||||
int start_patch,
|
||||
int num_patches);
|
||||
|
||||
void openSubdiv_osdGLAllocFVar(OpenSubdiv_GLMesh *gl_mesh,
|
||||
const float *fvar_data);
|
||||
void openSubdiv_osdGLDestroyFVar(OpenSubdiv_GLMesh *gl_mesh);
|
||||
|
||||
/* ** Utility functions ** */
|
||||
int openSubdiv_supportGPUDisplay(void);
|
||||
int openSubdiv_getAvailableEvaluators(void);
|
||||
|
@ -488,6 +488,39 @@ inline void TopologyRefinerFactory<OpenSubdiv_Converter>::reportInvalidTopology(
|
||||
printf("OpenSubdiv Error: %s\n", msg);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool TopologyRefinerFactory<OpenSubdiv_Converter>::assignFaceVaryingTopology(
|
||||
TopologyRefiner& refiner,
|
||||
const OpenSubdiv_Converter& conv)
|
||||
{
|
||||
if (conv.get_num_uv_layers(&conv) <= 0) {
|
||||
/* No UV maps, we can skip any face-varying data. */
|
||||
return true;
|
||||
}
|
||||
/* Count overall number of UV data.
|
||||
* NOTE: We only do single UV layer here, and we don't "merge" loops
|
||||
* together as it is done in OpenSubdiv examples.x
|
||||
*/
|
||||
const int num_faces = getNumBaseFaces(refiner);
|
||||
int num_uvs = 0;
|
||||
for (int face = 0; face < num_faces; ++face) {
|
||||
IndexArray face_verts = getBaseFaceVertices(refiner, face);
|
||||
num_uvs += face_verts.size();
|
||||
}
|
||||
/* Fill in actual UV offsets. */
|
||||
const int channel = createBaseFVarChannel(refiner, num_uvs);
|
||||
for (int face = 0, offset = 0; face < num_faces; ++face) {
|
||||
Far::IndexArray dst_face_uvs = getBaseFaceFVarValues(refiner,
|
||||
face,
|
||||
channel);
|
||||
for (int corner = 0; corner < dst_face_uvs.size(); ++corner) {
|
||||
dst_face_uvs[corner] = offset;
|
||||
++offset;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} /* namespace Far */
|
||||
} /* namespace OPENSUBDIV_VERSION */
|
||||
} /* namespace OpenSubdiv */
|
||||
@ -508,6 +541,33 @@ OpenSubdiv::Sdc::SchemeType get_capi_scheme_type(OpenSubdiv_SchemeType type)
|
||||
return OpenSubdiv::Sdc::SCHEME_CATMARK;
|
||||
}
|
||||
|
||||
static void import_fvar_data(OpenSubdiv_TopologyRefinerDescr *result,
|
||||
const OpenSubdiv_Converter& conv)
|
||||
{
|
||||
const int num_layers = conv.get_num_uv_layers(&conv),
|
||||
num_faces = conv.get_num_faces(&conv);
|
||||
/* Pre-allocate values in one go. */
|
||||
int num_fvar_values = 0;
|
||||
for (int layer = 0; layer < num_layers; ++layer) {
|
||||
num_fvar_values = result->osd_refiner->GetNumFVarValuesTotal();
|
||||
}
|
||||
result->uvs.resize(num_fvar_values * 2);
|
||||
/* Fill in all channels. */
|
||||
for (int layer = 0, offset = 0; layer < num_layers; ++layer) {
|
||||
for (int face = 0; face < num_faces; ++face) {
|
||||
const int num_verts = conv.get_num_face_verts(&conv, face);
|
||||
for (int vert = 0; vert < num_verts; ++vert) {
|
||||
float uv[2];
|
||||
conv.get_face_corner_uv(&conv, face, vert, uv);
|
||||
result->uvs[offset++] = uv[0];
|
||||
result->uvs[offset++] = uv[1];
|
||||
}
|
||||
}
|
||||
/* TODO(sergey): Currently we only support first layer only. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace */
|
||||
|
||||
struct OpenSubdiv_TopologyRefinerDescr *openSubdiv_createTopologyRefinerDescr(
|
||||
@ -536,6 +596,18 @@ struct OpenSubdiv_TopologyRefinerDescr *openSubdiv_createTopologyRefinerDescr(
|
||||
TopologyRefinerFactory<OpenSubdiv_Converter>::Create(
|
||||
*converter,
|
||||
topology_options);
|
||||
|
||||
if (result->osd_refiner->GetNumFVarChannels() > 0) {
|
||||
/* Import face varrying data now since later we wouldn't have
|
||||
* access to the converter.
|
||||
*
|
||||
* TODO(sergey): This is so-called "for now", for until we'll
|
||||
* find better way to plug OSD to Blender or for until something
|
||||
* happens inside of OSD API.
|
||||
*/
|
||||
import_fvar_data(result, *converter);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -83,6 +83,14 @@ typedef struct OpenSubdiv_Converter {
|
||||
int vert,
|
||||
int *vert_faces);
|
||||
|
||||
/* Face-varying data. */
|
||||
|
||||
int (*get_num_uv_layers)(const OpenSubdiv_Converter *converter);
|
||||
void (*get_face_corner_uv)(const OpenSubdiv_Converter *converter,
|
||||
int face,
|
||||
int corner,
|
||||
float r_uv[2]);
|
||||
|
||||
void (*free_user_data)(const OpenSubdiv_Converter *converter);
|
||||
void *user_data;
|
||||
} OpenSubdiv_Converter;
|
||||
|
@ -42,6 +42,10 @@
|
||||
#include <opensubdiv/osd/cpuGLVertexBuffer.h>
|
||||
#include <opensubdiv/osd/cpuEvaluator.h>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "opensubdiv_capi.h"
|
||||
|
||||
using OpenSubdiv::Osd::GLMeshInterface;
|
||||
|
||||
extern "C" char datatoc_gpu_shader_opensubd_display_glsl[];
|
||||
@ -78,7 +82,6 @@ typedef struct Transform {
|
||||
} Transform;
|
||||
|
||||
static bool g_use_osd_glsl = false;
|
||||
static int g_active_uv_index = -1;
|
||||
|
||||
static GLuint g_flat_fill_solid_program = 0;
|
||||
static GLuint g_flat_fill_texture2d_program = 0;
|
||||
@ -90,6 +93,59 @@ static GLuint g_lighting_ub = 0;
|
||||
static Lighting g_lighting_data;
|
||||
static Transform g_transform;
|
||||
|
||||
struct OpenSubdiv_GLMeshFVarData
|
||||
{
|
||||
OpenSubdiv_GLMeshFVarData() :
|
||||
texture_buffer(0) {
|
||||
}
|
||||
|
||||
~OpenSubdiv_GLMeshFVarData()
|
||||
{
|
||||
Release();
|
||||
}
|
||||
|
||||
void Release()
|
||||
{
|
||||
if (texture_buffer) {
|
||||
glDeleteTextures(1, &texture_buffer);
|
||||
}
|
||||
texture_buffer = 0;
|
||||
}
|
||||
|
||||
void Create(const OpenSubdiv::Far::PatchTable *patch_table,
|
||||
int fvarWidth,
|
||||
const float *fvar_src_data)
|
||||
{
|
||||
Release();
|
||||
OpenSubdiv::Far::ConstIndexArray indices = patch_table->GetFVarValues();
|
||||
|
||||
// expand fvardata to per-patch array
|
||||
std::vector<float> data;
|
||||
data.reserve(indices.size() * fvarWidth);
|
||||
|
||||
for (int fvert = 0; fvert < (int)indices.size(); ++fvert) {
|
||||
int index = indices[fvert] * fvarWidth;
|
||||
for (int i = 0; i < fvarWidth; ++i) {
|
||||
data.push_back(fvar_src_data[index++]);
|
||||
}
|
||||
}
|
||||
GLuint buffer;
|
||||
glGenBuffers(1, &buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, data.size()*sizeof(float),
|
||||
&data[0], GL_STATIC_DRAW);
|
||||
|
||||
glGenTextures(1, &texture_buffer);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, texture_buffer);
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, buffer);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, 0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
glDeleteBuffers(1, &buffer);
|
||||
}
|
||||
GLuint texture_buffer;
|
||||
};
|
||||
|
||||
/* TODO(sergey): This is actually duplicated code from BLI. */
|
||||
namespace {
|
||||
void copy_m3_m3(float m1[3][3], float m2[3][3])
|
||||
@ -307,8 +363,7 @@ GLuint linkProgram(const char *version, const char *define)
|
||||
return program;
|
||||
}
|
||||
|
||||
void bindProgram(GLMeshInterface * /*mesh*/,
|
||||
int program)
|
||||
void bindProgram(OpenSubdiv_GLMesh *gl_mesh, int program)
|
||||
{
|
||||
glUseProgram(program);
|
||||
|
||||
@ -352,23 +407,16 @@ void bindProgram(GLMeshInterface * /*mesh*/,
|
||||
glUniform4fv(glGetUniformLocation(program, "diffuse"), 1, color);
|
||||
}
|
||||
|
||||
/* TODO(sergey): Bring face varying back. */
|
||||
#if 0
|
||||
/* Face-vertex data */
|
||||
if (mesh->GetDrawContext()->GetFvarDataTextureBuffer()) {
|
||||
if (gl_mesh->fvar_data != NULL && gl_mesh->fvar_data->texture_buffer) {
|
||||
glActiveTexture(GL_TEXTURE31);
|
||||
glBindTexture(GL_TEXTURE_BUFFER,
|
||||
mesh->GetDrawContext()->GetFvarDataTextureBuffer());
|
||||
glBindTexture(GL_TEXTURE_BUFFER, gl_mesh->fvar_data->texture_buffer);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* TODO(sergey): Bring face varying back. */
|
||||
glUniform1i(glGetUniformLocation(program, "osd_fvar_count"),
|
||||
0/* * mesh->GetFVarCount()*/);
|
||||
|
||||
glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"),
|
||||
g_active_uv_index * 2);
|
||||
/* See notes below about why we use such values. */
|
||||
glUniform1i(glGetUniformLocation(program, "osd_fvar_count"), 2);
|
||||
glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"), 0);
|
||||
}
|
||||
|
||||
} /* namespace */
|
||||
@ -455,11 +503,9 @@ void openSubdiv_osdGLDisplayDeinit(void)
|
||||
}
|
||||
}
|
||||
|
||||
void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl,
|
||||
int active_uv_index)
|
||||
void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl)
|
||||
{
|
||||
g_use_osd_glsl = use_osd_glsl != 0;
|
||||
g_active_uv_index = active_uv_index;
|
||||
|
||||
/* Update transformation matrices. */
|
||||
glGetFloatv(GL_PROJECTION_MATRIX, g_transform.projection_matrix);
|
||||
@ -516,7 +562,7 @@ void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl,
|
||||
}
|
||||
}
|
||||
|
||||
static GLuint prepare_patchDraw(GLMeshInterface *mesh,
|
||||
static GLuint prepare_patchDraw(OpenSubdiv_GLMesh *gl_mesh,
|
||||
bool fill_quads)
|
||||
{
|
||||
GLint program = 0;
|
||||
@ -531,28 +577,31 @@ static GLuint prepare_patchDraw(GLMeshInterface *mesh,
|
||||
glUniform1i(location, model == GL_FLAT);
|
||||
}
|
||||
|
||||
/* TODO(sergey): Bring this back. */
|
||||
#if 0
|
||||
/* Face-vertex data */
|
||||
if (mesh->GetDrawContext()->GetFvarDataTextureBuffer()) {
|
||||
if (gl_mesh->fvar_data != NULL &&
|
||||
gl_mesh->fvar_data->texture_buffer)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE31);
|
||||
glBindTexture(GL_TEXTURE_BUFFER,
|
||||
mesh->GetDrawContext()->GetFvarDataTextureBuffer());
|
||||
gl_mesh->fvar_data->texture_buffer);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
GLint location = glGetUniformLocation(program, "osd_fvar_count");
|
||||
if (location != -1) {
|
||||
glUniform1i(location, mesh->GetFVarCount());
|
||||
/* TODO(sergey): This is width of FVar data, which happened to be 2. */
|
||||
glUniform1i(location, 2);
|
||||
}
|
||||
|
||||
location = glGetUniformLocation(program, "osd_active_uv_offset");
|
||||
if (location != -1) {
|
||||
glUniform1i(location,
|
||||
g_active_uv_index * 2);
|
||||
/* TODO(sergey): Since we only store single UV channel
|
||||
* we can always suuppose offset is 0.
|
||||
*
|
||||
* Ideally it should be active UV index times 2.
|
||||
*/
|
||||
glUniform1i(location, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
return program;
|
||||
}
|
||||
@ -584,7 +633,7 @@ static GLuint prepare_patchDraw(GLMeshInterface *mesh,
|
||||
program = g_wireframe_program;
|
||||
}
|
||||
|
||||
bindProgram(mesh, program);
|
||||
bindProgram(gl_mesh, program);
|
||||
|
||||
return program;
|
||||
}
|
||||
@ -645,7 +694,7 @@ static void draw_partition_patches_range(GLMeshInterface *mesh,
|
||||
const int num_draw_patches = std::min(num_remained_patches,
|
||||
num_block_patches - start_draw_patch);
|
||||
perform_drawElements(program,
|
||||
i,
|
||||
i + start_draw_patch,
|
||||
num_draw_patches * num_control_verts,
|
||||
patch.GetIndexBase() + start_draw_patch * num_control_verts);
|
||||
num_remained_patches -= num_draw_patches;
|
||||
@ -691,7 +740,7 @@ void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
|
||||
}
|
||||
|
||||
/* Setup GLSL/OpenGL to draw patches in current context. */
|
||||
GLuint program = prepare_patchDraw(mesh, fill_quads != 0);
|
||||
GLuint program = prepare_patchDraw(gl_mesh, fill_quads != 0);
|
||||
|
||||
if (start_patch != -1) {
|
||||
draw_partition_patches_range(mesh,
|
||||
@ -706,3 +755,21 @@ void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
|
||||
/* Finish patch drawing by restoring all changes to the OpenGL context. */
|
||||
finish_patchDraw(fill_quads != 0);
|
||||
}
|
||||
|
||||
void openSubdiv_osdGLAllocFVar(OpenSubdiv_GLMesh *gl_mesh,
|
||||
const float *fvar_data)
|
||||
{
|
||||
GLMeshInterface *mesh =
|
||||
(GLMeshInterface *)(gl_mesh->descriptor);
|
||||
gl_mesh->fvar_data = OBJECT_GUARDED_NEW(OpenSubdiv_GLMeshFVarData);
|
||||
gl_mesh->fvar_data->Create(mesh->GetFarPatchTable(),
|
||||
2,
|
||||
fvar_data);
|
||||
}
|
||||
|
||||
void openSubdiv_osdGLDestroyFVar(OpenSubdiv_GLMesh *gl_mesh)
|
||||
{
|
||||
if (gl_mesh->fvar_data != NULL) {
|
||||
OBJECT_GUARDED_DELETE(gl_mesh->fvar_data, OpenSubdiv_GLMeshFVarData);
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,12 @@
|
||||
|
||||
typedef struct OpenSubdiv_TopologyRefinerDescr {
|
||||
OpenSubdiv::Far::TopologyRefiner *osd_refiner;
|
||||
|
||||
/* TODO(sergey): For now only, need to find better place
|
||||
* after revisiting whole OSD drawing pipeline and Blender
|
||||
* integration.
|
||||
*/
|
||||
std::vector<float> uvs;
|
||||
} OpenSubdiv_TopologyRefinerDescr;
|
||||
|
||||
#endif /* __OPENSUBDIV_TOPOLOGY_REFINER_H__ */
|
||||
|
@ -313,9 +313,6 @@ CCGSubSurf *ccgSubSurf_new(CCGMeshIFC *ifc, int subdivLevels, CCGAllocatorIFC *a
|
||||
ss->osd_vao = 0;
|
||||
ss->skip_grids = false;
|
||||
ss->osd_compute = 0;
|
||||
ss->osd_uvs_invalid = true;
|
||||
ss->osd_subsurf_uv = 0;
|
||||
ss->osd_uv_index = -1;
|
||||
ss->osd_next_face_ptex_index = 0;
|
||||
ss->osd_coarse_coords = NULL;
|
||||
ss->osd_num_coarse_coords = 0;
|
||||
|
@ -254,11 +254,6 @@ struct CCGSubSurf {
|
||||
* to fill in PTex index of CCGFace.
|
||||
*/
|
||||
int osd_next_face_ptex_index;
|
||||
|
||||
/* ** Needs review. ** */
|
||||
bool osd_subsurf_uv;
|
||||
int osd_uv_index;
|
||||
bool osd_uvs_invalid;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -190,7 +190,6 @@ void ccgSubSurf_checkTopologyChanged(CCGSubSurf *ss, DerivedMesh *dm)
|
||||
/* ** Make sure both GPU and CPU backends are properly reset. ** */
|
||||
|
||||
ss->osd_coarse_coords_invalid = true;
|
||||
ss->osd_uvs_invalid = true;
|
||||
|
||||
/* Reset GPU part. */
|
||||
ss->osd_mesh_invalid = true;
|
||||
@ -256,8 +255,7 @@ bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss, bool use_osd_glsl)
|
||||
ss->osd_mesh = openSubdiv_createOsdGLMeshFromTopologyRefiner(
|
||||
ss->osd_topology_refiner,
|
||||
compute_type,
|
||||
ss->subdivLevels,
|
||||
ss->osd_subsurf_uv);
|
||||
ss->subdivLevels);
|
||||
ss->osd_topology_refiner = NULL;
|
||||
|
||||
if (UNLIKELY(ss->osd_mesh == NULL)) {
|
||||
@ -290,7 +288,7 @@ bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss, bool use_osd_glsl)
|
||||
ss->osd_coarse_coords_invalid = false;
|
||||
}
|
||||
|
||||
openSubdiv_osdGLMeshDisplayPrepare(use_osd_glsl, ss->osd_uv_index);
|
||||
openSubdiv_osdGLMeshDisplayPrepare(use_osd_glsl);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -62,6 +62,11 @@ typedef struct ConvDMStorage {
|
||||
*vert_poly_mem,
|
||||
*edge_poly_mem;
|
||||
#endif
|
||||
|
||||
MEdge *medge;
|
||||
MLoop *mloop;
|
||||
MPoly *mpoly;
|
||||
MLoopUV *mloopuv;
|
||||
} ConvDMStorage;
|
||||
|
||||
static OpenSubdiv_SchemeType conv_dm_get_type(
|
||||
@ -99,9 +104,7 @@ static int conv_dm_get_num_face_verts(const OpenSubdiv_Converter *converter,
|
||||
int face)
|
||||
{
|
||||
ConvDMStorage *storage = converter->user_data;
|
||||
DerivedMesh *dm = storage->dm;
|
||||
const MPoly *mp = dm->getPolyArray(dm);
|
||||
const MPoly *mpoly = &mp[face];
|
||||
const MPoly *mpoly = &storage->mpoly[face];
|
||||
return mpoly->totloop;
|
||||
}
|
||||
|
||||
@ -110,13 +113,10 @@ static void conv_dm_get_face_verts(const OpenSubdiv_Converter *converter,
|
||||
int *face_verts)
|
||||
{
|
||||
ConvDMStorage *storage = converter->user_data;
|
||||
DerivedMesh *dm = storage->dm;
|
||||
const MLoop *ml = dm->getLoopArray(dm);
|
||||
const MPoly *mp = dm->getPolyArray(dm);
|
||||
const MPoly *mpoly = &mp[face];
|
||||
const MPoly *mpoly = &storage->mpoly[face];
|
||||
int loop;
|
||||
for (loop = 0; loop < mpoly->totloop; loop++) {
|
||||
face_verts[loop] = ml[mpoly->loopstart + loop].v;
|
||||
face_verts[loop] = storage->mloop[mpoly->loopstart + loop].v;
|
||||
}
|
||||
}
|
||||
|
||||
@ -125,13 +125,10 @@ static void conv_dm_get_face_edges(const OpenSubdiv_Converter *converter,
|
||||
int *face_edges)
|
||||
{
|
||||
ConvDMStorage *storage = converter->user_data;
|
||||
DerivedMesh *dm = storage->dm;
|
||||
const MLoop *ml = dm->getLoopArray(dm);
|
||||
const MPoly *mp = dm->getPolyArray(dm);
|
||||
const MPoly *mpoly = &mp[face];
|
||||
const MPoly *mpoly = &storage->mpoly[face];
|
||||
int loop;
|
||||
for (loop = 0; loop < mpoly->totloop; loop++) {
|
||||
face_edges[loop] = ml[mpoly->loopstart + loop].e;
|
||||
face_edges[loop] = storage->mloop[mpoly->loopstart + loop].e;
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,9 +137,7 @@ static void conv_dm_get_edge_verts(const OpenSubdiv_Converter *converter,
|
||||
int *edge_verts)
|
||||
{
|
||||
ConvDMStorage *storage = converter->user_data;
|
||||
DerivedMesh *dm = storage->dm;
|
||||
const MEdge *me = dm->getEdgeArray(dm);
|
||||
const MEdge *medge = &me[edge];
|
||||
const MEdge *medge = &storage->medge[edge];
|
||||
edge_verts[0] = medge->v1;
|
||||
edge_verts[1] = medge->v2;
|
||||
}
|
||||
@ -153,14 +148,12 @@ static int conv_dm_get_num_edge_faces(const OpenSubdiv_Converter *converter,
|
||||
ConvDMStorage *storage = converter->user_data;
|
||||
#ifndef USE_MESH_ELEMENT_MAPPING
|
||||
DerivedMesh *dm = storage->dm;
|
||||
const MLoop *ml = dm->getLoopArray(dm);
|
||||
const MPoly *mp = dm->getPolyArray(dm);
|
||||
int num = 0, poly;
|
||||
for (poly = 0; poly < dm->getNumPolys(dm); poly++) {
|
||||
const MPoly *mpoly = &mp[poly];
|
||||
const MPoly *mpoly = &user_data->mpoly[poly];
|
||||
int loop;
|
||||
for (loop = 0; loop < mpoly->totloop; loop++) {
|
||||
const MLoop *mloop = &ml[mpoly->loopstart + loop];
|
||||
const MLoop *mloop = &storage->mloop[mpoly->loopstart + loop];
|
||||
if (mloop->e == edge) {
|
||||
++num;
|
||||
break;
|
||||
@ -180,14 +173,12 @@ static void conv_dm_get_edge_faces(const OpenSubdiv_Converter *converter,
|
||||
ConvDMStorage *storage = converter->user_data;
|
||||
#ifndef USE_MESH_ELEMENT_MAPPING
|
||||
DerivedMesh *dm = storage->dm;
|
||||
const MLoop *ml = dm->getLoopArray(dm);
|
||||
const MPoly *mp = dm->getPolyArray(dm);
|
||||
int num = 0, poly;
|
||||
for (poly = 0; poly < dm->getNumPolys(dm); poly++) {
|
||||
const MPoly *mpoly = &mp[poly];
|
||||
const MPoly *mpoly = &user_data->mpoly[poly];
|
||||
int loop;
|
||||
for (loop = 0; loop < mpoly->totloop; loop++) {
|
||||
const MLoop *mloop = &ml[mpoly->loopstart + loop];
|
||||
const MLoop *mloop = &storage->mloop[mpoly->loopstart + loop];
|
||||
if (mloop->e == edge) {
|
||||
edge_faces[num++] = poly;
|
||||
break;
|
||||
@ -205,9 +196,8 @@ static float conv_dm_get_edge_sharpness(const OpenSubdiv_Converter *converter,
|
||||
int edge)
|
||||
{
|
||||
ConvDMStorage *storage = converter->user_data;
|
||||
DerivedMesh *dm = storage->dm;
|
||||
CCGSubSurf *ss = storage->ss;
|
||||
const MEdge *medge = dm->getEdgeArray(dm);
|
||||
const MEdge *medge = storage->medge;
|
||||
return (float)medge[edge].crease / 255.0f * ss->subdivLevels;
|
||||
}
|
||||
|
||||
@ -217,10 +207,9 @@ static int conv_dm_get_num_vert_edges(const OpenSubdiv_Converter *converter,
|
||||
ConvDMStorage *storage = converter->user_data;
|
||||
#ifndef USE_MESH_ELEMENT_MAPPING
|
||||
DerivedMesh *dm = storage->dm;
|
||||
const MEdge *me = dm->getEdgeArray(dm);
|
||||
int num = 0, edge;
|
||||
for (edge = 0; edge < dm->getNumEdges(dm); edge++) {
|
||||
const MEdge *medge = &me[edge];
|
||||
const MEdge *medge = &user_data->medge[edge];
|
||||
if (medge->v1 == vert || medge->v2 == vert) {
|
||||
++num;
|
||||
}
|
||||
@ -238,10 +227,9 @@ static void conv_dm_get_vert_edges(const OpenSubdiv_Converter *converter,
|
||||
ConvDMStorage *storage = converter->user_data;
|
||||
#ifndef USE_MESH_ELEMENT_MAPPING
|
||||
DerivedMesh *dm = storage->dm;
|
||||
const MEdge *me = dm->getEdgeArray(dm);
|
||||
int num = 0, edge;
|
||||
for (edge = 0; edge < dm->getNumEdges(dm); edge++) {
|
||||
const MEdge *medge = &me[edge];
|
||||
const MEdge *medge = &user_data->medge[edge];
|
||||
if (medge->v1 == vert || medge->v2 == vert) {
|
||||
vert_edges[num++] = edge;
|
||||
}
|
||||
@ -259,14 +247,12 @@ static int conv_dm_get_num_vert_faces(const OpenSubdiv_Converter *converter,
|
||||
ConvDMStorage *storage = converter->user_data;
|
||||
#ifndef USE_MESH_ELEMENT_MAPPING
|
||||
DerivedMesh *dm = storage->dm;
|
||||
const MLoop *ml = dm->getLoopArray(dm);
|
||||
const MPoly *mp = dm->getPolyArray(dm);
|
||||
int num = 0, poly;
|
||||
for (poly = 0; poly < dm->getNumPolys(dm); poly++) {
|
||||
const MPoly *mpoly = &mp[poly];
|
||||
const MPoly *mpoly = &user_data->mpoly[poly];
|
||||
int loop;
|
||||
for (loop = 0; loop < mpoly->totloop; loop++) {
|
||||
const MLoop *mloop = &ml[mpoly->loopstart + loop];
|
||||
const MLoop *mloop = &storage->mloop[mpoly->loopstart + loop];
|
||||
if (mloop->v == vert) {
|
||||
++num;
|
||||
break;
|
||||
@ -286,14 +272,12 @@ static void conv_dm_get_vert_faces(const OpenSubdiv_Converter *converter,
|
||||
ConvDMStorage *storage = converter->user_data;
|
||||
#ifndef USE_MESH_ELEMENT_MAPPING
|
||||
DerivedMesh *dm = storage->dm;
|
||||
const MLoop *ml = dm->getLoopArray(dm);
|
||||
const MPoly *mp = dm->getPolyArray(dm);
|
||||
int num = 0, poly;
|
||||
for (poly = 0; poly < dm->getNumPolys(dm); poly++) {
|
||||
const MPoly *mpoly = &mp[poly];
|
||||
const MPoly *mpoly = &storage->mpoly[poly];
|
||||
int loop;
|
||||
for (loop = 0; loop < mpoly->totloop; loop++) {
|
||||
const MLoop *mloop = &ml[mpoly->loopstart + loop];
|
||||
const MLoop *mloop = &storage->mloop[mpoly->loopstart + loop];
|
||||
if (mloop->v == vert) {
|
||||
vert_faces[num++] = poly;
|
||||
break;
|
||||
@ -307,6 +291,24 @@ static void conv_dm_get_vert_faces(const OpenSubdiv_Converter *converter,
|
||||
#endif
|
||||
}
|
||||
|
||||
static int conv_dm_get_num_uv_layers(const OpenSubdiv_Converter *converter)
|
||||
{
|
||||
ConvDMStorage *storage = converter->user_data;
|
||||
DerivedMesh *dm = storage->dm;
|
||||
return CustomData_number_of_layers(&dm->loopData, CD_MLOOPUV);
|
||||
}
|
||||
|
||||
static void conv_dm_get_face_corner_uv(const OpenSubdiv_Converter *converter,
|
||||
int face,
|
||||
int corner,
|
||||
float r_uv[2])
|
||||
{
|
||||
ConvDMStorage *storage = converter->user_data;
|
||||
MPoly *mpoly = &storage->mpoly[face];
|
||||
MLoopUV *mloopuv = &storage->mloopuv[mpoly->loopstart + corner];
|
||||
copy_v2_v2(r_uv, mloopuv->uv);
|
||||
}
|
||||
|
||||
static void conv_dm_free_user_data(const OpenSubdiv_Converter *converter)
|
||||
{
|
||||
ConvDMStorage *user_data = converter->user_data;
|
||||
@ -348,9 +350,18 @@ void ccgSubSurf_converter_setup_from_derivedmesh(
|
||||
converter->get_num_vert_faces = conv_dm_get_num_vert_faces;
|
||||
converter->get_vert_faces = conv_dm_get_vert_faces;
|
||||
|
||||
converter->get_num_uv_layers = conv_dm_get_num_uv_layers;
|
||||
converter->get_face_corner_uv = conv_dm_get_face_corner_uv;
|
||||
|
||||
user_data = MEM_mallocN(sizeof(ConvDMStorage), __func__);
|
||||
user_data->ss = ss;
|
||||
user_data->dm = dm;
|
||||
|
||||
user_data->medge = dm->getEdgeArray(dm);
|
||||
user_data->mloop = dm->getLoopArray(dm);
|
||||
user_data->mpoly = dm->getPolyArray(dm);
|
||||
user_data->mloopuv = DM_get_loop_data_layer(dm, CD_MLOOPUV);
|
||||
|
||||
converter->free_user_data = conv_dm_free_user_data;
|
||||
converter->user_data = user_data;
|
||||
|
||||
@ -548,6 +559,19 @@ static void conv_ccg_get_vert_faces(const OpenSubdiv_Converter *converter,
|
||||
}
|
||||
}
|
||||
|
||||
static int conv_ccg_get_num_uv_layers(const OpenSubdiv_Converter *UNUSED(converter))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void conv_ccg_get_face_corner_uv(const OpenSubdiv_Converter * UNUSED(converter),
|
||||
int UNUSED(face),
|
||||
int UNUSED(corner),
|
||||
float r_uv[2])
|
||||
{
|
||||
zero_v2(r_uv);
|
||||
}
|
||||
|
||||
void ccgSubSurf_converter_setup_from_ccg(CCGSubSurf *ss,
|
||||
OpenSubdiv_Converter *converter)
|
||||
{
|
||||
@ -571,6 +595,9 @@ void ccgSubSurf_converter_setup_from_ccg(CCGSubSurf *ss,
|
||||
converter->get_num_vert_faces = conv_ccg_get_num_vert_faces;
|
||||
converter->get_vert_faces = conv_ccg_get_vert_faces;
|
||||
|
||||
converter->get_num_uv_layers = conv_ccg_get_num_uv_layers;
|
||||
converter->get_face_corner_uv = conv_ccg_get_face_corner_uv;
|
||||
|
||||
converter->free_user_data = NULL;
|
||||
converter->user_data = ss;
|
||||
}
|
||||
|
@ -3386,19 +3386,6 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
|
||||
int mat_index;
|
||||
int tot_element, start_element, tot_drawn;
|
||||
|
||||
#ifdef WITH_OPENSUBDIV
|
||||
if (ccgdm->useGpuBackend) {
|
||||
if (ccgSubSurf_prepareGLMesh(ss, true) == false) {
|
||||
return;
|
||||
}
|
||||
ccgSubSurf_drawGLMesh(ss, true, -1, -1);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
CCG_key_top_level(&key, ss);
|
||||
ccgdm_pbvh_update(ccgdm);
|
||||
|
||||
if (use_colors) {
|
||||
colType = CD_TEXTURE_MLOOPCOL;
|
||||
mloopcol = dm->getLoopDataArray(dm, colType);
|
||||
@ -3412,6 +3399,77 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_OPENSUBDIV
|
||||
if (ccgdm->useGpuBackend) {
|
||||
if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, true) == false)) {
|
||||
return;
|
||||
}
|
||||
if (drawParams == NULL) {
|
||||
ccgSubSurf_drawGLMesh(ss, true, -1, -1);
|
||||
return;
|
||||
}
|
||||
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 current_patch = 0;
|
||||
int mat_nr = -1;
|
||||
int start_draw_patch = 0, num_draw_patches = 0;
|
||||
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;
|
||||
if (faceFlags) {
|
||||
mat_nr = faceFlags[i].mat_nr + 1;
|
||||
}
|
||||
else {
|
||||
mat_nr = 0;
|
||||
}
|
||||
|
||||
if (drawParams != NULL) {
|
||||
MTexPoly *tp = (use_tface && mtexpoly) ? &mtexpoly[i] : NULL;
|
||||
draw_option = drawParams(tp, (mloopcol != NULL), mat_nr);
|
||||
}
|
||||
else {
|
||||
draw_option = (drawParamsMapped)
|
||||
? drawParamsMapped(userData, i, mat_nr)
|
||||
: DM_DRAW_OPTION_NORMAL;
|
||||
}
|
||||
|
||||
flush = (draw_option == DM_DRAW_OPTION_SKIP) || (i == num_base_faces - 1);
|
||||
|
||||
if (!flush && compareDrawOptions) {
|
||||
flush |= compareDrawOptions(userData, i, min_ii(i + 1, num_base_faces - 1)) == 0;
|
||||
}
|
||||
|
||||
current_patch += num_patches;
|
||||
|
||||
if (flush) {
|
||||
if (draw_option != DM_DRAW_OPTION_SKIP) {
|
||||
num_draw_patches += num_patches;
|
||||
}
|
||||
if (num_draw_patches != 0) {
|
||||
ccgSubSurf_drawGLMesh(ss,
|
||||
true,
|
||||
start_draw_patch,
|
||||
num_draw_patches);
|
||||
}
|
||||
start_draw_patch = current_patch;
|
||||
num_draw_patches = 0;
|
||||
}
|
||||
else {
|
||||
num_draw_patches += num_patches;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
CCG_key_top_level(&key, ss);
|
||||
ccgdm_pbvh_update(ccgdm);
|
||||
|
||||
GPU_vertex_setup(dm);
|
||||
GPU_normal_setup(dm);
|
||||
GPU_triangle_setup(dm);
|
||||
|
@ -868,14 +868,12 @@ static char *code_generate_geometry(ListBase *nodes, bool use_opensubdiv)
|
||||
BLI_dynstr_append(ds, datatoc_gpu_shader_geometry_glsl);
|
||||
|
||||
/* Generate varying assignments. */
|
||||
/* TODO(sergey): Disabled for now, needs revisit. */
|
||||
#if 0
|
||||
for (node = nodes->first; node; node = node->next) {
|
||||
for (input = node->inputs.first; input; input = input->next) {
|
||||
if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
|
||||
if (input->attribtype == CD_MTFACE) {
|
||||
BLI_dynstr_appendf(ds,
|
||||
"\tINTERP_FACE_VARYING_2(var%d, "
|
||||
"\t// INTERP_FACE_VARYING_2(var%d, "
|
||||
"fvar%d_offset, st);\n",
|
||||
input->attribid,
|
||||
input->attribid);
|
||||
@ -883,7 +881,6 @@ static char *code_generate_geometry(ListBase *nodes, bool use_opensubdiv)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
BLI_dynstr_append(ds, "}\n");
|
||||
code = BLI_dynstr_get_cstring(ds);
|
||||
|
Loading…
Reference in New Issue
Block a user