From b69cbe7d8759e604e34d81a9ddc90d8167751f33 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 4 Jan 2019 15:57:44 +0100 Subject: Fix T60124: Multires modifier not reading data from external files --- source/blender/blenkernel/BKE_subdiv.h | 30 +++++++++---------- source/blender/blenkernel/BKE_subdiv_eval.h | 12 +++++--- .../intern/subdiv_displacement_multires.c | 35 +++++++++++++++------- source/blender/blenkernel/intern/subdiv_eval.c | 12 ++++++++ 4 files changed, 60 insertions(+), 29 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/BKE_subdiv.h b/source/blender/blenkernel/BKE_subdiv.h index 0a09d3528b4..70572d30819 100644 --- a/source/blender/blenkernel/BKE_subdiv.h +++ b/source/blender/blenkernel/BKE_subdiv.h @@ -88,8 +88,7 @@ typedef struct SubdivStats { struct { /* Time spend on creating topology refiner, which includes time * 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; /* Total time spent in BKE_subdiv_to_mesh(). */ double subdiv_to_mesh_time; @@ -108,13 +107,19 @@ typedef struct SubdivStats { }; /* Per-value timestamp on when corresponding BKE_subdiv_stats_begin() was - * called. - */ + * called. */ double begin_timestamp_[NUM_SUBDIV_STATS_VALUES]; } SubdivStats; /* Functor which evaluates dispalcement at a given (u, v) of given ptex face. */ 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. * * NOTE: This function is supposed to return "continuous" displacement for @@ -124,8 +129,7 @@ typedef struct SubdivDisplacement { * displacement grids if needed. * * 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, const int ptex_face_index, const float u, const float v, @@ -142,8 +146,7 @@ typedef struct SubdivDisplacement { * It does not specify storage, memory layout or anything else. * It is possible to create different storages (like, grid based CPU side * buffers, GPU subdivision mesh, CPU side fully qualified mesh) from the same - * Subdiv structure. - */ + * Subdiv structure. */ typedef struct Subdiv { /* Settings this subdivision surface is created for. * @@ -152,8 +155,7 @@ typedef struct Subdiv { SubdivSettings settings; /* Topology refiner includes all the glue logic to feed Blender side * topology to OpenSubdiv. It can be shared by both evaluator and GL mesh - * drawer. - */ + * drawer. */ struct OpenSubdiv_TopologyRefiner *topology_refiner; /* CPU side evaluator. */ struct OpenSubdiv_Evaluator *evaluator; @@ -200,7 +202,7 @@ void BKE_subdiv_free(Subdiv *subdiv); void BKE_subdiv_displacement_attach_from_multires( Subdiv *subdiv, - const struct Mesh *mesh, + struct Mesh *mesh, const struct MultiresModifierData *mmd); void BKE_subdiv_displacement_detach(Subdiv *subdiv); @@ -212,8 +214,7 @@ int *BKE_subdiv_face_ptex_offset_get(Subdiv *subdiv); /* ============================= VARIOUS HELPERS ============================ */ /* 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( const float ptex_u, const float ptex_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 * 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( const float u, const float v, float *r_u, float *r_v); diff --git a/source/blender/blenkernel/BKE_subdiv_eval.h b/source/blender/blenkernel/BKE_subdiv_eval.h index 0ea5c978e62..b743c759ace 100644 --- a/source/blender/blenkernel/BKE_subdiv_eval.h +++ b/source/blender/blenkernel/BKE_subdiv_eval.h @@ -42,6 +42,12 @@ bool BKE_subdiv_eval_begin(struct Subdiv *subdiv); bool BKE_subdiv_eval_update_from_mesh(struct Subdiv *subdiv, 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. */ void BKE_subdiv_eval_limit_point( @@ -77,8 +83,7 @@ void BKE_subdiv_eval_face_varying( * TODO(sergey): This is currently used together with * BKE_subdiv_eval_final_point() which cas easily evaluate derivatives. * 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( struct Subdiv *subdiv, 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 * 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( struct Subdiv *subdiv, diff --git a/source/blender/blenkernel/intern/subdiv_displacement_multires.c b/source/blender/blenkernel/intern/subdiv_displacement_multires.c index 5744ac3ca0d..d6865e1826f 100644 --- a/source/blender/blenkernel/intern/subdiv_displacement_multires.c +++ b/source/blender/blenkernel/intern/subdiv_displacement_multires.c @@ -49,20 +49,23 @@ typedef struct PolyCornerIndex { typedef struct MultiresDisplacementData { int grid_size; + /* Mesh is used to read external displacement. */ + Mesh *mesh; const MPoly *mpoly; const MDisps *mdisps; /* Indexed by ptex face index, contains polygon/corner which corresponds * to it. * * 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; + /* Sanity check, is used in debug builds. + * Controls that initialize() was called prior to eval_displacement(). */ + bool is_initialized; } MultiresDisplacementData; /* 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 { AVERAGE_WITH_NONE, 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, const int ptex_face_index, const float u, const float v, @@ -245,6 +258,7 @@ static void eval_displacement(SubdivDisplacement *displacement, float r_D[3]) { MultiresDisplacementData *data = displacement->user_data; + BLI_assert(data->is_initialized); const int grid_size = data->grid_size; /* Get displacement in tangent space. */ const MDisps *displacement_grid; @@ -254,8 +268,7 @@ static void eval_displacement(SubdivDisplacement *displacement, &displacement_grid, &grid_u, &grid_v); /* Read displacement from the current displacement grid and see if any - * averaging is needed. - */ + * averaging is needed. */ float tangent_D[3]; eAverageWith average_with = 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 - * 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) { int num_ptex_faces = 0; @@ -323,25 +335,28 @@ static void displacement_data_init_mapping(SubdivDisplacement *displacement, } static void displacement_init_data(SubdivDisplacement *displacement, - const Mesh *mesh, + Mesh *mesh, const MultiresModifierData *mmd) { MultiresDisplacementData *data = displacement->user_data; data->grid_size = BKE_subdiv_grid_size_from_level(mmd->totlvl); + data->mesh = mesh; data->mpoly = mesh->mpoly; data->mdisps = CustomData_get_layer(&mesh->ldata, CD_MDISPS); + data->is_initialized = false; displacement_data_init_mapping(displacement, mesh); } static void displacement_init_functions(SubdivDisplacement *displacement) { + displacement->initialize = initialize; displacement->eval_displacement = eval_displacement; displacement->free = free_displacement; } void BKE_subdiv_displacement_attach_from_multires( Subdiv *subdiv, - const Mesh *mesh, + Mesh *mesh, const MultiresModifierData *mmd) { /* Make sure we don't have previously assigned displacement. */ diff --git a/source/blender/blenkernel/intern/subdiv_eval.c b/source/blender/blenkernel/intern/subdiv_eval.c index f4a9e1a95fd..7043edc7fc9 100644 --- a/source/blender/blenkernel/intern/subdiv_eval.c +++ b/source/blender/blenkernel/intern/subdiv_eval.c @@ -64,6 +64,7 @@ bool BKE_subdiv_eval_begin(Subdiv *subdiv) else { /* TODO(sergey): Check for topology change. */ } + BKE_subdiv_eval_init_displacement(subdiv); return true; } @@ -159,6 +160,17 @@ bool BKE_subdiv_eval_update_from_mesh(Subdiv *subdiv, const Mesh *mesh) 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 ========================== */ void BKE_subdiv_eval_limit_point( -- cgit v1.2.3