Fix T60124: Multires modifier not reading data from external files
This commit is contained in:
@@ -88,8 +88,7 @@ typedef struct SubdivStats {
|
|||||||
struct {
|
struct {
|
||||||
/* Time spend on creating topology refiner, which includes time
|
/* Time spend on creating topology refiner, which includes time
|
||||||
* spend on conversion from Blender data to OpenSubdiv data, and
|
* spend on conversion from Blender data to OpenSubdiv data, and
|
||||||
* time spend on topology orientation on OpenSubdiv C-API side.
|
* time spend on topology orientation on OpenSubdiv C-API side. */
|
||||||
*/
|
|
||||||
double topology_refiner_creation_time;
|
double topology_refiner_creation_time;
|
||||||
/* Total time spent in BKE_subdiv_to_mesh(). */
|
/* Total time spent in BKE_subdiv_to_mesh(). */
|
||||||
double subdiv_to_mesh_time;
|
double subdiv_to_mesh_time;
|
||||||
@@ -108,13 +107,19 @@ typedef struct SubdivStats {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Per-value timestamp on when corresponding BKE_subdiv_stats_begin() was
|
/* Per-value timestamp on when corresponding BKE_subdiv_stats_begin() was
|
||||||
* called.
|
* called. */
|
||||||
*/
|
|
||||||
double begin_timestamp_[NUM_SUBDIV_STATS_VALUES];
|
double begin_timestamp_[NUM_SUBDIV_STATS_VALUES];
|
||||||
} SubdivStats;
|
} SubdivStats;
|
||||||
|
|
||||||
/* Functor which evaluates dispalcement at a given (u, v) of given ptex face. */
|
/* Functor which evaluates dispalcement at a given (u, v) of given ptex face. */
|
||||||
typedef struct SubdivDisplacement {
|
typedef struct SubdivDisplacement {
|
||||||
|
/* Initialize displacement evaluator.
|
||||||
|
*
|
||||||
|
* Is called right before evaluation is actually needed. This allows to do
|
||||||
|
* some lazy initialization, like allocate evaluator from a main thread but
|
||||||
|
* then do actual evaluation from background job. */
|
||||||
|
void (*initialize)(struct SubdivDisplacement *displacement);
|
||||||
|
|
||||||
/* Return displacement which is to be added to the original coordinate.
|
/* Return displacement which is to be added to the original coordinate.
|
||||||
*
|
*
|
||||||
* NOTE: This function is supposed to return "continuous" displacement for
|
* NOTE: This function is supposed to return "continuous" displacement for
|
||||||
@@ -124,8 +129,7 @@ typedef struct SubdivDisplacement {
|
|||||||
* displacement grids if needed.
|
* displacement grids if needed.
|
||||||
*
|
*
|
||||||
* Averaging of displacement for vertices created for over coarse vertices
|
* Averaging of displacement for vertices created for over coarse vertices
|
||||||
* and edges is done by subdiv code.
|
* and edges is done by subdiv code. */
|
||||||
*/
|
|
||||||
void (*eval_displacement)(struct SubdivDisplacement *displacement,
|
void (*eval_displacement)(struct SubdivDisplacement *displacement,
|
||||||
const int ptex_face_index,
|
const int ptex_face_index,
|
||||||
const float u, const float v,
|
const float u, const float v,
|
||||||
@@ -142,8 +146,7 @@ typedef struct SubdivDisplacement {
|
|||||||
* It does not specify storage, memory layout or anything else.
|
* It does not specify storage, memory layout or anything else.
|
||||||
* It is possible to create different storages (like, grid based CPU side
|
* It is possible to create different storages (like, grid based CPU side
|
||||||
* buffers, GPU subdivision mesh, CPU side fully qualified mesh) from the same
|
* buffers, GPU subdivision mesh, CPU side fully qualified mesh) from the same
|
||||||
* Subdiv structure.
|
* Subdiv structure. */
|
||||||
*/
|
|
||||||
typedef struct Subdiv {
|
typedef struct Subdiv {
|
||||||
/* Settings this subdivision surface is created for.
|
/* Settings this subdivision surface is created for.
|
||||||
*
|
*
|
||||||
@@ -152,8 +155,7 @@ typedef struct Subdiv {
|
|||||||
SubdivSettings settings;
|
SubdivSettings settings;
|
||||||
/* Topology refiner includes all the glue logic to feed Blender side
|
/* Topology refiner includes all the glue logic to feed Blender side
|
||||||
* topology to OpenSubdiv. It can be shared by both evaluator and GL mesh
|
* topology to OpenSubdiv. It can be shared by both evaluator and GL mesh
|
||||||
* drawer.
|
* drawer. */
|
||||||
*/
|
|
||||||
struct OpenSubdiv_TopologyRefiner *topology_refiner;
|
struct OpenSubdiv_TopologyRefiner *topology_refiner;
|
||||||
/* CPU side evaluator. */
|
/* CPU side evaluator. */
|
||||||
struct OpenSubdiv_Evaluator *evaluator;
|
struct OpenSubdiv_Evaluator *evaluator;
|
||||||
@@ -200,7 +202,7 @@ void BKE_subdiv_free(Subdiv *subdiv);
|
|||||||
|
|
||||||
void BKE_subdiv_displacement_attach_from_multires(
|
void BKE_subdiv_displacement_attach_from_multires(
|
||||||
Subdiv *subdiv,
|
Subdiv *subdiv,
|
||||||
const struct Mesh *mesh,
|
struct Mesh *mesh,
|
||||||
const struct MultiresModifierData *mmd);
|
const struct MultiresModifierData *mmd);
|
||||||
|
|
||||||
void BKE_subdiv_displacement_detach(Subdiv *subdiv);
|
void BKE_subdiv_displacement_detach(Subdiv *subdiv);
|
||||||
@@ -212,8 +214,7 @@ int *BKE_subdiv_face_ptex_offset_get(Subdiv *subdiv);
|
|||||||
/* ============================= VARIOUS HELPERS ============================ */
|
/* ============================= VARIOUS HELPERS ============================ */
|
||||||
|
|
||||||
/* For a given (ptex_u, ptex_v) within a ptex face get corresponding
|
/* For a given (ptex_u, ptex_v) within a ptex face get corresponding
|
||||||
* (grid_u, grid_v) within a grid.
|
* (grid_u, grid_v) within a grid. */
|
||||||
*/
|
|
||||||
BLI_INLINE void BKE_subdiv_ptex_face_uv_to_grid_uv(
|
BLI_INLINE void BKE_subdiv_ptex_face_uv_to_grid_uv(
|
||||||
const float ptex_u, const float ptex_v,
|
const float ptex_u, const float ptex_v,
|
||||||
float *r_grid_u, float *r_grid_v);
|
float *r_grid_u, float *r_grid_v);
|
||||||
@@ -226,8 +227,7 @@ BLI_INLINE int BKE_subdiv_grid_size_from_level(const int level);
|
|||||||
/* Simplified version of mdisp_rot_face_to_crn, only handles quad and
|
/* Simplified version of mdisp_rot_face_to_crn, only handles quad and
|
||||||
* works in normalized coordinates.
|
* works in normalized coordinates.
|
||||||
*
|
*
|
||||||
* NOTE: Output coordinates are in ptex coordinates.
|
* NOTE: Output coordinates are in ptex coordinates. */
|
||||||
*/
|
|
||||||
BLI_INLINE int BKE_subdiv_rotate_quad_to_corner(
|
BLI_INLINE int BKE_subdiv_rotate_quad_to_corner(
|
||||||
const float u, const float v,
|
const float u, const float v,
|
||||||
float *r_u, float *r_v);
|
float *r_u, float *r_v);
|
||||||
|
@@ -42,6 +42,12 @@ bool BKE_subdiv_eval_begin(struct Subdiv *subdiv);
|
|||||||
bool BKE_subdiv_eval_update_from_mesh(struct Subdiv *subdiv,
|
bool BKE_subdiv_eval_update_from_mesh(struct Subdiv *subdiv,
|
||||||
const struct Mesh *mesh);
|
const struct Mesh *mesh);
|
||||||
|
|
||||||
|
/* Makes sure displacement evaluator is initialized.
|
||||||
|
*
|
||||||
|
* NOTE: This function must be called once before evaluating displacement or
|
||||||
|
* final surface position. */
|
||||||
|
void BKE_subdiv_eval_init_displacement(struct Subdiv *subdiv);
|
||||||
|
|
||||||
/* Single point queries. */
|
/* Single point queries. */
|
||||||
|
|
||||||
void BKE_subdiv_eval_limit_point(
|
void BKE_subdiv_eval_limit_point(
|
||||||
@@ -77,8 +83,7 @@ void BKE_subdiv_eval_face_varying(
|
|||||||
* TODO(sergey): This is currently used together with
|
* TODO(sergey): This is currently used together with
|
||||||
* BKE_subdiv_eval_final_point() which cas easily evaluate derivatives.
|
* BKE_subdiv_eval_final_point() which cas easily evaluate derivatives.
|
||||||
* Would be nice to have dispalcement evaluation function which does not require
|
* Would be nice to have dispalcement evaluation function which does not require
|
||||||
* knowing derivatives ahead of a time.
|
* knowing derivatives ahead of a time. */
|
||||||
*/
|
|
||||||
void BKE_subdiv_eval_displacement(
|
void BKE_subdiv_eval_displacement(
|
||||||
struct Subdiv *subdiv,
|
struct Subdiv *subdiv,
|
||||||
const int ptex_face_index,
|
const int ptex_face_index,
|
||||||
@@ -96,8 +101,7 @@ void BKE_subdiv_eval_final_point(
|
|||||||
*
|
*
|
||||||
* Will evaluate patch at uniformly distributed (u, v) coordinates on a grid
|
* Will evaluate patch at uniformly distributed (u, v) coordinates on a grid
|
||||||
* of given resolution, producing resolution^2 evaluation points. The order
|
* of given resolution, producing resolution^2 evaluation points. The order
|
||||||
* goes as u in rows, v in columns.
|
* goes as u in rows, v in columns. */
|
||||||
*/
|
|
||||||
|
|
||||||
void BKE_subdiv_eval_limit_patch_resolution_point(
|
void BKE_subdiv_eval_limit_patch_resolution_point(
|
||||||
struct Subdiv *subdiv,
|
struct Subdiv *subdiv,
|
||||||
|
@@ -49,20 +49,23 @@ typedef struct PolyCornerIndex {
|
|||||||
|
|
||||||
typedef struct MultiresDisplacementData {
|
typedef struct MultiresDisplacementData {
|
||||||
int grid_size;
|
int grid_size;
|
||||||
|
/* Mesh is used to read external displacement. */
|
||||||
|
Mesh *mesh;
|
||||||
const MPoly *mpoly;
|
const MPoly *mpoly;
|
||||||
const MDisps *mdisps;
|
const MDisps *mdisps;
|
||||||
/* Indexed by ptex face index, contains polygon/corner which corresponds
|
/* Indexed by ptex face index, contains polygon/corner which corresponds
|
||||||
* to it.
|
* to it.
|
||||||
*
|
*
|
||||||
* NOTE: For quad polygon this is an index of first corner only, since
|
* NOTE: For quad polygon this is an index of first corner only, since
|
||||||
* there we only have one ptex.
|
* there we only have one ptex. */
|
||||||
*/
|
|
||||||
PolyCornerIndex *ptex_poly_corner;
|
PolyCornerIndex *ptex_poly_corner;
|
||||||
|
/* Sanity check, is used in debug builds.
|
||||||
|
* Controls that initialize() was called prior to eval_displacement(). */
|
||||||
|
bool is_initialized;
|
||||||
} MultiresDisplacementData;
|
} MultiresDisplacementData;
|
||||||
|
|
||||||
/* Denotes which grid to use to average value of the displacement read from the
|
/* Denotes which grid to use to average value of the displacement read from the
|
||||||
* grid which corresponds to the ptex face.
|
* grid which corresponds to the ptex face. */
|
||||||
*/
|
|
||||||
typedef enum eAverageWith {
|
typedef enum eAverageWith {
|
||||||
AVERAGE_WITH_NONE,
|
AVERAGE_WITH_NONE,
|
||||||
AVERAGE_WITH_ALL,
|
AVERAGE_WITH_ALL,
|
||||||
@@ -238,6 +241,16 @@ static void average_displacement(SubdivDisplacement *displacement,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void initialize(SubdivDisplacement *displacement)
|
||||||
|
{
|
||||||
|
MultiresDisplacementData *data = displacement->user_data;
|
||||||
|
Mesh *mesh = data->mesh;
|
||||||
|
/* Make sure external displacement is read. */
|
||||||
|
CustomData_external_read(
|
||||||
|
&mesh->ldata, &mesh->id, CD_MASK_MDISPS, mesh->totloop);
|
||||||
|
data->is_initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
static void eval_displacement(SubdivDisplacement *displacement,
|
static void eval_displacement(SubdivDisplacement *displacement,
|
||||||
const int ptex_face_index,
|
const int ptex_face_index,
|
||||||
const float u, const float v,
|
const float u, const float v,
|
||||||
@@ -245,6 +258,7 @@ static void eval_displacement(SubdivDisplacement *displacement,
|
|||||||
float r_D[3])
|
float r_D[3])
|
||||||
{
|
{
|
||||||
MultiresDisplacementData *data = displacement->user_data;
|
MultiresDisplacementData *data = displacement->user_data;
|
||||||
|
BLI_assert(data->is_initialized);
|
||||||
const int grid_size = data->grid_size;
|
const int grid_size = data->grid_size;
|
||||||
/* Get displacement in tangent space. */
|
/* Get displacement in tangent space. */
|
||||||
const MDisps *displacement_grid;
|
const MDisps *displacement_grid;
|
||||||
@@ -254,8 +268,7 @@ static void eval_displacement(SubdivDisplacement *displacement,
|
|||||||
&displacement_grid,
|
&displacement_grid,
|
||||||
&grid_u, &grid_v);
|
&grid_u, &grid_v);
|
||||||
/* Read displacement from the current displacement grid and see if any
|
/* Read displacement from the current displacement grid and see if any
|
||||||
* averaging is needed.
|
* averaging is needed. */
|
||||||
*/
|
|
||||||
float tangent_D[3];
|
float tangent_D[3];
|
||||||
eAverageWith average_with =
|
eAverageWith average_with =
|
||||||
read_displacement_grid(displacement_grid, grid_size,
|
read_displacement_grid(displacement_grid, grid_size,
|
||||||
@@ -279,8 +292,7 @@ static void free_displacement(SubdivDisplacement *displacement)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* TODO(sergey): This seems to be generally used information, which almost
|
/* TODO(sergey): This seems to be generally used information, which almost
|
||||||
* worth adding to a subdiv itself, with possible cache of the value.
|
* worth adding to a subdiv itself, with possible cache of the value. */
|
||||||
*/
|
|
||||||
static int count_num_ptex_faces(const Mesh *mesh)
|
static int count_num_ptex_faces(const Mesh *mesh)
|
||||||
{
|
{
|
||||||
int num_ptex_faces = 0;
|
int num_ptex_faces = 0;
|
||||||
@@ -323,25 +335,28 @@ static void displacement_data_init_mapping(SubdivDisplacement *displacement,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void displacement_init_data(SubdivDisplacement *displacement,
|
static void displacement_init_data(SubdivDisplacement *displacement,
|
||||||
const Mesh *mesh,
|
Mesh *mesh,
|
||||||
const MultiresModifierData *mmd)
|
const MultiresModifierData *mmd)
|
||||||
{
|
{
|
||||||
MultiresDisplacementData *data = displacement->user_data;
|
MultiresDisplacementData *data = displacement->user_data;
|
||||||
data->grid_size = BKE_subdiv_grid_size_from_level(mmd->totlvl);
|
data->grid_size = BKE_subdiv_grid_size_from_level(mmd->totlvl);
|
||||||
|
data->mesh = mesh;
|
||||||
data->mpoly = mesh->mpoly;
|
data->mpoly = mesh->mpoly;
|
||||||
data->mdisps = CustomData_get_layer(&mesh->ldata, CD_MDISPS);
|
data->mdisps = CustomData_get_layer(&mesh->ldata, CD_MDISPS);
|
||||||
|
data->is_initialized = false;
|
||||||
displacement_data_init_mapping(displacement, mesh);
|
displacement_data_init_mapping(displacement, mesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void displacement_init_functions(SubdivDisplacement *displacement)
|
static void displacement_init_functions(SubdivDisplacement *displacement)
|
||||||
{
|
{
|
||||||
|
displacement->initialize = initialize;
|
||||||
displacement->eval_displacement = eval_displacement;
|
displacement->eval_displacement = eval_displacement;
|
||||||
displacement->free = free_displacement;
|
displacement->free = free_displacement;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BKE_subdiv_displacement_attach_from_multires(
|
void BKE_subdiv_displacement_attach_from_multires(
|
||||||
Subdiv *subdiv,
|
Subdiv *subdiv,
|
||||||
const Mesh *mesh,
|
Mesh *mesh,
|
||||||
const MultiresModifierData *mmd)
|
const MultiresModifierData *mmd)
|
||||||
{
|
{
|
||||||
/* Make sure we don't have previously assigned displacement. */
|
/* Make sure we don't have previously assigned displacement. */
|
||||||
|
@@ -64,6 +64,7 @@ bool BKE_subdiv_eval_begin(Subdiv *subdiv)
|
|||||||
else {
|
else {
|
||||||
/* TODO(sergey): Check for topology change. */
|
/* TODO(sergey): Check for topology change. */
|
||||||
}
|
}
|
||||||
|
BKE_subdiv_eval_init_displacement(subdiv);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,6 +160,17 @@ bool BKE_subdiv_eval_update_from_mesh(Subdiv *subdiv, const Mesh *mesh)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BKE_subdiv_eval_init_displacement(Subdiv *subdiv)
|
||||||
|
{
|
||||||
|
if (subdiv->displacement_evaluator == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (subdiv->displacement_evaluator->initialize == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
subdiv->displacement_evaluator->initialize(subdiv->displacement_evaluator);
|
||||||
|
}
|
||||||
|
|
||||||
/* ========================== Single point queries ========================== */
|
/* ========================== Single point queries ========================== */
|
||||||
|
|
||||||
void BKE_subdiv_eval_limit_point(
|
void BKE_subdiv_eval_limit_point(
|
||||||
|
Reference in New Issue
Block a user