Merge branch 'master' into blender2.8

Conflicts:
	source/blender/blenkernel/BKE_particle.h
	source/blender/blenkernel/intern/library.c
	source/blender/blenkernel/intern/particle.c
This commit is contained in:
Bastien Montagne 2016-07-25 15:07:17 +02:00
commit b1532493c2
198 changed files with 4661 additions and 1778 deletions

View File

@ -1283,11 +1283,21 @@ elseif(WIN32)
if(MSVC)
# Minimum MSVC Version
set(_min_ver "18.0.31101")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${_min_ver})
message(FATAL_ERROR
"Visual Studio 2013 (Update 4, ${_min_ver}) required, "
"found (${CMAKE_CXX_COMPILER_VERSION})")
if(MSVC_VERSION EQUAL 1800)
set(_min_ver "18.0.31101")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${_min_ver})
message(FATAL_ERROR
"Visual Studio 2013 (Update 4, ${_min_ver}) required, "
"found (${CMAKE_CXX_COMPILER_VERSION})")
endif()
endif()
if(MSVC_VERSION EQUAL 1900)
set(_min_ver "19.0.24210")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${_min_ver})
message(FATAL_ERROR
"Visual Studio 2015 (Update 3, ${_min_ver}) required, "
"found (${CMAKE_CXX_COMPILER_VERSION})")
endif()
endif()
unset(_min_ver)
@ -1353,17 +1363,6 @@ elseif(WIN32)
set(PLATFORM_LINKFLAGS_DEBUG "/IGNORE:4099 /NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:libc.lib")
# Use dynamic loading for OpenMP
if(WITH_OPENMP)
if(MSVC_VERSION EQUAL 1800)
set(OPENMP_DLL_NAME "vcomp120")
else()
set(OPENMP_DLL_NAME "vcomp140")
endif()
set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} /DELAYLOAD:${OPENMP_DLL_NAME}.dll delayimp.lib")
set(PLATFORM_LINKFLAGS_DEBUG "${PLATFORM_LINKFLAGS_DEBUG} /DELAYLOAD:${OPENMP_DLL_NAME}d.dll delayimp.lib")
endif()
if(NOT DEFINED LIBDIR)
# Setup 64bit and 64bit windows systems
@ -3162,6 +3161,14 @@ add_subdirectory(tests)
# CPack for generating packages
include(build_files/cmake/packaging.cmake)
#-----------------------------------------------------------------------------
# Use dynamic loading for OpenMP
if(WITH_BLENDER)
openmp_delayload(blender)
endif(WITH_BLENDER)
if(WITH_PLAYER)
openmp_delayload(blenderplayer)
endif(WITH_PLAYER)
#-----------------------------------------------------------------------------
# Print Final Configuration

View File

@ -1547,3 +1547,21 @@ function(print_all_vars)
message("${_var}=${${_var}}")
endforeach()
endfunction()
macro(openmp_delayload
projectname
)
if(MSVC)
if(WITH_OPENMP)
if(MSVC_VERSION EQUAL 1800)
set(OPENMP_DLL_NAME "vcomp120")
else()
set(OPENMP_DLL_NAME "vcomp140")
endif()
SET_TARGET_PROPERTIES(${projectname} PROPERTIES LINK_FLAGS_RELEASE "/DELAYLOAD:${OPENMP_DLL_NAME}.dll delayimp.lib")
SET_TARGET_PROPERTIES(${projectname} PROPERTIES LINK_FLAGS_DEBUG "/DELAYLOAD:${OPENMP_DLL_NAME}d.dll delayimp.lib")
SET_TARGET_PROPERTIES(${projectname} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/DELAYLOAD:${OPENMP_DLL_NAME}.dll delayimp.lib")
SET_TARGET_PROPERTIES(${projectname} PROPERTIES LINK_FLAGS_MINSIZEREL "/DELAYLOAD:${OPENMP_DLL_NAME}.dll delayimp.lib")
endif(WITH_OPENMP)
endif(MSVC)
endmacro()

View File

@ -26,10 +26,14 @@ set(INC_SYS
set(SRC
intern/curve_fit_cubic.c
intern/curve_fit_cubic_refit.c
intern/curve_fit_corners_detect.c
intern/curve_fit_inline.h
curve_fit_nd.h
intern/curve_fit_inline.h
intern/generic_alloc_impl.h
intern/generic_heap.c
intern/generic_heap.h
)
blender_add_lib(extern_curve_fit_nd "${SRC}" "${INC}" "${INC_SYS}")

View File

@ -86,6 +86,7 @@ int curve_fit_cubic_to_points_fl(
*
* \param points, points_len: The array of points to calculate a cubics from.
* \param dims: The number of dimensions for for each element in \a points.
* \param points_length_cache: Optional pre-calculated lengths between points.
* \param error_threshold: the error threshold to allow for,
* \param tan_l, tan_r: Normalized tangents the handles will be aligned to.
* Note that tangents must both point along the direction of the \a points,
@ -98,6 +99,7 @@ int curve_fit_cubic_to_points_fl(
int curve_fit_cubic_to_points_single_db(
const double *points,
const unsigned int points_len,
const double *points_length_cache,
const unsigned int dims,
const double error_threshold,
const double tan_l[],
@ -110,6 +112,7 @@ int curve_fit_cubic_to_points_single_db(
int curve_fit_cubic_to_points_single_fl(
const float *points,
const unsigned int points_len,
const float *points_length_cache,
const unsigned int dims,
const float error_threshold,
const float tan_l[],
@ -121,8 +124,40 @@ int curve_fit_cubic_to_points_single_fl(
enum {
CURVE_FIT_CALC_HIGH_QUALIY = (1 << 0),
CURVE_FIT_CALC_CYCLIC = (1 << 1),
};
/* curve_fit_cubic_refit.c */
int curve_fit_cubic_to_points_refit_db(
const double *points,
const unsigned int points_len,
const unsigned int dims,
const double error_threshold,
const unsigned int calc_flag,
const unsigned int *corners,
unsigned int corners_len,
const double corner_angle,
double **r_cubic_array, unsigned int *r_cubic_array_len,
unsigned int **r_cubic_orig_index,
unsigned int **r_corner_index_array, unsigned int *r_corner_index_len);
int curve_fit_cubic_to_points_refit_fl(
const float *points,
const unsigned int points_len,
const unsigned int dims,
const float error_threshold,
const unsigned int calc_flag,
const unsigned int *corners,
unsigned int corners_len,
const float corner_angle,
float **r_cubic_array, unsigned int *r_cubic_array_len,
unsigned int **r_cubic_orig_index,
unsigned int **r_corner_index_array, unsigned int *r_corner_index_len);
/* curve_fit_corners_detect.c */
/**

View File

@ -474,7 +474,7 @@ static double points_calc_circumference_factor(
* We could try support this but will likely cause extreme >1 scales which could cause other issues. */
// assert(angle >= len_tangent);
double factor = (angle / len_tangent);
assert(factor < (M_PI / 2) + DBL_EPSILON);
assert(factor < (M_PI / 2) + (DBL_EPSILON * 10));
return factor;
}
else {
@ -876,7 +876,6 @@ static double points_calc_coord_length(
#ifdef USE_LENGTH_CACHE
length = points_length_cache[i];
assert(len_vnvn(pt, pt_prev, dims) == points_length_cache[i]);
#else
length = len_vnvn(pt, pt_prev, dims);
@ -1435,6 +1434,7 @@ int curve_fit_cubic_to_points_fl(
int curve_fit_cubic_to_points_single_db(
const double *points,
const uint points_len,
const double *points_length_cache,
const uint dims,
const double error_threshold,
const double tan_l[],
@ -1451,10 +1451,14 @@ int curve_fit_cubic_to_points_single_db(
/* in this instance theres no advantage in using length cache,
* since we're not recursively calculating values. */
#ifdef USE_LENGTH_CACHE
double *points_length_cache = malloc(sizeof(double) * points_len);
points_calc_coord_length_cache(
points, points_len, dims,
points_length_cache);
double *points_length_cache_alloc = NULL;
if (points_length_cache == NULL) {
points_length_cache_alloc = malloc(sizeof(double) * points_len);
points_calc_coord_length_cache(
points, points_len, dims,
points_length_cache_alloc);
points_length_cache = points_length_cache_alloc;
}
#endif
fit_cubic_to_points(
@ -1467,7 +1471,9 @@ int curve_fit_cubic_to_points_single_db(
cubic, r_error_max_sq, &split_index);
#ifdef USE_LENGTH_CACHE
free(points_length_cache);
if (points_length_cache_alloc) {
free(points_length_cache_alloc);
}
#endif
copy_vnvn(r_handle_l, CUBIC_PT(cubic, 1, dims), dims);
@ -1479,6 +1485,7 @@ int curve_fit_cubic_to_points_single_db(
int curve_fit_cubic_to_points_single_fl(
const float *points,
const uint points_len,
const float *points_length_cache,
const uint dims,
const float error_threshold,
const float tan_l[],
@ -1490,9 +1497,15 @@ int curve_fit_cubic_to_points_single_fl(
{
const uint points_flat_len = points_len * dims;
double *points_db = malloc(sizeof(double) * points_flat_len);
double *points_length_cache_db = NULL;
copy_vndb_vnfl(points_db, points, points_flat_len);
if (points_length_cache) {
points_length_cache_db = malloc(sizeof(double) * points_len);
copy_vndb_vnfl(points_length_cache_db, points_length_cache, points_len);
}
#ifdef USE_VLA
double tan_l_db[dims];
double tan_r_db[dims];
@ -1510,7 +1523,7 @@ int curve_fit_cubic_to_points_single_fl(
copy_vndb_vnfl(tan_r_db, tan_r, dims);
int result = curve_fit_cubic_to_points_single_db(
points_db, points_len, dims,
points_db, points_len, points_length_cache_db, dims,
(double)error_threshold,
tan_l_db, tan_r_db,
r_handle_l_db, r_handle_r_db,
@ -1518,6 +1531,10 @@ int curve_fit_cubic_to_points_single_fl(
free(points_db);
if (points_length_cache_db) {
free(points_length_cache_db);
}
copy_vnfl_vndb(r_handle_l, r_handle_l_db, dims);
copy_vnfl_vndb(r_handle_r, r_handle_r_db, dims);
*r_error_sq = (float)r_error_sq_db;

File diff suppressed because it is too large Load Diff

View File

@ -290,14 +290,12 @@ MINLINE bool equals_vnvn(
return true;
}
#if 0
MINLINE void project_vn_vnvn(
double v_out[], const double p[], const double v_proj[], const uint dims)
{
const double mul = dot_vnvn(p, v_proj, dims) / dot_vnvn(v_proj, v_proj, dims);
mul_vnvn_fl(v_out, v_proj, mul, dims);
}
#endif
MINLINE void project_vn_vnvn_normalized(
double v_out[], const double p[], const double v_proj[], const uint dims)

View File

@ -0,0 +1,220 @@
/*
* Copyright (c) 2016, Blender Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the <organization> nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file generic_alloc_impl.c
* \ingroup curve_fit
*
* Simple Memory Chunking Allocator
* ================================
*
* Defines need to be set:
* - #TPOOL_IMPL_PREFIX: Prefix to use for the API.
* - #TPOOL_ALLOC_TYPE: Struct type this pool handles.
* - #TPOOL_STRUCT: Name for pool struct name.
* - #TPOOL_CHUNK_SIZE: Chunk size (optional), use 64kb when not defined.
*
* \note #TPOOL_ALLOC_TYPE must be at least ``sizeof(void *)``.
*
* Defines the API, uses #TPOOL_IMPL_PREFIX to prefix each function.
*
* - *_pool_create()
* - *_pool_destroy()
* - *_pool_clear()
*
* - *_pool_elem_alloc()
* - *_pool_elem_calloc()
* - *_pool_elem_free()
*/
/* check we're not building directly */
#if !defined(TPOOL_IMPL_PREFIX) || \
!defined(TPOOL_ALLOC_TYPE) || \
!defined(TPOOL_STRUCT)
# error "This file can't be compiled directly, include in another source file"
#endif
#define _CONCAT_AUX(MACRO_ARG1, MACRO_ARG2) MACRO_ARG1 ## MACRO_ARG2
#define _CONCAT(MACRO_ARG1, MACRO_ARG2) _CONCAT_AUX(MACRO_ARG1, MACRO_ARG2)
#define _TPOOL_PREFIX(id) _CONCAT(TPOOL_IMPL_PREFIX, _##id)
/* local identifiers */
#define pool_create _TPOOL_PREFIX(pool_create)
#define pool_destroy _TPOOL_PREFIX(pool_destroy)
#define pool_clear _TPOOL_PREFIX(pool_clear)
#define pool_elem_alloc _TPOOL_PREFIX(pool_elem_alloc)
#define pool_elem_calloc _TPOOL_PREFIX(pool_elem_calloc)
#define pool_elem_free _TPOOL_PREFIX(pool_elem_free)
/* private identifiers (only for this file, undefine after) */
#define pool_alloc_chunk _TPOOL_PREFIX(pool_alloc_chunk)
#define TPoolChunk _TPOOL_PREFIX(TPoolChunk)
#define TPoolChunkElemFree _TPOOL_PREFIX(TPoolChunkElemFree)
#ifndef TPOOL_CHUNK_SIZE
#define TPOOL_CHUNK_SIZE (1 << 16) /* 64kb */
#define _TPOOL_CHUNK_SIZE_UNDEF
#endif
#ifndef UNLIKELY
# ifdef __GNUC__
# define UNLIKELY(x) __builtin_expect(!!(x), 0)
# else
# define UNLIKELY(x) (x)
# endif
#endif
#ifdef __GNUC__
# define MAYBE_UNUSED __attribute__((unused))
#else
# define MAYBE_UNUSED
#endif
struct TPoolChunk {
struct TPoolChunk *prev;
unsigned int size;
unsigned int bufsize;
TPOOL_ALLOC_TYPE buf[0];
};
struct TPoolChunkElemFree {
struct TPoolChunkElemFree *next;
};
struct TPOOL_STRUCT {
/* Always keep at least one chunk (never NULL) */
struct TPoolChunk *chunk;
/* when NULL, allocate a new chunk */
struct TPoolChunkElemFree *free;
};
/**
* Number of elems to include per #TPoolChunk when no reserved size is passed,
* or we allocate past the reserved number.
*
* \note Optimize number for 64kb allocs.
*/
#define _TPOOL_CHUNK_DEFAULT_NUM \
(((1 << 16) - sizeof(struct TPoolChunk)) / sizeof(TPOOL_ALLOC_TYPE))
/** \name Internal Memory Management
* \{ */
static struct TPoolChunk *pool_alloc_chunk(
unsigned int tot_elems, struct TPoolChunk *chunk_prev)
{
struct TPoolChunk *chunk = malloc(
sizeof(struct TPoolChunk) + (sizeof(TPOOL_ALLOC_TYPE) * tot_elems));
chunk->prev = chunk_prev;
chunk->bufsize = tot_elems;
chunk->size = 0;
return chunk;
}
static TPOOL_ALLOC_TYPE *pool_elem_alloc(struct TPOOL_STRUCT *pool)
{
TPOOL_ALLOC_TYPE *elem;
if (pool->free) {
elem = (TPOOL_ALLOC_TYPE *)pool->free;
pool->free = pool->free->next;
}
else {
struct TPoolChunk *chunk = pool->chunk;
if (UNLIKELY(chunk->size == chunk->bufsize)) {
chunk = pool->chunk = pool_alloc_chunk(_TPOOL_CHUNK_DEFAULT_NUM, chunk);
}
elem = &chunk->buf[chunk->size++];
}
return elem;
}
MAYBE_UNUSED
static TPOOL_ALLOC_TYPE *pool_elem_calloc(struct TPOOL_STRUCT *pool)
{
TPOOL_ALLOC_TYPE *elem = pool_elem_alloc(pool);
memset(elem, 0, sizeof(*elem));
return elem;
}
static void pool_elem_free(struct TPOOL_STRUCT *pool, TPOOL_ALLOC_TYPE *elem)
{
struct TPoolChunkElemFree *elem_free = (struct TPoolChunkElemFree *)elem;
elem_free->next = pool->free;
pool->free = elem_free;
}
static void pool_create(struct TPOOL_STRUCT *pool, unsigned int tot_reserve)
{
pool->chunk = pool_alloc_chunk((tot_reserve > 1) ? tot_reserve : _TPOOL_CHUNK_DEFAULT_NUM, NULL);
pool->free = NULL;
}
MAYBE_UNUSED
static void pool_clear(struct TPOOL_STRUCT *pool)
{
/* Remove all except the last chunk */
while (pool->chunk->prev) {
struct TPoolChunk *chunk_prev = pool->chunk->prev;
free(pool->chunk);
pool->chunk = chunk_prev;
}
pool->chunk->size = 0;
pool->free = NULL;
}
static void pool_destroy(struct TPOOL_STRUCT *pool)
{
struct TPoolChunk *chunk = pool->chunk;
do {
struct TPoolChunk *chunk_prev;
chunk_prev = chunk->prev;
free(chunk);
chunk = chunk_prev;
} while (chunk);
pool->chunk = NULL;
pool->free = NULL;
}
/** \} */
#undef _TPOOL_CHUNK_DEFAULT_NUM
#undef _CONCAT_AUX
#undef _CONCAT
#undef _TPOOL_PREFIX
#undef TPoolChunk
#undef TPoolChunkElemFree
#ifdef _TPOOL_CHUNK_SIZE_UNDEF
# undef TPOOL_CHUNK_SIZE
# undef _TPOOL_CHUNK_SIZE_UNDEF
#endif

View File

@ -0,0 +1,278 @@
/*
* Copyright (c) 2016, Blender Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the <organization> nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** \file generic_heap.c
* \ingroup curve_fit
*/
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <assert.h>
#include "generic_heap.h"
/* swap with a temp value */
#define SWAP_TVAL(tval, a, b) { \
(tval) = (a); \
(a) = (b); \
(b) = (tval); \
} (void)0
#ifdef __GNUC__
# define UNLIKELY(x) __builtin_expect(!!(x), 0)
#else
# define UNLIKELY(x) (x)
#endif
/***/
struct HeapNode {
void *ptr;
double value;
unsigned int index;
};
/* heap_* pool allocator */
#define TPOOL_IMPL_PREFIX heap
#define TPOOL_ALLOC_TYPE HeapNode
#define TPOOL_STRUCT HeapMemPool
#include "generic_alloc_impl.h"
#undef TPOOL_IMPL_PREFIX
#undef TPOOL_ALLOC_TYPE
#undef TPOOL_STRUCT
struct Heap {
unsigned int size;
unsigned int bufsize;
HeapNode **tree;
struct HeapMemPool pool;
};
/** \name Internal Functions
* \{ */
#define HEAP_PARENT(i) (((i) - 1) >> 1)
#define HEAP_LEFT(i) (((i) << 1) + 1)
#define HEAP_RIGHT(i) (((i) << 1) + 2)
#define HEAP_COMPARE(a, b) ((a)->value < (b)->value)
#if 0 /* UNUSED */
#define HEAP_EQUALS(a, b) ((a)->value == (b)->value)
#endif
static void heap_swap(Heap *heap, const unsigned int i, const unsigned int j)
{
#if 0
SWAP(unsigned int, heap->tree[i]->index, heap->tree[j]->index);
SWAP(HeapNode *, heap->tree[i], heap->tree[j]);
#else
HeapNode **tree = heap->tree;
union {
unsigned int index;
HeapNode *node;
} tmp;
SWAP_TVAL(tmp.index, tree[i]->index, tree[j]->index);
SWAP_TVAL(tmp.node, tree[i], tree[j]);
#endif
}
static void heap_down(Heap *heap, unsigned int i)
{
/* size won't change in the loop */
const unsigned int size = heap->size;
while (1) {
const unsigned int l = HEAP_LEFT(i);
const unsigned int r = HEAP_RIGHT(i);
unsigned int smallest;
smallest = ((l < size) && HEAP_COMPARE(heap->tree[l], heap->tree[i])) ? l : i;
if ((r < size) && HEAP_COMPARE(heap->tree[r], heap->tree[smallest])) {
smallest = r;
}
if (smallest == i) {
break;
}
heap_swap(heap, i, smallest);
i = smallest;
}
}
static void heap_up(Heap *heap, unsigned int i)
{
while (i > 0) {
const unsigned int p = HEAP_PARENT(i);
if (HEAP_COMPARE(heap->tree[p], heap->tree[i])) {
break;
}
heap_swap(heap, p, i);
i = p;
}
}
/** \} */
/** \name Public Heap API
* \{ */
/* use when the size of the heap is known in advance */
Heap *HEAP_new(unsigned int tot_reserve)
{
Heap *heap = malloc(sizeof(Heap));
/* ensure we have at least one so we can keep doubling it */
heap->size = 0;
heap->bufsize = tot_reserve ? tot_reserve : 1;
heap->tree = malloc(heap->bufsize * sizeof(HeapNode *));
heap_pool_create(&heap->pool, tot_reserve);
return heap;
}
void HEAP_free(Heap *heap, HeapFreeFP ptrfreefp)
{
if (ptrfreefp) {
unsigned int i;
for (i = 0; i < heap->size; i++) {
ptrfreefp(heap->tree[i]->ptr);
}
}
heap_pool_destroy(&heap->pool);
free(heap->tree);
free(heap);
}
void HEAP_clear(Heap *heap, HeapFreeFP ptrfreefp)
{
if (ptrfreefp) {
unsigned int i;
for (i = 0; i < heap->size; i++) {
ptrfreefp(heap->tree[i]->ptr);
}
}
heap->size = 0;
heap_pool_clear(&heap->pool);
}
HeapNode *HEAP_insert(Heap *heap, double value, void *ptr)
{
HeapNode *node;
if (UNLIKELY(heap->size >= heap->bufsize)) {
heap->bufsize *= 2;
heap->tree = realloc(heap->tree, heap->bufsize * sizeof(*heap->tree));
}
node = heap_pool_elem_alloc(&heap->pool);
node->ptr = ptr;
node->value = value;
node->index = heap->size;
heap->tree[node->index] = node;
heap->size++;
heap_up(heap, node->index);
return node;
}
bool HEAP_is_empty(Heap *heap)
{
return (heap->size == 0);
}
unsigned int HEAP_size(Heap *heap)
{
return heap->size;
}
HeapNode *HEAP_top(Heap *heap)
{
return heap->tree[0];
}
double HEAP_top_value(Heap *heap)
{
return heap->tree[0]->value;
}
void *HEAP_popmin(Heap *heap)
{
void *ptr = heap->tree[0]->ptr;
assert(heap->size != 0);
heap_pool_elem_free(&heap->pool, heap->tree[0]);
if (--heap->size) {
heap_swap(heap, 0, heap->size);
heap_down(heap, 0);
}
return ptr;
}
void HEAP_remove(Heap *heap, HeapNode *node)
{
unsigned int i = node->index;
assert(heap->size != 0);
while (i > 0) {
unsigned int p = HEAP_PARENT(i);
heap_swap(heap, p, i);
i = p;
}
HEAP_popmin(heap);
}
double HEAP_node_value(HeapNode *node)
{
return node->value;
}
void *HEAP_node_ptr(HeapNode *node)
{
return node->ptr;
}

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2016, Blender Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the <organization> nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __GENERIC_HEAP_H__
#define __GENERIC_HEAP_H__
/** \file generic_heap.h
* \ingroup curve_fit
*/
struct Heap;
struct HeapNode;
typedef struct Heap Heap;
typedef struct HeapNode HeapNode;
typedef void (*HeapFreeFP)(void *ptr);
Heap *HEAP_new(unsigned int tot_reserve);
bool HEAP_is_empty(Heap *heap);
void HEAP_free(Heap *heap, HeapFreeFP ptrfreefp);
void *HEAP_node_ptr(HeapNode *node);
void HEAP_remove(Heap *heap, HeapNode *node);
HeapNode *HEAP_insert(Heap *heap, double value, void *ptr);
void *HEAP_popmin(Heap *heap);
void HEAP_clear(Heap *heap, HeapFreeFP ptrfreefp);
unsigned int HEAP_size(Heap *heap);
HeapNode *HEAP_top(Heap *heap);
double HEAP_top_value(Heap *heap);
double HEAP_node_value(HeapNode *node);
#endif /* __GENERIC_HEAP_IMPL_H__ */

View File

@ -81,7 +81,9 @@
# endif
#endif
#ifdef UINTPTR_MAX
#if defined(__SIZEOF_POINTER__)
# define LG_SIZEOF_PTR __SIZEOF_POINTER__
#elif defined(UINTPTR_MAX)
# if (UINTPTR_MAX == 0xFFFFFFFF)
# define LG_SIZEOF_PTR 4
# elif (UINTPTR_MAX == 0xFFFFFFFFFFFFFFFF)

View File

@ -861,7 +861,7 @@ Factory_filter(Factory* self, PyObject *args)
py_a_len= py_a ? PySequence_Size(py_a) : 0;
py_b_len= PySequence_Size(py_b);
if(!py_b_len || ((py_a != NULL) && !py_b_len))
if(!py_b_len || ((py_a != NULL) && !py_a_len))
{
PyErr_SetString(PyExc_ValueError, "The sequence has to contain at least one value!");
return NULL;

View File

@ -505,7 +505,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
)
cls.debug_use_hair_bvh = BoolProperty(
name="Use Hair BVH",
description="Use special type BVH optimized for hair. Uses more ram but renders faster",
description="Use special type BVH optimized for hair (uses more ram but renders faster)",
default=True,
)
cls.tile_order = EnumProperty(

View File

@ -459,7 +459,9 @@ class CyclesRender_PT_layer_passes(CyclesButtonsPanel, Panel):
col.prop(rl, "use_pass_z")
col.prop(rl, "use_pass_mist")
col.prop(rl, "use_pass_normal")
col.prop(rl, "use_pass_vector")
row = col.row()
row.prop(rl, "use_pass_vector")
row.active = not rd.use_motion_blur
col.prop(rl, "use_pass_uv")
col.prop(rl, "use_pass_object_index")
col.prop(rl, "use_pass_material_index")

View File

@ -680,6 +680,43 @@ static void create_subd_mesh(Scene *scene,
/* Sync */
static void sync_mesh_fluid_motion(BL::Object& b_ob, Scene *scene, Mesh *mesh)
{
if(scene->need_motion() == Scene::MOTION_NONE)
return;
BL::DomainFluidSettings b_fluid_domain = object_fluid_domain_find(b_ob);
if(!b_fluid_domain)
return;
/* If the mesh has modifiers following the fluid domain we can't export motion. */
if(b_fluid_domain.fluid_mesh_vertices.length() != mesh->verts.size())
return;
/* Find or add attribute */
float3 *P = &mesh->verts[0];
Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
if(!attr_mP) {
attr_mP = mesh->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION);
}
/* Only export previous and next frame, we don't have any in between data. */
float motion_times[2] = {-1.0f, 1.0f};
for (int step = 0; step < 2; step++) {
float relative_time = motion_times[step] * scene->motion_shutter_time() * 0.5f;
float3 *mP = attr_mP->data_float3() + step*mesh->verts.size();
BL::DomainFluidSettings::fluid_mesh_vertices_iterator fvi;
int i = 0;
for(b_fluid_domain.fluid_mesh_vertices.begin(fvi); fvi != b_fluid_domain.fluid_mesh_vertices.end(); ++fvi, ++i) {
mP[i] = P[i] + get_float3(fvi->velocity()) * relative_time;
}
}
}
Mesh *BlenderSync::sync_mesh(BL::Object& b_ob,
bool object_updated,
bool hide_tris)
@ -821,6 +858,9 @@ Mesh *BlenderSync::sync_mesh(BL::Object& b_ob,
mesh->displacement_method = Mesh::DISPLACE_BOTH;
}
/* fluid motion */
sync_mesh_fluid_motion(b_ob, scene, mesh);
/* tag update */
bool rebuild = false;
@ -910,6 +950,11 @@ void BlenderSync::sync_mesh_motion(BL::Object& b_ob,
* would need a more extensive check to see which objects are animated */
BL::Mesh b_mesh(PointerRNA_NULL);
/* fluid motion is exported immediate with mesh, skip here */
BL::DomainFluidSettings b_fluid_domain = object_fluid_domain_find(b_ob);
if (b_fluid_domain)
return;
if(ccl::BKE_object_is_deform_modified(b_ob, b_scene, preview)) {
/* get derived mesh */
b_mesh = object_to_mesh(b_data, b_ob, b_scene, true, !preview, false);

View File

@ -253,11 +253,10 @@ static bool object_boundbox_clip(Scene *scene,
boundbox[3 * i + 1],
boundbox[3 * i + 2]);
p = transform_point(&tfm, p);
p = transform_point(&worldtondc, p);
p = transform_perspective(&worldtondc, p);
if(p.z >= -margin) {
all_behind = false;
}
p /= p.z;
bb_min = min(bb_min, p);
bb_max = max(bb_max, p);
}
@ -682,12 +681,7 @@ void BlenderSync::sync_motion(BL::RenderSettings& b_render,
<< relative_time << ".";
/* fixed shutter time to get previous and next frame for motion pass */
float shuttertime;
if(scene->need_motion() == Scene::MOTION_PASS)
shuttertime = 2.0f;
else
shuttertime = scene->camera->shuttertime;
float shuttertime = scene->motion_shutter_time();
/* compute frame and subframe time */
float time = frame_center + frame_center_delta + relative_time * shuttertime * 0.5f;

View File

@ -131,7 +131,9 @@ private:
Transform& tfm,
bool *use_portal);
void sync_background_light(bool use_portal);
void sync_mesh_motion(BL::Object& b_ob, Object *object, float motion_time);
void sync_mesh_motion(BL::Object& b_ob,
Object *object,
float motion_time);
void sync_camera_motion(BL::RenderSettings& b_render,
BL::Object& b_ob,
int width, int height,

View File

@ -519,6 +519,23 @@ static inline BL::SmokeDomainSettings object_smoke_domain_find(BL::Object& b_ob)
return BL::SmokeDomainSettings(PointerRNA_NULL);
}
static inline BL::DomainFluidSettings object_fluid_domain_find(BL::Object b_ob)
{
BL::Object::modifiers_iterator b_mod;
for(b_ob.modifiers.begin(b_mod); b_mod != b_ob.modifiers.end(); ++b_mod) {
if(b_mod->is_a(&RNA_FluidSimulationModifier)) {
BL::FluidSimulationModifier b_fmd(*b_mod);
BL::FluidSettings fss = b_fmd.settings();
if(fss.type() == BL::FluidSettings::type_DOMAIN)
return (BL::DomainFluidSettings)b_fmd.settings();
}
}
return BL::DomainFluidSettings(PointerRNA_NULL);
}
/* ID Map
*
* Utility class to keep in sync with blender data.

View File

@ -387,6 +387,12 @@ ccl_device_inline void motion_triangle_intersect_subsurface(
float t, u, v;
if(ray_triangle_intersect_uv(P, dir, tmax, verts[2], verts[0], verts[1], &u, &v, &t)) {
for(int i = min(max_hits, ss_isect->num_hits) - 1; i >= 0; --i) {
if(ss_isect->hits[i].t == t) {
return;
}
}
ss_isect->num_hits++;
int hit;

View File

@ -256,7 +256,7 @@ ccl_device_inline void triangle_intersect_subsurface(
const float inv_det = 1.0f / det;
const float t = T * inv_det;
for(int i = min(max_hits, ss_isect->num_hits); i >= 0; --i) {
for(int i = min(max_hits, ss_isect->num_hits) - 1; i >= 0; --i) {
if(ss_isect->hits[i].t == t) {
return;
}

View File

@ -50,7 +50,7 @@ ccl_device_inline void bsdf_eval_init(BsdfEval *eval, ClosureType type, float3 v
else
eval->diffuse = value;
#else
*eval = value;
eval->diffuse = value;
#endif
}
@ -80,7 +80,7 @@ void bsdf_eval_accum(BsdfEval *eval, ClosureType type, float3 value)
else
eval->diffuse += value;
#else
*eval += value;
eval->diffuse += value;
#endif
}
@ -98,7 +98,7 @@ ccl_device_inline bool bsdf_eval_is_zero(BsdfEval *eval)
else
return is_zero(eval->diffuse);
#else
return is_zero(*eval);
return is_zero(eval->diffuse);
#endif
}
@ -117,7 +117,7 @@ ccl_device_inline void bsdf_eval_mul(BsdfEval *eval, float3 value)
else
eval->diffuse *= value;
#else
*eval *= value;
eval->diffuse *= value;
#endif
}
@ -172,7 +172,7 @@ ccl_device_inline void path_radiance_init(PathRadiance *L, int use_light_pass)
else
L->emission = make_float3(0.0f, 0.0f, 0.0f);
#else
*L = make_float3(0.0f, 0.0f, 0.0f);
L->emission = make_float3(0.0f, 0.0f, 0.0f);
#endif
}
@ -207,7 +207,7 @@ ccl_device_inline void path_radiance_bsdf_bounce(PathRadiance *L, ccl_addr_space
else
*throughput *= bsdf_eval->diffuse*inverse_pdf;
#else
*throughput *= *bsdf_eval*inverse_pdf;
*throughput *= bsdf_eval->diffuse*inverse_pdf;
#endif
}
@ -225,7 +225,7 @@ ccl_device_inline void path_radiance_accum_emission(PathRadiance *L, float3 thro
else
L->emission += throughput*value;
#else
*L += throughput*value;
L->emission += throughput*value;
#endif
}
@ -246,7 +246,7 @@ ccl_device_inline void path_radiance_accum_ao(PathRadiance *L, float3 throughput
else
L->emission += throughput*bsdf*ao;
#else
*L += throughput*bsdf*ao;
L->emission += throughput*bsdf*ao;
#endif
}
@ -277,7 +277,7 @@ ccl_device_inline void path_radiance_accum_light(PathRadiance *L, float3 through
else
L->emission += throughput*bsdf_eval->diffuse*shadow;
#else
*L += throughput*(*bsdf_eval)*shadow;
L->emission += throughput*bsdf_eval->diffuse*shadow;
#endif
}
@ -295,7 +295,7 @@ ccl_device_inline void path_radiance_accum_background(PathRadiance *L, float3 th
else
L->emission += throughput*value;
#else
*L += throughput*value;
L->emission += throughput*value;
#endif
}
@ -441,7 +441,7 @@ ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg, PathRadi
else
L_sum = L->emission;
#else
L_sum = *L;
L_sum = L->emission;
#endif
/* Reject invalid value */
@ -477,7 +477,7 @@ ccl_device_inline void path_radiance_accum_sample(PathRadiance *L, PathRadiance
L->shadow += L_sample->shadow*fac;
L->mist += L_sample->mist*fac;
#else
*L += *L_sample * fac;
L->emission += L_sample->emission * fac;
#endif
}

View File

@ -387,12 +387,13 @@ typedef enum BakePassFilterCombos {
BAKE_FILTER_SUBSURFACE_INDIRECT = (BAKE_FILTER_INDIRECT | BAKE_FILTER_SUBSURFACE),
} BakePassFilterCombos;
#ifdef __PASSES__
typedef ccl_addr_space struct PathRadiance {
#ifdef __PASSES__
int use_light_pass;
#endif
float3 emission;
#ifdef __PASSES__
float3 background;
float3 ao;
@ -426,25 +427,23 @@ typedef ccl_addr_space struct PathRadiance {
float4 shadow;
float mist;
#endif
} PathRadiance;
typedef struct BsdfEval {
#ifdef __PASSES__
int use_light_pass;
#endif
float3 diffuse;
#ifdef __PASSES__
float3 glossy;
float3 transmission;
float3 transparent;
float3 subsurface;
float3 scatter;
} BsdfEval;
#else
typedef ccl_addr_space float3 PathRadiance;
typedef float3 BsdfEval;
#endif
} BsdfEval;
/* Shader Flag */

View File

@ -109,6 +109,7 @@ void KERNEL_FUNCTION_FULL_NAME(shader)(KernelGlobals *kg,
{
if(type >= SHADER_EVAL_BAKE) {
kernel_assert(output_luma == NULL);
#ifdef __BAKING__
kernel_bake_evaluate(kg,
input,
output,
@ -117,6 +118,7 @@ void KERNEL_FUNCTION_FULL_NAME(shader)(KernelGlobals *kg,
i,
offset,
sample);
#endif
}
else {
kernel_shader_evaluate(kg,

View File

@ -22,6 +22,7 @@ set(SRC
bake.cpp
buffers.cpp
camera.cpp
constant_fold.cpp
film.cpp
graph.cpp
image.cpp
@ -49,6 +50,7 @@ set(SRC_HEADERS
background.h
buffers.h
camera.h
constant_fold.h
film.h
graph.h
image.h

View File

@ -0,0 +1,122 @@
/*
* Copyright 2011-2013 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "constant_fold.h"
#include "graph.h"
#include "util_foreach.h"
CCL_NAMESPACE_BEGIN
ConstantFolder::ConstantFolder(ShaderGraph *graph, ShaderNode *node, ShaderOutput *output)
: graph(graph), node(node), output(output)
{
}
bool ConstantFolder::all_inputs_constant() const
{
foreach(ShaderInput *input, node->inputs) {
if(input->link) {
return false;
}
}
return true;
}
void ConstantFolder::make_constant(float value) const
{
foreach(ShaderInput *sock, output->links) {
sock->set(value);
}
graph->disconnect(output);
}
void ConstantFolder::make_constant(float3 value) const
{
foreach(ShaderInput *sock, output->links) {
sock->set(value);
}
graph->disconnect(output);
}
void ConstantFolder::make_constant_clamp(float value, bool clamp) const
{
make_constant(clamp ? saturate(value) : value);
}
void ConstantFolder::make_constant_clamp(float3 value, bool clamp) const
{
if (clamp) {
value.x = saturate(value.x);
value.y = saturate(value.y);
value.z = saturate(value.z);
}
make_constant(value);
}
void ConstantFolder::bypass(ShaderOutput *new_output) const
{
assert(new_output);
/* Remove all outgoing links from socket and connect them to new_output instead.
* The graph->relink method affects node inputs, so it's not safe to use in constant
* folding if the node has multiple outputs and will thus be folded multiple times. */
vector<ShaderInput*> outputs = output->links;
graph->disconnect(output);
foreach(ShaderInput *sock, outputs) {
graph->connect(new_output, sock);
}
}
void ConstantFolder::discard() const
{
assert(output->type() == SocketType::CLOSURE);
graph->disconnect(output);
}
void ConstantFolder::bypass_or_discard(ShaderInput *input) const
{
assert(input->type() == SocketType::CLOSURE);
if (input->link) {
bypass(input->link);
}
else {
discard();
}
}
bool ConstantFolder::try_bypass_or_make_constant(ShaderInput *input, float3 input_value, bool clamp) const
{
if(!input->link) {
make_constant_clamp(input_value, clamp);
return true;
}
else if(!clamp) {
bypass(input->link);
return true;
}
return false;
}
CCL_NAMESPACE_END

View File

@ -0,0 +1,59 @@
/*
* Copyright 2011-2013 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CONSTANT_FOLD_H__
#define __CONSTANT_FOLD_H__
#include "util_types.h"
CCL_NAMESPACE_BEGIN
class ShaderGraph;
class ShaderInput;
class ShaderNode;
class ShaderOutput;
class ConstantFolder {
public:
ShaderGraph *const graph;
ShaderNode *const node;
ShaderOutput *const output;
ConstantFolder(ShaderGraph *graph, ShaderNode *node, ShaderOutput *output);
bool all_inputs_constant() const;
/* Constant folding helpers, always return true for convenience. */
void make_constant(float value) const;
void make_constant(float3 value) const;
void make_constant_clamp(float value, bool clamp) const;
void make_constant_clamp(float3 value, bool clamp) const;
/* Bypass node, relinking to another output socket. */
void bypass(ShaderOutput *output) const;
/* For closure nodes, discard node entirely or bypass to one of its inputs. */
void discard() const;
void bypass_or_discard(ShaderInput *input) const;
/* Bypass or make constant, unless we can't due to clamp being true. */
bool try_bypass_or_make_constant(ShaderInput *input, float3 input_value, bool clamp) const;
};
CCL_NAMESPACE_END
#endif /* __CONSTANT_FOLD_H__ */

View File

@ -1,5 +1,5 @@
/*
* Copyright 2011-2013 Blender Foundation
* Copyright 2011-2016 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,6 +18,7 @@
#include "graph.h"
#include "nodes.h"
#include "shader.h"
#include "constant_fold.h"
#include "util_algorithm.h"
#include "util_debug.h"
@ -126,17 +127,6 @@ ShaderOutput *ShaderNode::output(ustring name)
return NULL;
}
bool ShaderNode::all_inputs_constant() const
{
foreach(ShaderInput *input, inputs) {
if(input->link) {
return false;
}
}
return true;
}
void ShaderNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
foreach(ShaderInput *input, inputs) {
@ -278,6 +268,17 @@ void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to)
}
}
void ShaderGraph::disconnect(ShaderOutput *from)
{
assert(!finalized);
foreach(ShaderInput *sock, from->links) {
sock->link = NULL;
}
from->links.clear();
}
void ShaderGraph::disconnect(ShaderInput *to)
{
assert(!finalized);
@ -373,24 +374,12 @@ void ShaderGraph::copy_nodes(ShaderNodeSet& nodes, ShaderNodeMap& nnodemap)
ShaderNode *nnode = node->clone();
nnodemap[node] = nnode;
/* create new inputs and outputs to recreate links and ensure
* that we still point to valid SocketType if the NodeType
* changed in cloning, as it does for OSL nodes */
nnode->inputs.clear();
nnode->outputs.clear();
foreach(ShaderInput *input, node->inputs) {
ShaderInput *ninput = new ShaderInput(*input);
nnode->inputs.push_back(ninput);
ninput->parent = nnode;
ninput->link = NULL;
}
foreach(ShaderOutput *output, node->outputs) {
ShaderOutput *noutput = new ShaderOutput(*output);
nnode->outputs.push_back(noutput);
noutput->parent = nnode;
noutput->links.clear();
}
nnode->create_inputs_outputs(nnode->type);
}
/* recreate links */
@ -525,15 +514,8 @@ void ShaderGraph::constant_fold()
}
}
/* Optimize current node. */
if(node->constant_fold(this, output, output->links[0])) {
/* Apply optimized value to other connected sockets and disconnect. */
vector<ShaderInput*> links(output->links);
for(size_t i = 0; i < links.size(); i++) {
if(i > 0)
links[i]->parent->copy_value(links[i]->socket_type, *links[0]->parent, links[0]->socket_type);
disconnect(links[i]);
}
}
ConstantFolder folder(this, node, output);
node->constant_fold(folder);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2011-2013 Blender Foundation
* Copyright 2011-2016 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -41,6 +41,7 @@ class ShaderGraph;
class SVMCompiler;
class OSLCompiler;
class OutputNode;
class ConstantFolder;
/* Bump
*
@ -140,9 +141,7 @@ public:
/* ** Node optimization ** */
/* Check whether the node can be replaced with single constant. */
virtual bool constant_fold(ShaderGraph * /*graph*/, ShaderOutput * /*socket*/, ShaderInput * /*optimized*/) { return false; }
bool all_inputs_constant() const;
virtual void constant_fold(const ConstantFolder& /*folder*/) {}
/* Simplify settings used by artists to the ones which are simpler to
* evaluate in the kernel but keep the final result unchanged.
@ -251,6 +250,7 @@ public:
OutputNode *output();
void connect(ShaderOutput *from, ShaderInput *to);
void disconnect(ShaderOutput *from);
void disconnect(ShaderInput *to);
void relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to);

View File

@ -22,6 +22,7 @@
#include "svm_color_util.h"
#include "svm_math_util.h"
#include "osl.h"
#include "constant_fold.h"
#include "util_sky_model.h"
#include "util_foreach.h"
@ -1576,16 +1577,11 @@ RGBToBWNode::RGBToBWNode()
{
}
bool RGBToBWNode::constant_fold(ShaderGraph * /*graph*/,
ShaderOutput * /*socket*/,
ShaderInput *optimized)
void RGBToBWNode::constant_fold(const ConstantFolder& folder)
{
if(all_inputs_constant()) {
optimized->set(linear_rgb_to_gray(color));
return true;
if(folder.all_inputs_constant()) {
folder.make_constant(linear_rgb_to_gray(color));
}
return false;
}
void RGBToBWNode::compile(SVMCompiler& compiler)
@ -1663,40 +1659,35 @@ ConvertNode::ConvertNode(SocketType::Type from_, SocketType::Type to_, bool auto
special_type = SHADER_SPECIAL_TYPE_AUTOCONVERT;
}
bool ConvertNode::constant_fold(ShaderGraph * /*graph*/,
ShaderOutput * /*socket*/,
ShaderInput *optimized)
void ConvertNode::constant_fold(const ConstantFolder& folder)
{
/* proxy nodes should have been removed at this point */
assert(special_type != SHADER_SPECIAL_TYPE_PROXY);
/* TODO(DingTo): conversion from/to int is not supported yet, don't fold in that case */
if(all_inputs_constant()) {
if(folder.all_inputs_constant()) {
if(from == SocketType::FLOAT) {
if(SocketType::is_float3(to)) {
optimized->set(make_float3(value_float, value_float, value_float));
return true;
folder.make_constant(make_float3(value_float, value_float, value_float));
}
}
else if(SocketType::is_float3(from)) {
if(to == SocketType::FLOAT) {
if(from == SocketType::COLOR)
if(from == SocketType::COLOR) {
/* color to float */
optimized->set(linear_rgb_to_gray(value_color));
else
folder.make_constant(linear_rgb_to_gray(value_color));
}
else {
/* vector/point/normal to float */
optimized->set(average(value_vector));
return true;
folder.make_constant(average(value_vector));
}
}
else if(SocketType::is_float3(to)) {
optimized->set(value_color);
return true;
folder.make_constant(value_color);
}
}
}
return false;
}
void ConvertNode::compile(SVMCompiler& compiler)
@ -2366,15 +2357,15 @@ void EmissionNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_emission");
}
bool EmissionNode::constant_fold(ShaderGraph * /*graph*/,
ShaderOutput * /*socket*/,
ShaderInput * /*optimized*/)
void EmissionNode::constant_fold(const ConstantFolder& folder)
{
ShaderInput *color_in = input("Color");
ShaderInput *strength_in = input("Strength");
return ((!color_in->link && color == make_float3(0.0f, 0.0f, 0.0f)) ||
(!strength_in->link && strength == 0.0f));
if ((!color_in->link && color == make_float3(0.0f, 0.0f, 0.0f)) ||
(!strength_in->link && strength == 0.0f)) {
folder.discard();
}
}
/* Background Closure */
@ -2418,15 +2409,15 @@ void BackgroundNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_background");
}
bool BackgroundNode::constant_fold(ShaderGraph * /*graph*/,
ShaderOutput * /*socket*/,
ShaderInput * /*optimized*/)
void BackgroundNode::constant_fold(const ConstantFolder& folder)
{
ShaderInput *color_in = input("Color");
ShaderInput *strength_in = input("Strength");
return ((!color_in->link && color == make_float3(0.0f, 0.0f, 0.0f)) ||
(!strength_in->link && strength == 0.0f));
if ((!color_in->link && color == make_float3(0.0f, 0.0f, 0.0f)) ||
(!strength_in->link && strength == 0.0f)) {
folder.discard();
}
}
/* Holdout Closure */
@ -3388,12 +3379,9 @@ ValueNode::ValueNode()
{
}
bool ValueNode::constant_fold(ShaderGraph * /*graph*/,
ShaderOutput * /*socket*/,
ShaderInput *optimized)
void ValueNode::constant_fold(const ConstantFolder& folder)
{
optimized->set(value);
return true;
folder.make_constant(value);
}
void ValueNode::compile(SVMCompiler& compiler)
@ -3426,12 +3414,9 @@ ColorNode::ColorNode()
{
}
bool ColorNode::constant_fold(ShaderGraph * /*graph*/,
ShaderOutput * /*socket*/,
ShaderInput *optimized)
void ColorNode::constant_fold(const ConstantFolder& folder)
{
optimized->set(value);
return true;
folder.make_constant(value);
}
void ColorNode::compile(SVMCompiler& compiler)
@ -3480,6 +3465,20 @@ void AddClosureNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_add_closure");
}
void AddClosureNode::constant_fold(const ConstantFolder& folder)
{
ShaderInput *closure1_in = input("Closure1");
ShaderInput *closure2_in = input("Closure2");
/* remove useless add closures nodes */
if(!closure1_in->link) {
folder.bypass_or_discard(closure2_in);
}
else if(!closure2_in->link) {
folder.bypass_or_discard(closure1_in);
}
}
/* Mix Closure */
NODE_DEFINE(MixClosureNode)
@ -3511,37 +3510,28 @@ void MixClosureNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_mix_closure");
}
bool MixClosureNode::constant_fold(ShaderGraph *graph,
ShaderOutput * /*socket*/,
ShaderInput * /*optimized*/)
void MixClosureNode::constant_fold(const ConstantFolder& folder)
{
ShaderInput *fac_in = input("Fac");
ShaderInput *closure1_in = input("Closure1");
ShaderInput *closure2_in = input("Closure2");
ShaderOutput *closure_out = output("Closure");
/* remove useless mix closures nodes */
if(closure1_in->link == closure2_in->link) {
graph->relink(this, closure_out, closure1_in->link);
return true;
folder.bypass_or_discard(closure1_in);
}
/* remove unused mix closure input when factor is 0.0 or 1.0 */
/* check for closure links and make sure factor link is disconnected */
if(closure1_in->link && closure2_in->link && !fac_in->link) {
/* remove unused mix closure input when factor is 0.0 or 1.0
* check for closure links and make sure factor link is disconnected */
else if(!fac_in->link) {
/* factor 0.0 */
if(fac == 0.0f) {
graph->relink(this, closure_out, closure1_in->link);
return true;
if(fac <= 0.0f) {
folder.bypass_or_discard(closure1_in);
}
/* factor 1.0 */
else if(fac == 1.0f) {
graph->relink(this, closure_out, closure2_in->link);
return true;
else if(fac >= 1.0f) {
folder.bypass_or_discard(closure2_in);
}
}
return false;
}
/* Mix Closure */
@ -3603,28 +3593,21 @@ InvertNode::InvertNode()
{
}
bool InvertNode::constant_fold(ShaderGraph *graph,
ShaderOutput * /*socket*/,
ShaderInput *optimized)
void InvertNode::constant_fold(const ConstantFolder& folder)
{
ShaderInput *fac_in = input("Fac");
ShaderInput *color_in = input("Color");
ShaderOutput *color_out = output("Color");
if(!fac_in->link) {
/* evaluate fully constant node */
if(!color_in->link) {
optimized->set(interp(color, make_float3(1.0f, 1.0f, 1.0f) - color, fac));
return true;
folder.make_constant(interp(color, make_float3(1.0f, 1.0f, 1.0f) - color, fac));
}
/* remove no-op node */
else if(fac == 0.0f) {
graph->relink(this, color_out, color_in->link);
return true;
folder.bypass(color_in->link);
}
}
return false;
}
void InvertNode::compile(SVMCompiler& compiler)
@ -3713,63 +3696,47 @@ void MixNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_mix");
}
bool MixNode::constant_fold(ShaderGraph *graph,
ShaderOutput * /*socket*/,
ShaderInput *optimized)
void MixNode::constant_fold(const ConstantFolder& folder)
{
ShaderInput *fac_in = input("Fac");
ShaderInput *color1_in = input("Color1");
ShaderInput *color2_in = input("Color2");
ShaderOutput *color_out = output("Color");
/* evaluate fully constant node */
if(all_inputs_constant()) {
float3 result = svm_mix(type, fac, color1, color2);
optimized->set(use_clamp ? svm_mix_clamp(result) : result);
return true;
if(folder.all_inputs_constant()) {
folder.make_constant_clamp(svm_mix(type, fac, color1, color2), use_clamp);
return;
}
/* remove no-op node when factor is 0.0 */
if(!fac_in->link && fac <= 0.0f) {
/* note that some of the modes will clamp out of bounds values even without use_clamp */
if(!color1_in->link) {
float3 result = svm_mix(type, 0.0f, color1, color1);
optimized->set(use_clamp ? svm_mix_clamp(result) : result);
return true;
if(type == NODE_MIX_LIGHT || type == NODE_MIX_DODGE || type == NODE_MIX_BURN) {
if(!color1_in->link) {
folder.make_constant_clamp(svm_mix(type, 0.0f, color1, color1), use_clamp);
return;
}
}
else if(!use_clamp && type != NODE_MIX_LIGHT && type != NODE_MIX_DODGE && type != NODE_MIX_BURN) {
graph->relink(this, color_out, color1_in->link);
return true;
else if(folder.try_bypass_or_make_constant(color1_in, color1, use_clamp)) {
return;
}
}
if(type != NODE_MIX_BLEND) {
return false;
}
/* remove useless mix colors nodes */
if(color1_in->link && color1_in->link == color2_in->link && !use_clamp) {
graph->relink(this, color_out, color1_in->link);
return true;
}
if(!color1_in->link && !color2_in->link && color1 == color2) {
optimized->set(use_clamp ? svm_mix_clamp(color1) : color1);
return true;
}
/* remove no-op mix color node when factor is 1.0 */
if(!fac_in->link && fac >= 1.0f) {
if(!color2_in->link) {
optimized->set(use_clamp ? svm_mix_clamp(color2) : color2);
return true;
if(type == NODE_MIX_BLEND) {
/* remove useless mix colors nodes */
if(color1_in->link ? (color1_in->link == color2_in->link) : (!color2_in->link && color1 == color2)) {
if(folder.try_bypass_or_make_constant(color1_in, color1, use_clamp)) {
return;
}
}
else if(!use_clamp) {
graph->relink(this, color_out, color2_in->link);
return true;
/* remove no-op mix color node when factor is 1.0 */
if(!fac_in->link && fac >= 1.0f) {
if(folder.try_bypass_or_make_constant(color2_in, color2, use_clamp)) {
return;
}
}
}
return false;
}
/* Combine RGB */
@ -3792,16 +3759,11 @@ CombineRGBNode::CombineRGBNode()
{
}
bool CombineRGBNode::constant_fold(ShaderGraph * /*graph*/,
ShaderOutput * /*socket*/,
ShaderInput *optimized)
void CombineRGBNode::constant_fold(const ConstantFolder& folder)
{
if(all_inputs_constant()) {
optimized->set(make_float3(r, g, b));
return true;
if(folder.all_inputs_constant()) {
folder.make_constant(make_float3(r, g, b));
}
return false;
}
void CombineRGBNode::compile(SVMCompiler& compiler)
@ -3849,16 +3811,11 @@ CombineXYZNode::CombineXYZNode()
{
}
bool CombineXYZNode::constant_fold(ShaderGraph * /*graph*/,
ShaderOutput * /*socket*/,
ShaderInput *optimized)
void CombineXYZNode::constant_fold(const ConstantFolder& folder)
{
if(all_inputs_constant()) {
optimized->set(make_float3(x, y, z));
return true;
if(folder.all_inputs_constant()) {
folder.make_constant(make_float3(x, y, z));
}
return false;
}
void CombineXYZNode::compile(SVMCompiler& compiler)
@ -3906,16 +3863,11 @@ CombineHSVNode::CombineHSVNode()
{
}
bool CombineHSVNode::constant_fold(ShaderGraph * /*graph*/,
ShaderOutput * /*socket*/,
ShaderInput *optimized)
void CombineHSVNode::constant_fold(const ConstantFolder& folder)
{
if(all_inputs_constant()) {
optimized->set(hsv_to_rgb(make_float3(h, s, v)));
return true;
if(folder.all_inputs_constant()) {
folder.make_constant(hsv_to_rgb(make_float3(h, s, v)));
}
return false;
}
void CombineHSVNode::compile(SVMCompiler& compiler)
@ -3956,16 +3908,11 @@ GammaNode::GammaNode()
{
}
bool GammaNode::constant_fold(ShaderGraph * /*graph*/,
ShaderOutput * /*socket*/,
ShaderInput *optimized)
void GammaNode::constant_fold(const ConstantFolder& folder)
{
if(all_inputs_constant()) {
optimized->set(svm_math_gamma_color(color, gamma));
return true;
if(folder.all_inputs_constant()) {
folder.make_constant(svm_math_gamma_color(color, gamma));
}
return false;
}
void GammaNode::compile(SVMCompiler& compiler)
@ -4005,16 +3952,11 @@ BrightContrastNode::BrightContrastNode()
{
}
bool BrightContrastNode::constant_fold(ShaderGraph * /*graph*/,
ShaderOutput * /*socket*/,
ShaderInput *optimized)
void BrightContrastNode::constant_fold(const ConstantFolder& folder)
{
if(all_inputs_constant()) {
optimized->set(svm_brightness_contrast(color, bright, contrast));
return true;
if(folder.all_inputs_constant()) {
folder.make_constant(svm_brightness_contrast(color, bright, contrast));
}
return false;
}
void BrightContrastNode::compile(SVMCompiler& compiler)
@ -4057,20 +3999,16 @@ SeparateRGBNode::SeparateRGBNode()
{
}
bool SeparateRGBNode::constant_fold(ShaderGraph * /*graph*/,
ShaderOutput *socket,
ShaderInput *optimized)
void SeparateRGBNode::constant_fold(const ConstantFolder& folder)
{
if(all_inputs_constant()) {
if(folder.all_inputs_constant()) {
for(int channel = 0; channel < 3; channel++) {
if(outputs[channel] == socket) {
optimized->set(color[channel]);
return true;
if(outputs[channel] == folder.output) {
folder.make_constant(color[channel]);
return;
}
}
}
return false;
}
void SeparateRGBNode::compile(SVMCompiler& compiler)
@ -4118,20 +4056,16 @@ SeparateXYZNode::SeparateXYZNode()
{
}
bool SeparateXYZNode::constant_fold(ShaderGraph * /*graph*/,
ShaderOutput *socket,
ShaderInput *optimized)
void SeparateXYZNode::constant_fold(const ConstantFolder& folder)
{
if(all_inputs_constant()) {
if(folder.all_inputs_constant()) {
for(int channel = 0; channel < 3; channel++) {
if(outputs[channel] == socket) {
optimized->set(vector[channel]);
return true;
if(outputs[channel] == folder.output) {
folder.make_constant(vector[channel]);
return;
}
}
}
return false;
}
void SeparateXYZNode::compile(SVMCompiler& compiler)
@ -4179,22 +4113,18 @@ SeparateHSVNode::SeparateHSVNode()
{
}
bool SeparateHSVNode::constant_fold(ShaderGraph * /*graph*/,
ShaderOutput *socket,
ShaderInput *optimized)
void SeparateHSVNode::constant_fold(const ConstantFolder& folder)
{
if(all_inputs_constant()) {
if(folder.all_inputs_constant()) {
float3 hsv = rgb_to_hsv(color);
for(int channel = 0; channel < 3; channel++) {
if(outputs[channel] == socket) {
optimized->set(hsv[channel]);
return true;
if(outputs[channel] == folder.output) {
folder.make_constant(hsv[channel]);
return;
}
}
}
return false;
}
void SeparateHSVNode::compile(SVMCompiler& compiler)
@ -4580,16 +4510,11 @@ BlackbodyNode::BlackbodyNode()
{
}
bool BlackbodyNode::constant_fold(ShaderGraph * /*graph*/,
ShaderOutput * /*socket*/,
ShaderInput *optimized)
void BlackbodyNode::constant_fold(const ConstantFolder& folder)
{
if(all_inputs_constant()) {
optimized->set(svm_math_blackbody_color(temperature));
return true;
if(folder.all_inputs_constant()) {
folder.make_constant(svm_math_blackbody_color(temperature));
}
return false;
}
void BlackbodyNode::compile(SVMCompiler& compiler)
@ -4691,17 +4616,11 @@ MathNode::MathNode()
{
}
bool MathNode::constant_fold(ShaderGraph * /*graph*/,
ShaderOutput * /*socket*/,
ShaderInput *optimized)
void MathNode::constant_fold(const ConstantFolder& folder)
{
if(all_inputs_constant()) {
float value = svm_math(type, value1, value2);
optimized->set(use_clamp ? saturate(value) : value);
return true;
if(folder.all_inputs_constant()) {
folder.make_constant_clamp(svm_math(type, value1, value2), use_clamp);
}
return false;
}
void MathNode::compile(SVMCompiler& compiler)
@ -4755,31 +4674,25 @@ VectorMathNode::VectorMathNode()
{
}
bool VectorMathNode::constant_fold(ShaderGraph * /*graph*/,
ShaderOutput *socket,
ShaderInput *optimized)
void VectorMathNode::constant_fold(const ConstantFolder& folder)
{
float value;
float3 vector;
if(all_inputs_constant()) {
if(folder.all_inputs_constant()) {
svm_vector_math(&value,
&vector,
type,
vector1,
vector2);
if(socket == output("Value")) {
optimized->set(value);
return true;
if(folder.output == output("Value")) {
folder.make_constant(value);
}
else if(socket == output("Vector")) {
optimized->set(vector);
return true;
else if(folder.output == output("Vector")) {
folder.make_constant(vector);
}
}
return false;
}
void VectorMathNode::compile(SVMCompiler& compiler)
@ -4913,9 +4826,7 @@ void BumpNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_bump");
}
bool BumpNode::constant_fold(ShaderGraph *graph,
ShaderOutput * /*socket*/,
ShaderInput * /*optimized*/)
void BumpNode::constant_fold(const ConstantFolder& folder)
{
ShaderInput *height_in = input("Height");
ShaderInput *normal_in = input("Normal");
@ -4923,18 +4834,15 @@ bool BumpNode::constant_fold(ShaderGraph *graph,
if(height_in->link == NULL) {
if(normal_in->link == NULL) {
GeometryNode *geom = new GeometryNode();
graph->add(geom);
graph->relink(this, outputs[0], geom->output("Normal"));
folder.graph->add(geom);
folder.bypass(geom->output("Normal"));
}
else {
graph->relink(this, outputs[0], normal_in->link);
folder.bypass(normal_in->link);
}
return true;
}
/* TODO(sergey): Ignore bump with zero strength. */
return false;
}
@ -5154,12 +5062,10 @@ OSLNode::~OSLNode()
ShaderNode *OSLNode::clone() const
{
OSLNode *node = new OSLNode(*this);
node->type = new NodeType(*type);
return node;
return OSLNode::create(this->inputs.size(), this);
}
OSLNode* OSLNode::create(size_t num_inputs)
OSLNode* OSLNode::create(size_t num_inputs, const OSLNode *from)
{
/* allocate space for the node itself and parameters, aligned to 16 bytes
* assuming that's the most parameter types need */
@ -5169,7 +5075,17 @@ OSLNode* OSLNode::create(size_t num_inputs)
char *node_memory = (char*) operator new(node_size + inputs_size);
memset(node_memory, 0, node_size + inputs_size);
return new(node_memory) OSLNode();
if (!from) {
return new(node_memory) OSLNode();
}
else {
/* copy input default values and node type for cloning */
memcpy(node_memory + node_size, (char*)from + node_size, inputs_size);
OSLNode *node = new(node_memory) OSLNode(*from);
node->type = new NodeType(*(from->type));
return node;
}
}
char* OSLNode::input_default_value()

View File

@ -289,7 +289,7 @@ public:
class RGBToBWNode : public ShaderNode {
public:
SHADER_NODE_CLASS(RGBToBWNode)
bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
void constant_fold(const ConstantFolder& folder);
float3 color;
};
@ -299,7 +299,7 @@ public:
ConvertNode(SocketType::Type from, SocketType::Type to, bool autoconvert = false);
SHADER_NODE_BASE_CLASS(ConvertNode)
bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
void constant_fold(const ConstantFolder& folder);
SocketType::Type from, to;
@ -436,7 +436,7 @@ public:
class EmissionNode : public ShaderNode {
public:
SHADER_NODE_CLASS(EmissionNode)
bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
void constant_fold(const ConstantFolder& folder);
virtual ClosureType get_closure_type() { return CLOSURE_EMISSION_ID; }
bool has_surface_emission() { return true; }
@ -449,7 +449,7 @@ public:
class BackgroundNode : public ShaderNode {
public:
SHADER_NODE_CLASS(BackgroundNode)
bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
void constant_fold(const ConstantFolder& folder);
virtual ClosureType get_closure_type() { return CLOSURE_BACKGROUND_ID; }
float3 color;
@ -605,7 +605,7 @@ class ValueNode : public ShaderNode {
public:
SHADER_NODE_CLASS(ValueNode)
bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
void constant_fold(const ConstantFolder& folder);
float value;
};
@ -614,7 +614,7 @@ class ColorNode : public ShaderNode {
public:
SHADER_NODE_CLASS(ColorNode)
bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
void constant_fold(const ConstantFolder& folder);
float3 value;
};
@ -622,12 +622,13 @@ public:
class AddClosureNode : public ShaderNode {
public:
SHADER_NODE_CLASS(AddClosureNode)
void constant_fold(const ConstantFolder& folder);
};
class MixClosureNode : public ShaderNode {
public:
SHADER_NODE_CLASS(MixClosureNode)
bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
void constant_fold(const ConstantFolder& folder);
float fac;
};
@ -643,7 +644,7 @@ public:
class InvertNode : public ShaderNode {
public:
SHADER_NODE_CLASS(InvertNode)
bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
void constant_fold(const ConstantFolder& folder);
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
float fac;
@ -653,7 +654,7 @@ public:
class MixNode : public ShaderNode {
public:
SHADER_NODE_CLASS(MixNode)
bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
void constant_fold(const ConstantFolder& folder);
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
@ -667,7 +668,7 @@ public:
class CombineRGBNode : public ShaderNode {
public:
SHADER_NODE_CLASS(CombineRGBNode)
bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
void constant_fold(const ConstantFolder& folder);
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
float r, g, b;
@ -676,7 +677,7 @@ public:
class CombineHSVNode : public ShaderNode {
public:
SHADER_NODE_CLASS(CombineHSVNode)
bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
void constant_fold(const ConstantFolder& folder);
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
float h, s, v;
@ -685,7 +686,7 @@ public:
class CombineXYZNode : public ShaderNode {
public:
SHADER_NODE_CLASS(CombineXYZNode)
bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
void constant_fold(const ConstantFolder& folder);
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
float x, y, z;
@ -694,7 +695,7 @@ public:
class GammaNode : public ShaderNode {
public:
SHADER_NODE_CLASS(GammaNode)
bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
void constant_fold(const ConstantFolder& folder);
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
float3 color;
@ -704,7 +705,7 @@ public:
class BrightContrastNode : public ShaderNode {
public:
SHADER_NODE_CLASS(BrightContrastNode)
bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
void constant_fold(const ConstantFolder& folder);
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
float3 color;
@ -715,7 +716,7 @@ public:
class SeparateRGBNode : public ShaderNode {
public:
SHADER_NODE_CLASS(SeparateRGBNode)
bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
void constant_fold(const ConstantFolder& folder);
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
float3 color;
@ -724,7 +725,7 @@ public:
class SeparateHSVNode : public ShaderNode {
public:
SHADER_NODE_CLASS(SeparateHSVNode)
bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
void constant_fold(const ConstantFolder& folder);
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
float3 color;
@ -733,7 +734,7 @@ public:
class SeparateXYZNode : public ShaderNode {
public:
SHADER_NODE_CLASS(SeparateXYZNode)
bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
void constant_fold(const ConstantFolder& folder);
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
float3 vector;
@ -806,7 +807,7 @@ public:
class BlackbodyNode : public ShaderNode {
public:
SHADER_NODE_CLASS(BlackbodyNode)
bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
void constant_fold(const ConstantFolder& folder);
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
float temperature;
@ -816,7 +817,7 @@ class MathNode : public ShaderNode {
public:
SHADER_NODE_CLASS(MathNode)
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
void constant_fold(const ConstantFolder& folder);
float value1;
float value2;
@ -837,7 +838,7 @@ class VectorMathNode : public ShaderNode {
public:
SHADER_NODE_CLASS(VectorMathNode)
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
void constant_fold(const ConstantFolder& folder);
float3 vector1;
float3 vector2;
@ -859,7 +860,7 @@ public:
class BumpNode : public ShaderNode {
public:
SHADER_NODE_CLASS(BumpNode)
bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
void constant_fold(const ConstantFolder& folder);
bool has_spatial_varying() { return true; }
virtual int get_feature() {
return NODE_FEATURE_BUMP;
@ -920,7 +921,7 @@ public:
class OSLNode : public ShaderNode {
public:
static OSLNode *create(size_t num_inputs);
static OSLNode *create(size_t num_inputs, const OSLNode *from = NULL);
~OSLNode();
ShaderNode *clone() const;

View File

@ -263,6 +263,14 @@ Scene::MotionType Scene::need_motion(bool advanced_shading)
return MOTION_NONE;
}
float Scene::motion_shutter_time()
{
if(need_motion() == Scene::MOTION_PASS)
return 2.0f;
else
return camera->shuttertime;
}
bool Scene::need_global_attribute(AttributeStandard std)
{
if(std == ATTR_STD_UV)

View File

@ -213,6 +213,7 @@ public:
enum MotionType { MOTION_NONE = 0, MOTION_PASS, MOTION_BLUR };
MotionType need_motion(bool advanced_shading = true);
float motion_shutter_time();
bool need_update();
bool need_reset();

View File

@ -530,7 +530,7 @@ typedef struct {
#ifdef _WIN32
typedef long GHOST_TEmbedderWindowID;
typedef void* GHOST_TEmbedderWindowID;
#endif // _WIN32
#ifndef _WIN32

View File

@ -707,6 +707,7 @@ int GHOST_ContextWGL::choose_pixel_format(
PIXELFORMATDESCRIPTOR preferredPFD = {
sizeof(PIXELFORMATDESCRIPTOR), /* size */
1, /* version */
(DWORD) (
PFD_SUPPORT_OPENGL |
PFD_DRAW_TO_WINDOW |
PFD_SWAP_COPY | /* support swap copy */
@ -717,16 +718,16 @@ int GHOST_ContextWGL::choose_pixel_format(
needAlpha ? PFD_SUPPORT_COMPOSITION : /* support composition for transparent background */
#endif
0
),
)),
PFD_TYPE_RGBA, /* color type */
(needAlpha ? 32 : 24), /* preferred color depth */
(BYTE) (needAlpha ? 32 : 24), /* preferred color depth */
0, 0, 0, 0, 0, 0, /* color bits (ignored) */
needAlpha ? 8 : 0, /* alpha buffer */
(BYTE) (needAlpha ? 8 : 0), /* alpha buffer */
0, /* alpha shift (ignored) */
0, /* no accumulation buffer */
0, 0, 0, 0, /* accum bits (ignored) */
24, /* depth buffer */
needStencil ? 8 : 0, /* stencil buffer */
(BYTE) (needStencil ? 8 : 0), /* stencil buffer */
0, /* no auxiliary buffers */
PFD_MAIN_PLANE, /* main layer */
0, /* reserved */

View File

@ -64,7 +64,7 @@ bool GHOST_ImeWin32::SetInputLanguage()
* while composing a text.
*/
HKL keyboard_layout = ::GetKeyboardLayout(0);
input_language_id_ = reinterpret_cast<LANGID>(keyboard_layout);
input_language_id_ = LOWORD(keyboard_layout);
ime_status_ = ::ImmIsIME(keyboard_layout);
return ime_status_;
}

View File

@ -95,31 +95,6 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
m_parentWindowHwnd(parentwindowhwnd),
m_debug_context(is_debug)
{
OSVERSIONINFOEX versionInfo;
bool hasMinVersionForTaskbar = false;
ZeroMemory(&versionInfo, sizeof(OSVERSIONINFOEX));
versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
if (!GetVersionEx((OSVERSIONINFO *)&versionInfo)) {
versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (GetVersionEx((OSVERSIONINFO *)&versionInfo)) {
if ((versionInfo.dwMajorVersion == 6 && versionInfo.dwMinorVersion >= 1) ||
(versionInfo.dwMajorVersion >= 7))
{
hasMinVersionForTaskbar = true;
}
}
}
else {
if ((versionInfo.dwMajorVersion == 6 && versionInfo.dwMinorVersion >= 1) ||
(versionInfo.dwMajorVersion >= 7))
{
hasMinVersionForTaskbar = true;
}
}
if (state != GHOST_kWindowStateFullScreen) {
RECT rect;
MONITORINFO monitor;
@ -341,11 +316,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
}
}
}
if (hasMinVersionForTaskbar)
CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList, (LPVOID *)&m_Bar);
else
m_Bar = NULL;
CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (LPVOID *)&m_Bar);
}

View File

@ -67,12 +67,12 @@ int libmv_autoTrackMarker(libmv_AutoTrack* libmv_autotrack,
libmv_apiMarkerToMarker(*libmv_tracked_marker, &tracked_marker);
libmv_configureTrackRegionOptions(*libmv_options,
&options);
(((AutoTrack*) libmv_autotrack)->TrackMarker(&tracked_marker,
&result,
&options));
bool ok = (((AutoTrack*) libmv_autotrack)->TrackMarker(&tracked_marker,
&result,
&options));
libmv_markerToApiMarker(tracked_marker, libmv_tracked_marker);
libmv_regionTrackergetResult(result, libmv_result);
return result.is_usable();
return ok && result.is_usable();
}
void libmv_autoTrackAddMarker(libmv_AutoTrack* libmv_autotrack,

View File

@ -109,7 +109,7 @@ void MeanAndVarianceAlongRows(const Mat &A,
}
void HorizontalStack(const Mat &left, const Mat &right, Mat *stacked) {
assert(left.rows() == left.rows());
assert(left.rows() == right.rows());
int n = left.rows();
int m1 = left.cols();
int m2 = right.cols();

View File

@ -47,6 +47,7 @@ set(SRC
opensubdiv_device_context_cuda.h
opensubdiv_device_context_opencl.h
opensubdiv_intern.h
opensubdiv_topology_refiner.h
)
macro(OPENSUBDIV_DEFINE_COMPONENT component)
@ -69,6 +70,7 @@ add_definitions(-DGLEW_STATIC)
if(WIN32)
add_definitions(-DNOMINMAX)
add_definitions(-D_USE_MATH_DEFINES)
endif()
# TODO(sergey): Put CUEW back when CUDA is officially supported by OSD.

View File

@ -99,6 +99,7 @@ in block {
}
uniform samplerBuffer FVarDataBuffer;
uniform isamplerBuffer FVarDataOffsetBuffer;
out block {
VertexData v;
@ -208,6 +209,7 @@ struct LightSource {
float spotCutoff;
float spotExponent;
float spotCosCutoff;
float pad, pad2;
#endif
};

View File

@ -67,8 +67,10 @@
#include <opensubdiv/osd/glPatchTable.h>
#include <opensubdiv/far/stencilTable.h>
#include <opensubdiv/far/primvarRefiner.h>
#include "opensubdiv_intern.h"
#include "opensubdiv_topology_refiner.h"
#include "MEM_guardedalloc.h"
@ -142,11 +144,73 @@ typedef Mesh<GLVertexBuffer,
GLPatchTable> OsdGLSLComputeMesh;
#endif
namespace {
struct FVarVertex {
float u, v;
void Clear() {
u = v = 0.0f;
}
void AddWithWeight(FVarVertex const & src, float weight) {
u += weight * src.u;
v += weight * src.v;
}
};
static void interpolate_fvar_data(OpenSubdiv::Far::TopologyRefiner& refiner,
const std::vector<float> uvs,
std::vector<float> &fvar_data) {
/* TODO(sergey): Make it somehow more generic way. */
const int fvar_width = 2;
const int max_level = refiner.GetMaxLevel();
size_t fvar_data_offset = 0, values_offset = 0;
for (int channel = 0; channel < refiner.GetNumFVarChannels(); ++channel) {
const int num_values = refiner.GetLevel(0).GetNumFVarValues(0) * 2,
num_values_max = refiner.GetLevel(max_level).GetNumFVarValues(channel),
num_values_total = refiner.GetNumFVarValuesTotal(channel);
if (num_values_total <= 0) {
continue;
}
OpenSubdiv::Far::PrimvarRefiner primvar_refiner(refiner);
if (refiner.IsUniform()) {
/* For uniform we only keep the highest level of refinement. */
fvar_data.resize(fvar_data.size() + num_values_max * fvar_width);
std::vector<FVarVertex> buffer(num_values_total - num_values_max);
FVarVertex *src = &buffer[0];
memcpy(src, &uvs[values_offset], num_values * sizeof(float));
/* Defer the last level to treat separately with its alternate
* destination.
*/
for (int level = 1; level < max_level; ++level) {
FVarVertex *dst = src + refiner.GetLevel(level-1).GetNumFVarValues(channel);
primvar_refiner.InterpolateFaceVarying(level, src, dst, channel);
src = dst;
}
FVarVertex *dst = reinterpret_cast<FVarVertex *>(&fvar_data[fvar_data_offset]);
primvar_refiner.InterpolateFaceVarying(max_level, src, dst, channel);
fvar_data_offset += num_values_max * fvar_width;
} else {
/* For adaptive we keep all levels. */
fvar_data.resize(fvar_data.size() + num_values_total * fvar_width);
FVarVertex *src = reinterpret_cast<FVarVertex *>(&fvar_data[fvar_data_offset]);
memcpy(src, &uvs[values_offset], num_values * sizeof(float));
for (int level = 1; level <= max_level; ++level) {
FVarVertex *dst = src + refiner.GetLevel(level-1).GetNumFVarValues(channel);
primvar_refiner.InterpolateFaceVarying(level, src, dst, channel);
src = dst;
}
fvar_data_offset += num_values_total * fvar_width;
}
values_offset += num_values;
}
}
} // namespace
struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
OpenSubdiv_TopologyRefinerDescr *topology_refiner,
int evaluator_type,
int level,
int /*subdivide_uvs*/)
int level)
{
using OpenSubdiv::Far::TopologyRefiner;
@ -164,7 +228,7 @@ struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
const int num_varying_elements = 3;
GLMeshInterface *mesh = NULL;
TopologyRefiner *refiner = (TopologyRefiner*)topology_refiner;
TopologyRefiner *refiner = topology_refiner->osd_refiner;
switch(evaluator_type) {
#define CHECK_EVALUATOR_TYPE(type, class) \
@ -210,13 +274,23 @@ struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
(OpenSubdiv_GLMesh *) OBJECT_GUARDED_NEW(OpenSubdiv_GLMesh);
gl_mesh->evaluator_type = evaluator_type;
gl_mesh->descriptor = (OpenSubdiv_GLMeshDescr *) mesh;
gl_mesh->topology_refiner = (OpenSubdiv_TopologyRefinerDescr*)refiner;
gl_mesh->topology_refiner = topology_refiner;
if (refiner->GetNumFVarChannels() > 0) {
std::vector<float> fvar_data;
interpolate_fvar_data(*refiner, topology_refiner->uvs, fvar_data);
openSubdiv_osdGLAllocFVar(topology_refiner, gl_mesh, &fvar_data[0]);
}
else {
gl_mesh->fvar_data = NULL;
}
return gl_mesh;
}
void openSubdiv_deleteOsdGLMesh(struct OpenSubdiv_GLMesh *gl_mesh)
{
openSubdiv_osdGLDestroyFVar(gl_mesh);
switch (gl_mesh->evaluator_type) {
#define CHECK_EVALUATOR_TYPE(type, class) \
case OPENSUBDIV_EVALUATOR_ ## type: \
@ -249,6 +323,8 @@ void openSubdiv_deleteOsdGLMesh(struct OpenSubdiv_GLMesh *gl_mesh)
#undef CHECK_EVALUATOR_TYPE
}
/* NOTE: OSD refiner was owned by gl_mesh, no need to free it here. */
OBJECT_GUARDED_DELETE(gl_mesh->topology_refiner, OpenSubdiv_TopologyRefinerDescr);
OBJECT_GUARDED_DELETE(gl_mesh, OpenSubdiv_GLMesh);
}
@ -299,6 +375,9 @@ int openSubdiv_supportGPUDisplay(void)
return openSubdiv_gpu_legacy_support() &&
(GLEW_VERSION_3_2 ||
(GLEW_VERSION_3_1 && GLEW_EXT_geometry_shader4) ||
(GLEW_VERSION_3_0 && GLEW_EXT_geometry_shader4 && GLEW_ARB_uniform_buffer_object && (GLEW_ARB_texture_buffer_object || GLEW_EXT_texture_buffer_object)));
(GLEW_VERSION_3_0 &&
GLEW_EXT_geometry_shader4 &&
GLEW_ARB_uniform_buffer_object &&
(GLEW_ARB_texture_buffer_object || GLEW_EXT_texture_buffer_object)));
/* also ARB_explicit_attrib_location? */
}

View File

@ -32,16 +32,19 @@ extern "C" {
// Types declaration.
struct OpenSubdiv_GLMesh;
struct OpenSubdiv_GLMeshFVarData;
struct OpenSubdiv_TopologyRefinerDescr;
typedef struct OpenSubdiv_GLMesh OpenSubdiv_GLMesh;
#ifdef __cplusplus
struct OpenSubdiv_GLMeshDescr;
typedef struct OpenSubdiv_GLMesh {
int evaluator_type;
OpenSubdiv_GLMeshDescr *descriptor;
OpenSubdiv_TopologyRefinerDescr *topology_refiner;
OpenSubdiv_GLMeshFVarData *fvar_data;
} OpenSubdiv_GLMesh;
#endif
@ -66,8 +69,7 @@ enum {
OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
struct OpenSubdiv_TopologyRefinerDescr *topology_refiner,
int evaluator_type,
int level,
int subdivide_uvs);
int level);
void openSubdiv_deleteOsdGLMesh(OpenSubdiv_GLMesh *gl_mesh);
unsigned int openSubdiv_getOsdGLMeshPatchIndexBuffer(
@ -138,6 +140,11 @@ void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
int start_patch,
int num_patches);
void openSubdiv_osdGLAllocFVar(struct OpenSubdiv_TopologyRefinerDescr *topology_refiner,
OpenSubdiv_GLMesh *gl_mesh,
const float *fvar_data);
void openSubdiv_osdGLDestroyFVar(OpenSubdiv_GLMesh *gl_mesh);
/* ** Utility functions ** */
int openSubdiv_supportGPUDisplay(void);
int openSubdiv_getAvailableEvaluators(void);

View File

@ -32,8 +32,12 @@
#include <opensubdiv/far/topologyRefinerFactory.h>
#include "MEM_guardedalloc.h"
#include "opensubdiv_converter_capi.h"
#include "opensubdiv_intern.h"
#include "opensubdiv_topology_refiner.h"
#include <stack>
@ -49,6 +53,11 @@ inline void reverse_face_verts(int *face_verts, int num_verts)
face_verts[0] = last_vert;
}
struct TopologyRefinerData {
const OpenSubdiv_Converter& conv;
std::vector<float> *uvs;
};
} /* namespace */
#endif /* OPENSUBDIV_ORIENT_TOPOLOGY */
@ -137,10 +146,11 @@ inline void check_oriented_vert_connectivity(const int num_vert_edges,
} /* namespace */
template <>
inline bool TopologyRefinerFactory<OpenSubdiv_Converter>::resizeComponentTopology(
inline bool TopologyRefinerFactory<TopologyRefinerData>::resizeComponentTopology(
TopologyRefiner& refiner,
const OpenSubdiv_Converter& conv)
const TopologyRefinerData& cb_data)
{
const OpenSubdiv_Converter& conv = cb_data.conv;
/* Faces and face-verts */
const int num_faces = conv.get_num_faces(&conv);
setNumBaseFaces(refiner, num_faces);
@ -168,10 +178,11 @@ inline bool TopologyRefinerFactory<OpenSubdiv_Converter>::resizeComponentTopolog
}
template <>
inline bool TopologyRefinerFactory<OpenSubdiv_Converter>::assignComponentTopology(
inline bool TopologyRefinerFactory<TopologyRefinerData>::assignComponentTopology(
TopologyRefiner& refiner,
const OpenSubdiv_Converter& conv)
const TopologyRefinerData &cb_data)
{
const OpenSubdiv_Converter& conv = cb_data.conv;
using Far::IndexArray;
/* Face relations. */
const int num_faces = conv.get_num_faces(&conv);
@ -426,10 +437,11 @@ inline bool TopologyRefinerFactory<OpenSubdiv_Converter>::assignComponentTopolog
};
template <>
inline bool TopologyRefinerFactory<OpenSubdiv_Converter>::assignComponentTags(
inline bool TopologyRefinerFactory<TopologyRefinerData>::assignComponentTags(
TopologyRefiner& refiner,
const OpenSubdiv_Converter& conv)
const TopologyRefinerData& cb_data)
{
const OpenSubdiv_Converter& conv = cb_data.conv;
typedef OpenSubdiv::Sdc::Crease Crease;
int num_edges = conv.get_num_edges(&conv);
@ -476,14 +488,52 @@ inline bool TopologyRefinerFactory<OpenSubdiv_Converter>::assignComponentTags(
}
template <>
inline void TopologyRefinerFactory<OpenSubdiv_Converter>::reportInvalidTopology(
inline void TopologyRefinerFactory<TopologyRefinerData>::reportInvalidTopology(
TopologyError /*errCode*/,
const char *msg,
const OpenSubdiv_Converter& /*mesh*/)
const TopologyRefinerData& /*mesh*/)
{
printf("OpenSubdiv Error: %s\n", msg);
}
template <>
inline bool TopologyRefinerFactory<TopologyRefinerData>::assignFaceVaryingTopology(
TopologyRefiner& refiner,
const TopologyRefinerData& cb_data)
{
const OpenSubdiv_Converter& conv = cb_data.conv;
const int num_layers = conv.get_num_uv_layers(&conv);
if (num_layers <= 0) {
/* No UV maps, we can skip any face-varying data. */
return true;
}
const int num_faces = getNumBaseFaces(refiner);
size_t uvs_offset = 0;
for (int layer = 0; layer < num_layers; ++layer) {
conv.precalc_uv_layer(&conv, layer);
const int num_uvs = conv.get_num_uvs(&conv);
/* Fill in UV coordinates. */
cb_data.uvs->resize(cb_data.uvs->size() + num_uvs * 2);
conv.get_uvs(&conv, &cb_data.uvs->at(uvs_offset));
uvs_offset += num_uvs * 2;
/* Fill in per-corner index of the UV. */
const int channel = createBaseFVarChannel(refiner, num_uvs);
for (int face = 0; face < num_faces; ++face) {
Far::IndexArray dst_face_uvs = getBaseFaceFVarValues(refiner,
face,
channel);
for (int corner = 0; corner < dst_face_uvs.size(); ++corner) {
const int uv_index = conv.get_face_corner_uv_index(&conv,
face,
corner);
dst_face_uvs[corner] = uv_index;
}
}
conv.finish_uv_layer(&conv);
}
return true;
}
} /* namespace Far */
} /* namespace OPENSUBDIV_VERSION */
} /* namespace OpenSubdiv */
@ -517,33 +567,43 @@ struct OpenSubdiv_TopologyRefinerDescr *openSubdiv_createTopologyRefinerDescr(
Options options;
options.SetVtxBoundaryInterpolation(Options::VTX_BOUNDARY_EDGE_ONLY);
options.SetCreasingMethod(Options::CREASE_UNIFORM);
options.SetFVarLinearInterpolation(Options::FVAR_LINEAR_ALL);
if (converter->get_subdiv_uvs(converter)) {
options.SetFVarLinearInterpolation(Options::FVAR_LINEAR_CORNERS_ONLY);
}
else {
options.SetFVarLinearInterpolation(Options::FVAR_LINEAR_ALL);
}
TopologyRefinerFactory<OpenSubdiv_Converter>::Options
TopologyRefinerFactory<TopologyRefinerData>::Options
topology_options(scheme_type, options);
#ifdef OPENSUBDIV_VALIDATE_TOPOLOGY
topology_options.validateFullTopology = true;
#endif
OpenSubdiv_TopologyRefinerDescr *result = OBJECT_GUARDED_NEW(OpenSubdiv_TopologyRefinerDescr);
TopologyRefinerData cb_data = {*converter, &result->uvs};
/* We don't use guarded allocation here so we can re-use the refiner
* for GL mesh creation directly.
*/
return (struct OpenSubdiv_TopologyRefinerDescr*)
TopologyRefinerFactory<OpenSubdiv_Converter>::Create(
*converter,
result->osd_refiner =
TopologyRefinerFactory<TopologyRefinerData>::Create(
cb_data,
topology_options);
return result;
}
void openSubdiv_deleteTopologyRefinerDescr(
OpenSubdiv_TopologyRefinerDescr *topology_refiner)
{
delete (OpenSubdiv::Far::TopologyRefiner *)topology_refiner;
delete topology_refiner->osd_refiner;
OBJECT_GUARDED_DELETE(topology_refiner, OpenSubdiv_TopologyRefinerDescr);
}
int openSubdiv_topologyRefinerGetSubdivLevel(
const OpenSubdiv_TopologyRefinerDescr *topology_refiner)
{
using OpenSubdiv::Far::TopologyRefiner;
const TopologyRefiner *refiner = (const TopologyRefiner *)topology_refiner;
const TopologyRefiner *refiner = topology_refiner->osd_refiner;
return refiner->GetMaxLevel();
}
@ -552,7 +612,7 @@ int openSubdiv_topologyRefinerGetNumVerts(
{
using OpenSubdiv::Far::TopologyLevel;
using OpenSubdiv::Far::TopologyRefiner;
const TopologyRefiner *refiner = (const TopologyRefiner *)topology_refiner;
const TopologyRefiner *refiner = topology_refiner->osd_refiner;
const TopologyLevel &base_level = refiner->GetLevel(0);
return base_level.GetNumVertices();
}
@ -562,7 +622,7 @@ int openSubdiv_topologyRefinerGetNumEdges(
{
using OpenSubdiv::Far::TopologyLevel;
using OpenSubdiv::Far::TopologyRefiner;
const TopologyRefiner *refiner = (const TopologyRefiner *)topology_refiner;
const TopologyRefiner *refiner = topology_refiner->osd_refiner;
const TopologyLevel &base_level = refiner->GetLevel(0);
return base_level.GetNumEdges();
}
@ -572,7 +632,7 @@ int openSubdiv_topologyRefinerGetNumFaces(
{
using OpenSubdiv::Far::TopologyLevel;
using OpenSubdiv::Far::TopologyRefiner;
const TopologyRefiner *refiner = (const TopologyRefiner *)topology_refiner;
const TopologyRefiner *refiner = topology_refiner->osd_refiner;
const TopologyLevel &base_level = refiner->GetLevel(0);
return base_level.GetNumFaces();
}
@ -583,7 +643,7 @@ int openSubdiv_topologyRefinerGetNumFaceVerts(
{
using OpenSubdiv::Far::TopologyLevel;
using OpenSubdiv::Far::TopologyRefiner;
const TopologyRefiner *refiner = (const TopologyRefiner *)topology_refiner;
const TopologyRefiner *refiner = topology_refiner->osd_refiner;
const TopologyLevel &base_level = refiner->GetLevel(0);
return base_level.GetFaceVertices(face).size();
}
@ -592,10 +652,11 @@ int openSubdiv_topologyRefnerCompareConverter(
const OpenSubdiv_TopologyRefinerDescr *topology_refiner,
OpenSubdiv_Converter *converter)
{
typedef OpenSubdiv::Sdc::Options Options;
using OpenSubdiv::Far::ConstIndexArray;
using OpenSubdiv::Far::TopologyRefiner;
using OpenSubdiv::Far::TopologyLevel;
const TopologyRefiner *refiner = (const TopologyRefiner *)topology_refiner;
const TopologyRefiner *refiner = topology_refiner->osd_refiner;
const TopologyLevel &base_level = refiner->GetLevel(0);
const int num_verts = base_level.GetNumVertices();
const int num_edges = base_level.GetNumEdges();
@ -606,6 +667,12 @@ int openSubdiv_topologyRefnerCompareConverter(
if (scheme_type != refiner->GetSchemeType()) {
return false;
}
const Options options = refiner->GetSchemeOptions();
Options::FVarLinearInterpolation interp = options.GetFVarLinearInterpolation();
const bool subdiv_uvs = (interp != Options::FVAR_LINEAR_ALL);
if (converter->get_subdiv_uvs(converter) != subdiv_uvs) {
return false;
}
if (converter->get_num_verts(converter) != num_verts ||
converter->get_num_edges(converter) != num_edges ||
converter->get_num_faces(converter) != num_faces)

View File

@ -47,6 +47,8 @@ typedef struct OpenSubdiv_Converter {
OpenSubdiv_SchemeType (*get_type)(const OpenSubdiv_Converter *converter);
bool (*get_subdiv_uvs)(const OpenSubdiv_Converter *converter);
int (*get_num_faces)(const OpenSubdiv_Converter *converter);
int (*get_num_edges)(const OpenSubdiv_Converter *converter);
int (*get_num_verts)(const OpenSubdiv_Converter *converter);
@ -83,6 +85,20 @@ typedef struct OpenSubdiv_Converter {
int vert,
int *vert_faces);
/* Face-varying data. */
int (*get_num_uv_layers)(const OpenSubdiv_Converter *converter);
void (*precalc_uv_layer)(const OpenSubdiv_Converter *converter, int layer);
void (*finish_uv_layer)(const OpenSubdiv_Converter *converter);
int (*get_num_uvs)(const OpenSubdiv_Converter *converter);
void (*get_uvs)(const OpenSubdiv_Converter *converter, float *uvs);
int (*get_face_corner_uv_index)(const OpenSubdiv_Converter *converter,
int face,
int corner);
void (*free_user_data)(const OpenSubdiv_Converter *converter);
void *user_data;
} OpenSubdiv_Converter;

View File

@ -42,11 +42,29 @@
#include <opensubdiv/osd/cpuGLVertexBuffer.h>
#include <opensubdiv/osd/cpuEvaluator.h>
#include "MEM_guardedalloc.h"
#include "opensubdiv_capi.h"
#include "opensubdiv_topology_refiner.h"
using OpenSubdiv::Osd::GLMeshInterface;
extern "C" char datatoc_gpu_shader_opensubd_display_glsl[];
/* TODO(sergey): This is bit of bad level calls :S */
extern "C" {
void copy_m3_m3(float m1[3][3], float m2[3][3]);
void copy_m3_m4(float m1[3][3], float m2[4][4]);
void adjoint_m3_m3(float m1[3][3], float m[3][3]);
float determinant_m3_array(float m[3][3]);
bool invert_m3_m3(float m1[3][3], float m2[3][3]);
bool invert_m3(float m[3][3]);
void transpose_m3(float mat[3][3]);
}
#define MAX_LIGHTS 8
#define SUPPORT_COLOR_MATERIAL
typedef struct Light {
float position[4];
float ambient[4];
@ -60,6 +78,7 @@ typedef struct Light {
float spot_cutoff;
float spot_exponent;
float spot_cos_cutoff;
float pad, pad2;
#endif
} Light;
@ -75,7 +94,7 @@ typedef struct Transform {
} Transform;
static bool g_use_osd_glsl = false;
static int g_active_uv_index = -1;
static int g_active_uv_index = 0;
static GLuint g_flat_fill_solid_program = 0;
static GLuint g_flat_fill_texture2d_program = 0;
@ -87,102 +106,98 @@ static GLuint g_lighting_ub = 0;
static Lighting g_lighting_data;
static Transform g_transform;
/* TODO(sergey): This is actually duplicated code from BLI. */
namespace {
void copy_m3_m3(float m1[3][3], float m2[3][3])
struct OpenSubdiv_GLMeshFVarData
{
/* destination comes first: */
memcpy(&m1[0], &m2[0], 9 * sizeof(float));
}
void copy_m3_m4(float m1[3][3], float m2[4][4])
{
m1[0][0] = m2[0][0];
m1[0][1] = m2[0][1];
m1[0][2] = m2[0][2];
m1[1][0] = m2[1][0];
m1[1][1] = m2[1][1];
m1[1][2] = m2[1][2];
m1[2][0] = m2[2][0];
m1[2][1] = m2[2][1];
m1[2][2] = m2[2][2];
}
void adjoint_m3_m3(float m1[3][3], float m[3][3])
{
m1[0][0] = m[1][1] * m[2][2] - m[1][2] * m[2][1];
m1[0][1] = -m[0][1] * m[2][2] + m[0][2] * m[2][1];
m1[0][2] = m[0][1] * m[1][2] - m[0][2] * m[1][1];
m1[1][0] = -m[1][0] * m[2][2] + m[1][2] * m[2][0];
m1[1][1] = m[0][0] * m[2][2] - m[0][2] * m[2][0];
m1[1][2] = -m[0][0] * m[1][2] + m[0][2] * m[1][0];
m1[2][0] = m[1][0] * m[2][1] - m[1][1] * m[2][0];
m1[2][1] = -m[0][0] * m[2][1] + m[0][1] * m[2][0];
m1[2][2] = m[0][0] * m[1][1] - m[0][1] * m[1][0];
}
float determinant_m3_array(float m[3][3])
{
return (m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) -
m[1][0] * (m[0][1] * m[2][2] - m[0][2] * m[2][1]) +
m[2][0] * (m[0][1] * m[1][2] - m[0][2] * m[1][1]));
}
bool invert_m3_m3(float m1[3][3], float m2[3][3])
{
float det;
int a, b;
bool success;
/* calc adjoint */
adjoint_m3_m3(m1, m2);
/* then determinant old matrix! */
det = determinant_m3_array(m2);
success = (det != 0.0f);
if (det != 0.0f) {
det = 1.0f / det;
for (a = 0; a < 3; a++) {
for (b = 0; b < 3; b++) {
m1[a][b] *= det;
}
}
OpenSubdiv_GLMeshFVarData() :
texture_buffer(0) {
}
return success;
}
~OpenSubdiv_GLMeshFVarData()
{
Release();
}
bool invert_m3(float m[3][3])
{
float tmp[3][3];
bool success;
void Release()
{
if (texture_buffer) {
glDeleteTextures(1, &texture_buffer);
}
if (offset_buffer) {
glDeleteTextures(1, &offset_buffer);
}
texture_buffer = 0;
offset_buffer = 0;
fvar_width = 0;
channel_offsets.clear();
}
success = invert_m3_m3(tmp, m);
copy_m3_m3(m, tmp);
void Create(const OpenSubdiv::Far::TopologyRefiner *refiner,
const OpenSubdiv::Far::PatchTable *patch_table,
int fvar_width,
const float *fvar_src_data)
{
Release();
return success;
}
this->fvar_width = fvar_width;
void transpose_m3(float mat[3][3])
{
float t;
/* Expand fvar data to per-patch array */
const int max_level = refiner->GetMaxLevel();
const int num_channels = patch_table->GetNumFVarChannels();
std::vector<float> data;
int fvar_data_offset = 0;
channel_offsets.resize(num_channels);
for (int channel = 0; channel < num_channels; ++channel) {
OpenSubdiv::Far::ConstIndexArray indices =
patch_table->GetFVarValues(channel);
t = mat[0][1];
mat[0][1] = mat[1][0];
mat[1][0] = t;
t = mat[0][2];
mat[0][2] = mat[2][0];
mat[2][0] = t;
t = mat[1][2];
mat[1][2] = mat[2][1];
mat[2][1] = t;
}
channel_offsets[channel] = data.size();
data.reserve(data.size() + indices.size() * fvar_width);
for (int fvert = 0; fvert < (int)indices.size(); ++fvert) {
int index = indices[fvert] * fvar_width;
for (int i = 0; i < fvar_width; ++i) {
data.push_back(fvar_src_data[fvar_data_offset + index++]);
}
}
if (refiner->IsUniform()) {
const int num_values_max = refiner->GetLevel(max_level).GetNumFVarValues(channel);
fvar_data_offset += num_values_max * fvar_width;
} else {
const int num_values_total = refiner->GetNumFVarValuesTotal(channel);
fvar_data_offset += num_values_total * fvar_width;
}
}
GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, data.size()*sizeof(float),
&data[0], GL_STATIC_DRAW);
glGenTextures(1, &texture_buffer);
glBindTexture(GL_TEXTURE_BUFFER, texture_buffer);
glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, buffer);
glDeleteBuffers(1, &buffer);
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, channel_offsets.size()*sizeof(int),
&channel_offsets[0], GL_STATIC_DRAW);
glGenTextures(1, &offset_buffer);
glBindTexture(GL_TEXTURE_BUFFER, offset_buffer);
glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, buffer);
glBindTexture(GL_TEXTURE_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
GLuint texture_buffer;
GLuint offset_buffer;
std::vector<int> channel_offsets;
int fvar_width;
};
namespace {
GLuint compileShader(GLenum shaderType,
const char *section,
@ -196,11 +211,14 @@ GLuint compileShader(GLenum shaderType,
version,
define,
sdefine,
#ifdef SUPPORT_COLOR_MATERIAL
"#define SUPPORT_COLOR_MATERIAL\n",
#endif
datatoc_gpu_shader_opensubd_display_glsl
};
GLuint shader = glCreateShader(shaderType);
glShaderSource(shader, 4, sources, NULL);
glShaderSource(shader, 5, sources, NULL);
glCompileShader(shader);
GLint status;
@ -294,6 +312,10 @@ GLuint linkProgram(const char *version, const char *define)
glGetUniformLocation(program, "texture_buffer"),
0); /* GL_TEXTURE0 */
glProgramUniform1i(program,
glGetUniformLocation(program, "FVarDataOffsetBuffer"),
30); /* GL_TEXTURE30 */
glProgramUniform1i(program,
glGetUniformLocation(program, "FVarDataBuffer"),
31); /* GL_TEXTURE31 */
@ -301,8 +323,7 @@ GLuint linkProgram(const char *version, const char *define)
return program;
}
void bindProgram(GLMeshInterface * /*mesh*/,
int program)
void bindProgram(OpenSubdiv_GLMesh *gl_mesh, int program)
{
glUseProgram(program);
@ -346,23 +367,34 @@ void bindProgram(GLMeshInterface * /*mesh*/,
glUniform4fv(glGetUniformLocation(program, "diffuse"), 1, color);
}
/* TODO(sergey): Bring face varying back. */
#if 0
/* Face-vertex data */
if (mesh->GetDrawContext()->GetFvarDataTextureBuffer()) {
glActiveTexture(GL_TEXTURE31);
glBindTexture(GL_TEXTURE_BUFFER,
mesh->GetDrawContext()->GetFvarDataTextureBuffer());
glActiveTexture(GL_TEXTURE0);
if (gl_mesh->fvar_data != NULL) {
if (gl_mesh->fvar_data->texture_buffer) {
glActiveTexture(GL_TEXTURE31);
glBindTexture(GL_TEXTURE_BUFFER, gl_mesh->fvar_data->texture_buffer);
glActiveTexture(GL_TEXTURE0);
}
if (gl_mesh->fvar_data->offset_buffer) {
glActiveTexture(GL_TEXTURE30);
glBindTexture(GL_TEXTURE_BUFFER, gl_mesh->fvar_data->offset_buffer);
glActiveTexture(GL_TEXTURE0);
}
glUniform1i(glGetUniformLocation(program, "osd_fvar_count"),
gl_mesh->fvar_data->fvar_width);
if (gl_mesh->fvar_data->channel_offsets.size() > 0 &&
g_active_uv_index >= 0)
{
glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"),
gl_mesh->fvar_data->channel_offsets[g_active_uv_index]);
} else {
glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"), 0);
}
} else {
glUniform1i(glGetUniformLocation(program, "osd_fvar_count"), 0);
glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"), 0);
}
#endif
/* TODO(sergey): Bring face varying back. */
glUniform1i(glGetUniformLocation(program, "osd_fvar_count"),
0/* * mesh->GetFVarCount()*/);
glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"),
g_active_uv_index * 2);
}
} /* namespace */
@ -390,11 +422,27 @@ bool openSubdiv_osdGLDisplayInit(void)
/* minimum supported for OpenSubdiv */
}
g_flat_fill_solid_program = linkProgram(version, "#define FLAT_SHADING\n");
g_flat_fill_texture2d_program = linkProgram(version, "#define USE_TEXTURE_2D\n#define FLAT_SHADING\n");
g_smooth_fill_solid_program = linkProgram(version, "#define SMOOTH_SHADING\n");
g_smooth_fill_texture2d_program = linkProgram(version, "#define USE_TEXTURE_2D\n#define SMOOTH_SHADING\n");
g_wireframe_program = linkProgram(version, "#define WIREFRAME\n");
g_flat_fill_solid_program = linkProgram(
version,
"#define USE_COLOR_MATERIAL\n"
"#define FLAT_SHADING\n");
g_flat_fill_texture2d_program = linkProgram(
version,
"#define USE_COLOR_MATERIAL\n"
"#define USE_TEXTURE_2D\n"
"#define FLAT_SHADING\n");
g_smooth_fill_solid_program = linkProgram(
version,
"#define USE_COLOR_MATERIAL\n"
"#define SMOOTH_SHADING\n");
g_smooth_fill_texture2d_program = linkProgram(
version,
"#define USE_COLOR_MATERIAL\n"
"#define USE_TEXTURE_2D\n"
"#define SMOOTH_SHADING\n");
g_wireframe_program = linkProgram(
version,
"#define WIREFRAME\n");
glGenBuffers(1, &g_lighting_ub);
glBindBuffer(GL_UNIFORM_BUFFER, g_lighting_ub);
@ -436,8 +484,8 @@ void openSubdiv_osdGLDisplayDeinit(void)
void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl,
int active_uv_index)
{
g_use_osd_glsl = use_osd_glsl != 0;
g_active_uv_index = active_uv_index;
g_use_osd_glsl = (use_osd_glsl != 0);
/* Update transformation matrices. */
glGetFloatv(GL_PROJECTION_MATRIX, g_transform.projection_matrix);
@ -494,7 +542,7 @@ void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl,
}
}
static GLuint prepare_patchDraw(GLMeshInterface *mesh,
static GLuint prepare_patchDraw(OpenSubdiv_GLMesh *gl_mesh,
bool fill_quads)
{
GLint program = 0;
@ -509,28 +557,42 @@ static GLuint prepare_patchDraw(GLMeshInterface *mesh,
glUniform1i(location, model == GL_FLAT);
}
/* TODO(sergey): Bring this back. */
#if 0
/* Face-vertex data */
if (mesh->GetDrawContext()->GetFvarDataTextureBuffer()) {
glActiveTexture(GL_TEXTURE31);
glBindTexture(GL_TEXTURE_BUFFER,
mesh->GetDrawContext()->GetFvarDataTextureBuffer());
glActiveTexture(GL_TEXTURE0);
if (gl_mesh->fvar_data != NULL) {
if (gl_mesh->fvar_data->texture_buffer) {
glActiveTexture(GL_TEXTURE31);
glBindTexture(GL_TEXTURE_BUFFER,
gl_mesh->fvar_data->texture_buffer);
glActiveTexture(GL_TEXTURE0);
}
if (gl_mesh->fvar_data->offset_buffer) {
glActiveTexture(GL_TEXTURE30);
glBindTexture(GL_TEXTURE_BUFFER,
gl_mesh->fvar_data->offset_buffer);
glActiveTexture(GL_TEXTURE0);
}
GLint location = glGetUniformLocation(program, "osd_fvar_count");
if (location != -1) {
glUniform1i(location, mesh->GetFVarCount());
glUniform1i(location, gl_mesh->fvar_data->fvar_width);
}
location = glGetUniformLocation(program, "osd_active_uv_offset");
if (location != -1) {
glUniform1i(location,
g_active_uv_index * 2);
if (gl_mesh->fvar_data->channel_offsets.size() > 0 &&
g_active_uv_index >= 0)
{
glUniform1i(location,
gl_mesh->fvar_data->channel_offsets[g_active_uv_index]);
} else {
glUniform1i(location, 0);
}
}
} else {
glUniform1i(glGetUniformLocation(program, "osd_fvar_count"), 0);
glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"), 0);
}
#endif
}
return program;
}
@ -562,7 +624,7 @@ static GLuint prepare_patchDraw(GLMeshInterface *mesh,
program = g_wireframe_program;
}
bindProgram(mesh, program);
bindProgram(gl_mesh, program);
return program;
}
@ -623,7 +685,7 @@ static void draw_partition_patches_range(GLMeshInterface *mesh,
const int num_draw_patches = std::min(num_remained_patches,
num_block_patches - start_draw_patch);
perform_drawElements(program,
i,
i + start_draw_patch,
num_draw_patches * num_control_verts,
patch.GetIndexBase() + start_draw_patch * num_control_verts);
num_remained_patches -= num_draw_patches;
@ -669,7 +731,7 @@ void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
}
/* Setup GLSL/OpenGL to draw patches in current context. */
GLuint program = prepare_patchDraw(mesh, fill_quads != 0);
GLuint program = prepare_patchDraw(gl_mesh, fill_quads != 0);
if (start_patch != -1) {
draw_partition_patches_range(mesh,
@ -684,3 +746,23 @@ void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
/* Finish patch drawing by restoring all changes to the OpenGL context. */
finish_patchDraw(fill_quads != 0);
}
void openSubdiv_osdGLAllocFVar(OpenSubdiv_TopologyRefinerDescr *topology_refiner,
OpenSubdiv_GLMesh *gl_mesh,
const float *fvar_data)
{
GLMeshInterface *mesh =
(GLMeshInterface *)(gl_mesh->descriptor);
gl_mesh->fvar_data = OBJECT_GUARDED_NEW(OpenSubdiv_GLMeshFVarData);
gl_mesh->fvar_data->Create(topology_refiner->osd_refiner,
mesh->GetFarPatchTable(),
2,
fvar_data);
}
void openSubdiv_osdGLDestroyFVar(OpenSubdiv_GLMesh *gl_mesh)
{
if (gl_mesh->fvar_data != NULL) {
OBJECT_GUARDED_DELETE(gl_mesh->fvar_data, OpenSubdiv_GLMeshFVarData);
}
}

View File

@ -0,0 +1,41 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2016 Blender Foundation.
* All rights reserved.
*
* Contributor(s): Sergey Sharybin.
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef __OPENSUBDIV_TOPOLOGY_REFINER_H__
#define __OPENSUBDIV_TOPOLOGY_REFINER_H__
#include <opensubdiv/far/topologyRefiner.h>
typedef struct OpenSubdiv_TopologyRefinerDescr {
OpenSubdiv::Far::TopologyRefiner *osd_refiner;
/* TODO(sergey): For now only, need to find better place
* after revisiting whole OSD drawing pipeline and Blender
* integration.
*/
std::vector<float> uvs;
} OpenSubdiv_TopologyRefinerDescr;
#endif /* __OPENSUBDIV_TOPOLOGY_REFINER_H__ */

View File

@ -329,16 +329,21 @@ WARN_MSGID_NOT_CAPITALIZED_ALLOWED = {
"available with",
"brown fox",
"can't save image while rendering",
"constructive modifier",
"edge data",
"expected a timeline/animation area to be active",
"expected a view3d region",
"expected a view3d region & editcurve",
"expected a view3d region & editmesh",
"face data",
"image file not found",
"image format is read-only",
"image path can't be written to",
"in memory to enable editing!",
"jumps over",
"left",
"multi-res modifier",
"non-triangle face",
"right",
"the lazy dog",
"unable to load movie clip",
@ -351,6 +356,7 @@ WARN_MSGID_NOT_CAPITALIZED_ALLOWED = {
"unsupported format",
"unsupported image format",
"unsupported movie clip format",
"vertex data",
"verts only",
"virtual parents",
}

View File

@ -565,7 +565,9 @@ class SpellChecker:
"ui",
"unix",
"vbo", "vbos",
"wxyz",
"ycc", "ycca",
"yrgb",
"yuv", "yuva",
# Blender acronyms

View File

@ -155,6 +155,11 @@ def bake_action(frame_start,
atd = obj.animation_data_create()
if action is None:
action = bpy.data.actions.new("Action")
# Leave tweak mode before trying to modify the action (T48397)
if atd.use_tweak_mode:
atd.use_tweak_mode = False
atd.action = action
# -------------------------------------------------------------------------

View File

@ -285,8 +285,7 @@ def lightmap_uvpack(meshes,
for face_sel in face_groups:
print("\nStarting unwrap")
if len(face_sel) < 4:
print("\tWarning, less then 4 faces, skipping")
if not face_sel:
continue
pretty_faces = [prettyface(f) for f in face_sel if f.loop_total >= 4]

View File

@ -300,19 +300,36 @@ class INFO_MT_help(Menu):
def draw(self, context):
layout = self.layout
layout.operator("wm.url_open", text="Manual", icon='HELP').url = "https://www.blender.org/manual"
layout.operator("wm.url_open", text="Release Log", icon='URL').url = "http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/%d.%d" % bpy.app.version[:2]
layout.operator(
"wm.url_open", text="Manual", icon='HELP',
).url = "https://www.blender.org/manual"
layout.operator(
"wm.url_open", text="Release Log", icon='URL',
).url = "http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/%d.%d" % bpy.app.version[:2]
layout.separator()
layout.operator("wm.url_open", text="Blender Website", icon='URL').url = "https://www.blender.org"
layout.operator("wm.url_open", text="Blender Store", icon='URL').url = "https://store.blender.org"
layout.operator("wm.url_open", text="Developer Community", icon='URL').url = "https://www.blender.org/get-involved/"
layout.operator("wm.url_open", text="User Community", icon='URL').url = "https://www.blender.org/support/user-community"
layout.operator(
"wm.url_open", text="Blender Website", icon='URL',
).url = "https://www.blender.org"
layout.operator(
"wm.url_open", text="Blender Store", icon='URL',
).url = "https://store.blender.org"
layout.operator(
"wm.url_open", text="Developer Community", icon='URL',
).url = "https://www.blender.org/get-involved/"
layout.operator(
"wm.url_open", text="User Community", icon='URL',
).url = "https://www.blender.org/support/user-community"
layout.separator()
layout.operator("wm.url_open", text="Report a Bug", icon='URL').url = "https://developer.blender.org/maniphest/task/create/?project=2&type=Bug"
layout.operator(
"wm.url_open", text="Report a Bug", icon='URL',
).url = "https://developer.blender.org/maniphest/task/edit/form/1"
layout.separator()
layout.operator("wm.url_open", text="Python API Reference", icon='URL').url = bpy.types.WM_OT_doc_view._prefix
layout.operator(
"wm.url_open", text="Python API Reference", icon='URL',
).url = bpy.types.WM_OT_doc_view._prefix
layout.operator("wm.operator_cheat_sheet", icon='TEXT')
layout.operator("wm.sysinfo", icon='TEXT')
layout.separator()

View File

@ -1415,7 +1415,7 @@ class USERPREF_PT_addons(Panel):
split.operator("wm.url_open", text="Documentation", icon='HELP').url = info["wiki_url"]
split.operator("wm.url_open", text="Report a Bug", icon='URL').url = info.get(
"tracker_url",
"http://developer.blender.org/maniphest/task/create/?project=3&type=Bug")
"https://developer.blender.org/maniphest/task/edit/form/2")
if user_addon:
split.operator("wm.addon_remove", text="Remove", icon='CANCEL').module = mod.__name__

View File

@ -2361,6 +2361,7 @@ class VIEW3D_MT_edit_mesh_edges(Menu):
layout.operator("mesh.edge_face_add")
layout.operator("mesh.subdivide")
layout.operator("mesh.subdivide_edgering")
layout.operator("mesh.unsubdivide")
layout.separator()

View File

@ -570,6 +570,7 @@ class VIEW3D_PT_tools_curveedit_options_stroke(View3DPanel, Panel):
if cps.curve_type == 'BEZIER':
col.label("Bezier Options:")
col.prop(cps, "error_threshold")
col.prop(cps, "fit_method")
col.prop(cps, "use_corners_detect")
col = layout.column()

View File

@ -370,12 +370,10 @@ static void blf_font_draw_buffer_ex(
fbuf[3] = 1.0f;
}
else {
float alphatest;
fbuf[0] = (b_col_float[0] * a) + (fbuf[0] * (1.0f - a));
fbuf[1] = (b_col_float[1] * a) + (fbuf[1] * (1.0f - a));
fbuf[2] = (b_col_float[2] * a) + (fbuf[2] * (1.0f - a));
fbuf[3] = (alphatest = (fbuf[3] + a)) < 1.0f ?
alphatest : 1.0f;
fbuf[3] = MIN2(fbuf[3] + a, 1.0f); /* clamp to 1.0 */
}
}
}
@ -407,12 +405,10 @@ static void blf_font_draw_buffer_ex(
cbuf[3] = 255;
}
else {
int alphatest;
cbuf[0] = (unsigned char)((b_col_char[0] * a) + (cbuf[0] * (1.0f - a)));
cbuf[1] = (unsigned char)((b_col_char[1] * a) + (cbuf[1] * (1.0f - a)));
cbuf[2] = (unsigned char)((b_col_char[2] * a) + (cbuf[2] * (1.0f - a)));
cbuf[3] = (unsigned char)(((alphatest = ((int)cbuf[3] + (int)(a * 255))) < 255) ?
alphatest : 255);
cbuf[3] = (unsigned char)MIN2((int)cbuf[3] + (int)(a * 255), 255); /* clamp to 255 */
}
}
}

View File

@ -63,7 +63,7 @@ struct bAction *BKE_action_copy(struct Main *bmain, struct bAction *src);
/* Deallocate all of the Action's data, but not the Action itself */
void BKE_action_free(struct bAction *act);
void BKE_action_make_local(struct Main *bmain, struct bAction *act, const bool force_local);
void BKE_action_make_local(struct Main *bmain, struct bAction *act, const bool lib_local);
/* Action API ----------------- */

View File

@ -76,7 +76,7 @@ struct bArmature *BKE_armature_from_object(struct Object *ob);
int BKE_armature_bonelist_count(struct ListBase *lb);
void BKE_armature_bonelist_free(struct ListBase *lb);
void BKE_armature_free(struct bArmature *arm);
void BKE_armature_make_local(struct Main *bmain, struct bArmature *arm, const bool force_local);
void BKE_armature_make_local(struct Main *bmain, struct bArmature *arm, const bool lib_local);
struct bArmature *BKE_armature_copy(struct Main *bmain, struct bArmature *arm);
/* Bounding box. */
@ -95,6 +95,7 @@ float distfactor_to_bone(const float vec[3], const float b1[3], const float b2[3
void BKE_armature_where_is(struct bArmature *arm);
void BKE_armature_where_is_bone(struct Bone *bone, struct Bone *prevbone, const bool use_recursion);
void BKE_pose_clear_pointers(struct bPose *pose);
void BKE_pose_rebuild(struct Object *ob, struct bArmature *arm);
void BKE_pose_where_is(struct Scene *scene, struct Object *ob);
void BKE_pose_where_is_bone(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime, bool do_extra);

View File

@ -45,7 +45,7 @@ void BKE_brush_init(struct Brush *brush);
struct Brush *BKE_brush_add(struct Main *bmain, const char *name, short ob_mode);
struct Brush *BKE_brush_first_search(struct Main *bmain, short ob_mode);
struct Brush *BKE_brush_copy(struct Main *bmain, struct Brush *brush);
void BKE_brush_make_local(struct Main *bmain, struct Brush *brush, const bool force_local);
void BKE_brush_make_local(struct Main *bmain, struct Brush *brush, const bool lib_local);
void BKE_brush_unlink(struct Main *bmain, struct Brush *brush);
void BKE_brush_free(struct Brush *brush);

View File

@ -53,7 +53,7 @@ struct GPUFXSettings;
void BKE_camera_init(struct Camera *cam);
void *BKE_camera_add(struct Main *bmain, const char *name);
struct Camera *BKE_camera_copy(struct Main *bmain, struct Camera *cam);
void BKE_camera_make_local(struct Main *bmain, struct Camera *cam, const bool force_local);
void BKE_camera_make_local(struct Main *bmain, struct Camera *cam, const bool lib_local);
void BKE_camera_free(struct Camera *ca);
/* Camera Usage */

View File

@ -71,7 +71,7 @@ void BKE_curve_editfont_free(struct Curve *cu);
void BKE_curve_init(struct Curve *cu);
struct Curve *BKE_curve_add(struct Main *bmain, const char *name, int type);
struct Curve *BKE_curve_copy(struct Main *bmain, struct Curve *cu);
void BKE_curve_make_local(struct Main *bmain, struct Curve *cu, const bool force_local);
void BKE_curve_make_local(struct Main *bmain, struct Curve *cu, const bool lib_local);
short BKE_curve_type_get(struct Curve *cu);
void BKE_curve_type_test(struct Object *ob);
void BKE_curve_curve_dimension_update(struct Curve *cu);

View File

@ -82,6 +82,8 @@ struct VFont *BKE_vfont_load(struct Main *bmain, const char *filepath);
struct VFont *BKE_vfont_load_exists_ex(struct Main *bmain, const char *filepath, bool *r_exists);
struct VFont *BKE_vfont_load_exists(struct Main *bmain, const char *filepath);
void BKE_vfont_make_local(struct Main *bmain, struct VFont *vfont, const bool lib_local);
bool BKE_vfont_to_curve_ex(struct Main *bmain, struct Object *ob, int mode,
struct ListBase *r_nubase,
const wchar_t **r_text, int *r_text_len, bool *r_text_free,

View File

@ -56,6 +56,8 @@ struct bGPDframe *gpencil_frame_duplicate(struct bGPDframe *src);
struct bGPDlayer *gpencil_layer_duplicate(struct bGPDlayer *src);
struct bGPdata *gpencil_data_duplicate(struct Main *bmain, struct bGPdata *gpd, bool internal_copy);
void BKE_gpencil_make_local(struct Main *bmain, struct bGPdata *gpd, const bool lib_local);
void gpencil_frame_delete_laststroke(struct bGPDlayer *gpl, struct bGPDframe *gpf);

View File

@ -43,6 +43,7 @@ struct Scene;
void BKE_group_free(struct Group *group);
struct Group *BKE_group_add(struct Main *bmain, const char *name);
struct Group *BKE_group_copy(struct Main *bmain, struct Group *group);
void BKE_group_make_local(struct Main *bmain, struct Group *group, const bool lib_local);
bool BKE_group_object_add(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base);
bool BKE_group_object_unlink(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base);
struct Group *BKE_group_object_find(struct Group *group, struct Object *ob);

View File

@ -99,6 +99,8 @@ struct PreviewImage *BKE_previewimg_create(void);
/* create a copy of the preview image */
struct PreviewImage *BKE_previewimg_copy(struct PreviewImage *prv);
void BKE_previewimg_id_copy(struct ID *new_id, struct ID *old_id);
/* retrieve existing or create new preview image */
struct PreviewImage *BKE_previewimg_id_ensure(struct ID *id);

View File

@ -108,7 +108,7 @@ struct anim *openanim_noload(const char *name, int flags, int streamindex, char
void BKE_image_de_interlace(struct Image *ima, int odd);
void BKE_image_make_local(struct Main *bmain, struct Image *ima, const bool force_local);
void BKE_image_make_local(struct Main *bmain, struct Image *ima, const bool lib_local);
void BKE_image_tag_time(struct Image *ima);

View File

@ -46,7 +46,7 @@ void BKE_lamp_init(struct Lamp *la);
struct Lamp *BKE_lamp_add(struct Main *bmain, const char *name) ATTR_WARN_UNUSED_RESULT;
struct Lamp *BKE_lamp_copy(struct Main *bmain, struct Lamp *la) ATTR_WARN_UNUSED_RESULT;
struct Lamp *localize_lamp(struct Lamp *la) ATTR_WARN_UNUSED_RESULT;
void BKE_lamp_make_local(struct Main *bmain, struct Lamp *la, const bool force_local);
void BKE_lamp_make_local(struct Main *bmain, struct Lamp *la, const bool lib_local);
void BKE_lamp_free(struct Lamp *la);
void lamp_drivers_update(struct Scene *scene, struct Lamp *la, float ctime);

View File

@ -49,7 +49,7 @@ void BKE_lattice_init(struct Lattice *lt);
struct Lattice *BKE_lattice_add(struct Main *bmain, const char *name);
struct Lattice *BKE_lattice_copy(struct Main *bmain, struct Lattice *lt);
void BKE_lattice_free(struct Lattice *lt);
void BKE_lattice_make_local(struct Main *bmain, struct Lattice *lt, const bool force_local);
void BKE_lattice_make_local(struct Main *bmain, struct Lattice *lt, const bool lib_local);
void calc_lat_fudu(int flag, int res, float *r_fu, float *r_du);
struct LatticeDeformData;

View File

@ -80,6 +80,7 @@ void id_us_min(struct ID *id);
void id_fake_user_set(struct ID *id);
void id_fake_user_clear(struct ID *id);
void BKE_id_make_local_generic(struct Main *bmain, struct ID *id, const bool id_in_mainlist, const bool lib_local);
bool id_make_local(struct Main *bmain, struct ID *id, const bool test, const bool force_local);
bool id_single_user(struct bContext *C, struct ID *id, struct PointerRNA *ptr, struct PropertyRNA *prop);
bool id_copy(struct Main *bmain, struct ID *id, struct ID **newid, bool test);
@ -88,7 +89,7 @@ void BKE_id_expand_local(struct ID *id);
bool new_id(struct ListBase *lb, struct ID *id, const char *name);
void id_clear_lib_data(struct Main *bmain, struct ID *id);
void id_clear_lib_data_ex(struct Main *bmain, struct ID *id, bool id_in_mainlist);
void id_clear_lib_data_ex(struct Main *bmain, struct ID *id, const bool id_in_mainlist);
struct ListBase *which_libbase(struct Main *mainlib, short type);

View File

@ -54,6 +54,8 @@ FreestyleLineStyle *BKE_linestyle_new(struct Main *bmain, const char *name);
void BKE_linestyle_free(FreestyleLineStyle *linestyle);
FreestyleLineStyle *BKE_linestyle_copy(struct Main *bmain, FreestyleLineStyle *linestyle);
void BKE_linestyle_make_local(struct Main *bmain, struct FreestyleLineStyle *linestyle, const bool lib_local);
FreestyleLineStyle *BKE_linestyle_active_from_scene(struct Scene *scene);
LineStyleModifier *BKE_linestyle_color_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type);

View File

@ -125,6 +125,8 @@ struct Mask *BKE_mask_new(struct Main *bmain, const char *name);
struct Mask *BKE_mask_copy_nolib(struct Mask *mask);
struct Mask *BKE_mask_copy(struct Main *bmain, struct Mask *mask);
void BKE_mask_make_local(struct Main *bmain, struct Mask *mask, const bool lib_local);
void BKE_mask_free(struct Mask *mask);
void BKE_mask_coord_from_frame(float r_co[2], const float co[2], const float frame_size[2]);

View File

@ -57,7 +57,7 @@ struct Material *BKE_material_add(struct Main *bmain, const char *name);
struct Material *BKE_material_copy(struct Main *bmain, struct Material *ma);
struct Material *localize_material(struct Material *ma);
struct Material *give_node_material(struct Material *ma); /* returns node material or self */
void BKE_material_make_local(struct Main *bmain, struct Material *ma, const bool force_local);
void BKE_material_make_local(struct Main *bmain, struct Material *ma, const bool lib_local);
/* UNUSED */
// void automatname(struct Material *);
@ -78,15 +78,13 @@ enum {
};
struct Material *give_current_material(struct Object *ob, short act);
struct ID *material_from(struct Object *ob, short act);
void assign_material_id(struct ID *id, struct Material *ma, short act);
void assign_material(struct Object *ob, struct Material *ma, short act, int assign_type);
void assign_matarar(struct Object *ob, struct Material ***matar, short totcol);
short find_material_index(struct Object *ob, struct Material *ma);
bool object_add_material_slot(struct Object *ob);
bool object_remove_material_slot(struct Object *ob);
short BKE_object_material_slot_find_index(struct Object *ob, struct Material *ma);
bool BKE_object_material_slot_add(struct Object *ob);
bool BKE_object_material_slot_remove(struct Object *ob);
void BKE_texpaint_slot_refresh_cache(struct Scene *scene, struct Material *ma);
void BKE_texpaint_slots_refresh_object(struct Scene *scene, struct Object *ob);

View File

@ -43,7 +43,7 @@ void BKE_mball_init(struct MetaBall *mb);
struct MetaBall *BKE_mball_add(struct Main *bmain, const char *name);
struct MetaBall *BKE_mball_copy(struct Main *bmain, struct MetaBall *mb);
void BKE_mball_make_local(struct Main *bmain, struct MetaBall *mb, const bool force_local);
void BKE_mball_make_local(struct Main *bmain, struct MetaBall *mb, const bool lib_local);
bool BKE_mball_is_basis_for(struct Object *ob1, struct Object *ob2);
bool BKE_mball_is_basis(struct Object *ob);

View File

@ -91,7 +91,7 @@ struct Mesh *BKE_mesh_copy(struct Main *bmain, struct Mesh *me);
void BKE_mesh_update_customdata_pointers(struct Mesh *me, const bool do_ensure_tess_cd);
void BKE_mesh_ensure_skin_customdata(struct Mesh *me);
void BKE_mesh_make_local(struct Main *bmain, struct Mesh *me, const bool force_local);
void BKE_mesh_make_local(struct Main *bmain, struct Mesh *me, const bool lib_local);
void BKE_mesh_boundbox_calc(struct Mesh *me, float r_loc[3], float r_size[3]);
void BKE_mesh_texspace_calc(struct Mesh *me);
float (*BKE_mesh_orco_verts_get(struct Object *ob))[3];

View File

@ -125,6 +125,11 @@ void BKE_mesh_vert_edge_map_create(
void BKE_mesh_vert_edge_vert_map_create(
MeshElemMap **r_map, int **r_mem,
const struct MEdge *medge, int totvert, int totedge);
void BKE_mesh_edge_loop_map_create(
MeshElemMap **r_map, int **r_mem,
const struct MEdge *medge, const int totedge,
const struct MPoly *mpoly, const int totpoly,
const struct MLoop *mloop, const int totloop);
void BKE_mesh_edge_poly_map_create(
MeshElemMap **r_map, int **r_mem,
const struct MEdge *medge, const int totedge,
@ -186,13 +191,21 @@ typedef bool (*MeshRemapIslandsCalc)(
/* Above vert/UV mapping stuff does not do what we need here, but does things we do not need here.
* So better keep them separated for now, I think.
*/
bool BKE_mesh_calc_islands_loop_poly_uv(
bool BKE_mesh_calc_islands_loop_poly_edgeseam(
struct MVert *verts, const int totvert,
struct MEdge *edges, const int totedge,
struct MPoly *polys, const int totpoly,
struct MLoop *loops, const int totloop,
MeshIslandStore *r_island_store);
bool BKE_mesh_calc_islands_loop_poly_uvmap(
struct MVert *verts, const int totvert,
struct MEdge *edges, const int totedge,
struct MPoly *polys, const int totpoly,
struct MLoop *loops, const int totloop,
const struct MLoopUV *luvs,
MeshIslandStore *r_island_store);
int *BKE_mesh_calc_smoothgroups(
const struct MEdge *medge, const int totedge,
const struct MPoly *mpoly, const int totpoly,

View File

@ -346,7 +346,7 @@ void ntreeUserDecrefID(struct bNodeTree *ntree);
struct bNodeTree *ntreeFromID(struct ID *id);
void ntreeMakeLocal(struct Main *bmain, struct bNodeTree *ntree, bool id_in_mainlist, const bool force_local);
void ntreeMakeLocal(struct Main *bmain, struct bNodeTree *ntree, bool id_in_mainlist, const bool lib_local);
struct bNode *ntreeFindType(const struct bNodeTree *ntree, int type);
bool ntreeHasType(const struct bNodeTree *ntree, int type);
bool ntreeHasTree(const struct bNodeTree *ntree, const struct bNodeTree *lookup);

View File

@ -104,7 +104,7 @@ struct Object *BKE_object_lod_matob_get(struct Object *ob, struct Scene *scene);
struct Object *BKE_object_copy_ex(struct Main *bmain, struct Object *ob, bool copy_caches);
struct Object *BKE_object_copy(struct Main *bmain, struct Object *ob);
void BKE_object_make_local(struct Main *bmain, struct Object *ob, const bool force_local);
void BKE_object_make_local(struct Main *bmain, struct Object *ob, const bool lib_local);
bool BKE_object_is_libdata(struct Object *ob);
bool BKE_object_obdata_is_libdata(struct Object *ob);

View File

@ -101,6 +101,8 @@ struct Scene *BKE_scene_set_name(struct Main *bmain, const char *name);
struct Scene *BKE_scene_copy(struct Main *bmain, struct Scene *sce, int type);
void BKE_scene_groups_relink(struct Scene *sce);
void BKE_scene_make_local(struct Main *bmain, struct Scene *sce, const bool lib_local);
struct Object *BKE_scene_camera_find(struct Scene *sc);
#ifdef DURIAN_CAMERA_SWITCH
struct Object *BKE_scene_camera_switch_find(struct Scene *scene); // DURIAN_CAMERA_SWITCH

View File

@ -80,6 +80,8 @@ void BKE_sound_load(struct Main *main, struct bSound *sound);
void BKE_sound_free(struct bSound *sound);
void BKE_sound_make_local(struct Main *bmain, struct bSound *sound, const bool lib_local);
#if defined(__AUD_C_API_H__) || defined(WITH_SYSTEM_AUDASPACE)
AUD_Device *BKE_sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, float volume);
#endif

View File

@ -34,7 +34,7 @@ struct Speaker;
void BKE_speaker_init(struct Speaker *spk);
void *BKE_speaker_add(struct Main *bmain, const char *name);
struct Speaker *BKE_speaker_copy(struct Main *bmain, struct Speaker *spk);
void BKE_speaker_make_local(struct Main *bmain, struct Speaker *spk, const bool force_local);
void BKE_speaker_make_local(struct Main *bmain, struct Speaker *spk, const bool lib_local);
void BKE_speaker_free(struct Speaker *spk);
#endif

View File

@ -53,6 +53,7 @@ struct Text *BKE_text_load_ex(struct Main *bmain, const char *file, const cha
const bool is_internal);
struct Text *BKE_text_load (struct Main *bmain, const char *file, const char *relpath);
struct Text *BKE_text_copy (struct Main *bmain, struct Text *ta);
void BKE_text_make_local (struct Main *bmain, struct Text *text, const bool lib_local);
void BKE_text_clear (struct Text *text);
void BKE_text_write (struct Text *text, const char *str);
int BKE_text_file_modified_check(struct Text *text);

View File

@ -71,7 +71,7 @@ void BKE_texture_default(struct Tex *tex);
struct Tex *BKE_texture_copy(struct Main *bmain, struct Tex *tex);
struct Tex *BKE_texture_add(struct Main *bmain, const char *name);
struct Tex *BKE_texture_localize(struct Tex *tex);
void BKE_texture_make_local(struct Main *bmain, struct Tex *tex, const bool force_local);
void BKE_texture_make_local(struct Main *bmain, struct Tex *tex, const bool lib_local);
void BKE_texture_type_set(struct Tex *tex, int type);
void BKE_texture_mtex_default(struct MTex *mtex);

View File

@ -41,7 +41,7 @@ void BKE_world_init(struct World *wrld);
struct World *add_world(struct Main *bmian, const char *name);
struct World *BKE_world_copy(struct Main *bmain, struct World *wrld);
struct World *localize_world(struct World *wrld);
void BKE_world_make_local(struct Main *bmain, struct World *wrld, const bool force_local);
void BKE_world_make_local(struct Main *bmain, struct World *wrld, const bool lib_local);
#endif

View File

@ -313,12 +313,10 @@ CCGSubSurf *ccgSubSurf_new(CCGMeshIFC *ifc, int subdivLevels, CCGAllocatorIFC *a
ss->osd_vao = 0;
ss->skip_grids = false;
ss->osd_compute = 0;
ss->osd_uvs_invalid = true;
ss->osd_subsurf_uv = 0;
ss->osd_uv_index = -1;
ss->osd_next_face_ptex_index = 0;
ss->osd_coarse_coords = NULL;
ss->osd_num_coarse_coords = 0;
ss->osd_subdiv_uvs = false;
#endif
return ss;

View File

@ -205,7 +205,7 @@ void ccgSubSurf_checkTopologyChanged(CCGSubSurf *ss, struct DerivedMesh *dm);
void ccgSubSurf_prepareTopologyRefiner(CCGSubSurf *ss, struct DerivedMesh *dm);
/* Make sure GL mesh exists, up to date and ready to draw. */
bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss, bool use_osd_glsl);
bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss, bool use_osd_glsl, int active_uv_index);
/* Draw given partitions of the GL mesh.
*
@ -244,6 +244,8 @@ void ccgSubSurf_free_osd_mesh(CCGSubSurf *ss);
void ccgSubSurf_getMinMax(CCGSubSurf *ss, float r_min[3], float r_max[3]);
void ccgSubSurf__sync_subdivUvs(CCGSubSurf *ss, bool subsurf_uvs);
#endif
#endif /* __CCGSUBSURF_H__ */

View File

@ -86,7 +86,7 @@ void ccg_ehashIterator_next(EHashIterator *ehi);
int ccg_ehashIterator_isStopped(EHashIterator *ehi);
/**
* Standard allocator implementarion.
* Standard allocator implementation.
*/
CCGAllocatorIFC *ccg_getStandardAllocatorIFC(void);
@ -255,10 +255,7 @@ struct CCGSubSurf {
*/
int osd_next_face_ptex_index;
/* ** Needs review. ** */
bool osd_subsurf_uv;
int osd_uv_index;
bool osd_uvs_invalid;
bool osd_subdiv_uvs;
#endif
};

View File

@ -190,7 +190,6 @@ void ccgSubSurf_checkTopologyChanged(CCGSubSurf *ss, DerivedMesh *dm)
/* ** Make sure both GPU and CPU backends are properly reset. ** */
ss->osd_coarse_coords_invalid = true;
ss->osd_uvs_invalid = true;
/* Reset GPU part. */
ss->osd_mesh_invalid = true;
@ -216,7 +215,9 @@ static void ccgSubSurf__updateGLMeshCoords(CCGSubSurf *ss)
ss->osd_num_coarse_coords);
}
bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss, bool use_osd_glsl)
bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss,
bool use_osd_glsl,
int active_uv_index)
{
int compute_type;
@ -256,8 +257,7 @@ bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss, bool use_osd_glsl)
ss->osd_mesh = openSubdiv_createOsdGLMeshFromTopologyRefiner(
ss->osd_topology_refiner,
compute_type,
ss->subdivLevels,
ss->osd_subsurf_uv);
ss->subdivLevels);
ss->osd_topology_refiner = NULL;
if (UNLIKELY(ss->osd_mesh == NULL)) {
@ -290,7 +290,7 @@ bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss, bool use_osd_glsl)
ss->osd_coarse_coords_invalid = false;
}
openSubdiv_osdGLMeshDisplayPrepare(use_osd_glsl, ss->osd_uv_index);
openSubdiv_osdGLMeshDisplayPrepare(use_osd_glsl, active_uv_index);
return true;
}
@ -984,6 +984,11 @@ void ccgSubSurf__delete_pending(void)
BLI_spin_unlock(&delete_spin);
}
void ccgSubSurf__sync_subdivUvs(CCGSubSurf *ss, bool subdiv_uvs)
{
ss->osd_subdiv_uvs = subdiv_uvs;
}
/* ** Public API ** */
void BKE_subsurf_osd_init(void)

View File

@ -62,6 +62,16 @@ typedef struct ConvDMStorage {
*vert_poly_mem,
*edge_poly_mem;
#endif
MVert *mvert;
MEdge *medge;
MLoop *mloop;
MPoly *mpoly;
MeshIslandStore island_store;
int num_uvs;
float *uvs;
int *face_uvs;
} ConvDMStorage;
static OpenSubdiv_SchemeType conv_dm_get_type(
@ -74,6 +84,13 @@ static OpenSubdiv_SchemeType conv_dm_get_type(
return OSD_SCHEME_CATMARK;
}
static bool conv_dm_get_subdiv_uvs(
const OpenSubdiv_Converter *converter)
{
ConvDMStorage *storage = converter->user_data;
return (storage->ss->osd_subdiv_uvs);
}
static int conv_dm_get_num_faces(const OpenSubdiv_Converter *converter)
{
ConvDMStorage *storage = converter->user_data;
@ -99,9 +116,7 @@ static int conv_dm_get_num_face_verts(const OpenSubdiv_Converter *converter,
int face)
{
ConvDMStorage *storage = converter->user_data;
DerivedMesh *dm = storage->dm;
const MPoly *mp = dm->getPolyArray(dm);
const MPoly *mpoly = &mp[face];
const MPoly *mpoly = &storage->mpoly[face];
return mpoly->totloop;
}
@ -110,13 +125,10 @@ static void conv_dm_get_face_verts(const OpenSubdiv_Converter *converter,
int *face_verts)
{
ConvDMStorage *storage = converter->user_data;
DerivedMesh *dm = storage->dm;
const MLoop *ml = dm->getLoopArray(dm);
const MPoly *mp = dm->getPolyArray(dm);
const MPoly *mpoly = &mp[face];
const MPoly *mpoly = &storage->mpoly[face];
int loop;
for (loop = 0; loop < mpoly->totloop; loop++) {
face_verts[loop] = ml[mpoly->loopstart + loop].v;
face_verts[loop] = storage->mloop[mpoly->loopstart + loop].v;
}
}
@ -125,13 +137,10 @@ static void conv_dm_get_face_edges(const OpenSubdiv_Converter *converter,
int *face_edges)
{
ConvDMStorage *storage = converter->user_data;
DerivedMesh *dm = storage->dm;
const MLoop *ml = dm->getLoopArray(dm);
const MPoly *mp = dm->getPolyArray(dm);
const MPoly *mpoly = &mp[face];
const MPoly *mpoly = &storage->mpoly[face];
int loop;
for (loop = 0; loop < mpoly->totloop; loop++) {
face_edges[loop] = ml[mpoly->loopstart + loop].e;
face_edges[loop] = storage->mloop[mpoly->loopstart + loop].e;
}
}
@ -140,9 +149,7 @@ static void conv_dm_get_edge_verts(const OpenSubdiv_Converter *converter,
int *edge_verts)
{
ConvDMStorage *storage = converter->user_data;
DerivedMesh *dm = storage->dm;
const MEdge *me = dm->getEdgeArray(dm);
const MEdge *medge = &me[edge];
const MEdge *medge = &storage->medge[edge];
edge_verts[0] = medge->v1;
edge_verts[1] = medge->v2;
}
@ -153,14 +160,12 @@ static int conv_dm_get_num_edge_faces(const OpenSubdiv_Converter *converter,
ConvDMStorage *storage = converter->user_data;
#ifndef USE_MESH_ELEMENT_MAPPING
DerivedMesh *dm = storage->dm;
const MLoop *ml = dm->getLoopArray(dm);
const MPoly *mp = dm->getPolyArray(dm);
int num = 0, poly;
for (poly = 0; poly < dm->getNumPolys(dm); poly++) {
const MPoly *mpoly = &mp[poly];
const MPoly *mpoly = &user_data->mpoly[poly];
int loop;
for (loop = 0; loop < mpoly->totloop; loop++) {
const MLoop *mloop = &ml[mpoly->loopstart + loop];
const MLoop *mloop = &storage->mloop[mpoly->loopstart + loop];
if (mloop->e == edge) {
++num;
break;
@ -180,14 +185,12 @@ static void conv_dm_get_edge_faces(const OpenSubdiv_Converter *converter,
ConvDMStorage *storage = converter->user_data;
#ifndef USE_MESH_ELEMENT_MAPPING
DerivedMesh *dm = storage->dm;
const MLoop *ml = dm->getLoopArray(dm);
const MPoly *mp = dm->getPolyArray(dm);
int num = 0, poly;
for (poly = 0; poly < dm->getNumPolys(dm); poly++) {
const MPoly *mpoly = &mp[poly];
const MPoly *mpoly = &user_data->mpoly[poly];
int loop;
for (loop = 0; loop < mpoly->totloop; loop++) {
const MLoop *mloop = &ml[mpoly->loopstart + loop];
const MLoop *mloop = &storage->mloop[mpoly->loopstart + loop];
if (mloop->e == edge) {
edge_faces[num++] = poly;
break;
@ -205,9 +208,8 @@ static float conv_dm_get_edge_sharpness(const OpenSubdiv_Converter *converter,
int edge)
{
ConvDMStorage *storage = converter->user_data;
DerivedMesh *dm = storage->dm;
CCGSubSurf *ss = storage->ss;
const MEdge *medge = dm->getEdgeArray(dm);
const MEdge *medge = storage->medge;
return (float)medge[edge].crease / 255.0f * ss->subdivLevels;
}
@ -217,10 +219,9 @@ static int conv_dm_get_num_vert_edges(const OpenSubdiv_Converter *converter,
ConvDMStorage *storage = converter->user_data;
#ifndef USE_MESH_ELEMENT_MAPPING
DerivedMesh *dm = storage->dm;
const MEdge *me = dm->getEdgeArray(dm);
int num = 0, edge;
for (edge = 0; edge < dm->getNumEdges(dm); edge++) {
const MEdge *medge = &me[edge];
const MEdge *medge = &user_data->medge[edge];
if (medge->v1 == vert || medge->v2 == vert) {
++num;
}
@ -238,10 +239,9 @@ static void conv_dm_get_vert_edges(const OpenSubdiv_Converter *converter,
ConvDMStorage *storage = converter->user_data;
#ifndef USE_MESH_ELEMENT_MAPPING
DerivedMesh *dm = storage->dm;
const MEdge *me = dm->getEdgeArray(dm);
int num = 0, edge;
for (edge = 0; edge < dm->getNumEdges(dm); edge++) {
const MEdge *medge = &me[edge];
const MEdge *medge = &user_data->medge[edge];
if (medge->v1 == vert || medge->v2 == vert) {
vert_edges[num++] = edge;
}
@ -259,14 +259,12 @@ static int conv_dm_get_num_vert_faces(const OpenSubdiv_Converter *converter,
ConvDMStorage *storage = converter->user_data;
#ifndef USE_MESH_ELEMENT_MAPPING
DerivedMesh *dm = storage->dm;
const MLoop *ml = dm->getLoopArray(dm);
const MPoly *mp = dm->getPolyArray(dm);
int num = 0, poly;
for (poly = 0; poly < dm->getNumPolys(dm); poly++) {
const MPoly *mpoly = &mp[poly];
const MPoly *mpoly = &user_data->mpoly[poly];
int loop;
for (loop = 0; loop < mpoly->totloop; loop++) {
const MLoop *mloop = &ml[mpoly->loopstart + loop];
const MLoop *mloop = &storage->mloop[mpoly->loopstart + loop];
if (mloop->v == vert) {
++num;
break;
@ -286,14 +284,12 @@ static void conv_dm_get_vert_faces(const OpenSubdiv_Converter *converter,
ConvDMStorage *storage = converter->user_data;
#ifndef USE_MESH_ELEMENT_MAPPING
DerivedMesh *dm = storage->dm;
const MLoop *ml = dm->getLoopArray(dm);
const MPoly *mp = dm->getPolyArray(dm);
int num = 0, poly;
for (poly = 0; poly < dm->getNumPolys(dm); poly++) {
const MPoly *mpoly = &mp[poly];
const MPoly *mpoly = &storage->mpoly[poly];
int loop;
for (loop = 0; loop < mpoly->totloop; loop++) {
const MLoop *mloop = &ml[mpoly->loopstart + loop];
const MLoop *mloop = &storage->mloop[mpoly->loopstart + loop];
if (mloop->v == vert) {
vert_faces[num++] = poly;
break;
@ -307,9 +303,114 @@ static void conv_dm_get_vert_faces(const OpenSubdiv_Converter *converter,
#endif
}
static int conv_dm_get_num_uv_layers(const OpenSubdiv_Converter *converter)
{
ConvDMStorage *storage = converter->user_data;
DerivedMesh *dm = storage->dm;
int num_uv_layers = CustomData_number_of_layers(&dm->loopData, CD_MLOOPUV);
return num_uv_layers;
}
static void conv_dm_precalc_uv_layer(const OpenSubdiv_Converter *converter,
int layer)
{
ConvDMStorage *storage = converter->user_data;
DerivedMesh *dm = storage->dm;
const MLoopUV *mloopuv = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, layer);
const int num_loops = dm->getNumLoops(dm);
/* Initialize memory required for the operations. */
if (storage->uvs == NULL) {
storage->uvs = MEM_mallocN(sizeof(float) * 2 * num_loops, "osd uvs");
}
if (storage->face_uvs == NULL) {
storage->face_uvs = MEM_mallocN(sizeof(int) * num_loops, "osd face uvs");
}
/* Calculate islands connectivity of the UVs. */
BKE_mesh_calc_islands_loop_poly_uvmap(
storage->mvert, dm->getNumVerts(dm),
storage->medge, dm->getNumEdges(dm),
storage->mpoly, dm->getNumPolys(dm),
storage->mloop, dm->getNumLoops(dm),
mloopuv,
&storage->island_store);
/* Here we "weld" duplicated vertices from island to the same UV value.
* The idea here is that we need to pass individual islands to OpenSubdiv.
*/
storage->num_uvs = 0;
for (int island = 0; island < storage->island_store.islands_num; ++island) {
MeshElemMap *island_poly_map = storage->island_store.islands[island];
for (int poly = 0; poly < island_poly_map->count; ++poly) {
int poly_index = island_poly_map->indices[poly];
/* Within the same UV island we should share UV points across
* loops. Otherwise each poly will be subdivided individually
* which we don't really want.
*/
const MPoly *mpoly = &storage->mpoly[poly_index];
for (int loop = 0; loop < mpoly->totloop; ++loop) {
const MLoopUV *luv = &mloopuv[mpoly->loopstart + loop];
bool found = false;
/* TODO(sergey): Quite bad loop, which gives us O(N^2)
* complexity here. But how can we do it smarter, hopefully
* without requiring lots of additional memory.
*/
for (int i = 0; i < storage->num_uvs; ++i) {
if (equals_v2v2(luv->uv, &storage->uvs[2 * i])) {
storage->face_uvs[mpoly->loopstart + loop] = i;
found = true;
break;
}
}
if (!found) {
copy_v2_v2(&storage->uvs[2 * storage->num_uvs], luv->uv);
storage->face_uvs[mpoly->loopstart + loop] = storage->num_uvs;
++storage->num_uvs;
}
}
}
}
}
static void conv_dm_finish_uv_layer(const OpenSubdiv_Converter *converter)
{
ConvDMStorage *storage = converter->user_data;
BKE_mesh_loop_islands_free(&storage->island_store);
}
static int conv_dm_get_num_uvs(const OpenSubdiv_Converter *converter)
{
ConvDMStorage *storage = converter->user_data;
return storage->num_uvs;
}
static void conv_dm_get_uvs(const OpenSubdiv_Converter *converter, float *uvs)
{
ConvDMStorage *storage = converter->user_data;
memcpy(uvs, storage->uvs, sizeof(float) * 2 * storage->num_uvs);
}
static int conv_dm_get_face_corner_uv_index(const OpenSubdiv_Converter *converter,
int face,
int corner)
{
ConvDMStorage *storage = converter->user_data;
const MPoly *mpoly = &storage->mpoly[face];
return storage->face_uvs[mpoly->loopstart + corner];
}
static void conv_dm_free_user_data(const OpenSubdiv_Converter *converter)
{
ConvDMStorage *user_data = converter->user_data;
if (user_data->uvs != NULL) {
MEM_freeN(user_data->uvs);
}
if (user_data->face_uvs != NULL) {
MEM_freeN(user_data->face_uvs);
}
#ifdef USE_MESH_ELEMENT_MAPPING
MEM_freeN(user_data->vert_edge_map);
MEM_freeN(user_data->vert_edge_mem);
@ -330,6 +431,8 @@ void ccgSubSurf_converter_setup_from_derivedmesh(
converter->get_type = conv_dm_get_type;
converter->get_subdiv_uvs = conv_dm_get_subdiv_uvs;
converter->get_num_faces = conv_dm_get_num_faces;
converter->get_num_edges = conv_dm_get_num_edges;
converter->get_num_verts = conv_dm_get_num_verts;
@ -348,9 +451,27 @@ void ccgSubSurf_converter_setup_from_derivedmesh(
converter->get_num_vert_faces = conv_dm_get_num_vert_faces;
converter->get_vert_faces = conv_dm_get_vert_faces;
converter->get_num_uv_layers = conv_dm_get_num_uv_layers;
converter->precalc_uv_layer = conv_dm_precalc_uv_layer;
converter->finish_uv_layer = conv_dm_finish_uv_layer;
converter->get_num_uvs = conv_dm_get_num_uvs;
converter->get_uvs = conv_dm_get_uvs;
converter->get_face_corner_uv_index = conv_dm_get_face_corner_uv_index;
user_data = MEM_mallocN(sizeof(ConvDMStorage), __func__);
user_data->ss = ss;
user_data->dm = dm;
user_data->mvert = dm->getVertArray(dm);
user_data->medge = dm->getEdgeArray(dm);
user_data->mloop = dm->getLoopArray(dm);
user_data->mpoly = dm->getPolyArray(dm);
memset(&user_data->island_store, 0, sizeof(user_data->island_store));
user_data->uvs = NULL;
user_data->face_uvs = NULL;
converter->free_user_data = conv_dm_free_user_data;
converter->user_data = user_data;
@ -405,6 +526,13 @@ static OpenSubdiv_SchemeType conv_ccg_get_bilinear_type(
}
}
static bool conv_ccg_get_subdiv_uvs(
const OpenSubdiv_Converter *converter)
{
CCGSubSurf *ss = converter->user_data;
return (ss->osd_subdiv_uvs);
}
static int conv_ccg_get_num_faces(const OpenSubdiv_Converter *converter)
{
CCGSubSurf *ss = converter->user_data;
@ -548,11 +676,44 @@ static void conv_ccg_get_vert_faces(const OpenSubdiv_Converter *converter,
}
}
static int conv_ccg_get_num_uv_layers(const OpenSubdiv_Converter *UNUSED(converter))
{
return 0;
}
static void conv_ccg_precalc_uv_layer(const OpenSubdiv_Converter * UNUSED(converter),
int UNUSED(layer))
{
}
static void conv_ccg_finish_uv_layer(const OpenSubdiv_Converter *UNUSED(converter))
{
}
static int conv_ccg_get_num_uvs(const OpenSubdiv_Converter *UNUSED(converter))
{
return 0;
}
static void conv_ccg_get_uvs(const OpenSubdiv_Converter * UNUSED(converter),
float *UNUSED(uvs))
{
}
static int conv_ccg_get_face_corner_uv_index(const OpenSubdiv_Converter *UNUSED(converter),
int UNUSED(face),
int UNUSED(corner_))
{
return 0;
}
void ccgSubSurf_converter_setup_from_ccg(CCGSubSurf *ss,
OpenSubdiv_Converter *converter)
{
converter->get_type = conv_ccg_get_bilinear_type;
converter->get_subdiv_uvs = conv_ccg_get_subdiv_uvs;
converter->get_num_faces = conv_ccg_get_num_faces;
converter->get_num_edges = conv_ccg_get_num_edges;
converter->get_num_verts = conv_ccg_get_num_verts;
@ -571,6 +732,13 @@ void ccgSubSurf_converter_setup_from_ccg(CCGSubSurf *ss,
converter->get_num_vert_faces = conv_ccg_get_num_vert_faces;
converter->get_vert_faces = conv_ccg_get_vert_faces;
converter->get_num_uv_layers = conv_ccg_get_num_uv_layers;
converter->precalc_uv_layer = conv_ccg_precalc_uv_layer;
converter->finish_uv_layer = conv_ccg_finish_uv_layer;
converter->get_num_uvs = conv_ccg_get_num_uvs;
converter->get_uvs = conv_ccg_get_uvs;
converter->get_face_corner_uv_index = conv_ccg_get_face_corner_uv_index;
converter->free_user_data = NULL;
converter->user_data = ss;
}

View File

@ -95,34 +95,9 @@ bAction *add_empty_action(Main *bmain, const char name[])
/* .................................. */
// does copy_fcurve...
void BKE_action_make_local(Main *bmain, bAction *act, const bool force_local)
void BKE_action_make_local(Main *bmain, bAction *act, const bool lib_local)
{
bool is_local = false, is_lib = false;
/* - only lib users: do nothing (unless force_local is set)
* - only local users: set flag
* - mixed: make copy
*/
if (!ID_IS_LINKED_DATABLOCK(act)) {
return;
}
BKE_library_ID_test_usages(bmain, act, &is_local, &is_lib);
if (force_local || is_local) {
if (!is_lib) {
id_clear_lib_data(bmain, &act->id);
BKE_id_expand_local(&act->id);
}
else {
bAction *act_new = BKE_action_copy(bmain, act);
act_new->id.us = 0;
BKE_libblock_remap(bmain, act, act_new, ID_REMAP_SKIP_INDIRECT_USAGE);
}
}
BKE_id_make_local_generic(bmain, &act->id, true, lib_local);
}
/* .................................. */

View File

@ -144,34 +144,9 @@ void BKE_armature_free(bArmature *arm)
}
}
void BKE_armature_make_local(Main *bmain, bArmature *arm, const bool force_local)
void BKE_armature_make_local(Main *bmain, bArmature *arm, const bool lib_local)
{
bool is_local = false, is_lib = false;
/* - only lib users: do nothing (unless force_local is set)
* - only local users: set flag
* - mixed: make copy
*/
if (!ID_IS_LINKED_DATABLOCK(arm)) {
return;
}
BKE_library_ID_test_usages(bmain, arm, &is_local, &is_lib);
if (force_local || is_local) {
if (!is_lib) {
id_clear_lib_data(bmain, &arm->id);
BKE_id_expand_local(&arm->id);
}
else {
bArmature *arm_new = BKE_armature_copy(bmain, arm);
arm_new->id.us = 0;
BKE_libblock_remap(bmain, arm, arm_new, ID_REMAP_SKIP_INDIRECT_USAGE);
}
}
BKE_id_make_local_generic(bmain, &arm->id, true, lib_local);
}
static void copy_bonechildren(Bone *newBone, Bone *oldBone, Bone *actBone, Bone **newActBone)
@ -1931,6 +1906,17 @@ static int rebuild_pose_bone(bPose *pose, Bone *bone, bPoseChannel *parchan, int
return counter;
}
/**
* Clear pointers of object's pose (needed in remap case, since we cannot always wait for a complete pose rebuild).
*/
void BKE_pose_clear_pointers(bPose *pose)
{
for (bPoseChannel *pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
pchan->bone = NULL;
pchan->child = NULL;
}
}
/* only after leave editmode, duplicating, validating older files, library syncing */
/* NOTE: pose->flag is set for it */
void BKE_pose_rebuild(Object *ob, bArmature *arm)
@ -1951,10 +1937,7 @@ void BKE_pose_rebuild(Object *ob, bArmature *arm)
pose = ob->pose;
/* clear */
for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
pchan->bone = NULL;
pchan->child = NULL;
}
BKE_pose_clear_pointers(pose);
/* first step, check if all channels are there */
for (bone = arm->bonebase.first; bone; bone = bone->next) {

View File

@ -219,7 +219,7 @@ void BKE_brush_free(Brush *brush)
BKE_previewimg_free(&(brush->preview));
}
void BKE_brush_make_local(Main *bmain, Brush *brush, const bool force_local)
void BKE_brush_make_local(Main *bmain, Brush *brush, const bool lib_local)
{
bool is_local = false, is_lib = false;
@ -239,7 +239,7 @@ void BKE_brush_make_local(Main *bmain, Brush *brush, const bool force_local)
BKE_library_ID_test_usages(bmain, brush, &is_local, &is_lib);
if (force_local || is_local) {
if (lib_local || is_local) {
if (!is_lib) {
id_clear_lib_data(bmain, &brush->id);
BKE_id_expand_local(&brush->id);
@ -252,7 +252,9 @@ void BKE_brush_make_local(Main *bmain, Brush *brush, const bool force_local)
brush_new->id.us = 0;
BKE_libblock_remap(bmain, brush, brush_new, ID_REMAP_SKIP_INDIRECT_USAGE);
if (!lib_local) {
BKE_libblock_remap(bmain, brush, brush_new, ID_REMAP_SKIP_INDIRECT_USAGE);
}
}
}
}

View File

@ -78,8 +78,8 @@ void BKE_camera_init(Camera *cam)
/* stereoscopy 3d */
cam->stereo.interocular_distance = 0.065f;
cam->stereo.convergence_distance = 30.f * 0.065f;
cam->stereo.pole_merge_angle_from = DEG2RAD(60.0f);
cam->stereo.pole_merge_angle_to = DEG2RAD(75.0f);
cam->stereo.pole_merge_angle_from = DEG2RADF(60.0f);
cam->stereo.pole_merge_angle_to = DEG2RADF(75.0f);
}
void *BKE_camera_add(Main *bmain, const char *name)
@ -107,34 +107,9 @@ Camera *BKE_camera_copy(Main *bmain, Camera *cam)
return camn;
}
void BKE_camera_make_local(Main *bmain, Camera *cam, const bool force_local)
void BKE_camera_make_local(Main *bmain, Camera *cam, const bool lib_local)
{
bool is_local = false, is_lib = false;
/* - only lib users: do nothing (unless force_local is set)
* - only local users: set flag
* - mixed: make copy
*/
if (!ID_IS_LINKED_DATABLOCK(cam)) {
return;
}
BKE_library_ID_test_usages(bmain, cam, &is_local, &is_lib);
if (force_local || is_local) {
if (!is_lib) {
id_clear_lib_data(bmain, &cam->id);
BKE_id_expand_local(&cam->id);
}
else {
Camera *cam_new = BKE_camera_copy(bmain, cam);
cam_new->id.us = 0;
BKE_libblock_remap(bmain, cam, cam_new, ID_REMAP_SKIP_INDIRECT_USAGE);
}
}
BKE_id_make_local_generic(bmain, &cam->id, true, lib_local);
}
/** Free (or release) any data used by this camera (does not free the camera itself). */

View File

@ -982,6 +982,7 @@ static void save_sample_line(Scopes *scopes, const int idx, const float fx, cons
/* waveform */
switch (scopes->wavefrm_mode) {
case SCOPES_WAVEFRM_RGB:
case SCOPES_WAVEFRM_RGB_PARADE:
scopes->waveform_1[idx + 0] = fx;
scopes->waveform_1[idx + 1] = rgb[0];
scopes->waveform_2[idx + 0] = fx;
@ -1265,6 +1266,8 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings *
switch (scopes->wavefrm_mode) {
case SCOPES_WAVEFRM_RGB:
/* fall-through */
case SCOPES_WAVEFRM_RGB_PARADE:
ycc_mode = -1;
break;
case SCOPES_WAVEFRM_LUMA:

View File

@ -215,34 +215,9 @@ Curve *BKE_curve_copy(Main *bmain, Curve *cu)
return cun;
}
void BKE_curve_make_local(Main *bmain, Curve *cu, const bool force_local)
void BKE_curve_make_local(Main *bmain, Curve *cu, const bool lib_local)
{
bool is_local = false, is_lib = false;
/* - only lib users: do nothing (unless force_local is set)
* - when there are only local users: set flag
* - mixed: do a copy
*/
if (!ID_IS_LINKED_DATABLOCK(cu)) {
return;
}
BKE_library_ID_test_usages(bmain, cu, &is_local, &is_lib);
if (force_local || is_local) {
if (!is_lib) {
id_clear_lib_data(bmain, &cu->id);
BKE_id_expand_local(&cu->id);
}
else {
Curve *cu_new = BKE_curve_copy(bmain, cu);
cu_new->id.us = 0;
BKE_libblock_remap(bmain, cu, cu_new, ID_REMAP_SKIP_INDIRECT_USAGE);
}
}
BKE_id_make_local_generic(bmain, &cu->id, true, lib_local);
}
/* Get list of nurbs from editnurbs structure */

View File

@ -356,7 +356,7 @@ static MeshRemapIslandsCalc data_transfer_get_loop_islands_generator(const int c
{
switch (cddata_type) {
case CD_FAKE_UV:
return BKE_mesh_calc_islands_loop_poly_uv;
return BKE_mesh_calc_islands_loop_poly_edgeseam;
default:
break;
}

View File

@ -4161,7 +4161,7 @@ static void dynamicPaint_doSmudge(DynamicPaintSurface *surface, DynamicPaintBrus
CLAMP_MIN(max_velocity, vel);
}
steps = (int)ceil(max_velocity / bData->average_dist * timescale);
steps = (int)ceil((double)max_velocity / bData->average_dist * (double)timescale);
CLAMP(steps, 0, 12);
eff_scale = brush->smudge_strength / (float)steps * timescale;
@ -4312,7 +4312,7 @@ static int dynamicPaint_prepareEffectStep(
/* calculate average values (single thread) */
for (int index = 0; index < sData->total_points; index++) {
average_force += (*force)[index * 4 + 3];
average_force += (double)(*force)[index * 4 + 3];
}
average_force /= sData->total_points;
}
@ -4329,7 +4329,7 @@ static int dynamicPaint_prepareEffectStep(
shrink_speed = surface->shrink_speed;
fastest_effect = max_fff(spread_speed, shrink_speed, average_force);
avg_dist = bData->average_dist * CANVAS_REL_SIZE / getSurfaceDimension(sData);
avg_dist = bData->average_dist * (double)CANVAS_REL_SIZE / (double)getSurfaceDimension(sData);
steps = (int)ceilf(1.5f * EFF_MOVEMENT_PER_FRAME * fastest_effect / avg_dist * timescale);
CLAMP(steps, 1, 20);
@ -4687,7 +4687,8 @@ static void dynamicPaint_doWaveStep(DynamicPaintSurface *surface, float timescal
const float wave_scale = CANVAS_REL_SIZE / canvas_size;
/* allocate memory */
PaintWavePoint *prevPoint = MEM_mallocN(sData->total_points * sizeof(PaintWavePoint), "Temp previous points for wave simulation");
PaintWavePoint *prevPoint = MEM_mallocN(
sData->total_points * sizeof(PaintWavePoint), __func__);
if (!prevPoint)
return;
@ -4697,13 +4698,14 @@ static void dynamicPaint_doWaveStep(DynamicPaintSurface *surface, float timescal
int numOfNeighs = sData->adj_data->n_num[index];
for (i = 0; i < numOfNeighs; i++) {
average_dist += bNeighs[sData->adj_data->n_index[index] + i].dist;
average_dist += (double)bNeighs[sData->adj_data->n_index[index] + i].dist;
}
}
average_dist *= wave_scale / sData->adj_data->total_targets;
average_dist *= (double)wave_scale / sData->adj_data->total_targets;
/* determine number of required steps */
steps = (int)ceil((WAVE_TIME_FAC * timescale * surface->wave_timescale) / (average_dist / wave_speed / 3));
steps = (int)ceil((double)(WAVE_TIME_FAC * timescale * surface->wave_timescale) /
(average_dist / (double)wave_speed / 3));
CLAMP(steps, 1, 20);
timescale /= steps;

View File

@ -309,6 +309,11 @@ VFont *BKE_vfont_load_exists(struct Main *bmain, const char *filepath)
return BKE_vfont_load_exists_ex(bmain, filepath, NULL);
}
void BKE_vfont_make_local(Main *bmain, VFont *vfont, const bool lib_local)
{
BKE_id_make_local_generic(bmain, &vfont->id, true, lib_local);
}
static VFont *which_vfont(Curve *cu, CharInfo *info)
{
switch (info->flag & (CU_CHINFO_BOLD | CU_CHINFO_ITALIC)) {

View File

@ -390,6 +390,11 @@ bGPdata *gpencil_data_duplicate(Main *bmain, bGPdata *src, bool internal_copy)
return dst;
}
void BKE_gpencil_make_local(Main *bmain, bGPdata *gpd, const bool lib_local)
{
BKE_id_make_local_generic(bmain, &gpd->id, true, lib_local);
}
/* -------- GP-Stroke API --------- */
/* ensure selection status of stroke is in sync with its points */

View File

@ -104,6 +104,11 @@ Group *BKE_group_copy(Main *bmain, Group *group)
return groupn;
}
void BKE_group_make_local(Main *bmain, Group *group, const bool lib_local)
{
BKE_id_make_local_generic(bmain, &group->id, true, lib_local);
}
/* external */
static bool group_object_add_internal(Group *group, Object *ob)
{

View File

@ -221,6 +221,24 @@ PreviewImage *BKE_previewimg_copy(PreviewImage *prv)
return prv_img;
}
/** Duplicate preview image from \a id and clear icon_id, to be used by datablock copy functions. */
void BKE_previewimg_id_copy(ID *new_id, ID *old_id)
{
PreviewImage **old_prv_p = BKE_previewimg_id_get_p(old_id);
PreviewImage **new_prv_p = BKE_previewimg_id_get_p(new_id);
if (old_prv_p && *old_prv_p) {
BLI_assert(new_prv_p != NULL && ELEM(*new_prv_p, NULL, *old_prv_p));
// const int new_icon_id = get_next_free_id();
// if (new_icon_id == 0) {
// return; /* Failure. */
// }
*new_prv_p = BKE_previewimg_copy(*old_prv_p);
new_id->icon_id = (*new_prv_p)->icon_id = 0;
}
}
PreviewImage **BKE_previewimg_id_get_p(ID *id)
{
switch (GS(id->name)) {

View File

@ -456,10 +456,11 @@ Image *BKE_image_copy(Main *bmain, Image *ima)
copy_image_packedfiles(&nima->packedfiles, &ima->packedfiles);
nima->stereo3d_format = MEM_dupallocN(ima->stereo3d_format);
/* nima->stere3d_format is already allocated by image_alloc... */
*nima->stereo3d_format = *ima->stereo3d_format;
BLI_duplicatelist(&nima->views, &ima->views);
nima->preview = BKE_previewimg_copy(ima->preview);
BKE_previewimg_id_copy(&nima->id, &ima->id);
if (ID_IS_LINKED_DATABLOCK(ima)) {
BKE_id_expand_local(&nima->id);
@ -469,34 +470,9 @@ Image *BKE_image_copy(Main *bmain, Image *ima)
return nima;
}
void BKE_image_make_local(Main *bmain, Image *ima, const bool force_local)
void BKE_image_make_local(Main *bmain, Image *ima, const bool lib_local)
{
bool is_local = false, is_lib = false;
/* - only lib users: do nothing (unless force_local is set)
* - only local users: set flag
* - mixed: make copy
*/
if (!ID_IS_LINKED_DATABLOCK(ima)) {
return;
}
BKE_library_ID_test_usages(bmain, ima, &is_local, &is_lib);
if (force_local || is_local) {
if (!is_lib) {
id_clear_lib_data(bmain, &ima->id);
BKE_id_expand_local(&ima->id);
}
else {
Image *ima_new = BKE_image_copy(bmain, ima);
ima_new->id.us = 0;
BKE_libblock_remap(bmain, ima, ima_new, ID_REMAP_SKIP_INDIRECT_USAGE);
}
}
BKE_id_make_local_generic(bmain, &ima->id, true, lib_local);
}
void BKE_image_merge(Image *dest, Image *source)
@ -1083,39 +1059,48 @@ int BKE_image_imtype_to_ftype(const char imtype, ImbFormatOptions *r_options)
{
memset(r_options, 0, sizeof(*r_options));
if (imtype == R_IMF_IMTYPE_TARGA)
if (imtype == R_IMF_IMTYPE_TARGA) {
return IMB_FTYPE_TGA;
}
else if (imtype == R_IMF_IMTYPE_RAWTGA) {
r_options->flag = RAWTGA;
return IMB_FTYPE_TGA;
}
else if (imtype == R_IMF_IMTYPE_IRIS)
else if (imtype == R_IMF_IMTYPE_IRIS) {
return IMB_FTYPE_IMAGIC;
}
#ifdef WITH_HDR
else if (imtype == R_IMF_IMTYPE_RADHDR)
else if (imtype == R_IMF_IMTYPE_RADHDR) {
return IMB_FTYPE_RADHDR;
}
#endif
else if (imtype == R_IMF_IMTYPE_PNG) {
r_options->quality = 15;
return IMB_FTYPE_PNG;
}
#ifdef WITH_DDS
else if (imtype == R_IMF_IMTYPE_DDS)
else if (imtype == R_IMF_IMTYPE_DDS) {
return IMB_FTYPE_DDS;
}
#endif
else if (imtype == R_IMF_IMTYPE_BMP)
else if (imtype == R_IMF_IMTYPE_BMP) {
return IMB_FTYPE_BMP;
}
#ifdef WITH_TIFF
else if (imtype == R_IMF_IMTYPE_TIFF)
else if (imtype == R_IMF_IMTYPE_TIFF) {
return IMB_FTYPE_TIF;
}
#endif
else if (imtype == R_IMF_IMTYPE_OPENEXR || imtype == R_IMF_IMTYPE_MULTILAYER)
else if (imtype == R_IMF_IMTYPE_OPENEXR || imtype == R_IMF_IMTYPE_MULTILAYER) {
return IMB_FTYPE_OPENEXR;
}
#ifdef WITH_CINEON
else if (imtype == R_IMF_IMTYPE_CINEON)
else if (imtype == R_IMF_IMTYPE_CINEON) {
return IMB_FTYPE_CINEON;
else if (imtype == R_IMF_IMTYPE_DPX)
}
else if (imtype == R_IMF_IMTYPE_DPX) {
return IMB_FTYPE_DPX;
}
#endif
#ifdef WITH_OPENJPEG
else if (imtype == R_IMF_IMTYPE_JP2) {
@ -1132,46 +1117,60 @@ int BKE_image_imtype_to_ftype(const char imtype, ImbFormatOptions *r_options)
char BKE_image_ftype_to_imtype(const int ftype, const ImbFormatOptions *options)
{
if (ftype == 0)
if (ftype == 0) {
return R_IMF_IMTYPE_TARGA;
else if (ftype == IMB_FTYPE_IMAGIC)
}
else if (ftype == IMB_FTYPE_IMAGIC) {
return R_IMF_IMTYPE_IRIS;
}
#ifdef WITH_HDR
else if (ftype == IMB_FTYPE_RADHDR)
else if (ftype == IMB_FTYPE_RADHDR) {
return R_IMF_IMTYPE_RADHDR;
}
#endif
else if (ftype == IMB_FTYPE_PNG)
else if (ftype == IMB_FTYPE_PNG) {
return R_IMF_IMTYPE_PNG;
}
#ifdef WITH_DDS
else if (ftype == IMB_FTYPE_DDS)
else if (ftype == IMB_FTYPE_DDS) {
return R_IMF_IMTYPE_DDS;
}
#endif
else if (ftype == IMB_FTYPE_BMP)
else if (ftype == IMB_FTYPE_BMP) {
return R_IMF_IMTYPE_BMP;
}
#ifdef WITH_TIFF
else if (ftype == IMB_FTYPE_TIF)
else if (ftype == IMB_FTYPE_TIF) {
return R_IMF_IMTYPE_TIFF;
}
#endif
else if (ftype == IMB_FTYPE_OPENEXR)
else if (ftype == IMB_FTYPE_OPENEXR) {
return R_IMF_IMTYPE_OPENEXR;
}
#ifdef WITH_CINEON
else if (ftype == IMB_FTYPE_CINEON)
else if (ftype == IMB_FTYPE_CINEON) {
return R_IMF_IMTYPE_CINEON;
else if (ftype == IMB_FTYPE_DPX)
}
else if (ftype == IMB_FTYPE_DPX) {
return R_IMF_IMTYPE_DPX;
}
#endif
else if (ftype == IMB_FTYPE_TGA) {
if (options && (options->flag & RAWTGA))
if (options && (options->flag & RAWTGA)) {
return R_IMF_IMTYPE_RAWTGA;
else
}
else {
return R_IMF_IMTYPE_TARGA;
}
}
#ifdef WITH_OPENJPEG
else if (ftype == IMB_FTYPE_JP2)
else if (ftype == IMB_FTYPE_JP2) {
return R_IMF_IMTYPE_JP2;
}
#endif
else
else {
return R_IMF_IMTYPE_JPEG90;
}
}

Some files were not shown because too many files have changed in this diff Show More