Geometry Nodes: Make simulation caching optional #107767
|
@ -567,6 +567,7 @@ const bTheme U_theme_default = {
|
|||
.handle_vertex_size = 4,
|
||||
.anim_active = RGBA(0x4d272766),
|
||||
.anim_preview_range = RGBA(0xa14d0066),
|
||||
.simulated_frames = RGBA(0x721e65ff),
|
||||
},
|
||||
.space_nla = {
|
||||
.back = RGBA(0x30303000),
|
||||
|
|
|
@ -720,7 +720,7 @@ typedef struct PBVHFaceIter {
|
|||
const struct BMesh *bm;
|
||||
CCGKey subdiv_key_;
|
||||
|
||||
int last_face_index_;
|
||||
int last_poly_index_;
|
||||
} PBVHFaceIter;
|
||||
|
||||
void BKE_pbvh_face_iter_init(PBVH *pbvh, PBVHNode *node, PBVHFaceIter *fd);
|
||||
|
|
|
@ -162,7 +162,7 @@ static void mesh_recalc_looptri__single_threaded(const Span<int> corner_verts,
|
|||
const float (*poly_normals)[3])
|
||||
{
|
||||
MemArena *pf_arena = nullptr;
|
||||
uint tri_index = 0;
|
||||
uint looptri_i = 0;
|
||||
|
||||
if (poly_normals != nullptr) {
|
||||
for (const int64_t i : polys.index_range()) {
|
||||
|
@ -170,17 +170,17 @@ static void mesh_recalc_looptri__single_threaded(const Span<int> corner_verts,
|
|||
polys,
|
||||
positions,
|
||||
uint(i),
|
||||
&mlooptri[tri_index],
|
||||
&mlooptri[looptri_i],
|
||||
&pf_arena,
|
||||
poly_normals[i]);
|
||||
tri_index += uint(polys[i].size() - 2);
|
||||
looptri_i += uint(polys[i].size() - 2);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (const int64_t i : polys.index_range()) {
|
||||
mesh_calc_tessellation_for_face(
|
||||
corner_verts, polys, positions, uint(i), &mlooptri[tri_index], &pf_arena);
|
||||
tri_index += uint(polys[i].size() - 2);
|
||||
corner_verts, polys, positions, uint(i), &mlooptri[looptri_i], &pf_arena);
|
||||
looptri_i += uint(polys[i].size() - 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -188,7 +188,7 @@ static void mesh_recalc_looptri__single_threaded(const Span<int> corner_verts,
|
|||
BLI_memarena_free(pf_arena);
|
||||
pf_arena = nullptr;
|
||||
}
|
||||
BLI_assert(tri_index == uint(poly_to_tri_count(int(polys.size()), int(corner_verts.size()))));
|
||||
BLI_assert(looptri_i == uint(poly_to_tri_count(int(polys.size()), int(corner_verts.size()))));
|
||||
}
|
||||
|
||||
struct TessellationUserData {
|
||||
|
@ -213,12 +213,12 @@ static void mesh_calc_tessellation_for_face_fn(void *__restrict userdata,
|
|||
{
|
||||
const TessellationUserData *data = static_cast<const TessellationUserData *>(userdata);
|
||||
TessellationUserTLS *tls_data = static_cast<TessellationUserTLS *>(tls->userdata_chunk);
|
||||
const int tri_index = poly_to_tri_count(index, int(data->polys[index].start()));
|
||||
const int looptri_i = poly_to_tri_count(index, int(data->polys[index].start()));
|
||||
mesh_calc_tessellation_for_face_impl(data->corner_verts,
|
||||
data->polys,
|
||||
data->positions,
|
||||
uint(index),
|
||||
&data->mlooptri[tri_index],
|
||||
&data->mlooptri[looptri_i],
|
||||
&tls_data->pf_arena,
|
||||
false,
|
||||
nullptr);
|
||||
|
@ -230,12 +230,12 @@ static void mesh_calc_tessellation_for_face_with_normal_fn(void *__restrict user
|
|||
{
|
||||
const TessellationUserData *data = static_cast<const TessellationUserData *>(userdata);
|
||||
TessellationUserTLS *tls_data = static_cast<TessellationUserTLS *>(tls->userdata_chunk);
|
||||
const int tri_index = poly_to_tri_count(index, int(data->polys[index].start()));
|
||||
const int looptri_i = poly_to_tri_count(index, int(data->polys[index].start()));
|
||||
mesh_calc_tessellation_for_face_impl(data->corner_verts,
|
||||
data->polys,
|
||||
data->positions,
|
||||
uint(index),
|
||||
&data->mlooptri[tri_index],
|
||||
&data->mlooptri[looptri_i],
|
||||
&tls_data->pf_arena,
|
||||
true,
|
||||
data->poly_normals[index]);
|
||||
|
|
|
@ -1660,7 +1660,7 @@ static void sculpt_update_persistent_base(Object *ob)
|
|||
}
|
||||
|
||||
static void sculpt_update_object(
|
||||
Depsgraph *depsgraph, Object *ob, Object *ob_eval, bool need_pmap, bool is_paint_tool)
|
||||
Depsgraph *depsgraph, Object *ob, Object *ob_eval, bool /*need_pmap*/, bool is_paint_tool)
|
||||
{
|
||||
Scene *scene = DEG_get_input_scene(depsgraph);
|
||||
Sculpt *sd = scene->toolsettings->sculpt;
|
||||
|
@ -1766,13 +1766,13 @@ static void sculpt_update_object(
|
|||
sculpt_attribute_update_refs(ob);
|
||||
sculpt_update_persistent_base(ob);
|
||||
|
||||
if (need_pmap && ob->type == OB_MESH && !ss->pmap) {
|
||||
if (ob->type == OB_MESH && !ss->pmap) {
|
||||
BKE_mesh_vert_poly_map_create(
|
||||
&ss->pmap, &ss->pmap_mem, me->polys(), me->corner_verts().data(), me->totvert);
|
||||
}
|
||||
|
||||
if (ss->pbvh) {
|
||||
BKE_pbvh_pmap_set(ss->pbvh, ss->pmap);
|
||||
}
|
||||
if (ss->pbvh) {
|
||||
BKE_pbvh_pmap_set(ss->pbvh, ss->pmap);
|
||||
}
|
||||
|
||||
if (ss->deform_modifiers_active) {
|
||||
|
|
|
@ -11,10 +11,13 @@
|
|||
#include "BLI_bitmap.h"
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_math_vector.hh"
|
||||
#include "BLI_rand.h"
|
||||
#include "BLI_task.h"
|
||||
#include "BLI_task.hh"
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_vector.hh"
|
||||
#include "BLI_vector_set.hh"
|
||||
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
|
@ -199,10 +202,10 @@ static int partition_indices_faces(int *prim_indices,
|
|||
int i1 = lo, i2 = 0;
|
||||
|
||||
while (i1 < hi) {
|
||||
int poly = looptri_polys[prim_scratch[i2]];
|
||||
const int poly_i = looptri_polys[prim_scratch[i2]];
|
||||
bool side = prim_bbc[prim_scratch[i2]].bcentroid[axis] >= mid;
|
||||
|
||||
while (i1 < hi && looptri_polys[prim_scratch[i2]] == poly) {
|
||||
while (i1 < hi && looptri_polys[prim_scratch[i2]] == poly_i) {
|
||||
prim_indices[side ? hi2-- : lo2++] = prim_scratch[i2];
|
||||
i1++;
|
||||
i2++;
|
||||
|
@ -229,10 +232,10 @@ static int partition_indices_grids(int *prim_indices,
|
|||
int i1 = lo, i2 = 0;
|
||||
|
||||
while (i1 < hi) {
|
||||
int poly = BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, prim_scratch[i2]);
|
||||
int poly_i = BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, prim_scratch[i2]);
|
||||
bool side = prim_bbc[prim_scratch[i2]].bcentroid[axis] >= mid;
|
||||
|
||||
while (i1 < hi && BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, prim_scratch[i2]) == poly) {
|
||||
while (i1 < hi && BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, prim_scratch[i2]) == poly_i) {
|
||||
prim_indices[side ? hi2-- : lo2++] = prim_scratch[i2];
|
||||
i1++;
|
||||
i2++;
|
||||
|
@ -513,21 +516,21 @@ static void test_face_boundaries(PBVH *pbvh)
|
|||
switch (BKE_pbvh_type(pbvh)) {
|
||||
case PBVH_FACES: {
|
||||
for (int j = 0; j < node->totprim; j++) {
|
||||
int poly = pbvh->looptri_polys[node->prim_indices[j]];
|
||||
int poly_i = pbvh->looptri_polys[node->prim_indices[j]];
|
||||
|
||||
if (node_map[poly] >= 0 && node_map[poly] != i) {
|
||||
int old_i = node_map[poly];
|
||||
if (node_map[poly_i] >= 0 && node_map[poly_i] != i) {
|
||||
int old_i = node_map[poly_i];
|
||||
int prim_i = node->prim_indices - pbvh->prim_indices + j;
|
||||
|
||||
printf("PBVH split error; poly: %d, prim_i: %d, node1: %d, node2: %d, totprim: %d\n",
|
||||
poly,
|
||||
poly_i,
|
||||
prim_i,
|
||||
old_i,
|
||||
i,
|
||||
node->totprim);
|
||||
}
|
||||
|
||||
node_map[poly] = i;
|
||||
node_map[poly_i] = i;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -791,16 +794,16 @@ static void pbvh_validate_node_prims(PBVH *pbvh)
|
|||
}
|
||||
|
||||
for (int j = 0; j < node->totprim; j++) {
|
||||
int poly;
|
||||
int poly_i;
|
||||
|
||||
if (pbvh->header.type == PBVH_FACES) {
|
||||
poly = pbvh->looptri_polys[node->prim_indices[j]];
|
||||
poly_i = pbvh->looptri_polys[node->prim_indices[j]];
|
||||
}
|
||||
else {
|
||||
poly = BKE_subdiv_ccg_grid_to_face_index(pbvh->subdiv_ccg, node->prim_indices[j]);
|
||||
poly_i = BKE_subdiv_ccg_grid_to_face_index(pbvh->subdiv_ccg, node->prim_indices[j]);
|
||||
}
|
||||
|
||||
totface = max_ii(totface, poly + 1);
|
||||
totface = max_ii(totface, poly_i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -818,23 +821,23 @@ static void pbvh_validate_node_prims(PBVH *pbvh)
|
|||
}
|
||||
|
||||
for (int j = 0; j < node->totprim; j++) {
|
||||
int poly;
|
||||
int poly_i;
|
||||
|
||||
if (pbvh->header.type == PBVH_FACES) {
|
||||
poly = pbvh->looptri_polys[node->prim_indices[j]];
|
||||
poly_i = pbvh->looptri_polys[node->prim_indices[j]];
|
||||
}
|
||||
else {
|
||||
poly = BKE_subdiv_ccg_grid_to_face_index(pbvh->subdiv_ccg, node->prim_indices[j]);
|
||||
poly_i = BKE_subdiv_ccg_grid_to_face_index(pbvh->subdiv_ccg, node->prim_indices[j]);
|
||||
}
|
||||
|
||||
if (facemap[poly] != -1 && facemap[poly] != i) {
|
||||
if (facemap[poly_i] != -1 && facemap[poly_i] != i) {
|
||||
printf("%s: error: face spanned multiple nodes (old: %d new: %d)\n",
|
||||
__func__,
|
||||
facemap[poly],
|
||||
facemap[poly_i],
|
||||
i);
|
||||
}
|
||||
|
||||
facemap[poly] = i;
|
||||
facemap[poly_i] = i;
|
||||
}
|
||||
}
|
||||
MEM_SAFE_FREE(facemap);
|
||||
|
@ -862,7 +865,10 @@ void BKE_pbvh_update_mesh_pointers(PBVH *pbvh, Mesh *mesh)
|
|||
|
||||
/* Make sure cached normals start out calculated. */
|
||||
mesh->vert_normals();
|
||||
mesh->poly_normals();
|
||||
|
||||
pbvh->vert_normals = BKE_mesh_vert_normals_for_write(mesh);
|
||||
pbvh->poly_normals = mesh->runtime->poly_normals;
|
||||
|
||||
pbvh->vdata = &mesh->vdata;
|
||||
pbvh->ldata = &mesh->ldata;
|
||||
|
@ -1367,7 +1373,6 @@ struct PBVHUpdateData {
|
|||
PBVH *pbvh;
|
||||
Span<PBVHNode *> nodes;
|
||||
|
||||
float (*vert_normals)[3] = nullptr;
|
||||
int flag = 0;
|
||||
bool show_sculpt_face_sets = false;
|
||||
PBVHAttrReq *attrs = nullptr;
|
||||
|
@ -1376,133 +1381,66 @@ struct PBVHUpdateData {
|
|||
PBVHUpdateData(PBVH *pbvh_, Span<PBVHNode *> nodes_) : pbvh(pbvh_), nodes(nodes_) {}
|
||||
};
|
||||
|
||||
static void pbvh_update_normals_clear_task_cb(void *__restrict userdata,
|
||||
const int n,
|
||||
const TaskParallelTLS *__restrict /*tls*/)
|
||||
{
|
||||
PBVHUpdateData *data = static_cast<PBVHUpdateData *>(userdata);
|
||||
PBVH *pbvh = data->pbvh;
|
||||
PBVHNode *node = data->nodes[n];
|
||||
float(*vert_normals)[3] = data->vert_normals;
|
||||
|
||||
if (node->flag & PBVH_UpdateNormals) {
|
||||
const int *verts = node->vert_indices;
|
||||
const int totvert = node->uniq_verts;
|
||||
for (int i = 0; i < totvert; i++) {
|
||||
const int v = verts[i];
|
||||
if (pbvh->vert_bitmap[v]) {
|
||||
zero_v3(vert_normals[v]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void pbvh_update_normals_accum_task_cb(void *__restrict userdata,
|
||||
const int n,
|
||||
const TaskParallelTLS *__restrict /*tls*/)
|
||||
{
|
||||
PBVHUpdateData *data = static_cast<PBVHUpdateData *>(userdata);
|
||||
|
||||
PBVH *pbvh = data->pbvh;
|
||||
PBVHNode *node = data->nodes[n];
|
||||
float(*vert_normals)[3] = data->vert_normals;
|
||||
|
||||
if (node->flag & PBVH_UpdateNormals) {
|
||||
uint mpoly_prev = UINT_MAX;
|
||||
blender::float3 fn;
|
||||
|
||||
const int *faces = node->prim_indices;
|
||||
const int totface = node->totprim;
|
||||
|
||||
for (int i = 0; i < totface; i++) {
|
||||
const int tri_index = faces[i];
|
||||
const int poly_index = pbvh->looptri_polys[tri_index];
|
||||
const MLoopTri *lt = &pbvh->looptri[faces[i]];
|
||||
const int vtri[3] = {
|
||||
pbvh->corner_verts[lt->tri[0]],
|
||||
pbvh->corner_verts[lt->tri[1]],
|
||||
pbvh->corner_verts[lt->tri[2]],
|
||||
};
|
||||
const int sides = 3;
|
||||
|
||||
/* Face normal and mask */
|
||||
if (poly_index != mpoly_prev) {
|
||||
const blender::IndexRange poly = pbvh->polys[poly_index];
|
||||
fn = blender::bke::mesh::poly_normal_calc(
|
||||
{reinterpret_cast<const blender::float3 *>(pbvh->vert_positions), pbvh->totvert},
|
||||
{&pbvh->corner_verts[poly.start()], poly.size()});
|
||||
mpoly_prev = poly_index;
|
||||
}
|
||||
|
||||
for (int j = sides; j--;) {
|
||||
const int v = vtri[j];
|
||||
|
||||
if (pbvh->vert_bitmap[v]) {
|
||||
/* NOTE: This avoids `lock, add_v3_v3, unlock`
|
||||
* and is five to ten times quicker than a spin-lock.
|
||||
* Not exact equivalent though, since atomicity is only ensured for one component
|
||||
* of the vector at a time, but here it shall not make any sensible difference. */
|
||||
for (int k = 3; k--;) {
|
||||
atomic_add_and_fetch_fl(&vert_normals[v][k], fn[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void pbvh_update_normals_store_task_cb(void *__restrict userdata,
|
||||
const int n,
|
||||
const TaskParallelTLS *__restrict /*tls*/)
|
||||
{
|
||||
PBVHUpdateData *data = static_cast<PBVHUpdateData *>(userdata);
|
||||
PBVH *pbvh = data->pbvh;
|
||||
PBVHNode *node = data->nodes[n];
|
||||
float(*vert_normals)[3] = data->vert_normals;
|
||||
|
||||
if (node->flag & PBVH_UpdateNormals) {
|
||||
const int *verts = node->vert_indices;
|
||||
const int totvert = node->uniq_verts;
|
||||
|
||||
for (int i = 0; i < totvert; i++) {
|
||||
const int v = verts[i];
|
||||
|
||||
/* No atomics necessary because we are iterating over uniq_verts only,
|
||||
* so we know only this thread will handle this vertex. */
|
||||
if (pbvh->vert_bitmap[v]) {
|
||||
normalize_v3(vert_normals[v]);
|
||||
pbvh->vert_bitmap[v] = false;
|
||||
}
|
||||
}
|
||||
|
||||
node->flag &= ~PBVH_UpdateNormals;
|
||||
}
|
||||
}
|
||||
|
||||
static void pbvh_faces_update_normals(PBVH *pbvh, Span<PBVHNode *> nodes)
|
||||
{
|
||||
/* subtle assumptions:
|
||||
* - We know that for all edited vertices, the nodes with faces
|
||||
* adjacent to these vertices have been marked with PBVH_UpdateNormals.
|
||||
* This is true because if the vertex is inside the brush radius, the
|
||||
* bounding box of its adjacent faces will be as well.
|
||||
* - However this is only true for the vertices that have actually been
|
||||
* edited, not for all vertices in the nodes marked for update, so we
|
||||
* can only update vertices marked in the `vert_bitmap`.
|
||||
*/
|
||||
using namespace blender;
|
||||
using namespace blender::bke;
|
||||
const Span<float3> positions(reinterpret_cast<const float3 *>(pbvh->vert_positions),
|
||||
pbvh->totvert);
|
||||
const OffsetIndices polys = pbvh->polys;
|
||||
const Span<int> corner_verts(pbvh->corner_verts, pbvh->mesh->totloop);
|
||||
|
||||
PBVHUpdateData data(pbvh, nodes);
|
||||
data.pbvh = pbvh;
|
||||
data.nodes = nodes;
|
||||
data.vert_normals = pbvh->vert_normals;
|
||||
MutableSpan<bool> update_tags(pbvh->vert_bitmap, pbvh->totvert);
|
||||
|
||||
TaskParallelSettings settings;
|
||||
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
|
||||
VectorSet<int> polys_to_update;
|
||||
for (const PBVHNode *node : nodes) {
|
||||
for (const int vert : Span(node->vert_indices, node->uniq_verts)) {
|
||||
if (update_tags[vert]) {
|
||||
polys_to_update.add_multiple({pbvh->pmap[vert].indices, pbvh->pmap[vert].count});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Zero normals before accumulation. */
|
||||
BLI_task_parallel_range(0, nodes.size(), &data, pbvh_update_normals_clear_task_cb, &settings);
|
||||
BLI_task_parallel_range(0, nodes.size(), &data, pbvh_update_normals_accum_task_cb, &settings);
|
||||
BLI_task_parallel_range(0, nodes.size(), &data, pbvh_update_normals_store_task_cb, &settings);
|
||||
if (polys_to_update.is_empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
MutableSpan<float3> vert_normals(reinterpret_cast<float3 *>(pbvh->vert_normals), pbvh->totvert);
|
||||
MutableSpan<float3> poly_normals = pbvh->poly_normals;
|
||||
|
||||
VectorSet<int> verts_to_update;
|
||||
threading::parallel_invoke(
|
||||
[&]() {
|
||||
threading::parallel_for(polys_to_update.index_range(), 512, [&](const IndexRange range) {
|
||||
for (const int i : polys_to_update.as_span().slice(range)) {
|
||||
poly_normals[i] = mesh::poly_normal_calc(positions, corner_verts.slice(polys[i]));
|
||||
}
|
||||
});
|
||||
},
|
||||
[&]() {
|
||||
/* Update all normals connected to affected faces faces, even if not explicitly tagged. */
|
||||
verts_to_update.reserve(polys_to_update.size());
|
||||
for (const int poly : polys_to_update) {
|
||||
verts_to_update.add_multiple(corner_verts.slice(polys[poly]));
|
||||
}
|
||||
|
||||
for (const int vert : verts_to_update) {
|
||||
update_tags[vert] = false;
|
||||
}
|
||||
for (PBVHNode *node : nodes) {
|
||||
node->flag &= ~PBVH_UpdateNormals;
|
||||
}
|
||||
});
|
||||
|
||||
threading::parallel_for(verts_to_update.index_range(), 1024, [&](const IndexRange range) {
|
||||
for (const int vert : verts_to_update.as_span().slice(range)) {
|
||||
float3 normal(0.0f);
|
||||
for (const int poly : Span(pbvh->pmap[vert].indices, pbvh->pmap[vert].count)) {
|
||||
normal += poly_normals[poly];
|
||||
}
|
||||
vert_normals[vert] = math::normalize(normal);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void pbvh_update_mask_redraw_task_cb(void *__restrict userdata,
|
||||
|
@ -2532,17 +2470,17 @@ static bool pbvh_faces_node_raycast(PBVH *pbvh,
|
|||
{
|
||||
const float(*positions)[3] = pbvh->vert_positions;
|
||||
const int *corner_verts = pbvh->corner_verts;
|
||||
const int *faces = node->prim_indices;
|
||||
int totface = node->totprim;
|
||||
const int *looptris = node->prim_indices;
|
||||
int looptris_num = node->totprim;
|
||||
bool hit = false;
|
||||
float nearest_vertex_co[3] = {0.0f};
|
||||
|
||||
for (int i = 0; i < totface; i++) {
|
||||
const int tri_index = faces[i];
|
||||
const MLoopTri *lt = &pbvh->looptri[tri_index];
|
||||
for (int i = 0; i < looptris_num; i++) {
|
||||
const int looptri_i = looptris[i];
|
||||
const MLoopTri *lt = &pbvh->looptri[looptri_i];
|
||||
const int *face_verts = node->face_vert_indices[i];
|
||||
|
||||
if (paint_is_face_hidden(pbvh->looptri_polys, pbvh->hide_poly, tri_index)) {
|
||||
if (paint_is_face_hidden(pbvh->looptri_polys, pbvh->hide_poly, looptri_i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2578,7 +2516,7 @@ static bool pbvh_faces_node_raycast(PBVH *pbvh,
|
|||
len_squared_v3v3(location, co[j]) < len_squared_v3v3(location, nearest_vertex_co)) {
|
||||
copy_v3_v3(nearest_vertex_co, co[j]);
|
||||
r_active_vertex->i = corner_verts[lt->tri[j]];
|
||||
*r_active_face_index = pbvh->looptri_polys[tri_index];
|
||||
*r_active_face_index = pbvh->looptri_polys[looptri_i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2843,16 +2781,16 @@ static bool pbvh_faces_node_nearest_to_ray(PBVH *pbvh,
|
|||
{
|
||||
const float(*positions)[3] = pbvh->vert_positions;
|
||||
const int *corner_verts = pbvh->corner_verts;
|
||||
const int *faces = node->prim_indices;
|
||||
int i, totface = node->totprim;
|
||||
const int *looptris = node->prim_indices;
|
||||
int i, looptris_num = node->totprim;
|
||||
bool hit = false;
|
||||
|
||||
for (i = 0; i < totface; i++) {
|
||||
const int tri_index = faces[i];
|
||||
const MLoopTri *lt = &pbvh->looptri[tri_index];
|
||||
for (i = 0; i < looptris_num; i++) {
|
||||
const int looptri_i = looptris[i];
|
||||
const MLoopTri *lt = &pbvh->looptri[looptri_i];
|
||||
const int *face_verts = node->face_vert_indices[i];
|
||||
|
||||
if (paint_is_face_hidden(pbvh->looptri_polys, pbvh->hide_poly, tri_index)) {
|
||||
if (paint_is_face_hidden(pbvh->looptri_polys, pbvh->hide_poly, looptri_i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -3635,15 +3573,15 @@ static void pbvh_face_iter_step(PBVHFaceIter *fd, bool do_step)
|
|||
}
|
||||
case PBVH_GRIDS:
|
||||
case PBVH_FACES: {
|
||||
int face_index = 0;
|
||||
int poly_i = 0;
|
||||
|
||||
if (do_step) {
|
||||
fd->prim_index_++;
|
||||
|
||||
while (fd->prim_index_ < fd->node_->totprim) {
|
||||
face_index = face_iter_prim_to_face(fd, fd->node_->prim_indices[fd->prim_index_]);
|
||||
poly_i = face_iter_prim_to_face(fd, fd->node_->prim_indices[fd->prim_index_]);
|
||||
|
||||
if (face_index != fd->last_face_index_) {
|
||||
if (poly_i != fd->last_poly_index_) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3651,24 +3589,24 @@ static void pbvh_face_iter_step(PBVHFaceIter *fd, bool do_step)
|
|||
}
|
||||
}
|
||||
else if (fd->prim_index_ < fd->node_->totprim) {
|
||||
face_index = face_iter_prim_to_face(fd, fd->node_->prim_indices[fd->prim_index_]);
|
||||
poly_i = face_iter_prim_to_face(fd, fd->node_->prim_indices[fd->prim_index_]);
|
||||
}
|
||||
|
||||
if (fd->prim_index_ >= fd->node_->totprim) {
|
||||
return;
|
||||
}
|
||||
|
||||
fd->last_face_index_ = face_index;
|
||||
const int poly_start = fd->poly_offsets_[face_index];
|
||||
const int poly_size = fd->poly_offsets_[face_index + 1] - poly_start;
|
||||
fd->last_poly_index_ = poly_i;
|
||||
const int poly_start = fd->poly_offsets_[poly_i];
|
||||
const int poly_size = fd->poly_offsets_[poly_i + 1] - poly_start;
|
||||
|
||||
fd->face.i = fd->index = face_index;
|
||||
fd->face.i = fd->index = poly_i;
|
||||
|
||||
if (fd->face_sets_) {
|
||||
fd->face_set = fd->face_sets_ + face_index;
|
||||
fd->face_set = fd->face_sets_ + poly_i;
|
||||
}
|
||||
if (fd->hide_poly_) {
|
||||
fd->hide = fd->hide_poly_ + face_index;
|
||||
fd->hide = fd->hide_poly_ + poly_i;
|
||||
}
|
||||
|
||||
pbvh_face_iter_verts_reserve(fd, poly_size);
|
||||
|
@ -3715,7 +3653,7 @@ void BKE_pbvh_face_iter_init(PBVH *pbvh, PBVHNode *node, PBVHFaceIter *fd)
|
|||
fd->looptri_polys_ = pbvh->looptri_polys;
|
||||
fd->hide_poly_ = pbvh->hide_poly;
|
||||
fd->face_sets_ = pbvh->face_sets;
|
||||
fd->last_face_index_ = -1;
|
||||
fd->last_poly_index_ = -1;
|
||||
|
||||
break;
|
||||
case PBVH_BMESH:
|
||||
|
@ -3799,8 +3737,8 @@ void BKE_pbvh_sync_visibility_from_verts(PBVH *pbvh, Mesh *mesh)
|
|||
&mesh->pdata, CD_PROP_BOOL, ".hide_poly", mesh->totpoly));
|
||||
|
||||
bool delete_hide_poly = true;
|
||||
for (const int face_index : polys.index_range()) {
|
||||
const blender::IndexRange poly = polys[face_index];
|
||||
for (const int poly_i : polys.index_range()) {
|
||||
const blender::IndexRange poly = polys[poly_i];
|
||||
bool hidden = false;
|
||||
|
||||
for (int loop_index = 0; !hidden && loop_index < poly.size(); loop_index++) {
|
||||
|
@ -3827,7 +3765,7 @@ void BKE_pbvh_sync_visibility_from_verts(PBVH *pbvh, Mesh *mesh)
|
|||
|
||||
if (hide_poly) {
|
||||
delete_hide_poly = delete_hide_poly && !hidden;
|
||||
hide_poly[face_index] = hidden;
|
||||
hide_poly[poly_i] = hidden;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "BLI_vector.hh"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_span.hh"
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
|
@ -155,6 +157,7 @@ struct PBVH {
|
|||
|
||||
/* NOTE: Normals are not `const` because they can be updated for drawing by sculpt code. */
|
||||
float (*vert_normals)[3];
|
||||
blender::MutableSpan<blender::float3> poly_normals;
|
||||
bool *hide_vert;
|
||||
float (*vert_positions)[3];
|
||||
blender::OffsetIndices<int> polys;
|
||||
|
|
|
@ -704,7 +704,7 @@ static bool do_versions_sequencer_init_retiming_tool_data(Sequence *seq, void *u
|
|||
|
||||
SeqRetimingHandle *handle = &seq->retiming_handles[seq->retiming_handle_num - 1];
|
||||
handle->strip_frame_index = round_fl_to_int(content_length / seq->speed_factor);
|
||||
seq->speed_factor = 0.0f;
|
||||
seq->speed_factor = 1.0f;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1174,7 +1174,8 @@ void do_versions_after_linking_300(FileData * /*fd*/, Main *bmain)
|
|||
SOCK_OBJECT,
|
||||
SOCK_COLLECTION,
|
||||
SOCK_TEXTURE,
|
||||
SOCK_MATERIAL)) {
|
||||
SOCK_MATERIAL))
|
||||
{
|
||||
link->tosock = link->tosock->next;
|
||||
}
|
||||
}
|
||||
|
@ -1786,6 +1787,18 @@ static bool version_set_seq_single_frame_content(Sequence *seq, void * /*user_da
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool version_seq_fix_broken_sound_strips(Sequence *seq, void * /*user_data*/)
|
||||
{
|
||||
if (seq->type != SEQ_TYPE_SOUND_RAM || seq->speed_factor != 0.0f) {
|
||||
return true;
|
||||
}
|
||||
|
||||
seq->speed_factor = 1.0f;
|
||||
SEQ_retiming_data_clear(seq);
|
||||
seq->startofs = 0.0f;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Those `version_liboverride_rnacollections_*` functions mimic the old, pre-3.0 code to find
|
||||
* anchor and source items in the given list of modifiers, constraints etc., using only the
|
||||
* `subitem_local` data of the override property operation.
|
||||
|
@ -2633,7 +2646,8 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 300, 17)) {
|
||||
if (!DNA_struct_elem_find(
|
||||
fd->filesdna, "View3DOverlay", "float", "normals_constant_screen_size")) {
|
||||
fd->filesdna, "View3DOverlay", "float", "normals_constant_screen_size"))
|
||||
{
|
||||
LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
|
||||
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
|
||||
LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
|
||||
|
@ -2661,7 +2675,8 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 300, 18)) {
|
||||
if (!DNA_struct_elem_find(
|
||||
fd->filesdna, "WorkSpace", "AssetLibraryReference", "asset_library_ref")) {
|
||||
fd->filesdna, "WorkSpace", "AssetLibraryReference", "asset_library_ref"))
|
||||
{
|
||||
LISTBASE_FOREACH (WorkSpace *, workspace, &bmain->workspaces) {
|
||||
BKE_asset_library_reference_init_default(&workspace->asset_library_ref);
|
||||
}
|
||||
|
@ -4354,5 +4369,13 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
*/
|
||||
{
|
||||
/* Keep this block, even when empty. */
|
||||
|
||||
/* Fix sound strips with speed factor set to 0. See #107289. */
|
||||
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
||||
Editing *ed = SEQ_editing_get(scene);
|
||||
if (ed != nullptr) {
|
||||
SEQ_for_each_callback(&ed->seqbase, version_seq_fix_broken_sound_strips, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,6 +109,7 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme)
|
|||
{
|
||||
/* Keep this block, even when empty. */
|
||||
FROM_DEFAULT_V4_UCHAR(space_node.node_zone_simulation);
|
||||
FROM_DEFAULT_V4_UCHAR(space_action.simulated_frames);
|
||||
}
|
||||
|
||||
#undef FROM_DEFAULT_V4_UCHAR
|
||||
|
|
|
@ -30,7 +30,7 @@ void PlaneTrackDeformNode::convert_to_operations(NodeConverter &converter,
|
|||
warp_image_operation->set_tracking_object(data->tracking_object);
|
||||
warp_image_operation->set_plane_track_name(data->plane_track_name);
|
||||
warp_image_operation->set_framenumber(frame_number);
|
||||
if (data->flag & CMP_NODEFLAG_PLANETRACKDEFORM_MOTION_BLUR) {
|
||||
if (data->flag & CMP_NODE_PLANE_TRACK_DEFORM_FLAG_MOTION_BLUR) {
|
||||
warp_image_operation->set_motion_blur_samples(data->motion_blur_samples);
|
||||
warp_image_operation->set_motion_blur_shutter(data->motion_blur_shutter);
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ void PlaneTrackDeformNode::convert_to_operations(NodeConverter &converter,
|
|||
plane_mask_operation->set_tracking_object(data->tracking_object);
|
||||
plane_mask_operation->set_plane_track_name(data->plane_track_name);
|
||||
plane_mask_operation->set_framenumber(frame_number);
|
||||
if (data->flag & CMP_NODEFLAG_PLANETRACKDEFORM_MOTION_BLUR) {
|
||||
if (data->flag & CMP_NODE_PLANE_TRACK_DEFORM_FLAG_MOTION_BLUR) {
|
||||
plane_mask_operation->set_motion_blur_samples(data->motion_blur_samples);
|
||||
plane_mask_operation->set_motion_blur_shutter(data->motion_blur_shutter);
|
||||
}
|
||||
|
|
|
@ -191,9 +191,10 @@ struct PBVHBatches {
|
|||
switch (args->pbvh_type) {
|
||||
case PBVH_FACES: {
|
||||
for (int i = 0; i < args->totprim; i++) {
|
||||
int face_index = args->looptri_polys[args->prim_indices[i]];
|
||||
const int looptri_i = args->prim_indices[i];
|
||||
const int poly_i = args->looptri_polys[looptri_i];
|
||||
|
||||
if (args->hide_poly && args->hide_poly[face_index]) {
|
||||
if (args->hide_poly && args->hide_poly[poly_i]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -336,8 +337,8 @@ struct PBVHBatches {
|
|||
int last_poly = -1;
|
||||
bool flat = false;
|
||||
|
||||
foreach_faces([&](int /*buffer_i*/, int /*tri_i*/, int vertex_i, const int tri) {
|
||||
const int poly_i = args->looptri_polys[tri];
|
||||
foreach_faces([&](int /*buffer_i*/, int /*tri_i*/, int vertex_i, const int looptri_i) {
|
||||
const int poly_i = args->looptri_polys[looptri_i];
|
||||
if (poly_i != last_poly) {
|
||||
last_poly = poly_i;
|
||||
flat = sharp_faces && sharp_faces[poly_i];
|
||||
|
@ -545,20 +546,20 @@ struct PBVHBatches {
|
|||
{
|
||||
const blender::Span<int> corner_verts = args->corner_verts;
|
||||
auto foreach_faces =
|
||||
[&](std::function<void(int buffer_i, int tri_i, int vertex_i, const int tri)> func) {
|
||||
[&](std::function<void(int buffer_i, int tri_i, int vertex_i, const int /*looptri_i*/)>
|
||||
func) {
|
||||
int buffer_i = 0;
|
||||
|
||||
for (int i : IndexRange(args->totprim)) {
|
||||
int face_index = args->looptri_polys[args->prim_indices[i]];
|
||||
const int looptri_i = args->prim_indices[i];
|
||||
const int poly_i = args->looptri_polys[looptri_i];
|
||||
|
||||
if (args->hide_poly && args->hide_poly[face_index]) {
|
||||
if (args->hide_poly && args->hide_poly[poly_i]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const int tri = args->prim_indices[i];
|
||||
|
||||
for (int j : IndexRange(3)) {
|
||||
func(buffer_i, j, corner_verts[args->mlooptri[tri].tri[j]], tri);
|
||||
func(buffer_i, j, corner_verts[args->mlooptri[looptri_i].tri[j]], looptri_i);
|
||||
buffer_i++;
|
||||
}
|
||||
}
|
||||
|
@ -580,7 +581,7 @@ struct PBVHBatches {
|
|||
|
||||
switch (vbo.type) {
|
||||
case CD_PBVH_CO_TYPE:
|
||||
foreach_faces([&](int /*buffer_i*/, int /*tri_i*/, int vertex_i, const int /*tri*/) {
|
||||
foreach_faces([&](int /*buffer_i*/, int /*tri_i*/, int vertex_i, const int /*looptri_i*/) {
|
||||
*static_cast<float3 *>(GPU_vertbuf_raw_step(&access)) = args->vert_positions[vertex_i];
|
||||
});
|
||||
break;
|
||||
|
@ -592,14 +593,17 @@ struct PBVHBatches {
|
|||
CustomData_get_layer(args->vdata, CD_PAINT_MASK));
|
||||
|
||||
if (mask) {
|
||||
foreach_faces([&](int /*buffer_i*/, int /*tri_i*/, int vertex_i, const int /*tri*/) {
|
||||
*static_cast<uchar *>(GPU_vertbuf_raw_step(&access)) = uchar(mask[vertex_i] * 255.0f);
|
||||
});
|
||||
foreach_faces(
|
||||
[&](int /*buffer_i*/, int /*tri_i*/, int vertex_i, const int /*looptri_i*/) {
|
||||
*static_cast<uchar *>(GPU_vertbuf_raw_step(&access)) = uchar(mask[vertex_i] *
|
||||
255.0f);
|
||||
});
|
||||
}
|
||||
else {
|
||||
foreach_faces([&](int /*buffer_i*/, int /*tri_i*/, int /*vertex_i*/, const int /*tri*/) {
|
||||
*static_cast<uchar *>(GPU_vertbuf_raw_step(&access)) = 0;
|
||||
});
|
||||
foreach_faces(
|
||||
[&](int /*buffer_i*/, int /*tri_i*/, int /*vertex_i*/, const int /*looptri_i*/) {
|
||||
*static_cast<uchar *>(GPU_vertbuf_raw_step(&access)) = 0;
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -611,31 +615,34 @@ struct PBVHBatches {
|
|||
int last_poly = -1;
|
||||
uchar fset_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
|
||||
|
||||
foreach_faces([&](int /*buffer_i*/, int /*tri_i*/, int /*vertex_i*/, const int tri) {
|
||||
const int poly_i = args->looptri_polys[tri];
|
||||
if (last_poly != poly_i) {
|
||||
last_poly = poly_i;
|
||||
foreach_faces(
|
||||
[&](int /*buffer_i*/, int /*tri_i*/, int /*vertex_i*/, const int looptri_i) {
|
||||
const int poly_i = args->looptri_polys[looptri_i];
|
||||
if (last_poly != poly_i) {
|
||||
last_poly = poly_i;
|
||||
|
||||
const int fset = face_sets[poly_i];
|
||||
const int fset = face_sets[poly_i];
|
||||
|
||||
if (fset != args->face_sets_color_default) {
|
||||
BKE_paint_face_set_overlay_color_get(fset, args->face_sets_color_seed, fset_color);
|
||||
}
|
||||
else {
|
||||
/* Skip for the default color face set to render it white. */
|
||||
fset_color[0] = fset_color[1] = fset_color[2] = UCHAR_MAX;
|
||||
}
|
||||
}
|
||||
if (fset != args->face_sets_color_default) {
|
||||
BKE_paint_face_set_overlay_color_get(
|
||||
fset, args->face_sets_color_seed, fset_color);
|
||||
}
|
||||
else {
|
||||
/* Skip for the default color face set to render it white. */
|
||||
fset_color[0] = fset_color[1] = fset_color[2] = UCHAR_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
*static_cast<uchar3 *>(GPU_vertbuf_raw_step(&access)) = fset_color;
|
||||
});
|
||||
*static_cast<uchar3 *>(GPU_vertbuf_raw_step(&access)) = fset_color;
|
||||
});
|
||||
}
|
||||
else {
|
||||
uchar fset_color[4] = {255, 255, 255, 255};
|
||||
|
||||
foreach_faces([&](int /*buffer_i*/, int /*tri_i*/, int /*vertex_i*/, const int /*tri*/) {
|
||||
*static_cast<uchar3 *>(GPU_vertbuf_raw_step(&access)) = fset_color;
|
||||
});
|
||||
foreach_faces(
|
||||
[&](int /*buffer_i*/, int /*tri_i*/, int /*vertex_i*/, const int /*looptri_i*/) {
|
||||
*static_cast<uchar3 *>(GPU_vertbuf_raw_step(&access)) = fset_color;
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -645,25 +652,26 @@ struct PBVHBatches {
|
|||
const MPropCol *mpropcol = static_cast<const MPropCol *>(
|
||||
CustomData_get_layer_named(args->vdata, CD_PROP_COLOR, vbo.name.c_str()));
|
||||
|
||||
foreach_faces([&](int /*buffer_i*/, int /*tri_i*/, int vertex_i, const int /*tri*/) {
|
||||
ushort color[4];
|
||||
const MPropCol *col = mpropcol + vertex_i;
|
||||
foreach_faces(
|
||||
[&](int /*buffer_i*/, int /*tri_i*/, int vertex_i, const int /*looptri_i*/) {
|
||||
ushort color[4];
|
||||
const MPropCol *col = mpropcol + vertex_i;
|
||||
|
||||
color[0] = unit_float_to_ushort_clamp(col->color[0]);
|
||||
color[1] = unit_float_to_ushort_clamp(col->color[1]);
|
||||
color[2] = unit_float_to_ushort_clamp(col->color[2]);
|
||||
color[3] = unit_float_to_ushort_clamp(col->color[3]);
|
||||
color[0] = unit_float_to_ushort_clamp(col->color[0]);
|
||||
color[1] = unit_float_to_ushort_clamp(col->color[1]);
|
||||
color[2] = unit_float_to_ushort_clamp(col->color[2]);
|
||||
color[3] = unit_float_to_ushort_clamp(col->color[3]);
|
||||
|
||||
*static_cast<ushort4 *>(GPU_vertbuf_raw_step(&access)) = color;
|
||||
});
|
||||
*static_cast<ushort4 *>(GPU_vertbuf_raw_step(&access)) = color;
|
||||
});
|
||||
}
|
||||
else if (vbo.domain == ATTR_DOMAIN_CORNER) {
|
||||
const MPropCol *mpropcol = static_cast<const MPropCol *>(
|
||||
CustomData_get_layer_named(args->ldata, CD_PROP_COLOR, vbo.name.c_str()));
|
||||
|
||||
foreach_faces([&](int /*buffer_i*/, int tri_i, int /*vertex_i*/, const int tri) {
|
||||
foreach_faces([&](int /*buffer_i*/, int tri_i, int /*vertex_i*/, const int looptri_i) {
|
||||
ushort color[4];
|
||||
const MPropCol *col = mpropcol + args->mlooptri[tri].tri[tri_i];
|
||||
const MPropCol *col = mpropcol + args->mlooptri[looptri_i].tri[tri_i];
|
||||
|
||||
color[0] = unit_float_to_ushort_clamp(col->color[0]);
|
||||
color[1] = unit_float_to_ushort_clamp(col->color[1]);
|
||||
|
@ -679,25 +687,26 @@ struct PBVHBatches {
|
|||
const MLoopCol *mbytecol = static_cast<const MLoopCol *>(
|
||||
CustomData_get_layer_named(args->vdata, CD_PROP_BYTE_COLOR, vbo.name.c_str()));
|
||||
|
||||
foreach_faces([&](int /*buffer_i*/, int /*tri_i*/, int vertex_i, const int /*tri*/) {
|
||||
ushort color[4];
|
||||
const MLoopCol *col = mbytecol + vertex_i;
|
||||
foreach_faces(
|
||||
[&](int /*buffer_i*/, int /*tri_i*/, int vertex_i, const int /*looptri_i*/) {
|
||||
ushort color[4];
|
||||
const MLoopCol *col = mbytecol + vertex_i;
|
||||
|
||||
color[0] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[col->r]);
|
||||
color[1] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[col->g]);
|
||||
color[2] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[col->b]);
|
||||
color[3] = col->a * 257;
|
||||
color[0] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[col->r]);
|
||||
color[1] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[col->g]);
|
||||
color[2] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[col->b]);
|
||||
color[3] = col->a * 257;
|
||||
|
||||
*static_cast<ushort4 *>(GPU_vertbuf_raw_step(&access)) = color;
|
||||
});
|
||||
*static_cast<ushort4 *>(GPU_vertbuf_raw_step(&access)) = color;
|
||||
});
|
||||
}
|
||||
else if (vbo.domain == ATTR_DOMAIN_CORNER) {
|
||||
const MLoopCol *mbytecol = static_cast<const MLoopCol *>(
|
||||
CustomData_get_layer_named(args->ldata, CD_PROP_BYTE_COLOR, vbo.name.c_str()));
|
||||
|
||||
foreach_faces([&](int /*buffer_i*/, int tri_i, int /*vertex_i*/, const int tri) {
|
||||
foreach_faces([&](int /*buffer_i*/, int tri_i, int /*vertex_i*/, const int looptri_i) {
|
||||
ushort color[4];
|
||||
const MLoopCol *col = mbytecol + args->mlooptri[tri].tri[tri_i];
|
||||
const MLoopCol *col = mbytecol + args->mlooptri[looptri_i].tri[tri_i];
|
||||
|
||||
color[0] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[col->r]);
|
||||
color[1] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[col->g]);
|
||||
|
@ -712,9 +721,9 @@ struct PBVHBatches {
|
|||
const float2 *mloopuv = static_cast<const float2 *>(
|
||||
CustomData_get_layer_named(args->ldata, CD_PROP_FLOAT2, vbo.name.c_str()));
|
||||
|
||||
foreach_faces([&](int /*buffer_i*/, int tri_i, int /*vertex_i*/, const int tri) {
|
||||
foreach_faces([&](int /*buffer_i*/, int tri_i, int /*vertex_i*/, const int looptri_i) {
|
||||
*static_cast<float2 *>(
|
||||
GPU_vertbuf_raw_step(&access)) = mloopuv[args->mlooptri[tri].tri[tri_i]];
|
||||
GPU_vertbuf_raw_step(&access)) = mloopuv[args->mlooptri[looptri_i].tri[tri_i]];
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
@ -965,8 +974,9 @@ struct PBVHBatches {
|
|||
CustomData_get_layer_named(args->pdata, CD_PROP_INT32, "material_index"));
|
||||
|
||||
if (mat_index && args->totprim) {
|
||||
int poly_index = args->looptri_polys[args->prim_indices[0]];
|
||||
material_index = mat_index[poly_index];
|
||||
const int looptri_i = args->prim_indices[0];
|
||||
const int poly_i = args->looptri_polys[looptri_i];
|
||||
material_index = mat_index[poly_i];
|
||||
}
|
||||
|
||||
const blender::Span<blender::int2> edges = args->me->edges();
|
||||
|
@ -974,13 +984,13 @@ struct PBVHBatches {
|
|||
/* Calculate number of edges. */
|
||||
int edge_count = 0;
|
||||
for (int i = 0; i < args->totprim; i++) {
|
||||
const int tri_i = args->prim_indices[i];
|
||||
const int poly_i = args->looptri_polys[tri_i];
|
||||
const int looptri_i = args->prim_indices[i];
|
||||
const int poly_i = args->looptri_polys[looptri_i];
|
||||
if (args->hide_poly && args->hide_poly[poly_i]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const MLoopTri *lt = args->mlooptri + args->prim_indices[i];
|
||||
const MLoopTri *lt = &args->mlooptri[looptri_i];
|
||||
int r_edges[3];
|
||||
BKE_mesh_looptri_get_real_edges(
|
||||
edges.data(), args->corner_verts.data(), args->corner_edges.data(), lt, r_edges);
|
||||
|
@ -1001,13 +1011,13 @@ struct PBVHBatches {
|
|||
|
||||
int vertex_i = 0;
|
||||
for (int i = 0; i < args->totprim; i++) {
|
||||
const int tri_i = args->prim_indices[i];
|
||||
const int poly_i = args->looptri_polys[tri_i];
|
||||
const int looptri_i = args->prim_indices[i];
|
||||
const int poly_i = args->looptri_polys[looptri_i];
|
||||
if (args->hide_poly && args->hide_poly[poly_i]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const MLoopTri *lt = args->mlooptri + args->prim_indices[i];
|
||||
const MLoopTri *lt = &args->mlooptri[looptri_i];
|
||||
int r_edges[3];
|
||||
BKE_mesh_looptri_get_real_edges(
|
||||
edges.data(), args->corner_verts.data(), args->corner_edges.data(), lt, r_edges);
|
||||
|
@ -1059,8 +1069,8 @@ struct PBVHBatches {
|
|||
CustomData_get_layer_named(args->pdata, CD_PROP_INT32, "material_index"));
|
||||
|
||||
if (mat_index && args->totprim) {
|
||||
int poly_index = BKE_subdiv_ccg_grid_to_face_index(args->subdiv_ccg, args->grid_indices[0]);
|
||||
material_index = mat_index[poly_index];
|
||||
int poly_i = BKE_subdiv_ccg_grid_to_face_index(args->subdiv_ccg, args->grid_indices[0]);
|
||||
material_index = mat_index[poly_i];
|
||||
}
|
||||
|
||||
needs_tri_index = true;
|
||||
|
|
|
@ -180,6 +180,7 @@ typedef enum ThemeColorID {
|
|||
TH_NODE_ATTRIBUTE,
|
||||
|
||||
TH_NODE_ZONE_SIMULATION,
|
||||
TH_SIMULATED_FRAMES,
|
||||
|
||||
TH_CONSOLE_OUTPUT,
|
||||
TH_CONSOLE_INPUT,
|
||||
|
|
|
@ -644,6 +644,9 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
|
|||
case TH_NODE_ZONE_SIMULATION:
|
||||
cp = ts->node_zone_simulation;
|
||||
break;
|
||||
case TH_SIMULATED_FRAMES:
|
||||
cp = ts->simulated_frames;
|
||||
break;
|
||||
|
||||
case TH_SEQ_MOVIE:
|
||||
cp = ts->movie;
|
||||
|
|
|
@ -18,10 +18,12 @@
|
|||
|
||||
#include "DNA_curve_types.h"
|
||||
#include "DNA_lattice_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_deform.h"
|
||||
#include "BKE_layer.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_object.h"
|
||||
|
@ -53,6 +55,7 @@ typedef struct UndoLattice {
|
|||
char typeu, typev, typew;
|
||||
float fu, fv, fw;
|
||||
float du, dv, dw;
|
||||
MDeformVert *dvert;
|
||||
size_t undo_size;
|
||||
} UndoLattice;
|
||||
|
||||
|
@ -68,6 +71,14 @@ static void undolatt_to_editlatt(UndoLattice *ult, EditLatt *editlatt)
|
|||
memcpy(editlatt->latt->def, ult->def, sizeof(BPoint) * len_src);
|
||||
}
|
||||
|
||||
/* Even for the same amount of points we dont just copy memory for MDeformVert, relations to
|
||||
* MDeformWeight might have changed. */
|
||||
if (editlatt->latt->dvert && ult->dvert) {
|
||||
BKE_defvert_array_free(editlatt->latt->dvert, len_dst);
|
||||
editlatt->latt->dvert = MEM_mallocN(sizeof(MDeformVert) * len_src, "Lattice MDeformVert");
|
||||
BKE_defvert_array_copy(editlatt->latt->dvert, ult->dvert, len_src);
|
||||
}
|
||||
|
||||
editlatt->latt->pntsu = ult->pntsu;
|
||||
editlatt->latt->pntsv = ult->pntsv;
|
||||
editlatt->latt->pntsw = ult->pntsw;
|
||||
|
@ -106,6 +117,13 @@ static void *undolatt_from_editlatt(UndoLattice *ult, EditLatt *editlatt)
|
|||
ult->dv = editlatt->latt->dv;
|
||||
ult->dw = editlatt->latt->dw;
|
||||
|
||||
if (editlatt->latt->dvert) {
|
||||
const int tot = ult->pntsu * ult->pntsv * ult->pntsw;
|
||||
ult->dvert = MEM_mallocN(sizeof(MDeformVert) * tot, "Undo Lattice MDeformVert");
|
||||
BKE_defvert_array_copy(ult->dvert, editlatt->latt->dvert, tot);
|
||||
ult->undo_size += sizeof(*ult->dvert) * tot;
|
||||
}
|
||||
|
||||
ult->undo_size += sizeof(*ult->def) * ult->pntsu * ult->pntsv * ult->pntsw;
|
||||
|
||||
return ult;
|
||||
|
@ -116,6 +134,10 @@ static void undolatt_free_data(UndoLattice *ult)
|
|||
if (ult->def) {
|
||||
MEM_freeN(ult->def);
|
||||
}
|
||||
if (ult->dvert) {
|
||||
BKE_defvert_array_free(ult->dvert, ult->pntsu * ult->pntsv * ult->pntsw);
|
||||
ult->dvert = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
|
|
@ -665,7 +665,7 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm
|
|||
int island_index = 0;
|
||||
data->tool = (RNA_enum_get(op->ptr, "mode") == BRUSH_STROKE_SMOOTH) ?
|
||||
UV_SCULPT_TOOL_RELAX :
|
||||
ts->uvsculpt->paint.brush->uv_sculpt_tool;
|
||||
eBrushUVSculptTool(ts->uvsculpt->paint.brush->uv_sculpt_tool);
|
||||
data->invert = (RNA_enum_get(op->ptr, "mode") == BRUSH_STROKE_INVERT) ? 1 : 0;
|
||||
|
||||
data->uvsculpt = &ts->uvsculpt->paint;
|
||||
|
|
|
@ -691,17 +691,18 @@ static void timeline_cache_draw_simulation_nodes(
|
|||
GPU_matrix_scale_2f(1.0, height);
|
||||
|
||||
float color[4];
|
||||
UI_GetThemeColor4fv(TH_SIMULATED_FRAMES, color);
|
||||
switch (cache.cache_state()) {
|
||||
case blender::bke::sim::CacheState::Invalid: {
|
||||
copy_v4_fl4(color, 0.8, 0.8, 0.2, 0.3);
|
||||
color[3] = 0.4f;
|
||||
break;
|
||||
}
|
||||
case blender::bke::sim::CacheState::Valid: {
|
||||
copy_v4_fl4(color, 0.8, 0.8, 0.2, 1.0);
|
||||
color[3] = 0.7f;
|
||||
break;
|
||||
}
|
||||
case blender::bke::sim::CacheState::Baked: {
|
||||
copy_v4_fl4(color, 1.0, 0.6, 0.2, 1.0);
|
||||
color[3] = 1.0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -125,7 +125,8 @@ class ParamsBuilder {
|
|||
const int param_index = this->current_param_index();
|
||||
const ParamType ¶m_type = signature_->params[param_index].type;
|
||||
BLI_assert(param_type.category() == ParamCategory::SingleOutput);
|
||||
const CPPType &type = param_type.data_type().single_type();
|
||||
const DataType data_type = param_type.data_type();
|
||||
const CPPType &type = data_type.single_type();
|
||||
|
||||
if (bool(signature_->params[param_index].flag & ParamFlag::SupportsUnusedOutput)) {
|
||||
/* An empty span indicates that this is ignored. */
|
||||
|
|
|
@ -1,621 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup imbdds
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on a similar file from the NVIDIA texture tools
|
||||
* (http://nvidia-texture-tools.googlecode.com/)
|
||||
*
|
||||
* Original license from NVIDIA follows.
|
||||
*/
|
||||
|
||||
/* Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#include <BLI_sys_types.h> /* For `uint`. */
|
||||
|
||||
#include <BlockDXT.h>
|
||||
#include <ColorBlock.h>
|
||||
#include <Common.h>
|
||||
#include <Stream.h>
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* BlockDXT1
|
||||
* --------------------------------------------------------------------------*/
|
||||
|
||||
uint BlockDXT1::evaluatePalette(Color32 color_array[4]) const
|
||||
{
|
||||
/* Does bit expansion before interpolation. */
|
||||
color_array[0].b = (col0.b << 3) | (col0.b >> 2);
|
||||
color_array[0].g = (col0.g << 2) | (col0.g >> 4);
|
||||
color_array[0].r = (col0.r << 3) | (col0.r >> 2);
|
||||
color_array[0].a = 0xFF;
|
||||
|
||||
/* @@ Same as above, but faster?
|
||||
* Color32 c;
|
||||
* c.u = ((col0.u << 3) & 0xf8) | ((col0.u << 5) & 0xfc00) | ((col0.u << 8) & 0xf80000);
|
||||
* c.u |= (c.u >> 5) & 0x070007;
|
||||
* c.u |= (c.u >> 6) & 0x000300;
|
||||
* color_array[0].u = c.u; */
|
||||
|
||||
color_array[1].r = (col1.r << 3) | (col1.r >> 2);
|
||||
color_array[1].g = (col1.g << 2) | (col1.g >> 4);
|
||||
color_array[1].b = (col1.b << 3) | (col1.b >> 2);
|
||||
color_array[1].a = 0xFF;
|
||||
|
||||
/* @@ Same as above, but faster?
|
||||
* c.u = ((col1.u << 3) & 0xf8) | ((col1.u << 5) & 0xfc00) | ((col1.u << 8) & 0xf80000);
|
||||
* c.u |= (c.u >> 5) & 0x070007;
|
||||
* c.u |= (c.u >> 6) & 0x000300;
|
||||
* color_array[1].u = c.u; */
|
||||
|
||||
if (col0.u > col1.u) {
|
||||
/* Four-color block: derive the other two colors. */
|
||||
color_array[2].r = (2 * color_array[0].r + color_array[1].r) / 3;
|
||||
color_array[2].g = (2 * color_array[0].g + color_array[1].g) / 3;
|
||||
color_array[2].b = (2 * color_array[0].b + color_array[1].b) / 3;
|
||||
color_array[2].a = 0xFF;
|
||||
|
||||
color_array[3].r = (2 * color_array[1].r + color_array[0].r) / 3;
|
||||
color_array[3].g = (2 * color_array[1].g + color_array[0].g) / 3;
|
||||
color_array[3].b = (2 * color_array[1].b + color_array[0].b) / 3;
|
||||
color_array[3].a = 0xFF;
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
/* Three-color block: derive the other color. */
|
||||
color_array[2].r = (color_array[0].r + color_array[1].r) / 2;
|
||||
color_array[2].g = (color_array[0].g + color_array[1].g) / 2;
|
||||
color_array[2].b = (color_array[0].b + color_array[1].b) / 2;
|
||||
color_array[2].a = 0xFF;
|
||||
|
||||
/* Set all components to 0 to match DXT specs. */
|
||||
color_array[3].r = 0x00; /* color_array[2].r; */
|
||||
color_array[3].g = 0x00; /* color_array[2].g; */
|
||||
color_array[3].b = 0x00; /* color_array[2].b; */
|
||||
color_array[3].a = 0x00;
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
uint BlockDXT1::evaluatePaletteNV5x(Color32 color_array[4]) const
|
||||
{
|
||||
/* Does bit expansion before interpolation. */
|
||||
color_array[0].b = (3 * col0.b * 22) / 8;
|
||||
color_array[0].g = (col0.g << 2) | (col0.g >> 4);
|
||||
color_array[0].r = (3 * col0.r * 22) / 8;
|
||||
color_array[0].a = 0xFF;
|
||||
|
||||
color_array[1].r = (3 * col1.r * 22) / 8;
|
||||
color_array[1].g = (col1.g << 2) | (col1.g >> 4);
|
||||
color_array[1].b = (3 * col1.b * 22) / 8;
|
||||
color_array[1].a = 0xFF;
|
||||
|
||||
int gdiff = color_array[1].g - color_array[0].g;
|
||||
|
||||
if (col0.u > col1.u) {
|
||||
/* Four-color block: derive the other two colors. */
|
||||
color_array[2].r = ((2 * col0.r + col1.r) * 22) / 8;
|
||||
color_array[2].g = (256 * color_array[0].g + gdiff / 4 + 128 + gdiff * 80) / 256;
|
||||
color_array[2].b = ((2 * col0.b + col1.b) * 22) / 8;
|
||||
color_array[2].a = 0xFF;
|
||||
|
||||
color_array[3].r = ((2 * col1.r + col0.r) * 22) / 8;
|
||||
color_array[3].g = (256 * color_array[1].g - gdiff / 4 + 128 - gdiff * 80) / 256;
|
||||
color_array[3].b = ((2 * col1.b + col0.b) * 22) / 8;
|
||||
color_array[3].a = 0xFF;
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
/* Three-color block: derive the other color. */
|
||||
color_array[2].r = ((col0.r + col1.r) * 33) / 8;
|
||||
color_array[2].g = (256 * color_array[0].g + gdiff / 4 + 128 + gdiff * 128) / 256;
|
||||
color_array[2].b = ((col0.b + col1.b) * 33) / 8;
|
||||
color_array[2].a = 0xFF;
|
||||
|
||||
/* Set all components to 0 to match DXT specs. */
|
||||
color_array[3].r = 0x00; /* color_array[2].r; */
|
||||
color_array[3].g = 0x00; /* color_array[2].g; */
|
||||
color_array[3].b = 0x00; /* color_array[2].b; */
|
||||
color_array[3].a = 0x00;
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
void BlockDXT1::evaluatePalette3(Color32 color_array[4]) const
|
||||
{
|
||||
color_array[0].b = (col0.b << 3) | (col0.b >> 2);
|
||||
color_array[0].g = (col0.g << 2) | (col0.g >> 4);
|
||||
color_array[0].r = (col0.r << 3) | (col0.r >> 2);
|
||||
color_array[0].a = 0xFF;
|
||||
|
||||
color_array[1].r = (col1.r << 3) | (col1.r >> 2);
|
||||
color_array[1].g = (col1.g << 2) | (col1.g >> 4);
|
||||
color_array[1].b = (col1.b << 3) | (col1.b >> 2);
|
||||
color_array[1].a = 0xFF;
|
||||
|
||||
/* Three-color block: derive the other color. */
|
||||
color_array[2].r = (color_array[0].r + color_array[1].r) / 2;
|
||||
color_array[2].g = (color_array[0].g + color_array[1].g) / 2;
|
||||
color_array[2].b = (color_array[0].b + color_array[1].b) / 2;
|
||||
color_array[2].a = 0xFF;
|
||||
|
||||
/* Set all components to 0 to match DXT specs. */
|
||||
color_array[3].r = 0x00; /* color_array[2].r; */
|
||||
color_array[3].g = 0x00; /* color_array[2].g; */
|
||||
color_array[3].b = 0x00; /* color_array[2].b; */
|
||||
color_array[3].a = 0x00;
|
||||
}
|
||||
|
||||
void BlockDXT1::evaluatePalette4(Color32 color_array[4]) const
|
||||
{
|
||||
color_array[0].b = (col0.b << 3) | (col0.b >> 2);
|
||||
color_array[0].g = (col0.g << 2) | (col0.g >> 4);
|
||||
color_array[0].r = (col0.r << 3) | (col0.r >> 2);
|
||||
color_array[0].a = 0xFF;
|
||||
|
||||
color_array[1].r = (col1.r << 3) | (col1.r >> 2);
|
||||
color_array[1].g = (col1.g << 2) | (col1.g >> 4);
|
||||
color_array[1].b = (col1.b << 3) | (col1.b >> 2);
|
||||
color_array[1].a = 0xFF;
|
||||
|
||||
/* Four-color block: derive the other two colors. */
|
||||
color_array[2].r = (2 * color_array[0].r + color_array[1].r) / 3;
|
||||
color_array[2].g = (2 * color_array[0].g + color_array[1].g) / 3;
|
||||
color_array[2].b = (2 * color_array[0].b + color_array[1].b) / 3;
|
||||
color_array[2].a = 0xFF;
|
||||
|
||||
color_array[3].r = (2 * color_array[1].r + color_array[0].r) / 3;
|
||||
color_array[3].g = (2 * color_array[1].g + color_array[0].g) / 3;
|
||||
color_array[3].b = (2 * color_array[1].b + color_array[0].b) / 3;
|
||||
color_array[3].a = 0xFF;
|
||||
}
|
||||
|
||||
void BlockDXT1::decodeBlock(ColorBlock *block) const
|
||||
{
|
||||
/* Decode color block. */
|
||||
Color32 color_array[4];
|
||||
evaluatePalette(color_array);
|
||||
|
||||
/* Write color block. */
|
||||
for (uint j = 0; j < 4; j++) {
|
||||
for (uint i = 0; i < 4; i++) {
|
||||
uint idx = (row[j] >> (2 * i)) & 3;
|
||||
block->color(i, j) = color_array[idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BlockDXT1::decodeBlockNV5x(ColorBlock *block) const
|
||||
{
|
||||
/* Decode color block. */
|
||||
Color32 color_array[4];
|
||||
evaluatePaletteNV5x(color_array);
|
||||
|
||||
/* Write color block. */
|
||||
for (uint j = 0; j < 4; j++) {
|
||||
for (uint i = 0; i < 4; i++) {
|
||||
uint idx = (row[j] >> (2 * i)) & 3;
|
||||
block->color(i, j) = color_array[idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BlockDXT1::setIndices(const int *idx)
|
||||
{
|
||||
indices = 0;
|
||||
for (uint i = 0; i < 16; i++) {
|
||||
indices |= (idx[i] & 3) << (2 * i);
|
||||
}
|
||||
}
|
||||
|
||||
inline void BlockDXT1::flip4()
|
||||
{
|
||||
swap(row[0], row[3]);
|
||||
swap(row[1], row[2]);
|
||||
}
|
||||
|
||||
inline void BlockDXT1::flip2()
|
||||
{
|
||||
swap(row[0], row[1]);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* BlockDXT3
|
||||
* ---------------------------------------------------------------------------*/
|
||||
|
||||
void BlockDXT3::decodeBlock(ColorBlock *block) const
|
||||
{
|
||||
/* Decode color. */
|
||||
color.decodeBlock(block);
|
||||
|
||||
/* Decode alpha. */
|
||||
alpha.decodeBlock(block);
|
||||
}
|
||||
|
||||
void BlockDXT3::decodeBlockNV5x(ColorBlock *block) const
|
||||
{
|
||||
color.decodeBlockNV5x(block);
|
||||
alpha.decodeBlock(block);
|
||||
}
|
||||
|
||||
void AlphaBlockDXT3::decodeBlock(ColorBlock *block) const
|
||||
{
|
||||
block->color(0x0).a = (alpha0 << 4) | alpha0;
|
||||
block->color(0x1).a = (alpha1 << 4) | alpha1;
|
||||
block->color(0x2).a = (alpha2 << 4) | alpha2;
|
||||
block->color(0x3).a = (alpha3 << 4) | alpha3;
|
||||
block->color(0x4).a = (alpha4 << 4) | alpha4;
|
||||
block->color(0x5).a = (alpha5 << 4) | alpha5;
|
||||
block->color(0x6).a = (alpha6 << 4) | alpha6;
|
||||
block->color(0x7).a = (alpha7 << 4) | alpha7;
|
||||
block->color(0x8).a = (alpha8 << 4) | alpha8;
|
||||
block->color(0x9).a = (alpha9 << 4) | alpha9;
|
||||
block->color(0xA).a = (alphaA << 4) | alphaA;
|
||||
block->color(0xB).a = (alphaB << 4) | alphaB;
|
||||
block->color(0xC).a = (alphaC << 4) | alphaC;
|
||||
block->color(0xD).a = (alphaD << 4) | alphaD;
|
||||
block->color(0xE).a = (alphaE << 4) | alphaE;
|
||||
block->color(0xF).a = (alphaF << 4) | alphaF;
|
||||
}
|
||||
|
||||
void AlphaBlockDXT3::flip4()
|
||||
{
|
||||
swap(row[0], row[3]);
|
||||
swap(row[1], row[2]);
|
||||
}
|
||||
|
||||
void AlphaBlockDXT3::flip2()
|
||||
{
|
||||
swap(row[0], row[1]);
|
||||
}
|
||||
|
||||
void BlockDXT3::flip4()
|
||||
{
|
||||
alpha.flip4();
|
||||
color.flip4();
|
||||
}
|
||||
|
||||
void BlockDXT3::flip2()
|
||||
{
|
||||
alpha.flip2();
|
||||
color.flip2();
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* BlockDXT5
|
||||
* ---------------------------------------------------------------------------*/
|
||||
|
||||
void AlphaBlockDXT5::evaluatePalette(uint8 alpha[8]) const
|
||||
{
|
||||
if (alpha0() > alpha1()) {
|
||||
evaluatePalette8(alpha);
|
||||
}
|
||||
else {
|
||||
evaluatePalette6(alpha);
|
||||
}
|
||||
}
|
||||
|
||||
void AlphaBlockDXT5::evaluatePalette8(uint8 alpha[8]) const
|
||||
{
|
||||
/* 8-alpha block: derive the other six alphas.
|
||||
* Bit code 000 = alpha0, 001 = alpha1, others are interpolated. */
|
||||
alpha[0] = alpha0();
|
||||
alpha[1] = alpha1();
|
||||
alpha[2] = (6 * alpha[0] + 1 * alpha[1]) / 7; /* bit code 010 */
|
||||
alpha[3] = (5 * alpha[0] + 2 * alpha[1]) / 7; /* bit code 011 */
|
||||
alpha[4] = (4 * alpha[0] + 3 * alpha[1]) / 7; /* bit code 100 */
|
||||
alpha[5] = (3 * alpha[0] + 4 * alpha[1]) / 7; /* bit code 101 */
|
||||
alpha[6] = (2 * alpha[0] + 5 * alpha[1]) / 7; /* bit code 110 */
|
||||
alpha[7] = (1 * alpha[0] + 6 * alpha[1]) / 7; /* bit code 111 */
|
||||
}
|
||||
|
||||
void AlphaBlockDXT5::evaluatePalette6(uint8 alpha[8]) const
|
||||
{
|
||||
/* 6-alpha block.
|
||||
* Bit code 000 = alpha0, 001 = alpha1, others are interpolated. */
|
||||
alpha[0] = alpha0();
|
||||
alpha[1] = alpha1();
|
||||
alpha[2] = (4 * alpha[0] + 1 * alpha[1]) / 5; /* Bit code 010 */
|
||||
alpha[3] = (3 * alpha[0] + 2 * alpha[1]) / 5; /* Bit code 011 */
|
||||
alpha[4] = (2 * alpha[0] + 3 * alpha[1]) / 5; /* Bit code 100 */
|
||||
alpha[5] = (1 * alpha[0] + 4 * alpha[1]) / 5; /* Bit code 101 */
|
||||
alpha[6] = 0x00; /* Bit code 110 */
|
||||
alpha[7] = 0xFF; /* Bit code 111 */
|
||||
}
|
||||
|
||||
void AlphaBlockDXT5::indices(uint8 index_array[16]) const
|
||||
{
|
||||
index_array[0x0] = bits0();
|
||||
index_array[0x1] = bits1();
|
||||
index_array[0x2] = bits2();
|
||||
index_array[0x3] = bits3();
|
||||
index_array[0x4] = bits4();
|
||||
index_array[0x5] = bits5();
|
||||
index_array[0x6] = bits6();
|
||||
index_array[0x7] = bits7();
|
||||
index_array[0x8] = bits8();
|
||||
index_array[0x9] = bits9();
|
||||
index_array[0xA] = bitsA();
|
||||
index_array[0xB] = bitsB();
|
||||
index_array[0xC] = bitsC();
|
||||
index_array[0xD] = bitsD();
|
||||
index_array[0xE] = bitsE();
|
||||
index_array[0xF] = bitsF();
|
||||
}
|
||||
|
||||
uint AlphaBlockDXT5::index(uint index) const
|
||||
{
|
||||
int offset = (3 * index + 16);
|
||||
return uint((this->u >> offset) & 0x7);
|
||||
}
|
||||
|
||||
void AlphaBlockDXT5::setIndex(uint index, uint value)
|
||||
{
|
||||
int offset = (3 * index + 16);
|
||||
uint64 mask = uint64(0x7) << offset;
|
||||
this->u = (this->u & ~mask) | (uint64(value) << offset);
|
||||
}
|
||||
|
||||
void AlphaBlockDXT5::decodeBlock(ColorBlock *block) const
|
||||
{
|
||||
uint8 alpha_array[8];
|
||||
evaluatePalette(alpha_array);
|
||||
|
||||
uint8 index_array[16];
|
||||
indices(index_array);
|
||||
|
||||
for (uint i = 0; i < 16; i++) {
|
||||
block->color(i).a = alpha_array[index_array[i]];
|
||||
}
|
||||
}
|
||||
|
||||
void AlphaBlockDXT5::flip4()
|
||||
{
|
||||
uint64 *b = (uint64 *)this;
|
||||
|
||||
/* @@ The masks might have to be byte swapped. */
|
||||
uint64 tmp = (*b & (uint64)(0x000000000000FFFFLL));
|
||||
tmp |= (*b & (uint64)(0x000000000FFF0000LL)) << 36;
|
||||
tmp |= (*b & (uint64)(0x000000FFF0000000LL)) << 12;
|
||||
tmp |= (*b & (uint64)(0x000FFF0000000000LL)) >> 12;
|
||||
tmp |= (*b & (uint64)(0xFFF0000000000000LL)) >> 36;
|
||||
|
||||
*b = tmp;
|
||||
}
|
||||
|
||||
void AlphaBlockDXT5::flip2()
|
||||
{
|
||||
uint *b = (uint *)this;
|
||||
|
||||
/* @@ The masks might have to be byte swapped. */
|
||||
uint tmp = (*b & 0xFF000000);
|
||||
tmp |= (*b & 0x00000FFF) << 12;
|
||||
tmp |= (*b & 0x00FFF000) >> 12;
|
||||
|
||||
*b = tmp;
|
||||
}
|
||||
|
||||
void BlockDXT5::decodeBlock(ColorBlock *block) const
|
||||
{
|
||||
/* Decode color. */
|
||||
color.decodeBlock(block);
|
||||
|
||||
/* Decode alpha. */
|
||||
alpha.decodeBlock(block);
|
||||
}
|
||||
|
||||
void BlockDXT5::decodeBlockNV5x(ColorBlock *block) const
|
||||
{
|
||||
/* Decode color. */
|
||||
color.decodeBlockNV5x(block);
|
||||
|
||||
/* Decode alpha. */
|
||||
alpha.decodeBlock(block);
|
||||
}
|
||||
|
||||
void BlockDXT5::flip4()
|
||||
{
|
||||
alpha.flip4();
|
||||
color.flip4();
|
||||
}
|
||||
|
||||
void BlockDXT5::flip2()
|
||||
{
|
||||
alpha.flip2();
|
||||
color.flip2();
|
||||
}
|
||||
|
||||
void BlockATI1::decodeBlock(ColorBlock *block) const
|
||||
{
|
||||
uint8 alpha_array[8];
|
||||
alpha.evaluatePalette(alpha_array);
|
||||
|
||||
uint8 index_array[16];
|
||||
alpha.indices(index_array);
|
||||
|
||||
for (uint i = 0; i < 16; i++) {
|
||||
Color32 &c = block->color(i);
|
||||
c.b = c.g = c.r = alpha_array[index_array[i]];
|
||||
c.a = 255;
|
||||
}
|
||||
}
|
||||
|
||||
void BlockATI1::flip4()
|
||||
{
|
||||
alpha.flip4();
|
||||
}
|
||||
|
||||
void BlockATI1::flip2()
|
||||
{
|
||||
alpha.flip2();
|
||||
}
|
||||
|
||||
void BlockATI2::decodeBlock(ColorBlock *block) const
|
||||
{
|
||||
uint8 alpha_array[8];
|
||||
uint8 index_array[16];
|
||||
|
||||
x.evaluatePalette(alpha_array);
|
||||
x.indices(index_array);
|
||||
|
||||
for (uint i = 0; i < 16; i++) {
|
||||
Color32 &c = block->color(i);
|
||||
c.r = alpha_array[index_array[i]];
|
||||
}
|
||||
|
||||
y.evaluatePalette(alpha_array);
|
||||
y.indices(index_array);
|
||||
|
||||
for (uint i = 0; i < 16; i++) {
|
||||
Color32 &c = block->color(i);
|
||||
c.g = alpha_array[index_array[i]];
|
||||
c.b = 0;
|
||||
c.a = 255;
|
||||
}
|
||||
}
|
||||
|
||||
void BlockATI2::flip4()
|
||||
{
|
||||
x.flip4();
|
||||
y.flip4();
|
||||
}
|
||||
|
||||
void BlockATI2::flip2()
|
||||
{
|
||||
x.flip2();
|
||||
y.flip2();
|
||||
}
|
||||
|
||||
void BlockCTX1::evaluatePalette(Color32 color_array[4]) const
|
||||
{
|
||||
/* Does bit expansion before interpolation. */
|
||||
color_array[0].b = 0x00;
|
||||
color_array[0].g = col0[1];
|
||||
color_array[0].r = col0[0];
|
||||
color_array[0].a = 0xFF;
|
||||
|
||||
color_array[1].r = 0x00;
|
||||
color_array[1].g = col0[1];
|
||||
color_array[1].b = col1[0];
|
||||
color_array[1].a = 0xFF;
|
||||
|
||||
color_array[2].r = 0x00;
|
||||
color_array[2].g = (2 * color_array[0].g + color_array[1].g) / 3;
|
||||
color_array[2].b = (2 * color_array[0].b + color_array[1].b) / 3;
|
||||
color_array[2].a = 0xFF;
|
||||
|
||||
color_array[3].r = 0x00;
|
||||
color_array[3].g = (2 * color_array[1].g + color_array[0].g) / 3;
|
||||
color_array[3].b = (2 * color_array[1].b + color_array[0].b) / 3;
|
||||
color_array[3].a = 0xFF;
|
||||
}
|
||||
|
||||
void BlockCTX1::decodeBlock(ColorBlock *block) const
|
||||
{
|
||||
/* Decode color block. */
|
||||
Color32 color_array[4];
|
||||
evaluatePalette(color_array);
|
||||
|
||||
/* Write color block. */
|
||||
for (uint j = 0; j < 4; j++) {
|
||||
for (uint i = 0; i < 4; i++) {
|
||||
uint idx = (row[j] >> (2 * i)) & 3;
|
||||
block->color(i, j) = color_array[idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BlockCTX1::setIndices(const int *idx)
|
||||
{
|
||||
indices = 0;
|
||||
for (uint i = 0; i < 16; i++) {
|
||||
indices |= (idx[i] & 3) << (2 * i);
|
||||
}
|
||||
}
|
||||
|
||||
inline void BlockCTX1::flip4()
|
||||
{
|
||||
swap(row[0], row[3]);
|
||||
swap(row[1], row[2]);
|
||||
}
|
||||
|
||||
inline void BlockCTX1::flip2()
|
||||
{
|
||||
swap(row[0], row[1]);
|
||||
}
|
||||
|
||||
void mem_read(Stream &mem, BlockDXT1 &block)
|
||||
{
|
||||
mem_read(mem, block.col0.u);
|
||||
mem_read(mem, block.col1.u);
|
||||
mem_read(mem, block.indices);
|
||||
}
|
||||
|
||||
void mem_read(Stream &mem, AlphaBlockDXT3 &block)
|
||||
{
|
||||
for (ushort &alpha : block.row) {
|
||||
mem_read(mem, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
void mem_read(Stream &mem, BlockDXT3 &block)
|
||||
{
|
||||
mem_read(mem, block.alpha);
|
||||
mem_read(mem, block.color);
|
||||
}
|
||||
|
||||
void mem_read(Stream &mem, AlphaBlockDXT5 &block)
|
||||
{
|
||||
mem_read(mem, block.u);
|
||||
}
|
||||
|
||||
void mem_read(Stream &mem, BlockDXT5 &block)
|
||||
{
|
||||
mem_read(mem, block.alpha);
|
||||
mem_read(mem, block.color);
|
||||
}
|
||||
|
||||
void mem_read(Stream &mem, BlockATI1 &block)
|
||||
{
|
||||
mem_read(mem, block.alpha);
|
||||
}
|
||||
|
||||
void mem_read(Stream &mem, BlockATI2 &block)
|
||||
{
|
||||
mem_read(mem, block.x);
|
||||
mem_read(mem, block.y);
|
||||
}
|
||||
|
||||
void mem_read(Stream &mem, BlockCTX1 &block)
|
||||
{
|
||||
mem_read(mem, block.col0[0]);
|
||||
mem_read(mem, block.col0[1]);
|
||||
mem_read(mem, block.col1[0]);
|
||||
mem_read(mem, block.col1[1]);
|
||||
mem_read(mem, block.indices);
|
||||
}
|
|
@ -1,310 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup imbdds
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on a similar file from the NVIDIA texture tools
|
||||
* (http://nvidia-texture-tools.googlecode.com/)
|
||||
*
|
||||
* Original license from NVIDIA follows.
|
||||
*/
|
||||
|
||||
/* Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Color.h>
|
||||
#include <ColorBlock.h>
|
||||
#include <Common.h>
|
||||
#include <Stream.h>
|
||||
|
||||
/** DXT1 block. */
|
||||
struct BlockDXT1 {
|
||||
Color16 col0;
|
||||
Color16 col1;
|
||||
union {
|
||||
uint8 row[4];
|
||||
uint indices;
|
||||
};
|
||||
|
||||
bool isFourColorMode() const;
|
||||
|
||||
uint evaluatePalette(Color32 color_array[4]) const;
|
||||
uint evaluatePaletteNV5x(Color32 color_array[4]) const;
|
||||
|
||||
/** Evaluate palette assuming 3 color block. */
|
||||
void evaluatePalette3(Color32 color_array[4]) const;
|
||||
/** Evaluate palette assuming 4 color block. */
|
||||
void evaluatePalette4(Color32 color_array[4]) const;
|
||||
|
||||
void decodeBlock(ColorBlock *block) const;
|
||||
void decodeBlockNV5x(ColorBlock *block) const;
|
||||
|
||||
void setIndices(const int *idx);
|
||||
|
||||
/** Flip DXT1 block vertically. */
|
||||
void flip4();
|
||||
/** Flip half DXT1 block vertically. */
|
||||
void flip2();
|
||||
};
|
||||
|
||||
/** Return true if the block uses four color mode, false otherwise. */
|
||||
inline bool BlockDXT1::isFourColorMode() const
|
||||
{
|
||||
return col0.u > col1.u;
|
||||
}
|
||||
|
||||
/** DXT3 alpha block with explicit alpha. */
|
||||
struct AlphaBlockDXT3 {
|
||||
union {
|
||||
struct {
|
||||
uint alpha0 : 4;
|
||||
uint alpha1 : 4;
|
||||
uint alpha2 : 4;
|
||||
uint alpha3 : 4;
|
||||
uint alpha4 : 4;
|
||||
uint alpha5 : 4;
|
||||
uint alpha6 : 4;
|
||||
uint alpha7 : 4;
|
||||
uint alpha8 : 4;
|
||||
uint alpha9 : 4;
|
||||
uint alphaA : 4;
|
||||
uint alphaB : 4;
|
||||
uint alphaC : 4;
|
||||
uint alphaD : 4;
|
||||
uint alphaE : 4;
|
||||
uint alphaF : 4;
|
||||
};
|
||||
uint16 row[4];
|
||||
};
|
||||
|
||||
void decodeBlock(ColorBlock *block) const;
|
||||
|
||||
/** Flip DXT3 alpha block vertically. */
|
||||
void flip4();
|
||||
/** Flip half DXT3 alpha block vertically. */
|
||||
void flip2();
|
||||
};
|
||||
|
||||
/** DXT3 block. */
|
||||
struct BlockDXT3 {
|
||||
AlphaBlockDXT3 alpha;
|
||||
BlockDXT1 color;
|
||||
|
||||
void decodeBlock(ColorBlock *block) const;
|
||||
void decodeBlockNV5x(ColorBlock *block) const;
|
||||
|
||||
/** Flip DXT3 block vertically. */
|
||||
void flip4();
|
||||
/** Flip half DXT3 block vertically. */
|
||||
void flip2();
|
||||
};
|
||||
|
||||
/** DXT5 alpha block. */
|
||||
struct AlphaBlockDXT5 {
|
||||
/* uint64 unions do not compile on all platforms */
|
||||
#if 0
|
||||
union {
|
||||
struct {
|
||||
uint64 alpha0 : 8; /* 8 */
|
||||
uint64 alpha1 : 8; /* 16 */
|
||||
uint64 bits0 : 3; /* 3 - 19 */
|
||||
uint64 bits1 : 3; /* 6 - 22 */
|
||||
uint64 bits2 : 3; /* 9 - 25 */
|
||||
uint64 bits3 : 3; /* 12 - 28 */
|
||||
uint64 bits4 : 3; /* 15 - 31 */
|
||||
uint64 bits5 : 3; /* 18 - 34 */
|
||||
uint64 bits6 : 3; /* 21 - 37 */
|
||||
uint64 bits7 : 3; /* 24 - 40 */
|
||||
uint64 bits8 : 3; /* 27 - 43 */
|
||||
uint64 bits9 : 3; /* 30 - 46 */
|
||||
uint64 bitsA : 3; /* 33 - 49 */
|
||||
uint64 bitsB : 3; /* 36 - 52 */
|
||||
uint64 bitsC : 3; /* 39 - 55 */
|
||||
uint64 bitsD : 3; /* 42 - 58 */
|
||||
uint64 bitsE : 3; /* 45 - 61 */
|
||||
uint64 bitsF : 3; /* 48 - 64 */
|
||||
};
|
||||
uint64 u;
|
||||
};
|
||||
#endif
|
||||
uint64 u;
|
||||
uint8 alpha0() const
|
||||
{
|
||||
return u & 0xffLL;
|
||||
}
|
||||
uint8 alpha1() const
|
||||
{
|
||||
return (u >> 8) & 0xffLL;
|
||||
}
|
||||
uint8 bits0() const
|
||||
{
|
||||
return (u >> 16) & 0x7LL;
|
||||
}
|
||||
uint8 bits1() const
|
||||
{
|
||||
return (u >> 19) & 0x7LL;
|
||||
}
|
||||
uint8 bits2() const
|
||||
{
|
||||
return (u >> 22) & 0x7LL;
|
||||
}
|
||||
uint8 bits3() const
|
||||
{
|
||||
return (u >> 25) & 0x7LL;
|
||||
}
|
||||
uint8 bits4() const
|
||||
{
|
||||
return (u >> 28) & 0x7LL;
|
||||
}
|
||||
uint8 bits5() const
|
||||
{
|
||||
return (u >> 31) & 0x7LL;
|
||||
}
|
||||
uint8 bits6() const
|
||||
{
|
||||
return (u >> 34) & 0x7LL;
|
||||
}
|
||||
uint8 bits7() const
|
||||
{
|
||||
return (u >> 37) & 0x7LL;
|
||||
}
|
||||
uint8 bits8() const
|
||||
{
|
||||
return (u >> 40) & 0x7LL;
|
||||
}
|
||||
uint8 bits9() const
|
||||
{
|
||||
return (u >> 43) & 0x7LL;
|
||||
}
|
||||
uint8 bitsA() const
|
||||
{
|
||||
return (u >> 46) & 0x7LL;
|
||||
}
|
||||
uint8 bitsB() const
|
||||
{
|
||||
return (u >> 49) & 0x7LL;
|
||||
}
|
||||
uint8 bitsC() const
|
||||
{
|
||||
return (u >> 52) & 0x7LL;
|
||||
}
|
||||
uint8 bitsD() const
|
||||
{
|
||||
return (u >> 55) & 0x7LL;
|
||||
}
|
||||
uint8 bitsE() const
|
||||
{
|
||||
return (u >> 58) & 0x7LL;
|
||||
}
|
||||
uint8 bitsF() const
|
||||
{
|
||||
return (u >> 61) & 0x7LL;
|
||||
}
|
||||
|
||||
void evaluatePalette(uint8 alpha[8]) const;
|
||||
void evaluatePalette8(uint8 alpha[8]) const;
|
||||
void evaluatePalette6(uint8 alpha[8]) const;
|
||||
void indices(uint8 index_array[16]) const;
|
||||
|
||||
uint index(uint index) const;
|
||||
void setIndex(uint index, uint value);
|
||||
|
||||
void decodeBlock(ColorBlock *block) const;
|
||||
|
||||
void flip4();
|
||||
void flip2();
|
||||
};
|
||||
|
||||
/** DXT5 block. */
|
||||
struct BlockDXT5 {
|
||||
AlphaBlockDXT5 alpha;
|
||||
BlockDXT1 color;
|
||||
|
||||
void decodeBlock(ColorBlock *block) const;
|
||||
void decodeBlockNV5x(ColorBlock *block) const;
|
||||
|
||||
/** Flip DXT5 block vertically. */
|
||||
void flip4();
|
||||
/** Flip half DXT5 block vertically. */
|
||||
void flip2();
|
||||
};
|
||||
|
||||
/** ATI1 block. */
|
||||
struct BlockATI1 {
|
||||
AlphaBlockDXT5 alpha;
|
||||
|
||||
/** Decode ATI1 block. */
|
||||
void decodeBlock(ColorBlock *block) const;
|
||||
|
||||
/** Flip ATI1 block vertically. */
|
||||
void flip4();
|
||||
/** Flip half ATI1 block vertically. */
|
||||
void flip2();
|
||||
};
|
||||
|
||||
/** ATI2 block. */
|
||||
struct BlockATI2 {
|
||||
AlphaBlockDXT5 x;
|
||||
AlphaBlockDXT5 y;
|
||||
|
||||
/** Decode ATI2 block. */
|
||||
void decodeBlock(ColorBlock *block) const;
|
||||
|
||||
/** Flip ATI2 block vertically. */
|
||||
void flip4();
|
||||
/** Flip half ATI2 block vertically. */
|
||||
void flip2();
|
||||
};
|
||||
|
||||
/** CTX1 block. */
|
||||
struct BlockCTX1 {
|
||||
uint8 col0[2];
|
||||
uint8 col1[2];
|
||||
union {
|
||||
uint8 row[4];
|
||||
uint indices;
|
||||
};
|
||||
|
||||
void evaluatePalette(Color32 color_array[4]) const;
|
||||
void setIndices(const int *idx);
|
||||
|
||||
void decodeBlock(ColorBlock *block) const;
|
||||
|
||||
/** Flip CTX1 block vertically. */
|
||||
void flip4();
|
||||
/** Flip half CTX1 block vertically. */
|
||||
void flip2();
|
||||
};
|
||||
|
||||
void mem_read(Stream &mem, BlockDXT1 &block);
|
||||
void mem_read(Stream &mem, AlphaBlockDXT3 &block);
|
||||
void mem_read(Stream &mem, BlockDXT3 &block);
|
||||
void mem_read(Stream &mem, AlphaBlockDXT5 &block);
|
||||
void mem_read(Stream &mem, BlockDXT5 &block);
|
||||
void mem_read(Stream &mem, BlockATI1 &block);
|
||||
void mem_read(Stream &mem, BlockATI2 &block);
|
||||
void mem_read(Stream &mem, BlockCTX1 &block);
|
|
@ -1,47 +0,0 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Copyright 2006 Blender Foundation
|
||||
|
||||
set(INC
|
||||
.
|
||||
..
|
||||
../..
|
||||
../../../blenkernel
|
||||
../../../blenlib
|
||||
../../../makesdna
|
||||
../../../../../intern/guardedalloc
|
||||
../../../../../intern/utfconv
|
||||
)
|
||||
|
||||
set(INC_SYS
|
||||
|
||||
)
|
||||
|
||||
set(SRC
|
||||
BlockDXT.h
|
||||
Color.h
|
||||
ColorBlock.h
|
||||
Common.h
|
||||
DirectDrawSurface.h
|
||||
FlipDXT.h
|
||||
Image.h
|
||||
PixelFormat.h
|
||||
Stream.h
|
||||
dds_api.h
|
||||
|
||||
BlockDXT.cpp
|
||||
ColorBlock.cpp
|
||||
DirectDrawSurface.cpp
|
||||
FlipDXT.cpp
|
||||
Image.cpp
|
||||
Stream.cpp
|
||||
dds_api.cpp
|
||||
)
|
||||
|
||||
set(LIB
|
||||
)
|
||||
|
||||
if(WITH_IMAGE_DDS)
|
||||
add_definitions(-DWITH_DDS)
|
||||
endif()
|
||||
|
||||
blender_add_lib(bf_imbuf_dds "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
|
@ -1,92 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup imbdds
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on a similar file from the NVIDIA texture tools
|
||||
* (http://nvidia-texture-tools.googlecode.com/)
|
||||
*
|
||||
* Original license from NVIDIA follows.
|
||||
*/
|
||||
|
||||
/* This code is in the public domain -- <castanyo@yahoo.es> */
|
||||
|
||||
#pragma once
|
||||
|
||||
/** 32 bit color stored as BGRA. */
|
||||
class Color32 {
|
||||
public:
|
||||
Color32() {}
|
||||
Color32(const Color32 &) = default;
|
||||
|
||||
Color32(unsigned char R, unsigned char G, unsigned char B)
|
||||
{
|
||||
setRGBA(R, G, B, 0xFF);
|
||||
}
|
||||
Color32(unsigned char R, unsigned char G, unsigned char B, unsigned char A)
|
||||
{
|
||||
setRGBA(R, G, B, A);
|
||||
}
|
||||
#if 0
|
||||
Color32(unsigned char c[4])
|
||||
{
|
||||
setRGBA(c[0], c[1], c[2], c[3]);
|
||||
}
|
||||
Color32(float R, float G, float B)
|
||||
{
|
||||
setRGBA(uint(R * 255), uint(G * 255), uint(B * 255), 0xFF);
|
||||
}
|
||||
Color32(float R, float G, float B, float A)
|
||||
{
|
||||
setRGBA(uint(R * 255), uint(G * 255), uint(B * 255), uint(A * 255));
|
||||
}
|
||||
#endif
|
||||
Color32(unsigned int U) : u(U) {}
|
||||
|
||||
void setRGBA(unsigned char R, unsigned char G, unsigned char B, unsigned char A)
|
||||
{
|
||||
r = R;
|
||||
g = G;
|
||||
b = B;
|
||||
a = A;
|
||||
}
|
||||
|
||||
void setBGRA(unsigned char B, unsigned char G, unsigned char R, unsigned char A = 0xFF)
|
||||
{
|
||||
r = R;
|
||||
g = G;
|
||||
b = B;
|
||||
a = A;
|
||||
}
|
||||
|
||||
operator unsigned int() const
|
||||
{
|
||||
return u;
|
||||
}
|
||||
|
||||
union {
|
||||
struct {
|
||||
unsigned char b, g, r, a;
|
||||
};
|
||||
unsigned int u;
|
||||
};
|
||||
};
|
||||
|
||||
/** 16 bit 565 BGR color. */
|
||||
class Color16 {
|
||||
public:
|
||||
Color16() {}
|
||||
Color16(const Color16 &c) : u(c.u) {}
|
||||
explicit Color16(unsigned short U) : u(U) {}
|
||||
|
||||
union {
|
||||
struct {
|
||||
unsigned short b : 5;
|
||||
unsigned short g : 6;
|
||||
unsigned short r : 5;
|
||||
};
|
||||
unsigned short u;
|
||||
};
|
||||
};
|
|
@ -1,468 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup imbdds
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on a similar file from the NVIDIA texture tools
|
||||
* (http://nvidia-texture-tools.googlecode.com/)
|
||||
*
|
||||
* Original license from NVIDIA follows.
|
||||
*/
|
||||
|
||||
/* This code is in the public domain - <castanyo@yahoo.es> */
|
||||
|
||||
#include <ColorBlock.h>
|
||||
#include <Common.h>
|
||||
#include <Image.h>
|
||||
|
||||
#if 0
|
||||
/* Get approximate luminance. */
|
||||
inline static uint colorLuminance(Color32 c)
|
||||
{
|
||||
return c.r + c.g + c.b;
|
||||
}
|
||||
|
||||
/* Get the euclidean distance between the given colors. */
|
||||
inline static uint colorDistance(Color32 c0, Color32 c1)
|
||||
{
|
||||
return (c0.r - c1.r) * (c0.r - c1.r) + (c0.g - c1.g) * (c0.g - c1.g) +
|
||||
(c0.b - c1.b) * (c0.b - c1.b);
|
||||
}
|
||||
#endif
|
||||
|
||||
ColorBlock::ColorBlock(const uint *linearImage)
|
||||
{
|
||||
for (uint i = 0; i < 16; i++) {
|
||||
color(i) = Color32(linearImage[i]);
|
||||
}
|
||||
}
|
||||
|
||||
ColorBlock::ColorBlock(const ColorBlock &block)
|
||||
{
|
||||
for (uint i = 0; i < 16; i++) {
|
||||
color(i) = block.color(i);
|
||||
}
|
||||
}
|
||||
|
||||
ColorBlock::ColorBlock(const Image *img, uint x, uint y)
|
||||
{
|
||||
init(img, x, y);
|
||||
}
|
||||
|
||||
void ColorBlock::init(const Image *img, uint x, uint y)
|
||||
{
|
||||
init(img->width(), img->height(), (const uint *)img->pixels(), x, y);
|
||||
}
|
||||
|
||||
void ColorBlock::init(uint w, uint h, const uint *data, uint x, uint y)
|
||||
{
|
||||
const uint bw = MIN(w - x, 4U);
|
||||
const uint bh = MIN(h - y, 4U);
|
||||
|
||||
/* Blocks that are smaller than 4x4 are handled by repeating the pixels.
|
||||
* @@ That's only correct when block size is 1, 2 or 4, but not with 3. :(
|
||||
* @@ Ideally we should zero the weights of the pixels out of range. */
|
||||
|
||||
for (uint i = 0; i < 4; i++) {
|
||||
const int by = i % bh;
|
||||
|
||||
for (uint e = 0; e < 4; e++) {
|
||||
const int bx = e % bw;
|
||||
const uint idx = (y + by) * w + x + bx;
|
||||
|
||||
color(e, i).u = data[idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ColorBlock::init(uint w, uint h, const float *data, uint x, uint y)
|
||||
{
|
||||
const uint bw = MIN(w - x, 4U);
|
||||
const uint bh = MIN(h - y, 4U);
|
||||
|
||||
/* Blocks that are smaller than 4x4 are handled by repeating the pixels.
|
||||
* @@ That's only correct when block size is 1, 2 or 4, but not with 3. :(
|
||||
* @@ Ideally we should zero the weights of the pixels out of range. */
|
||||
|
||||
uint srcPlane = w * h;
|
||||
|
||||
for (uint i = 0; i < 4; i++) {
|
||||
const uint by = i % bh;
|
||||
|
||||
for (uint e = 0; e < 4; e++) {
|
||||
const uint bx = e % bw;
|
||||
const uint idx = ((y + by) * w + x + bx);
|
||||
|
||||
Color32 &c = color(e, i);
|
||||
/* @@ Is this the right way to quantize floats to bytes? */
|
||||
c.r = uint8(255 * CLAMP(data[idx + 0 * srcPlane], 0.0f, 1.0f));
|
||||
c.g = uint8(255 * CLAMP(data[idx + 1 * srcPlane], 0.0f, 1.0f));
|
||||
c.b = uint8(255 * CLAMP(data[idx + 2 * srcPlane], 0.0f, 1.0f));
|
||||
c.a = uint8(255 * CLAMP(data[idx + 3 * srcPlane], 0.0f, 1.0f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint8 component(Color32 c, uint i)
|
||||
{
|
||||
if (i == 0) {
|
||||
return c.r;
|
||||
}
|
||||
if (i == 1) {
|
||||
return c.g;
|
||||
}
|
||||
if (i == 2) {
|
||||
return c.b;
|
||||
}
|
||||
if (i == 3) {
|
||||
return c.a;
|
||||
}
|
||||
if (i == 4) {
|
||||
return 0xFF;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ColorBlock::swizzle(uint x, uint y, uint z, uint w)
|
||||
{
|
||||
for (Color32 &color : m_color) {
|
||||
const Color32 c = color;
|
||||
color.r = component(c, x);
|
||||
color.g = component(c, y);
|
||||
color.b = component(c, z);
|
||||
color.a = component(c, w);
|
||||
}
|
||||
}
|
||||
|
||||
bool ColorBlock::isSingleColor(Color32 mask /*= Color32(0xFF, 0xFF, 0xFF, 0x00) */) const
|
||||
{
|
||||
uint u = m_color[0].u & mask.u;
|
||||
|
||||
for (int i = 1; i < 16; i++) {
|
||||
if (u != (m_color[i].u & mask.u)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/** Returns true if the block has a single color, ignoring transparent pixels. */
|
||||
bool ColorBlock::isSingleColorNoAlpha() const
|
||||
{
|
||||
Color32 c;
|
||||
int i;
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (m_color[i].a != 0) {
|
||||
c = m_color[i];
|
||||
}
|
||||
}
|
||||
|
||||
Color32 mask(0xFF, 0xFF, 0xFF, 0x00);
|
||||
uint u = c.u & mask.u;
|
||||
|
||||
for (; i < 16; i++) {
|
||||
if (u != (m_color[i].u & mask.u)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/** Count number of unique colors in this color block. */
|
||||
uint ColorBlock::countUniqueColors() const
|
||||
{
|
||||
uint count = 0;
|
||||
|
||||
/* @@ This does not have to be o(n^2) */
|
||||
for (int i = 0; i < 16; i++) {
|
||||
bool unique = true;
|
||||
for (int j = 0; j < i; j++) {
|
||||
if (m_color[i] != m_color[j]) {
|
||||
unique = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (unique) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/** Get average color of the block. */
|
||||
Color32 ColorBlock::averageColor() const
|
||||
{
|
||||
uint r, g, b, a;
|
||||
r = g = b = a = 0;
|
||||
|
||||
for (uint i = 0; i < 16; i++) {
|
||||
r += m_color[i].r;
|
||||
g += m_color[i].g;
|
||||
b += m_color[i].b;
|
||||
a += m_color[i].a;
|
||||
}
|
||||
|
||||
return Color32(uint8(r / 16), uint8(g / 16), uint8(b / 16), uint8(a / 16));
|
||||
}
|
||||
#endif
|
||||
|
||||
bool ColorBlock::hasAlpha() const
|
||||
{
|
||||
for (const auto &i : m_color) {
|
||||
if (i.a != 255) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
/** Get diameter color range. */
|
||||
void ColorBlock::diameterRange(Color32 *start, Color32 *end) const
|
||||
{
|
||||
Color32 c0, c1;
|
||||
uint best_dist = 0;
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
for (int j = i + 1; j < 16; j++) {
|
||||
uint dist = colorDistance(m_color[i], m_color[j]);
|
||||
if (dist > best_dist) {
|
||||
best_dist = dist;
|
||||
c0 = m_color[i];
|
||||
c1 = m_color[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*start = c0;
|
||||
*end = c1;
|
||||
}
|
||||
|
||||
/** Get luminance color range. */
|
||||
void ColorBlock::luminanceRange(Color32 *start, Color32 *end) const
|
||||
{
|
||||
Color32 minColor, maxColor;
|
||||
uint minLuminance, maxLuminance;
|
||||
|
||||
maxLuminance = minLuminance = colorLuminance(m_color[0]);
|
||||
|
||||
for (uint i = 1; i < 16; i++) {
|
||||
uint luminance = colorLuminance(m_color[i]);
|
||||
|
||||
if (luminance > maxLuminance) {
|
||||
maxLuminance = luminance;
|
||||
maxColor = m_color[i];
|
||||
}
|
||||
else if (luminance < minLuminance) {
|
||||
minLuminance = luminance;
|
||||
minColor = m_color[i];
|
||||
}
|
||||
}
|
||||
|
||||
*start = minColor;
|
||||
*end = maxColor;
|
||||
}
|
||||
|
||||
/** Get color range based on the bounding box. */
|
||||
void ColorBlock::boundsRange(Color32 *start, Color32 *end) const
|
||||
{
|
||||
Color32 minColor(255, 255, 255);
|
||||
Color32 maxColor(0, 0, 0);
|
||||
|
||||
for (uint i = 0; i < 16; i++) {
|
||||
if (m_color[i].r < minColor.r) {
|
||||
minColor.r = m_color[i].r;
|
||||
}
|
||||
if (m_color[i].g < minColor.g) {
|
||||
minColor.g = m_color[i].g;
|
||||
}
|
||||
if (m_color[i].b < minColor.b) {
|
||||
minColor.b = m_color[i].b;
|
||||
}
|
||||
if (m_color[i].r > maxColor.r) {
|
||||
maxColor.r = m_color[i].r;
|
||||
}
|
||||
if (m_color[i].g > maxColor.g) {
|
||||
maxColor.g = m_color[i].g;
|
||||
}
|
||||
if (m_color[i].b > maxColor.b) {
|
||||
maxColor.b = m_color[i].b;
|
||||
}
|
||||
}
|
||||
|
||||
/* Offset range by 1/16 of the extents */
|
||||
Color32 inset;
|
||||
inset.r = (maxColor.r - minColor.r) >> 4;
|
||||
inset.g = (maxColor.g - minColor.g) >> 4;
|
||||
inset.b = (maxColor.b - minColor.b) >> 4;
|
||||
|
||||
minColor.r = (minColor.r + inset.r <= 255) ? minColor.r + inset.r : 255;
|
||||
minColor.g = (minColor.g + inset.g <= 255) ? minColor.g + inset.g : 255;
|
||||
minColor.b = (minColor.b + inset.b <= 255) ? minColor.b + inset.b : 255;
|
||||
|
||||
maxColor.r = (maxColor.r >= inset.r) ? maxColor.r - inset.r : 0;
|
||||
maxColor.g = (maxColor.g >= inset.g) ? maxColor.g - inset.g : 0;
|
||||
maxColor.b = (maxColor.b >= inset.b) ? maxColor.b - inset.b : 0;
|
||||
|
||||
*start = minColor;
|
||||
*end = maxColor;
|
||||
}
|
||||
|
||||
/** Get color range based on the bounding box. */
|
||||
void ColorBlock::boundsRangeAlpha(Color32 *start, Color32 *end) const
|
||||
{
|
||||
Color32 minColor(255, 255, 255, 255);
|
||||
Color32 maxColor(0, 0, 0, 0);
|
||||
|
||||
for (uint i = 0; i < 16; i++) {
|
||||
if (m_color[i].r < minColor.r) {
|
||||
minColor.r = m_color[i].r;
|
||||
}
|
||||
if (m_color[i].g < minColor.g) {
|
||||
minColor.g = m_color[i].g;
|
||||
}
|
||||
if (m_color[i].b < minColor.b) {
|
||||
minColor.b = m_color[i].b;
|
||||
}
|
||||
if (m_color[i].a < minColor.a) {
|
||||
minColor.a = m_color[i].a;
|
||||
}
|
||||
if (m_color[i].r > maxColor.r) {
|
||||
maxColor.r = m_color[i].r;
|
||||
}
|
||||
if (m_color[i].g > maxColor.g) {
|
||||
maxColor.g = m_color[i].g;
|
||||
}
|
||||
if (m_color[i].b > maxColor.b) {
|
||||
maxColor.b = m_color[i].b;
|
||||
}
|
||||
if (m_color[i].a > maxColor.a) {
|
||||
maxColor.a = m_color[i].a;
|
||||
}
|
||||
}
|
||||
|
||||
/* Offset range by 1/16 of the extents */
|
||||
Color32 inset;
|
||||
inset.r = (maxColor.r - minColor.r) >> 4;
|
||||
inset.g = (maxColor.g - minColor.g) >> 4;
|
||||
inset.b = (maxColor.b - minColor.b) >> 4;
|
||||
inset.a = (maxColor.a - minColor.a) >> 4;
|
||||
|
||||
minColor.r = (minColor.r + inset.r <= 255) ? minColor.r + inset.r : 255;
|
||||
minColor.g = (minColor.g + inset.g <= 255) ? minColor.g + inset.g : 255;
|
||||
minColor.b = (minColor.b + inset.b <= 255) ? minColor.b + inset.b : 255;
|
||||
minColor.a = (minColor.a + inset.a <= 255) ? minColor.a + inset.a : 255;
|
||||
|
||||
maxColor.r = (maxColor.r >= inset.r) ? maxColor.r - inset.r : 0;
|
||||
maxColor.g = (maxColor.g >= inset.g) ? maxColor.g - inset.g : 0;
|
||||
maxColor.b = (maxColor.b >= inset.b) ? maxColor.b - inset.b : 0;
|
||||
maxColor.a = (maxColor.a >= inset.a) ? maxColor.a - inset.a : 0;
|
||||
|
||||
*start = minColor;
|
||||
*end = maxColor;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/** Sort colors by absolute value in their 16 bit representation. */
|
||||
void ColorBlock::sortColorsByAbsoluteValue()
|
||||
{
|
||||
/* Dummy selection sort. */
|
||||
for (uint a = 0; a < 16; a++) {
|
||||
uint max = a;
|
||||
Color16 cmax(m_color[a]);
|
||||
|
||||
for (uint b = a + 1; b < 16; b++) {
|
||||
Color16 cb(m_color[b]);
|
||||
|
||||
if (cb.u > cmax.u) {
|
||||
max = b;
|
||||
cmax = cb;
|
||||
}
|
||||
}
|
||||
swap(m_color[a], m_color[max]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/** Find extreme colors in the given axis. */
|
||||
void ColorBlock::computeRange(Vector3::Arg axis, Color32 *start, Color32 *end) const
|
||||
{
|
||||
|
||||
int mini, maxi;
|
||||
mini = maxi = 0;
|
||||
|
||||
float min, max;
|
||||
min = max = dot(Vector3(m_color[0].r, m_color[0].g, m_color[0].b), axis);
|
||||
|
||||
for (uint i = 1; i < 16; i++) {
|
||||
const Vector3 vec(m_color[i].r, m_color[i].g, m_color[i].b);
|
||||
|
||||
float val = dot(vec, axis);
|
||||
if (val < min) {
|
||||
mini = i;
|
||||
min = val;
|
||||
}
|
||||
else if (val > max) {
|
||||
maxi = i;
|
||||
max = val;
|
||||
}
|
||||
}
|
||||
|
||||
*start = m_color[mini];
|
||||
*end = m_color[maxi];
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/** Sort colors in the given axis. */
|
||||
void ColorBlock::sortColors(const Vector3 &axis)
|
||||
{
|
||||
float luma_array[16];
|
||||
|
||||
for (uint i = 0; i < 16; i++) {
|
||||
const Vector3 vec(m_color[i].r, m_color[i].g, m_color[i].b);
|
||||
luma_array[i] = dot(vec, axis);
|
||||
}
|
||||
|
||||
/* Dummy selection sort. */
|
||||
for (uint a = 0; a < 16; a++) {
|
||||
uint min = a;
|
||||
for (uint b = a + 1; b < 16; b++) {
|
||||
if (luma_array[b] < luma_array[min]) {
|
||||
min = b;
|
||||
}
|
||||
}
|
||||
swap(luma_array[a], luma_array[min]);
|
||||
swap(m_color[a], m_color[min]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/** Get the volume of the color block. */
|
||||
float ColorBlock::volume() const
|
||||
{
|
||||
Box bounds;
|
||||
bounds.clearBounds();
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
const Vector3 point(m_color[i].r, m_color[i].g, m_color[i].b);
|
||||
bounds.addPointToBounds(point);
|
||||
}
|
||||
|
||||
return bounds.volume();
|
||||
}
|
||||
#endif
|
|
@ -1,83 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup imbdds
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on a similar file from the NVIDIA texture tools
|
||||
* (http://nvidia-texture-tools.googlecode.com/)
|
||||
*
|
||||
* Original license from NVIDIA follows.
|
||||
*/
|
||||
|
||||
/* This code is in the public domain -- <castanyo@yahoo.es> */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Color.h>
|
||||
#include <Image.h>
|
||||
|
||||
/** Uncompressed 4x4 color block. */
|
||||
struct ColorBlock {
|
||||
ColorBlock() = default;
|
||||
/** Initialize the color block from an array of colors. */
|
||||
ColorBlock(const uint *linearImage);
|
||||
/** Initialize the color block with the contents of the given block. */
|
||||
ColorBlock(const ColorBlock &block);
|
||||
/** Initialize this color block. */
|
||||
ColorBlock(const Image *img, uint x, uint y);
|
||||
|
||||
void init(const Image *img, uint x, uint y);
|
||||
void init(uint w, uint h, const uint *data, uint x, uint y);
|
||||
void init(uint w, uint h, const float *data, uint x, uint y);
|
||||
|
||||
void swizzle(uint x, uint y, uint z, uint w); /* 0=r, 1=g, 2=b, 3=a, 4=0xFF, 5=0 */
|
||||
|
||||
/** Returns true if the block has a single color. */
|
||||
bool isSingleColor(Color32 mask = Color32(0xFF, 0xFF, 0xFF, 0x00)) const;
|
||||
/** Return true if the block is not fully opaque. */
|
||||
bool hasAlpha() const;
|
||||
|
||||
/* Accessors */
|
||||
const Color32 *colors() const;
|
||||
|
||||
Color32 color(uint i) const;
|
||||
Color32 &color(uint i);
|
||||
|
||||
Color32 color(uint x, uint y) const;
|
||||
Color32 &color(uint x, uint y);
|
||||
|
||||
private:
|
||||
Color32 m_color[4 * 4];
|
||||
};
|
||||
|
||||
/** Get pointer to block colors. */
|
||||
inline const Color32 *ColorBlock::colors() const
|
||||
{
|
||||
return m_color;
|
||||
}
|
||||
|
||||
/** Get block color. */
|
||||
inline Color32 ColorBlock::color(uint i) const
|
||||
{
|
||||
return m_color[i];
|
||||
}
|
||||
|
||||
/** Get block color. */
|
||||
inline Color32 &ColorBlock::color(uint i)
|
||||
{
|
||||
return m_color[i];
|
||||
}
|
||||
|
||||
/** Get block color. */
|
||||
inline Color32 ColorBlock::color(uint x, uint y) const
|
||||
{
|
||||
return m_color[y * 4 + x];
|
||||
}
|
||||
|
||||
/** Get block color. */
|
||||
inline Color32 &ColorBlock::color(uint x, uint y)
|
||||
{
|
||||
return m_color[y * 4 + x];
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup imbdds
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef MIN
|
||||
# define MIN(a, b) ((a) <= (b) ? (a) : (b))
|
||||
#endif
|
||||
#ifndef MAX
|
||||
# define MAX(a, b) ((a) >= (b) ? (a) : (b))
|
||||
#endif
|
||||
#ifndef CLAMP
|
||||
# define CLAMP(x, a, b) MIN(MAX((x), (a)), (b))
|
||||
#endif
|
||||
|
||||
template<typename T> inline void swap(T &a, T &b)
|
||||
{
|
||||
T tmp = a;
|
||||
a = b;
|
||||
b = tmp;
|
||||
}
|
||||
|
||||
typedef unsigned char uint8;
|
||||
typedef unsigned short uint16;
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned int uint32;
|
||||
typedef unsigned long long uint64;
|
||||
|
||||
// copied from nvtt src/nvimage/nvimage.h
|
||||
inline uint computePitch(uint w, uint bitsize, uint alignment)
|
||||
{
|
||||
return ((w * bitsize + 8 * alignment - 1) / (8 * alignment)) * alignment;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,175 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup imbdds
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on a similar file from the NVIDIA texture tools
|
||||
* (http://nvidia-texture-tools.googlecode.com/)
|
||||
*
|
||||
* Original license from NVIDIA follows.
|
||||
*/
|
||||
|
||||
/* Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ColorBlock.h>
|
||||
#include <Common.h>
|
||||
#include <Image.h>
|
||||
#include <Stream.h>
|
||||
|
||||
struct DDSPixelFormat {
|
||||
uint size;
|
||||
uint flags;
|
||||
uint fourcc;
|
||||
uint bitcount;
|
||||
uint rmask;
|
||||
uint gmask;
|
||||
uint bmask;
|
||||
uint amask;
|
||||
};
|
||||
|
||||
struct DDSCaps {
|
||||
uint caps1;
|
||||
uint caps2;
|
||||
uint caps3;
|
||||
uint caps4;
|
||||
};
|
||||
|
||||
/** DDS file header for DX10. */
|
||||
struct DDSHeader10 {
|
||||
uint dxgiFormat;
|
||||
uint resourceDimension;
|
||||
uint miscFlag;
|
||||
uint arraySize;
|
||||
uint reserved;
|
||||
};
|
||||
|
||||
/** DDS file header. */
|
||||
struct DDSHeader {
|
||||
uint fourcc;
|
||||
uint size;
|
||||
uint flags;
|
||||
uint height;
|
||||
uint width;
|
||||
uint pitch;
|
||||
uint depth;
|
||||
uint mipmapcount;
|
||||
uint reserved[11];
|
||||
DDSPixelFormat pf;
|
||||
DDSCaps caps;
|
||||
uint notused;
|
||||
DDSHeader10 header10;
|
||||
|
||||
/* Helper methods. */
|
||||
DDSHeader();
|
||||
|
||||
void setWidth(uint w);
|
||||
void setHeight(uint h);
|
||||
void setDepth(uint d);
|
||||
void setMipmapCount(uint count);
|
||||
void setTexture2D();
|
||||
void setTexture3D();
|
||||
void setTextureCube();
|
||||
void setLinearSize(uint size);
|
||||
void setPitch(uint pitch);
|
||||
void setFourCC(uint8 c0, uint8 c1, uint8 c2, uint8 c3);
|
||||
void setFormatCode(uint code);
|
||||
void setSwizzleCode(uint8 c0, uint8 c1, uint8 c2, uint8 c3);
|
||||
void setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask);
|
||||
void setDX10Format(uint format);
|
||||
void setNormalFlag(bool b);
|
||||
void setSrgbFlag(bool b);
|
||||
void setHasAlphaFlag(bool b);
|
||||
void setUserVersion(int version);
|
||||
|
||||
// void swapBytes();
|
||||
|
||||
bool hasDX10Header() const;
|
||||
uint signature() const;
|
||||
uint toolVersion() const;
|
||||
uint userVersion() const;
|
||||
bool isNormalMap() const;
|
||||
bool isSrgb() const;
|
||||
bool hasAlpha() const;
|
||||
uint d3d9Format() const;
|
||||
};
|
||||
|
||||
/** DirectDraw Surface. (DDS) */
|
||||
class DirectDrawSurface {
|
||||
public:
|
||||
DirectDrawSurface(unsigned char *mem, uint size);
|
||||
|
||||
bool isValid() const;
|
||||
bool isSupported() const;
|
||||
|
||||
bool hasAlpha() const;
|
||||
|
||||
uint mipmapCount() const;
|
||||
uint fourCC() const;
|
||||
uint width() const;
|
||||
uint height() const;
|
||||
uint depth() const;
|
||||
bool isTexture1D() const;
|
||||
bool isTexture2D() const;
|
||||
bool isTexture3D() const;
|
||||
bool isTextureCube() const;
|
||||
|
||||
void setNormalFlag(bool b);
|
||||
void setHasAlphaFlag(bool b);
|
||||
void setUserVersion(int version);
|
||||
|
||||
void mipmap(Image *img, uint f, uint m);
|
||||
/**
|
||||
* It was easier to copy this function from upstream than to resync.
|
||||
* This should be removed if a resync ever occurs.
|
||||
*/
|
||||
void *readData(uint &size);
|
||||
// void mipmap(FloatImage *img, uint f, uint m);
|
||||
|
||||
void printInfo() const;
|
||||
|
||||
private:
|
||||
uint blockSize() const;
|
||||
uint faceSize() const;
|
||||
uint mipmapSize(uint m) const;
|
||||
|
||||
uint offset(uint f, uint m);
|
||||
|
||||
void readLinearImage(Image *img);
|
||||
void readBlockImage(Image *img);
|
||||
void readBlock(ColorBlock *rgba);
|
||||
|
||||
private:
|
||||
/** Memory where DDS file resides. */
|
||||
Stream stream;
|
||||
DDSHeader header;
|
||||
};
|
||||
|
||||
void mem_read(Stream &mem, DDSPixelFormat &pf);
|
||||
void mem_read(Stream &mem, DDSCaps &caps);
|
||||
void mem_read(Stream &mem, DDSHeader &header);
|
||||
void mem_read(Stream &mem, DDSHeader10 &header);
|
|
@ -1,247 +0,0 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause
|
||||
* Copyright 2009 Google Inc. All rights reserved. */
|
||||
|
||||
/** \file
|
||||
* \ingroup imbdds
|
||||
* This file comes from the chromium project, adapted to Blender to add DDS
|
||||
* flipping to OpenGL convention for Blender.
|
||||
*/
|
||||
|
||||
#include "IMB_imbuf_types.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <BlockDXT.h>
|
||||
#include <ColorBlock.h>
|
||||
#include <Common.h>
|
||||
#include <FlipDXT.h>
|
||||
#include <Stream.h>
|
||||
|
||||
/* A function that flips a DXTC block. */
|
||||
using FlipBlockFunction = void (*)(uint8_t *block);
|
||||
|
||||
/* Flips a full DXT1 block in the y direction. */
|
||||
static void FlipDXT1BlockFull(uint8_t *block)
|
||||
{
|
||||
/* A DXT1 block layout is:
|
||||
* [0-1] color0.
|
||||
* [2-3] color1.
|
||||
* [4-7] color bitmap, 2 bits per pixel.
|
||||
* So each of the 4-7 bytes represents one line, flipping a block is just
|
||||
* flipping those bytes. */
|
||||
uint8_t tmp = block[4];
|
||||
block[4] = block[7];
|
||||
block[7] = tmp;
|
||||
tmp = block[5];
|
||||
block[5] = block[6];
|
||||
block[6] = tmp;
|
||||
}
|
||||
|
||||
/* Flips the first 2 lines of a DXT1 block in the y direction. */
|
||||
static void FlipDXT1BlockHalf(uint8_t *block)
|
||||
{
|
||||
/* See layout above. */
|
||||
uint8_t tmp = block[4];
|
||||
block[4] = block[5];
|
||||
block[5] = tmp;
|
||||
}
|
||||
|
||||
/* Flips a full DXT3 block in the y direction. */
|
||||
static void FlipDXT3BlockFull(uint8_t *block)
|
||||
{
|
||||
/* A DXT3 block layout is:
|
||||
* [0-7] alpha bitmap, 4 bits per pixel.
|
||||
* [8-15] a DXT1 block. */
|
||||
|
||||
/* We can flip the alpha bits at the byte level (2 bytes per line). */
|
||||
uint8_t tmp = block[0];
|
||||
|
||||
block[0] = block[6];
|
||||
block[6] = tmp;
|
||||
tmp = block[1];
|
||||
block[1] = block[7];
|
||||
block[7] = tmp;
|
||||
tmp = block[2];
|
||||
block[2] = block[4];
|
||||
block[4] = tmp;
|
||||
tmp = block[3];
|
||||
block[3] = block[5];
|
||||
block[5] = tmp;
|
||||
|
||||
/* And flip the DXT1 block using the above function. */
|
||||
FlipDXT1BlockFull(block + 8);
|
||||
}
|
||||
|
||||
/* Flips the first 2 lines of a DXT3 block in the y direction. */
|
||||
static void FlipDXT3BlockHalf(uint8_t *block)
|
||||
{
|
||||
/* See layout above. */
|
||||
uint8_t tmp = block[0];
|
||||
|
||||
block[0] = block[2];
|
||||
block[2] = tmp;
|
||||
tmp = block[1];
|
||||
block[1] = block[3];
|
||||
block[3] = tmp;
|
||||
FlipDXT1BlockHalf(block + 8);
|
||||
}
|
||||
|
||||
/* Flips a full DXT5 block in the y direction. */
|
||||
static void FlipDXT5BlockFull(uint8_t *block)
|
||||
{
|
||||
/* A DXT5 block layout is:
|
||||
* [0] alpha0.
|
||||
* [1] alpha1.
|
||||
* [2-7] alpha bitmap, 3 bits per pixel.
|
||||
* [8-15] a DXT1 block. */
|
||||
|
||||
/* The alpha bitmap doesn't easily map lines to bytes, so we have to
|
||||
* interpret it correctly. Extracted from
|
||||
* http://www.opengl.org/registry/specs/EXT/texture_compression_s3tc.txt :
|
||||
*
|
||||
* The 6 "bits" bytes of the block are decoded into one 48-bit integer:
|
||||
*
|
||||
* bits = bits_0 + 256 * (bits_1 + 256 * (bits_2 + 256 * (bits_3 +
|
||||
* 256 * (bits_4 + 256 * bits_5))))
|
||||
*
|
||||
* bits is a 48-bit unsigned-integer, from which a three-bit control code
|
||||
* is extracted for a texel at location (x,y) in the block using:
|
||||
*
|
||||
* code(x,y) = bits[3*(4*y+x)+1..3*(4*y+x)+0]
|
||||
*
|
||||
* where bit 47 is the most significant and bit 0 is the least
|
||||
* significant bit. */
|
||||
uint line_0_1 = block[2] + 256 * (block[3] + 256 * block[4]);
|
||||
uint line_2_3 = block[5] + 256 * (block[6] + 256 * block[7]);
|
||||
/* swap lines 0 and 1 in line_0_1. */
|
||||
uint line_1_0 = ((line_0_1 & 0x000fff) << 12) | ((line_0_1 & 0xfff000) >> 12);
|
||||
/* swap lines 2 and 3 in line_2_3. */
|
||||
uint line_3_2 = ((line_2_3 & 0x000fff) << 12) | ((line_2_3 & 0xfff000) >> 12);
|
||||
|
||||
block[2] = line_3_2 & 0xff;
|
||||
block[3] = (line_3_2 & 0xff00) >> 8;
|
||||
block[4] = (line_3_2 & 0xff0000) >> 16;
|
||||
block[5] = line_1_0 & 0xff;
|
||||
block[6] = (line_1_0 & 0xff00) >> 8;
|
||||
block[7] = (line_1_0 & 0xff0000) >> 16;
|
||||
|
||||
/* And flip the DXT1 block using the above function. */
|
||||
FlipDXT1BlockFull(block + 8);
|
||||
}
|
||||
|
||||
/* Flips the first 2 lines of a DXT5 block in the y direction. */
|
||||
static void FlipDXT5BlockHalf(uint8_t *block)
|
||||
{
|
||||
/* See layout above. */
|
||||
uint line_0_1 = block[2] + 256 * (block[3] + 256 * block[4]);
|
||||
uint line_1_0 = ((line_0_1 & 0x000fff) << 12) | ((line_0_1 & 0xfff000) >> 12);
|
||||
block[2] = line_1_0 & 0xff;
|
||||
block[3] = (line_1_0 & 0xff00) >> 8;
|
||||
block[4] = (line_1_0 & 0xff0000) >> 16;
|
||||
FlipDXT1BlockHalf(block + 8);
|
||||
}
|
||||
|
||||
int FlipDXTCImage(uint width,
|
||||
uint height,
|
||||
uint levels,
|
||||
int fourcc,
|
||||
uint8_t *data,
|
||||
int data_size,
|
||||
uint *r_num_valid_levels)
|
||||
{
|
||||
*r_num_valid_levels = 0;
|
||||
|
||||
/* Must have valid dimensions. */
|
||||
if (width == 0 || height == 0) {
|
||||
return 0;
|
||||
}
|
||||
/* Height must be a power-of-two. */
|
||||
if ((height & (height - 1)) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
FlipBlockFunction full_block_function;
|
||||
FlipBlockFunction half_block_function;
|
||||
uint block_bytes = 0;
|
||||
|
||||
switch (fourcc) {
|
||||
case FOURCC_DXT1:
|
||||
full_block_function = FlipDXT1BlockFull;
|
||||
half_block_function = FlipDXT1BlockHalf;
|
||||
block_bytes = 8;
|
||||
break;
|
||||
case FOURCC_DXT3:
|
||||
full_block_function = FlipDXT3BlockFull;
|
||||
half_block_function = FlipDXT3BlockHalf;
|
||||
block_bytes = 16;
|
||||
break;
|
||||
case FOURCC_DXT5:
|
||||
full_block_function = FlipDXT5BlockFull;
|
||||
half_block_function = FlipDXT5BlockHalf;
|
||||
block_bytes = 16;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
*r_num_valid_levels = levels;
|
||||
|
||||
uint mip_width = width;
|
||||
uint mip_height = height;
|
||||
|
||||
const uint8_t *data_end = data + data_size;
|
||||
|
||||
for (uint i = 0; i < levels; i++) {
|
||||
uint blocks_per_row = (mip_width + 3) / 4;
|
||||
uint blocks_per_col = (mip_height + 3) / 4;
|
||||
uint blocks = blocks_per_row * blocks_per_col;
|
||||
|
||||
if (data + block_bytes * blocks > data_end) {
|
||||
/* Stop flipping when running out of data to be modified, avoiding possible buffer overrun
|
||||
* on a malformed files. */
|
||||
*r_num_valid_levels = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (mip_height == 1) {
|
||||
/* no flip to do, and we're done. */
|
||||
break;
|
||||
}
|
||||
if (mip_height == 2) {
|
||||
/* flip the first 2 lines in each block. */
|
||||
for (uint i = 0; i < blocks_per_row; i++) {
|
||||
half_block_function(data + i * block_bytes);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* flip each block. */
|
||||
for (uint i = 0; i < blocks; i++) {
|
||||
full_block_function(data + i * block_bytes);
|
||||
}
|
||||
|
||||
/* Swap each block line in the first half of the image with the
|
||||
* corresponding one in the second half.
|
||||
* note that this is a no-op if mip_height is 4. */
|
||||
uint row_bytes = block_bytes * blocks_per_row;
|
||||
uint8_t *temp_line = new uint8_t[row_bytes];
|
||||
|
||||
for (uint y = 0; y < blocks_per_col / 2; y++) {
|
||||
uint8_t *line1 = data + y * row_bytes;
|
||||
uint8_t *line2 = data + (blocks_per_col - y - 1) * row_bytes;
|
||||
|
||||
memcpy(temp_line, line1, row_bytes);
|
||||
memcpy(line1, line2, row_bytes);
|
||||
memcpy(line2, temp_line, row_bytes);
|
||||
}
|
||||
|
||||
delete[] temp_line;
|
||||
}
|
||||
|
||||
/* mip levels are contiguous. */
|
||||
data += block_bytes * blocks;
|
||||
mip_width = MAX(1U, mip_width >> 1);
|
||||
mip_height = MAX(1U, mip_height >> 1);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_sys_types.h"
|
||||
|
||||
/**
|
||||
* Flips a DXTC image, by flipping and swapping DXTC blocks as appropriate.
|
||||
*
|
||||
* Use to flip vertically to fit OpenGL convention.
|
||||
*/
|
||||
int FlipDXTCImage(unsigned int width,
|
||||
unsigned int height,
|
||||
unsigned int levels,
|
||||
int fourcc,
|
||||
uint8_t *data,
|
||||
int data_size,
|
||||
unsigned int *r_num_valid_levels);
|
|
@ -1,106 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup imbdds
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on a similar file from the NVIDIA texture tools
|
||||
* (http://nvidia-texture-tools.googlecode.com/)
|
||||
*
|
||||
* Original license from NVIDIA follows.
|
||||
*/
|
||||
|
||||
/* This code is in the public domain -- <castanyo@yahoo.es>. */
|
||||
|
||||
#include <Color.h>
|
||||
#include <Image.h>
|
||||
|
||||
#include <cstdio> /* printf */
|
||||
|
||||
Image::Image() : m_width(0), m_height(0), m_format(Format_RGB), m_data(nullptr) {}
|
||||
|
||||
Image::~Image()
|
||||
{
|
||||
free();
|
||||
}
|
||||
|
||||
void Image::allocate(uint w, uint h)
|
||||
{
|
||||
free();
|
||||
m_width = w;
|
||||
m_height = h;
|
||||
m_data = new Color32[w * h];
|
||||
}
|
||||
|
||||
void Image::free()
|
||||
{
|
||||
delete[] m_data;
|
||||
m_data = nullptr;
|
||||
}
|
||||
|
||||
uint Image::width() const
|
||||
{
|
||||
return m_width;
|
||||
}
|
||||
|
||||
uint Image::height() const
|
||||
{
|
||||
return m_height;
|
||||
}
|
||||
|
||||
const Color32 *Image::scanline(uint h) const
|
||||
{
|
||||
if (h >= m_height) {
|
||||
printf("DDS: scanline beyond dimensions of image\n");
|
||||
return m_data;
|
||||
}
|
||||
return m_data + h * m_width;
|
||||
}
|
||||
|
||||
Color32 *Image::scanline(uint h)
|
||||
{
|
||||
if (h >= m_height) {
|
||||
printf("DDS: scanline beyond dimensions of image\n");
|
||||
return m_data;
|
||||
}
|
||||
return m_data + h * m_width;
|
||||
}
|
||||
|
||||
const Color32 *Image::pixels() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
Color32 *Image::pixels()
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
const Color32 &Image::pixel(uint idx) const
|
||||
{
|
||||
if (idx >= m_width * m_height) {
|
||||
printf("DDS: pixel beyond dimensions of image\n");
|
||||
return m_data[0];
|
||||
}
|
||||
return m_data[idx];
|
||||
}
|
||||
|
||||
Color32 &Image::pixel(uint idx)
|
||||
{
|
||||
if (idx >= m_width * m_height) {
|
||||
printf("DDS: pixel beyond dimensions of image\n");
|
||||
return m_data[0];
|
||||
}
|
||||
return m_data[idx];
|
||||
}
|
||||
|
||||
Image::Format Image::format() const
|
||||
{
|
||||
return m_format;
|
||||
}
|
||||
|
||||
void Image::setFormat(Image::Format f)
|
||||
{
|
||||
m_format = f;
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup imbdds
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on a similar file from the NVIDIA texture tools
|
||||
* (http://nvidia-texture-tools.googlecode.com/)
|
||||
*
|
||||
* Original license from NVIDIA follows.
|
||||
*/
|
||||
|
||||
/* This code is in the public domain -- <castanyo@yahoo.es> */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Color.h"
|
||||
#include "Common.h"
|
||||
|
||||
/** 32 bit RGBA image. */
|
||||
class Image {
|
||||
public:
|
||||
enum Format {
|
||||
Format_RGB,
|
||||
Format_ARGB,
|
||||
};
|
||||
|
||||
Image();
|
||||
~Image();
|
||||
|
||||
void allocate(uint w, uint h);
|
||||
#if 0
|
||||
bool load(const char *name);
|
||||
|
||||
void wrap(void *data, uint w, uint h);
|
||||
void unwrap();
|
||||
#endif
|
||||
|
||||
uint width() const;
|
||||
uint height() const;
|
||||
|
||||
const Color32 *scanline(uint h) const;
|
||||
Color32 *scanline(uint h);
|
||||
|
||||
const Color32 *pixels() const;
|
||||
Color32 *pixels();
|
||||
|
||||
const Color32 &pixel(uint idx) const;
|
||||
Color32 &pixel(uint idx);
|
||||
|
||||
const Color32 &pixel(uint x, uint y) const;
|
||||
Color32 &pixel(uint x, uint y);
|
||||
|
||||
Format format() const;
|
||||
void setFormat(Format f);
|
||||
|
||||
private:
|
||||
void free();
|
||||
|
||||
private:
|
||||
uint m_width;
|
||||
uint m_height;
|
||||
Format m_format;
|
||||
Color32 *m_data;
|
||||
};
|
||||
|
||||
inline const Color32 &Image::pixel(uint x, uint y) const
|
||||
{
|
||||
return pixel(y * width() + x);
|
||||
}
|
||||
|
||||
inline Color32 &Image::pixel(uint x, uint y)
|
||||
{
|
||||
return pixel(y * width() + x);
|
||||
}
|
|
@ -1,117 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup imbdds
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on a similar file from the NVIDIA texture tools
|
||||
* (http://nvidia-texture-tools.googlecode.com/)
|
||||
*
|
||||
* Original license from NVIDIA follows.
|
||||
*/
|
||||
|
||||
/* Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
namespace PixelFormat {
|
||||
|
||||
/** Convert component \a c having \a inbits to the returned value having \a outbits. */
|
||||
inline uint convert(uint c, uint inbits, uint outbits)
|
||||
{
|
||||
if (inbits == 0) {
|
||||
return 0;
|
||||
}
|
||||
else if (inbits >= outbits) {
|
||||
/* truncate */
|
||||
return c >> (inbits - outbits);
|
||||
}
|
||||
else {
|
||||
/* bitexpand */
|
||||
return (c << (outbits - inbits)) | convert(c, inbits, outbits - inbits);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get pixel component shift and size given its mask. */
|
||||
inline void maskShiftAndSize(uint mask, uint *shift, uint *size)
|
||||
{
|
||||
if (!mask) {
|
||||
*shift = 0;
|
||||
*size = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
*shift = 0;
|
||||
while ((mask & 1) == 0) {
|
||||
++(*shift);
|
||||
mask >>= 1;
|
||||
}
|
||||
|
||||
*size = 0;
|
||||
while ((mask & 1) == 1) {
|
||||
++(*size);
|
||||
mask >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
inline float quantizeCeil(float f, int inbits, int outbits)
|
||||
{
|
||||
#if 0
|
||||
uint i = f * (float(1 << inbits) - 1);
|
||||
i = convert(i, inbits, outbits);
|
||||
float result = float(i) / (float(1 << outbits) - 1);
|
||||
nvCheck(result >= f);
|
||||
#endif
|
||||
float result;
|
||||
|
||||
int offset = 0;
|
||||
do {
|
||||
uint i = offset + uint(f * (float(1 << inbits) - 1));
|
||||
i = convert(i, inbits, outbits);
|
||||
result = float(i) / (float(1 << outbits) - 1);
|
||||
offset++;
|
||||
} while (result < f);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#if 0
|
||||
inline float quantizeRound(float f, int bits)
|
||||
{
|
||||
float scale = float(1 << bits);
|
||||
return fround(f * scale) / scale;
|
||||
}
|
||||
|
||||
inline float quantizeFloor(float f, int bits)
|
||||
{
|
||||
float scale = float(1 << bits);
|
||||
return floor(f * scale) / scale;
|
||||
}
|
||||
#endif
|
||||
|
||||
} /* namespace PixelFormat */
|
|
@ -1,105 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup imbdds
|
||||
*/
|
||||
|
||||
#include "BLI_sys_types.h" /* For `uint`. */
|
||||
|
||||
#include <Stream.h>
|
||||
|
||||
#include <cstdio> /* printf */
|
||||
#include <cstring> /* memcpy */
|
||||
|
||||
static const char *msg_error_seek = "DDS: trying to seek beyond end of stream (corrupt file?)";
|
||||
static const char *msg_error_read = "DDS: trying to read beyond end of stream (corrupt file?)";
|
||||
|
||||
inline bool is_read_within_bounds(const Stream &mem, uint count)
|
||||
{
|
||||
if (mem.pos >= mem.size) {
|
||||
/* No more data remained in the memory buffer. */
|
||||
return false;
|
||||
}
|
||||
|
||||
if (count > mem.size - mem.pos) {
|
||||
/* Reading past the memory bounds. */
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint Stream::seek(uint p)
|
||||
{
|
||||
if (p > size) {
|
||||
set_failed(msg_error_seek);
|
||||
}
|
||||
else {
|
||||
pos = p;
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
uint mem_read(Stream &mem, unsigned long long &i)
|
||||
{
|
||||
if (!is_read_within_bounds(mem, 8)) {
|
||||
mem.set_failed(msg_error_seek);
|
||||
return 0;
|
||||
}
|
||||
memcpy(&i, mem.mem + mem.pos, 8); /* TODO: make sure little endian. */
|
||||
mem.pos += 8;
|
||||
return 8;
|
||||
}
|
||||
|
||||
uint mem_read(Stream &mem, uint &i)
|
||||
{
|
||||
if (!is_read_within_bounds(mem, 4)) {
|
||||
mem.set_failed(msg_error_read);
|
||||
return 0;
|
||||
}
|
||||
memcpy(&i, mem.mem + mem.pos, 4); /* TODO: make sure little endian. */
|
||||
mem.pos += 4;
|
||||
return 4;
|
||||
}
|
||||
|
||||
uint mem_read(Stream &mem, ushort &i)
|
||||
{
|
||||
if (!is_read_within_bounds(mem, 2)) {
|
||||
mem.set_failed(msg_error_read);
|
||||
return 0;
|
||||
}
|
||||
memcpy(&i, mem.mem + mem.pos, 2); /* TODO: make sure little endian. */
|
||||
mem.pos += 2;
|
||||
return 2;
|
||||
}
|
||||
|
||||
uint mem_read(Stream &mem, uchar &i)
|
||||
{
|
||||
if (!is_read_within_bounds(mem, 1)) {
|
||||
mem.set_failed(msg_error_read);
|
||||
return 0;
|
||||
}
|
||||
i = (mem.mem + mem.pos)[0];
|
||||
mem.pos += 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint mem_read(Stream &mem, uchar *i, uint count)
|
||||
{
|
||||
if (!is_read_within_bounds(mem, count)) {
|
||||
mem.set_failed(msg_error_read);
|
||||
return 0;
|
||||
}
|
||||
memcpy(i, mem.mem + mem.pos, count);
|
||||
mem.pos += count;
|
||||
return count;
|
||||
}
|
||||
|
||||
void Stream::set_failed(const char *msg)
|
||||
{
|
||||
if (!failed) {
|
||||
puts(msg);
|
||||
failed = true;
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup imbdds
|
||||
*/
|
||||
|
||||
/* simple memory stream functions with buffer overflow check */
|
||||
|
||||
#pragma once
|
||||
|
||||
struct Stream {
|
||||
unsigned char *mem; /* location in memory */
|
||||
unsigned int size; /* size */
|
||||
unsigned int pos; /* current position */
|
||||
bool failed; /* error occurred when seeking */
|
||||
Stream(unsigned char *m, unsigned int s) : mem(m), size(s), pos(0), failed(false) {}
|
||||
unsigned int seek(unsigned int p);
|
||||
void set_failed(const char *msg);
|
||||
};
|
||||
|
||||
unsigned int mem_read(Stream &mem, unsigned long long &i);
|
||||
unsigned int mem_read(Stream &mem, unsigned int &i);
|
||||
unsigned int mem_read(Stream &mem, unsigned short &i);
|
||||
unsigned int mem_read(Stream &mem, unsigned char &i);
|
||||
unsigned int mem_read(Stream &mem, unsigned char *i, unsigned int count);
|
|
@ -1,193 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup imbdds
|
||||
*/
|
||||
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include <DirectDrawSurface.h>
|
||||
#include <FlipDXT.h>
|
||||
#include <Stream.h>
|
||||
#include <cstddef>
|
||||
#include <cstdio> /* printf */
|
||||
#include <dds_api.h>
|
||||
#include <fstream>
|
||||
|
||||
#if defined(WIN32)
|
||||
# include "utfconv.h"
|
||||
#endif
|
||||
|
||||
#include "IMB_allocimbuf.h"
|
||||
#include "IMB_imbuf.h"
|
||||
#include "IMB_imbuf_types.h"
|
||||
#include "imbuf.h"
|
||||
|
||||
#include "IMB_colormanagement.h"
|
||||
#include "IMB_colormanagement_intern.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
bool imb_save_dds(struct ImBuf *ibuf, const char *filepath, int /*flags*/)
|
||||
{
|
||||
return false; /* TODO: finish this function. */
|
||||
|
||||
/* check image buffer */
|
||||
if (ibuf == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (ibuf->rect == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* open file for writing */
|
||||
std::ofstream fildes;
|
||||
|
||||
#if defined(WIN32)
|
||||
wchar_t *wname = alloc_utf16_from_8(filepath, 0);
|
||||
fildes.open(wname);
|
||||
free(wname);
|
||||
#else
|
||||
fildes.open(filepath);
|
||||
#endif
|
||||
|
||||
/* write header */
|
||||
fildes << "DDS ";
|
||||
fildes.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool imb_is_a_dds(const uchar *mem, const size_t size)
|
||||
{
|
||||
if (size < 8) {
|
||||
return false;
|
||||
}
|
||||
/* heuristic check to see if mem contains a DDS file */
|
||||
/* header.fourcc == FOURCC_DDS */
|
||||
if ((mem[0] != 'D') || (mem[1] != 'D') || (mem[2] != 'S') || (mem[3] != ' ')) {
|
||||
return false;
|
||||
}
|
||||
/* header.size == 124 */
|
||||
if ((mem[4] != 124) || mem[5] || mem[6] || mem[7]) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
struct ImBuf *imb_load_dds(const uchar *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
|
||||
{
|
||||
struct ImBuf *ibuf = nullptr;
|
||||
DirectDrawSurface dds((uchar *)mem, size); /* reads header */
|
||||
uchar bits_per_pixel;
|
||||
uint *rect;
|
||||
Image img;
|
||||
uint numpixels = 0;
|
||||
int col;
|
||||
uchar *cp = (uchar *)&col;
|
||||
Color32 pixel;
|
||||
Color32 *pixels = nullptr;
|
||||
|
||||
/* OCIO_TODO: never was able to save DDS, so can't test loading
|
||||
* but profile used to be set to sRGB and can't see rect_float here, so
|
||||
* default byte space should work fine
|
||||
*/
|
||||
colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE);
|
||||
|
||||
if (!imb_is_a_dds(mem, size)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* check if DDS is valid and supported */
|
||||
if (!dds.isValid()) {
|
||||
/* no need to print error here, just testing if it is a DDS */
|
||||
if (flags & IB_test) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
printf("DDS: not valid; header follows\n");
|
||||
dds.printInfo();
|
||||
return nullptr;
|
||||
}
|
||||
if (!dds.isSupported()) {
|
||||
printf("DDS: format not supported\n");
|
||||
return nullptr;
|
||||
}
|
||||
if ((dds.width() > 65535) || (dds.height() > 65535)) {
|
||||
printf("DDS: dimensions too large\n");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* convert DDS into ImBuf */
|
||||
dds.mipmap(&img, 0, 0); /* load first face, first mipmap */
|
||||
pixels = img.pixels();
|
||||
numpixels = dds.width() * dds.height();
|
||||
bits_per_pixel = 24;
|
||||
if (img.format() == Image::Format_ARGB) {
|
||||
/* check that there is effectively an alpha channel */
|
||||
for (uint i = 0; i < numpixels; i++) {
|
||||
pixel = pixels[i];
|
||||
if (pixel.a != 255) {
|
||||
bits_per_pixel = 32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ibuf = IMB_allocImBuf(dds.width(), dds.height(), bits_per_pixel, 0);
|
||||
if (ibuf == nullptr) {
|
||||
return nullptr; /* memory allocation failed */
|
||||
}
|
||||
|
||||
ibuf->ftype = IMB_FTYPE_DDS;
|
||||
ibuf->dds_data.fourcc = dds.fourCC();
|
||||
ibuf->dds_data.nummipmaps = dds.mipmapCount();
|
||||
|
||||
if ((flags & IB_test) == 0) {
|
||||
if (!imb_addrectImBuf(ibuf)) {
|
||||
return ibuf;
|
||||
}
|
||||
if (ibuf->rect == nullptr) {
|
||||
return ibuf;
|
||||
}
|
||||
|
||||
rect = ibuf->rect;
|
||||
cp[3] = 0xff; /* default alpha if alpha channel is not present */
|
||||
|
||||
for (uint i = 0; i < numpixels; i++) {
|
||||
pixel = pixels[i];
|
||||
cp[0] = pixel.r; /* set R component of col */
|
||||
cp[1] = pixel.g; /* set G component of col */
|
||||
cp[2] = pixel.b; /* set B component of col */
|
||||
if (dds.hasAlpha()) {
|
||||
cp[3] = pixel.a; /* set A component of col */
|
||||
}
|
||||
rect[i] = col;
|
||||
}
|
||||
|
||||
if (ibuf->dds_data.fourcc != FOURCC_DDS) {
|
||||
ibuf->dds_data.data = (uchar *)dds.readData(ibuf->dds_data.size);
|
||||
|
||||
/* flip compressed texture */
|
||||
if (ibuf->dds_data.data) {
|
||||
FlipDXTCImage(dds.width(),
|
||||
dds.height(),
|
||||
ibuf->dds_data.nummipmaps,
|
||||
dds.fourCC(),
|
||||
ibuf->dds_data.data,
|
||||
ibuf->dds_data.size,
|
||||
&ibuf->dds_data.nummipmaps);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ibuf->dds_data.data = nullptr;
|
||||
ibuf->dds_data.size = 0;
|
||||
}
|
||||
|
||||
/* flip uncompressed texture */
|
||||
IMB_flipy(ibuf);
|
||||
}
|
||||
|
||||
return ibuf;
|
||||
}
|
||||
|
||||
} /* extern "C" */
|
|
@ -1,24 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup imbdds
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../../IMB_imbuf.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool imb_is_a_dds(const unsigned char *mem, size_t size);
|
||||
bool imb_save_dds(struct ImBuf *ibuf, const char *filepath, int flags);
|
||||
struct ImBuf *imb_load_dds(const unsigned char *mem,
|
||||
size_t size,
|
||||
int flags,
|
||||
char colorspace[IM_MAX_SPACE]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -2143,11 +2143,12 @@ typedef enum CMPNodeStabilizeInverse {
|
|||
CMP_NODE_STABILIZE_FLAG_INVERSE = 1,
|
||||
} CMPNodeStabilizeInverse;
|
||||
|
||||
/* Plane track deform node. */
|
||||
#define CMP_NODE_PLANE_TRACK_DEFORM_MOTION_BLUR_SAMPLES_MAX 64
|
||||
|
||||
enum {
|
||||
CMP_NODEFLAG_PLANETRACKDEFORM_MOTION_BLUR = 1,
|
||||
};
|
||||
/* Plane track deform node. */
|
||||
typedef enum CMPNodePlaneTrackDeformFlags {
|
||||
CMP_NODE_PLANE_TRACK_DEFORM_FLAG_MOTION_BLUR = 1,
|
||||
} CMPNodePlaneTrackDeformFlags;
|
||||
|
||||
/* Set Alpha Node. */
|
||||
|
||||
|
@ -2176,8 +2177,6 @@ typedef enum CMPNodeCombSepColorMode {
|
|||
CMP_NODE_COMBSEP_COLOR_YUV = 4,
|
||||
} CMPNodeCombSepColorMode;
|
||||
|
||||
#define CMP_NODE_PLANETRACKDEFORM_MBLUR_SAMPLES_MAX 64
|
||||
|
||||
/* Point Density shader node */
|
||||
|
||||
enum {
|
||||
|
|
|
@ -345,7 +345,7 @@ typedef struct ThemeSpace {
|
|||
unsigned char nodeclass_geometry[4], nodeclass_attribute[4];
|
||||
|
||||
unsigned char node_zone_simulation[4];
|
||||
char _pad8[4];
|
||||
unsigned char simulated_frames[4];
|
||||
|
||||
/** For sequence editor. */
|
||||
unsigned char movie[4], movieclip[4], mask[4], image[4], scene[4], audio[4];
|
||||
|
|
|
@ -9213,12 +9213,12 @@ static void def_cmp_planetrackdeform(StructRNA *srna)
|
|||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_motion_blur", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", CMP_NODEFLAG_PLANETRACKDEFORM_MOTION_BLUR);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", CMP_NODE_PLANE_TRACK_DEFORM_FLAG_MOTION_BLUR);
|
||||
RNA_def_property_ui_text(prop, "Motion Blur", "Use multi-sampled motion blur of the mask");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
|
||||
prop = RNA_def_property(srna, "motion_blur_samples", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_range(prop, 1, CMP_NODE_PLANETRACKDEFORM_MBLUR_SAMPLES_MAX);
|
||||
RNA_def_property_range(prop, 1, CMP_NODE_PLANE_TRACK_DEFORM_MOTION_BLUR_SAMPLES_MAX);
|
||||
RNA_def_property_ui_text(prop, "Samples", "Number of motion blur samples");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
|
||||
|
|
|
@ -3563,6 +3563,12 @@ static void rna_def_userdef_theme_space_action(BlenderRNA *brna)
|
|||
RNA_def_property_ui_text(
|
||||
prop, "Interpolation Line", "Color of lines showing non-bezier interpolation modes");
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
|
||||
|
||||
prop = RNA_def_property(srna, "simulated_frames", PROP_FLOAT, PROP_COLOR_GAMMA);
|
||||
RNA_def_property_float_sdna(prop, NULL, "simulated_frames");
|
||||
RNA_def_property_array(prop, 4);
|
||||
RNA_def_property_ui_text(prop, "Simulated Frames", "");
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
|
||||
}
|
||||
|
||||
static void rna_def_userdef_theme_space_nla(BlenderRNA *brna)
|
||||
|
|
|
@ -102,7 +102,7 @@ static void node_composit_buts_planetrackdeform(uiLayout *layout, bContext *C, P
|
|||
}
|
||||
|
||||
uiItemR(layout, ptr, "use_motion_blur", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
|
||||
if (data->flag & CMP_NODEFLAG_PLANETRACKDEFORM_MOTION_BLUR) {
|
||||
if (data->flag & CMP_NODE_PLANE_TRACK_DEFORM_FLAG_MOTION_BLUR) {
|
||||
uiItemR(layout, ptr, "motion_blur_samples", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
|
||||
uiItemR(layout, ptr, "motion_blur_shutter", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
|
||||
}
|
||||
|
|
|
@ -75,6 +75,18 @@ if(WITH_TBB)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_USD)
|
||||
# USD links libMaterialX, when using pre-compiled libraries
|
||||
# ensures `usd_ms` can find `MaterialXRender` and friends.
|
||||
#
|
||||
# NOTE: This is _only_ needed when linking blender before the install target runs.
|
||||
# Once MATERIALX libraries have been copied into `TARGETDIR_LIB` then Blender will link.
|
||||
# Don't rely on this though as failing on a fresh build is no good and the library
|
||||
# files could get outdated too.
|
||||
if(DEFINED LIBDIR)
|
||||
link_directories(${LIBDIR}/materialx/lib)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_PYTHON)
|
||||
list(APPEND INC ../blender/python)
|
||||
|
|
Loading…
Reference in New Issue