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:
commit
b1532493c2
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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}")
|
||||
|
|
|
@ -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 */
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
@ -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)
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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__ */
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -530,7 +530,7 @@ typedef struct {
|
|||
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef long GHOST_TEmbedderWindowID;
|
||||
typedef void* GHOST_TEmbedderWindowID;
|
||||
#endif // _WIN32
|
||||
|
||||
#ifndef _WIN32
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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_;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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? */
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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__ */
|
|
@ -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",
|
||||
}
|
||||
|
|
|
@ -565,7 +565,9 @@ class SpellChecker:
|
|||
"ui",
|
||||
"unix",
|
||||
"vbo", "vbos",
|
||||
"wxyz",
|
||||
"ycc", "ycca",
|
||||
"yrgb",
|
||||
"yuv", "yuva",
|
||||
|
||||
# Blender acronyms
|
||||
|
|
|
@ -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
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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__
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 ----------------- */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/* .................................. */
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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). */
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue