Merged changes in the trunk up to revision 26260.

This commit is contained in:
2010-01-25 21:06:08 +00:00
345 changed files with 33456 additions and 21350 deletions

View File

@@ -248,7 +248,7 @@ IF(UNIX AND NOT APPLE)
SET(PLATFORM_LINKFLAGS "-pthread") SET(PLATFORM_LINKFLAGS "-pthread")
# Better warnings # Better warnings
SET(C_WARNINGS "-Wall -Wno-char-subscripts -Wpointer-arith -Wcast-align -Wdeclaration-after-statement") SET(C_WARNINGS "-Wall -Wno-char-subscripts -Wpointer-arith -Wcast-align -Wdeclaration-after-statement -Wno-unknown-pragmas")
SET(CXX_WARNINGS "-Wall -Wno-invalid-offsetof -Wno-sign-compare") SET(CXX_WARNINGS "-Wall -Wno-invalid-offsetof -Wno-sign-compare")
INCLUDE_DIRECTORIES(${JPEG_INCLUDE_DIR} ${PNG_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} ) INCLUDE_DIRECTORIES(${JPEG_INCLUDE_DIR} ${PNG_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} )
@@ -601,7 +601,7 @@ IF(APPLE)
ENDIF(CMAKE_OSX_ARCHITECTURES MATCHES "i386") ENDIF(CMAKE_OSX_ARCHITECTURES MATCHES "i386")
# Better warnings # Better warnings
SET(C_WARNINGS "-Wall -Wno-char-subscripts -Wpointer-arith -Wcast-align -Wdeclaration-after-statement") SET(C_WARNINGS "-Wall -Wno-char-subscripts -Wpointer-arith -Wcast-align -Wdeclaration-after-statement -Wno-unknown-pragmas")
SET(CXX_WARNINGS "-Wall -Wno-invalid-offsetof -Wno-sign-compare") SET(CXX_WARNINGS "-Wall -Wno-invalid-offsetof -Wno-sign-compare")
ENDIF(APPLE) ENDIF(APPLE)

225
config/aix4-config.py Normal file
View File

@@ -0,0 +1,225 @@
import os
LCGDIR = os.getcwd()+"/../lib/aix-4.3-ppc"
LIBDIR = LCGDIR
print LCGDIR
WITH_BF_VERSE = 'false'
BF_VERSE_INCLUDE = "#extern/verse/dist"
BF_PYTHON = LCGDIR+'/python'
BF_PYTHON_VERSION = '3.1'
WITH_BF_STATICPYTHON = 'true'
BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}'
BF_PYTHON_BINARY = '${BF_PYTHON}/bin/python${BF_PYTHON_VERSION}'
BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}' #BF_PYTHON+'/lib/python'+BF_PYTHON_VERSION+'/config/libpython'+BF_PYTHON_VERSION+'.a'
BF_PYTHON_LINKFLAGS = ['-Xlinker', '-export-dynamic']
BF_PYTHON_LIB_STATIC = '${BF_PYTHON}/lib/python2.5/config/libpython${BF_PYTHON_VERSION}.a'
WITH_BF_OPENAL = 'false'
WITH_BF_STATICOPENAL = 'false'
BF_OPENAL = LCGDIR+'/openal'
BF_OPENAL_INC = '${BF_OPENAL}/include'
BF_OPENAL_LIB = 'openal'
BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a'
BF_OPENAL_LIBPATH = LIBDIR + '/lib'
BF_CXX = '/usr'
WITH_BF_STATICCXX = 'false'
BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a'
WITH_BF_SDL = 'false'
BF_SDL = LCGDIR+'/sdl' #$(shell sdl-config --prefix)
BF_SDL_INC = '${BF_SDL}/include/SDL' #$(shell $(BF_SDL)/bin/sdl-config --cflags)
BF_SDL_LIB = 'SDL audio iconv charset' #BF_SDL #$(shell $(BF_SDL)/bin/sdl-config --libs) -lSDL_mixer
BF_SDL_LIBPATH = '${BF_SDL}/lib'
WITH_BF_OPENEXR = 'false'
WITH_BF_STATICOPENEXR = 'false'
BF_OPENEXR = '/usr'
# when compiling with your own openexr lib you might need to set...
# BF_OPENEXR_INC = '${BF_OPENEXR}/include/OpenEXR ${BF_OPENEXR}/include'
BF_OPENEXR_INC = '${BF_OPENEXR}/include/OpenEXR'
BF_OPENEXR_LIB = 'Half IlmImf Iex Imath '
BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a'
# BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib'
WITH_BF_DDS = 'false'
WITH_BF_JPEG = 'false'
BF_JPEG = LCGDIR+'/jpeg'
BF_JPEG_INC = '${BF_JPEG}/include'
BF_JPEG_LIB = 'jpeg'
BF_JPEG_LIBPATH = '${BF_JPEG}/lib'
WITH_BF_PNG = 'false'
BF_PNG = LCGDIR+"/png"
BF_PNG_INC = '${BF_PNG}/include'
BF_PNG_LIB = 'png'
BF_PNG_LIBPATH = '${BF_PNG}/lib'
BF_TIFF = '/usr/nekoware'
BF_TIFF_INC = '${BF_TIFF}/include'
WITH_BF_ZLIB = 'true'
BF_ZLIB = LCGDIR+"/zlib"
BF_ZLIB_INC = '${BF_ZLIB}/include'
BF_ZLIB_LIB = 'z'
BF_ZLIB_LIBPATH = '${BF_ZLIB}/lib'
WITH_BF_INTERNATIONAL = 'false'
BF_GETTEXT = LCGDIR+'/gettext'
BF_GETTEXT_INC = '${BF_GETTEXT}/include'
BF_GETTEXT_LIB = 'gettextpo intl'
BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
WITH_BF_FTGL = 'false'
BF_FTGL = '#extern/bFTGL'
BF_FTGL_INC = '${BF_FTGL}/include'
BF_FTGL_LIB = 'extern_ftgl'
WITH_BF_GAMEENGINE='false'
WITH_BF_ODE = 'false'
BF_ODE = LIBDIR + '/ode'
BF_ODE_INC = BF_ODE + '/include'
BF_ODE_LIB = BF_ODE + '/lib/libode.a'
WITH_BF_BULLET = 'true'
BF_BULLET = '#extern/bullet2/src'
BF_BULLET_INC = '${BF_BULLET}'
BF_BULLET_LIB = 'extern_bullet'
BF_SOLID = '#extern/solid'
BF_SOLID_INC = '${BF_SOLID}'
BF_SOLID_LIB = 'extern_solid'
WITH_BF_YAFRAY = 'true'
#WITH_BF_NSPR = 'true'
#BF_NSPR = $(LIBDIR)/nspr
#BF_NSPR_INC = -I$(BF_NSPR)/include -I$(BF_NSPR)/include/nspr
#BF_NSPR_LIB =
# Uncomment the following line to use Mozilla inplace of netscape
#CPPFLAGS += -DMOZ_NOT_NET
# Location of MOZILLA/Netscape header files...
#BF_MOZILLA = $(LIBDIR)/mozilla
#BF_MOZILLA_INC = -I$(BF_MOZILLA)/include/mozilla/nspr -I$(BF_MOZILLA)/include/mozilla -I$(BF_MOZILLA)/include/mozilla/xpcom -I$(BF_MOZILLA)/include/mozilla/idl
#BF_MOZILLA_LIB =
# Will fall back to look in BF_MOZILLA_INC/nspr and BF_MOZILLA_LIB
# if this is not set.
#
# Be paranoid regarding library creation (do not update archives)
#BF_PARANOID = 'true'
# enable freetype2 support for text objects
BF_FREETYPE = LCGDIR+'/freetype'
BF_FREETYPE_INC = '${BF_FREETYPE}/include ${BF_FREETYPE}/include/freetype2'
BF_FREETYPE_LIB = 'freetype'
BF_FREETYPE_LIBPATH = '${BF_FREETYPE}/lib'
WITH_BF_QUICKTIME = 'false' # -DWITH_QUICKTIME
BF_QUICKTIME = '/usr/local'
BF_QUICKTIME_INC = '${BF_QUICKTIME}/include'
WITH_BF_ICONV = 'false'
BF_ICONV = LIBDIR + "/iconv"
BF_ICONV_INC = '${BF_ICONV}/include'
BF_ICONV_LIB = 'iconv charset'
BF_ICONV_LIBPATH = '${BF_ICONV}/lib'
WITH_BF_BINRELOC = 'false'
# enable ffmpeg support
WITH_BF_FFMPEG = 'false' # -DWITH_FFMPEG
# Uncomment the following two lines to use system's ffmpeg
BF_FFMPEG = LCGDIR+'/ffmpeg'
BF_FFMPEG_LIB = 'avformat avcodec swscale avutil avdevice faad faac vorbis x264 ogg mp3lame z'
BF_FFMPEG_INC = '${BF_FFMPEG}/include'
BF_FFMPEG_LIBPATH='${BF_FFMPEG}/lib'
# enable ogg, vorbis and theora in ffmpeg
WITH_BF_OGG = 'false' # -DWITH_OGG
BF_OGG = '/usr'
BF_OGG_INC = '${BF_OGG}/include'
BF_OGG_LIB = 'ogg vorbis theoraenc theoradec'
WITH_BF_OPENJPEG = 'false'
BF_OPENJPEG = '#extern/libopenjpeg'
BF_OPENJPEG_LIB = ''
BF_OPENJPEG_INC = '${BF_OPENJPEG}'
BF_OPENJPEG_LIBPATH='${BF_OPENJPEG}/lib'
WITH_BF_REDCODE = 'false'
BF_REDCODE = '#extern/libredcode'
BF_REDCODE_LIB = ''
BF_REDCODE_INC = '${BF_REDCODE}/include'
BF_REDCODE_LIBPATH='${BF_REDCODE}/lib'
# Mesa Libs should go here if your using them as well....
WITH_BF_STATICOPENGL = 'false'
BF_OPENGL = '/usr'
BF_OPENGL_INC = '${BF_OPENGL}/include'
BF_OPENGL_LIB = 'GL GLU X11 Xi Xext'
BF_OPENGL_LIBPATH = '/usr/X11R6/lib'
BF_OPENGL_LIB_STATIC = '${BF_OPENGL}/libGL.a ${BF_OPENGL}/libGLU.a ${BF_OPENGL}/libXxf86vm.a ${BF_OPENGL}/libX11.a ${BF_OPENGL}/libXi.a ${BF_OPENGL}/libXext.a ${BF_OPENGL}/libXxf86vm.a'
CC = 'gcc'
CXX = 'g++'
CCFLAGS = [ '-pipe', '-funsigned-char', '-fno-strict-aliasing' ]
CPPFLAGS = [ '-DXP_UNIX', '-DWIN32', '-DFREE_WINDOWS' ]
CXXFLAGS = ['-pipe', '-funsigned-char', '-fno-strict-aliasing' ]
REL_CFLAGS = [ '-O2' ]
REL_CCFLAGS = [ '-O2' ]
C_WARN = [ '-Wall' , '-Wno-char-subscripts', '-Wdeclaration-after-statement' ]
CC_WARN = [ '-Wall' ]
##BF_DEPEND = 'true'
##
##AR = ar
##ARFLAGS = ruv
##ARFLAGSQUIET = ru
##
##FIX_STUBS_WARNINGS = -Wno-unused
LLIBS = 'c m dl pthread dmedia movie'
##LOPTS = --dynamic
##DYNLDFLAGS = -shared $(LDFLAGS)
BF_PROFILE_FLAGS = ['-pg','-g']
BF_PROFILE = 'false'
BF_DEBUG = 'false'
BF_DEBUG_FLAGS = '-g'
BF_BUILDDIR = '../build/aix4'
BF_INSTALLDIR='../install/aix4'
BF_DOCDIR='../install/doc'
#Link against pthread
LDIRS = []
LDIRS.append(BF_FREETYPE_LIBPATH)
LDIRS.append(BF_PNG_LIBPATH)
LDIRS.append(BF_ZLIB_LIBPATH)
LDIRS.append(BF_SDL_LIBPATH)
LDIRS.append(BF_OPENAL_LIBPATH)
LDIRS.append(BF_ICONV_LIBPATH)
PLATFORM_LINKFLAGS = []
for x in LDIRS:
PLATFORM_LINKFLAGS.append("-L"+x)
PLATFORM_LINKFLAGS += ['-L${LCGDIR}/jpeg/lib' , '-L/usr/lib32', '-n32', '-v', '-no_prelink']
print PLATFORM_LINKFLAGS
LINKFLAGS= PLATFORM_LINKFLAGS

View File

@@ -4,7 +4,7 @@ LCGDIR = os.getcwd()+"/../lib/irix-6.5-mips"
LIBDIR = LCGDIR LIBDIR = LCGDIR
BF_PYTHON = LCGDIR+'/python' BF_PYTHON = LCGDIR+'/python'
BF_PYTHON_VERSION = '2.5' BF_PYTHON_VERSION = '3.1'
WITH_BF_STATICPYTHON = 'true' WITH_BF_STATICPYTHON = 'true'
BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}' BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}'
BF_PYTHON_BINARY = '${BF_PYTHON}/bin/python${BF_PYTHON_VERSION}' BF_PYTHON_BINARY = '${BF_PYTHON}/bin/python${BF_PYTHON_VERSION}'

View File

@@ -2,7 +2,7 @@ LCGDIR = '#../lib/windows'
LIBDIR = '${LCGDIR}' LIBDIR = '${LCGDIR}'
BF_PYTHON = LIBDIR + '/python' BF_PYTHON = LIBDIR + '/python'
BF_PYTHON_VERSION = '2.5' BF_PYTHON_VERSION = '3.1'
BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}' BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}'
BF_PYTHON_BINARY = 'python' BF_PYTHON_BINARY = 'python'
BF_PYTHON_LIB = 'python25' BF_PYTHON_LIB = 'python25'

View File

@@ -2,7 +2,7 @@ LCGDIR = '../lib/openbsd3'
LIBDIR = '${LCGDIR}' LIBDIR = '${LCGDIR}'
BF_PYTHON = '/usr/local' BF_PYTHON = '/usr/local'
BF_PYTHON_VERSION = '2.5' BF_PYTHON_VERSION = '3.1'
BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}' BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}'
BF_PYTHON_BINARY = '${BF_PYTHON}/bin/python${BF_PYTHON_VERSION}' BF_PYTHON_BINARY = '${BF_PYTHON}/bin/python${BF_PYTHON_VERSION}'
BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}' BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}'

View File

@@ -2,7 +2,7 @@ LCGDIR = '../lib/sunos5'
LIBDIR = '${LCGDIR}' LIBDIR = '${LCGDIR}'
BF_PYTHON = '/usr/local' BF_PYTHON = '/usr/local'
BF_PYTHON_VERSION = '2.5' BF_PYTHON_VERSION = '3.1'
BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}' BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}'
BF_PYTHON_BINARY = '${BF_PYTHON}/bin/python${BF_PYTHON_VERSION}' BF_PYTHON_BINARY = '${BF_PYTHON}/bin/python${BF_PYTHON_VERSION}'
BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}' #BF_PYTHON+'/lib/python'+BF_PYTHON_VERSION+'/config/libpython'+BF_PYTHON_VERSION+'.a' BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}' #BF_PYTHON+'/lib/python'+BF_PYTHON_VERSION+'/config/libpython'+BF_PYTHON_VERSION+'.a'

View File

@@ -20,7 +20,7 @@
# #
# ***** END LGPL LICENSE BLOCK ***** # ***** END LGPL LICENSE BLOCK *****
SET(INC . intern FX SRC ${PTHREADS_INC} ${LIBSAMPLERATE_INC} ${OPENAL_INCLUDE_DIR}) SET(INC . intern FX SRC ${PTHREADS_INC} ${LIBSAMPLERATE_INC})
FILE(GLOB SRC intern/*.cpp intern/*.h FX/*.cpp SRC/*.cpp) FILE(GLOB SRC intern/*.cpp intern/*.h FX/*.cpp SRC/*.cpp)

View File

@@ -284,9 +284,7 @@ AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize)
} }
#endif #endif
m_device = alcOpenDevice("ALSA Software"); m_device = alcOpenDevice(NULL);
if(m_device == NULL)
m_device = alcOpenDevice(NULL);
if(!m_device) if(!m_device)
AUD_THROW(AUD_ERROR_OPENAL); AUD_THROW(AUD_ERROR_OPENAL);

View File

@@ -14,7 +14,7 @@ if window_system == 'darwin':
pf = ['GHOST_DisplayManager', 'GHOST_System', 'GHOST_Window', 'GHOST_DropTarget'] pf = ['GHOST_DisplayManager', 'GHOST_System', 'GHOST_Window', 'GHOST_DropTarget']
defs=['_USE_MATH_DEFINES'] defs=['_USE_MATH_DEFINES']
if window_system in ('linux2', 'openbsd3', 'sunos5', 'freebsd6', 'irix6'): if window_system in ('linux2', 'openbsd3', 'sunos5', 'freebsd6', 'irix6', 'aix4', 'aix5'):
for f in pf: for f in pf:
try: try:
sources.remove('intern' + os.sep + f + 'Win32.cpp') sources.remove('intern' + os.sep + f + 'Win32.cpp')

View File

@@ -35,7 +35,7 @@
#include <X11/cursorfont.h> #include <X11/cursorfont.h>
#include <X11/Xatom.h> #include <X11/Xatom.h>
#if defined(__sun__) || defined( __sun ) || defined (__sparc) || defined (__sparc__) #if defined(__sun__) || defined( __sun ) || defined (__sparc) || defined (__sparc__) || defined (_AIX)
#include <strings.h> #include <strings.h>
#endif #endif
@@ -1435,7 +1435,7 @@ setWindowCursorGrab(
setWindowCursorVisibility(false); setWindowCursorVisibility(false);
} }
XGrabPointer(m_display, m_window, True, ButtonPressMask| ButtonReleaseMask|PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); XGrabPointer(m_display, m_window, False, ButtonPressMask| ButtonReleaseMask|PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
} }
else { else {
if (m_cursorGrab==GHOST_kGrabHide) { if (m_cursorGrab==GHOST_kGrabHide) {

View File

@@ -487,8 +487,10 @@ short MEM_testN(void *vmemh) {
if (membl) membl = MEMNEXT(membl); if (membl) membl = MEMNEXT(membl);
while(membl) { while(membl) {
if (vmemh == membl+1) if (vmemh == membl+1) {
mem_unlock_thread();
return 1; return 1;
}
if(membl->next) if(membl->next)
membl= MEMNEXT(membl->next); membl= MEMNEXT(membl->next);
@@ -628,8 +630,8 @@ static void rem_memblock(MemHead *memh)
mmap_in_use -= memh->len; mmap_in_use -= memh->len;
if (munmap(memh, memh->len + sizeof(MemHead) + sizeof(MemTail))) if (munmap(memh, memh->len + sizeof(MemHead) + sizeof(MemTail)))
printf("Couldn't unmap memory %s\n", memh->name); printf("Couldn't unmap memory %s\n", memh->name);
} }
else { else {
if(malloc_debug_memset && memh->len) if(malloc_debug_memset && memh->len)
memset(memh+1, 255, memh->len); memset(memh+1, 255, memh->len);
free(memh); free(memh);

View File

@@ -0,0 +1,885 @@
#include "EIGENVALUE_HELPER.h"
void Eigentred2(sEigenvalue& eval) {
// This is derived from the Algol procedures tred2 by
// Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
// Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
// Fortran subroutine in EISPACK.
int n=eval.n;
for (int j = 0; j < n; j++) {
eval.d[j] = eval.V[n-1][j];
}
// Householder reduction to tridiagonal form.
for (int i = n-1; i > 0; i--) {
// Scale to avoid under/overflow.
float scale = 0.0;
float h = 0.0;
for (int k = 0; k < i; k++) {
scale = scale + fabs(eval.d[k]);
}
if (scale == 0.0) {
eval.e[i] = eval.d[i-1];
for (int j = 0; j < i; j++) {
eval.d[j] = eval.V[i-1][j];
eval.V[i][j] = 0.0;
eval.V[j][i] = 0.0;
}
} else {
// Generate Householder vector.
for (int k = 0; k < i; k++) {
eval.d[k] /= scale;
h += eval.d[k] * eval.d[k];
}
float f = eval.d[i-1];
float g = sqrt(h);
if (f > 0) {
g = -g;
}
eval.e[i] = scale * g;
h = h - f * g;
eval.d[i-1] = f - g;
for (int j = 0; j < i; j++) {
eval.e[j] = 0.0;
}
// Apply similarity transformation to remaining columns.
for (int j = 0; j < i; j++) {
f = eval.d[j];
eval.V[j][i] = f;
g = eval.e[j] + eval.V[j][j] * f;
for (int k = j+1; k <= i-1; k++) {
g += eval.V[k][j] * eval.d[k];
eval.e[k] += eval.V[k][j] * f;
}
eval.e[j] = g;
}
f = 0.0;
for (int j = 0; j < i; j++) {
eval.e[j] /= h;
f += eval.e[j] * eval.d[j];
}
float hh = f / (h + h);
for (int j = 0; j < i; j++) {
eval.e[j] -= hh * eval.d[j];
}
for (int j = 0; j < i; j++) {
f = eval.d[j];
g = eval.e[j];
for (int k = j; k <= i-1; k++) {
eval.V[k][j] -= (f * eval.e[k] + g * eval.d[k]);
}
eval.d[j] = eval.V[i-1][j];
eval.V[i][j] = 0.0;
}
}
eval.d[i] = h;
}
// Accumulate transformations.
for (int i = 0; i < n-1; i++) {
eval.V[n-1][i] = eval.V[i][i];
eval.V[i][i] = 1.0;
float h = eval.d[i+1];
if (h != 0.0) {
for (int k = 0; k <= i; k++) {
eval.d[k] = eval.V[k][i+1] / h;
}
for (int j = 0; j <= i; j++) {
float g = 0.0;
for (int k = 0; k <= i; k++) {
g += eval.V[k][i+1] * eval.V[k][j];
}
for (int k = 0; k <= i; k++) {
eval.V[k][j] -= g * eval.d[k];
}
}
}
for (int k = 0; k <= i; k++) {
eval.V[k][i+1] = 0.0;
}
}
for (int j = 0; j < n; j++) {
eval.d[j] = eval.V[n-1][j];
eval.V[n-1][j] = 0.0;
}
eval.V[n-1][n-1] = 1.0;
eval.e[0] = 0.0;
}
void Eigencdiv(sEigenvalue& eval, float xr, float xi, float yr, float yi) {
float r,d;
if (fabs(yr) > fabs(yi)) {
r = yi/yr;
d = yr + r*yi;
eval.cdivr = (xr + r*xi)/d;
eval.cdivi = (xi - r*xr)/d;
} else {
r = yr/yi;
d = yi + r*yr;
eval.cdivr = (r*xr + xi)/d;
eval.cdivi = (r*xi - xr)/d;
}
}
void Eigentql2 (sEigenvalue& eval) {
// This is derived from the Algol procedures tql2, by
// Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
// Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
// Fortran subroutine in EISPACK.
int n=eval.n;
for (int i = 1; i < n; i++) {
eval.e[i-1] = eval.e[i];
}
eval.e[n-1] = 0.0;
float f = 0.0;
float tst1 = 0.0;
float eps = pow(2.0,-52.0);
for (int l = 0; l < n; l++) {
// Find small subdiagonal element
tst1 = max(tst1,fabs(eval.d[l]) + fabs(eval.e[l]));
int m = l;
// Original while-loop from Java code
while (m < n) {
if (fabs(eval.e[m]) <= eps*tst1) {
break;
}
m++;
}
// If m == l, d[l] is an eigenvalue,
// otherwise, iterate.
if (m > l) {
int iter = 0;
do {
iter = iter + 1; // (Could check iteration count here.)
// Compute implicit shift
float g = eval.d[l];
float p = (eval.d[l+1] - g) / (2.0 * eval.e[l]);
float r = hypot(p,1.0);
if (p < 0) {
r = -r;
}
eval.d[l] = eval.e[l] / (p + r);
eval.d[l+1] = eval.e[l] * (p + r);
float dl1 = eval.d[l+1];
float h = g - eval.d[l];
for (int i = l+2; i < n; i++) {
eval.d[i] -= h;
}
f = f + h;
// Implicit QL transformation.
p = eval.d[m];
float c = 1.0;
float c2 = c;
float c3 = c;
float el1 = eval.e[l+1];
float s = 0.0;
float s2 = 0.0;
for (int i = m-1; i >= l; i--) {
c3 = c2;
c2 = c;
s2 = s;
g = c * eval.e[i];
h = c * p;
r = hypot(p,eval.e[i]);
eval.e[i+1] = s * r;
s = eval.e[i] / r;
c = p / r;
p = c * eval.d[i] - s * g;
eval.d[i+1] = h + s * (c * g + s * eval.d[i]);
// Accumulate transformation.
for (int k = 0; k < n; k++) {
h = eval.V[k][i+1];
eval.V[k][i+1] = s * eval.V[k][i] + c * h;
eval.V[k][i] = c * eval.V[k][i] - s * h;
}
}
p = -s * s2 * c3 * el1 * eval.e[l] / dl1;
eval.e[l] = s * p;
eval.d[l] = c * p;
// Check for convergence.
} while (fabs(eval.e[l]) > eps*tst1);
}
eval.d[l] = eval.d[l] + f;
eval.e[l] = 0.0;
}
// Sort eigenvalues and corresponding vectors.
for (int i = 0; i < n-1; i++) {
int k = i;
float p = eval.d[i];
for (int j = i+1; j < n; j++) {
if (eval.d[j] < p) {
k = j;
p = eval.d[j];
}
}
if (k != i) {
eval.d[k] = eval.d[i];
eval.d[i] = p;
for (int j = 0; j < n; j++) {
p = eval.V[j][i];
eval.V[j][i] = eval.V[j][k];
eval.V[j][k] = p;
}
}
}
}
void Eigenorthes (sEigenvalue& eval) {
// This is derived from the Algol procedures orthes and ortran,
// by Martin and Wilkinson, Handbook for Auto. Comp.,
// Vol.ii-Linear Algebra, and the corresponding
// Fortran subroutines in EISPACK.
int n=eval.n;
int low = 0;
int high = n-1;
for (int m = low+1; m <= high-1; m++) {
// Scale column.
float scale = 0.0;
for (int i = m; i <= high; i++) {
scale = scale + fabs(eval.H[i][m-1]);
}
if (scale != 0.0) {
// Compute Householder transformation.
float h = 0.0;
for (int i = high; i >= m; i--) {
eval.ort[i] = eval.H[i][m-1]/scale;
h += eval.ort[i] * eval.ort[i];
}
float g = sqrt(h);
if (eval.ort[m] > 0) {
g = -g;
}
h = h - eval.ort[m] * g;
eval.ort[m] = eval.ort[m] - g;
// Apply Householder similarity transformation
// H = (I-u*u'/h)*H*(I-u*u')/h)
for (int j = m; j < n; j++) {
float f = 0.0;
for (int i = high; i >= m; i--) {
f += eval.ort[i]*eval.H[i][j];
}
f = f/h;
for (int i = m; i <= high; i++) {
eval.H[i][j] -= f*eval.ort[i];
}
}
for (int i = 0; i <= high; i++) {
float f = 0.0;
for (int j = high; j >= m; j--) {
f += eval.ort[j]*eval.H[i][j];
}
f = f/h;
for (int j = m; j <= high; j++) {
eval.H[i][j] -= f*eval.ort[j];
}
}
eval.ort[m] = scale*eval.ort[m];
eval.H[m][m-1] = scale*g;
}
}
// Accumulate transformations (Algol's ortran).
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
eval.V[i][j] = (i == j ? 1.0 : 0.0);
}
}
for (int m = high-1; m >= low+1; m--) {
if (eval.H[m][m-1] != 0.0) {
for (int i = m+1; i <= high; i++) {
eval.ort[i] = eval.H[i][m-1];
}
for (int j = m; j <= high; j++) {
float g = 0.0;
for (int i = m; i <= high; i++) {
g += eval.ort[i] * eval.V[i][j];
}
// Double division avoids possible underflow
g = (g / eval.ort[m]) / eval.H[m][m-1];
for (int i = m; i <= high; i++) {
eval.V[i][j] += g * eval.ort[i];
}
}
}
}
}
void Eigenhqr2 (sEigenvalue& eval) {
// This is derived from the Algol procedure hqr2,
// by Martin and Wilkinson, Handbook for Auto. Comp.,
// Vol.ii-Linear Algebra, and the corresponding
// Fortran subroutine in EISPACK.
// Initialize
int nn = eval.n;
int n = nn-1;
int low = 0;
int high = nn-1;
float eps = pow(2.0,-52.0);
float exshift = 0.0;
float p=0,q=0,r=0,s=0,z=0,t,w,x,y;
// Store roots isolated by balanc and compute matrix norm
float norm = 0.0;
for (int i = 0; i < nn; i++) {
if ((i < low) || (i > high)) {
eval.d[i] = eval.H[i][i];
eval.e[i] = 0.0;
}
for (int j = max(i-1,0); j < nn; j++) {
norm = norm + fabs(eval.H[i][j]);
}
}
// Outer loop over eigenvalue index
int iter = 0;
int totIter = 0;
while (n >= low) {
// NT limit no. of iterations
totIter++;
if(totIter>100) {
//if(totIter>15) std::cout<<"!!!!iter ABORT !!!!!!! "<<totIter<<"\n";
// NT hack/fix, return large eigenvalues
for (int i = 0; i < nn; i++) {
eval.d[i] = 10000.;
eval.e[i] = 10000.;
}
return;
}
// Look for single small sub-diagonal element
int l = n;
while (l > low) {
s = fabs(eval.H[l-1][l-1]) + fabs(eval.H[l][l]);
if (s == 0.0) {
s = norm;
}
if (fabs(eval.H[l][l-1]) < eps * s) {
break;
}
l--;
}
// Check for convergence
// One root found
if (l == n) {
eval.H[n][n] = eval.H[n][n] + exshift;
eval.d[n] = eval.H[n][n];
eval.e[n] = 0.0;
n--;
iter = 0;
// Two roots found
} else if (l == n-1) {
w = eval.H[n][n-1] * eval.H[n-1][n];
p = (eval.H[n-1][n-1] - eval.H[n][n]) / 2.0;
q = p * p + w;
z = sqrt(fabs(q));
eval.H[n][n] = eval.H[n][n] + exshift;
eval.H[n-1][n-1] = eval.H[n-1][n-1] + exshift;
x = eval.H[n][n];
// float pair
if (q >= 0) {
if (p >= 0) {
z = p + z;
} else {
z = p - z;
}
eval.d[n-1] = x + z;
eval.d[n] = eval.d[n-1];
if (z != 0.0) {
eval.d[n] = x - w / z;
}
eval.e[n-1] = 0.0;
eval.e[n] = 0.0;
x = eval.H[n][n-1];
s = fabs(x) + fabs(z);
p = x / s;
q = z / s;
r = sqrt(p * p+q * q);
p = p / r;
q = q / r;
// Row modification
for (int j = n-1; j < nn; j++) {
z = eval.H[n-1][j];
eval.H[n-1][j] = q * z + p * eval.H[n][j];
eval.H[n][j] = q * eval.H[n][j] - p * z;
}
// Column modification
for (int i = 0; i <= n; i++) {
z = eval.H[i][n-1];
eval.H[i][n-1] = q * z + p * eval.H[i][n];
eval.H[i][n] = q * eval.H[i][n] - p * z;
}
// Accumulate transformations
for (int i = low; i <= high; i++) {
z = eval.V[i][n-1];
eval.V[i][n-1] = q * z + p * eval.V[i][n];
eval.V[i][n] = q * eval.V[i][n] - p * z;
}
// Complex pair
} else {
eval.d[n-1] = x + p;
eval.d[n] = x + p;
eval.e[n-1] = z;
eval.e[n] = -z;
}
n = n - 2;
iter = 0;
// No convergence yet
} else {
// Form shift
x = eval.H[n][n];
y = 0.0;
w = 0.0;
if (l < n) {
y = eval.H[n-1][n-1];
w = eval.H[n][n-1] * eval.H[n-1][n];
}
// Wilkinson's original ad hoc shift
if (iter == 10) {
exshift += x;
for (int i = low; i <= n; i++) {
eval.H[i][i] -= x;
}
s = fabs(eval.H[n][n-1]) + fabs(eval.H[n-1][n-2]);
x = y = 0.75 * s;
w = -0.4375 * s * s;
}
// MATLAB's new ad hoc shift
if (iter == 30) {
s = (y - x) / 2.0;
s = s * s + w;
if (s > 0) {
s = sqrt(s);
if (y < x) {
s = -s;
}
s = x - w / ((y - x) / 2.0 + s);
for (int i = low; i <= n; i++) {
eval.H[i][i] -= s;
}
exshift += s;
x = y = w = 0.964;
}
}
iter = iter + 1; // (Could check iteration count here.)
// Look for two consecutive small sub-diagonal elements
int m = n-2;
while (m >= l) {
z = eval.H[m][m];
r = x - z;
s = y - z;
p = (r * s - w) / eval.H[m+1][m] + eval.H[m][m+1];
q = eval.H[m+1][m+1] - z - r - s;
r = eval.H[m+2][m+1];
s = fabs(p) + fabs(q) + fabs(r);
p = p / s;
q = q / s;
r = r / s;
if (m == l) {
break;
}
if (fabs(eval.H[m][m-1]) * (fabs(q) + fabs(r)) <
eps * (fabs(p) * (fabs(eval.H[m-1][m-1]) + fabs(z) +
fabs(eval.H[m+1][m+1])))) {
break;
}
m--;
}
for (int i = m+2; i <= n; i++) {
eval.H[i][i-2] = 0.0;
if (i > m+2) {
eval.H[i][i-3] = 0.0;
}
}
// Double QR step involving rows l:n and columns m:n
for (int k = m; k <= n-1; k++) {
int notlast = (k != n-1);
if (k != m) {
p = eval.H[k][k-1];
q = eval.H[k+1][k-1];
r = (notlast ? eval.H[k+2][k-1] : 0.0);
x = fabs(p) + fabs(q) + fabs(r);
if (x != 0.0) {
p = p / x;
q = q / x;
r = r / x;
}
}
if (x == 0.0) {
break;
}
s = sqrt(p * p + q * q + r * r);
if (p < 0) {
s = -s;
}
if (s != 0) {
if (k != m) {
eval.H[k][k-1] = -s * x;
} else if (l != m) {
eval.H[k][k-1] = -eval.H[k][k-1];
}
p = p + s;
x = p / s;
y = q / s;
z = r / s;
q = q / p;
r = r / p;
// Row modification
for (int j = k; j < nn; j++) {
p = eval.H[k][j] + q * eval.H[k+1][j];
if (notlast) {
p = p + r * eval.H[k+2][j];
eval.H[k+2][j] = eval.H[k+2][j] - p * z;
}
eval.H[k][j] = eval.H[k][j] - p * x;
eval.H[k+1][j] = eval.H[k+1][j] - p * y;
}
// Column modification
for (int i = 0; i <= min(n,k+3); i++) {
p = x * eval.H[i][k] + y * eval.H[i][k+1];
if (notlast) {
p = p + z * eval.H[i][k+2];
eval.H[i][k+2] = eval.H[i][k+2] - p * r;
}
eval.H[i][k] = eval.H[i][k] - p;
eval.H[i][k+1] = eval.H[i][k+1] - p * q;
}
// Accumulate transformations
for (int i = low; i <= high; i++) {
p = x * eval.V[i][k] + y * eval.V[i][k+1];
if (notlast) {
p = p + z * eval.V[i][k+2];
eval.V[i][k+2] = eval.V[i][k+2] - p * r;
}
eval.V[i][k] = eval.V[i][k] - p;
eval.V[i][k+1] = eval.V[i][k+1] - p * q;
}
} // (s != 0)
} // k loop
} // check convergence
} // while (n >= low)
//if(totIter>15) std::cout<<"!!!!iter "<<totIter<<"\n";
// Backsubstitute to find vectors of upper triangular form
if (norm == 0.0) {
return;
}
for (n = nn-1; n >= 0; n--) {
p = eval.d[n];
q = eval.e[n];
// float vector
if (q == 0) {
int l = n;
eval.H[n][n] = 1.0;
for (int i = n-1; i >= 0; i--) {
w = eval.H[i][i] - p;
r = 0.0;
for (int j = l; j <= n; j++) {
r = r + eval.H[i][j] * eval.H[j][n];
}
if (eval.e[i] < 0.0) {
z = w;
s = r;
} else {
l = i;
if (eval.e[i] == 0.0) {
if (w != 0.0) {
eval.H[i][n] = -r / w;
} else {
eval.H[i][n] = -r / (eps * norm);
}
// Solve real equations
} else {
x = eval.H[i][i+1];
y = eval.H[i+1][i];
q = (eval.d[i] - p) * (eval.d[i] - p) + eval.e[i] * eval.e[i];
t = (x * s - z * r) / q;
eval.H[i][n] = t;
if (fabs(x) > fabs(z)) {
eval.H[i+1][n] = (-r - w * t) / x;
} else {
eval.H[i+1][n] = (-s - y * t) / z;
}
}
// Overflow control
t = fabs(eval.H[i][n]);
if ((eps * t) * t > 1) {
for (int j = i; j <= n; j++) {
eval.H[j][n] = eval.H[j][n] / t;
}
}
}
}
// Complex vector
} else if (q < 0) {
int l = n-1;
// Last vector component imaginary so matrix is triangular
if (fabs(eval.H[n][n-1]) > fabs(eval.H[n-1][n])) {
eval.H[n-1][n-1] = q / eval.H[n][n-1];
eval.H[n-1][n] = -(eval.H[n][n] - p) / eval.H[n][n-1];
} else {
Eigencdiv(eval, 0.0,-eval.H[n-1][n],eval.H[n-1][n-1]-p,q);
eval.H[n-1][n-1] = eval.cdivr;
eval.H[n-1][n] = eval.cdivi;
}
eval.H[n][n-1] = 0.0;
eval.H[n][n] = 1.0;
for (int i = n-2; i >= 0; i--) {
float ra,sa,vr,vi;
ra = 0.0;
sa = 0.0;
for (int j = l; j <= n; j++) {
ra = ra + eval.H[i][j] * eval.H[j][n-1];
sa = sa + eval.H[i][j] * eval.H[j][n];
}
w = eval.H[i][i] - p;
if (eval.e[i] < 0.0) {
z = w;
r = ra;
s = sa;
} else {
l = i;
if (eval.e[i] == 0) {
Eigencdiv(eval,-ra,-sa,w,q);
eval.H[i][n-1] = eval.cdivr;
eval.H[i][n] = eval.cdivi;
} else {
// Solve complex equations
x = eval.H[i][i+1];
y = eval.H[i+1][i];
vr = (eval.d[i] - p) * (eval.d[i] - p) + eval.e[i] * eval.e[i] - q * q;
vi = (eval.d[i] - p) * 2.0 * q;
if ((vr == 0.0) && (vi == 0.0)) {
vr = eps * norm * (fabs(w) + fabs(q) +
fabs(x) + fabs(y) + fabs(z));
}
Eigencdiv(eval, x*r-z*ra+q*sa,x*s-z*sa-q*ra,vr,vi);
eval.H[i][n-1] = eval.cdivr;
eval.H[i][n] = eval.cdivi;
if (fabs(x) > (fabs(z) + fabs(q))) {
eval.H[i+1][n-1] = (-ra - w * eval.H[i][n-1] + q * eval.H[i][n]) / x;
eval.H[i+1][n] = (-sa - w * eval.H[i][n] - q * eval.H[i][n-1]) / x;
} else {
Eigencdiv(eval, -r-y*eval.H[i][n-1],-s-y*eval.H[i][n],z,q);
eval.H[i+1][n-1] = eval.cdivr;
eval.H[i+1][n] = eval.cdivi;
}
}
// Overflow control
t = max(fabs(eval.H[i][n-1]),fabs(eval.H[i][n]));
if ((eps * t) * t > 1) {
for (int j = i; j <= n; j++) {
eval.H[j][n-1] = eval.H[j][n-1] / t;
eval.H[j][n] = eval.H[j][n] / t;
}
}
}
}
}
}
// Vectors of isolated roots
for (int i = 0; i < nn; i++) {
if (i < low || i > high) {
for (int j = i; j < nn; j++) {
eval.V[i][j] = eval.H[i][j];
}
}
}
// Back transformation to get eigenvectors of original matrix
for (int j = nn-1; j >= low; j--) {
for (int i = low; i <= high; i++) {
z = 0.0;
for (int k = low; k <= min(j,high); k++) {
z = z + eval.V[i][k] * eval.H[k][j];
}
eval.V[i][j] = z;
}
}
}
int computeEigenvalues3x3(
float dout[3],
float a[3][3])
{
/*TNT::Array2D<float> A = TNT::Array2D<float>(3,3, &a[0][0]);
TNT::Array1D<float> eig = TNT::Array1D<float>(3);
TNT::Array1D<float> eigImag = TNT::Array1D<float>(3);
JAMA::Eigenvalue<float> jeig = JAMA::Eigenvalue<float>(A);*/
sEigenvalue jeig;
// Compute the values
{
jeig.n = 3;
int n=3;
//V = Array2D<float>(n,n);
//d = Array1D<float>(n);
//e = Array1D<float>(n);
for (int y=0; y<3; y++)
{
jeig.d[y]=0.0f;
jeig.e[y]=0.0f;
for (int t=0; t<3; t++) jeig.V[y][t]=0.0f;
}
jeig.issymmetric = 1;
for (int j = 0; (j < 3) && jeig.issymmetric; j++) {
for (int i = 0; (i < 3) && jeig.issymmetric; i++) {
jeig.issymmetric = (a[i][j] == a[j][i]);
}
}
if (jeig.issymmetric) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
jeig.V[i][j] = a[i][j];
}
}
// Tridiagonalize.
Eigentred2(jeig);
// Diagonalize.
Eigentql2(jeig);
} else {
//H = TNT::Array2D<float>(n,n);
for (int y=0; y<3; y++)
{
jeig.ort[y]=0.0f;
for (int t=0; t<3; t++) jeig.H[y][t]=0.0f;
}
//ort = TNT::Array1D<float>(n);
for (int j = 0; j < n; j++) {
for (int i = 0; i < n; i++) {
jeig.H[i][j] = a[i][j];
}
}
// Reduce to Hessenberg form.
Eigenorthes(jeig);
// Reduce Hessenberg to real Schur form.
Eigenhqr2(jeig);
}
}
//jeig.getfloatEigenvalues(eig);
// complex ones
//jeig.getImagEigenvalues(eigImag);
dout[0] = sqrt(jeig.d[0]*jeig.d[0] + jeig.e[0]*jeig.e[0]);
dout[1] = sqrt(jeig.d[1]*jeig.d[1] + jeig.e[1]*jeig.e[1]);
dout[2] = sqrt(jeig.d[2]*jeig.d[2] + jeig.e[2]*jeig.e[2]);
return 0;
}

View File

@@ -15,33 +15,60 @@
// along with Wavelet Turbulence. If not, see <http://www.gnu.org/licenses/>. // along with Wavelet Turbulence. If not, see <http://www.gnu.org/licenses/>.
// //
// Copyright 2008 Theodore Kim and Nils Thuerey // Copyright 2008 Theodore Kim and Nils Thuerey
// //
//////////////////////////////////////////////////////////////////////
// Modified to not require TNT matrix library anymore. It was very slow
// when being run in parallel. Required TNT JAMA::Eigenvalue libraries were
// converted into independent functions.
// - MiikaH
//
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// Helper function, compute eigenvalues of 3x3 matrix // Helper function, compute eigenvalues of 3x3 matrix
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
#include "tnt/jama_eig.h" #ifndef EIGENVAL_HELPER_H
#define EIGENVAL_HELPER_H
//#include "tnt/jama_eig.h"
#include <algorithm>
#include <cmath>
using namespace std;
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// eigenvalues of 3x3 non-symmetric matrix // eigenvalues of 3x3 non-symmetric matrix
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
int inline computeEigenvalues3x3(
float dout[3],
float a[3][3]) struct sEigenvalue
{ {
TNT::Array2D<float> A = TNT::Array2D<float>(3,3, &a[0][0]); int n;
TNT::Array1D<float> eig = TNT::Array1D<float>(3); int issymmetric;
TNT::Array1D<float> eigImag = TNT::Array1D<float>(3); float d[3]; /* real part */
JAMA::Eigenvalue<float> jeig = JAMA::Eigenvalue<float>(A); float e[3]; /* img part */
jeig.getRealEigenvalues(eig); float V[3][3]; /* Eigenvectors */
// complex ones float H[3][3];
jeig.getImagEigenvalues(eigImag);
dout[0] = sqrt(eig[0]*eig[0] + eigImag[0]*eigImag[0]);
dout[1] = sqrt(eig[1]*eig[1] + eigImag[1]*eigImag[1]);
dout[2] = sqrt(eig[2]*eig[2] + eigImag[2]*eigImag[2]);
return 0;
}
#undef rfabs float ort[3];
#undef ROT
float cdivr;
float cdivi;
};
void Eigentred2(sEigenvalue& eval);
void Eigencdiv(sEigenvalue& eval, float xr, float xi, float yr, float yi);
void Eigentql2 (sEigenvalue& eval);
void Eigenorthes (sEigenvalue& eval);
void Eigenhqr2 (sEigenvalue& eval);
int computeEigenvalues3x3(float dout[3], float a[3][3]);
#endif

View File

@@ -19,6 +19,11 @@
// FLUID_3D.cpp: implementation of the FLUID_3D class. // FLUID_3D.cpp: implementation of the FLUID_3D class.
// //
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// Heavy parallel optimization done. Many of the old functions now
// take begin and end parameters and process only specified part of the data.
// Some functions were divided into multiple ones.
// - MiikaH
//////////////////////////////////////////////////////////////////////
#include "FLUID_3D.h" #include "FLUID_3D.h"
#include "IMAGE.h" #include "IMAGE.h"
@@ -26,6 +31,10 @@
#include "SPHERE.h" #include "SPHERE.h"
#include <zlib.h> #include <zlib.h>
#if PARALLEL==1
#include <omp.h>
#endif // PARALLEL
// boundary conditions of the fluid domain // boundary conditions of the fluid domain
#define DOMAIN_BC_FRONT 0 // z #define DOMAIN_BC_FRONT 0 // z
#define DOMAIN_BC_TOP 1 // y #define DOMAIN_BC_TOP 1 // y
@@ -90,6 +99,13 @@ FLUID_3D::FLUID_3D(int *res, float *p0, float dt) :
_heatOld = new float[_totalCells]; _heatOld = new float[_totalCells];
_obstacles = new unsigned char[_totalCells]; // set 0 at end of step _obstacles = new unsigned char[_totalCells]; // set 0 at end of step
// For threaded version:
_xVelocityTemp = new float[_totalCells];
_yVelocityTemp = new float[_totalCells];
_zVelocityTemp = new float[_totalCells];
_densityTemp = new float[_totalCells];
_heatTemp = new float[_totalCells];
// DG TODO: check if alloc went fine // DG TODO: check if alloc went fine
for (int x = 0; x < _totalCells; x++) for (int x = 0; x < _totalCells; x++)
@@ -167,6 +183,12 @@ FLUID_3D::~FLUID_3D()
if (_obstacles) delete[] _obstacles; if (_obstacles) delete[] _obstacles;
// if (_wTurbulence) delete _wTurbulence; // if (_wTurbulence) delete _wTurbulence;
if (_xVelocityTemp) delete[] _xVelocityTemp;
if (_yVelocityTemp) delete[] _yVelocityTemp;
if (_zVelocityTemp) delete[] _zVelocityTemp;
if (_densityTemp) delete[] _densityTemp;
if (_heatTemp) delete[] _heatTemp;
// printf("deleted fluid\n"); // printf("deleted fluid\n");
} }
@@ -182,108 +204,306 @@ void FLUID_3D::initBlenderRNA(float *alpha, float *beta)
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
void FLUID_3D::step() void FLUID_3D::step()
{ {
// addSmokeTestCase(_density, _res);
// addSmokeTestCase(_heat, _res);
wipeBoundaries(); int threadval = 1;
#if PARALLEL==1
threadval = omp_get_max_threads();
#endif
int stepParts = 1;
float partSize = _zRes;
#if PARALLEL==1
stepParts = threadval*2; // Dividing parallelized sections into numOfThreads * 2 sections
partSize = (float)_zRes/stepParts; // Size of one part;
if (partSize < 4) {stepParts = threadval; // If the slice gets too low (might actually slow things down, change it to larger
partSize = (float)_zRes/stepParts;}
if (partSize < 4) {stepParts = (int)(ceil((float)_zRes/4.0f)); // If it's still too low (only possible on future systems with +24 cores), change it to 4
partSize = (float)_zRes/stepParts;}
#else
int zBegin=0;
int zEnd=_zRes;
#endif
#if PARALLEL==1
#pragma omp parallel
{
#pragma omp for schedule(static,1)
for (int i=0; i<stepParts; i++)
{
int zBegin = (int)((float)i*partSize + 0.5f);
int zEnd = (int)((float)(i+1)*partSize + 0.5f);
#endif
wipeBoundariesSL(zBegin, zEnd);
addVorticity(zBegin, zEnd);
addBuoyancy(_heat, _density, zBegin, zEnd);
addForce(zBegin, zEnd);
#if PARALLEL==1
} // end of parallel
#pragma omp barrier
#pragma omp single
{
#endif
SWAP_POINTERS(_xVelocity, _xVelocityTemp);
SWAP_POINTERS(_yVelocity, _yVelocityTemp);
SWAP_POINTERS(_zVelocity, _zVelocityTemp);
#if PARALLEL==1
} // end of single
#pragma omp barrier
#pragma omp for
for (int i=0; i<2; i++)
{
if (i==0)
{
#endif
project();
#if PARALLEL==1
}
else
{
#endif
diffuseHeat();
#if PARALLEL==1
}
}
#pragma omp barrier
#pragma omp single
{
#endif
SWAP_POINTERS(_xVelocity, _xVelocityOld);
SWAP_POINTERS(_yVelocity, _yVelocityOld);
SWAP_POINTERS(_zVelocity, _zVelocityOld);
SWAP_POINTERS(_density, _densityOld);
SWAP_POINTERS(_heat, _heatOld);
advectMacCormackBegin(0, _zRes);
#if PARALLEL==1
} // end of single
#pragma omp barrier
#pragma omp for schedule(static,1)
for (int i=0; i<stepParts; i++)
{
int zBegin = (int)((float)i*partSize + 0.5f);
int zEnd = (int)((float)(i+1)*partSize + 0.5f);
#endif
advectMacCormackEnd1(zBegin, zEnd);
#if PARALLEL==1
} // end of parallel
#pragma omp barrier
#pragma omp for schedule(static,1)
for (int i=0; i<stepParts; i++)
{
int zBegin = (int)((float)i*partSize + 0.5f);
int zEnd = (int)((float)(i+1)*partSize + 0.5f);
#endif
advectMacCormackEnd2(zBegin, zEnd);
artificialDampingSL(zBegin, zEnd);
// Using forces as temp arrays
#if PARALLEL==1
}
}
for (int i=1; i<stepParts; i++)
{
int zPos=(int)((float)i*partSize + 0.5f);
artificialDampingExactSL(zPos);
}
#endif
SWAP_POINTERS(_xVelocity, _xForce);
SWAP_POINTERS(_yVelocity, _yForce);
SWAP_POINTERS(_zVelocity, _zForce);
// run the solvers
addVorticity();
addBuoyancy(_heat, _density);
addForce();
project();
diffuseHeat();
// advect everything
advectMacCormack();
// if(_wTurbulence) {
// _wTurbulence->stepTurbulenceFull(_dt/_dx,
// _xVelocity, _yVelocity, _zVelocity, _obstacles);
// _wTurbulence->stepTurbulenceReadable(_dt/_dx,
// _xVelocity, _yVelocity, _zVelocity, _obstacles);
// }
/*
// no file output
float *src = _density;
string prefix = string("./original.preview/density_fullxy_");
writeImageSliceXY(src,_res, _res[2]/2, prefix, _totalSteps);
*/
// artificial damping -- this is necessary because we use a
// collated grid, and at very coarse grid resolutions, banding
// artifacts can occur
artificialDamping(_xVelocity);
artificialDamping(_yVelocity);
artificialDamping(_zVelocity);
/*
// no file output
string pbrtPrefix = string("./pbrt/density_small_");
IMAGE::dumpPBRT(_totalSteps, pbrtPrefix, _density, _res[0],_res[1],_res[2]);
*/
_totalTime += _dt; _totalTime += _dt;
_totalSteps++; _totalSteps++;
// todo xxx dg: only clear obstacles, not boundaries
// memset(_obstacles, 0, sizeof(unsigned char)*_xRes*_yRes*_zRes);
// wipe forces
// for external forces we can't do it at the beginning of this function but at the end
for (int i = 0; i < _totalCells; i++) for (int i = 0; i < _totalCells; i++)
{ {
_xForce[i] = _yForce[i] = _zForce[i] = 0.0f; _xForce[i] = _yForce[i] = _zForce[i] = 0.0f;
} }
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// helper function to dampen co-located grid artifacts of given arrays in intervals // helper function to dampen co-located grid artifacts of given arrays in intervals
// (only needed for velocity, strength (w) depends on testcase... // (only needed for velocity, strength (w) depends on testcase...
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
void FLUID_3D::artificialDamping(float* field) {
void FLUID_3D::artificialDampingSL(int zBegin, int zEnd) {
const float w = 0.9; const float w = 0.9;
memmove(_xForce+(_slabSize*zBegin), _xVelocityTemp+(_slabSize*zBegin), sizeof(float)*_slabSize*(zEnd-zBegin));
memmove(_yForce+(_slabSize*zBegin), _yVelocityTemp+(_slabSize*zBegin), sizeof(float)*_slabSize*(zEnd-zBegin));
memmove(_zForce+(_slabSize*zBegin), _zVelocityTemp+(_slabSize*zBegin), sizeof(float)*_slabSize*(zEnd-zBegin));
if(_totalSteps % 4 == 1) { if(_totalSteps % 4 == 1) {
for (int z = 1; z < _res[2]-1; z++) for (int z = zBegin+1; z < zEnd-1; z++)
for (int y = 1; y < _res[1]-1; y++) for (int y = 1; y < _res[1]-1; y++)
for (int x = 1+(y+z)%2; x < _res[0]-1; x+=2) { for (int x = 1+(y+z)%2; x < _res[0]-1; x+=2) {
const int index = x + y*_res[0] + z * _slabSize; const int index = x + y*_res[0] + z * _slabSize;
field[index] = (1-w)*field[index] + 1./6. * w*( _xForce[index] = (1-w)*_xVelocityTemp[index] + 1./6. * w*(
field[index+1] + field[index-1] + _xVelocityTemp[index+1] + _xVelocityTemp[index-1] +
field[index+_res[0]] + field[index-_res[0]] + _xVelocityTemp[index+_res[0]] + _xVelocityTemp[index-_res[0]] +
field[index+_slabSize] + field[index-_slabSize] ); _xVelocityTemp[index+_slabSize] + _xVelocityTemp[index-_slabSize] );
_yForce[index] = (1-w)*_yVelocityTemp[index] + 1./6. * w*(
_yVelocityTemp[index+1] + _yVelocityTemp[index-1] +
_yVelocityTemp[index+_res[0]] + _yVelocityTemp[index-_res[0]] +
_yVelocityTemp[index+_slabSize] + _yVelocityTemp[index-_slabSize] );
_zForce[index] = (1-w)*_zVelocityTemp[index] + 1./6. * w*(
_zVelocityTemp[index+1] + _zVelocityTemp[index-1] +
_zVelocityTemp[index+_res[0]] + _zVelocityTemp[index-_res[0]] +
_zVelocityTemp[index+_slabSize] + _zVelocityTemp[index-_slabSize] );
} }
} }
if(_totalSteps % 4 == 3) { if(_totalSteps % 4 == 3) {
for (int z = 1; z < _res[2]-1; z++) for (int z = zBegin+1; z < zEnd-1; z++)
for (int y = 1; y < _res[1]-1; y++) for (int y = 1; y < _res[1]-1; y++)
for (int x = 1+(y+z+1)%2; x < _res[0]-1; x+=2) { for (int x = 1+(y+z+1)%2; x < _res[0]-1; x+=2) {
const int index = x + y*_res[0] + z * _slabSize; const int index = x + y*_res[0] + z * _slabSize;
field[index] = (1-w)*field[index] + 1./6. * w*( _xForce[index] = (1-w)*_xVelocityTemp[index] + 1./6. * w*(
field[index+1] + field[index-1] + _xVelocityTemp[index+1] + _xVelocityTemp[index-1] +
field[index+_res[0]] + field[index-_res[0]] + _xVelocityTemp[index+_res[0]] + _xVelocityTemp[index-_res[0]] +
field[index+_slabSize] + field[index-_slabSize] ); _xVelocityTemp[index+_slabSize] + _xVelocityTemp[index-_slabSize] );
_yForce[index] = (1-w)*_yVelocityTemp[index] + 1./6. * w*(
_yVelocityTemp[index+1] + _yVelocityTemp[index-1] +
_yVelocityTemp[index+_res[0]] + _yVelocityTemp[index-_res[0]] +
_yVelocityTemp[index+_slabSize] + _yVelocityTemp[index-_slabSize] );
_zForce[index] = (1-w)*_zVelocityTemp[index] + 1./6. * w*(
_zVelocityTemp[index+1] + _zVelocityTemp[index-1] +
_zVelocityTemp[index+_res[0]] + _zVelocityTemp[index-_res[0]] +
_zVelocityTemp[index+_slabSize] + _zVelocityTemp[index-_slabSize] );
} }
}
}
void FLUID_3D::artificialDampingExactSL(int pos) {
const float w = 0.9;
int index, x,y,z;
size_t posslab;
for (z=pos-1; z<=pos; z++)
{
posslab=z * _slabSize;
if(_totalSteps % 4 == 1) {
for (y = 1; y < _res[1]-1; y++)
for (x = 1+(y+z)%2; x < _res[0]-1; x+=2) {
index = x + y*_res[0] + posslab;
_xForce[index] = (1-w)*_xVelocityTemp[index] + 1./6. * w*(
_xVelocityTemp[index+1] + _xVelocityTemp[index-1] +
_xVelocityTemp[index+_res[0]] + _xVelocityTemp[index-_res[0]] +
_xVelocityTemp[index+_slabSize] + _xVelocityTemp[index-_slabSize] );
_yForce[index] = (1-w)*_yVelocityTemp[index] + 1./6. * w*(
_yVelocityTemp[index+1] + _yVelocityTemp[index-1] +
_yVelocityTemp[index+_res[0]] + _yVelocityTemp[index-_res[0]] +
_yVelocityTemp[index+_slabSize] + _yVelocityTemp[index-_slabSize] );
_zForce[index] = (1-w)*_zVelocityTemp[index] + 1./6. * w*(
_zVelocityTemp[index+1] + _zVelocityTemp[index-1] +
_zVelocityTemp[index+_res[0]] + _zVelocityTemp[index-_res[0]] +
_zVelocityTemp[index+_slabSize] + _zVelocityTemp[index-_slabSize] );
}
}
if(_totalSteps % 4 == 3) {
for (y = 1; y < _res[1]-1; y++)
for (x = 1+(y+z+1)%2; x < _res[0]-1; x+=2) {
index = x + y*_res[0] + posslab;
_xForce[index] = (1-w)*_xVelocityTemp[index] + 1./6. * w*(
_xVelocityTemp[index+1] + _xVelocityTemp[index-1] +
_xVelocityTemp[index+_res[0]] + _xVelocityTemp[index-_res[0]] +
_xVelocityTemp[index+_slabSize] + _xVelocityTemp[index-_slabSize] );
_yForce[index] = (1-w)*_yVelocityTemp[index] + 1./6. * w*(
_yVelocityTemp[index+1] + _yVelocityTemp[index-1] +
_yVelocityTemp[index+_res[0]] + _yVelocityTemp[index-_res[0]] +
_yVelocityTemp[index+_slabSize] + _yVelocityTemp[index-_slabSize] );
_zForce[index] = (1-w)*_zVelocityTemp[index] + 1./6. * w*(
_zVelocityTemp[index+1] + _zVelocityTemp[index-1] +
_zVelocityTemp[index+_res[0]] + _zVelocityTemp[index-_res[0]] +
_zVelocityTemp[index+_slabSize] + _zVelocityTemp[index-_slabSize] );
}
}
} }
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// copy out the boundary in all directions // copy out the boundary in all directions
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
void FLUID_3D::copyBorderAll(float* field) void FLUID_3D::copyBorderAll(float* field, int zBegin, int zEnd)
{ {
int index; int index, x, y, z;
int zSize = zEnd-zBegin;
int _blockTotalCells=_slabSize * zSize;
if ((zBegin==0))
for (int y = 0; y < _yRes; y++) for (int y = 0; y < _yRes; y++)
for (int x = 0; x < _xRes; x++) for (int x = 0; x < _xRes; x++)
{ {
// front slab // front slab
index = x + y * _xRes; index = x + y * _xRes;
field[index] = field[index + _slabSize]; field[index] = field[index + _slabSize];
}
if (zEnd==_zRes)
for (y = 0; y < _yRes; y++)
for (x = 0; x < _xRes; x++)
{
// back slab // back slab
index += _totalCells - _slabSize; index = x + y * _xRes + _blockTotalCells - _slabSize;
field[index] = field[index - _slabSize]; field[index] = field[index - _slabSize];
} }
for (int z = 0; z < _zRes; z++) for (z = 0; z < zSize; z++)
for (int x = 0; x < _xRes; x++) for (x = 0; x < _xRes; x++)
{ {
// bottom slab // bottom slab
index = x + z * _slabSize; index = x + z * _slabSize;
@@ -294,8 +514,8 @@ void FLUID_3D::copyBorderAll(float* field)
field[index] = field[index - _xRes]; field[index] = field[index - _xRes];
} }
for (int z = 0; z < _zRes; z++) for (z = 0; z < zSize; z++)
for (int y = 0; y < _yRes; y++) for (y = 0; y < _yRes; y++)
{ {
// left slab // left slab
index = y * _xRes + z * _slabSize; index = y * _xRes + z * _slabSize;
@@ -310,27 +530,123 @@ void FLUID_3D::copyBorderAll(float* field)
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// wipe boundaries of velocity and density // wipe boundaries of velocity and density
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
void FLUID_3D::wipeBoundaries() void FLUID_3D::wipeBoundaries(int zBegin, int zEnd)
{ {
setZeroBorder(_xVelocity, _res); setZeroBorder(_xVelocity, _res, zBegin, zEnd);
setZeroBorder(_yVelocity, _res); setZeroBorder(_yVelocity, _res, zBegin, zEnd);
setZeroBorder(_zVelocity, _res); setZeroBorder(_zVelocity, _res, zBegin, zEnd);
setZeroBorder(_density, _res); setZeroBorder(_density, _res, zBegin, zEnd);
} }
void FLUID_3D::wipeBoundariesSL(int zBegin, int zEnd)
{
/////////////////////////////////////
// setZeroBorder to all:
/////////////////////////////////////
/////////////////////////////////////
// setZeroX
/////////////////////////////////////
const int slabSize = _xRes * _yRes;
int index, x,y,z;
for (z = zBegin; z < zEnd; z++)
for (y = 0; y < _yRes; y++)
{
// left slab
index = y * _xRes + z * slabSize;
_xVelocity[index] = 0.0f;
_yVelocity[index] = 0.0f;
_zVelocity[index] = 0.0f;
_density[index] = 0.0f;
// right slab
index += _xRes - 1;
_xVelocity[index] = 0.0f;
_yVelocity[index] = 0.0f;
_zVelocity[index] = 0.0f;
_density[index] = 0.0f;
}
/////////////////////////////////////
// setZeroY
/////////////////////////////////////
for (z = zBegin; z < zEnd; z++)
for (x = 0; x < _xRes; x++)
{
// bottom slab
index = x + z * slabSize;
_xVelocity[index] = 0.0f;
_yVelocity[index] = 0.0f;
_zVelocity[index] = 0.0f;
_density[index] = 0.0f;
// top slab
index += slabSize - _xRes;
_xVelocity[index] = 0.0f;
_yVelocity[index] = 0.0f;
_zVelocity[index] = 0.0f;
_density[index] = 0.0f;
}
/////////////////////////////////////
// setZeroZ
/////////////////////////////////////
const int totalCells = _xRes * _yRes * _zRes;
index = 0;
if ((zBegin == 0))
for (y = 0; y < _yRes; y++)
for (x = 0; x < _xRes; x++, index++)
{
// front slab
_xVelocity[index] = 0.0f;
_yVelocity[index] = 0.0f;
_zVelocity[index] = 0.0f;
_density[index] = 0.0f;
}
if (zEnd == _zRes)
{
index=0;
int indexx=0;
const int cellsslab = totalCells - slabSize;
for (y = 0; y < _yRes; y++)
for (x = 0; x < _xRes; x++, index++)
{
// back slab
indexx = index + cellsslab;
_xVelocity[indexx] = 0.0f;
_yVelocity[indexx] = 0.0f;
_zVelocity[indexx] = 0.0f;
_density[indexx] = 0.0f;
}
}
}
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// add forces to velocity field // add forces to velocity field
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
void FLUID_3D::addForce() void FLUID_3D::addForce(int zBegin, int zEnd)
{ {
for (int i = 0; i < _totalCells; i++) int begin=zBegin * _slabSize;
int end=begin + (zEnd - zBegin) * _slabSize;
for (int i = begin; i < end; i++)
{ {
_xVelocity[i] += _dt * _xForce[i]; _xVelocityTemp[i] = _xVelocity[i] + _dt * _xForce[i];
_yVelocity[i] += _dt * _yForce[i]; _yVelocityTemp[i] = _yVelocity[i] + _dt * _yForce[i];
_zVelocity[i] += _dt * _zForce[i]; _zVelocityTemp[i] = _zVelocity[i] + _dt * _zForce[i];
} }
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// project into divergence free field // project into divergence free field
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
@@ -344,18 +660,18 @@ void FLUID_3D::project()
memset(_pressure, 0, sizeof(float)*_totalCells); memset(_pressure, 0, sizeof(float)*_totalCells);
memset(_divergence, 0, sizeof(float)*_totalCells); memset(_divergence, 0, sizeof(float)*_totalCells);
setObstacleBoundaries(_pressure); setObstacleBoundaries(_pressure, 0, _zRes);
// copy out the boundaries // copy out the boundaries
if(DOMAIN_BC_LEFT == 0) setNeumannX(_xVelocity, _res); if(DOMAIN_BC_LEFT == 0) setNeumannX(_xVelocity, _res, 0, _zRes);
else setZeroX(_xVelocity, _res); else setZeroX(_xVelocity, _res, 0, _zRes);
if(DOMAIN_BC_TOP == 0) setNeumannY(_yVelocity, _res); if(DOMAIN_BC_TOP == 0) setNeumannY(_yVelocity, _res, 0, _zRes);
else setZeroY(_yVelocity, _res); else setZeroY(_yVelocity, _res, 0, _zRes);
if(DOMAIN_BC_FRONT == 0) setNeumannZ(_zVelocity, _res); if(DOMAIN_BC_FRONT == 0) setNeumannZ(_zVelocity, _res, 0, _zRes);
else setZeroZ(_zVelocity, _res); else setZeroZ(_zVelocity, _res, 0, _zRes);
// calculate divergence // calculate divergence
index = _slabSize + _xRes + 1; index = _slabSize + _xRes + 1;
@@ -385,12 +701,12 @@ void FLUID_3D::project()
// DG: commenting this helps CG to get a better start, 10-20% speed improvement // DG: commenting this helps CG to get a better start, 10-20% speed improvement
// _pressure[index] = 0.0f; // _pressure[index] = 0.0f;
} }
copyBorderAll(_pressure); copyBorderAll(_pressure, 0, _zRes);
// solve Poisson equation // solve Poisson equation
solvePressurePre(_pressure, _divergence, _obstacles); solvePressurePre(_pressure, _divergence, _obstacles);
setObstaclePressure(_pressure); setObstaclePressure(_pressure, 0, _zRes);
// project out solution // project out solution
float invDx = 1.0f / _dx; float invDx = 1.0f / _dx;
@@ -411,6 +727,9 @@ void FLUID_3D::project()
if (_divergence) delete[] _divergence; if (_divergence) delete[] _divergence;
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// diffuse heat // diffuse heat
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
@@ -418,13 +737,14 @@ void FLUID_3D::diffuseHeat()
{ {
SWAP_POINTERS(_heat, _heatOld); SWAP_POINTERS(_heat, _heatOld);
copyBorderAll(_heatOld); copyBorderAll(_heatOld, 0, _zRes);
solveHeat(_heat, _heatOld, _obstacles); solveHeat(_heat, _heatOld, _obstacles);
// zero out inside obstacles // zero out inside obstacles
for (int x = 0; x < _totalCells; x++) for (int x = 0; x < _totalCells; x++)
if (_obstacles[x]) if (_obstacles[x])
_heat[x] = 0.0f; _heat[x] = 0.0f;
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
@@ -444,12 +764,28 @@ void FLUID_3D::addObstacle(OBSTACLE* obstacle)
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// calculate the obstacle directional types // calculate the obstacle directional types
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
void FLUID_3D::setObstaclePressure(float *_pressure) void FLUID_3D::setObstaclePressure(float *_pressure, int zBegin, int zEnd)
{ {
// compleately TODO
const size_t index_ = _slabSize + _xRes + 1;
//int vIndex=_slabSize + _xRes + 1;
int bb=0;
int bt=0;
if (zBegin == 0) {bb = 1;}
if (zEnd == _zRes) {bt = 1;}
// tag remaining obstacle blocks // tag remaining obstacle blocks
for (int z = 1, index = _slabSize + _xRes + 1; for (int z = zBegin + bb; z < zEnd - bt; z++)
z < _zRes - 1; z++, index += 2 * _xRes) {
size_t index = index_ +(z-1)*_slabSize;
for (int y = 1; y < _yRes - 1; y++, index += 2) for (int y = 1; y < _yRes - 1; y++, index += 2)
{
for (int x = 1; x < _xRes - 1; x++, index++) for (int x = 1; x < _xRes - 1; x++, index++)
{ {
// could do cascade of ifs, but they are a pain // could do cascade of ifs, but they are a pain
@@ -507,15 +843,33 @@ void FLUID_3D::setObstaclePressure(float *_pressure)
// this means it's not a full no-slip boundary condition // this means it's not a full no-slip boundary condition
// but a "half-slip" - still looks ok right now // but a "half-slip" - still looks ok right now
} }
} //vIndex++;
} // x loop
//vIndex += 2;
} // y loop
//vIndex += 2 * _xRes;
} // z loop
} }
void FLUID_3D::setObstacleBoundaries(float *_pressure) void FLUID_3D::setObstacleBoundaries(float *_pressure, int zBegin, int zEnd)
{ {
// cull degenerate obstacles , move to addObstacle? // cull degenerate obstacles , move to addObstacle?
for (int z = 1, index = _slabSize + _xRes + 1;
z < _zRes - 1; z++, index += 2 * _xRes) // r = b - Ax
const size_t index_ = _slabSize + _xRes + 1;
int bb=0;
int bt=0;
if (zBegin == 0) {bb = 1;}
if (zEnd == _zRes) {bt = 1;}
for (int z = zBegin + bb; z < zEnd - bt; z++)
{
size_t index = index_ +(z-1)*_slabSize;
for (int y = 1; y < _yRes - 1; y++, index += 2) for (int y = 1; y < _yRes - 1; y++, index += 2)
{
for (int x = 1; x < _xRes - 1; x++, index++) for (int x = 1; x < _xRes - 1; x++, index++)
{ {
if (_obstacles[index] != EMPTY) if (_obstacles[index] != EMPTY)
@@ -545,17 +899,22 @@ void FLUID_3D::setObstacleBoundaries(float *_pressure)
_zVelocity[index] = 0.0f; _zVelocity[index] = 0.0f;
_pressure[index] = 0.0f; _pressure[index] = 0.0f;
} }
} //vIndex++;
} // x-loop
//vIndex += 2;
} // y-loop
//vIndex += 2* _xRes;
} // z-loop
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// add buoyancy forces // add buoyancy forces
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
void FLUID_3D::addBuoyancy(float *heat, float *density) void FLUID_3D::addBuoyancy(float *heat, float *density, int zBegin, int zEnd)
{ {
int index = 0; int index = zBegin*_slabSize;
for (int z = 0; z < _zRes; z++) for (int z = zBegin; z < zEnd; z++)
for (int y = 0; y < _yRes; y++) for (int y = 0; y < _yRes; y++)
for (int x = 0; x < _xRes; x++, index++) for (int x = 0; x < _xRes; x++, index++)
{ {
@@ -566,30 +925,55 @@ void FLUID_3D::addBuoyancy(float *heat, float *density)
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// add vorticity to the force field // add vorticity to the force field
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
void FLUID_3D::addVorticity() void FLUID_3D::addVorticity(int zBegin, int zEnd)
{ {
int x,y,z,index; //int x,y,z,index;
if(_vorticityEps<=0.) return; if(_vorticityEps<=0.) return;
int _blockSize=zEnd-zBegin;
int _blockTotalCells = _slabSize * (_blockSize+2);
float *_xVorticity, *_yVorticity, *_zVorticity, *_vorticity; float *_xVorticity, *_yVorticity, *_zVorticity, *_vorticity;
_xVorticity = new float[_totalCells]; int _vIndex = _slabSize + _xRes + 1;
_yVorticity = new float[_totalCells]; int bb=0;
_zVorticity = new float[_totalCells]; int bt=0;
_vorticity = new float[_totalCells]; int bb1=-1;
int bt1=-1;
memset(_xVorticity, 0, sizeof(float)*_totalCells); if (zBegin == 0) {bb1 = 1; bb = 1; _blockTotalCells-=_blockSize;}
memset(_yVorticity, 0, sizeof(float)*_totalCells); if (zEnd == _zRes) {bt1 = 1;bt = 1; _blockTotalCells-=_blockSize;}
memset(_zVorticity, 0, sizeof(float)*_totalCells);
memset(_vorticity, 0, sizeof(float)*_totalCells); _xVorticity = new float[_blockTotalCells];
_yVorticity = new float[_blockTotalCells];
_zVorticity = new float[_blockTotalCells];
_vorticity = new float[_blockTotalCells];
memset(_xVorticity, 0, sizeof(float)*_blockTotalCells);
memset(_yVorticity, 0, sizeof(float)*_blockTotalCells);
memset(_zVorticity, 0, sizeof(float)*_blockTotalCells);
memset(_vorticity, 0, sizeof(float)*_blockTotalCells);
//const size_t indexsetupV=_slabSize;
const size_t index_ = _slabSize + _xRes + 1;
// calculate vorticity // calculate vorticity
float gridSize = 0.5f / _dx; float gridSize = 0.5f / _dx;
index = _slabSize + _xRes + 1; //index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++) size_t vIndex=_xRes + 1;
for (int z = zBegin + bb1; z < (zEnd - bt1); z++)
{
size_t index = index_ +(z-1)*_slabSize;
vIndex = index-(zBegin-1+bb)*_slabSize;
for (int y = 1; y < _yRes - 1; y++, index += 2)
{
for (int x = 1; x < _xRes - 1; x++, index++)
{ {
int up = _obstacles[index + _xRes] ? index : index + _xRes; int up = _obstacles[index + _xRes] ? index : index + _xRes;
int down = _obstacles[index - _xRes] ? index : index - _xRes; int down = _obstacles[index - _xRes] ? index : index - _xRes;
float dy = (up == index || down == index) ? 1.0f / _dx : gridSize; float dy = (up == index || down == index) ? 1.0f / _dx : gridSize;
@@ -600,34 +984,51 @@ void FLUID_3D::addVorticity()
int left = _obstacles[index - 1] ? index : index - 1; int left = _obstacles[index - 1] ? index : index - 1;
float dx = (right == index || right == index) ? 1.0f / _dx : gridSize; float dx = (right == index || right == index) ? 1.0f / _dx : gridSize;
_xVorticity[index] = (_zVelocity[up] - _zVelocity[down]) * dy + (-_yVelocity[out] + _yVelocity[in]) * dz; _xVorticity[vIndex] = (_zVelocity[up] - _zVelocity[down]) * dy + (-_yVelocity[out] + _yVelocity[in]) * dz;
_yVorticity[index] = (_xVelocity[out] - _xVelocity[in]) * dz + (-_zVelocity[right] + _zVelocity[left]) * dx; _yVorticity[vIndex] = (_xVelocity[out] - _xVelocity[in]) * dz + (-_zVelocity[right] + _zVelocity[left]) * dx;
_zVorticity[index] = (_yVelocity[right] - _yVelocity[left]) * dx + (-_xVelocity[up] + _xVelocity[down])* dy; _zVorticity[vIndex] = (_yVelocity[right] - _yVelocity[left]) * dx + (-_xVelocity[up] + _xVelocity[down])* dy;
_vorticity[index] = sqrtf(_xVorticity[index] * _xVorticity[index] + _vorticity[vIndex] = sqrtf(_xVorticity[vIndex] * _xVorticity[vIndex] +
_yVorticity[index] * _yVorticity[index] + _yVorticity[vIndex] * _yVorticity[vIndex] +
_zVorticity[index] * _zVorticity[index]); _zVorticity[vIndex] * _zVorticity[vIndex]);
vIndex++;
} }
vIndex+=2;
}
//vIndex+=2*_xRes;
}
// calculate normalized vorticity vectors // calculate normalized vorticity vectors
float eps = _vorticityEps; float eps = _vorticityEps;
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes) //index = _slabSize + _xRes + 1;
for (y = 1; y < _yRes - 1; y++, index += 2) vIndex=_slabSize + _xRes + 1;
for (x = 1; x < _xRes - 1; x++, index++)
for (int z = zBegin + bb; z < (zEnd - bt); z++)
{
size_t index = index_ +(z-1)*_slabSize;
vIndex = index-(zBegin-1+bb)*_slabSize;
for (int y = 1; y < _yRes - 1; y++, index += 2)
{
for (int x = 1; x < _xRes - 1; x++, index++)
{
//
if (!_obstacles[index]) if (!_obstacles[index])
{ {
float N[3]; float N[3];
int up = _obstacles[index + _xRes] ? index : index + _xRes; int up = _obstacles[index + _xRes] ? vIndex : vIndex + _xRes;
int down = _obstacles[index - _xRes] ? index : index - _xRes; int down = _obstacles[index - _xRes] ? vIndex : vIndex - _xRes;
float dy = (up == index || down == index) ? 1.0f / _dx : gridSize; float dy = (up == vIndex || down == vIndex) ? 1.0f / _dx : gridSize;
int out = _obstacles[index + _slabSize] ? index : index + _slabSize; int out = _obstacles[index + _slabSize] ? vIndex : vIndex + _slabSize;
int in = _obstacles[index - _slabSize] ? index : index - _slabSize; int in = _obstacles[index - _slabSize] ? vIndex : vIndex - _slabSize;
float dz = (out == index || in == index) ? 1.0f / _dx : gridSize; float dz = (out == vIndex || in == vIndex) ? 1.0f / _dx : gridSize;
int right = _obstacles[index + 1] ? index : index + 1; int right = _obstacles[index + 1] ? vIndex : vIndex + 1;
int left = _obstacles[index - 1] ? index : index - 1; int left = _obstacles[index - 1] ? vIndex : vIndex - 1;
float dx = (right == index || right == index) ? 1.0f / _dx : gridSize; float dx = (right == vIndex || right == vIndex) ? 1.0f / _dx : gridSize;
N[0] = (_vorticity[right] - _vorticity[left]) * dx; N[0] = (_vorticity[right] - _vorticity[left]) * dx;
N[1] = (_vorticity[up] - _vorticity[down]) * dy; N[1] = (_vorticity[up] - _vorticity[down]) * dy;
N[2] = (_vorticity[out] - _vorticity[in]) * dz; N[2] = (_vorticity[out] - _vorticity[in]) * dz;
@@ -640,11 +1041,17 @@ void FLUID_3D::addVorticity()
N[1] *= magnitude; N[1] *= magnitude;
N[2] *= magnitude; N[2] *= magnitude;
_xForce[index] += (N[1] * _zVorticity[index] - N[2] * _yVorticity[index]) * _dx * eps; _xForce[index] += (N[1] * _zVorticity[vIndex] - N[2] * _yVorticity[vIndex]) * _dx * eps;
_yForce[index] -= (N[0] * _zVorticity[index] - N[2] * _xVorticity[index]) * _dx * eps; _yForce[index] -= (N[0] * _zVorticity[vIndex] - N[2] * _xVorticity[vIndex]) * _dx * eps;
_zForce[index] += (N[0] * _yVorticity[index] - N[1] * _xVorticity[index]) * _dx * eps; _zForce[index] += (N[0] * _yVorticity[vIndex] - N[1] * _xVorticity[vIndex]) * _dx * eps;
} }
} } // if
vIndex++;
} // x loop
vIndex+=2;
} // y loop
//vIndex+=2*_xRes;
} // z loop
if (_xVorticity) delete[] _xVorticity; if (_xVorticity) delete[] _xVorticity;
if (_yVorticity) delete[] _yVorticity; if (_yVorticity) delete[] _yVorticity;
@@ -652,54 +1059,80 @@ void FLUID_3D::addVorticity()
if (_vorticity) delete[] _vorticity; if (_vorticity) delete[] _vorticity;
} }
//////////////////////////////////////////////////////////////////////
// Advect using the MacCormack method from the Selle paper void FLUID_3D::advectMacCormackBegin(int zBegin, int zEnd)
//////////////////////////////////////////////////////////////////////
void FLUID_3D::advectMacCormack()
{ {
Vec3Int res = Vec3Int(_xRes,_yRes,_zRes); Vec3Int res = Vec3Int(_xRes,_yRes,_zRes);
if(DOMAIN_BC_LEFT == 0) copyBorderX(_xVelocity, res); if(DOMAIN_BC_LEFT == 0) copyBorderX(_xVelocityOld, res, zBegin, zEnd);
else setZeroX(_xVelocity, res); else setZeroX(_xVelocityOld, res, zBegin, zEnd);
if(DOMAIN_BC_TOP == 0) copyBorderY(_yVelocity, res); if(DOMAIN_BC_TOP == 0) copyBorderY(_yVelocityOld, res, zBegin, zEnd);
else setZeroY(_yVelocity, res); else setZeroY(_yVelocityOld, res, zBegin, zEnd);
if(DOMAIN_BC_FRONT == 0) copyBorderZ(_zVelocity, res); if(DOMAIN_BC_FRONT == 0) copyBorderZ(_zVelocityOld, res, zBegin, zEnd);
else setZeroZ(_zVelocity, res); else setZeroZ(_zVelocityOld, res, zBegin, zEnd);
}
SWAP_POINTERS(_xVelocity, _xVelocityOld); //////////////////////////////////////////////////////////////////////
SWAP_POINTERS(_yVelocity, _yVelocityOld); // Advect using the MacCormack method from the Selle paper
SWAP_POINTERS(_zVelocity, _zVelocityOld); //////////////////////////////////////////////////////////////////////
SWAP_POINTERS(_density, _densityOld); void FLUID_3D::advectMacCormackEnd1(int zBegin, int zEnd)
SWAP_POINTERS(_heat, _heatOld); {
Vec3Int res = Vec3Int(_xRes,_yRes,_zRes);
const float dt0 = _dt / _dx; const float dt0 = _dt / _dx;
// use force arrays as temp arrays
for (int x = 0; x < _totalCells; x++)
_xForce[x] = _yForce[x] = 0.0;
float* t1 = _xForce; int begin=zBegin * _slabSize;
float* t2 = _yForce; int end=begin + (zEnd - zBegin) * _slabSize;
for (int x = begin; x < end; x++)
_xForce[x] = 0.0;
advectFieldMacCormack(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _densityOld, _density, t1,t2, res, _obstacles); // advectFieldMacCormack1(dt, xVelocity, yVelocity, zVelocity, oldField, newField, res)
advectFieldMacCormack(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _heatOld, _heat, t1,t2, res, _obstacles);
advectFieldMacCormack(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _xVelocityOld, _xVelocity, t1,t2, res, _obstacles);
advectFieldMacCormack(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _yVelocityOld, _yVelocity, t1,t2, res, _obstacles);
advectFieldMacCormack(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _zVelocityOld, _zVelocity, t1,t2, res, _obstacles);
if(DOMAIN_BC_LEFT == 0) copyBorderX(_xVelocity, res); advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _densityOld, _densityTemp, res, zBegin, zEnd);
else setZeroX(_xVelocity, res); advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _heatOld, _heatTemp, res, zBegin, zEnd);
advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _xVelocityOld, _xVelocity, res, zBegin, zEnd);
advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _yVelocityOld, _yVelocity, res, zBegin, zEnd);
advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _zVelocityOld, _zVelocity, res, zBegin, zEnd);
if(DOMAIN_BC_TOP == 0) copyBorderY(_yVelocity, res); // Have to wait untill all the threads are done -> so continuing in step 3
else setZeroY(_yVelocity, res); }
if(DOMAIN_BC_FRONT == 0) copyBorderZ(_zVelocity, res); //////////////////////////////////////////////////////////////////////
else setZeroZ(_zVelocity, res); // Advect using the MacCormack method from the Selle paper
//////////////////////////////////////////////////////////////////////
setZeroBorder(_density, res); void FLUID_3D::advectMacCormackEnd2(int zBegin, int zEnd)
setZeroBorder(_heat, res); {
const float dt0 = _dt / _dx;
for (int x = 0; x < _totalCells; x++) Vec3Int res = Vec3Int(_xRes,_yRes,_zRes);
t1[x] = t2[x] = 0.0;
// use force array as temp arrays
float* t1 = _xForce;
// advectFieldMacCormack2(dt, xVelocity, yVelocity, zVelocity, oldField, newField, tempfield, temp, res, obstacles)
advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _densityOld, _density, _densityTemp, t1, res, _obstacles, zBegin, zEnd);
advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _heatOld, _heat, _heatTemp, t1, res, _obstacles, zBegin, zEnd);
advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _xVelocityOld, _xVelocityTemp, _xVelocity, t1, res, _obstacles, zBegin, zEnd);
advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _yVelocityOld, _yVelocityTemp, _yVelocity, t1, res, _obstacles, zBegin, zEnd);
advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _zVelocityOld, _zVelocityTemp, _zVelocity, t1, res, _obstacles, zBegin, zEnd);
if(DOMAIN_BC_LEFT == 0) copyBorderX(_xVelocityTemp, res, zBegin, zEnd);
else setZeroX(_xVelocityTemp, res, zBegin, zEnd);
if(DOMAIN_BC_TOP == 0) copyBorderY(_yVelocityTemp, res, zBegin, zEnd);
else setZeroY(_yVelocityTemp, res, zBegin, zEnd);
if(DOMAIN_BC_FRONT == 0) copyBorderZ(_zVelocityTemp, res, zBegin, zEnd);
else setZeroZ(_zVelocityTemp, res, zBegin, zEnd);
setZeroBorder(_density, res, zBegin, zEnd);
setZeroBorder(_heat, res, zBegin, zEnd);
/*int begin=zBegin * _slabSize;
int end=begin + (zEnd - zBegin) * _slabSize;
for (int x = begin; x < end; x++)
_xForce[x] = _yForce[x] = 0.0f;*/
} }

View File

@@ -19,6 +19,11 @@
// FLUID_3D.h: interface for the FLUID_3D class. // FLUID_3D.h: interface for the FLUID_3D class.
// //
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// Heavy parallel optimization done. Many of the old functions now
// take begin and end parameters and process only specified part of the data.
// Some functions were divided into multiple ones.
// - MiikaH
//////////////////////////////////////////////////////////////////////
#ifndef FLUID_3D_H #ifndef FLUID_3D_H
#define FLUID_3D_H #define FLUID_3D_H
@@ -74,7 +79,8 @@ class FLUID_3D
int _totalImgDumps; int _totalImgDumps;
int _totalVelDumps; int _totalVelDumps;
void artificialDamping(float* field); void artificialDampingSL(int zBegin, int zEnd);
void artificialDampingExactSL(int pos);
// fields // fields
float* _density; float* _density;
@@ -92,6 +98,13 @@ class FLUID_3D
float* _zForce; float* _zForce;
unsigned char* _obstacles; unsigned char* _obstacles;
// Required for proper threading:
float* _xVelocityTemp;
float* _yVelocityTemp;
float* _zVelocityTemp;
float* _heatTemp;
float* _densityTemp;
// CG fields // CG fields
int _iterations; int _iterations;
@@ -107,13 +120,14 @@ class FLUID_3D
// WTURBULENCE* _wTurbulence; // WTURBULENCE* _wTurbulence;
// boundary setting functions // boundary setting functions
void copyBorderAll(float* field); void copyBorderAll(float* field, int zBegin, int zEnd);
// timestepping functions // timestepping functions
void wipeBoundaries(); void wipeBoundaries(int zBegin, int zEnd);
void addForce(); void wipeBoundariesSL(int zBegin, int zEnd);
void addVorticity(); void addForce(int zBegin, int zEnd);
void addBuoyancy(float *heat, float *density); void addVorticity(int zBegin, int zEnd);
void addBuoyancy(float *heat, float *density, int zBegin, int zEnd);
// solver stuff // solver stuff
void project(); void project();
@@ -122,41 +136,58 @@ class FLUID_3D
void solvePressurePre(float* field, float* b, unsigned char* skip); void solvePressurePre(float* field, float* b, unsigned char* skip);
void solveHeat(float* field, float* b, unsigned char* skip); void solveHeat(float* field, float* b, unsigned char* skip);
// handle obstacle boundaries // handle obstacle boundaries
void setObstacleBoundaries(float *_pressure); void setObstacleBoundaries(float *_pressure, int zBegin, int zEnd);
void setObstaclePressure(float *_pressure); void setObstaclePressure(float *_pressure, int zBegin, int zEnd);
public: public:
// advection, accessed e.g. by WTURBULENCE class // advection, accessed e.g. by WTURBULENCE class
void advectMacCormack(); //void advectMacCormack();
void advectMacCormackBegin(int zBegin, int zEnd);
void advectMacCormackEnd1(int zBegin, int zEnd);
void advectMacCormackEnd2(int zBegin, int zEnd);
// boundary setting functions // boundary setting functions
static void copyBorderX(float* field, Vec3Int res); static void copyBorderX(float* field, Vec3Int res, int zBegin, int zEnd);
static void copyBorderY(float* field, Vec3Int res); static void copyBorderY(float* field, Vec3Int res, int zBegin, int zEnd);
static void copyBorderZ(float* field, Vec3Int res); static void copyBorderZ(float* field, Vec3Int res, int zBegin, int zEnd);
static void setNeumannX(float* field, Vec3Int res); static void setNeumannX(float* field, Vec3Int res, int zBegin, int zEnd);
static void setNeumannY(float* field, Vec3Int res); static void setNeumannY(float* field, Vec3Int res, int zBegin, int zEnd);
static void setNeumannZ(float* field, Vec3Int res); static void setNeumannZ(float* field, Vec3Int res, int zBegin, int zEnd);
static void setZeroX(float* field, Vec3Int res); static void setZeroX(float* field, Vec3Int res, int zBegin, int zEnd);
static void setZeroY(float* field, Vec3Int res); static void setZeroY(float* field, Vec3Int res, int zBegin, int zEnd);
static void setZeroZ(float* field, Vec3Int res); static void setZeroZ(float* field, Vec3Int res, int zBegin, int zEnd);
static void setZeroBorder(float* field, Vec3Int res) { static void setZeroBorder(float* field, Vec3Int res, int zBegin, int zEnd) {
setZeroX(field, res); setZeroX(field, res, zBegin, zEnd);
setZeroY(field, res); setZeroY(field, res, zBegin, zEnd);
setZeroZ(field, res); setZeroZ(field, res, zBegin, zEnd);
}; };
// static advection functions, also used by WTURBULENCE // static advection functions, also used by WTURBULENCE
static void advectFieldSemiLagrange(const float dt, const float* velx, const float* vely, const float* velz, static void advectFieldSemiLagrange(const float dt, const float* velx, const float* vely, const float* velz,
float* oldField, float* newField, Vec3Int res); float* oldField, float* newField, Vec3Int res, int zBegin, int zEnd);
static void advectFieldMacCormack(const float dt, const float* xVelocity, const float* yVelocity, const float* zVelocity, static void advectFieldMacCormack1(const float dt, const float* xVelocity, const float* yVelocity, const float* zVelocity,
float* oldField, float* newField, float* temp1, float* temp2, Vec3Int res, const unsigned char* obstacles); float* oldField, float* tempResult, Vec3Int res, int zBegin, int zEnd);
static void advectFieldMacCormack2(const float dt, const float* xVelocity, const float* yVelocity, const float* zVelocity,
float* oldField, float* newField, float* tempResult, float* temp1,Vec3Int res, const unsigned char* obstacles, int zBegin, int zEnd);
// temp ones for testing
/*static void advectFieldMacCormack(const float dt, const float* xVelocity, const float* yVelocity, const float* zVelocity,
float* oldField, float* newField, float* temp1, float* temp2, Vec3Int res, const unsigned char* obstacles);*/
/*static void advectFieldSemiLagrange2(const float dt, const float* velx, const float* vely, const float* velz,
float* oldField, float* newField, Vec3Int res);*/
// maccormack helper functions // maccormack helper functions
static void clampExtrema(const float dt, const float* xVelocity, const float* yVelocity, const float* zVelocity, static void clampExtrema(const float dt, const float* xVelocity, const float* yVelocity, const float* zVelocity,
float* oldField, float* newField, Vec3Int res); float* oldField, float* newField, Vec3Int res, int zBegin, int zEnd);
static void clampOutsideRays(const float dt, const float* xVelocity, const float* yVelocity, const float* zVelocity, static void clampOutsideRays(const float dt, const float* xVelocity, const float* yVelocity, const float* zVelocity,
float* oldField, float* newField, Vec3Int res, const unsigned char* obstacles, const float *oldAdvection); float* oldField, float* newField, Vec3Int res, const unsigned char* obstacles, const float *oldAdvection, int zBegin, int zEnd);
// output helper functions // output helper functions
// static void writeImageSliceXY(const float *field, Vec3Int res, int slice, string prefix, int picCnt, float scale=1.); // static void writeImageSliceXY(const float *field, Vec3Int res, int slice, string prefix, int picCnt, float scale=1.);

View File

@@ -19,11 +19,150 @@
// FLUID_3D.cpp: implementation of the FLUID_3D class. // FLUID_3D.cpp: implementation of the FLUID_3D class.
// //
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// Both solvers optimized by merging loops and precalculating
// stuff used in iteration loop.
// - MiikaH
//////////////////////////////////////////////////////////////////////
#include "FLUID_3D.h" #include "FLUID_3D.h"
#include <cstring> #include <cstring>
#define SOLVER_ACCURACY 1e-06 #define SOLVER_ACCURACY 1e-06
//////////////////////////////////////////////////////////////////////
// solve the heat equation with CG
//////////////////////////////////////////////////////////////////////
void FLUID_3D::solveHeat(float* field, float* b, unsigned char* skip)
{
int x, y, z;
const int twoxr = 2 * _xRes;
size_t index;
const float heatConst = _dt * _heatDiffusion / (_dx * _dx);
float *_q, *_residual, *_direction, *_Acenter;
// i = 0
int i = 0;
_residual = new float[_totalCells]; // set 0
_direction = new float[_totalCells]; // set 0
_q = new float[_totalCells]; // set 0
_Acenter = new float[_totalCells]; // set 0
memset(_residual, 0, sizeof(float)*_totalCells);
memset(_q, 0, sizeof(float)*_totalCells);
memset(_direction, 0, sizeof(float)*_totalCells);
memset(_Acenter, 0, sizeof(float)*_totalCells);
float deltaNew = 0.0f;
// r = b - Ax
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += twoxr)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
{
// if the cell is a variable
_Acenter[index] = 1.0f;
if (!skip[index])
{
// set the matrix to the Poisson stencil in order
if (!skip[index + 1]) _Acenter[index] += heatConst;
if (!skip[index - 1]) _Acenter[index] += heatConst;
if (!skip[index + _xRes]) _Acenter[index] += heatConst;
if (!skip[index - _xRes]) _Acenter[index] += heatConst;
if (!skip[index + _slabSize]) _Acenter[index] += heatConst;
if (!skip[index - _slabSize]) _Acenter[index] += heatConst;
_residual[index] = b[index] - (_Acenter[index] * field[index] +
field[index - 1] * (skip[index - 1] ? 0.0 : -heatConst) +
field[index + 1] * (skip[index + 1] ? 0.0 : -heatConst) +
field[index - _xRes] * (skip[index - _xRes] ? 0.0 : -heatConst) +
field[index + _xRes] * (skip[index + _xRes] ? 0.0 : -heatConst) +
field[index - _slabSize] * (skip[index - _slabSize] ? 0.0 : -heatConst) +
field[index + _slabSize] * (skip[index + _slabSize] ? 0.0 : -heatConst));
}
else
{
_residual[index] = 0.0f;
}
_direction[index] = _residual[index];
deltaNew += _residual[index] * _residual[index];
}
// While deltaNew > (eps^2) * delta0
const float eps = SOLVER_ACCURACY;
float maxR = 2.0f * eps;
while ((i < _iterations) && (maxR > eps))
{
// q = Ad
float alpha = 0.0f;
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += twoxr)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
{
// if the cell is a variable
if (!skip[index])
{
_q[index] = (_Acenter[index] * _direction[index] +
_direction[index - 1] * (skip[index - 1] ? 0.0 : -heatConst) +
_direction[index + 1] * (skip[index + 1] ? 0.0 : -heatConst) +
_direction[index - _xRes] * (skip[index - _xRes] ? 0.0 : -heatConst) +
_direction[index + _xRes] * (skip[index + _xRes] ? 0.0 : -heatConst) +
_direction[index - _slabSize] * (skip[index - _slabSize] ? 0.0 : -heatConst) +
_direction[index + _slabSize] * (skip[index + _slabSize] ? 0.0 : -heatConst));
}
else
{
_q[index] = 0.0f;
}
alpha += _direction[index] * _q[index];
}
if (fabs(alpha) > 0.0f)
alpha = deltaNew / alpha;
float deltaOld = deltaNew;
deltaNew = 0.0f;
maxR = 0.0f;
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += twoxr)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
{
field[index] += alpha * _direction[index];
_residual[index] -= alpha * _q[index];
maxR = (_residual[index] > maxR) ? _residual[index] : maxR;
deltaNew += _residual[index] * _residual[index];
}
float beta = deltaNew / deltaOld;
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += twoxr)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
_direction[index] = _residual[index] + beta * _direction[index];
i++;
}
// cout << i << " iterations converged to " << maxR << endl;
if (_residual) delete[] _residual;
if (_direction) delete[] _direction;
if (_q) delete[] _q;
if (_Acenter) delete[] _Acenter;
}
void FLUID_3D::solvePressurePre(float* field, float* b, unsigned char* skip) void FLUID_3D::solvePressurePre(float* field, float* b, unsigned char* skip)
{ {
int x, y, z; int x, y, z;
@@ -45,6 +184,8 @@ void FLUID_3D::solvePressurePre(float* field, float* b, unsigned char* skip)
memset(_h, 0, sizeof(float)*_xRes*_yRes*_zRes); memset(_h, 0, sizeof(float)*_xRes*_yRes*_zRes);
memset(_Precond, 0, sizeof(float)*_xRes*_yRes*_zRes); memset(_Precond, 0, sizeof(float)*_xRes*_yRes*_zRes);
float deltaNew = 0.0f;
// r = b - Ax // r = b - Ax
index = _slabSize + _xRes + 1; index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes) for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
@@ -62,16 +203,19 @@ void FLUID_3D::solvePressurePre(float* field, float* b, unsigned char* skip)
if (!skip[index - _xRes]) Acenter += 1.; if (!skip[index - _xRes]) Acenter += 1.;
if (!skip[index + _slabSize]) Acenter += 1.; if (!skip[index + _slabSize]) Acenter += 1.;
if (!skip[index - _slabSize]) Acenter += 1.; if (!skip[index - _slabSize]) Acenter += 1.;
}
_residual[index] = b[index] - (Acenter * field[index] +
_residual[index] = b[index] - (Acenter * field[index] +
field[index - 1] * (skip[index - 1] ? 0.0 : -1.0f)+ field[index - 1] * (skip[index - 1] ? 0.0 : -1.0f)+
field[index + 1] * (skip[index + 1] ? 0.0 : -1.0f)+ field[index + 1] * (skip[index + 1] ? 0.0 : -1.0f)+
field[index - _xRes] * (skip[index - _xRes] ? 0.0 : -1.0f)+ field[index - _xRes] * (skip[index - _xRes] ? 0.0 : -1.0f)+
field[index + _xRes] * (skip[index + _xRes] ? 0.0 : -1.0f)+ field[index + _xRes] * (skip[index + _xRes] ? 0.0 : -1.0f)+
field[index - _slabSize] * (skip[index - _slabSize] ? 0.0 : -1.0f)+ field[index - _slabSize] * (skip[index - _slabSize] ? 0.0 : -1.0f)+
field[index + _slabSize] * (skip[index + _slabSize] ? 0.0 : -1.0f) ); field[index + _slabSize] * (skip[index + _slabSize] ? 0.0 : -1.0f) );
_residual[index] = (skip[index]) ? 0.0f : _residual[index]; }
else
{
_residual[index] = 0.0f;
}
// P^-1 // P^-1
if(Acenter < 1.0) if(Acenter < 1.0)
@@ -81,18 +225,10 @@ void FLUID_3D::solvePressurePre(float* field, float* b, unsigned char* skip)
// p = P^-1 * r // p = P^-1 * r
_direction[index] = _residual[index] * _Precond[index]; _direction[index] = _residual[index] * _Precond[index];
deltaNew += _residual[index] * _direction[index];
} }
// deltaNew = transpose(r) * p
float deltaNew = 0.0f;
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
deltaNew += _residual[index] * _direction[index];
// delta0 = deltaNew
// float delta0 = deltaNew;
// While deltaNew > (eps^2) * delta0 // While deltaNew > (eps^2) * delta0
const float eps = SOLVER_ACCURACY; const float eps = SOLVER_ACCURACY;
@@ -101,7 +237,9 @@ void FLUID_3D::solvePressurePre(float* field, float* b, unsigned char* skip)
// while (i < _iterations) // while (i < _iterations)
while ((i < _iterations) && (maxR > 0.001*eps)) while ((i < _iterations) && (maxR > 0.001*eps))
{ {
// (s) q = Ad (p)
float alpha = 0.0f;
index = _slabSize + _xRes + 1; index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes) for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2) for (y = 1; y < _yRes - 1; y++, index += 2)
@@ -118,71 +256,52 @@ void FLUID_3D::solvePressurePre(float* field, float* b, unsigned char* skip)
if (!skip[index - _xRes]) Acenter += 1.; if (!skip[index - _xRes]) Acenter += 1.;
if (!skip[index + _slabSize]) Acenter += 1.; if (!skip[index + _slabSize]) Acenter += 1.;
if (!skip[index - _slabSize]) Acenter += 1.; if (!skip[index - _slabSize]) Acenter += 1.;
}
_q[index] = Acenter * _direction[index] +
_q[index] = Acenter * _direction[index] +
_direction[index - 1] * (skip[index - 1] ? 0.0 : -1.0f) + _direction[index - 1] * (skip[index - 1] ? 0.0 : -1.0f) +
_direction[index + 1] * (skip[index + 1] ? 0.0 : -1.0f) + _direction[index + 1] * (skip[index + 1] ? 0.0 : -1.0f) +
_direction[index - _xRes] * (skip[index - _xRes] ? 0.0 : -1.0f) + _direction[index - _xRes] * (skip[index - _xRes] ? 0.0 : -1.0f) +
_direction[index + _xRes] * (skip[index + _xRes] ? 0.0 : -1.0f)+ _direction[index + _xRes] * (skip[index + _xRes] ? 0.0 : -1.0f)+
_direction[index - _slabSize] * (skip[index - _slabSize] ? 0.0 : -1.0f) + _direction[index - _slabSize] * (skip[index - _slabSize] ? 0.0 : -1.0f) +
_direction[index + _slabSize] * (skip[index + _slabSize] ? 0.0 : -1.0f); _direction[index + _slabSize] * (skip[index + _slabSize] ? 0.0 : -1.0f);
_q[index] = (skip[index]) ? 0.0f : _q[index]; }
else
{
_q[index] = 0.0f;
}
alpha += _direction[index] * _q[index];
} }
// alpha = deltaNew / (transpose(d) * q)
float alpha = 0.0f;
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
alpha += _direction[index] * _q[index];
if (fabs(alpha) > 0.0f) if (fabs(alpha) > 0.0f)
alpha = deltaNew / alpha; alpha = deltaNew / alpha;
float deltaOld = deltaNew;
deltaNew = 0.0f;
maxR = 0.0;
float tmp;
// x = x + alpha * d // x = x + alpha * d
index = _slabSize + _xRes + 1; index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes) for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2) for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++) for (x = 1; x < _xRes - 1; x++, index++)
{
field[index] += alpha * _direction[index]; field[index] += alpha * _direction[index];
// r = r - alpha * q _residual[index] -= alpha * _q[index];
maxR = 0.0;
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
{
_residual[index] -= alpha * _q[index];
// maxR = (_residual[index] > maxR) ? _residual[index] : maxR;
}
// if(maxR <= eps) _h[index] = _Precond[index] * _residual[index];
// break;
tmp = _residual[index] * _h[index];
deltaNew += tmp;
maxR = (tmp > maxR) ? tmp : maxR;
// h = P^-1 * r
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
{
_h[index] = _Precond[index] * _residual[index];
} }
// deltaOld = deltaNew
float deltaOld = deltaNew;
// deltaNew = transpose(r) * h
deltaNew = 0.0f;
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
{
deltaNew += _residual[index] * _h[index];
maxR = (_residual[index]* _h[index] > maxR) ? _residual[index]* _h[index] : maxR;
}
// beta = deltaNew / deltaOld // beta = deltaNew / deltaOld
float beta = deltaNew / deltaOld; float beta = deltaNew / deltaOld;
@@ -205,320 +324,3 @@ void FLUID_3D::solvePressurePre(float* field, float* b, unsigned char* skip)
if (_direction) delete[] _direction; if (_direction) delete[] _direction;
if (_q) delete[] _q; if (_q) delete[] _q;
} }
//////////////////////////////////////////////////////////////////////
// solve the poisson equation with CG
//////////////////////////////////////////////////////////////////////
#if 0
void FLUID_3D::solvePressure(float* field, float* b, unsigned char* skip)
{
int x, y, z;
size_t index;
// i = 0
int i = 0;
memset(_residual, 0, sizeof(float)*_xRes*_yRes*_zRes);
memset(_q, 0, sizeof(float)*_xRes*_yRes*_zRes);
memset(_direction, 0, sizeof(float)*_xRes*_yRes*_zRes);
// r = b - Ax
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
{
// if the cell is a variable
float Acenter = 0.0f;
if (!skip[index])
{
// set the matrix to the Poisson stencil in order
if (!skip[index + 1]) Acenter += 1.;
if (!skip[index - 1]) Acenter += 1.;
if (!skip[index + _xRes]) Acenter += 1.;
if (!skip[index - _xRes]) Acenter += 1.;
if (!skip[index + _slabSize]) Acenter += 1.;
if (!skip[index - _slabSize]) Acenter += 1.;
}
_residual[index] = b[index] - (Acenter * field[index] +
field[index - 1] * (skip[index - 1] ? 0.0 : -1.0f)+
field[index + 1] * (skip[index + 1] ? 0.0 : -1.0f)+
field[index - _xRes] * (skip[index - _xRes] ? 0.0 : -1.0f)+
field[index + _xRes] * (skip[index + _xRes] ? 0.0 : -1.0f)+
field[index - _slabSize] * (skip[index - _slabSize] ? 0.0 : -1.0f)+
field[index + _slabSize] * (skip[index + _slabSize] ? 0.0 : -1.0f) );
_residual[index] = (skip[index]) ? 0.0f : _residual[index];
}
// d = r
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
_direction[index] = _residual[index];
// deltaNew = transpose(r) * r
float deltaNew = 0.0f;
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
deltaNew += _residual[index] * _residual[index];
// delta0 = deltaNew
// float delta0 = deltaNew;
// While deltaNew > (eps^2) * delta0
const float eps = SOLVER_ACCURACY;
float maxR = 2.0f * eps;
while ((i < _iterations) && (maxR > eps))
{
// q = Ad
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
{
// if the cell is a variable
float Acenter = 0.0f;
if (!skip[index])
{
// set the matrix to the Poisson stencil in order
if (!skip[index + 1]) Acenter += 1.;
if (!skip[index - 1]) Acenter += 1.;
if (!skip[index + _xRes]) Acenter += 1.;
if (!skip[index - _xRes]) Acenter += 1.;
if (!skip[index + _slabSize]) Acenter += 1.;
if (!skip[index - _slabSize]) Acenter += 1.;
}
_q[index] = Acenter * _direction[index] +
_direction[index - 1] * (skip[index - 1] ? 0.0 : -1.0f) +
_direction[index + 1] * (skip[index + 1] ? 0.0 : -1.0f) +
_direction[index - _xRes] * (skip[index - _xRes] ? 0.0 : -1.0f) +
_direction[index + _xRes] * (skip[index + _xRes] ? 0.0 : -1.0f)+
_direction[index - _slabSize] * (skip[index - _slabSize] ? 0.0 : -1.0f) +
_direction[index + _slabSize] * (skip[index + _slabSize] ? 0.0 : -1.0f);
_q[index] = (skip[index]) ? 0.0f : _q[index];
}
// alpha = deltaNew / (transpose(d) * q)
float alpha = 0.0f;
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
alpha += _direction[index] * _q[index];
if (fabs(alpha) > 0.0f)
alpha = deltaNew / alpha;
// x = x + alpha * d
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
field[index] += alpha * _direction[index];
// r = r - alpha * q
maxR = 0.0f;
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
{
_residual[index] -= alpha * _q[index];
maxR = (_residual[index] > maxR) ? _residual[index] : maxR;
}
// deltaOld = deltaNew
float deltaOld = deltaNew;
// deltaNew = transpose(r) * r
deltaNew = 0.0f;
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
deltaNew += _residual[index] * _residual[index];
// beta = deltaNew / deltaOld
float beta = deltaNew / deltaOld;
// d = r + beta * d
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
_direction[index] = _residual[index] + beta * _direction[index];
// i = i + 1
i++;
}
// cout << i << " iterations converged to " << maxR << endl;
}
#endif
//////////////////////////////////////////////////////////////////////
// solve the heat equation with CG
//////////////////////////////////////////////////////////////////////
void FLUID_3D::solveHeat(float* field, float* b, unsigned char* skip)
{
int x, y, z;
size_t index;
const float heatConst = _dt * _heatDiffusion / (_dx * _dx);
float *_q, *_residual, *_direction;
// i = 0
int i = 0;
_residual = new float[_totalCells]; // set 0
_direction = new float[_totalCells]; // set 0
_q = new float[_totalCells]; // set 0
memset(_residual, 0, sizeof(float)*_xRes*_yRes*_zRes);
memset(_q, 0, sizeof(float)*_xRes*_yRes*_zRes);
memset(_direction, 0, sizeof(float)*_xRes*_yRes*_zRes);
// r = b - Ax
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
{
// if the cell is a variable
float Acenter = 1.0f;
if (!skip[index])
{
// set the matrix to the Poisson stencil in order
if (!skip[index + 1]) Acenter += heatConst;
if (!skip[index - 1]) Acenter += heatConst;
if (!skip[index + _xRes]) Acenter += heatConst;
if (!skip[index - _xRes]) Acenter += heatConst;
if (!skip[index + _slabSize]) Acenter += heatConst;
if (!skip[index - _slabSize]) Acenter += heatConst;
}
_residual[index] = b[index] - (Acenter * field[index] +
field[index - 1] * (skip[index - 1] ? 0.0 : -heatConst) +
field[index + 1] * (skip[index + 1] ? 0.0 : -heatConst) +
field[index - _xRes] * (skip[index - _xRes] ? 0.0 : -heatConst) +
field[index + _xRes] * (skip[index + _xRes] ? 0.0 : -heatConst) +
field[index - _slabSize] * (skip[index - _slabSize] ? 0.0 : -heatConst) +
field[index + _slabSize] * (skip[index + _slabSize] ? 0.0 : -heatConst));
_residual[index] = (skip[index]) ? 0.0f : _residual[index];
}
// d = r
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
_direction[index] = _residual[index];
// deltaNew = transpose(r) * r
float deltaNew = 0.0f;
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
deltaNew += _residual[index] * _residual[index];
// delta0 = deltaNew
// float delta0 = deltaNew;
// While deltaNew > (eps^2) * delta0
const float eps = SOLVER_ACCURACY;
float maxR = 2.0f * eps;
while ((i < _iterations) && (maxR > eps))
{
// q = Ad
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
{
// if the cell is a variable
float Acenter = 1.0f;
if (!skip[index])
{
// set the matrix to the Poisson stencil in order
if (!skip[index + 1]) Acenter += heatConst;
if (!skip[index - 1]) Acenter += heatConst;
if (!skip[index + _xRes]) Acenter += heatConst;
if (!skip[index - _xRes]) Acenter += heatConst;
if (!skip[index + _slabSize]) Acenter += heatConst;
if (!skip[index - _slabSize]) Acenter += heatConst;
}
_q[index] = (Acenter * _direction[index] +
_direction[index - 1] * (skip[index - 1] ? 0.0 : -heatConst) +
_direction[index + 1] * (skip[index + 1] ? 0.0 : -heatConst) +
_direction[index - _xRes] * (skip[index - _xRes] ? 0.0 : -heatConst) +
_direction[index + _xRes] * (skip[index + _xRes] ? 0.0 : -heatConst) +
_direction[index - _slabSize] * (skip[index - _slabSize] ? 0.0 : -heatConst) +
_direction[index + _slabSize] * (skip[index + _slabSize] ? 0.0 : -heatConst));
_q[index] = (skip[index]) ? 0.0f : _q[index];
}
// alpha = deltaNew / (transpose(d) * q)
float alpha = 0.0f;
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
alpha += _direction[index] * _q[index];
if (fabs(alpha) > 0.0f)
alpha = deltaNew / alpha;
// x = x + alpha * d
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
field[index] += alpha * _direction[index];
// r = r - alpha * q
maxR = 0.0f;
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
{
_residual[index] -= alpha * _q[index];
maxR = (_residual[index] > maxR) ? _residual[index] : maxR;
}
// deltaOld = deltaNew
float deltaOld = deltaNew;
// deltaNew = transpose(r) * r
deltaNew = 0.0f;
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
deltaNew += _residual[index] * _residual[index];
// beta = deltaNew / deltaOld
float beta = deltaNew / deltaOld;
// d = r + beta * d
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
_direction[index] = _residual[index] + beta * _direction[index];
// i = i + 1
i++;
}
// cout << i << " iterations converged to " << maxR << endl;
if (_residual) delete[] _residual;
if (_direction) delete[] _direction;
if (_q) delete[] _q;
}

View File

@@ -19,6 +19,11 @@
// FLUID_3D.cpp: implementation of the static functions of the FLUID_3D class. // FLUID_3D.cpp: implementation of the static functions of the FLUID_3D class.
// //
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// Heavy parallel optimization done. Many of the old functions now
// take begin and end parameters and process only specified part of the data.
// Some functions were divided into multiple ones.
// - MiikaH
//////////////////////////////////////////////////////////////////////
#include <zlib.h> #include <zlib.h>
#include "FLUID_3D.h" #include "FLUID_3D.h"
@@ -75,11 +80,11 @@ void FLUID_3D::addSmokeTestCase(float* field, Vec3Int res)
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// set x direction to Neumann boundary conditions // set x direction to Neumann boundary conditions
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
void FLUID_3D::setNeumannX(float* field, Vec3Int res) void FLUID_3D::setNeumannX(float* field, Vec3Int res, int zBegin, int zEnd)
{ {
const int slabSize = res[0] * res[1]; const int slabSize = res[0] * res[1];
int index; int index;
for (int z = 0; z < res[2]; z++) for (int z = zBegin; z < zEnd; z++)
for (int y = 0; y < res[1]; y++) for (int y = 0; y < res[1]; y++)
{ {
// left slab // left slab
@@ -93,7 +98,7 @@ void FLUID_3D::setNeumannX(float* field, Vec3Int res)
// fix, force top slab to only allow outwards flux // fix, force top slab to only allow outwards flux
for (int y = 0; y < res[1]; y++) for (int y = 0; y < res[1]; y++)
for (int z = 0; z < res[2]; z++) for (int z = zBegin; z < zEnd; z++)
{ {
// top slab // top slab
index = y * res[0] + z * slabSize; index = y * res[0] + z * slabSize;
@@ -107,11 +112,11 @@ void FLUID_3D::setNeumannX(float* field, Vec3Int res)
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// set y direction to Neumann boundary conditions // set y direction to Neumann boundary conditions
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
void FLUID_3D::setNeumannY(float* field, Vec3Int res) void FLUID_3D::setNeumannY(float* field, Vec3Int res, int zBegin, int zEnd)
{ {
const int slabSize = res[0] * res[1]; const int slabSize = res[0] * res[1];
int index; int index;
for (int z = 0; z < res[2]; z++) for (int z = zBegin; z < zEnd; z++)
for (int x = 0; x < res[0]; x++) for (int x = 0; x < res[0]; x++)
{ {
// bottom slab // bottom slab
@@ -124,7 +129,7 @@ void FLUID_3D::setNeumannY(float* field, Vec3Int res)
} }
// fix, force top slab to only allow outwards flux // fix, force top slab to only allow outwards flux
for (int z = 0; z < res[2]; z++) for (int z = zBegin; z < zEnd; z++)
for (int x = 0; x < res[0]; x++) for (int x = 0; x < res[0]; x++)
{ {
// top slab // top slab
@@ -140,22 +145,36 @@ void FLUID_3D::setNeumannY(float* field, Vec3Int res)
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// set z direction to Neumann boundary conditions // set z direction to Neumann boundary conditions
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
void FLUID_3D::setNeumannZ(float* field, Vec3Int res) void FLUID_3D::setNeumannZ(float* field, Vec3Int res, int zBegin, int zEnd)
{ {
const int slabSize = res[0] * res[1]; const int slabSize = res[0] * res[1];
const int totalCells = res[0] * res[1] * res[2]; const int totalCells = res[0] * res[1] * res[2];
const int cellsslab = totalCells - slabSize;
int index; int index;
index = 0;
if (zBegin == 0)
for (int y = 0; y < res[1]; y++) for (int y = 0; y < res[1]; y++)
for (int x = 0; x < res[0]; x++) for (int x = 0; x < res[0]; x++, index++)
{ {
// front slab // front slab
index = x + y * res[0];
field[index] = field[index + 2 * slabSize]; field[index] = field[index + 2 * slabSize];
}
if (zEnd == res[2])
{
index = 0;
int indexx = 0;
for (int y = 0; y < res[1]; y++)
for (int x = 0; x < res[0]; x++, index++)
{
// back slab // back slab
index += totalCells - slabSize; indexx = index + cellsslab;
field[index] = field[index - 2 * slabSize]; field[indexx] = field[indexx - 2 * slabSize];
} }
// fix, force top slab to only allow outwards flux // fix, force top slab to only allow outwards flux
for (int y = 0; y < res[1]; y++) for (int y = 0; y < res[1]; y++)
@@ -163,22 +182,24 @@ void FLUID_3D::setNeumannZ(float* field, Vec3Int res)
{ {
// top slab // top slab
index = x + y * res[0]; index = x + y * res[0];
index += totalCells - slabSize; index += cellsslab;
if(field[index]<0.) field[index] = 0.; if(field[index]<0.) field[index] = 0.;
index -= slabSize; index -= slabSize;
if(field[index]<0.) field[index] = 0.; if(field[index]<0.) field[index] = 0.;
} }
} // zEnd == res[2]
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// set x direction to zero // set x direction to zero
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
void FLUID_3D::setZeroX(float* field, Vec3Int res) void FLUID_3D::setZeroX(float* field, Vec3Int res, int zBegin, int zEnd)
{ {
const int slabSize = res[0] * res[1]; const int slabSize = res[0] * res[1];
int index; int index;
for (int z = 0; z < res[2]; z++) for (int z = zBegin; z < zEnd; z++)
for (int y = 0; y < res[1]; y++) for (int y = 0; y < res[1]; y++)
{ {
// left slab // left slab
@@ -194,11 +215,11 @@ void FLUID_3D::setZeroX(float* field, Vec3Int res)
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// set y direction to zero // set y direction to zero
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
void FLUID_3D::setZeroY(float* field, Vec3Int res) void FLUID_3D::setZeroY(float* field, Vec3Int res, int zBegin, int zEnd)
{ {
const int slabSize = res[0] * res[1]; const int slabSize = res[0] * res[1];
int index; int index;
for (int z = 0; z < res[2]; z++) for (int z = zBegin; z < zEnd; z++)
for (int x = 0; x < res[0]; x++) for (int x = 0; x < res[0]; x++)
{ {
// bottom slab // bottom slab
@@ -214,32 +235,44 @@ void FLUID_3D::setZeroY(float* field, Vec3Int res)
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// set z direction to zero // set z direction to zero
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
void FLUID_3D::setZeroZ(float* field, Vec3Int res) void FLUID_3D::setZeroZ(float* field, Vec3Int res, int zBegin, int zEnd)
{ {
const int slabSize = res[0] * res[1]; const int slabSize = res[0] * res[1];
const int totalCells = res[0] * res[1] * res[2]; const int totalCells = res[0] * res[1] * res[2];
int index;
int index = 0;
if ((zBegin == 0))
for (int y = 0; y < res[1]; y++) for (int y = 0; y < res[1]; y++)
for (int x = 0; x < res[0]; x++) for (int x = 0; x < res[0]; x++, index++)
{ {
// front slab // front slab
index = x + y * res[0];
field[index] = 0.0f; field[index] = 0.0f;
}
// back slab if (zEnd == res[2])
index += totalCells - slabSize; {
field[index] = 0.0f; index=0;
} int indexx=0;
const int cellsslab = totalCells - slabSize;
for (int y = 0; y < res[1]; y++)
for (int x = 0; x < res[0]; x++, index++)
{
// back slab
indexx = index + cellsslab;
field[indexx] = 0.0f;
}
}
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// copy grid boundary // copy grid boundary
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
void FLUID_3D::copyBorderX(float* field, Vec3Int res) void FLUID_3D::copyBorderX(float* field, Vec3Int res, int zBegin, int zEnd)
{ {
const int slabSize = res[0] * res[1]; const int slabSize = res[0] * res[1];
int index; int index;
for (int z = 0; z < res[2]; z++) for (int z = zBegin; z < zEnd; z++)
for (int y = 0; y < res[1]; y++) for (int y = 0; y < res[1]; y++)
{ {
// left slab // left slab
@@ -251,12 +284,12 @@ void FLUID_3D::copyBorderX(float* field, Vec3Int res)
field[index] = field[index - 1]; field[index] = field[index - 1];
} }
} }
void FLUID_3D::copyBorderY(float* field, Vec3Int res) void FLUID_3D::copyBorderY(float* field, Vec3Int res, int zBegin, int zEnd)
{ {
const int slabSize = res[0] * res[1]; const int slabSize = res[0] * res[1];
const int totalCells = res[0] * res[1] * res[2]; //const int totalCells = res[0] * res[1] * res[2];
int index; int index;
for (int z = 0; z < res[2]; z++) for (int z = zBegin; z < zEnd; z++)
for (int x = 0; x < res[0]; x++) for (int x = 0; x < res[0]; x++)
{ {
// bottom slab // bottom slab
@@ -267,40 +300,49 @@ void FLUID_3D::copyBorderY(float* field, Vec3Int res)
field[index] = field[index - res[0]]; field[index] = field[index - res[0]];
} }
} }
void FLUID_3D::copyBorderZ(float* field, Vec3Int res) void FLUID_3D::copyBorderZ(float* field, Vec3Int res, int zBegin, int zEnd)
{ {
const int slabSize = res[0] * res[1]; const int slabSize = res[0] * res[1];
const int totalCells = res[0] * res[1] * res[2]; const int totalCells = res[0] * res[1] * res[2];
int index; int index=0;
if ((zBegin == 0))
for (int y = 0; y < res[1]; y++) for (int y = 0; y < res[1]; y++)
for (int x = 0; x < res[0]; x++) for (int x = 0; x < res[0]; x++, index++)
{ {
// front slab
index = x + y * res[0];
field[index] = field[index + slabSize]; field[index] = field[index + slabSize];
// back slab
index += totalCells - slabSize;
field[index] = field[index - slabSize];
} }
if ((zEnd == res[2]))
{
index=0;
int indexx=0;
const int cellsslab = totalCells - slabSize;
for (int y = 0; y < res[1]; y++)
for (int x = 0; x < res[0]; x++, index++)
{
// back slab
indexx = index + cellsslab;
field[indexx] = field[indexx - slabSize];
}
}
} }
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
// advect field with the semi lagrangian method // advect field with the semi lagrangian method
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
void FLUID_3D::advectFieldSemiLagrange(const float dt, const float* velx, const float* vely, const float* velz, void FLUID_3D::advectFieldSemiLagrange(const float dt, const float* velx, const float* vely, const float* velz,
float* oldField, float* newField, Vec3Int res) float* oldField, float* newField, Vec3Int res, int zBegin, int zEnd)
{ {
const int xres = res[0]; const int xres = res[0];
const int yres = res[1]; const int yres = res[1];
const int zres = res[2]; const int zres = res[2];
const int slabSize = res[0] * res[1]; const int slabSize = res[0] * res[1];
// scale dt up to grid resolution
#if PARALLEL==1 && !_WIN32 for (int z = zBegin; z < zEnd; z++)
#pragma omp parallel
#pragma omp for schedule(static)
#endif
for (int z = 0; z < zres; z++)
for (int y = 0; y < yres; y++) for (int y = 0; y < yres; y++)
for (int x = 0; x < xres; x++) for (int x = 0; x < xres; x++)
{ {
@@ -357,50 +399,69 @@ void FLUID_3D::advectFieldSemiLagrange(const float dt, const float* velx, const
} }
} }
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
// advect field with the maccormack method // advect field with the maccormack method
// //
// comments are the pseudocode from selle's paper // comments are the pseudocode from selle's paper
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
void FLUID_3D::advectFieldMacCormack(const float dt, const float* xVelocity, const float* yVelocity, const float* zVelocity, void FLUID_3D::advectFieldMacCormack1(const float dt, const float* xVelocity, const float* yVelocity, const float* zVelocity,
float* oldField, float* newField, float* temp1, float* temp2, Vec3Int res, const unsigned char* obstacles) float* oldField, float* tempResult, Vec3Int res, int zBegin, int zEnd)
{ {
float* phiHatN = temp1;
float* phiHatN1 = temp2;
const int sx= res[0]; const int sx= res[0];
const int sy= res[1]; const int sy= res[1];
const int sz= res[2]; const int sz= res[2];
for (int x = 0; x < sx * sy * sz; x++) /*for (int x = 0; x < sx * sy * sz; x++)
phiHatN[x] = phiHatN1[x] = oldField[x]; phiHatN[x] = phiHatN1[x] = oldField[x];*/ // not needed as all the values are written first
float*& phiN = oldField;
float*& phiN1 = tempResult;
// phiHatN1 = A(phiN)
advectFieldSemiLagrange( dt, xVelocity, yVelocity, zVelocity, phiN, phiN1, res, zBegin, zEnd); // uses wide data from old field and velocities (both are whole)
}
void FLUID_3D::advectFieldMacCormack2(const float dt, const float* xVelocity, const float* yVelocity, const float* zVelocity,
float* oldField, float* newField, float* tempResult, float* temp1, Vec3Int res, const unsigned char* obstacles, int zBegin, int zEnd)
{
float* phiHatN = tempResult;
float* t1 = temp1;
const int sx= res[0];
const int sy= res[1];
const int sz= res[2];
float*& phiN = oldField; float*& phiN = oldField;
float*& phiN1 = newField; float*& phiN1 = newField;
// phiHatN1 = A(phiN)
advectFieldSemiLagrange( dt, xVelocity, yVelocity, zVelocity, phiN, phiHatN1, res);
// phiHatN = A^R(phiHatN1) // phiHatN = A^R(phiHatN1)
advectFieldSemiLagrange( -1.0*dt, xVelocity, yVelocity, zVelocity, phiHatN1, phiHatN, res); advectFieldSemiLagrange( -1.0*dt, xVelocity, yVelocity, zVelocity, phiHatN, t1, res, zBegin, zEnd); // uses wide data from old field and velocities (both are whole)
// phiN1 = phiHatN1 + (phiN - phiHatN) / 2 // phiN1 = phiHatN1 + (phiN - phiHatN) / 2
const int border = 0; const int border = 0;
for (int z = border; z < sz-border; z++) for (int z = zBegin+border; z < zEnd-border; z++)
for (int y = border; y < sy-border; y++) for (int y = border; y < sy-border; y++)
for (int x = border; x < sx-border; x++) { for (int x = border; x < sx-border; x++) {
int index = x + y * sx + z * sx*sy; int index = x + y * sx + z * sx*sy;
phiN1[index] = phiHatN1[index] + (phiN[index] - phiHatN[index]) * 0.50f; phiN1[index] = phiHatN[index] + (phiN[index] - t1[index]) * 0.50f;
//phiN1[index] = phiHatN1[index]; // debug, correction off //phiN1[index] = phiHatN1[index]; // debug, correction off
} }
copyBorderX(phiN1, res); copyBorderX(phiN1, res, zBegin, zEnd);
copyBorderY(phiN1, res); copyBorderY(phiN1, res, zBegin, zEnd);
copyBorderZ(phiN1, res); copyBorderZ(phiN1, res, zBegin, zEnd);
// clamp any newly created extrema // clamp any newly created extrema
clampExtrema(dt, xVelocity, yVelocity, zVelocity, oldField, newField, res); clampExtrema(dt, xVelocity, yVelocity, zVelocity, oldField, newField, res, zBegin, zEnd); // uses wide data from old field and velocities (both are whole)
// if the error estimate was bad, revert to first order // if the error estimate was bad, revert to first order
clampOutsideRays(dt, xVelocity, yVelocity, zVelocity, oldField, newField, res, obstacles, phiHatN1); clampOutsideRays(dt, xVelocity, yVelocity, zVelocity, oldField, newField, res, obstacles, phiHatN, zBegin, zEnd); // phiHatN is only used at cells within thread range, so its ok
} }
@@ -408,13 +469,21 @@ void FLUID_3D::advectFieldMacCormack(const float dt, const float* xVelocity, con
// Clamp the extrema generated by the BFECC error correction // Clamp the extrema generated by the BFECC error correction
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
void FLUID_3D::clampExtrema(const float dt, const float* velx, const float* vely, const float* velz, void FLUID_3D::clampExtrema(const float dt, const float* velx, const float* vely, const float* velz,
float* oldField, float* newField, Vec3Int res) float* oldField, float* newField, Vec3Int res, int zBegin, int zEnd)
{ {
const int xres= res[0]; const int xres= res[0];
const int yres= res[1]; const int yres= res[1];
const int zres= res[2]; const int zres= res[2];
const int slabSize = res[0] * res[1]; const int slabSize = res[0] * res[1];
for (int z = 1; z < zres-1; z++)
int bb=0;
int bt=0;
if (zBegin == 0) {bb = 1;}
if (zEnd == res[2]) {bt = 1;}
for (int z = zBegin+bb; z < zEnd-bt; z++)
for (int y = 1; y < yres-1; y++) for (int y = 1; y < yres-1; y++)
for (int x = 1; x < xres-1; x++) for (int x = 1; x < xres-1; x++)
{ {
@@ -484,14 +553,20 @@ void FLUID_3D::clampExtrema(const float dt, const float* velx, const float* vely
// incorrect // incorrect
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
void FLUID_3D::clampOutsideRays(const float dt, const float* velx, const float* vely, const float* velz, void FLUID_3D::clampOutsideRays(const float dt, const float* velx, const float* vely, const float* velz,
float* oldField, float* newField, Vec3Int res, const unsigned char* obstacles, const float *oldAdvection) float* oldField, float* newField, Vec3Int res, const unsigned char* obstacles, const float *oldAdvection, int zBegin, int zEnd)
{ {
const int sx= res[0]; const int sx= res[0];
const int sy= res[1]; const int sy= res[1];
const int sz= res[2]; const int sz= res[2];
const int slabSize = res[0] * res[1]; const int slabSize = res[0] * res[1];
for (int z = 1; z < sz-1; z++) int bb=0;
int bt=0;
if (zBegin == 0) {bb = 1;}
if (zEnd == res[2]) {bt = 1;}
for (int z = zBegin+bb; z < zEnd-bt; z++)
for (int y = 1; y < sy-1; y++) for (int y = 1; y < sy-1; y++)
for (int x = 1; x < sx-1; x++) for (int x = 1; x < sx-1; x++)
{ {
@@ -607,4 +682,3 @@ void FLUID_3D::clampOutsideRays(const float dt, const float* velx, const float*
} }
} // xyz } // xyz
} }

View File

@@ -0,0 +1,136 @@
#include "LU_HELPER.h"
int isNonsingular (sLU LU_) {
for (int j = 0; j < 3; j++) {
if (LU_.values[j][j] == 0)
return 0;
}
return 1;
}
sLU computeLU( float a[3][3])
{
sLU result;
int m=3;
int n=3;
//float LU_[3][3];
for (int i = 0; i < m; i++) {
result.piv[i] = i;
for (int j = 0; j < n; j++) result.values[i][j]=a[i][j];
}
result.pivsign = 1;
//Real *LUrowi = 0;;
//Array1D<Real> LUcolj(m);
//float *LUrowi = 0;
float LUcolj[3];
// Outer loop.
for (int j = 0; j < n; j++) {
// Make a copy of the j-th column to localize references.
for (int i = 0; i < m; i++) {
LUcolj[i] = result.values[i][j];
}
// Apply previous transformations.
for (int i = 0; i < m; i++) {
//float LUrowi[3];
//LUrowi = result.values[i];
// Most of the time is spent in the following dot product.
int kmax = min(i,j);
double s = 0.0;
for (int k = 0; k < kmax; k++) {
s += result.values[i][k]*LUcolj[k];
}
result.values[i][j] = LUcolj[i] -= s;
}
// Find pivot and exchange if necessary.
int p = j;
for (int i = j+1; i < m; i++) {
if (abs(LUcolj[i]) > abs(LUcolj[p])) {
p = i;
}
}
if (p != j) {
int k=0;
for (k = 0; k < n; k++) {
double t = result.values[p][k];
result.values[p][k] = result.values[j][k];
result.values[j][k] = t;
}
k = result.piv[p];
result.piv[p] = result.piv[j];
result.piv[j] = k;
result.pivsign = -result.pivsign;
}
// Compute multipliers.
if ((j < m) && (result.values[j][j] != 0.0)) {
for (int i = j+1; i < m; i++) {
result.values[i][j] /= result.values[j][j];
}
}
}
return result;
}
void solveLU3x3(sLU& A, float x[3], float b[3])
{
//TNT::Array1D<float> jamaB = TNT::Array1D<float>(3, &b[0]);
//TNT::Array1D<float> jamaX = A.solve(jamaB);
// Solve A, B
{
if (!isNonsingular(A)) {
x[0]=0.0f;
x[1]=0.0f;
x[2]=0.0f;
return;
}
//Array1D<Real> Ax = permute_copy(b, piv);
float Ax[3];
// permute copy: b , A.piv
{
for (int i = 0; i < 3; i++)
Ax[i] = b[A.piv[i]];
}
// Solve L*Y = B(piv)
for (int k = 0; k < 3; k++) {
for (int i = k+1; i < 3; i++) {
Ax[i] -= Ax[k]*A.values[i][k];
}
}
// Solve U*X = Y;
for (int k = 2; k >= 0; k--) {
Ax[k] /= A.values[k][k];
for (int i = 0; i < k; i++)
Ax[i] -= Ax[k]*A.values[i][k];
}
x[0] = Ax[0];
x[1] = Ax[1];
x[2] = Ax[2];
return;
}
}

View File

@@ -17,40 +17,35 @@
// Copyright 2008 Theodore Kim and Nils Thuerey // Copyright 2008 Theodore Kim and Nils Thuerey
// //
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// Modified to not require TNT matrix library anymore. It was very slow
// when being run in parallel. Required TNT JAMA:LU libraries were
// converted into independent functions.
// - MiikaH
//////////////////////////////////////////////////////////////////////
#ifndef LU_HELPER_H #ifndef LU_HELPER_H
#define LU_HELPER_H #define LU_HELPER_H
#include <cmath>
#include <algorithm>
using namespace std;
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// Helper function, compute eigenvalues of 3x3 matrix // Helper function, compute eigenvalues of 3x3 matrix
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
#include "tnt/jama_lu.h" struct sLU
//////////////////////////////////////////////////////////////////////
// LU decomposition of 3x3 non-symmetric matrix
//////////////////////////////////////////////////////////////////////
JAMA::LU<float> inline computeLU3x3(
float a[3][3])
{ {
TNT::Array2D<float> A = TNT::Array2D<float>(3,3, &a[0][0]); float values[3][3];
JAMA::LU<float> jLU= JAMA::LU<float>(A); int pivsign;
return jLU; int piv[3];
} };
int isNonsingular (sLU LU_);
sLU computeLU( float a[3][3]);
void solveLU3x3(sLU& A, float x[3], float b[3]);
//////////////////////////////////////////////////////////////////////
// LU decomposition of 3x3 non-symmetric matrix
//////////////////////////////////////////////////////////////////////
void inline solveLU3x3(
JAMA::LU<float>& A,
float x[3],
float b[3])
{
TNT::Array1D<float> jamaB = TNT::Array1D<float>(3, &b[0]);
TNT::Array1D<float> jamaX = A.solve(jamaB);
x[0] = jamaX[0];
x[1] = jamaX[1];
x[2] = jamaX[2];
}
#endif #endif

View File

@@ -18,6 +18,10 @@
// //
// WTURBULENCE handling // WTURBULENCE handling
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
// Parallelized turbulence even further. TNT matrix library functions
// rewritten to improve performance.
// - MiikaH
//////////////////////////////////////////////////////////////////////
#include "WTURBULENCE.h" #include "WTURBULENCE.h"
#include "INTERPOLATE.h" #include "INTERPOLATE.h"
@@ -29,6 +33,7 @@
#include "LU_HELPER.h" #include "LU_HELPER.h"
#include "SPHERE.h" #include "SPHERE.h"
#include <zlib.h> #include <zlib.h>
#include <math.h>
// needed to access static advection functions // needed to access static advection functions
#include "FLUID_3D.h" #include "FLUID_3D.h"
@@ -278,27 +283,34 @@ static float minDz(int x, int y, int z, float* input, Vec3Int res)
// Beware -- uses big density maccormack as temporary arrays // Beware -- uses big density maccormack as temporary arrays
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
void WTURBULENCE::advectTextureCoordinates (float dtOrg, float* xvel, float* yvel, float* zvel, float *tempBig1, float *tempBig2) { void WTURBULENCE::advectTextureCoordinates (float dtOrg, float* xvel, float* yvel, float* zvel, float *tempBig1, float *tempBig2) {
// advection // advection
SWAP_POINTERS(_tcTemp, _tcU); SWAP_POINTERS(_tcTemp, _tcU);
FLUID_3D::copyBorderX(_tcTemp, _resSm); FLUID_3D::copyBorderX(_tcTemp, _resSm, 0 , _resSm[2]);
FLUID_3D::copyBorderY(_tcTemp, _resSm); FLUID_3D::copyBorderY(_tcTemp, _resSm, 0 , _resSm[2]);
FLUID_3D::copyBorderZ(_tcTemp, _resSm); FLUID_3D::copyBorderZ(_tcTemp, _resSm, 0 , _resSm[2]);
FLUID_3D::advectFieldMacCormack(dtOrg, xvel, yvel, zvel, FLUID_3D::advectFieldMacCormack1(dtOrg, xvel, yvel, zvel,
_tcTemp, _tcU, tempBig1, tempBig2, _resSm, NULL); _tcTemp, tempBig1, _resSm, 0 , _resSm[2]);
FLUID_3D::advectFieldMacCormack2(dtOrg, xvel, yvel, zvel,
_tcTemp, _tcU, tempBig1, tempBig2, _resSm, NULL, 0 , _resSm[2]);
SWAP_POINTERS(_tcTemp, _tcV); SWAP_POINTERS(_tcTemp, _tcV);
FLUID_3D::copyBorderX(_tcTemp, _resSm); FLUID_3D::copyBorderX(_tcTemp, _resSm, 0 , _resSm[2]);
FLUID_3D::copyBorderY(_tcTemp, _resSm); FLUID_3D::copyBorderY(_tcTemp, _resSm, 0 , _resSm[2]);
FLUID_3D::copyBorderZ(_tcTemp, _resSm); FLUID_3D::copyBorderZ(_tcTemp, _resSm, 0 , _resSm[2]);
FLUID_3D::advectFieldMacCormack(dtOrg, xvel, yvel, zvel, FLUID_3D::advectFieldMacCormack1(dtOrg, xvel, yvel, zvel,
_tcTemp, _tcV, tempBig1, tempBig2, _resSm, NULL); _tcTemp, tempBig1, _resSm, 0 , _resSm[2]);
FLUID_3D::advectFieldMacCormack2(dtOrg, xvel, yvel, zvel,
_tcTemp, _tcV, tempBig1, tempBig2, _resSm, NULL, 0 , _resSm[2]);
SWAP_POINTERS(_tcTemp, _tcW); SWAP_POINTERS(_tcTemp, _tcW);
FLUID_3D::copyBorderX(_tcTemp, _resSm); FLUID_3D::copyBorderX(_tcTemp, _resSm, 0 , _resSm[2]);
FLUID_3D::copyBorderY(_tcTemp, _resSm); FLUID_3D::copyBorderY(_tcTemp, _resSm, 0 , _resSm[2]);
FLUID_3D::copyBorderZ(_tcTemp, _resSm); FLUID_3D::copyBorderZ(_tcTemp, _resSm, 0 , _resSm[2]);
FLUID_3D::advectFieldMacCormack(dtOrg, xvel, yvel, zvel, FLUID_3D::advectFieldMacCormack1(dtOrg, xvel, yvel, zvel,
_tcTemp, _tcW, tempBig1, tempBig2, _resSm, NULL); _tcTemp, tempBig1, _resSm, 0 , _resSm[2]);
FLUID_3D::advectFieldMacCormack2(dtOrg, xvel, yvel, zvel,
_tcTemp, _tcW, tempBig1, tempBig2, _resSm, NULL, 0 , _resSm[2]);
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
@@ -325,9 +337,9 @@ void WTURBULENCE::computeEigenvalues(float *_eigMin, float *_eigMax) {
// ONLY compute the eigenvalues after checking that the matrix // ONLY compute the eigenvalues after checking that the matrix
// is nonsingular // is nonsingular
JAMA::LU<float> LU = computeLU3x3(jacobian); sLU LU = computeLU(jacobian);
if (LU.isNonsingular()) if (isNonsingular(LU))
{ {
// get the analytic eigenvalues, quite slow right now... // get the analytic eigenvalues, quite slow right now...
Vec3 eigenvalues = Vec3(1.); Vec3 eigenvalues = Vec3(1.);
@@ -422,9 +434,9 @@ void WTURBULENCE::computeEnergy(float *_energy, float* xvel, float* yvel, float*
for (int x = 0; x < _totalCellsSm; x++) for (int x = 0; x < _totalCellsSm; x++)
_energy[x] = 0.5f * (xvel[x] * xvel[x] + yvel[x] * yvel[x] + zvel[x] * zvel[x]); _energy[x] = 0.5f * (xvel[x] * xvel[x] + yvel[x] * yvel[x] + zvel[x] * zvel[x]);
FLUID_3D::copyBorderX(_energy, _resSm); FLUID_3D::copyBorderX(_energy, _resSm, 0 , _resSm[2]);
FLUID_3D::copyBorderY(_energy, _resSm); FLUID_3D::copyBorderY(_energy, _resSm, 0 , _resSm[2]);
FLUID_3D::copyBorderZ(_energy, _resSm); FLUID_3D::copyBorderZ(_energy, _resSm, 0 , _resSm[2]);
// pseudo-march the values into the obstacles // pseudo-march the values into the obstacles
// the wavelet upsampler only uses a 3x3 support neighborhood, so // the wavelet upsampler only uses a 3x3 support neighborhood, so
@@ -563,7 +575,7 @@ Vec3 WTURBULENCE::WVelocityWithJacobian(Vec3 orgPos, float* xUnwarped, float* yU
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// perform an actual noise advection step // perform an actual noise advection step
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
void WTURBULENCE::stepTurbulenceReadable(float dtOrg, float* xvel, float* yvel, float* zvel, unsigned char *obstacles) /*void WTURBULENCE::stepTurbulenceReadable(float dtOrg, float* xvel, float* yvel, float* zvel, unsigned char *obstacles)
{ {
// enlarge timestep to match grid // enlarge timestep to match grid
const float dt = dtOrg * _amplify; const float dt = dtOrg * _amplify;
@@ -689,9 +701,9 @@ void WTURBULENCE::stepTurbulenceReadable(float dtOrg, float* xvel, float* yvel,
const float dtSubdiv = dt / (float)totalSubsteps; const float dtSubdiv = dt / (float)totalSubsteps;
// set boundaries of big velocity grid // set boundaries of big velocity grid
FLUID_3D::setZeroX(bigUx, _resBig); FLUID_3D::setZeroX(bigUx, _resBig, 0, _resBig[2]);
FLUID_3D::setZeroY(bigUy, _resBig); FLUID_3D::setZeroY(bigUy, _resBig, 0, _resBig[2]);
FLUID_3D::setZeroZ(bigUz, _resBig); FLUID_3D::setZeroZ(bigUz, _resBig, 0, _resBig[2]);
// do the MacCormack advection, with substepping if necessary // do the MacCormack advection, with substepping if necessary
for(int substep = 0; substep < totalSubsteps; substep++) for(int substep = 0; substep < totalSubsteps; substep++)
@@ -704,7 +716,7 @@ void WTURBULENCE::stepTurbulenceReadable(float dtOrg, float* xvel, float* yvel,
} // substep } // substep
// wipe the density borders // wipe the density borders
FLUID_3D::setZeroBorder(_densityBig, _resBig); FLUID_3D::setZeroBorder(_densityBig, _resBig, 0, _resBig[2]);
// reset texture coordinates now in preparation for next timestep // reset texture coordinates now in preparation for next timestep
// Shouldn't do this before generating the noise because then the // Shouldn't do this before generating the noise because then the
@@ -724,7 +736,9 @@ void WTURBULENCE::stepTurbulenceReadable(float dtOrg, float* xvel, float* yvel,
_totalStepsBig++; _totalStepsBig++;
} }*/
//struct
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// perform the full turbulence algorithm, including OpenMP // perform the full turbulence algorithm, including OpenMP
@@ -747,6 +761,7 @@ void WTURBULENCE::stepTurbulenceFull(float dtOrg, float* xvel, float* yvel, floa
memset(_tcTemp, 0, sizeof(float)*_totalCellsSm); memset(_tcTemp, 0, sizeof(float)*_totalCellsSm);
// prepare textures // prepare textures
advectTextureCoordinates(dtOrg, xvel,yvel,zvel, tempBig1, tempBig2); advectTextureCoordinates(dtOrg, xvel,yvel,zvel, tempBig1, tempBig2);
@@ -763,25 +778,38 @@ void WTURBULENCE::stepTurbulenceFull(float dtOrg, float* xvel, float* yvel, floa
if (obstacles[x]) highFreqEnergy[x] = 0.f; if (obstacles[x]) highFreqEnergy[x] = 0.f;
Vec3Int ressm(_xResSm, _yResSm, _zResSm); Vec3Int ressm(_xResSm, _yResSm, _zResSm);
FLUID_3D::setNeumannX(highFreqEnergy, ressm); FLUID_3D::setNeumannX(highFreqEnergy, ressm, 0 , ressm[2]);
FLUID_3D::setNeumannY(highFreqEnergy, ressm); FLUID_3D::setNeumannY(highFreqEnergy, ressm, 0 , ressm[2]);
FLUID_3D::setNeumannZ(highFreqEnergy, ressm); FLUID_3D::setNeumannZ(highFreqEnergy, ressm, 0 , ressm[2]);
int threadval = 1;
#if PARALLEL==1
threadval = omp_get_max_threads();
#endif
// parallel region setup // parallel region setup
float maxVelMagThreads[8] = { -1., -1., -1., -1., -1., -1., -1., -1. }; // Uses omp_get_max_trheads to get number of required cells.
#if PARALLEL==1 && !_WIN32 float* maxVelMagThreads = new float[threadval];
for (int i=0; i<threadval; i++) maxVelMagThreads[i] = -1.0f;
#if PARALLEL==1
#pragma omp parallel #pragma omp parallel
#endif #endif
{ float maxVelMag1 = 0.; { float maxVelMag1 = 0.;
#if PARALLEL==1 && !_WIN32 #if PARALLEL==1
const int id = omp_get_thread_num(); /*, num = omp_get_num_threads(); */ const int id = omp_get_thread_num(); /*, num = omp_get_num_threads(); */
#endif #endif
// vector noise main loop // vector noise main loop
#if PARALLEL==1 && !_WIN32 #if PARALLEL==1
#pragma omp for schedule(static) #pragma omp for schedule(static,1)
#endif #endif
for (int zSmall = 0; zSmall < _zResSm; zSmall++) for (int zSmall = 0; zSmall < _zResSm; zSmall++)
{
for (int ySmall = 0; ySmall < _yResSm; ySmall++) for (int ySmall = 0; ySmall < _yResSm; ySmall++)
for (int xSmall = 0; xSmall < _xResSm; xSmall++) for (int xSmall = 0; xSmall < _xResSm; xSmall++)
{ {
@@ -796,14 +824,14 @@ void WTURBULENCE::stepTurbulenceFull(float dtOrg, float* xvel, float* yvel, floa
// get LU factorization of texture jacobian and apply // get LU factorization of texture jacobian and apply
// it to unit vectors // it to unit vectors
JAMA::LU<float> LU = computeLU3x3(jacobian); sLU LU = computeLU(jacobian);
float xUnwarped[] = {1.0f, 0.0f, 0.0f}; float xUnwarped[] = {1.0f, 0.0f, 0.0f};
float yUnwarped[] = {0.0f, 1.0f, 0.0f}; float yUnwarped[] = {0.0f, 1.0f, 0.0f};
float zUnwarped[] = {0.0f, 0.0f, 1.0f}; float zUnwarped[] = {0.0f, 0.0f, 1.0f};
float xWarped[] = {1.0f, 0.0f, 0.0f}; float xWarped[] = {1.0f, 0.0f, 0.0f};
float yWarped[] = {0.0f, 1.0f, 0.0f}; float yWarped[] = {0.0f, 1.0f, 0.0f};
float zWarped[] = {0.0f, 0.0f, 1.0f}; float zWarped[] = {0.0f, 0.0f, 1.0f};
bool nonSingular = LU.isNonsingular(); bool nonSingular = isNonsingular(LU);
#if 0 #if 0
// UNUSED // UNUSED
float eigMax = 10.0f; float eigMax = 10.0f;
@@ -908,24 +936,27 @@ void WTURBULENCE::stepTurbulenceFull(float dtOrg, float* xvel, float* yvel, floa
obstacles, posSm[0], posSm[1], posSm[2], _xResSm, _yResSm, _zResSm); obstacles, posSm[0], posSm[1], posSm[2], _xResSm, _yResSm, _zResSm);
if (obsCheck > 0.95) if (obsCheck > 0.95)
bigUx[index] = bigUy[index] = bigUz[index] = 0.; bigUx[index] = bigUy[index] = bigUz[index] = 0.;
} // xyz } // xyz*/
#if PARALLEL==1 && !_WIN32 #if PARALLEL==1
maxVelMagThreads[id] = maxVelMag1; maxVelMagThreads[id] = maxVelMag1;
#else #else
maxVelMagThreads[0] = maxVelMag1; maxVelMagThreads[0] = maxVelMag1;
#endif #endif
}
} }
} // omp } // omp
// compute maximum over threads // compute maximum over threads
float maxVelMag = maxVelMagThreads[0]; float maxVelMag = maxVelMagThreads[0];
#if PARALLEL==1 && !_WIN32 #if PARALLEL==1
for (int i = 1; i < 8; i++) for (int i = 1; i < threadval; i++)
if (maxVelMag < maxVelMagThreads[i]) if (maxVelMag < maxVelMagThreads[i])
maxVelMag = maxVelMagThreads[i]; maxVelMag = maxVelMagThreads[i];
delete [] maxVelMagThreads;
#endif #endif
// prepare density for an advection // prepare density for an advection
SWAP_POINTERS(_densityBig, _densityBigOld); SWAP_POINTERS(_densityBig, _densityBigOld);
@@ -941,15 +972,56 @@ void WTURBULENCE::stepTurbulenceFull(float dtOrg, float* xvel, float* yvel, floa
const float dtSubdiv = dt / (float)totalSubsteps; const float dtSubdiv = dt / (float)totalSubsteps;
// set boundaries of big velocity grid // set boundaries of big velocity grid
FLUID_3D::setZeroX(bigUx, _resBig); FLUID_3D::setZeroX(bigUx, _resBig, 0 , _resBig[2]);
FLUID_3D::setZeroY(bigUy, _resBig); FLUID_3D::setZeroY(bigUy, _resBig, 0 , _resBig[2]);
FLUID_3D::setZeroZ(bigUz, _resBig); FLUID_3D::setZeroZ(bigUz, _resBig, 0 , _resBig[2]);
#if PARALLEL==1
int stepParts = threadval*2; // Dividing parallelized sections into numOfThreads * 2 sections
float partSize = (float)_zResBig/stepParts; // Size of one part;
if (partSize < 4) {stepParts = threadval; // If the slice gets too low (might actually slow things down, change it to larger
partSize = (float)_zResBig/stepParts;}
if (partSize < 4) {stepParts = (int)(ceil((float)_zResBig/4.0f)); // If it's still too low (only possible on future systems with +24 cores), change it to 4
partSize = (float)_zResBig/stepParts;}
#else
int zBegin=0;
int zEnd=_resBig[2];
#endif
// do the MacCormack advection, with substepping if necessary // do the MacCormack advection, with substepping if necessary
for(int substep = 0; substep < totalSubsteps; substep++) for(int substep = 0; substep < totalSubsteps; substep++)
{ {
FLUID_3D::advectFieldMacCormack(dtSubdiv, bigUx, bigUy, bigUz,
_densityBigOld, _densityBig, tempBig1, tempBig2, _resBig, NULL); #if PARALLEL==1
#pragma omp parallel
{
#pragma omp for schedule(static,1)
for (int i=0; i<stepParts; i++)
{
int zBegin = (int)((float)i*partSize + 0.5f);
int zEnd = (int)((float)(i+1)*partSize + 0.5f);
#endif
FLUID_3D::advectFieldMacCormack1(dtSubdiv, bigUx, bigUy, bigUz,
_densityBigOld, tempBig1, _resBig, zBegin, zEnd);
#if PARALLEL==1
}
#pragma omp barrier
#pragma omp for schedule(static,1)
for (int i=0; i<stepParts; i++)
{
int zBegin = (int)((float)i*partSize + 0.5f);
int zEnd = (int)((float)(i+1)*partSize + 0.5f);
#endif
FLUID_3D::advectFieldMacCormack2(dtSubdiv, bigUx, bigUy, bigUz,
_densityBigOld, _densityBig, tempBig1, tempBig2, _resBig, NULL, zBegin, zEnd);
#if PARALLEL==1
}
}
#endif
if (substep < totalSubsteps - 1) if (substep < totalSubsteps - 1)
SWAP_POINTERS(_densityBig, _densityBigOld); SWAP_POINTERS(_densityBig, _densityBigOld);
@@ -964,7 +1036,7 @@ void WTURBULENCE::stepTurbulenceFull(float dtOrg, float* xvel, float* yvel, floa
free(highFreqEnergy); free(highFreqEnergy);
// wipe the density borders // wipe the density borders
FLUID_3D::setZeroBorder(_densityBig, _resBig); FLUID_3D::setZeroBorder(_densityBig, _resBig, 0 , _resBig[2]);
// reset texture coordinates now in preparation for next timestep // reset texture coordinates now in preparation for next timestep
// Shouldn't do this before generating the noise because then the // Shouldn't do this before generating the noise because then the

View File

@@ -30,6 +30,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <math.h>
// y in smoke is z in blender // y in smoke is z in blender
extern "C" FLUID_3D *smoke_init(int *res, float *p0, float dt) extern "C" FLUID_3D *smoke_init(int *res, float *p0, float dt)
@@ -110,8 +111,8 @@ extern "C" void smoke_dissolve(FLUID_3D *fluid, int speed, int log)
heat[i] *= (1.0 - dydx); heat[i] *= (1.0 - dydx);
if(heat[i] < 0.0f) /*if(heat[i] < 0.0f)
heat[i] = 0.0f; heat[i] = 0.0f;*/
} }
} }
else // linear falloff else // linear falloff
@@ -127,10 +128,9 @@ extern "C" void smoke_dissolve(FLUID_3D *fluid, int speed, int log)
if(density[i] < 0.0f) if(density[i] < 0.0f)
density[i] = 0.0f; density[i] = 0.0f;
heat[i] -= dydx; if(abs(heat[i]) < dydx) heat[i] = 0.0f;
else if (heat[i]>0.0f) heat[i] -= dydx;
if(heat[i] < 0.0f) else if (heat[i]<0.0f) heat[i] += dydx;
heat[i] = 0.0f;
} }
} }

View File

@@ -39,6 +39,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h> #include <ctype.h>
#include <string.h> #include <string.h>
#if defined(__sun__) || defined( __sun ) || defined (__sparc) || defined (__sparc__) || defined (_AIX)
#include <strings.h>
#endif
#include "STR_String.h" #include "STR_String.h"
/*------------------------------------------------------------------------------------------------- /*-------------------------------------------------------------------------------------------------

View File

@@ -355,6 +355,10 @@
RelativePath="..\..\..\source\blender\python\intern\bpy_operator_wrap.c" RelativePath="..\..\..\source\blender\python\intern\bpy_operator_wrap.c"
> >
</File> </File>
<File
RelativePath="..\..\..\source\blender\python\intern\bpy_props.c"
>
</File>
<File <File
RelativePath="..\..\..\source\blender\python\intern\bpy_rna.c" RelativePath="..\..\..\source\blender\python\intern\bpy_rna.c"
> >
@@ -444,6 +448,10 @@
RelativePath="..\..\..\source\blender\python\intern\bpy_panel_wrap.h" RelativePath="..\..\..\source\blender\python\intern\bpy_panel_wrap.h"
> >
</File> </File>
<File
RelativePath="..\..\..\source\blender\python\intern\bpy_props.h"
>
</File>
<File <File
RelativePath="..\..\..\source\blender\python\intern\bpy_rna.h" RelativePath="..\..\..\source\blender\python\intern\bpy_rna.h"
> >

View File

@@ -571,6 +571,10 @@
RelativePath="..\..\..\source\blender\blenlib\intern\math_base.c" RelativePath="..\..\..\source\blender\blenlib\intern\math_base.c"
> >
</File> </File>
<File
RelativePath="..\..\..\source\blender\blenlib\intern\math_base_inline.c"
>
</File>
<File <File
RelativePath="..\..\..\source\blender\blenlib\intern\math_color.c" RelativePath="..\..\..\source\blender\blenlib\intern\math_color.c"
> >
@@ -736,6 +740,10 @@
RelativePath="..\..\..\source\blender\blenlib\BLI_math_geom.h" RelativePath="..\..\..\source\blender\blenlib\BLI_math_geom.h"
> >
</File> </File>
<File
RelativePath="..\..\..\source\blender\blenlib\BLI_math_inline.h"
>
</File>
<File <File
RelativePath="..\..\..\source\blender\blenlib\BLI_math_matrix.h" RelativePath="..\..\..\source\blender\blenlib\BLI_math_matrix.h"
> >

View File

@@ -44,7 +44,7 @@
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
Optimization="2" Optimization="2"
InlineFunctionExpansion="1" InlineFunctionExpansion="1"
AdditionalIncludeDirectories="..\..\..\..\lib\windows\QTDevWin\CIncludes;..\..\..\..\lib\windows\sdl\include;..\..\..\..\lib\windows\python\include\python2.6;..\..\..\..\build\msvc_9\intern\bsp\include;..\..\..\..\build\msvc_9\intern\ghost\include;..\..\..\..\build\msvc_9\intern\elbeem\include;..\..\..\..\build\msvc_9\intern\opennl\include;..\..\..\..\build\msvc_9\intern\bmfont\include;..\..\..\..\build\msvc_9\intern\blenkey\include;..\..\..\..\build\msvc_9\intern\decimation\include;..\..\..\..\build\msvc_9\intern\memutil\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\intern\smoke\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\source\blender;..\..\..\source\blender\img;..\..\..\source\blender\verify;..\..\..\source\blender\ftfont;..\..\..\source\blender\misc;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\python;..\..\..\source\blender\editors\include;..\..\..\source\blender\renderui;..\..\..\source\blender\blenloader;..\..\..\source\blender\quicktime;..\..\..\source\blender\blenkernel;..\..\..\source\blender\blenfont;..\..\..\source\blender\makesdna;..\..\..\source\blender\makesrna;..\..\..\source\blender\nodes;..\..\..\source\blender\windowmanager;..\..\..\source\blender\blenpluginapi;..\..\..\source\blender\renderconverter;..\..\..\source\blender\readstreamglue;..\..\..\source\blender\render\extern\include;..\..\..\source\blender\radiosity\extern\include;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\network;..\..\..\source\gameengine\soundsystem\snd_openal;..\..\..\..\build\msvc_9\extern\verse\include;..\..\..\..\lib\windows\pthreads\include;..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\source\blender\gpu;..\..\..\intern\audaspace\intern;..\..\..\source\blender\ikplugin" AdditionalIncludeDirectories="..\..\..\..\lib\windows\QTDevWin\CIncludes;..\..\..\..\lib\windows\sdl\include;..\..\..\..\lib\windows\python\include\python2.6;..\..\..\..\build\msvc_9\intern\bsp\include;..\..\..\..\build\msvc_9\intern\ghost\include;..\..\..\..\build\msvc_9\intern\elbeem\include;..\..\..\..\build\msvc_9\intern\opennl\include;..\..\..\..\build\msvc_9\intern\bmfont\include;..\..\..\..\build\msvc_9\intern\blenkey\include;..\..\..\..\build\msvc_9\intern\decimation\include;..\..\..\..\build\msvc_9\intern\memutil\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\intern\smoke\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\source\blender;..\..\..\source\blender\img;..\..\..\source\blender\verify;..\..\..\source\blender\ftfont;..\..\..\source\blender\misc;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\python;..\..\..\source\blender\editors\include;..\..\..\source\blender\editors\interface;..\..\..\source\blender\renderui;..\..\..\source\blender\blenloader;..\..\..\source\blender\quicktime;..\..\..\source\blender\blenkernel;..\..\..\source\blender\blenfont;..\..\..\source\blender\makesdna;..\..\..\source\blender\makesrna;..\..\..\source\blender\nodes;..\..\..\source\blender\windowmanager;..\..\..\source\blender\blenpluginapi;..\..\..\source\blender\renderconverter;..\..\..\source\blender\readstreamglue;..\..\..\source\blender\render\extern\include;..\..\..\source\blender\radiosity\extern\include;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\network;..\..\..\source\gameengine\soundsystem\snd_openal;..\..\..\..\build\msvc_9\extern\verse\include;..\..\..\..\lib\windows\pthreads\include;..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\source\blender\gpu;..\..\..\intern\audaspace\intern;..\..\..\source\blender\ikplugin"
PreprocessorDefinitions="NDEBUG;WIN32;_LIB;_CONSOLE;GAMEBLENDER=1;WITH_QUICKTIME;INTERNATIONAL;WITH_FREETYPE2;WITH_INTERNATIONAL;WITH_OPENEXR;WITH_DDS;WITH_BULLET=1;WITH_FFMPEG" PreprocessorDefinitions="NDEBUG;WIN32;_LIB;_CONSOLE;GAMEBLENDER=1;WITH_QUICKTIME;INTERNATIONAL;WITH_FREETYPE2;WITH_INTERNATIONAL;WITH_OPENEXR;WITH_DDS;WITH_BULLET=1;WITH_FFMPEG"
StringPooling="true" StringPooling="true"
RuntimeLibrary="0" RuntimeLibrary="0"
@@ -119,7 +119,7 @@
<Tool <Tool
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
Optimization="0" Optimization="0"
AdditionalIncludeDirectories="..\..\..\..\lib\windows\QTDevWin\CIncludes;..\..\..\..\lib\windows\sdl\include;..\..\..\..\lib\windows\python\include\python2.6;..\..\..\..\build\msvc_9\intern\bsp\include;..\..\..\..\build\msvc_9\intern\ghost\include;..\..\..\..\build\msvc_9\intern\elbeem\include;..\..\..\..\build\msvc_9\intern\opennl\include;..\..\..\..\build\msvc_9\intern\bmfont\include;..\..\..\..\build\msvc_9\intern\blenkey\include;..\..\..\..\build\msvc_9\intern\decimation\include;..\..\..\..\build\msvc_9\intern\memutil\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\intern\smoke\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\source\blender;..\..\..\source\blender\img;..\..\..\source\blender\verify;..\..\..\source\blender\ftfont;..\..\..\source\blender\misc;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\python;..\..\..\source\blender\editors\include;..\..\..\source\blender\renderui;..\..\..\source\blender\blenloader;..\..\..\source\blender\quicktime;..\..\..\source\blender\blenkernel;..\..\..\source\blender\blenfont;..\..\..\source\blender\makesdna;..\..\..\source\blender\makesrna;..\..\..\source\blender\nodes;..\..\..\source\blender\windowmanager;..\..\..\source\blender\blenpluginapi;..\..\..\source\blender\renderconverter;..\..\..\source\blender\readstreamglue;..\..\..\source\blender\render\extern\include;..\..\..\source\blender\radiosity\extern\include;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\network;..\..\..\source\gameengine\soundsystem\snd_openal;..\..\..\..\build\msvc_9\extern\verse\include;..\..\..\..\lib\windows\pthreads\include;..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\source\blender\gpu;..\..\..\intern\audaspace\intern;..\..\..\source\blender\ikplugin" AdditionalIncludeDirectories="..\..\..\..\lib\windows\QTDevWin\CIncludes;..\..\..\..\lib\windows\sdl\include;..\..\..\..\lib\windows\python\include\python2.6;..\..\..\..\build\msvc_9\intern\bsp\include;..\..\..\..\build\msvc_9\intern\ghost\include;..\..\..\..\build\msvc_9\intern\elbeem\include;..\..\..\..\build\msvc_9\intern\opennl\include;..\..\..\..\build\msvc_9\intern\bmfont\include;..\..\..\..\build\msvc_9\intern\blenkey\include;..\..\..\..\build\msvc_9\intern\decimation\include;..\..\..\..\build\msvc_9\intern\memutil\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\intern\smoke\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\source\blender;..\..\..\source\blender\img;..\..\..\source\blender\verify;..\..\..\source\blender\ftfont;..\..\..\source\blender\misc;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\python;..\..\..\source\blender\editors\include;..\..\..\source\blender\editors\interface;..\..\..\source\blender\renderui;..\..\..\source\blender\blenloader;..\..\..\source\blender\quicktime;..\..\..\source\blender\blenkernel;..\..\..\source\blender\blenfont;..\..\..\source\blender\makesdna;..\..\..\source\blender\makesrna;..\..\..\source\blender\nodes;..\..\..\source\blender\windowmanager;..\..\..\source\blender\blenpluginapi;..\..\..\source\blender\renderconverter;..\..\..\source\blender\readstreamglue;..\..\..\source\blender\render\extern\include;..\..\..\source\blender\radiosity\extern\include;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\network;..\..\..\source\gameengine\soundsystem\snd_openal;..\..\..\..\build\msvc_9\extern\verse\include;..\..\..\..\lib\windows\pthreads\include;..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\source\blender\gpu;..\..\..\intern\audaspace\intern;..\..\..\source\blender\ikplugin"
PreprocessorDefinitions="_DEBUG;WIN32;_LIB;_CONSOLE;GAMEBLENDER=1;WITH_QUICKTIME;INTERNATIONAL;WITH_BF_INTERNATIONAL;WITH_FREETYPE2;WITH_OPENEXR;WITH_DDS;WITH_BULLET = 1;WITH_FFMPEG" PreprocessorDefinitions="_DEBUG;WIN32;_LIB;_CONSOLE;GAMEBLENDER=1;WITH_QUICKTIME;INTERNATIONAL;WITH_BF_INTERNATIONAL;WITH_FREETYPE2;WITH_OPENEXR;WITH_DDS;WITH_BULLET = 1;WITH_FFMPEG"
BasicRuntimeChecks="3" BasicRuntimeChecks="3"
RuntimeLibrary="1" RuntimeLibrary="1"
@@ -459,6 +459,10 @@
<Filter <Filter
Name="space_view3d" Name="space_view3d"
> >
<File
RelativePath="..\..\..\source\blender\editors\space_view3d\drawanimviz.c"
>
</File>
<File <File
RelativePath="..\..\..\source\blender\editors\space_view3d\drawarmature.c" RelativePath="..\..\..\source\blender\editors\space_view3d\drawarmature.c"
> >

View File

@@ -349,6 +349,10 @@
RelativePath="..\..\..\source\blender\nodes\intern\CMP_nodes\CMP_chromaMatte.c" RelativePath="..\..\..\source\blender\nodes\intern\CMP_nodes\CMP_chromaMatte.c"
> >
</File> </File>
<File
RelativePath="..\..\..\source\blender\nodes\intern\CMP_nodes\CMP_colorbalance.c"
>
</File>
<File <File
RelativePath="..\..\..\source\blender\nodes\intern\CMP_nodes\CMP_colorMatte.c" RelativePath="..\..\..\source\blender\nodes\intern\CMP_nodes\CMP_colorMatte.c"
> >
@@ -409,6 +413,10 @@
RelativePath="..\..\..\source\blender\nodes\intern\CMP_nodes\CMP_glare.c" RelativePath="..\..\..\source\blender\nodes\intern\CMP_nodes\CMP_glare.c"
> >
</File> </File>
<File
RelativePath="..\..\..\source\blender\nodes\intern\CMP_nodes\CMP_huecorrect.c"
>
</File>
<File <File
RelativePath="..\..\..\source\blender\nodes\intern\CMP_nodes\CMP_hueSatVal.c" RelativePath="..\..\..\source\blender\nodes\intern\CMP_nodes\CMP_hueSatVal.c"
> >

Binary file not shown.

Before

Width:  |  Height:  |  Size: 204 KiB

After

Width:  |  Height:  |  Size: 205 KiB

View File

@@ -146,7 +146,7 @@ def write_pov(filename, scene=None, info_callback=None):
file.write('\tup <0, 1, 0>\n') file.write('\tup <0, 1, 0>\n')
file.write('\tangle %f \n' % (360.0 * atan(16.0 / camera.data.lens) / pi)) file.write('\tangle %f \n' % (360.0 * atan(16.0 / camera.data.lens) / pi))
file.write('\trotate <%.6f, %.6f, %.6f>\n' % tuple([degrees(e) for e in matrix.rotationPart().toEuler()])) file.write('\trotate <%.6f, %.6f, %.6f>\n' % tuple([degrees(e) for e in matrix.rotation_part().to_euler()]))
file.write('\ttranslate <%.6f, %.6f, %.6f>\n' % (matrix[3][0], matrix[3][1], matrix[3][2])) file.write('\ttranslate <%.6f, %.6f, %.6f>\n' % (matrix[3][0], matrix[3][1], matrix[3][2]))
file.write('}\n') file.write('}\n')

View File

@@ -839,7 +839,7 @@ def make_track_chunk(ID, obj):
track_chunk.add_variable("position", _3ds_point_3d(obj.getLocation())) track_chunk.add_variable("position", _3ds_point_3d(obj.getLocation()))
elif ID==ROT_TRACK_TAG: elif ID==ROT_TRACK_TAG:
# rotation (quaternion, angle first, followed by axis): # rotation (quaternion, angle first, followed by axis):
q = obj.getEuler().toQuat() q = obj.getEuler().to_quat()
track_chunk.add_variable("rotation", _3ds_point_4d((q.angle, q.axis[0], q.axis[1], q.axis[2]))) track_chunk.add_variable("rotation", _3ds_point_4d((q.angle, q.axis[0], q.axis[1], q.axis[2])))
elif ID==SCL_TRACK_TAG: elif ID==SCL_TRACK_TAG:
# scale vector: # scale vector:

View File

@@ -146,7 +146,7 @@ def eulerRadToDeg(eul):
mtx4_identity = Mathutils.Matrix() mtx4_identity = Mathutils.Matrix()
# testing # testing
mtx_x90 = Mathutils.RotationMatrix( math.pi/2, 3, 'x') # used mtx_x90 = Mathutils.RotationMatrix( math.pi/2, 3, 'X') # used
#mtx_x90n = RotationMatrix(-90, 3, 'x') #mtx_x90n = RotationMatrix(-90, 3, 'x')
#mtx_y90 = RotationMatrix( 90, 3, 'y') #mtx_y90 = RotationMatrix( 90, 3, 'y')
#mtx_y90n = RotationMatrix(-90, 3, 'y') #mtx_y90n = RotationMatrix(-90, 3, 'y')
@@ -154,11 +154,11 @@ mtx_x90 = Mathutils.RotationMatrix( math.pi/2, 3, 'x') # used
#mtx_z90n = RotationMatrix(-90, 3, 'z') #mtx_z90n = RotationMatrix(-90, 3, 'z')
#mtx4_x90 = RotationMatrix( 90, 4, 'x') #mtx4_x90 = RotationMatrix( 90, 4, 'x')
mtx4_x90n = Mathutils.RotationMatrix(-math.pi/2, 4, 'x') # used mtx4_x90n = Mathutils.RotationMatrix(-math.pi/2, 4, 'X') # used
#mtx4_y90 = RotationMatrix( 90, 4, 'y') #mtx4_y90 = RotationMatrix( 90, 4, 'y')
mtx4_y90n = Mathutils.RotationMatrix(-math.pi/2, 4, 'y') # used mtx4_y90n = Mathutils.RotationMatrix(-math.pi/2, 4, 'Y') # used
mtx4_z90 = Mathutils.RotationMatrix( math.pi/2, 4, 'z') # used mtx4_z90 = Mathutils.RotationMatrix( math.pi/2, 4, 'Z') # used
mtx4_z90n = Mathutils.RotationMatrix(-math.pi/2, 4, 'z') # used mtx4_z90n = Mathutils.RotationMatrix(-math.pi/2, 4, 'Z') # used
# def strip_path(p): # def strip_path(p):
# return p.split('\\')[-1].split('/')[-1] # return p.split('\\')[-1].split('/')[-1]
@@ -590,9 +590,9 @@ def write(filename, batch_objects = None, \
def getAnimParRelMatrixRot(self, frame): def getAnimParRelMatrixRot(self, frame):
type = self.blenObject.type type = self.blenObject.type
if self.fbxParent: if self.fbxParent:
matrix_rot = (((self.__anim_poselist[frame] * GLOBAL_MATRIX) * (self.fbxParent.__anim_poselist[frame] * GLOBAL_MATRIX).invert())).rotationPart() matrix_rot = (((self.__anim_poselist[frame] * GLOBAL_MATRIX) * (self.fbxParent.__anim_poselist[frame] * GLOBAL_MATRIX).invert())).rotation_part()
else: else:
matrix_rot = (self.__anim_poselist[frame] * GLOBAL_MATRIX).rotationPart() matrix_rot = (self.__anim_poselist[frame] * GLOBAL_MATRIX).rotation_part()
# Lamps need to be rotated # Lamps need to be rotated
if type =='LAMP': if type =='LAMP':
@@ -600,7 +600,7 @@ def write(filename, batch_objects = None, \
elif type =='CAMERA': elif type =='CAMERA':
# elif ob and type =='Camera': # elif ob and type =='Camera':
y = Mathutils.Vector(0,1,0) * matrix_rot y = Mathutils.Vector(0,1,0) * matrix_rot
matrix_rot = matrix_rot * Mathutils.RotationMatrix(math.pi/2, 3, 'r', y) matrix_rot = matrix_rot * Mathutils.RotationMatrix(math.pi/2, 3, y)
return matrix_rot return matrix_rot
@@ -676,11 +676,11 @@ def write(filename, batch_objects = None, \
# par_matrix = mtx4_z90 * parent.matrix['ARMATURESPACE'] # dont apply armature matrix anymore # par_matrix = mtx4_z90 * parent.matrix['ARMATURESPACE'] # dont apply armature matrix anymore
matrix = matrix * par_matrix.copy().invert() matrix = matrix * par_matrix.copy().invert()
matrix_rot = matrix.rotationPart() matrix_rot = matrix.rotation_part()
loc = tuple(matrix.translationPart()) loc = tuple(matrix.translation_part())
scale = tuple(matrix.scalePart()) scale = tuple(matrix.scale_part())
rot = tuple(matrix_rot.toEuler()) rot = tuple(matrix_rot.to_euler())
else: else:
# This is bad because we need the parent relative matrix from the fbx parent (if we have one), dont use anymore # This is bad because we need the parent relative matrix from the fbx parent (if we have one), dont use anymore
@@ -692,20 +692,20 @@ def write(filename, batch_objects = None, \
# matrix = matrix_scale * matrix # matrix = matrix_scale * matrix
if matrix: if matrix:
loc = tuple(matrix.translationPart()) loc = tuple(matrix.translation_part())
scale = tuple(matrix.scalePart()) scale = tuple(matrix.scale_part())
matrix_rot = matrix.rotationPart() matrix_rot = matrix.rotation_part()
# Lamps need to be rotated # Lamps need to be rotated
if ob and ob.type =='Lamp': if ob and ob.type =='Lamp':
matrix_rot = mtx_x90 * matrix_rot matrix_rot = mtx_x90 * matrix_rot
rot = tuple(matrix_rot.toEuler()) rot = tuple(matrix_rot.to_euler())
elif ob and ob.type =='Camera': elif ob and ob.type =='Camera':
y = Mathutils.Vector(0,1,0) * matrix_rot y = Mathutils.Vector(0,1,0) * matrix_rot
matrix_rot = matrix_rot * Mathutils.RotationMatrix(math.pi/2, 3, 'r', y) matrix_rot = matrix_rot * Mathutils.RotationMatrix(math.pi/2, 3, y)
rot = tuple(matrix_rot.toEuler()) rot = tuple(matrix_rot.to_euler())
else: else:
rot = tuple(matrix_rot.toEuler()) rot = tuple(matrix_rot.to_euler())
else: else:
if not loc: if not loc:
loc = 0,0,0 loc = 0,0,0
@@ -1131,7 +1131,7 @@ def write(filename, batch_objects = None, \
else: else:
do_light = 1 do_light = 1
scale = abs(GLOBAL_MATRIX.scalePart()[0]) # scale is always uniform in this case scale = abs(GLOBAL_MATRIX.scale_part()[0]) # scale is always uniform in this case
file.write('\n\t\t\tProperty: "LightType", "enum", "",%i' % light_type) file.write('\n\t\t\tProperty: "LightType", "enum", "",%i' % light_type)
file.write('\n\t\t\tProperty: "CastLightOnObject", "bool", "",1') file.write('\n\t\t\tProperty: "CastLightOnObject", "bool", "",1')
@@ -1753,7 +1753,7 @@ def write(filename, batch_objects = None, \
for uf in uvlayer.data: for uf in uvlayer.data:
# for f in me.faces: # for f in me.faces:
# workaround, since uf.uv iteration is wrong atm # workaround, since uf.uv iteration is wrong atm
for uv in [uf.uv1, uf.uv2, uf.uv3, uf.uv4][:len(uf.uv)]: for uv in uf.uv:
# for uv in f.uv: # for uv in f.uv:
if i==-1: if i==-1:
file.write('%.6f,%.6f' % tuple(uv)) file.write('%.6f,%.6f' % tuple(uv))
@@ -2866,18 +2866,18 @@ Takes: {''')
# ---------------- # ----------------
for TX_LAYER, TX_CHAN in enumerate('TRS'): # transform, rotate, scale for TX_LAYER, TX_CHAN in enumerate('TRS'): # transform, rotate, scale
if TX_CHAN=='T': context_bone_anim_vecs = [mtx[0].translationPart() for mtx in context_bone_anim_mats] if TX_CHAN=='T': context_bone_anim_vecs = [mtx[0].translation_part() for mtx in context_bone_anim_mats]
elif TX_CHAN=='S': context_bone_anim_vecs = [mtx[0].scalePart() for mtx in context_bone_anim_mats] elif TX_CHAN=='S': context_bone_anim_vecs = [mtx[0].scale_part() for mtx in context_bone_anim_mats]
elif TX_CHAN=='R': elif TX_CHAN=='R':
# Was.... # Was....
# elif TX_CHAN=='R': context_bone_anim_vecs = [mtx[1].toEuler() for mtx in context_bone_anim_mats] # elif TX_CHAN=='R': context_bone_anim_vecs = [mtx[1].to_euler() for mtx in context_bone_anim_mats]
# #
# ...but we need to use the previous euler for compatible conversion. # ...but we need to use the previous euler for compatible conversion.
context_bone_anim_vecs = [] context_bone_anim_vecs = []
prev_eul = None prev_eul = None
for mtx in context_bone_anim_mats: for mtx in context_bone_anim_mats:
if prev_eul: prev_eul = mtx[1].toEuler(prev_eul) if prev_eul: prev_eul = mtx[1].to_euler(prev_eul)
else: prev_eul = mtx[1].toEuler() else: prev_eul = mtx[1].to_euler()
context_bone_anim_vecs.append(eulerRadToDeg(prev_eul)) context_bone_anim_vecs.append(eulerRadToDeg(prev_eul))
# context_bone_anim_vecs.append(prev_eul) # context_bone_anim_vecs.append(prev_eul)

View File

@@ -564,7 +564,7 @@ def write(filename, objects, scene,
tface = uv_layer.data[f_index] tface = uv_layer.data[f_index]
# workaround, since tface.uv iteration is wrong atm # workaround, since tface.uv iteration is wrong atm
uvs = [tface.uv1, tface.uv2, tface.uv3, tface.uv4][:len(tface.uv)] uvs = tface.uv
# uvs = [tface.uv1, tface.uv2, tface.uv3] # uvs = [tface.uv1, tface.uv2, tface.uv3]
# # add another UV if it's a quad # # add another UV if it's a quad

View File

@@ -81,7 +81,7 @@ from export_3ds import create_derived_objects, free_derived_objects
# #
DEG2RAD=0.017453292519943295 DEG2RAD=0.017453292519943295
MATWORLD= Mathutils.RotationMatrix(-90, 4, 'x') MATWORLD= Mathutils.RotationMatrix(-90, 4, 'X')
#################################### ####################################
# Global Variables # Global Variables
@@ -239,8 +239,8 @@ class x3d_class:
# get the camera location, subtract 90 degress from X to orient like X3D does # get the camera location, subtract 90 degress from X to orient like X3D does
# mat = ob.matrixWorld - mat is now passed! # mat = ob.matrixWorld - mat is now passed!
loc = self.rotatePointForVRML(mat.translationPart()) loc = self.rotatePointForVRML(mat.translation_part())
rot = mat.toEuler() rot = mat.to_euler()
rot = (((rot[0]-90)), rot[1], rot[2]) rot = (((rot[0]-90)), rot[1], rot[2])
# rot = (((rot[0]-90)*DEG2RAD), rot[1]*DEG2RAD, rot[2]*DEG2RAD) # rot = (((rot[0]-90)*DEG2RAD), rot[1]*DEG2RAD, rot[2]*DEG2RAD)
nRot = self.rotatePointForVRML( rot ) nRot = self.rotatePointForVRML( rot )
@@ -300,8 +300,8 @@ class x3d_class:
# note -dz seems to equal om[3][1] # note -dz seems to equal om[3][1]
# note dy seems to equal om[3][2] # note dy seems to equal om[3][2]
#location=(ob.matrixWorld*MATWORLD).translationPart() # now passed #location=(ob.matrixWorld*MATWORLD).translation_part() # now passed
location=(mtx*MATWORLD).translationPart() location=(mtx*MATWORLD).translation_part()
radius = lamp.distance*math.cos(beamWidth) radius = lamp.distance*math.cos(beamWidth)
# radius = lamp.dist*math.cos(beamWidth) # radius = lamp.dist*math.cos(beamWidth)
@@ -346,8 +346,8 @@ class x3d_class:
ambi = 0 ambi = 0
ambientIntensity = 0 ambientIntensity = 0
# location=(ob.matrixWorld*MATWORLD).translationPart() # now passed # location=(ob.matrixWorld*MATWORLD).translation_part() # now passed
location= (mtx*MATWORLD).translationPart() location= (mtx*MATWORLD).translation_part()
self.file.write("<PointLight DEF=\"%s\" " % safeName) self.file.write("<PointLight DEF=\"%s\" " % safeName)
self.file.write("ambientIntensity=\"%s\" " % (round(ambientIntensity,self.cp))) self.file.write("ambientIntensity=\"%s\" " % (round(ambientIntensity,self.cp)))
@@ -364,8 +364,8 @@ class x3d_class:
return return
else: else:
dx,dy,dz = self.computeDirection(mtx) dx,dy,dz = self.computeDirection(mtx)
# location=(ob.matrixWorld*MATWORLD).translationPart() # location=(ob.matrixWorld*MATWORLD).translation_part()
location=(mtx*MATWORLD).translationPart() location=(mtx*MATWORLD).translation_part()
self.writeIndented("<%s\n" % obname,1) self.writeIndented("<%s\n" % obname,1)
self.writeIndented("direction=\"%s %s %s\"\n" % (round(dx,3),round(dy,3),round(dz,3))) self.writeIndented("direction=\"%s %s %s\"\n" % (round(dx,3),round(dy,3),round(dz,3)))
self.writeIndented("location=\"%s %s %s\"\n" % (round(location[0],3), round(location[1],3), round(location[2],3))) self.writeIndented("location=\"%s %s %s\"\n" % (round(location[0],3), round(location[1],3), round(location[2],3)))
@@ -448,9 +448,9 @@ class x3d_class:
# mtx = ob.matrixWorld * MATWORLD # mtx is now passed # mtx = ob.matrixWorld * MATWORLD # mtx is now passed
mtx = mtx * MATWORLD mtx = mtx * MATWORLD
loc= mtx.translationPart() loc= mtx.translation_part()
sca= mtx.scalePart() sca= mtx.scale_part()
quat = mtx.toQuat() quat = mtx.to_quat()
rot= quat.axis rot= quat.axis
self.writeIndented('<Transform DEF="%s" translation="%.6f %.6f %.6f" scale="%.6f %.6f %.6f" rotation="%.6f %.6f %.6f %.6f">\n' % \ self.writeIndented('<Transform DEF="%s" translation="%.6f %.6f %.6f" scale="%.6f %.6f %.6f" rotation="%.6f %.6f %.6f %.6f">\n' % \
@@ -617,7 +617,7 @@ class x3d_class:
for face in mesh.active_uv_texture.data: for face in mesh.active_uv_texture.data:
# for face in mesh.faces: # for face in mesh.faces:
# workaround, since tface.uv iteration is wrong atm # workaround, since tface.uv iteration is wrong atm
uvs = [face.uv1, face.uv2, face.uv3, face.uv4][:len(face.uv)] uvs = face.uv
# uvs = [face.uv1, face.uv2, face.uv3, face.uv4] if face.verts[3] else [face.uv1, face.uv2, face.uv3] # uvs = [face.uv1, face.uv2, face.uv3, face.uv4] if face.verts[3] else [face.uv1, face.uv2, face.uv3]
for uv in uvs: for uv in uvs:
@@ -1048,7 +1048,7 @@ class x3d_class:
def computeDirection(self, mtx): def computeDirection(self, mtx):
x,y,z=(0,-1.0,0) # point down x,y,z=(0,-1.0,0) # point down
ax,ay,az = (mtx*MATWORLD).toEuler() ax,ay,az = (mtx*MATWORLD).to_euler()
# ax *= DEG2RAD # ax *= DEG2RAD
# ay *= DEG2RAD # ay *= DEG2RAD

View File

@@ -89,13 +89,13 @@ MATRIX_IDENTITY_4x4 = Matrix([1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1])
def eulerRotate(x,y,z, rot_order): def eulerRotate(x,y,z, rot_order):
# Clamp all values between 0 and 360, values outside this raise an error. # Clamp all values between 0 and 360, values outside this raise an error.
mats=[RotationMatrix(math.radians(x%360),3,'x'), RotationMatrix(math.radians(y%360),3,'y'), RotationMatrix(math.radians(z%360),3,'z')] mats=[RotationMatrix(math.radians(x % 360), 3, 'X'), RotationMatrix(math.radians(y % 360),3,'Y'), RotationMatrix(math.radians(z % 360), 3, 'Z')]
# print rot_order # print rot_order
# Standard BVH multiplication order, apply the rotation in the order Z,X,Y # Standard BVH multiplication order, apply the rotation in the order Z,X,Y
#XXX, order changes??? #XXX, order changes???
#eul = (mats[rot_order[2]]*(mats[rot_order[1]]* (mats[rot_order[0]]* MATRIX_IDENTITY_3x3))).toEuler() #eul = (mats[rot_order[2]]*(mats[rot_order[1]]* (mats[rot_order[0]]* MATRIX_IDENTITY_3x3))).to_euler()
eul = (MATRIX_IDENTITY_3x3*mats[rot_order[0]]*(mats[rot_order[1]]* (mats[rot_order[2]]))).toEuler() eul = (MATRIX_IDENTITY_3x3*mats[rot_order[0]]*(mats[rot_order[1]]* (mats[rot_order[2]]))).to_euler()
eul = math.degrees(eul.x), math.degrees(eul.y), math.degrees(eul.z) eul = math.degrees(eul.x), math.degrees(eul.y), math.degrees(eul.z)
@@ -534,8 +534,8 @@ def bvh_node_dict2armature(context, bvh_nodes, IMPORT_START_FRAME= 1, IMPORT_LOO
bone_name= bvh_node.temp # may not be the same name as the bvh_node, could have been shortened. bone_name= bvh_node.temp # may not be the same name as the bvh_node, could have been shortened.
pose_bone= pose_bones[bone_name] pose_bone= pose_bones[bone_name]
rest_bone= arm_data.bones[bone_name] rest_bone= arm_data.bones[bone_name]
#XXX bone_rest_matrix = rest_bone.matrix['ARMATURESPACE'].rotationPart() #XXX bone_rest_matrix = rest_bone.matrix['ARMATURESPACE'].rotation_part()
bone_rest_matrix = rest_bone.matrix.rotationPart() bone_rest_matrix = rest_bone.matrix.rotation_part()
bone_rest_matrix_inv= Matrix(bone_rest_matrix) bone_rest_matrix_inv= Matrix(bone_rest_matrix)
@@ -575,31 +575,31 @@ def bvh_node_dict2armature(context, bvh_nodes, IMPORT_START_FRAME= 1, IMPORT_LOO
if ROT_STYLE=='QUAT': if ROT_STYLE=='QUAT':
# Set the rotation, not so simple # Set the rotation, not so simple
bone_rotation_matrix= Euler(math.radians(rx), math.radians(ry), math.radians(rz)).toMatrix() bone_rotation_matrix= Euler(math.radians(rx), math.radians(ry), math.radians(rz)).to_matrix()
bone_rotation_matrix.resize4x4() bone_rotation_matrix.resize4x4()
#XXX ORDER CHANGE??? #XXX ORDER CHANGE???
#pose_bone.rotation_quaternion= (bone_rest_matrix * bone_rotation_matrix * bone_rest_matrix_inv).toQuat() # ORIGINAL #pose_bone.rotation_quaternion= (bone_rest_matrix * bone_rotation_matrix * bone_rest_matrix_inv).to_quat() # ORIGINAL
# pose_bone.rotation_quaternion= (bone_rest_matrix_inv * bone_rotation_matrix * bone_rest_matrix).toQuat() # pose_bone.rotation_quaternion= (bone_rest_matrix_inv * bone_rotation_matrix * bone_rest_matrix).to_quat()
# pose_bone.rotation_quaternion= (bone_rotation_matrix * bone_rest_matrix).toQuat() # BAD # pose_bone.rotation_quaternion= (bone_rotation_matrix * bone_rest_matrix).to_quat() # BAD
# pose_bone.rotation_quaternion= bone_rotation_matrix.toQuat() # NOT GOOD # pose_bone.rotation_quaternion= bone_rotation_matrix.to_quat() # NOT GOOD
# pose_bone.rotation_quaternion= bone_rotation_matrix.toQuat() # NOT GOOD # pose_bone.rotation_quaternion= bone_rotation_matrix.to_quat() # NOT GOOD
#pose_bone.rotation_quaternion= (bone_rotation_matrix * bone_rest_matrix_inv * bone_rest_matrix).toQuat() #pose_bone.rotation_quaternion= (bone_rotation_matrix * bone_rest_matrix_inv * bone_rest_matrix).to_quat()
#pose_bone.rotation_quaternion= (bone_rest_matrix_inv * bone_rest_matrix * bone_rotation_matrix).toQuat() #pose_bone.rotation_quaternion= (bone_rest_matrix_inv * bone_rest_matrix * bone_rotation_matrix).to_quat()
#pose_bone.rotation_quaternion= (bone_rest_matrix * bone_rotation_matrix * bone_rest_matrix_inv).toQuat() #pose_bone.rotation_quaternion= (bone_rest_matrix * bone_rotation_matrix * bone_rest_matrix_inv).to_quat()
#pose_bone.rotation_quaternion= ( bone_rest_matrix* bone_rest_matrix_inv * bone_rotation_matrix).toQuat() #pose_bone.rotation_quaternion= ( bone_rest_matrix* bone_rest_matrix_inv * bone_rotation_matrix).to_quat()
#pose_bone.rotation_quaternion= (bone_rotation_matrix * bone_rest_matrix * bone_rest_matrix_inv).toQuat() #pose_bone.rotation_quaternion= (bone_rotation_matrix * bone_rest_matrix * bone_rest_matrix_inv).to_quat()
#pose_bone.rotation_quaternion= (bone_rest_matrix_inv * bone_rotation_matrix * bone_rest_matrix ).toQuat() #pose_bone.rotation_quaternion= (bone_rest_matrix_inv * bone_rotation_matrix * bone_rest_matrix ).to_quat()
pose_bone.rotation_quaternion= (bone_rest_matrix_inv * bone_rotation_matrix * bone_rest_matrix).toQuat() pose_bone.rotation_quaternion= (bone_rest_matrix_inv * bone_rotation_matrix * bone_rest_matrix).to_quat()
else: else:
bone_rotation_matrix= Euler(math.radians(rx), math.radians(ry), math.radians(rz)).toMatrix() bone_rotation_matrix= Euler(math.radians(rx), math.radians(ry), math.radians(rz)).to_matrix()
bone_rotation_matrix.resize4x4() bone_rotation_matrix.resize4x4()
eul= (bone_rest_matrix * bone_rotation_matrix * bone_rest_matrix_inv).toEuler() eul= (bone_rest_matrix * bone_rotation_matrix * bone_rest_matrix_inv).to_euler()
#pose_bone.rotation_euler = math.radians(rx), math.radians(ry), math.radians(rz) #pose_bone.rotation_euler = math.radians(rx), math.radians(ry), math.radians(rz)
pose_bone.rotation_euler = eul pose_bone.rotation_euler = eul
@@ -610,8 +610,8 @@ def bvh_node_dict2armature(context, bvh_nodes, IMPORT_START_FRAME= 1, IMPORT_LOO
# Set the Location, simple too # Set the Location, simple too
#XXX ORDER CHANGE #XXX ORDER CHANGE
# pose_bone.location= (TranslationMatrix(Vector(lx, ly, lz) - bvh_node.rest_head_local ) * bone_rest_matrix_inv).translationPart() # WHY * 10? - just how pose works # pose_bone.location= (TranslationMatrix(Vector(lx, ly, lz) - bvh_node.rest_head_local ) * bone_rest_matrix_inv).translation_part() # WHY * 10? - just how pose works
# pose_bone.location= (bone_rest_matrix_inv * TranslationMatrix(Vector(lx, ly, lz) - bvh_node.rest_head_local )).translationPart() # pose_bone.location= (bone_rest_matrix_inv * TranslationMatrix(Vector(lx, ly, lz) - bvh_node.rest_head_local )).translation_part()
# pose_bone.location= lx, ly, lz # pose_bone.location= lx, ly, lz
pose_bone.location= Vector(lx, ly, lz) - bvh_node.rest_head_local pose_bone.location= Vector(lx, ly, lz) - bvh_node.rest_head_local
@@ -714,12 +714,12 @@ def bvh_node_dict2armature(context, bvh_nodes, IMPORT_START_FRAME= 1, IMPORT_LOO
def pose_rot(anim_data): def pose_rot(anim_data):
bone_rotation_matrix= Euler(anim_data[3], anim_data[4], anim_data[5]).toMatrix() bone_rotation_matrix= Euler(anim_data[3], anim_data[4], anim_data[5]).to_matrix()
bone_rotation_matrix.resize4x4() bone_rotation_matrix.resize4x4()
return tuple((bone_rest_matrix * bone_rotation_matrix * bone_rest_matrix_inv).toQuat()) # qw,qx,qy,qz return tuple((bone_rest_matrix * bone_rotation_matrix * bone_rest_matrix_inv).to_quat()) # qw,qx,qy,qz
def pose_loc(anim_data): def pose_loc(anim_data):
return tuple((TranslationMatrix(Vector(anim_data[0], anim_data[1], anim_data[2])) * bone_rest_matrix_inv).translationPart()) return tuple((TranslationMatrix(Vector(anim_data[0], anim_data[1], anim_data[2])) * bone_rest_matrix_inv).translation_part())
last_frame= len(bvh_node.anim_data)+IMPORT_START_FRAME-1 last_frame= len(bvh_node.anim_data)+IMPORT_START_FRAME-1

View File

@@ -34,8 +34,8 @@ from bpy import ops as _ops_module
# fake operator module # fake operator module
ops = _ops_module.ops_fake_module ops = _ops_module.ops_fake_module
import sys import sys as _sys
DEBUG = ("-d" in sys.argv) DEBUG = ("-d" in _sys.argv)
def load_scripts(reload_scripts=False): def load_scripts(reload_scripts=False):
@@ -65,6 +65,12 @@ def load_scripts(reload_scripts=False):
traceback.print_exc() traceback.print_exc()
return None return None
def test_reload(module):
try:
reload(module)
except:
traceback.print_exc()
if reload_scripts: if reload_scripts:
# reload modules that may not be directly included # reload modules that may not be directly included
for type_class_name in dir(types): for type_class_name in dir(types):
@@ -76,14 +82,14 @@ def load_scripts(reload_scripts=False):
for module_name in loaded_modules: for module_name in loaded_modules:
print("Reloading:", module_name) print("Reloading:", module_name)
reload(sys.modules[module_name]) test_reload(_sys.modules[module_name])
for base_path in utils.script_paths(): for base_path in utils.script_paths():
for path_subdir in ("ui", "op", "io"): for path_subdir in ("ui", "op", "io"):
path = os.path.join(base_path, path_subdir) path = os.path.join(base_path, path_subdir)
if os.path.isdir(path): if os.path.isdir(path):
if path not in sys.path: # reloading would add twice if path not in _sys.path: # reloading would add twice
sys.path.insert(0, path) _sys.path.insert(0, path)
for f in sorted(os.listdir(path)): for f in sorted(os.listdir(path)):
if f.endswith(".py"): if f.endswith(".py"):
# python module # python module
@@ -96,7 +102,7 @@ def load_scripts(reload_scripts=False):
if reload_scripts and mod: if reload_scripts and mod:
print("Reloading:", mod) print("Reloading:", mod)
reload(mod) test_reload(mod)
if DEBUG: if DEBUG:
print("Time %.4f" % (time.time() - t_main)) print("Time %.4f" % (time.time() - t_main))
@@ -104,10 +110,13 @@ def load_scripts(reload_scripts=False):
def _main(): def _main():
# security issue, dont allow the $CWD in the path.
_sys.path[:] = filter(None, _sys.path)
# a bit nasty but this prevents help() and input() from locking blender # a bit nasty but this prevents help() and input() from locking blender
# Ideally we could have some way for the console to replace sys.stdin but # Ideally we could have some way for the console to replace sys.stdin but
# python would lock blender while waiting for a return value, not easy :| # python would lock blender while waiting for a return value, not easy :|
sys.stdin = None _sys.stdin = None
# if "-d" in sys.argv: # Enable this to measure startup speed # if "-d" in sys.argv: # Enable this to measure startup speed
if 0: if 0:

View File

@@ -18,6 +18,27 @@
# <pep8 compliant> # <pep8 compliant>
"""
This module contains application values that remain unchanged during runtime.
.. data:: version
The Blender version as a tuple of 3 numbers. eg. (2, 50, 11)
.. data:: version_string
The Blender version formatted as a string.
.. data:: home
The blender home directory, normally matching $HOME
.. data:: binary_path
The location of blenders executable, useful for utilities that spawn new instances.
"""
# constants # constants
import _bpy import _bpy
version = _bpy._VERSION version = _bpy._VERSION

View File

@@ -134,7 +134,7 @@ class bpy_ops_submodule_op(object):
def idname(self): def idname(self):
# submod.foo -> SUBMOD_OT_foo # submod.foo -> SUBMOD_OT_foo
return self.module.upper() + '_OT_' + self.func return self.module + '.' + self.func
def __call__(self, *args, **kw): def __call__(self, *args, **kw):

View File

@@ -18,13 +18,18 @@
# <pep8 compliant> # <pep8 compliant>
import bpy """
import os This module contains utility functions spesific to blender but
not assosiated with blenders internal data.
"""
import bpy as _bpy
import os as _os
def expandpath(path): def expandpath(path):
if path.startswith("//"): if path.startswith("//"):
return os.path.join(os.path.dirname(bpy.data.filename), path[2:]) return _os.path.join(_os.path.dirname(_bpy.data.filename), path[2:])
return path return path
@@ -47,67 +52,74 @@ _unclean_chars = ''.join([chr(i) for i in _unclean_chars])
def clean_name(name, replace="_"): def clean_name(name, replace="_"):
''' """
Returns a name with characters replaced that may cause problems under various circumstances, such as writing to a file.
All characters besides A-Z/a-z, 0-9 are replaced with "_" All characters besides A-Z/a-z, 0-9 are replaced with "_"
or the replace argumet if defined. or the replace argumet if defined.
''' """
for ch in _unclean_chars: for ch in _unclean_chars:
name = name.replace(ch, replace) name = name.replace(ch, replace)
return name return name
def display_name(name): def display_name(name):
''' """
Only capitalize all lowercase names, mixed case use them as is. Creates a display string from name to be used menus and the user interface.
should work with filenames and module names. Capitalize the first letter in all lowercase names, mixed case names are kept as is.
''' Intended for use with filenames and module names.
name_base = os.path.splitext(name)[0] """
name_base = _os.path.splitext(name)[0]
# string replacements # string replacements
name_base = name_base.replace("_colon_", ":") name_base = name_base.replace("_colon_", ":")
name_base = name_base.replace("_", " ") name_base = name_base.replace("_", " ")
if name_base.lower() == name_base: if name_base.islower():
return ' '.join([w[0].upper() + w[1:] for w in name_base.split()]) return name_base.capitalize()
else: else:
return name_base return name_base
# base scripts # base scripts
_scripts = os.path.join(os.path.dirname(__file__), os.path.pardir, os.path.pardir) _scripts = _os.path.join(_os.path.dirname(__file__), _os.path.pardir, _os.path.pardir)
_scripts = (os.path.normpath(_scripts), ) _scripts = (_os.path.normpath(_scripts), )
def script_paths(*args): def script_paths(*args):
"""
Returns a list of valid script paths from the home directory and user preferences.
Accepts any number of string arguments which are joined to make a path.
"""
scripts = list(_scripts) scripts = list(_scripts)
# add user scripts dir # add user scripts dir
user_script_path = bpy.context.user_preferences.filepaths.python_scripts_directory user_script_path = _bpy.context.user_preferences.filepaths.python_scripts_directory
if not user_script_path: if not user_script_path:
# XXX - WIN32 needs checking, perhaps better call a blender internal function. # XXX - WIN32 needs checking, perhaps better call a blender internal function.
user_script_path = os.path.join(os.path.expanduser("~"), ".blender", "scripts") user_script_path = _os.path.join(_os.path.expanduser("~"), ".blender", "scripts")
user_script_path = os.path.normpath(user_script_path) user_script_path = _os.path.normpath(user_script_path)
if user_script_path not in scripts and os.path.isdir(user_script_path): if user_script_path not in scripts and _os.path.isdir(user_script_path):
scripts.append(user_script_path) scripts.append(user_script_path)
if not args: if not args:
return scripts return scripts
subdir = os.path.join(*args) subdir = _os.path.join(*args)
script_paths = [] script_paths = []
for path in scripts: for path in scripts:
path_subdir = os.path.join(path, subdir) path_subdir = _os.path.join(path, subdir)
if os.path.isdir(path_subdir): if _os.path.isdir(path_subdir):
script_paths.append(path_subdir) script_paths.append(path_subdir)
return script_paths return script_paths
_presets = os.path.join(_scripts[0], "presets") # FIXME - multiple paths _presets = _os.path.join(_scripts[0], "presets") # FIXME - multiple paths
def preset_paths(subdir): def preset_paths(subdir):
@@ -115,4 +127,4 @@ def preset_paths(subdir):
Returns a list of paths for a spesific preset. Returns a list of paths for a spesific preset.
''' '''
return (os.path.join(_presets, subdir), ) return (_os.path.join(_presets, subdir), )

View File

@@ -94,19 +94,19 @@ class _GenericBone:
def x_axis(self): def x_axis(self):
""" Vector pointing down the x-axis of the bone. """ Vector pointing down the x-axis of the bone.
""" """
return self.matrix.rotationPart() * Vector(1,0,0) return self.matrix.rotation_part() * Vector(1,0,0)
@property @property
def y_axis(self): def y_axis(self):
""" Vector pointing down the x-axis of the bone. """ Vector pointing down the x-axis of the bone.
""" """
return self.matrix.rotationPart() * Vector(0,1,0) return self.matrix.rotation_part() * Vector(0,1,0)
@property @property
def z_axis(self): def z_axis(self):
""" Vector pointing down the x-axis of the bone. """ Vector pointing down the x-axis of the bone.
""" """
return self.matrix.rotationPart() * Vector(0,0,1) return self.matrix.rotation_part() * Vector(0,0,1)
@property @property
def basename(self): def basename(self):
@@ -236,7 +236,7 @@ class EditBone(StructRNA, _GenericBone):
Expects a 4x4 or 3x3 matrix. Expects a 4x4 or 3x3 matrix.
""" """
from Mathutils import Vector from Mathutils import Vector
z_vec = self.matrix.rotationPart() * Vector(0.0, 0.0, 1.0) z_vec = self.matrix.rotation_part() * Vector(0.0, 0.0, 1.0)
self.tail = matrix * self.tail self.tail = matrix * self.tail
self.head = matrix * self.head self.head = matrix * self.head
scalar = matrix.median_scale scalar = matrix.median_scale
@@ -421,8 +421,8 @@ class OrderedMeta(type):
# Only defined so operators members can be used by accessing self.order # Only defined so operators members can be used by accessing self.order
class Operator(StructRNA, metaclass=OrderedMeta): #class Operator(StructRNA, metaclass=OrderedMeta):
__slots__ = () # __slots__ = ()
class Macro(StructRNA, metaclass=OrderedMeta): class Macro(StructRNA, metaclass=OrderedMeta):

View File

@@ -30,14 +30,14 @@ def get_hub(co, _hubs, EPS_SPLINE):
if (hub.co - co).length < EPS_SPLINE: if (hub.co - co).length < EPS_SPLINE:
return hub return hub
key = co.toTuple(3) key = co.to_tuple(3)
hub = _hubs[key] = Hub(co, key, len(_hubs)) hub = _hubs[key] = Hub(co, key, len(_hubs))
return hub return hub
else: else:
pass pass
''' '''
key = co.toTuple(3) key = co.to_tuple(3)
try: try:
return _hubs[key] return _hubs[key]
except: except:
@@ -274,9 +274,7 @@ def get_splines(gp):
def xsect_spline(sp_a, sp_b, _hubs): def xsect_spline(sp_a, sp_b, _hubs):
from Mathutils import LineIntersect from Geometry import ClosestPointOnLine, LineIntersect
from Mathutils import MidpointVecs
from Geometry import ClosestPointOnLine
pt_a_prev = pt_b_prev = None pt_a_prev = pt_b_prev = None
EPS_SPLINE = (sp_a.length + sp_b.length) / (EPS_SPLINE_DIV * 2) EPS_SPLINE = (sp_a.length + sp_b.length) / (EPS_SPLINE_DIV * 2)
pt_a_prev = sp_a.points[0] pt_a_prev = sp_a.points[0]
@@ -296,7 +294,7 @@ def xsect_spline(sp_a, sp_b, _hubs):
# if f >= 0.0-EPS_SPLINE and f <= 1.0+EPS_SPLINE: # if f >= 0.0-EPS_SPLINE and f <= 1.0+EPS_SPLINE:
if f >= 0.0 and f <= 1.0: if f >= 0.0 and f <= 1.0:
# This wont happen often # This wont happen often
co = MidpointVecs(xsect[0], xsect[1]) co = xsect[0].lerp(xsect[1], 0.5)
hub = get_hub(co, _hubs, EPS_SPLINE) hub = get_hub(co, _hubs, EPS_SPLINE)
sp_a.hubs.append((a, hub)) sp_a.hubs.append((a, hub))
@@ -309,7 +307,6 @@ def xsect_spline(sp_a, sp_b, _hubs):
def connect_splines(splines): def connect_splines(splines):
HASH_PREC = 8 HASH_PREC = 8
from Mathutils import AngleBetweenVecs
from math import radians from math import radians
ANG_LIMIT = radians(ANGLE_JOIN_LIMIT) ANG_LIMIT = radians(ANGLE_JOIN_LIMIT)
def sort_pair(a, b): def sort_pair(a, b):
@@ -341,7 +338,7 @@ def connect_splines(splines):
v1 = p1a - p1b v1 = p1a - p1b
v2 = p2b - p2a v2 = p2b - p2a
if AngleBetweenVecs(v1, v2) > ANG_LIMIT: if v1.angle(v2) > ANG_LIMIT:
return False return False
# print("joining!") # print("joining!")
@@ -354,8 +351,8 @@ def connect_splines(splines):
while do_join: while do_join:
do_join = False do_join = False
for i, s1 in enumerate(splines): for i, s1 in enumerate(splines):
key1a = s1.points[0].toTuple(HASH_PREC) key1a = s1.points[0].to_tuple(HASH_PREC)
key1b = s1.points[-1].toTuple(HASH_PREC) key1b = s1.points[-1].to_tuple(HASH_PREC)
for j, s2 in enumerate(splines): for j, s2 in enumerate(splines):
if s1 is s2: if s1 is s2:
@@ -363,8 +360,8 @@ def connect_splines(splines):
length_average = min(s1.length, s2.length) length_average = min(s1.length, s2.length)
key2a = s2.points[0].toTuple(HASH_PREC) key2a = s2.points[0].to_tuple(HASH_PREC)
key2b = s2.points[-1].toTuple(HASH_PREC) key2b = s2.points[-1].to_tuple(HASH_PREC)
# there are 4 ways this may be joined # there are 4 ways this may be joined
key_pair = sort_pair(key1a, key2a) key_pair = sort_pair(key1a, key2a)

View File

@@ -154,6 +154,8 @@ def generate_rig(context, obj_orig, prefix="ORG-", META_DEF=True):
from collections import OrderedDict from collections import OrderedDict
import rigify_utils import rigify_utils
reload(rigify_utils) reload(rigify_utils)
print("Begin...")
# Not needed but catches any errors before duplicating # Not needed but catches any errors before duplicating
validate_rig(context, obj_orig) validate_rig(context, obj_orig)
@@ -164,23 +166,85 @@ def generate_rig(context, obj_orig, prefix="ORG-", META_DEF=True):
rest_backup = obj_orig.data.pose_position rest_backup = obj_orig.data.pose_position
obj_orig.data.pose_position = 'REST' obj_orig.data.pose_position = 'REST'
bpy.ops.object.mode_set(mode='OBJECT') bpy.ops.object.mode_set(mode='OBJECT')
scene = context.scene scene = context.scene
# copy object and data # Check if the generated rig already exists, so we can
# regenerate in the same object. If not, create a new
# object to generate the rig in.
print("Fetch rig.")
try:
name = obj_orig["rig_object_name"]
except KeyError:
name = "rig"
try:
obj = scene.objects[name]
except KeyError:
obj = bpy.data.objects.new(name, type='ARMATURE')
obj.data = bpy.data.armatures.new(name)
scene.objects.link(obj)
obj.data.pose_position = 'POSE'
# Get rid of anim data in case the rig already existed
print("Clear rig animation data.")
obj.animation_data_clear()
# Select generated rig object
obj_orig.selected = False obj_orig.selected = False
obj = obj_orig.copy()
obj.data = obj_orig.data.copy()
scene.objects.link(obj)
scene.objects.active = obj
obj.selected = True obj.selected = True
scene.objects.active = obj
# Remove all bones from the generated rig armature.
bpy.ops.object.mode_set(mode='EDIT')
for bone in obj.data.edit_bones:
obj.data.edit_bones.remove(bone)
bpy.ops.object.mode_set(mode='OBJECT')
# Create temporary duplicates for merging
temp_rig_1 = obj_orig.copy()
temp_rig_1.data = obj_orig.data.copy()
scene.objects.link(temp_rig_1)
temp_rig_2 = obj_orig.copy()
temp_rig_2.data = obj.data
scene.objects.link(temp_rig_2)
# Select the temp rigs for merging
for objt in scene.objects:
objt.selected = False # deselect all objects
temp_rig_1.selected = True
temp_rig_2.selected = True
scene.objects.active = temp_rig_2
# Merge the temporary rigs
bpy.ops.object.join(context)
# Delete the second temp rig
bpy.ops.object.delete()
# Select the generated rig
for objt in scene.objects:
objt.selected = False # deselect all objects
obj.selected = True
scene.objects.active = obj
# Copy over the pose_bone custom properties
for bone in obj_orig.pose.bones:
for prop in bone.keys():
obj.pose.bones[bone.name][prop] = bone[prop]
# Create proxy deformation rig
# TODO: remove this
if META_DEF: if META_DEF:
obj_def = obj_orig.copy() obj_def = obj_orig.copy()
obj_def.data = obj_orig.data.copy() obj_def.data = obj_orig.data.copy()
scene.objects.link(obj_def) scene.objects.link(obj_def)
scene.update()
print("On to the real work.")
arm = obj.data arm = obj.data
@@ -255,7 +319,7 @@ def generate_rig(context, obj_orig, prefix="ORG-", META_DEF=True):
# for pbone in obj.pose.bones: # for pbone in obj.pose.bones:
for pbone in bones_sorted: for pbone in bones_sorted:
bone_name = pbone.name bone_name = pbone.name
print(bone_name)
if bone_name not in bone_typeinfos: if bone_name not in bone_typeinfos:
continue continue
@@ -268,6 +332,7 @@ def generate_rig(context, obj_orig, prefix="ORG-", META_DEF=True):
bone_names_pre = {bone.name for bone in arm.bones} bone_names_pre = {bone.name for bone in arm.bones}
for type_name, type_func in bone_typeinfos[bone_name]: for type_name, type_func in bone_typeinfos[bone_name]:
print(" " + type_name)
# this bones definition of the current typeinfo # this bones definition of the current typeinfo
definition = bone_def_dict[type_name] definition = bone_def_dict[type_name]
options = get_bone_type_options(pbone, type_name) options = get_bone_type_options(pbone, type_name)
@@ -386,7 +451,10 @@ def generate_rig(context, obj_orig, prefix="ORG-", META_DEF=True):
bpy.ops.object.mode_set(mode=mode_orig) bpy.ops.object.mode_set(mode=mode_orig)
obj_orig.data.pose_position = rest_backup obj_orig.data.pose_position = rest_backup
obj.data.pose_position = 'POSE' obj.data.pose_position = 'POSE'
obj_orig.data.pose_position = 'POSE'
context.user_preferences.edit.global_undo = global_undo context.user_preferences.edit.global_undo = global_undo
print("Done.\n")
return obj return obj
@@ -431,7 +499,7 @@ def generate_test(context, metarig_type="", GENERATE_FINAL=True):
else: else:
new_objects.append((obj, None)) new_objects.append((obj, None))
else: else:
print("note: rig type '%s' has no metarig_template(), can't test this", module_name) print("note: rig type '%s' has no metarig_template(), can't test this" % module_name)
return new_objects return new_objects

View File

@@ -19,7 +19,7 @@
# <pep8 compliant> # <pep8 compliant>
import bpy import bpy
from math import radians from math import radians, pi
from rigify import RigifyError, get_layer_dict, ORG_PREFIX from rigify import RigifyError, get_layer_dict, ORG_PREFIX
from rigify_utils import bone_class_instance, copy_bone_simple, add_pole_target_bone, add_stretch_to, blend_bone_list, get_side_name, get_base_name from rigify_utils import bone_class_instance, copy_bone_simple, add_pole_target_bone, add_stretch_to, blend_bone_list, get_side_name, get_base_name
from rna_prop_ui import rna_idprop_ui_prop_get from rna_prop_ui import rna_idprop_ui_prop_get
@@ -162,7 +162,7 @@ def ik(obj, definitions, base_names, options):
con.use_target = True con.use_target = True
con.use_rotation = False con.use_rotation = False
con.chain_length = 2 con.chain_length = 2
con.pole_angle = -90.0 # XXX, RAD2DEG con.pole_angle = -pi/2
# last step setup layers # last step setup layers
if "ik_layer" in options: if "ik_layer" in options:
@@ -223,6 +223,7 @@ def fk(obj, definitions, base_names, options):
fk_chain.forearm_p.rotation_mode = 'XYZ' fk_chain.forearm_p.rotation_mode = 'XYZ'
fk_chain.forearm_p.lock_rotation = (False, True, True) fk_chain.forearm_p.lock_rotation = (False, True, True)
fk_chain.hand_p.rotation_mode = 'ZXY' fk_chain.hand_p.rotation_mode = 'ZXY'
fk_chain.arm_p.lock_location = True, True, True
con = fk_chain.arm_p.constraints.new('COPY_LOCATION') con = fk_chain.arm_p.constraints.new('COPY_LOCATION')
con.target = obj con.target = obj
@@ -276,7 +277,14 @@ def fk(obj, definitions, base_names, options):
fk_chain.arm_b.layer = layer fk_chain.arm_b.layer = layer
fk_chain.forearm_b.layer = layer fk_chain.forearm_b.layer = layer
fk_chain.hand_b.layer = layer fk_chain.hand_b.layer = layer
# Forearm was getting wrong roll somehow. Hack to fix that.
bpy.ops.object.mode_set(mode='EDIT')
fk_chain.update()
mt.update()
fk_chain.forearm_e.roll = mt.forearm_e.roll
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.mode_set(mode='EDIT') bpy.ops.object.mode_set(mode='EDIT')
return None, fk_chain.arm, fk_chain.forearm, fk_chain.hand return None, fk_chain.arm, fk_chain.forearm, fk_chain.hand
@@ -338,6 +346,11 @@ def deform(obj, definitions, base_names, options):
con.target = obj con.target = obj
con.subtarget = definitions[2] con.subtarget = definitions[2]
con = uarm1.constraints.new('COPY_SCALE')
con.name = "trackto"
con.target = obj
con.subtarget = definitions[1]
con = uarm2.constraints.new('COPY_ROTATION') con = uarm2.constraints.new('COPY_ROTATION')
con.name = "copy_rot" con.name = "copy_rot"
con.target = obj con.target = obj
@@ -349,6 +362,11 @@ def deform(obj, definitions, base_names, options):
con.target = obj con.target = obj
con.subtarget = definitions[2] con.subtarget = definitions[2]
con = farm1.constraints.new('COPY_SCALE')
con.name = "copy_rot"
con.target = obj
con.subtarget = definitions[2]
con = farm2.constraints.new('COPY_ROTATION') con = farm2.constraints.new('COPY_ROTATION')
con.name = "copy_rot" con.name = "copy_rot"
con.target = obj con.target = obj

View File

@@ -127,8 +127,8 @@ def main(obj, bone_definition, base_names, options):
delta_pbone.rotation_mode = 'XYZ' delta_pbone.rotation_mode = 'XYZ'
rot = delta_pmatrix.invert().rotationPart() * child_pmatrix.rotationPart() rot = delta_pmatrix.invert().rotation_part() * child_pmatrix.rotation_part()
rot = rot.invert().toEuler() rot = rot.invert().to_euler()
fcurve_drivers = delta_pbone.driver_add("rotation_euler", -1) fcurve_drivers = delta_pbone.driver_add("rotation_euler", -1)
for i, fcurve_driver in enumerate(fcurve_drivers): for i, fcurve_driver in enumerate(fcurve_drivers):
@@ -141,7 +141,7 @@ def main(obj, bone_definition, base_names, options):
mod.coefficients[1] = 0.0 mod.coefficients[1] = 0.0
# tricky, find the transform to drive the bone to this location. # tricky, find the transform to drive the bone to this location.
delta_head_offset = child_pmatrix.rotationPart() * (delta_phead - child_phead) delta_head_offset = child_pmatrix.rotation_part() * (delta_phead - child_phead)
fcurve_drivers = delta_pbone.driver_add("location", -1) fcurve_drivers = delta_pbone.driver_add("location", -1)
for i, fcurve_driver in enumerate(fcurve_drivers): for i, fcurve_driver in enumerate(fcurve_drivers):

View File

@@ -0,0 +1,277 @@
# ##### 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from rna_prop_ui import rna_idprop_ui_prop_get
from math import acos
from Mathutils import Vector
from rigify import get_layer_dict
from rigify_utils import bone_class_instance, copy_bone_simple
#METARIG_NAMES = ("cpy",)
RIG_TYPE = "eye_balls"
def mark_actions():
for action in bpy.data.actions:
action.tag = True
def get_unmarked_action():
for action in bpy.data.actions:
if action.tag != True:
return action
return None
def add_action(name=None):
mark_actions()
bpy.ops.action.new()
action = get_unmarked_action()
if name is not None:
action.name = name
return action
def metarig_template():
# generated by rigify.write_meta_rig
bpy.ops.object.mode_set(mode='EDIT')
obj = bpy.context.active_object
arm = obj.data
bone = arm.edit_bones.new('Bone')
bone.head[:] = 0.0000, 0.0000, 0.0000
bone.tail[:] = 0.0000, 0.0000, 1.0000
bone.roll = 0.0000
bone.connected = False
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones['Bone']
pbone['type'] = 'copy'
def metarig_definition(obj, orig_bone_name):
bone = obj.data.bones[orig_bone_name]
chain = []
try:
chain += [bone.parent.name, bone.name]
except AttributeError:
raise RigifyError("'%s' rig type requires a parent (bone: %s)" % (RIG_TYPE, base_names[0]))
return chain
def deform(obj, definitions, base_names, options):
bpy.ops.object.mode_set(mode='EDIT')
eb = obj.data.edit_bones
pb = obj.pose.bones
# Get list of eyes
if "eyes" in options:
eye_base_names = options["eyes"].replace(" ", "").split(",")
else:
eye_base_names = []
# Get their ORG- names
eyes = []
for name in eye_base_names:
eyes += ["ORG-"+name]
# Duplicate the eyes to make deformation bones
def_eyes = [] # def/org pairs
for eye in eyes:
def_eyes += [(copy_bone_simple(obj.data, eye, "DEF-"+base_names[eye], parent=True).name, eye)]
bpy.ops.object.mode_set(mode='OBJECT')
# Constraints
for eye in def_eyes:
con = pb[eye[0]].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = eye[1]
return (None,)
def control(obj, definitions, base_names, options):
bpy.ops.object.mode_set(mode='EDIT')
eb = obj.data.edit_bones
bb = obj.data.bones
pb = obj.pose.bones
head = definitions[0]
eye_target = definitions[1]
# Get list of eyes
if "eyes" in options:
eye_base_names = options["eyes"].replace(" ", "").split(",")
else:
eye_base_names = []
# Get their ORG- names
eyes = []
for name in eye_base_names:
eyes += ["ORG-"+name]
# Get the average position of the eyes
center = Vector(0,0,0)
for eye in eyes:
center += eb[eye].head
if len(eyes) != 0:
center /= len(eyes)
# Get the average length of the eyes
length = 0.0
for eye in eyes:
length += eb[eye].length
if len(eyes) == 0:
length = 1.0
else:
length /= len(eyes)
# Make the mind's eye
minds_eye = copy_bone_simple(obj.data, eye_target, "MCH-"+base_names[eye_target]+".mind", parent=True).name
eb[minds_eye].head = center
eb[minds_eye].tail = eb[eye_target].head
eb[minds_eye].roll = 0.0
eb[minds_eye].length = length
# Create org/copy/control eye sets
eye_sets = []
for eye in eyes:
copy = copy_bone_simple(obj.data, minds_eye, "MCH-"+base_names[eye]+".cpy", parent=True).name
eb[copy].translate(eb[eye].head - eb[copy].head)
eb[copy].parent = eb[eye].parent
control = copy_bone_simple(obj.data, eye, base_names[eye], parent=True).name
eb[control].parent = eb[copy]
eye_sets += [(eye, copy, control)]
# Bones for parent/free switch for eye target
target_ctrl = copy_bone_simple(obj.data, eye_target, base_names[eye_target], parent=True).name
parent = copy_bone_simple(obj.data, head, "MCH-eye_target_parent", parent=False).name
eb[target_ctrl].parent = eb[parent]
bpy.ops.object.mode_set(mode='OBJECT')
# Axis locks
pb[target_ctrl].lock_scale = False, True, True
# Add eye_spread action if it doesn't already exist
action_name = "eye_spread"
if action_name in bpy.data.actions:
spread_action = bpy.data.actions[action_name]
else:
spread_action = add_action(name=action_name)
# Add free property
prop_name = "free"
prop = rna_idprop_ui_prop_get(pb[target_ctrl], prop_name, create=True)
pb[target_ctrl][prop_name] = 0.0
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
prop["min"] = 0.0
prop["max"] = 1.0
free_driver_path = pb[target_ctrl].path_to_id() + '["free"]'
# Constraints
# Mind's eye tracks eye target control
con = pb[minds_eye].constraints.new('DAMPED_TRACK')
con.target = obj
con.subtarget = target_ctrl
# Parent copies transforms of head
con = pb[parent].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = head
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
driver.type = 'AVERAGE'
mod = fcurve.modifiers[0]
mod.coefficients[0] = 1.0
mod.coefficients[1] = -1.0
var = driver.variables.new()
var.name = "free"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = free_driver_path
# Eye set's constraints
for eye in eye_sets:
# Org copies transforms of control
con = pb[eye[0]].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = eye[2]
# Copy copies rotation of mind's eye
con = pb[eye[1]].constraints.new('COPY_ROTATION')
con.target = obj
con.subtarget = minds_eye
# Control gets action constraint for eye spread
con = pb[eye[2]].constraints.new('ACTION')
con.target = obj
con.subtarget = target_ctrl
con.action = spread_action
con.transform_channel = 'SCALE_X'
con.start_frame = -20
con.end_frame = 20
con.minimum = 0.0
con.maximum = 2.0
con.target_space = 'LOCAL'
# Set layers
#layer = list(bb[definitions[2]].layer)
#bb[lid1].layer = layer
#bb[lid2].layer = layer
#bb[lid3].layer = layer
#bb[lid4].layer = layer
#bb[lid5].layer = layer
#bb[lid6].layer = layer
#bb[lid7].layer = layer
#bb[lid8].layer = layer
return (None,)
def main(obj, bone_definition, base_names, options):
# Create control rig
control(obj, bone_definition, base_names, options)
# Create deform rig
deform(obj, bone_definition, base_names, options)
return (None,)

View File

@@ -0,0 +1,686 @@
# ##### 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from rna_prop_ui import rna_idprop_ui_prop_get
from math import acos
from Mathutils import Vector
from rigify import get_layer_dict
from rigify_utils import bone_class_instance, copy_bone_simple
#METARIG_NAMES = ("cpy",)
RIG_TYPE = "eye_lid"
def mark_actions():
for action in bpy.data.actions:
action.tag = True
def get_unmarked_action():
for action in bpy.data.actions:
if action.tag != True:
return action
return None
def add_action(name=None):
mark_actions()
bpy.ops.action.new()
action = get_unmarked_action()
if name is not None:
action.name = name
return action
def metarig_template():
# generated by rigify.write_meta_rig
bpy.ops.object.mode_set(mode='EDIT')
obj = bpy.context.active_object
arm = obj.data
bone = arm.edit_bones.new('Bone')
bone.head[:] = 0.0000, 0.0000, 0.0000
bone.tail[:] = 0.0000, 0.0000, 1.0000
bone.roll = 0.0000
bone.connected = False
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones['Bone']
pbone['type'] = 'copy'
def metarig_definition(obj, orig_bone_name):
bb = obj.data.bones
bone = bb[orig_bone_name]
chain = []
try:
chain += [bone.parent.parent.name, bone.parent.name, bone.name]
except AttributeError:
raise RigifyError("'%s' rig type requires a chain of two parents (bone: %s)" % (RIG_TYPE, base_names[0]))
chain += [child.name for child in bone.children_recursive_basename]
if len(chain) < 10:
raise RigifyError("'%s' rig type requires a chain of 10 bones (bone: %s)" % (RIG_TYPE, base_names[0]))
chain = chain[:10]
try:
chain += [bb[chain[9]].children[0].name]
chain += [bb[chain[10]].children[0].name]
except IndexError:
raise RigifyError("'%s' rig type requires a chain of 10 bones (bone: %s)" % (RIG_TYPE, base_names[0]))
return chain
def deform(obj, definitions, base_names, options):
bpy.ops.object.mode_set(mode='EDIT')
eb = obj.data.edit_bones
pb = obj.pose.bones
# Upper lid MCH
lid1 = make_lid_stretch_bone(obj, "MCH-lid", definitions[2], definitions[3], 1.0)
lid2 = make_lid_stretch_bone(obj, "MCH-lid", definitions[3], definitions[4], 1.0)
lid22 = make_lid_stretch_bone(obj, "MCH-lid", definitions[4], definitions[5], 1.0)
lid33 = make_lid_stretch_bone(obj, "MCH-lid", definitions[4], definitions[3], 1.0)
lid3 = make_lid_stretch_bone(obj, "MCH-lid", definitions[5], definitions[4], 1.0)
lid4 = make_lid_stretch_bone(obj, "MCH-lid", definitions[6], definitions[5], 1.0)
dlid22 = copy_bone_simple(obj.data, lid22, "MCH-lid", parent=True).name
dlid33 = copy_bone_simple(obj.data, lid33, "MCH-lid", parent=True).name
eb[dlid22].bbone_segments = 8
eb[dlid33].bbone_segments = 8
eb[lid1].parent = eb[definitions[2]]
eb[lid2].parent = eb[definitions[3]]
eb[lid22].parent = eb[definitions[4]]
eb[lid33].parent = eb[definitions[4]]
eb[lid3].parent = eb[definitions[5]]
eb[lid4].parent = eb[definitions[6]]
# Lower lid MCH
lid5 = make_lid_stretch_bone(obj, "MCH-lid", definitions[6], definitions[7], 1.0)
lid6 = make_lid_stretch_bone(obj, "MCH-lid", definitions[7], definitions[8], 1.0)
lid66 = make_lid_stretch_bone(obj, "MCH-lid", definitions[8], definitions[9], 1.0)
lid77 = make_lid_stretch_bone(obj, "MCH-lid", definitions[8], definitions[7], 1.0)
lid7 = make_lid_stretch_bone(obj, "MCH-lid", definitions[9], definitions[8], 1.0)
lid8 = make_lid_stretch_bone(obj, "MCH-lid", definitions[2], definitions[9], 1.0)
dlid66 = copy_bone_simple(obj.data, lid66, "MCH-lid", parent=True).name
dlid77 = copy_bone_simple(obj.data, lid77, "MCH-lid", parent=True).name
eb[dlid66].bbone_segments = 8
eb[dlid77].bbone_segments = 8
eb[lid5].parent = eb[definitions[6]]
eb[lid6].parent = eb[definitions[7]]
eb[lid66].parent = eb[definitions[8]]
eb[lid77].parent = eb[definitions[8]]
eb[lid7].parent = eb[definitions[9]]
eb[lid8].parent = eb[definitions[2]]
# Upper lid DEF
dlid1 = copy_bone_simple(obj.data, lid1, "DEF-" + base_names[definitions[2]], parent=True).name
dlid2 = copy_bone_simple(obj.data, lid2, "DEF-" + base_names[definitions[3]], parent=True).name
dlid3 = copy_bone_simple(obj.data, lid3, "DEF-" + base_names[definitions[4]], parent=True).name
dlid4 = copy_bone_simple(obj.data, lid4, "DEF-" + base_names[definitions[5]], parent=True).name
eb[dlid2].parent = eb[dlid1]
eb[dlid22].parent = eb[dlid2]
eb[dlid3].parent = eb[dlid4]
eb[dlid33].parent = eb[dlid3]
eb[dlid2].connected = True
eb[dlid22].connected = True
eb[dlid3].connected = True
eb[dlid33].connected = True
eb[dlid1].bbone_segments = 8
eb[dlid2].bbone_segments = 8
eb[dlid3].bbone_segments = 8
eb[dlid4].bbone_segments = 8
# Lower lid DEF
dlid5 = copy_bone_simple(obj.data, lid5, "DEF-" + base_names[definitions[6]], parent=True).name
dlid6 = copy_bone_simple(obj.data, lid6, "DEF-" + base_names[definitions[7]], parent=True).name
dlid7 = copy_bone_simple(obj.data, lid7, "DEF-" + base_names[definitions[8]], parent=True).name
dlid8 = copy_bone_simple(obj.data, lid8, "DEF-" + base_names[definitions[9]], parent=True).name
eb[dlid6].parent = eb[dlid5]
eb[dlid66].parent = eb[dlid6]
eb[dlid7].parent = eb[dlid8]
eb[dlid77].parent = eb[dlid7]
eb[dlid6].connected = True
eb[dlid66].connected = True
eb[dlid7].connected = True
eb[dlid77].connected = True
eb[dlid5].bbone_segments = 8
eb[dlid6].bbone_segments = 8
eb[dlid7].bbone_segments = 8
eb[dlid8].bbone_segments = 8
bpy.ops.object.mode_set(mode='OBJECT')
# Constraints
con = pb[dlid1].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lid1
con = pb[dlid22].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lid22
con = pb[dlid33].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lid33
con = pb[dlid2].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lid2
con = pb[dlid3].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lid3
con = pb[dlid4].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lid4
con = pb[dlid5].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lid5
con = pb[dlid6].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lid6
con = pb[dlid66].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lid66
con = pb[dlid77].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lid77
con = pb[dlid7].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lid7
con = pb[dlid8].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lid8
return (None,)
def control(obj, definitions, base_names, options):
bpy.ops.object.mode_set(mode='EDIT')
eb = obj.data.edit_bones
bb = obj.data.bones
pb = obj.pose.bones
head_e = eb[definitions[0]]
eye_e = eb[definitions[1]]
# Make eye "flower"
flo1 = copy_bone_simple(obj.data, definitions[1], "MCH-"+base_names[definitions[2]]+".flower", parent=True).name
flo2 = copy_bone_simple(obj.data, definitions[1], "MCH-"+base_names[definitions[3]]+".flower", parent=True).name
flo3 = copy_bone_simple(obj.data, definitions[1], "MCH-"+base_names[definitions[4]]+".flower", parent=True).name
flo4 = copy_bone_simple(obj.data, definitions[1], "MCH-"+base_names[definitions[5]]+".flower", parent=True).name
flo5 = copy_bone_simple(obj.data, definitions[1], "MCH-"+base_names[definitions[6]]+".flower", parent=True).name
flo6 = copy_bone_simple(obj.data, definitions[1], "MCH-"+base_names[definitions[7]]+".flower", parent=True).name
flo7 = copy_bone_simple(obj.data, definitions[1], "MCH-"+base_names[definitions[8]]+".flower", parent=True).name
flo8 = copy_bone_simple(obj.data, definitions[1], "MCH-"+base_names[definitions[9]]+".flower", parent=True).name
eb[flo1].tail = eb[definitions[2]].head
eb[flo2].tail = eb[definitions[3]].head
eb[flo3].tail = eb[definitions[4]].head
eb[flo4].tail = eb[definitions[5]].head
eb[flo5].tail = eb[definitions[6]].head
eb[flo6].tail = eb[definitions[7]].head
eb[flo7].tail = eb[definitions[8]].head
eb[flo8].tail = eb[definitions[9]].head
# Make eye lids on tips of flowers
flid1 = copy_bone_simple(obj.data, definitions[2], "MCH-"+base_names[definitions[2]]).name
flid2 = copy_bone_simple(obj.data, definitions[3], "MCH-"+base_names[definitions[3]]).name
flid3 = copy_bone_simple(obj.data, definitions[4], "MCH-"+base_names[definitions[4]]).name
flid4 = copy_bone_simple(obj.data, definitions[5], "MCH-"+base_names[definitions[5]]).name
flid5 = copy_bone_simple(obj.data, definitions[6], "MCH-"+base_names[definitions[6]]).name
flid6 = copy_bone_simple(obj.data, definitions[7], "MCH-"+base_names[definitions[7]]).name
flid7 = copy_bone_simple(obj.data, definitions[8], "MCH-"+base_names[definitions[8]]).name
flid8 = copy_bone_simple(obj.data, definitions[9], "MCH-"+base_names[definitions[9]]).name
eb[flid1].parent = eb[flo1]
eb[flid2].parent = eb[flo2]
eb[flid3].parent = eb[flo3]
eb[flid4].parent = eb[flo4]
eb[flid5].parent = eb[flo5]
eb[flid6].parent = eb[flo6]
eb[flid7].parent = eb[flo7]
eb[flid8].parent = eb[flo8]
# Make eye lid controls
lid1 = copy_bone_simple(obj.data, definitions[2], base_names[definitions[2]]).name
lid2 = copy_bone_simple(obj.data, definitions[3], base_names[definitions[3]]).name
lid3 = copy_bone_simple(obj.data, definitions[4], base_names[definitions[4]]).name
lid4 = copy_bone_simple(obj.data, definitions[5], base_names[definitions[5]]).name
lid5 = copy_bone_simple(obj.data, definitions[6], base_names[definitions[6]]).name
lid6 = copy_bone_simple(obj.data, definitions[7], base_names[definitions[7]]).name
lid7 = copy_bone_simple(obj.data, definitions[8], base_names[definitions[8]]).name
lid8 = copy_bone_simple(obj.data, definitions[9], base_names[definitions[9]]).name
size = eb[lid1].length
eb[lid1].tail = eb[lid1].head + Vector(0,size,0)
eb[lid2].tail = eb[lid2].head + Vector(0,size,0)
eb[lid3].tail = eb[lid3].head + Vector(0,size,0)
eb[lid4].tail = eb[lid4].head + Vector(0,size,0)
eb[lid5].tail = eb[lid5].head + Vector(0,size,0)
eb[lid6].tail = eb[lid6].head + Vector(0,size,0)
eb[lid7].tail = eb[lid7].head + Vector(0,size,0)
eb[lid8].tail = eb[lid8].head + Vector(0,size,0)
eb[lid1].roll = 0
eb[lid2].roll = 0
eb[lid3].roll = 0
eb[lid4].roll = 0
eb[lid5].roll = 0
eb[lid6].roll = 0
eb[lid7].roll = 0
eb[lid8].roll = 0
eb[lid1].parent = head_e
eb[lid2].parent = head_e
eb[lid3].parent = head_e
eb[lid4].parent = head_e
eb[lid5].parent = head_e
eb[lid6].parent = head_e
eb[lid7].parent = head_e
eb[lid8].parent = head_e
lower_lid_ctrl = copy_bone_simple(obj.data, definitions[10], base_names[definitions[10]]).name
upper_lid_ctrl = copy_bone_simple(obj.data, definitions[11], base_names[definitions[11]]).name
eb[lower_lid_ctrl].parent = head_e
eb[upper_lid_ctrl].parent = head_e
distance = (eb[lower_lid_ctrl].head - eb[upper_lid_ctrl].head).length
bpy.ops.object.mode_set(mode='OBJECT')
# Axis locks
pb[lower_lid_ctrl].lock_location = True, False, True
pb[upper_lid_ctrl].lock_location = True, False, True
# Add eye close action if it doesn't already exist
action_name = "eye_close"
if action_name in bpy.data.actions:
close_action = bpy.data.actions[action_name]
else:
close_action = add_action(name=action_name)
# Add close property (useful when making the animation in the action)
prop_name = "close_action"
prop = rna_idprop_ui_prop_get(pb[upper_lid_ctrl], prop_name, create=True)
pb[upper_lid_ctrl][prop_name] = 1.0
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
prop["min"] = 0.0
prop["max"] = 1.0
close_driver_path = pb[upper_lid_ctrl].path_to_id() + '["close_action"]'
# Constraints
# Flowers track lid controls
con = pb[flo1].constraints.new('DAMPED_TRACK')
con.target = obj
con.subtarget = lid1
con = pb[flo2].constraints.new('DAMPED_TRACK')
con.target = obj
con.subtarget = lid2
con = pb[flo3].constraints.new('DAMPED_TRACK')
con.target = obj
con.subtarget = lid3
con = pb[flo4].constraints.new('DAMPED_TRACK')
con.target = obj
con.subtarget = lid4
con = pb[flo5].constraints.new('DAMPED_TRACK')
con.target = obj
con.subtarget = lid5
con = pb[flo6].constraints.new('DAMPED_TRACK')
con.target = obj
con.subtarget = lid6
con = pb[flo7].constraints.new('DAMPED_TRACK')
con.target = obj
con.subtarget = lid7
con = pb[flo8].constraints.new('DAMPED_TRACK')
con.target = obj
con.subtarget = lid8
# ORG bones to flower lids
con = pb[definitions[2]].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = flid1
con = pb[definitions[3]].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = flid2
con = pb[definitions[4]].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = flid3
con = pb[definitions[5]].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = flid4
con = pb[definitions[6]].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = flid5
con = pb[definitions[7]].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = flid6
con = pb[definitions[8]].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = flid7
con = pb[definitions[9]].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = flid8
# Action constraints, upper lid
con = pb[lid1].constraints.new('ACTION')
con.target = obj
con.subtarget = upper_lid_ctrl
con.action = close_action
con.transform_channel = 'LOCATION_Y'
con.start_frame = -30
con.end_frame = 30
con.minimum = -distance*2
con.maximum = distance
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = close_driver_path
con = pb[lid2].constraints.new('ACTION')
con.target = obj
con.subtarget = upper_lid_ctrl
con.action = close_action
con.transform_channel = 'LOCATION_Y'
con.start_frame = -30
con.end_frame = 30
con.minimum = -distance*2
con.maximum = distance
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = close_driver_path
con = pb[lid3].constraints.new('ACTION')
con.target = obj
con.subtarget = upper_lid_ctrl
con.action = close_action
con.transform_channel = 'LOCATION_Y'
con.start_frame = -30
con.end_frame = 30
con.minimum = -distance*2
con.maximum = distance
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = close_driver_path
con = pb[lid4].constraints.new('ACTION')
con.target = obj
con.subtarget = upper_lid_ctrl
con.action = close_action
con.transform_channel = 'LOCATION_Y'
con.start_frame = -30
con.end_frame = 30
con.minimum = -distance*2
con.maximum = distance
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = close_driver_path
con = pb[lid5].constraints.new('ACTION')
con.target = obj
con.subtarget = upper_lid_ctrl
con.action = close_action
con.transform_channel = 'LOCATION_Y'
con.start_frame = -30
con.end_frame = 30
con.minimum = -distance*2
con.maximum = distance
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = close_driver_path
# Action constraints, lower lid
con = pb[lid5].constraints.new('ACTION')
con.target = obj
con.subtarget = lower_lid_ctrl
con.action = close_action
con.transform_channel = 'LOCATION_Y'
con.start_frame = -30
con.end_frame = 30
con.minimum = -distance
con.maximum = distance*2
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = close_driver_path
con = pb[lid6].constraints.new('ACTION')
con.target = obj
con.subtarget = lower_lid_ctrl
con.action = close_action
con.transform_channel = 'LOCATION_Y'
con.start_frame = -30
con.end_frame = 30
con.minimum = -distance
con.maximum = distance*2
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = close_driver_path
con = pb[lid7].constraints.new('ACTION')
con.target = obj
con.subtarget = lower_lid_ctrl
con.action = close_action
con.transform_channel = 'LOCATION_Y'
con.start_frame = -30
con.end_frame = 30
con.minimum = -distance
con.maximum = distance*2
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = close_driver_path
con = pb[lid8].constraints.new('ACTION')
con.target = obj
con.subtarget = lower_lid_ctrl
con.action = close_action
con.transform_channel = 'LOCATION_Y'
con.start_frame = -30
con.end_frame = 30
con.minimum = -distance
con.maximum = distance*2
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = close_driver_path
con = pb[lid1].constraints.new('ACTION')
con.target = obj
con.subtarget = lower_lid_ctrl
con.action = close_action
con.transform_channel = 'LOCATION_Y'
con.start_frame = -30
con.end_frame = 30
con.minimum = -distance
con.maximum = distance*2
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = close_driver_path
# Set layers
layer = list(bb[definitions[2]].layer)
bb[lid1].layer = layer
bb[lid2].layer = layer
bb[lid3].layer = layer
bb[lid4].layer = layer
bb[lid5].layer = layer
bb[lid6].layer = layer
bb[lid7].layer = layer
bb[lid8].layer = layer
return (None,)
def main(obj, bone_definition, base_names, options):
# Create control rig
control(obj, bone_definition, base_names, options)
# Create deform rig
deform(obj, bone_definition, base_names, options)
return (None,)
def make_lid_stretch_bone(obj, name, bone1, bone2, roll_alpha):
eb = obj.data.edit_bones
pb = obj.pose.bones
# Create the bone, pointing from bone1 to bone2
bone_e = copy_bone_simple(obj.data, bone1, name, parent=True)
bone_e.connected = False
bone_e.tail = eb[bone2].head
bone = bone_e.name
# Align the bone roll with the average direction of bone1 and bone2
vec = bone_e.y_axis.cross(((1.0-roll_alpha)*eb[bone1].y_axis) + (roll_alpha*eb[bone2].y_axis)).normalize()
ang = acos(vec * bone_e.x_axis)
bone_e.roll += ang
c1 = vec * bone_e.x_axis
bone_e.roll -= (ang*2)
c2 = vec * bone_e.x_axis
if c1 > c2:
bone_e.roll += (ang*2)
bpy.ops.object.mode_set(mode='OBJECT')
bone_p = pb[bone]
# Constrains
con = bone_p.constraints.new('COPY_LOCATION')
con.target = obj
con.subtarget = bone1
con = bone_p.constraints.new('DAMPED_TRACK')
con.target = obj
con.subtarget = bone2
con = bone_p.constraints.new('STRETCH_TO')
con.target = obj
con.subtarget = bone2
con.volume = 'NO_VOLUME'
bpy.ops.object.mode_set(mode='EDIT')
return bone

View File

@@ -150,103 +150,171 @@ def deform(obj, definitions, base_names, options):
def main(obj, bone_definition, base_names, options): def main(obj, bone_definition, base_names, options):
# *** EDITMODE # *** EDITMODE
bpy.ops.object.mode_set(mode='EDIT')
# get assosiated data # get assosiated data
arm = obj.data arm = obj.data
orig_ebone = arm.edit_bones[bone_definition[0]] bb = obj.data.bones
eb = obj.data.edit_bones
pb = obj.pose.bones
org_f1 = bone_definition[0] # Original finger bone 01
org_f2 = bone_definition[1] # Original finger bone 02
org_f3 = bone_definition[2] # Original finger bone 03
# Check options
if "bend_ratio" in options:
bend_ratio = options["bend_ratio"]
else:
bend_ratio = 0.4
yes = [1, 1.0, True, "True", "true", "Yes", "yes"]
make_hinge = False
if ("hinge" in options) and (eb[org_f1].parent is not None):
if options["hinge"] in yes:
make_hinge = True
obj.animation_data_create() # needed if its a new armature with no keys
# Needed if its a new armature with no keys
children = orig_ebone.children_recursive obj.animation_data_create()
tot_len = reduce(lambda f, ebone: f + ebone.length, children, orig_ebone.length)
# FIXME, the line below is far too arbitrary
base_name = base_names[bone_definition[0]].rsplit(".", 2)[0]
# first make a new bone at the location of the finger
#control_ebone = arm.edit_bones.new(base_name)
control_ebone = copy_bone_simple(arm, bone_definition[0], base_name + get_side_name(base_names[bone_definition[0]]), parent=True)
control_bone_name = control_ebone.name # we dont know if we get the name requested
control_ebone.connected = orig_ebone.connected
control_ebone.parent = orig_ebone.parent
control_ebone.length = tot_len
# now add bones inbetween this and its children recursively
# switching modes so store names only!
children = [ebone.name for ebone in children]
driver_bone_pairs = []
for child_bone_name in children:
child_ebone = arm.edit_bones[child_bone_name]
# finger.02 --> finger_driver.02
driver_bone_name = child_bone_name.split('.')
driver_bone_name = driver_bone_name[0] + "_driver." + ".".join(driver_bone_name[1:])
driver_ebone = copy_bone_simple(arm, child_ebone.name, driver_bone_name)
driver_ebone.length *= 0.5
# Insert driver_ebone in the chain without connected parents
driver_ebone.connected = False
driver_ebone.parent = child_ebone.parent
child_ebone.connected = False
child_ebone.parent = driver_ebone
# Add the drivers to these when in posemode.
driver_bone_pairs.append((child_bone_name, driver_bone_name))
del control_ebone
# Create the control bone
base_name = base_names[bone_definition[0]].split(".", 1)[0]
tot_len = eb[org_f1].length + eb[org_f2].length + eb[org_f3].length
control = copy_bone_simple(arm, bone_definition[0], base_name + get_side_name(base_names[bone_definition[0]]), parent=True).name
eb[control].connected = eb[org_f1].connected
eb[control].parent = eb[org_f1].parent
eb[control].length = tot_len
# Create secondary control bones
f1 = copy_bone_simple(arm, bone_definition[0], base_names[bone_definition[0]]).name
f2 = copy_bone_simple(arm, bone_definition[1], base_names[bone_definition[1]]).name
f3 = copy_bone_simple(arm, bone_definition[2], base_names[bone_definition[2]]).name
# Create driver bones
df1 = copy_bone_simple(arm, bone_definition[0], "MCH-" + base_names[bone_definition[0]]).name
eb[df1].length /= 2
df2 = copy_bone_simple(arm, bone_definition[1], "MCH-" + base_names[bone_definition[1]]).name
eb[df2].length /= 2
df3 = copy_bone_simple(arm, bone_definition[2], "MCH-" + base_names[bone_definition[2]]).name
eb[df3].length /= 2
# Set parents of the bones, interleaving the driver bones with the secondary control bones
eb[f3].connected = False
eb[df3].connected = False
eb[f2].connected = False
eb[df2].connected = False
eb[f1].connected = False
eb[df1].connected = eb[org_f1].connected
eb[f3].parent = eb[df3]
eb[df3].parent = eb[f2]
eb[f2].parent = eb[df2]
eb[df2].parent = eb[f1]
eb[f1].parent = eb[df1]
eb[df1].parent = eb[org_f1].parent
# Set up bones for hinge
if make_hinge:
socket = copy_bone_simple(arm, org_f1, "MCH-socket_"+control, parent=True).name
hinge = copy_bone_simple(arm, eb[org_f1].parent.name, "MCH-hinge_"+control).name
eb[control].connected = False
eb[control].parent = eb[hinge]
# Create the deform rig while we're still in edit mode
deform(obj, bone_definition, base_names, options) deform(obj, bone_definition, base_names, options)
# *** POSEMODE # *** POSEMODE
bpy.ops.object.mode_set(mode='OBJECT') bpy.ops.object.mode_set(mode='OBJECT')
# Set rotation modes and axis locks
orig_pbone = obj.pose.bones[bone_definition[0]] pb[control].rotation_mode = obj.pose.bones[bone_definition[0]].rotation_mode
control_pbone = obj.pose.bones[control_bone_name] pb[control].lock_location = True, True, True
control_bbone = arm.bones[control_bone_name] pb[control].lock_scale = True, False, True
control_pbone.rotation_mode = obj.pose.bones[bone_definition[0]].rotation_mode pb[f1].rotation_mode = 'YZX'
pb[f2].rotation_mode = 'YZX'
pb[f3].rotation_mode = 'YZX'
# only allow Y scale pb[f1].lock_location = True, True, True
control_pbone.lock_scale = (True, False, True) pb[f2].lock_location = True, True, True
pb[f3].lock_location = True, True, True
control_pbone["bend_ratio"] = 0.4 pb[df2].rotation_mode = 'YZX'
prop = rna_idprop_ui_prop_get(control_pbone, "bend_ratio", create=True) pb[df3].rotation_mode = 'YZX'
# Add the bend_ratio property to the control bone
pb[control]["bend_ratio"] = bend_ratio
prop = rna_idprop_ui_prop_get(pb[control], "bend_ratio", create=True)
prop["soft_min"] = 0.0 prop["soft_min"] = 0.0
prop["soft_max"] = 1.0 prop["soft_max"] = 1.0
con = orig_pbone.constraints.new('COPY_LOCATION') # Add hinge property to the control bone
if make_hinge:
pb[control]["hinge"] = 0.0
prop = rna_idprop_ui_prop_get(pb[control], "hinge", create=True)
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
# Constraints
con = pb[df1].constraints.new('COPY_LOCATION')
con.target = obj con.target = obj
con.subtarget = control_bone_name con.subtarget = control
con = orig_pbone.constraints.new('COPY_ROTATION') con = pb[df1].constraints.new('COPY_ROTATION')
con.target = obj con.target = obj
con.subtarget = control_bone_name con.subtarget = control
con = pb[org_f1].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = f1
con = pb[org_f2].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = f2
con = pb[org_f3].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = f3
if make_hinge:
con = pb[hinge].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = bb[org_f1].parent.name
hinge_driver_path = pb[control].path_to_id() + '["hinge"]'
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
var.name = "var"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = hinge_driver_path
mod = fcurve.modifiers[0]
# setup child drivers on each new smaller bone added. assume 2 for now. mod.poly_order = 1
mod.coefficients[0] = 1.0
# drives the bones mod.coefficients[1] = -1.0
controller_path = control_pbone.path_to_id() # 'pose.bones["%s"]' % control_bone_name
con = pb[control].constraints.new('COPY_LOCATION')
con.target = obj
con.subtarget = socket
# Create the drivers for the driver bones (control bone scale rotates driver bones)
controller_path = pb[control].path_to_id() # 'pose.bones["%s"]' % control_bone_name
i = 0 i = 0
for child_bone_name, driver_bone_name in driver_bone_pairs: for bone in [df2, df3]:
# XXX - todo, any number # XXX - todo, any number
if i == 2: if i == 2:
break break
driver_pbone = obj.pose.bones[driver_bone_name] pbone = pb[bone]
driver_pbone.rotation_mode = 'YZX' pbone.rotation_mode = 'YZX'
fcurve_driver = driver_pbone.driver_add("rotation_euler", 0) fcurve_driver = pbone.driver_add("rotation_euler", 0)
#obj.driver_add('pose.bones["%s"].scale', 1) #obj.driver_add('pose.bones["%s"].scale', 1)
#obj.animation_data.drivers[-1] # XXX, WATCH THIS #obj.animation_data.drivers[-1] # XXX, WATCH THIS
@@ -272,24 +340,18 @@ def main(obj, bone_definition, base_names, options):
elif i == 1: elif i == 1:
driver.expression = '(-scale+1.0)*pi*2.0*br' driver.expression = '(-scale+1.0)*pi*2.0*br'
child_pbone = obj.pose.bones[child_bone_name]
# only allow X rotation
driver_pbone.lock_rotation = child_pbone.lock_rotation = (False, True, True)
i += 1 i += 1
# Last step setup layers
# last step setup layers
if "ex_layer" in options: if "ex_layer" in options:
layer = [n==options["ex_layer"] for n in range(0,32)] layer = [n==options["ex_layer"] for n in range(0,32)]
else: else:
layer = list(arm.bones[bone_definition[0]].layer) layer = list(arm.bones[bone_definition[0]].layer)
for child_bone_name, driver_bone_name in driver_bone_pairs: for bone_name in [f1, f2, f3]:
arm.bones[driver_bone_name].layer = layer arm.bones[bone_name].layer = layer
layer = list(arm.bones[bone_definition[0]].layer) layer = list(arm.bones[bone_definition[0]].layer)
control_bbone.layer = layer bb[control].layer = layer
# no blending the result of this # no blending the result of this
return None return None

View File

@@ -19,6 +19,7 @@
# <pep8 compliant> # <pep8 compliant>
import bpy import bpy
from math import pi
from rigify import RigifyError, get_layer_dict from rigify import RigifyError, get_layer_dict
from rigify_utils import bone_class_instance, copy_bone_simple, blend_bone_list, get_side_name, get_base_name from rigify_utils import bone_class_instance, copy_bone_simple, blend_bone_list, get_side_name, get_base_name
from rna_prop_ui import rna_idprop_ui_prop_get from rna_prop_ui import rna_idprop_ui_prop_get
@@ -219,12 +220,14 @@ def ik(obj, bone_definition, base_names, options):
ik.foot_roll_p.lock_rotation = False, True, True ik.foot_roll_p.lock_rotation = False, True, True
ik_chain.toe_p.rotation_mode = 'YXZ' ik_chain.toe_p.rotation_mode = 'YXZ'
ik_chain.toe_p.lock_rotation = False, True, True ik_chain.toe_p.lock_rotation = False, True, True
ik_chain.toe_p.lock_location = True, True, True
ik.foot_roll_p.lock_location = True, True, True
# IK # IK
con = ik_chain.shin_p.constraints.new('IK') con = ik_chain.shin_p.constraints.new('IK')
con.chain_length = 2 con.chain_length = 2
con.iterations = 500 con.iterations = 500
con.pole_angle = -90.0 # XXX - in deg! con.pole_angle = -pi/2
con.use_tail = True con.use_tail = True
con.use_stretch = True con.use_stretch = True
con.use_target = True con.use_target = True
@@ -329,6 +332,7 @@ def fk(obj, bone_definition, base_names, options):
foot_p.rotation_mode = 'YXZ' foot_p.rotation_mode = 'YXZ'
fk_chain.toe_p.rotation_mode = 'YXZ' fk_chain.toe_p.rotation_mode = 'YXZ'
fk_chain.toe_p.lock_rotation = False, True, True fk_chain.toe_p.lock_rotation = False, True, True
fk_chain.thigh_p.lock_location = True, True, True
con = fk_chain.thigh_p.constraints.new('COPY_LOCATION') con = fk_chain.thigh_p.constraints.new('COPY_LOCATION')
con.target = obj con.target = obj
@@ -336,7 +340,7 @@ def fk(obj, bone_definition, base_names, options):
# hinge # hinge
prop = rna_idprop_ui_prop_get(fk_chain.thigh_p, "hinge", create=True) prop = rna_idprop_ui_prop_get(fk_chain.thigh_p, "hinge", create=True)
fk_chain.thigh_p["hinge"] = 0.5 fk_chain.thigh_p["hinge"] = 0.0
prop["soft_min"] = 0.0 prop["soft_min"] = 0.0
prop["soft_max"] = 1.0 prop["soft_max"] = 1.0
@@ -441,6 +445,11 @@ def deform(obj, definitions, base_names, options):
con.target = obj con.target = obj
con.subtarget = definitions[2] con.subtarget = definitions[2]
con = uleg1.constraints.new('COPY_SCALE')
con.name = "scale"
con.target = obj
con.subtarget = definitions[1]
con = uleg2.constraints.new('COPY_ROTATION') con = uleg2.constraints.new('COPY_ROTATION')
con.name = "copy_rot" con.name = "copy_rot"
con.target = obj con.target = obj
@@ -452,6 +461,11 @@ def deform(obj, definitions, base_names, options):
con.target = obj con.target = obj
con.subtarget = definitions[2] con.subtarget = definitions[2]
con = lleg1.constraints.new('COPY_SCALE')
con.name = "copy_rot"
con.target = obj
con.subtarget = definitions[2]
con = lleg2.constraints.new('COPY_ROTATION') con = lleg2.constraints.new('COPY_ROTATION')
con.name = "copy_rot" con.name = "copy_rot"
con.target = obj con.target = obj
@@ -484,5 +498,5 @@ def main(obj, bone_definition, base_names, options):
deform(obj, bone_definition, base_names, options) deform(obj, bone_definition, base_names, options)
bpy.ops.object.mode_set(mode='OBJECT') bpy.ops.object.mode_set(mode='OBJECT')
blend_bone_list(obj, bone_definition + [None], bones_fk, bones_ik, target_bone=bones_ik[6], target_prop="ik", blend_default=0.0) blend_bone_list(obj, bone_definition + [None], bones_fk, bones_ik, target_bone=bones_ik[6], target_prop="ik", blend_default=1.0)

View File

@@ -19,6 +19,8 @@
# <pep8 compliant> # <pep8 compliant>
import bpy import bpy
from rna_prop_ui import rna_idprop_ui_prop_get
from math import pi
from rigify import RigifyError from rigify import RigifyError
from rigify_utils import bone_class_instance, copy_bone_simple, add_pole_target_bone, get_side_name, get_base_name from rigify_utils import bone_class_instance, copy_bone_simple, add_pole_target_bone, get_side_name, get_base_name
from Mathutils import Vector from Mathutils import Vector
@@ -104,6 +106,8 @@ def metarig_definition(obj, orig_bone_name):
def ik(obj, bone_definition, base_names, options): def ik(obj, bone_definition, base_names, options):
eb = obj.data.edit_bones
pb = obj.pose.bones
arm = obj.data arm = obj.data
bpy.ops.object.mode_set(mode='EDIT') bpy.ops.object.mode_set(mode='EDIT')
@@ -114,13 +118,14 @@ def ik(obj, bone_definition, base_names, options):
mt.attr_initialize(METARIG_NAMES, bone_definition) mt.attr_initialize(METARIG_NAMES, bone_definition)
mt_chain.attr_initialize(METARIG_NAMES, bone_definition) mt_chain.attr_initialize(METARIG_NAMES, bone_definition)
ik_chain = mt_chain.copy(to_fmt="%s", base_names=base_names) ik_chain = mt_chain.copy(to_fmt="MCH-%s.ik", base_names=base_names)
ik_chain.thigh_e.connected = False ik_chain.thigh_e.connected = False
ik_chain.thigh_e.parent = mt.hips_e ik_chain.thigh_e.parent = mt.hips_e
ik_chain.foot_e.parent = None ik_chain.foot_e.parent = None
ik_chain.rename("foot", get_base_name(ik_chain.foot) + "_ik" + get_side_name(ik_chain.foot)) ik_chain.rename("foot", get_base_name(base_names[bone_definition[3]]) + "_ik" + get_side_name(base_names[bone_definition[3]]))
ik_chain.rename("toe", get_base_name(base_names[bone_definition[4]]) + "_ik" + get_side_name(base_names[bone_definition[4]]))
# keep the foot_ik as the parent # keep the foot_ik as the parent
ik_chain.toe_e.connected = False ik_chain.toe_e.connected = False
@@ -129,22 +134,30 @@ def ik(obj, bone_definition, base_names, options):
ik_chain.foot_e.align_orientation(mt_chain.toe_e) ik_chain.foot_e.align_orientation(mt_chain.toe_e)
# children of ik_foot # children of ik_foot
ik = bone_class_instance(obj, ["foot_roll", "foot_roll_01", "foot_roll_02", "knee_target", "foot_target"]) ik = bone_class_instance(obj, ["foot_roll", "foot_roll_01", "foot_roll_02", "foot_target"])
ik.knee_target = add_pole_target_bone(obj, mt_chain.shin, "knee_target" + get_side_name(base_names[mt_chain.foot])) #XXX - pick a better name # knee rotator
ik.update() knee_rotator = copy_bone_simple(arm, mt_chain.toe, "knee_rotator" + get_side_name(base_names[mt_chain.foot]), parent=True).name
ik.knee_target_e.parent = mt.hips_e eb[knee_rotator].connected = False
eb[knee_rotator].parent = eb[mt.hips]
eb[knee_rotator].head = eb[ik_chain.thigh].head
eb[knee_rotator].tail = eb[knee_rotator].head + eb[mt_chain.toe].vector
eb[knee_rotator].length = eb[ik_chain.thigh].length / 2
eb[knee_rotator].roll += pi/2
# parent ik leg to the knee rotator
eb[ik_chain.thigh].parent = eb[knee_rotator]
# foot roll is an interesting one! # foot roll is an interesting one!
# plot a vector from the toe bones head, bactwards to the length of the foot # plot a vector from the toe bones head, bactwards to the length of the foot
# then align it with the foot but reverse direction. # then align it with the foot but reverse direction.
ik.foot_roll_e = copy_bone_simple(arm, mt_chain.toe, get_base_name(base_names[mt_chain.foot]) + "_roll" + get_side_name(base_names[mt_chain.foot])) ik.foot_roll_e = copy_bone_simple(arm, mt_chain.toe, get_base_name(base_names[mt_chain.foot]) + "_roll" + get_side_name(base_names[mt_chain.foot]))
ik.foot_roll = ik.foot_roll_e.name ik.foot_roll = ik.foot_roll_e.name
ik.foot_roll_e.connected = False
ik.foot_roll_e.parent = ik_chain.foot_e ik.foot_roll_e.parent = ik_chain.foot_e
ik.foot_roll_e.translate(- (mt_chain.toe_e.vector.normalize() * mt_chain.foot_e.length)) ik.foot_roll_e.head -= mt_chain.toe_e.vector.normalize() * mt_chain.foot_e.length
ik.foot_roll_e.align_orientation(mt_chain.foot_e) ik.foot_roll_e.tail = ik.foot_roll_e.head - (mt_chain.foot_e.vector.normalize() * mt_chain.toe_e.length)
ik.foot_roll_e.tail = ik.foot_roll_e.head - ik.foot_roll_e.vector # flip ik.foot_roll_e.align_roll(mt_chain.foot_e.matrix.rotation_part() * Vector(0.0, 0.0, -1.0))
ik.foot_roll_e.align_roll(mt_chain.foot_e.matrix.rotationPart() * Vector(0.0, 0.0, -1.0))
# MCH-foot # MCH-foot
ik.foot_roll_01_e = copy_bone_simple(arm, mt_chain.foot, "MCH-" + base_names[mt_chain.foot]) ik.foot_roll_01_e = copy_bone_simple(arm, mt_chain.foot, "MCH-" + base_names[mt_chain.foot])
@@ -173,23 +186,74 @@ def ik(obj, bone_definition, base_names, options):
mt_chain.update() mt_chain.update()
ik.update() ik.update()
ik_chain.update() ik_chain.update()
# Set rotation modes and axis locks
#pb[knee_rotator].rotation_mode = 'YXZ'
#pb[knee_rotator].lock_rotation = False, True, False
pb[knee_rotator].lock_location = True, True, True
pb[ik.foot_roll].rotation_mode = 'XYZ'
pb[ik.foot_roll].lock_rotation = False, True, True
pb[ik_chain.toe].rotation_mode = 'XYZ'
pb[ik_chain.toe].lock_rotation = False, True, True
# IK switch property
prop = rna_idprop_ui_prop_get(pb[ik_chain.foot], "ik", create=True)
pb[ik_chain.foot]["ik"] = 1.0
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
prop["min"] = 0.0
prop["max"] = 1.0
ik_driver_path = pb[ik_chain.foot].path_to_id() + '["ik"]'
# simple constraining of orig bones # simple constraining of orig bones
con = mt_chain.thigh_p.constraints.new('COPY_TRANSFORMS') con = mt_chain.thigh_p.constraints.new('COPY_TRANSFORMS')
con.target = obj con.target = obj
con.subtarget = ik_chain.thigh con.subtarget = ik_chain.thigh
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
var.name = "var"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = ik_driver_path
con = mt_chain.shin_p.constraints.new('COPY_TRANSFORMS') con = mt_chain.shin_p.constraints.new('COPY_TRANSFORMS')
con.target = obj con.target = obj
con.subtarget = ik_chain.shin con.subtarget = ik_chain.shin
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
var.name = "var"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = ik_driver_path
con = mt_chain.foot_p.constraints.new('COPY_TRANSFORMS') con = mt_chain.foot_p.constraints.new('COPY_TRANSFORMS')
con.target = obj con.target = obj
con.subtarget = ik.foot_roll_02 con.subtarget = ik.foot_roll_02
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
var.name = "var"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = ik_driver_path
con = mt_chain.toe_p.constraints.new('COPY_TRANSFORMS') con = mt_chain.toe_p.constraints.new('COPY_TRANSFORMS')
con.target = obj con.target = obj
con.subtarget = ik_chain.toe con.subtarget = ik_chain.toe
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
var.name = "var"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = ik_driver_path
# others... # others...
con = ik.foot_roll_01_p.constraints.new('COPY_ROTATION') con = ik.foot_roll_01_p.constraints.new('COPY_ROTATION')
@@ -211,8 +275,7 @@ def ik(obj, bone_definition, base_names, options):
con.target = obj con.target = obj
con.subtarget = ik.foot_target con.subtarget = ik.foot_target
con.pole_target = obj con.pole_target = None
con.pole_subtarget = ik.knee_target
ik.update() ik.update()
ik_chain.update() ik_chain.update()
@@ -226,12 +289,204 @@ def ik(obj, bone_definition, base_names, options):
obj.data.bones[getattr(ik_chain, attr)].layer = layer obj.data.bones[getattr(ik_chain, attr)].layer = layer
for attr in ik.attr_names: for attr in ik.attr_names:
obj.data.bones[getattr(ik, attr)].layer = layer obj.data.bones[getattr(ik, attr)].layer = layer
obj.data.bones[knee_rotator].layer = layer
return None, ik_chain.thigh, ik_chain.shin, ik_chain.foot, ik_chain.toe
return None, ik_chain.thigh, ik_chain.shin, ik_chain.foot, ik_chain.toe def fk(obj, bone_definition, base_names, options):
eb = obj.data.edit_bones
pb = obj.pose.bones
arm = obj.data
bpy.ops.object.mode_set(mode='EDIT')
# setup the existing bones, use names from METARIG_NAMES
mt = bone_class_instance(obj, ["hips"])
mt_chain = bone_class_instance(obj, ["thigh", "shin", "foot", "toe"])
mt.attr_initialize(METARIG_NAMES, bone_definition)
mt_chain.attr_initialize(METARIG_NAMES, bone_definition)
fk_chain = mt_chain.copy(to_fmt="%s", base_names=base_names)
# Create the socket
socket = copy_bone_simple(arm, mt_chain.thigh, "MCH-leg_socket").name
eb[socket].parent = eb[mt.hips]
eb[socket].length = eb[mt_chain.thigh].length / 4
# Create the hinge
hinge = copy_bone_simple(arm, mt.hips, "MCH-leg_hinge").name
eb[hinge].length = eb[mt.hips].length / 2
# Make leg child of hinge
eb[fk_chain.thigh].connected = False
eb[fk_chain.thigh].parent = eb[hinge]
bpy.ops.object.mode_set(mode='OBJECT')
# Set rotation modes and axis locks
pb[fk_chain.shin].rotation_mode = 'XYZ'
pb[fk_chain.shin].lock_rotation = False, True, True
# Constrain original bones to control bones
con = mt_chain.thigh_p.constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = fk_chain.thigh
con = mt_chain.shin_p.constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = fk_chain.shin
con = mt_chain.foot_p.constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = fk_chain.foot
con = mt_chain.toe_p.constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = fk_chain.toe
# Socket constraint
con = pb[fk_chain.thigh].constraints.new('COPY_LOCATION')
con.target = obj
con.subtarget = socket
# Hinge constraint
con = pb[hinge].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = mt.hips
prop = rna_idprop_ui_prop_get(pb[fk_chain.thigh], "hinge", create=True)
pb[fk_chain.thigh]["hinge"] = 0.0
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
prop["min"] = 0.0
prop["max"] = 1.0
hinge_driver_path = pb[fk_chain.thigh].path_to_id() + '["hinge"]'
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
var.name = "var"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = hinge_driver_path
mod = fcurve.modifiers[0]
mod.poly_order = 1
mod.coefficients[0] = 1.0
mod.coefficients[1] = -1.0
return None, fk_chain.thigh, fk_chain.shin, fk_chain.foot, fk_chain.toe
def deform(obj, definitions, base_names, options):
bpy.ops.object.mode_set(mode='EDIT')
# Create upper leg bones: two bones, each half of the upper leg.
uleg1 = copy_bone_simple(obj.data, definitions[1], "DEF-%s.01" % base_names[definitions[1]], parent=True)
uleg2 = copy_bone_simple(obj.data, definitions[1], "DEF-%s.02" % base_names[definitions[1]], parent=True)
uleg1.connected = False
uleg2.connected = False
uleg2.parent = uleg1
center = uleg1.center
uleg1.tail = center
uleg2.head = center
# Create lower leg bones: two bones, each half of the lower leg.
lleg1 = copy_bone_simple(obj.data, definitions[2], "DEF-%s.01" % base_names[definitions[2]], parent=True)
lleg2 = copy_bone_simple(obj.data, definitions[2], "DEF-%s.02" % base_names[definitions[2]], parent=True)
lleg1.connected = False
lleg2.connected = False
lleg2.parent = lleg1
center = lleg1.center
lleg1.tail = center
lleg2.head = center
# Create a bone for the second lower leg deform bone to twist with
twist = copy_bone_simple(obj.data, lleg2.name, "MCH-leg_twist")
twist.length /= 4
twist.connected = False
twist.parent = obj.data.edit_bones[definitions[3]]
# Create foot bone
foot = copy_bone_simple(obj.data, definitions[3], "DEF-%s" % base_names[definitions[3]], parent=True)
# Create toe bone
toe = copy_bone_simple(obj.data, definitions[4], "DEF-%s" % base_names[definitions[4]], parent=True)
# Store names before leaving edit mode
uleg1_name = uleg1.name
uleg2_name = uleg2.name
lleg1_name = lleg1.name
lleg2_name = lleg2.name
twist_name = twist.name
foot_name = foot.name
toe_name = toe.name
# Leave edit mode
bpy.ops.object.mode_set(mode='OBJECT')
# Get the pose bones
uleg1 = obj.pose.bones[uleg1_name]
uleg2 = obj.pose.bones[uleg2_name]
lleg1 = obj.pose.bones[lleg1_name]
lleg2 = obj.pose.bones[lleg2_name]
foot = obj.pose.bones[foot_name]
toe = obj.pose.bones[toe_name]
# Upper leg constraints
con = uleg1.constraints.new('DAMPED_TRACK')
con.name = "trackto"
con.target = obj
con.subtarget = definitions[2]
con = uleg2.constraints.new('COPY_ROTATION')
con.name = "copy_rot"
con.target = obj
con.subtarget = definitions[1]
# Lower leg constraints
con = lleg1.constraints.new('COPY_ROTATION')
con.name = "copy_rot"
con.target = obj
con.subtarget = definitions[2]
con = lleg2.constraints.new('COPY_ROTATION')
con.name = "copy_rot"
con.target = obj
con.subtarget = twist_name
con = lleg2.constraints.new('DAMPED_TRACK')
con.name = "trackto"
con.target = obj
con.subtarget = definitions[3]
# Foot constraint
con = foot.constraints.new('COPY_ROTATION')
con.name = "copy_rot"
con.target = obj
con.subtarget = definitions[3]
# Toe constraint
con = toe.constraints.new('COPY_ROTATION')
con.name = "copy_rot"
con.target = obj
con.subtarget = definitions[4]
bpy.ops.object.mode_set(mode='EDIT')
return (uleg1_name, uleg2_name, lleg1_name, lleg2_name, foot_name, toe_name, None)
def main(obj, bone_definition, base_names, options): def main(obj, bone_definition, base_names, options):
bones_fk = fk(obj, bone_definition, base_names, options)
bones_ik = ik(obj, bone_definition, base_names, options) bones_ik = ik(obj, bone_definition, base_names, options)
deform(obj, bone_definition, base_names, options)
return bones_ik return bones_ik

View File

@@ -19,15 +19,69 @@
# <pep8 compliant> # <pep8 compliant>
import bpy import bpy
from math import acos from rna_prop_ui import rna_idprop_ui_prop_get
from math import acos, pi
from Mathutils import Vector from Mathutils import Vector
from rigify import get_layer_dict from rigify import get_layer_dict, RigifyError
from rigify_utils import bone_class_instance, copy_bone_simple from rigify_utils import bone_class_instance, copy_bone_simple
#METARIG_NAMES = ("cpy",) #METARIG_NAMES = ("cpy",)
RIG_TYPE = "mouth" RIG_TYPE = "mouth"
def mark_actions():
for action in bpy.data.actions:
action.tag = True
def get_unmarked_action():
for action in bpy.data.actions:
if action.tag != True:
return action
return None
def add_action(name=None):
mark_actions()
bpy.ops.action.new()
action = get_unmarked_action()
if name is not None:
action.name = name
return action
def addget_shape_key(obj, name="Key"):
""" Fetches a shape key, or creates it if it doesn't exist
"""
# Create a shapekey set if it doesn't already exist
if obj.data.shape_keys is None:
shape = obj.add_shape_key(name="Basis", from_mix=False)
obj.active_shape_key_index = 0
# Get the shapekey, or create it if it doesn't already exist
if name in obj.data.shape_keys.keys:
shape_key = obj.data.shape_keys.keys[name]
else:
shape_key = obj.add_shape_key(name=name, from_mix=False)
return shape_key
def addget_shape_key_driver(obj, name="Key"):
""" Fetches the driver for the shape key, or creates it if it doesn't
already exist.
"""
driver_path = 'keys["' + name + '"].value'
fcurve = None
driver = None
if obj.data.shape_keys.animation_data is not None:
for driver_s in obj.data.shape_keys.animation_data.drivers:
if driver_s.data_path == driver_path:
fcurve = driver_s
if fcurve == None:
fcurve = obj.data.shape_keys.keys[name].driver_add("value", 0)
fcurve.driver.type = 'AVERAGE'
return fcurve
def metarig_template(): def metarig_template():
# generated by rigify.write_meta_rig # generated by rigify.write_meta_rig
bpy.ops.object.mode_set(mode='EDIT') bpy.ops.object.mode_set(mode='EDIT')
@@ -49,7 +103,7 @@ def metarig_definition(obj, orig_bone_name):
chain = [] chain = []
try: try:
chain += [bone.parent.name, bone.parent.parent.name, bone.name] chain += [bone.parent.parent.name, bone.parent.name, bone.name]
except AttributeError: except AttributeError:
raise RigifyError("'%s' rig type requires a chain of two parents (bone: %s)" % (RIG_TYPE, base_names[0])) raise RigifyError("'%s' rig type requires a chain of two parents (bone: %s)" % (RIG_TYPE, base_names[0]))
@@ -67,62 +121,66 @@ def deform(obj, definitions, base_names, options):
eb = obj.data.edit_bones eb = obj.data.edit_bones
pb = obj.pose.bones pb = obj.pose.bones
# Options
req_options = ["mesh"]
for option in req_options:
if option not in options:
raise RigifyError("'%s' rig type requires a '%s' option (bone: %s)" % (RIG_TYPE, option, base_names[definitions[0]]))
meshes = options["mesh"].replace(" ", "").split(",")
# Upper lip MCH # Upper lip MCH
lip1 = make_lip_stretch_bone(obj, "MCH-lip", definitions[2], definitions[3], 1.0) lip1 = make_lip_stretch_bone(obj, "MCH-lip", definitions[3], definitions[2], 0.0)
lip2 = make_lip_stretch_bone(obj, "MCH-lip", definitions[3], definitions[4], 1.0) lip2 = make_lip_stretch_bone(obj, "MCH-lip", definitions[4], definitions[3], 0.0)
lip22 = make_lip_stretch_bone(obj, "MCH-lip", definitions[4], definitions[5], 1.0) lip22 = make_lip_stretch_bone(obj, "MCH-lip", definitions[5], definitions[4], 0.0)
lip33 = make_lip_stretch_bone(obj, "MCH-lip", definitions[4], definitions[3], 1.0) lip33 = make_lip_stretch_bone(obj, "MCH-lip", definitions[3], definitions[4], 0.0)
lip3 = make_lip_stretch_bone(obj, "MCH-lip", definitions[5], definitions[4], 1.0) lip3 = make_lip_stretch_bone(obj, "MCH-lip", definitions[4], definitions[5], 0.0)
lip4 = make_lip_stretch_bone(obj, "MCH-lip", definitions[6], definitions[5], 1.0) lip4 = make_lip_stretch_bone(obj, "MCH-lip", definitions[5], definitions[6], 0.0)
dlip22 = copy_bone_simple(obj.data, lip22, "MCH-lip", parent=True).name eb[lip1].parent = eb[definitions[3]]
dlip33 = copy_bone_simple(obj.data, lip33, "MCH-lip", parent=True).name eb[lip2].parent = eb[definitions[4]]
eb[dlip22].bbone_segments = 8 eb[lip22].parent = eb[definitions[5]]
eb[dlip33].bbone_segments = 8 eb[lip33].parent = eb[definitions[3]]
eb[lip3].parent = eb[definitions[4]]
eb[lip4].parent = eb[definitions[5]]
eb[lip1].parent = eb[definitions[2]] eb[lip22].bbone_segments = 8
eb[lip2].parent = eb[definitions[3]] eb[lip33].bbone_segments = 8
eb[lip22].parent = eb[definitions[4]]
eb[lip33].parent = eb[definitions[4]]
eb[lip3].parent = eb[definitions[5]]
eb[lip4].parent = eb[definitions[6]]
# Lower lip MCH # Lower lip MCH
lip5 = make_lip_stretch_bone(obj, "MCH-lip", definitions[6], definitions[7], 1.0) lip5 = make_lip_stretch_bone(obj, "MCH-lip", definitions[7], definitions[6], 0.0)
lip6 = make_lip_stretch_bone(obj, "MCH-lip", definitions[7], definitions[8], 1.0) lip6 = make_lip_stretch_bone(obj, "MCH-lip", definitions[8], definitions[7], 0.0)
lip66 = make_lip_stretch_bone(obj, "MCH-lip", definitions[8], definitions[9], 1.0) lip66 = make_lip_stretch_bone(obj, "MCH-lip", definitions[9], definitions[8], 0.0)
lip77 = make_lip_stretch_bone(obj, "MCH-lip", definitions[8], definitions[7], 1.0) lip77 = make_lip_stretch_bone(obj, "MCH-lip", definitions[7], definitions[8], 0.0)
lip7 = make_lip_stretch_bone(obj, "MCH-lip", definitions[9], definitions[8], 1.0) lip7 = make_lip_stretch_bone(obj, "MCH-lip", definitions[8], definitions[9], 0.0)
lip8 = make_lip_stretch_bone(obj, "MCH-lip", definitions[2], definitions[9], 1.0) lip8 = make_lip_stretch_bone(obj, "MCH-lip", definitions[9], definitions[2], 0.0)
dlip66 = copy_bone_simple(obj.data, lip66, "MCH-lip", parent=True).name eb[lip5].parent = eb[definitions[7]]
dlip77 = copy_bone_simple(obj.data, lip77, "MCH-lip", parent=True).name eb[lip6].parent = eb[definitions[8]]
eb[dlip66].bbone_segments = 8 eb[lip66].parent = eb[definitions[9]]
eb[dlip77].bbone_segments = 8 eb[lip77].parent = eb[definitions[7]]
eb[lip7].parent = eb[definitions[8]]
eb[lip8].parent = eb[definitions[9]]
eb[lip5].parent = eb[definitions[6]] eb[lip66].bbone_segments = 8
eb[lip6].parent = eb[definitions[7]] eb[lip77].bbone_segments = 8
eb[lip66].parent = eb[definitions[8]]
eb[lip77].parent = eb[definitions[8]]
eb[lip7].parent = eb[definitions[9]]
eb[lip8].parent = eb[definitions[2]]
# Upper lip DEF # Upper lip DEF
dlip1 = copy_bone_simple(obj.data, lip1, "DEF-lip", parent=True).name dlip1 = copy_bone_simple(obj.data, lip1, "DEF-" + base_names[definitions[4]] + ".01.R", parent=True).name
dlip2 = copy_bone_simple(obj.data, lip2, "DEF-lip", parent=True).name dlip2 = copy_bone_simple(obj.data, lip2, "DEF-" + base_names[definitions[4]] + ".02.R", parent=True).name
dlip3 = copy_bone_simple(obj.data, lip3, "DEF-lip", parent=True).name dlip3 = copy_bone_simple(obj.data, lip3, "DEF-" + base_names[definitions[4]] + ".02.L", parent=True).name
dlip4 = copy_bone_simple(obj.data, lip4, "DEF-lip", parent=True).name dlip4 = copy_bone_simple(obj.data, lip4, "DEF-" + base_names[definitions[4]] + ".01.L", parent=True).name
eb[dlip2].parent = eb[dlip1] eb[dlip1].parent = eb[dlip2]
eb[dlip22].parent = eb[dlip2] eb[dlip2].parent = eb[lip22]
eb[dlip3].parent = eb[dlip4] eb[dlip4].parent = eb[dlip3]
eb[dlip33].parent = eb[dlip3] eb[dlip3].parent = eb[lip33]
eb[dlip2].connected = True eb[dlip1].connected = True
eb[dlip22].connected = True eb[dlip2].connected = True
eb[dlip3].connected = True eb[dlip4].connected = True
eb[dlip33].connected = True eb[dlip3].connected = True
eb[dlip1].bbone_segments = 8 eb[dlip1].bbone_segments = 8
eb[dlip2].bbone_segments = 8 eb[dlip2].bbone_segments = 8
@@ -130,28 +188,28 @@ def deform(obj, definitions, base_names, options):
eb[dlip4].bbone_segments = 8 eb[dlip4].bbone_segments = 8
# Lower lip DEF # Lower lip DEF
dlip5 = copy_bone_simple(obj.data, lip5, "DEF-lip", parent=True).name dlip8 = copy_bone_simple(obj.data, lip8, "DEF-" + base_names[definitions[8]] + ".01.R", parent=True).name
dlip6 = copy_bone_simple(obj.data, lip6, "DEF-lip", parent=True).name dlip7 = copy_bone_simple(obj.data, lip7, "DEF-" + base_names[definitions[8]] + ".02.R", parent=True).name
dlip7 = copy_bone_simple(obj.data, lip7, "DEF-lip", parent=True).name dlip6 = copy_bone_simple(obj.data, lip6, "DEF-" + base_names[definitions[8]] + ".02.L", parent=True).name
dlip8 = copy_bone_simple(obj.data, lip8, "DEF-lip", parent=True).name dlip5 = copy_bone_simple(obj.data, lip5, "DEF-" + base_names[definitions[8]] + ".01.L", parent=True).name
eb[dlip6].parent = eb[dlip5]
eb[dlip66].parent = eb[dlip6]
eb[dlip7].parent = eb[dlip8] eb[dlip5].parent = eb[dlip6]
eb[dlip77].parent = eb[dlip7] eb[dlip6].parent = eb[lip66]
eb[dlip8].parent = eb[dlip7]
eb[dlip7].parent = eb[lip77]
eb[dlip5].connected = True
eb[dlip6].connected = True eb[dlip6].connected = True
eb[dlip66].connected = True eb[dlip8].connected = True
eb[dlip7].connected = True eb[dlip7].connected = True
eb[dlip77].connected = True
eb[dlip5].bbone_segments = 8 eb[dlip5].bbone_segments = 8
eb[dlip6].bbone_segments = 8 eb[dlip6].bbone_segments = 8
eb[dlip7].bbone_segments = 8 eb[dlip7].bbone_segments = 8
eb[dlip8].bbone_segments = 8 eb[dlip8].bbone_segments = 8
bpy.ops.object.mode_set(mode='OBJECT') bpy.ops.object.mode_set(mode='OBJECT')
# Constraints # Constraints
@@ -159,14 +217,6 @@ def deform(obj, definitions, base_names, options):
con.target = obj con.target = obj
con.subtarget = lip1 con.subtarget = lip1
con = pb[dlip22].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lip22
con = pb[dlip33].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lip33
con = pb[dlip2].constraints.new('COPY_TRANSFORMS') con = pb[dlip2].constraints.new('COPY_TRANSFORMS')
con.target = obj con.target = obj
con.subtarget = lip2 con.subtarget = lip2
@@ -187,14 +237,6 @@ def deform(obj, definitions, base_names, options):
con.target = obj con.target = obj
con.subtarget = lip6 con.subtarget = lip6
con = pb[dlip66].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lip66
con = pb[dlip77].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lip77
con = pb[dlip7].constraints.new('COPY_TRANSFORMS') con = pb[dlip7].constraints.new('COPY_TRANSFORMS')
con.target = obj con.target = obj
con.subtarget = lip7 con.subtarget = lip7
@@ -203,6 +245,88 @@ def deform(obj, definitions, base_names, options):
con.target = obj con.target = obj
con.subtarget = lip8 con.subtarget = lip8
# Corrective shape keys for the corners of the mouth.
bpy.ops.object.mode_set(mode='EDIT')
# Calculate the rotation difference between the bones
rotdiff_r = acos(eb[lip1].matrix.to_quat() * eb[lip8].matrix.to_quat()) * 2
rotdiff_l = acos(eb[lip4].matrix.to_quat() * eb[lip5].matrix.to_quat()) * 2
bpy.ops.object.mode_set(mode='OBJECT')
# Left side
for mesh_name in meshes:
mesh_obj = bpy.data.objects[mesh_name]
shape_key_name = "COR-" + base_names[definitions[4]] + ".L.spread"
# Add/get the shape key
shape_key = addget_shape_key(mesh_obj, name=shape_key_name)
# Add/get the shape key driver
fcurve = addget_shape_key_driver(mesh_obj, name=shape_key_name)
driver = fcurve.driver
# Get the variable, or create it if it doesn't already exist
var_name = base_names[definitions[6]]
if var_name in driver.variables:
var = driver.variables[var_name]
else:
var = driver.variables.new()
var.name = var_name
# Set up the variable
var.type = "ROTATION_DIFF"
#var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].bone_target = lip4
#var.targets[1].id_type = 'OBJECT'
var.targets[1].id = obj
var.targets[1].bone_target = lip5
# Set fcurve offset
mod = fcurve.modifiers[0]
if rotdiff_l != pi:
mod.coefficients[0] = -rotdiff_l / (pi-rotdiff_l)
mod.coefficients[1] = 1 / (pi-rotdiff_l)
# Right side
for mesh_name in meshes:
mesh_obj = bpy.data.objects[mesh_name]
shape_key_name = "COR-" + base_names[definitions[4]] + ".R.spread"
# Add/get the shape key
shape_key = addget_shape_key(mesh_obj, name=shape_key_name)
# Add/get the shape key driver
fcurve = addget_shape_key_driver(mesh_obj, name=shape_key_name)
driver = fcurve.driver
# Get the variable, or create it if it doesn't already exist
var_name = base_names[definitions[2]]
if var_name in driver.variables:
var = driver.variables[var_name]
else:
var = driver.variables.new()
var.name = var_name
# Set up the variable
var.type = "ROTATION_DIFF"
#var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].bone_target = lip1
#var.targets[1].id_type = 'OBJECT'
var.targets[1].id = obj
var.targets[1].bone_target = lip8
# Set fcurve offset
mod = fcurve.modifiers[0]
if rotdiff_r != pi:
mod.coefficients[0] = -rotdiff_r / (pi-rotdiff_r)
mod.coefficients[1] = 1 / (pi-rotdiff_r)
return (None,) return (None,)
@@ -217,6 +341,7 @@ def control(obj, definitions, base_names, options):
head_e = eb[definitions[0]] head_e = eb[definitions[0]]
jaw_e = eb[definitions[1]] jaw_e = eb[definitions[1]]
jaw = definitions[1]
# Head lips # Head lips
hlip1 = copy_bone_simple(obj.data, definitions[2], "MCH-"+base_names[definitions[2]]+".head").name hlip1 = copy_bone_simple(obj.data, definitions[2], "MCH-"+base_names[definitions[2]]+".head").name
@@ -285,14 +410,14 @@ def control(obj, definitions, base_names, options):
eb[lip7].roll = 0 eb[lip7].roll = 0
eb[lip8].roll = 0 eb[lip8].roll = 0
eb[lip1].parent = eb[jlip1] eb[lip1].parent = eb[hlip1]
eb[lip2].parent = eb[jlip2] eb[lip2].parent = eb[hlip2]
eb[lip3].parent = eb[jlip3] eb[lip3].parent = eb[hlip3]
eb[lip4].parent = eb[jlip4] eb[lip4].parent = eb[hlip4]
eb[lip5].parent = eb[jlip5] eb[lip5].parent = eb[hlip5]
eb[lip6].parent = eb[jlip6] eb[lip6].parent = eb[hlip6]
eb[lip7].parent = eb[jlip7] eb[lip7].parent = eb[hlip7]
eb[lip8].parent = eb[jlip8] eb[lip8].parent = eb[hlip8]
# Link lips # Link lips
llip1 = copy_bone_simple(obj.data, definitions[2], "MCH-"+base_names[definitions[2]]+".link").name llip1 = copy_bone_simple(obj.data, definitions[2], "MCH-"+base_names[definitions[2]]+".link").name
@@ -313,53 +438,84 @@ def control(obj, definitions, base_names, options):
eb[llip7].parent = eb[lip7] eb[llip7].parent = eb[lip7]
eb[llip8].parent = eb[lip8] eb[llip8].parent = eb[lip8]
# Jaw open tracker
jopent = copy_bone_simple(obj.data, jaw_e.name, "MCH-"+base_names[jaw_e.name]+".track", parent=True).name
eb[jopent].connected = False
eb[jopent].tail = jaw_e.tail + Vector(0,0,jaw_e.length)
eb[jopent].head = jaw_e.tail
bpy.ops.object.mode_set(mode='OBJECT') bpy.ops.object.mode_set(mode='OBJECT')
# Add eye close action if it doesn't already exist
action_name = "mouth_open"
if action_name in bpy.data.actions:
open_action = bpy.data.actions[action_name]
else:
open_action = add_action(name=action_name)
# Add close property (useful when making the animation in the action)
prop_name = "open_action"
prop = rna_idprop_ui_prop_get(pb[lip1], prop_name, create=True)
pb[lip1][prop_name] = 1.0
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
prop["min"] = 0.0
prop["max"] = 1.0
open_driver_path = pb[lip1].path_to_id() + '["open_action"]'
# Constraints # Constraints
# Jaw lips to head lips # Jaw open tracker stretches to jaw tip
influence = [0.0, 0.1, 0.5] con = pb[jopent].constraints.new('STRETCH_TO')
con = pb[jlip1].constraints.new('COPY_TRANSFORMS')
con.target = obj con.target = obj
con.subtarget = hlip1 con.subtarget = jaw
con.head_tail = 1.0
con.original_length = bb[jopent].length
con.volume = 'NO_VOLUME'
# Head lips to jaw lips
influence = [0.0, 0.1, 0.5, 0.25, 0.0]
con = pb[hlip1].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = jlip1
con.influence = influence[2] con.influence = influence[2]
con = pb[jlip2].constraints.new('COPY_TRANSFORMS') con = pb[hlip2].constraints.new('COPY_TRANSFORMS')
con.target = obj con.target = obj
con.subtarget = hlip2 con.subtarget = jlip2
con.influence = influence[1] con.influence = influence[1]
con = pb[jlip3].constraints.new('COPY_TRANSFORMS') con = pb[hlip3].constraints.new('COPY_TRANSFORMS')
con.target = obj con.target = obj
con.subtarget = hlip3 con.subtarget = jlip3
con.influence = influence[0] con.influence = influence[0]
con = pb[jlip4].constraints.new('COPY_TRANSFORMS') con = pb[hlip4].constraints.new('COPY_TRANSFORMS')
con.target = obj con.target = obj
con.subtarget = hlip4 con.subtarget = jlip4
con.influence = influence[1] con.influence = influence[1]
con = pb[jlip5].constraints.new('COPY_TRANSFORMS') con = pb[hlip5].constraints.new('COPY_TRANSFORMS')
con.target = obj con.target = obj
con.subtarget = hlip5 con.subtarget = jlip5
con.influence = influence[2] con.influence = influence[2]
con = pb[jlip6].constraints.new('COPY_TRANSFORMS') con = pb[hlip6].constraints.new('COPY_TRANSFORMS')
con.target = obj con.target = obj
con.subtarget = hlip6 con.subtarget = jlip6
con.influence = 1.0 - influence[1] con.influence = 1.0 - influence[3]
con = pb[jlip7].constraints.new('COPY_TRANSFORMS') con = pb[hlip7].constraints.new('COPY_TRANSFORMS')
con.target = obj con.target = obj
con.subtarget = hlip7 con.subtarget = jlip7
con.influence = 1.0 - influence[0] con.influence = 1.0 - influence[4]
con = pb[jlip8].constraints.new('COPY_TRANSFORMS') con = pb[hlip8].constraints.new('COPY_TRANSFORMS')
con.target = obj con.target = obj
con.subtarget = hlip8 con.subtarget = jlip8
con.influence = 1.0 - influence[1] con.influence = 1.0 - influence[3]
# ORG bones to link lips # ORG bones to link lips
con = pb[definitions[2]].constraints.new('COPY_TRANSFORMS') con = pb[definitions[2]].constraints.new('COPY_TRANSFORMS')
@@ -394,6 +550,151 @@ def control(obj, definitions, base_names, options):
con.target = obj con.target = obj
con.subtarget = llip8 con.subtarget = llip8
# Action constraints for open mouth
con = pb[lip1].constraints.new('ACTION')
con.target = obj
con.subtarget = jopent
con.action = open_action
con.transform_channel = 'SCALE_Y'
con.start_frame = 0
con.end_frame = 60
con.minimum = 0.0
con.maximum = 1.0
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = open_driver_path
con = pb[lip2].constraints.new('ACTION')
con.target = obj
con.subtarget = jopent
con.action = open_action
con.transform_channel = 'SCALE_Y'
con.start_frame = 0
con.end_frame = 60
con.minimum = 0.0
con.maximum = 1.0
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = open_driver_path
con = pb[lip3].constraints.new('ACTION')
con.target = obj
con.subtarget = jopent
con.action = open_action
con.transform_channel = 'SCALE_Y'
con.start_frame = 0
con.end_frame = 60
con.minimum = 0.0
con.maximum = 1.0
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = open_driver_path
con = pb[lip4].constraints.new('ACTION')
con.target = obj
con.subtarget = jopent
con.action = open_action
con.transform_channel = 'SCALE_Y'
con.start_frame = 0
con.end_frame = 60
con.minimum = 0.0
con.maximum = 1.0
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = open_driver_path
con = pb[lip5].constraints.new('ACTION')
con.target = obj
con.subtarget = jopent
con.action = open_action
con.transform_channel = 'SCALE_Y'
con.start_frame = 0
con.end_frame = 60
con.minimum = 0.0
con.maximum = 1.0
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = open_driver_path
con = pb[lip6].constraints.new('ACTION')
con.target = obj
con.subtarget = jopent
con.action = open_action
con.transform_channel = 'SCALE_Y'
con.start_frame = 0
con.end_frame = 60
con.minimum = 0.0
con.maximum = 1.0
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = open_driver_path
con = pb[lip7].constraints.new('ACTION')
con.target = obj
con.subtarget = jopent
con.action = open_action
con.transform_channel = 'SCALE_Y'
con.start_frame = 0
con.end_frame = 60
con.minimum = 0.0
con.maximum = 1.0
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = open_driver_path
con = pb[lip8].constraints.new('ACTION')
con.target = obj
con.subtarget = jopent
con.action = open_action
con.transform_channel = 'SCALE_Y'
con.start_frame = 0
con.end_frame = 60
con.minimum = 0.0
con.maximum = 1.0
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = open_driver_path
# Set layers # Set layers
layer = list(bb[definitions[2]].layer) layer = list(bb[definitions[2]].layer)

View File

@@ -213,6 +213,9 @@ def main(obj, bone_definition, base_names, options):
ex_chain.update() ex_chain.update()
ex.update() ex.update()
# Axis locks
ex.head_ctrl_p.lock_location = True, True, True
# Simple one off constraints, no drivers # Simple one off constraints, no drivers
con = ex.head_ctrl_p.constraints.new('COPY_LOCATION') con = ex.head_ctrl_p.constraints.new('COPY_LOCATION')
con.target = obj con.target = obj

View File

@@ -152,6 +152,7 @@ def main(obj, bone_definition, base_names, options):
control_pbone.rotation_mode = 'YZX' control_pbone.rotation_mode = 'YZX'
control_pbone.lock_rotation = False, True, True control_pbone.lock_rotation = False, True, True
control_pbone.lock_location = True, True, True
driver_fcurves = pinky_pbone.driver_add("rotation_euler") driver_fcurves = pinky_pbone.driver_add("rotation_euler")
@@ -163,6 +164,8 @@ def main(obj, bone_definition, base_names, options):
prop = rna_idprop_ui_prop_get(control_pbone, "spread", create=True) prop = rna_idprop_ui_prop_get(control_pbone, "spread", create=True)
prop["soft_min"] = -1.0 prop["soft_min"] = -1.0
prop["soft_max"] = 1.0 prop["soft_max"] = 1.0
prop["min"] = -1.0
prop["max"] = 1.0
# ***** # *****
@@ -246,15 +249,15 @@ def main(obj, bone_definition, base_names, options):
# NOTE: the direction of the Z rotation depends on which side the palm is on. # NOTE: the direction of the Z rotation depends on which side the palm is on.
# we could do a simple side-of-x test but better to work out the direction # we could do a simple side-of-x test but better to work out the direction
# the hand is facing. # the hand is facing.
from Mathutils import Vector, AngleBetweenVecs from Mathutils import Vector
from math import degrees from math import degrees
child_pbone_01 = obj.pose.bones[children[0]].bone child_pbone_01 = obj.pose.bones[children[0]].bone
child_pbone_02 = obj.pose.bones[children[1]].bone child_pbone_02 = obj.pose.bones[children[1]].bone
rel_vec = child_pbone_01.head - child_pbone_02.head rel_vec = child_pbone_01.head - child_pbone_02.head
x_vec = child_pbone_01.matrix.rotationPart() * Vector(1.0, 0.0, 0.0) x_vec = child_pbone_01.matrix.rotation_part() * Vector(1.0, 0.0, 0.0)
return degrees(AngleBetweenVecs(rel_vec, x_vec)) > 90.0 return degrees(rel_vec.angle(x_vec)) > 90.0
if x_direction(): # flip if x_direction(): # flip
driver.expression = "-(%s)" % driver.expression driver.expression = "-(%s)" % driver.expression

View File

@@ -0,0 +1,176 @@
# ##### 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from rna_prop_ui import rna_idprop_ui_prop_get
from math import acos
from Mathutils import Vector
from rigify import get_layer_dict
from rigify_utils import bone_class_instance, copy_bone_simple
#METARIG_NAMES = ("cpy",)
RIG_TYPE = "shape_key_distance"
def addget_shape_key(obj, name="Key"):
""" Fetches a shape key, or creates it if it doesn't exist
"""
# Create a shapekey set if it doesn't already exist
if obj.data.shape_keys is None:
shape = obj.add_shape_key(name="Basis", from_mix=False)
obj.active_shape_key_index = 0
# Get the shapekey, or create it if it doesn't already exist
if name in obj.data.shape_keys.keys:
shape_key = obj.data.shape_keys.keys[name]
else:
shape_key = obj.add_shape_key(name=name, from_mix=False)
return shape_key
def addget_shape_key_driver(obj, name="Key"):
""" Fetches the driver for the shape key, or creates it if it doesn't
already exist.
"""
driver_path = 'keys["' + name + '"].value'
fcurve = None
driver = None
if obj.data.shape_keys.animation_data is not None:
for driver_s in obj.data.shape_keys.animation_data.drivers:
if driver_s.data_path == driver_path:
fcurve = driver_s
if fcurve == None:
fcurve = obj.data.shape_keys.keys[name].driver_add("value", 0)
fcurve.driver.type = 'AVERAGE'
return fcurve
def metarig_template():
# generated by rigify.write_meta_rig
bpy.ops.object.mode_set(mode='EDIT')
obj = bpy.context.active_object
arm = obj.data
bone = arm.edit_bones.new('Bone')
bone.head[:] = 0.0000, 0.0000, 0.0000
bone.tail[:] = 0.0000, 0.0000, 1.0000
bone.roll = 0.0000
bone.connected = False
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones['Bone']
pbone['type'] = 'copy'
def metarig_definition(obj, orig_bone_name):
bone = obj.data.bones[orig_bone_name]
return [bone.name]
def deform(obj, definitions, base_names, options):
bpy.ops.object.mode_set(mode='EDIT')
eb = obj.data.edit_bones
bone_from = definitions[0]
# Options
req_options = ["to", "mesh", "shape_key"]
for option in req_options:
if option not in options:
raise RigifyError("'%s' rig type requires a '%s' option (bone: %s)" % (RIG_TYPE, option, base_names[definitions[0]]))
bone_to = "ORG-" + options["to"]
meshes = options["mesh"].replace(" ", "").split(",")
shape_key_name = options["shape_key"]
if "dmul" in options:
shape_blend_fac = options["dmul"]
else:
shape_blend_fac = 1.0
# Calculate the distance between the bones
distance = (eb[bone_from].head - eb[bone_to].head).length
bpy.ops.object.mode_set(mode='OBJECT')
# For every listed mesh object
for mesh_name in meshes:
mesh_obj = bpy.data.objects[mesh_name]
# Add/get the shape key
shape_key = addget_shape_key(mesh_obj, name=shape_key_name)
# Add/get the shape key driver
fcurve = addget_shape_key_driver(mesh_obj, name=shape_key_name)
driver = fcurve.driver
# Get the variable, or create it if it doesn't already exist
var_name = base_names[bone_from]
if var_name in driver.variables:
var = driver.variables[var_name]
else:
var = driver.variables.new()
var.name = var_name
# Set up the variable
var.type = "LOC_DIFF"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].bone_target = bone_from
var.targets[1].id_type = 'OBJECT'
var.targets[1].id = obj
var.targets[1].bone_target = bone_to
# Set fcurve offset, so zero is at the rest distance
mod = fcurve.modifiers[0]
if distance > 0.00001:
mod.coefficients[0] = -shape_blend_fac
mod.coefficients[1] = shape_blend_fac / distance
return (None,)
def control(obj, definitions, base_names, options):
""" options:
mesh: name of mesh object with the shape key
shape_key: name of shape key
to: name of bone to measure distance from
"""
pass
def main(obj, bone_definition, base_names, options):
# Create control rig
#control(obj, bone_definition, base_names, options)
# Create deform rig
deform(obj, bone_definition, base_names, options)
return (None,)

View File

@@ -0,0 +1,176 @@
# ##### 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from rna_prop_ui import rna_idprop_ui_prop_get
from math import acos
from Mathutils import Vector
from rigify import get_layer_dict
from rigify_utils import bone_class_instance, copy_bone_simple
#METARIG_NAMES = ("cpy",)
RIG_TYPE = "shape_key_rotdiff"
def addget_shape_key(obj, name="Key"):
""" Fetches a shape key, or creates it if it doesn't exist
"""
# Create a shapekey set if it doesn't already exist
if obj.data.shape_keys is None:
shape = obj.add_shape_key(name="Basis", from_mix=False)
obj.active_shape_key_index = 0
# Get the shapekey, or create it if it doesn't already exist
if name in obj.data.shape_keys.keys:
shape_key = obj.data.shape_keys.keys[name]
else:
shape_key = obj.add_shape_key(name=name, from_mix=False)
return shape_key
def addget_shape_key_driver(obj, name="Key"):
""" Fetches the driver for the shape key, or creates it if it doesn't
already exist.
"""
driver_path = 'keys["' + name + '"].value'
fcurve = None
driver = None
if obj.data.shape_keys.animation_data is not None:
for driver_s in obj.data.shape_keys.animation_data.drivers:
if driver_s.data_path == driver_path:
fcurve = driver_s
if fcurve == None:
fcurve = obj.data.shape_keys.keys[name].driver_add("value", 0)
fcurve.driver.type = 'AVERAGE'
return fcurve
def metarig_template():
# generated by rigify.write_meta_rig
bpy.ops.object.mode_set(mode='EDIT')
obj = bpy.context.active_object
arm = obj.data
bone = arm.edit_bones.new('Bone')
bone.head[:] = 0.0000, 0.0000, 0.0000
bone.tail[:] = 0.0000, 0.0000, 1.0000
bone.roll = 0.0000
bone.connected = False
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones['Bone']
pbone['type'] = 'copy'
def metarig_definition(obj, orig_bone_name):
bone = obj.data.bones[orig_bone_name]
return [bone.name]
def deform(obj, definitions, base_names, options):
bpy.ops.object.mode_set(mode='EDIT')
eb = obj.data.edit_bones
bone_from = definitions[0]
# Options
req_options = ["to", "mesh", "shape_key"]
for option in req_options:
if option not in options:
raise RigifyError("'%s' rig type requires a '%s' option (bone: %s)" % (RIG_TYPE, option, base_names[definitions[0]]))
bone_to = "ORG-" + options["to"]
meshes = options["mesh"].replace(" ", "").split(",")
shape_key_name = options["shape_key"]
if "dmul" in options:
shape_blend_fac = options["dmul"]
else:
shape_blend_fac = 1.0
# Calculate the rotation difference between the bones
rotdiff = (eb[bone_from].matrix.to_quat() * eb[bone_to].matrix.to_quat()) * 2
bpy.ops.object.mode_set(mode='OBJECT')
# For every listed mesh object
for mesh_name in meshes:
mesh_obj = bpy.data.objects[mesh_name]
# Add/get the shape key
shape_key = addget_shape_key(mesh_obj, name=shape_key_name)
# Add/get the shape key driver
fcurve = addget_shape_key_driver(mesh_obj, name=shape_key_name)
driver = fcurve.driver
# Get the variable, or create it if it doesn't already exist
var_name = base_names[bone_from]
if var_name in driver.variables:
var = driver.variables[var_name]
else:
var = driver.variables.new()
var.name = var_name
# Set up the variable
var.type = "ROTATION_DIFF"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].bone_target = bone_from
var.targets[1].id_type = 'OBJECT'
var.targets[1].id = obj
var.targets[1].bone_target = bone_to
# Set fcurve offset, so zero is at the rest distance
mod = fcurve.modifiers[0]
if rotdiff > 0.00001:
mod.coefficients[0] = -shape_blend_fac
mod.coefficients[1] = shape_blend_fac / rotdiff
return (None,)
def control(obj, definitions, base_names, options):
""" options:
mesh: name of mesh object with the shape key
shape_key: name of shape key
to: name of bone to measure distance from
"""
pass
def main(obj, bone_definition, base_names, options):
# Create control rig
#control(obj, bone_definition, base_names, options)
# Create deform rig
deform(obj, bone_definition, base_names, options)
return (None,)

View File

@@ -304,6 +304,9 @@ def main(obj, bone_definition, base_names, options):
mt_chain.update() mt_chain.update()
ex_chain.update() ex_chain.update()
rv_chain.update() rv_chain.update()
# Axis locks
ex.ribcage_copy_p.lock_location = True, True, True
# df.pelvis_p / DEF-wgt_pelvis # df.pelvis_p / DEF-wgt_pelvis
con = df.pelvis_p.constraints.new('COPY_LOCATION') con = df.pelvis_p.constraints.new('COPY_LOCATION')
@@ -437,7 +440,10 @@ def main(obj, bone_definition, base_names, options):
# Add bend prop # Add bend prop
prop_name = "bend_%.2d" % i prop_name = "bend_%.2d" % i
prop = rna_idprop_ui_prop_get(ex.ribcage_copy_p, prop_name, create=True) prop = rna_idprop_ui_prop_get(ex.ribcage_copy_p, prop_name, create=True)
ex.ribcage_copy_p[prop_name] = 1.0 if ("bend_%.2d" % i) in options:
ex.ribcage_copy_p[prop_name] = options["bend_%.2d" % i]
else:
ex.ribcage_copy_p[prop_name] = 1.0
prop["soft_min"] = 0.0 prop["soft_min"] = 0.0
prop["soft_max"] = 1.0 prop["soft_max"] = 1.0

View File

@@ -145,28 +145,12 @@ def blend_bone_list(obj, apply_bones, from_bones, to_bones, target_bone=None, ta
var.targets[0].id = obj var.targets[0].id = obj
var.targets[0].data_path = driver_path var.targets[0].data_path = driver_path
def blend_location(new_pbone, from_bone_name, to_bone_name): def blend_transforms(new_pbone, from_bone_name, to_bone_name):
con = new_pbone.constraints.new('COPY_LOCATION') con = new_pbone.constraints.new('COPY_TRANSFORMS')
con.target = obj con.target = obj
con.subtarget = from_bone_name con.subtarget = from_bone_name
con = new_pbone.constraints.new('COPY_LOCATION') con = new_pbone.constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = to_bone_name
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
driver.type = 'AVERAGE'
fcurve.modifiers.remove(0) # grr dont need a modifier
blend_target(driver)
def blend_rotation(new_pbone, from_bone_name, to_bone_name):
con = new_pbone.constraints.new('COPY_ROTATION')
con.target = obj
con.subtarget = from_bone_name
con = new_pbone.constraints.new('COPY_ROTATION')
con.target = obj con.target = obj
con.subtarget = to_bone_name con.subtarget = to_bone_name
@@ -187,12 +171,8 @@ def blend_bone_list(obj, apply_bones, from_bones, to_bones, target_bone=None, ta
new_pbone = obj.pose.bones[new_bone_name] new_pbone = obj.pose.bones[new_bone_name]
# if the bone is connected or its location is totally locked then dont add location blending. blend_transforms(new_pbone, from_bone_name, to_bone_name)
if not (new_pbone.bone.connected or (False not in new_pbone.lock_location)):
blend_location(new_pbone, from_bone_name, to_bone_name)
if not (False not in new_pbone.lock_rotation): # TODO. 4D chech?
blend_rotation(new_pbone, from_bone_name, to_bone_name)
def add_pole_target_bone(obj, base_bone_name, name, mode='CROSS'): def add_pole_target_bone(obj, base_bone_name, name, mode='CROSS'):
@@ -225,8 +205,8 @@ def add_pole_target_bone(obj, base_bone_name, name, mode='CROSS'):
offset.length = distance offset.length = distance
elif mode == 'ZAVERAGE': elif mode == 'ZAVERAGE':
# between both bones Z axis # between both bones Z axis
z_axis_a = base_ebone.matrix.copy().rotationPart() * Vector(0.0, 0.0, -1.0) z_axis_a = base_ebone.matrix.copy().rotation_part() * Vector(0.0, 0.0, -1.0)
z_axis_b = parent_ebone.matrix.copy().rotationPart() * Vector(0.0, 0.0, -1.0) z_axis_b = parent_ebone.matrix.copy().rotation_part() * Vector(0.0, 0.0, -1.0)
offset = (z_axis_a + z_axis_b).normalize() * distance offset = (z_axis_a + z_axis_b).normalize() * distance
else: else:
# preset axis # preset axis
@@ -294,8 +274,8 @@ def write_meta_rig(obj, func_name="metarig_template"):
for bone_name in bones: for bone_name in bones:
bone = arm.edit_bones[bone_name] bone = arm.edit_bones[bone_name]
code.append(" bone = arm.edit_bones.new('%s')" % bone.name) code.append(" bone = arm.edit_bones.new('%s')" % bone.name)
code.append(" bone.head[:] = %.4f, %.4f, %.4f" % bone.head.toTuple(4)) code.append(" bone.head[:] = %.4f, %.4f, %.4f" % bone.head.to_tuple(4))
code.append(" bone.tail[:] = %.4f, %.4f, %.4f" % bone.tail.toTuple(4)) code.append(" bone.tail[:] = %.4f, %.4f, %.4f" % bone.tail.to_tuple(4))
code.append(" bone.roll = %.4f" % bone.roll) code.append(" bone.roll = %.4f" % bone.roll)
code.append(" bone.connected = %s" % str(bone.connected)) code.append(" bone.connected = %s" % str(bone.connected))
if bone.parent: if bone.parent:

View File

@@ -263,7 +263,7 @@ class InfoFunctionRNA:
for rna_prop in rna_func.parameters.values(): for rna_prop in rna_func.parameters.values():
prop = GetInfoPropertyRNA(rna_prop, parent_id) prop = GetInfoPropertyRNA(rna_prop, parent_id)
if rna_prop.use_return: if rna_prop.use_output:
self.return_values.append(prop) self.return_values.append(prop)
else: else:
self.args.append(prop) self.args.append(prop)

View File

@@ -90,7 +90,7 @@ class MeshMirrorUV(bpy.types.Operator):
mirror_gt = {} mirror_gt = {}
mirror_lt = {} mirror_lt = {}
vcos = [v.co.toTuple(5) for v in mesh.verts] vcos = [v.co.to_tuple(5) for v in mesh.verts]
for i, co in enumerate(vcos): for i, co in enumerate(vcos):
if co[0] > 0.0: if co[0] > 0.0:

View File

@@ -22,8 +22,7 @@
import time, functools import time, functools
import bpy import bpy
# from Blender import Window # from Blender import Window
from Mathutils import MidpointVecs, Vector from Mathutils import Vector
from Mathutils import AngleBetweenVecs as _AngleBetweenVecs_
# import BPyMessages # import BPyMessages
# from Blender.Draw import PupMenu # from Blender.Draw import PupMenu
@@ -36,7 +35,7 @@ CULL_METHOD = 0
def AngleBetweenVecs(a1,a2): def AngleBetweenVecs(a1,a2):
import math import math
try: try:
return math.degrees(_AngleBetweenVecs_(a1,a2)) return math.degrees(a1.angle(a2))
except: except:
return 180.0 return 180.0
@@ -54,7 +53,7 @@ class edge(object):
self.removed = 0 # Have we been culled from the eloop self.removed = 0 # Have we been culled from the eloop
self.match = None # The other edge were making a face with self.match = None # The other edge were making a face with
self.cent= MidpointVecs(co1, co2) self.cent= co1.lerp(co2, 0.5)
self.angle= 0.0 self.angle= 0.0
self.fake= False self.fake= False
@@ -501,7 +500,7 @@ def skin2EdgeLoops(eloop1, eloop2, me, ob, MODE):
return new_faces return new_faces
def main(context): def main(self, context):
global CULL_METHOD global CULL_METHOD
ob = context.object ob = context.object
@@ -509,7 +508,7 @@ def main(context):
is_editmode = (ob.mode=='EDIT') is_editmode = (ob.mode=='EDIT')
if is_editmode: bpy.ops.object.mode_set(mode='OBJECT', toggle=False) if is_editmode: bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
if ob == None or ob.type != 'MESH': if ob == None or ob.type != 'MESH':
raise Exception("BPyMessages.Error_NoMeshActive()") self.report({'ERROR'}, "No active mesh selected\n")
return return
me = ob.data me = ob.data
@@ -518,7 +517,7 @@ def main(context):
selEdges = getSelectedEdges(context, me, ob) selEdges = getSelectedEdges(context, me, ob)
vertLoops = getVertLoops(selEdges, me) # list of lists of edges. vertLoops = getVertLoops(selEdges, me) # list of lists of edges.
if vertLoops == None: if vertLoops == None:
raise Exception('Error%t|Selection includes verts that are a part of more then 1 loop') self.report({'ERROR'}, "Selection includes verts that are a part of more then 1 loop\n")
if is_editmode: bpy.ops.object.mode_set(mode='EDIT', toggle=False) if is_editmode: bpy.ops.object.mode_set(mode='EDIT', toggle=False)
return return
# print len(vertLoops) # print len(vertLoops)
@@ -531,7 +530,7 @@ def main(context):
return return
elif len(vertLoops) < 2: elif len(vertLoops) < 2:
raise Exception('Error%t|No Vertloops found!') self.report({'ERROR'}, "No Vertloops found\n")
if is_editmode: bpy.ops.object.mode_set(mode='EDIT', toggle=False) if is_editmode: bpy.ops.object.mode_set(mode='EDIT', toggle=False)
return return
else: else:
@@ -642,7 +641,7 @@ class MESH_OT_skin(bpy.types.Operator):
''' '''
def execute(self, context): def execute(self, context):
main(context) main(self, context)
return {'FINISHED'} return {'FINISHED'}

View File

@@ -0,0 +1,146 @@
# ##### 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
def randomize_selected(seed, loc, rot, scale, scale_even, scale_min):
import random
from random import uniform
from Mathutils import Vector
random.seed(seed)
def rand_vec(vec_range):
return Vector([uniform(- val, val) for val in vec_range])
for obj in bpy.context.selected_objects:
if loc:
obj.location += rand_vec(loc)
else: # otherwise the values change under us
uniform(0.0, 0.0), uniform(0.0, 0.0), uniform(0.0, 0.0)
if rot: # TODO, non euler's
vec = rand_vec(rot)
obj.rotation_euler[0] += vec[0]
obj.rotation_euler[1] += vec[1]
obj.rotation_euler[2] += vec[2]
else:
uniform(0.0, 0.0), uniform(0.0, 0.0), uniform(0.0, 0.0)
if scale:
org_sca_x, org_sca_y, org_sca_z = obj.scale
if scale_even:
sca_x = sca_y = sca_z = uniform(scale[0], - scale[0])
uniform(0.0, 0.0), uniform(0.0, 0.0)
else:
sca_x, sca_y, sca_z = rand_vec(scale)
aX = sca_x + org_sca_x
bX = org_sca_x * scale_min
aY = sca_y + org_sca_y
bY = org_sca_y * scale_min
aZ = sca_z + org_sca_z
bZ = org_sca_z * scale_min
if aX < bX:
aX = bX
if aY < bY:
aY = bY
if aZ < bZ:
aZ = bZ
obj.scale = aX, aY, aZ
else:
uniform(0.0, 0.0), uniform(0.0, 0.0), uniform(0.0, 0.0)
from bpy.props import *
class RandomizeLocRotSize(bpy.types.Operator):
'''Randomize objects loc/rot/scale.'''
bl_idname = "object.randomize_locrotsize"
bl_label = "Randomize Loc Rot Size"
bl_register = True
bl_undo = True
random_seed = IntProperty(name="Random Seed",
description="Seed value for the random generator",
default=0, min=0, max=1000)
use_loc = BoolProperty(name="Randomize Location",
description="Randomize the scale values", default=True)
loc = FloatVectorProperty(name="Location",
description="Maximun distance the objects can spread over each axis",
default=(0.0, 0.0, 0.0), min=-100.0, max=100.0)
use_rot = BoolProperty(name="Randomize Rotation",
description="Randomize the rotation values", default=True)
rot = FloatVectorProperty(name="Rotation",
description="Maximun rotation over each axis",
default=(0.0, 0.0, 0.0), min=-180.0, max=180.0)
use_scale = BoolProperty(name="Randomize Scale",
description="Randomize the scale values", default=True)
scale_even = BoolProperty(name="Scale Even",
description="Use the same scale value for all axis", default=False)
scale_min = FloatProperty(name="Minimun Scale Factor",
description="Lowest scale percentage possible",
default=0.15, min=-1.0, max=1.0, precision=3)
scale = FloatVectorProperty(name="Scale",
description="Maximum scale randomization over each axis",
default=(0.0, 0.0, 0.0), min=-100.0, max=100.0)
def execute(self, context):
from math import radians
seed = self.properties.random_seed
loc = None if not self.properties.use_loc else self.properties.loc
rot = None if not self.properties.use_rot else self.properties.rot * radians(1.0)
scale = None if not self.properties.use_scale else self.properties.scale
scale_even = self.properties.scale_even
scale_min = self.properties.scale_min
randomize_selected(seed, loc, rot, scale, scale_even, scale_min)
return {'FINISHED'}
# Register the operator
bpy.types.register(RandomizeLocRotSize)
def menu_func(self, context):
if context.mode == 'OBJECT':
self.layout.operator(RandomizeLocRotSize.bl_idname,
text="Randomize Loc Rot Size")
bpy.types.VIEW3D_MT_transform.append(menu_func)

View File

@@ -52,6 +52,10 @@ class ExportUVLayout(bpy.types.Operator):
return image_width, image_height return image_width, image_height
def execute(self, context): def execute(self, context):
# for making an XML compatible string
from xml.sax.saxutils import escape
from os.path import basename
ob = context.active_object ob = context.active_object
is_editmode = (ob.mode == 'EDIT') is_editmode = (ob.mode == 'EDIT')
if is_editmode: if is_editmode:
@@ -84,15 +88,17 @@ class ExportUVLayout(bpy.types.Operator):
fw('<svg width="%dpx" height="%dpx" viewBox="0px 0px %dpx %dpx"\n' % (image_width, image_height, image_width, image_height)) fw('<svg width="%dpx" height="%dpx" viewBox="0px 0px %dpx %dpx"\n' % (image_width, image_height, image_width, image_height))
fw(' xmlns="http://www.w3.org/2000/svg" version="1.1">\n') fw(' xmlns="http://www.w3.org/2000/svg" version="1.1">\n')
fw('<desc>%s, %s, %s (Blender %s)</desc>\n' % (bpy.data.filename, ob.name, mesh.name, bpy.app.version_string)) desc = "%s, %s, %s (Blender %s)" % (basename(bpy.data.filename), ob.name, mesh.name, bpy.app.version_string)
fw('<desc>%s</desc>\n' % escape(desc))
# svg colors # svg colors
fill_settings = [] fill_settings = []
fill_default = 'fill="grey"'
for mat in mesh.materials if mesh.materials else [None]: for mat in mesh.materials if mesh.materials else [None]:
if mat: if mat:
fill_settings.append('fill="rgb(%d, %d, %d)"' % tuple(int(c*255) for c in mat.diffuse_color)) fill_settings.append('fill="rgb(%d, %d, %d)"' % tuple(int(c*255) for c in mat.diffuse_color))
else: else:
fill_settings.append('fill="grey"') fill_settings.append(fill_default)
only_selected = self.properties.only_selected only_selected = self.properties.only_selected
@@ -105,8 +111,13 @@ class ExportUVLayout(bpy.types.Operator):
uvs = uv.uv1, uv.uv2, uv.uv3 uvs = uv.uv1, uv.uv2, uv.uv3
else: else:
uvs = uv.uv1, uv.uv2, uv.uv3, uv.uv4 uvs = uv.uv1, uv.uv2, uv.uv3, uv.uv4
try: # rare cases material index is invalid.
fill = fill_settings[faces[i].material_index]
except IndexError:
fill = fill_default
fw('<polygon %s fill-opacity="0.5" stroke="black" stroke-width="1px" \n' % fill_settings[faces[i].material_index]) fw('<polygon %s fill-opacity="0.5" stroke="black" stroke-width="1px" \n' % fill)
fw(' points="') fw(' points="')
for j, uv in enumerate(uvs): for j, uv in enumerate(uvs):

View File

@@ -936,7 +936,7 @@ def main(context, island_margin, projection_limit):
# Initialize projectVecs # Initialize projectVecs
if USER_VIEW_INIT: if USER_VIEW_INIT:
# Generate Projection # Generate Projection
projectVecs = [Vector(Window.GetViewVector()) * ob.matrixWorld.copy().invert().rotationPart()] # We add to this allong the way projectVecs = [Vector(Window.GetViewVector()) * ob.matrixWorld.copy().invert().rotation_part()] # We add to this allong the way
else: else:
projectVecs = [] projectVecs = []

View File

@@ -6,7 +6,7 @@
# for keyboard event comparison # for keyboard event comparison
# import GameKeys # import GameKeys
# support for Vector(), Matrix() types and advanced functions like AngleBetweenVecs(v1,v2) and RotationMatrix(...) # support for Vector(), Matrix() types and advanced functions like ScaleMatrix(...) and RotationMatrix(...)
# import Mathutils # import Mathutils
# for functions like getWindowWidth(), getWindowHeight() # for functions like getWindowWidth(), getWindowHeight()

View File

@@ -0,0 +1,22 @@
import bpy
class OBJECT_PT_hello(bpy.types.Panel):
bl_label = "Hello World Panel"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "object"
def draw(self, context):
layout = self.layout
obj = context.object
row = layout.row()
row.label(text="Hello world!", icon='WORLD_DATA')
row = layout.row()
row.label(text="Active object is: " + obj.name)
row = layout.row()
row.prop(obj, "name")
bpy.types.register(OBJECT_PT_hello)

View File

@@ -0,0 +1,160 @@
# ##### 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
narrowui = 180
################################################
# Generic Panels (Independent of DataType)
class MotionPathButtonsPanel(bpy.types.Panel):
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_label = "Motion Paths"
def draw_settings(self, context, avs, wide_ui, bones=False):
layout = self.layout
mps = avs.motion_paths
if wide_ui:
layout.prop(mps, "type", expand=True)
else:
layout.prop(mps, "type", text="")
split = layout.split()
col = split.column()
sub = col.column(align=True)
if (mps.type == 'CURRENT_FRAME'):
sub.prop(mps, "before_current", text="Before")
sub.prop(mps, "after_current", text="After")
elif (mps.type == 'RANGE'):
sub.prop(mps, "start_frame", text="Start")
sub.prop(mps, "end_frame", text="End")
sub.prop(mps, "frame_step", text="Step")
if bones:
col.row().prop(mps, "bake_location", expand=True)
if wide_ui:
col = split.column()
col.label(text="Display:")
col.prop(mps, "show_frame_numbers", text="Frame Numbers")
col.prop(mps, "highlight_keyframes", text="Keyframes")
col.prop(mps, "show_keyframe_numbers", text="Keyframe Numbers")
# FIXME: this panel still needs to be ported so that it will work correctly with animviz
class OnionSkinButtonsPanel(bpy.types.Panel):
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_label = "Onion Skinning"
def draw(self, context):
layout = self.layout
arm = context.armature
wide_ui = context.region.width > narrowui
if wide_ui:
layout.prop(arm, "ghost_type", expand=True)
else:
layout.prop(arm, "ghost_type", text="")
split = layout.split()
col = split.column()
sub = col.column(align=True)
if arm.ghost_type == 'RANGE':
sub.prop(arm, "ghost_start_frame", text="Start")
sub.prop(arm, "ghost_end_frame", text="End")
sub.prop(arm, "ghost_size", text="Step")
elif arm.ghost_type == 'CURRENT_FRAME':
sub.prop(arm, "ghost_step", text="Range")
sub.prop(arm, "ghost_size", text="Step")
if wide_ui:
col = split.column()
col.label(text="Display:")
col.prop(arm, "ghost_only_selected", text="Selected Only")
################################################
# Specific Panels for DataTypes
class OBJECT_PT_motion_paths(MotionPathButtonsPanel):
#bl_label = "Object Motion Paths"
bl_context = "object"
def poll(self, context):
return (context.object)
def draw(self, context):
layout = self.layout
ob = context.object
wide_ui = context.region.width > narrowui
self.draw_settings(context, ob.animation_visualisation, wide_ui)
layout.separator()
split = layout.split()
col = split.column()
col.operator("object.paths_calculate", text="Calculate Paths")
if wide_ui:
col = split.column()
col.operator("object.paths_clear", text="Clear Paths")
class DATA_PT_motion_paths(MotionPathButtonsPanel):
#bl_label = "Bone Motion Paths"
bl_context = "data"
def poll(self, context):
# XXX: include posemode check?
return (context.object) and (context.armature)
def draw(self, context):
layout = self.layout
ob = context.object
wide_ui = context.region.width > narrowui
self.draw_settings(context, ob.pose.animation_visualisation, wide_ui, bones=True)
layout.separator()
split = layout.split()
col = split.column()
col.operator("pose.paths_calculate", text="Calculate Paths")
if wide_ui:
col = split.column()
col.operator("pose.paths_clear", text="Clear Paths")
#bpy.types.register(OBJECT_PT_onion_skinning)
#bpy.types.register(DATA_PT_onion_skinning)
bpy.types.register(OBJECT_PT_motion_paths)
bpy.types.register(DATA_PT_motion_paths)

View File

@@ -158,58 +158,11 @@ class DATA_PT_bone_groups(DataButtonsPanel):
row.active = (ob.proxy is None) row.active = (ob.proxy is None)
row.operator("pose.group_assign", text="Assign") row.operator("pose.group_assign", text="Assign")
row.operator("pose.group_remove", text="Remove") #row.operator("pose.bone_group_remove_from", text="Remove") row.operator("pose.group_unassign", text="Remove") #row.operator("pose.bone_group_remove_from", text="Remove")
#row.operator("object.bone_group_select", text="Select") #row.operator("object.bone_group_select", text="Select")
#row.operator("object.bone_group_deselect", text="Deselect") #row.operator("object.bone_group_deselect", text="Deselect")
# TODO: this panel will soon be depreceated too
class DATA_PT_paths(DataButtonsPanel):
bl_label = "Paths"
def draw(self, context):
layout = self.layout
arm = context.armature
wide_ui = context.region.width > narrowui
if wide_ui:
layout.prop(arm, "paths_type", expand=True)
else:
layout.prop(arm, "paths_type", text="")
split = layout.split()
col = split.column()
sub = col.column(align=True)
if (arm.paths_type == 'CURRENT_FRAME'):
sub.prop(arm, "path_before_current", text="Before")
sub.prop(arm, "path_after_current", text="After")
elif (arm.paths_type == 'RANGE'):
sub.prop(arm, "path_start_frame", text="Start")
sub.prop(arm, "path_end_frame", text="End")
sub.prop(arm, "path_size", text="Step")
col.row().prop(arm, "paths_location", expand=True)
if wide_ui:
col = split.column()
col.label(text="Display:")
col.prop(arm, "paths_show_frame_numbers", text="Frame Numbers")
col.prop(arm, "paths_highlight_keyframes", text="Keyframes")
col.prop(arm, "paths_show_keyframe_numbers", text="Keyframe Numbers")
layout.separator()
split = layout.split()
col = split.column()
col.operator("pose.paths_calculate", text="Calculate Paths")
if wide_ui:
col = split.column()
col.operator("pose.paths_clear", text="Clear Paths")
class DATA_PT_ghost(DataButtonsPanel): class DATA_PT_ghost(DataButtonsPanel):
bl_label = "Ghost" bl_label = "Ghost"
@@ -302,7 +255,6 @@ bpy.types.register(DATA_PT_context_arm)
bpy.types.register(DATA_PT_skeleton) bpy.types.register(DATA_PT_skeleton)
bpy.types.register(DATA_PT_display) bpy.types.register(DATA_PT_display)
bpy.types.register(DATA_PT_bone_groups) bpy.types.register(DATA_PT_bone_groups)
bpy.types.register(DATA_PT_paths)
bpy.types.register(DATA_PT_ghost) bpy.types.register(DATA_PT_ghost)
bpy.types.register(DATA_PT_iksolver_itasc) bpy.types.register(DATA_PT_iksolver_itasc)

View File

@@ -352,6 +352,7 @@ class DATA_PT_spot(DataButtonsPanel):
sub.prop(lamp, "spot_size", text="Size") sub.prop(lamp, "spot_size", text="Size")
sub.prop(lamp, "spot_blend", text="Blend", slider=True) sub.prop(lamp, "spot_blend", text="Blend", slider=True)
col.prop(lamp, "square") col.prop(lamp, "square")
col.prop(lamp, "show_cone")
if wide_ui: if wide_ui:
col = split.column() col = split.column()

View File

@@ -20,7 +20,7 @@
import bpy import bpy
narrowui = 180 narrowui = 180
narrowmod = 260
class DataButtonsPanel(bpy.types.Panel): class DataButtonsPanel(bpy.types.Panel):
bl_space_type = 'PROPERTIES' bl_space_type = 'PROPERTIES'
@@ -36,14 +36,13 @@ class DATA_PT_modifiers(DataButtonsPanel):
ob = context.object ob = context.object
wide_ui = context.region.width > narrowui wide_ui = context.region.width > narrowui
compact_mod = context.region.width < narrowmod
row = layout.row() row = layout.row()
row.operator_menu_enum("object.modifier_add", "type") row.operator_menu_enum("object.modifier_add", "type")
if wide_ui:
row.label()
for md in ob.modifiers: for md in ob.modifiers:
box = layout.template_modifier(md) box = layout.template_modifier(md, compact=compact_mod)
if box: if box:
# match enum type to our functions, avoids a lookup table. # match enum type to our functions, avoids a lookup table.
getattr(self, md.type)(box, ob, md, wide_ui) getattr(self, md.type)(box, ob, md, wide_ui)
@@ -352,10 +351,11 @@ class DATA_PT_modifiers(DataButtonsPanel):
col.prop(md, "mode", text="") col.prop(md, "mode", text="")
if wide_ui: if wide_ui:
col = split.column() col = split.column()
col.label(text="Vertex Group:")
if md.mode == 'ARMATURE': if md.mode == 'ARMATURE':
col.label(text="Armature:")
col.prop(md, "armature", text="") col.prop(md, "armature", text="")
elif md.mode == 'VERTEX_GROUP': elif md.mode == 'VERTEX_GROUP':
col.label(text="Vertex Group:")
col.prop_object(md, "vertex_group", ob, "vertex_groups", text="") col.prop_object(md, "vertex_group", ob, "vertex_groups", text="")
sub = col.column() sub = col.column()

View File

@@ -80,6 +80,8 @@ class PHYSICS_PT_smoke(PhysicButtonsPanel):
col = split.column() col = split.column()
col.label(text="Resolution:") col.label(text="Resolution:")
col.prop(domain, "maxres", text="Divisions") col.prop(domain, "maxres", text="Divisions")
col.label(text="Particle:")
col.prop(domain, "initial_velocity", text="Initial Velocity")
if wide_ui: if wide_ui:
col = split.column() col = split.column()
@@ -155,6 +157,13 @@ class PHYSICS_PT_smoke_cache(PhysicButtonsPanel):
return md and (md.smoke_type == 'TYPE_DOMAIN') return md and (md.smoke_type == 'TYPE_DOMAIN')
def draw(self, context): def draw(self, context):
layout = self.layout
domain = context.smoke.domain_settings
layout.label(text="Compression:")
layout.prop(domain, "smoke_cache_comp", expand=True)
md = context.smoke.domain_settings md = context.smoke.domain_settings
cache = md.point_cache_low cache = md.point_cache_low
@@ -203,6 +212,14 @@ class PHYSICS_PT_smoke_cache_highres(PhysicButtonsPanel):
return md and (md.smoke_type == 'TYPE_DOMAIN') and md.domain_settings.highres return md and (md.smoke_type == 'TYPE_DOMAIN') and md.domain_settings.highres
def draw(self, context): def draw(self, context):
layout = self.layout
domain = context.smoke.domain_settings
layout.label(text="Compression:")
layout.prop(domain, "smoke_cache_high_comp", expand=True)
md = context.smoke.domain_settings md = context.smoke.domain_settings
cache = md.point_cache_high cache = md.point_cache_high

View File

@@ -74,6 +74,8 @@ class SCENE_PT_unit(SceneButtonsPanel):
if wide_ui: if wide_ui:
col = split.column() col = split.column()
col.prop(unit, "use_separate") col.prop(unit, "use_separate")
layout.column().prop(unit, "rotation_units")
class SCENE_PT_keying_sets(SceneButtonsPanel): class SCENE_PT_keying_sets(SceneButtonsPanel):
@@ -178,11 +180,40 @@ class SCENE_PT_physics(SceneButtonsPanel):
else: else:
layout.column().prop(scene, "gravity", text="") layout.column().prop(scene, "gravity", text="")
class SCENE_PT_simplify(SceneButtonsPanel):
bl_label = "Simplify"
COMPAT_ENGINES = {'BLENDER_RENDER'}
def draw_header(self, context):
scene = context.scene
rd = scene.render_data
self.layout.prop(rd, "use_simplify", text="")
def draw(self, context):
layout = self.layout
scene = context.scene
rd = scene.render_data
wide_ui = context.region.width > narrowui
layout.active = rd.use_simplify
split = layout.split()
col = split.column()
col.prop(rd, "simplify_subdivision", text="Subdivision")
col.prop(rd, "simplify_child_particles", text="Child Particles")
if wide_ui:
col = split.column()
col.prop(rd, "simplify_shadow_samples", text="Shadow Samples")
col.prop(rd, "simplify_ao_sss", text="AO and SSS")
bpy.types.register(SCENE_PT_scene) bpy.types.register(SCENE_PT_scene)
bpy.types.register(SCENE_PT_unit) bpy.types.register(SCENE_PT_unit)
bpy.types.register(SCENE_PT_keying_sets) bpy.types.register(SCENE_PT_keying_sets)
bpy.types.register(SCENE_PT_keying_set_paths) bpy.types.register(SCENE_PT_keying_set_paths)
bpy.types.register(SCENE_PT_physics) bpy.types.register(SCENE_PT_physics)
bpy.types.register(SCENE_PT_simplify)
bpy.types.register(SCENE_PT_custom_props) bpy.types.register(SCENE_PT_custom_props)

View File

@@ -851,6 +851,7 @@ class TEXTURE_PT_voxeldata(TextureButtonsPanel):
layout.prop(vd, "resolution") layout.prop(vd, "resolution")
elif vd.file_format == 'SMOKE': elif vd.file_format == 'SMOKE':
layout.prop(vd, "domain_object") layout.prop(vd, "domain_object")
layout.prop(vd, "smoke_data_type")
elif vd.file_format == 'IMAGE_SEQUENCE': elif vd.file_format == 'IMAGE_SEQUENCE':
layout.template_image(tex, "image", tex.image_user) layout.template_image(tex, "image", tex.image_user)

View File

@@ -73,6 +73,7 @@ class DOPESHEET_MT_view(bpy.types.Menu):
layout.column() layout.column()
layout.prop(st, "realtime_updates")
layout.prop(st, "show_cframe_indicator") layout.prop(st, "show_cframe_indicator")
layout.prop(st, "show_sliders") layout.prop(st, "show_sliders")
layout.prop(st, "automerge_keyframes") layout.prop(st, "automerge_keyframes")

View File

@@ -68,9 +68,10 @@ class GRAPH_MT_view(bpy.types.Menu):
layout.column() layout.column()
layout.separator()
layout.operator("graph.properties", icon='MENU_PANEL') layout.operator("graph.properties", icon='MENU_PANEL')
layout.separator()
layout.prop(st, "realtime_updates")
layout.prop(st, "show_cframe_indicator") layout.prop(st, "show_cframe_indicator")
layout.prop(st, "show_cursor") layout.prop(st, "show_cursor")
layout.prop(st, "show_sliders") layout.prop(st, "show_sliders")

View File

@@ -35,6 +35,7 @@ class IMAGE_MT_view(bpy.types.Menu):
show_uvedit = sima.show_uvedit show_uvedit = sima.show_uvedit
layout.operator("image.properties", icon='MENU_PANEL') layout.operator("image.properties", icon='MENU_PANEL')
layout.operator("image.scopes", icon='MENU_PANEL')
layout.separator() layout.separator()
@@ -386,6 +387,21 @@ class IMAGE_PT_game_properties(bpy.types.Panel):
col.separator() col.separator()
col.prop(ima, "mapping", expand=True) col.prop(ima, "mapping", expand=True)
class IMAGE_PT_view_histogram(bpy.types.Panel):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'PREVIEW'
bl_label = "Histogram"
def poll(self, context):
sima = context.space_data
return (sima and sima.image)
def draw(self, context):
layout = self.layout
sima = context.space_data
layout.template_histogram(sima, "histogram")
class IMAGE_PT_view_properties(bpy.types.Panel): class IMAGE_PT_view_properties(bpy.types.Panel):
bl_space_type = 'IMAGE_EDITOR' bl_space_type = 'IMAGE_EDITOR'
@@ -417,6 +433,7 @@ class IMAGE_PT_view_properties(bpy.types.Panel):
col.prop(sima, "draw_repeated", text="Repeat") col.prop(sima, "draw_repeated", text="Repeat")
if show_uvedit: if show_uvedit:
col.prop(uvedit, "normalized_coordinates", text="Normalized") col.prop(uvedit, "normalized_coordinates", text="Normalized")
elif show_uvedit: elif show_uvedit:
col.label(text="Coordinates:") col.label(text="Coordinates:")
col.prop(uvedit, "normalized_coordinates", text="Normalized") col.prop(uvedit, "normalized_coordinates", text="Normalized")
@@ -562,3 +579,4 @@ bpy.types.register(IMAGE_PT_paint_stroke)
bpy.types.register(IMAGE_PT_paint_curve) bpy.types.register(IMAGE_PT_paint_curve)
bpy.types.register(IMAGE_PT_game_properties) bpy.types.register(IMAGE_PT_game_properties)
bpy.types.register(IMAGE_PT_view_properties) bpy.types.register(IMAGE_PT_view_properties)
bpy.types.register(IMAGE_PT_view_histogram)

View File

@@ -90,6 +90,8 @@ class INFO_MT_file(bpy.types.Menu):
layout.separator() layout.separator()
layout.operator("screen.userpref_show", text="User Preferences...", icon='PREFERENCES') layout.operator("screen.userpref_show", text="User Preferences...", icon='PREFERENCES')
layout.operator_context = 'EXEC_AREA'
layout.operator("wm.read_homefile", text="Load Factory Settings").factory = True layout.operator("wm.read_homefile", text="Load Factory Settings").factory = True
layout.separator() layout.separator()
@@ -222,7 +224,11 @@ class INFO_MT_add(bpy.types.Menu):
layout.operator_menu_enum("object.effector_add", "type", 'EMPTY', text="Force Field", icon='OUTLINER_OB_EMPTY') layout.operator_menu_enum("object.effector_add", "type", 'EMPTY', text="Force Field", icon='OUTLINER_OB_EMPTY')
layout.separator() layout.separator()
layout.operator_menu_enum("object.group_instance_add", "type", text="Group Instance", icon='OUTLINER_OB_EMPTY') if(len(bpy.data.groups) > 10):
layout.operator_context = 'INVOKE_DEFAULT'
layout.operator("object.group_instance_add", "type", text="Group Instance...", icon='OUTLINER_OB_EMPTY')
else:
layout.operator_menu_enum("object.group_instance_add", "type", text="Group Instance", icon='OUTLINER_OB_EMPTY')
class INFO_MT_game(bpy.types.Menu): class INFO_MT_game(bpy.types.Menu):

View File

@@ -58,6 +58,8 @@ class NLA_MT_view(bpy.types.Menu):
layout.operator("nla.properties", icon='MENU_PANEL') layout.operator("nla.properties", icon='MENU_PANEL')
layout.separator() layout.separator()
layout.prop(st, "realtime_updates")
layout.prop(st, "show_cframe_indicator") layout.prop(st, "show_cframe_indicator")
layout.operator("anim.time_toggle", text="Show Frames" if st.show_seconds else "Show Seconds") layout.operator("anim.time_toggle", text="Show Frames" if st.show_seconds else "Show Seconds")

View File

@@ -78,7 +78,6 @@ class TEXT_PT_properties(bpy.types.Panel):
layout = self.layout layout = self.layout
st = context.space_data st = context.space_data
text = st.text
flow = layout.column_flow() flow = layout.column_flow()
flow.prop(st, "line_numbers") flow.prop(st, "line_numbers")
@@ -89,7 +88,10 @@ class TEXT_PT_properties(bpy.types.Panel):
flow = layout.column_flow() flow = layout.column_flow()
flow.prop(st, "font_size") flow.prop(st, "font_size")
flow.prop(st, "tab_width") flow.prop(st, "tab_width")
flow.prop(text, "tabs_as_spaces")
text = st.text
if text:
flow.prop(text, "tabs_as_spaces")
class TEXT_PT_find(bpy.types.Panel): class TEXT_PT_find(bpy.types.Panel):

View File

@@ -114,7 +114,13 @@ class TIME_MT_frame(bpy.types.Menu):
layout.operator("marker.duplicate", text="Duplicate Marker") layout.operator("marker.duplicate", text="Duplicate Marker")
layout.operator("marker.move", text="Grab/Move Marker") layout.operator("marker.move", text="Grab/Move Marker")
layout.operator("marker.delete", text="Delete Marker") layout.operator("marker.delete", text="Delete Marker")
layout.label(text="ToDo: Name Marker")
# it was ok for riscos... ok TODO, operator
for marker in context.scene.timeline_markers:
if marker.selected:
layout.separator()
layout.prop(marker, "name", text="", icon='MARKER_HLT')
break
layout.separator() layout.separator()

View File

@@ -18,6 +18,7 @@
# <pep8 compliant> # <pep8 compliant>
import bpy import bpy
import os.path
# General UI Theme Settings (User Interface) # General UI Theme Settings (User Interface)
def ui_items_general(col, context): def ui_items_general(col, context):
@@ -161,7 +162,8 @@ class USERPREF_HT_header(bpy.types.Header):
if userpref.active_section == 'INPUT': if userpref.active_section == 'INPUT':
layout.operator_context = 'INVOKE_DEFAULT' layout.operator_context = 'INVOKE_DEFAULT'
layout.operator("wm.keyconfig_export", "Export Key Configuration...").path = "keymap.py" op = layout.operator("wm.keyconfig_export", "Export Key Configuration...")
op.path = "keymap.py"
class USERPREF_PT_tabs(bpy.types.Panel): class USERPREF_PT_tabs(bpy.types.Panel):
@@ -416,6 +418,13 @@ class USERPREF_PT_system(bpy.types.Panel):
col.separator() col.separator()
col.separator() col.separator()
col.separator() col.separator()
col.label(text="Screencast:")
col.prop(system, "screencast_fps")
col.prop(system, "screencast_wait_time")
col.separator()
col.separator()
col.separator()
#column = split.column() #column = split.column()
#colsplit = column.split(percentage=0.85) #colsplit = column.split(percentage=0.85)
@@ -735,6 +744,7 @@ class USERPREF_PT_theme(bpy.types.Panel):
col = split.column() col = split.column()
col.prop(image, "back") col.prop(image, "back")
col.prop(image, "scope_back")
col.prop(image, "button") col.prop(image, "button")
col = split.column() col = split.column()
@@ -1043,10 +1053,12 @@ class USERPREF_PT_input(bpy.types.Panel):
row = col.row() row = col.row()
row.prop(km, "children_expanded", text="", no_bg=True) row.prop(km, "children_expanded", text="", no_bg=True)
row.label(text=km.name) row.label(text=km.name)
row.label() row.label()
row.label() row.label()
if km.modal:
row.label(text="", icon='LINKED')
if km.user_defined: if km.user_defined:
row.operator("wm.keymap_restore", text="Restore") row.operator("wm.keymap_restore", text="Restore")
else: else:
@@ -1158,15 +1170,24 @@ class USERPREF_PT_input(bpy.types.Panel):
subrow.prop(kmi, "alt") subrow.prop(kmi, "alt")
subrow.prop(kmi, "oskey", text="Cmd") subrow.prop(kmi, "oskey", text="Cmd")
subrow.prop(kmi, "key_modifier", text="", event=True) subrow.prop(kmi, "key_modifier", text="", event=True)
def display_properties(properties, title = None):
box.separator()
if title:
box.label(text=title)
flow = box.column_flow(columns=2)
for pname in dir(properties):
if not properties.is_property_hidden(pname):
value = eval("properties." + pname)
if isinstance(value, bpy.types.OperatorProperties):
display_properties(value, title = pname)
else:
flow.prop(properties, pname)
# Operator properties # Operator properties
props = kmi.properties props = kmi.properties
if props is not None: if props is not None:
box.separator() display_properties(props)
flow = box.column_flow(columns=2)
for pname in dir(props):
if not props.is_property_hidden(pname):
flow.prop(props, pname)
# Modal key maps attached to this operator # Modal key maps attached to this operator
if not km.modal: if not km.modal:
@@ -1336,16 +1357,22 @@ class WM_OT_keyconfig_test(bpy.types.Operator):
s.append(", key_modifier=\'%s\'" % kmi.key_modifier) s.append(", key_modifier=\'%s\'" % kmi.key_modifier)
s.append(")\n") s.append(")\n")
def export_properties(prefix, properties):
for pname in dir(properties):
if not properties.is_property_hidden(pname):
value = eval("properties.%s" % pname)
if isinstance(value, bpy.types.OperatorProperties):
export_properties(prefix + "." + pname, value)
elif properties.is_property_set(pname):
value = _string_value(value)
if value != "":
s.append(prefix + ".%s = %s\n" % (pname, value))
props = kmi.properties props = kmi.properties
if props is not None: if props is not None:
for pname in dir(props): export_properties("kmi.properties", props)
if props.is_property_set(pname) and not props.is_property_hidden(pname):
value = eval("props.%s" % pname)
value = _string_value(value)
if value != "":
s.append("kmi.properties.%s = %s\n" % (pname, value))
return "".join(s).strip() return "".join(s).strip()
@@ -1443,6 +1470,9 @@ class WM_OT_keyconfig_export(bpy.types.Operator):
bl_label = "Export Key Configuration..." bl_label = "Export Key Configuration..."
path = bpy.props.StringProperty(name="File Path", description="File path to write file to.") path = bpy.props.StringProperty(name="File Path", description="File path to write file to.")
filter_folder = bpy.props.BoolProperty(name="Filter folders", description="", default=True)
filter_text = bpy.props.BoolProperty(name="Filter text", description="", default=True)
filter_python = bpy.props.BoolProperty(name="Filter python", description="", default=True)
def execute(self, context): def execute(self, context):
if not self.properties.path: if not self.properties.path:
@@ -1455,10 +1485,15 @@ class WM_OT_keyconfig_export(bpy.types.Operator):
wm = context.manager wm = context.manager
kc = wm.active_keyconfig kc = wm.active_keyconfig
f.write('# Configuration %s\n' % kc.name) if kc.name == 'Blender':
name = os.path.splitext(os.path.basename(self.properties.path))[0]
else:
name = kc.name
f.write("wm = bpy.data.windowmanagers[0]\n") f.write('# Configuration %s\n' % name)
f.write("kc = wm.add_keyconfig(\'%s\')\n\n" % kc.name)
f.write("wm = bpy.data.window_managers[0]\n")
f.write("kc = wm.add_keyconfig(\'%s\')\n\n" % name)
for km in kc.keymaps: for km in kc.keymaps:
km = km.active() km = km.active()
@@ -1484,18 +1519,25 @@ class WM_OT_keyconfig_export(bpy.types.Operator):
f.write(", key_modifier=\'%s\'" % kmi.key_modifier) f.write(", key_modifier=\'%s\'" % kmi.key_modifier)
f.write(")\n") f.write(")\n")
def export_properties(prefix, properties):
for pname in dir(properties):
if not properties.is_property_hidden(pname):
value = eval("properties.%s" % pname)
if isinstance(value, bpy.types.OperatorProperties):
export_properties(prefix + "." + pname, value)
elif properties.is_property_set(pname):
value = _string_value(value)
if value != "":
f.write(prefix + ".%s = %s\n" % (pname, value))
props = kmi.properties props = kmi.properties
if props is not None: if props is not None:
for pname in dir(props): export_properties("kmi.properties", props)
if props.is_property_set(pname) and not props.is_property_hidden(pname):
value = eval("props.%s" % pname)
value = _string_value(value)
if value != "":
f.write("kmi.properties.%s = %s\n" % (pname, value))
f.write("\n") f.write("\n")
f.write("wm.active_keyconfig = wm.keyconfigs[\'%s\']\n" % name)
f.close() f.close()
return {'FINISHED'} return {'FINISHED'}

View File

@@ -419,6 +419,9 @@ class VIEW3D_MT_select_pose(bpy.types.Menu):
props.extend = True props.extend = True
props.direction = 'CHILD' props.direction = 'CHILD'
layout.separator()
layout.operator_menu_enum("pose.select_grouped", "type", text="Grouped")
layout.operator("object.select_pattern", text="Select Pattern...") layout.operator("object.select_pattern", text="Select Pattern...")
@@ -987,6 +990,8 @@ class VIEW3D_MT_pose(bpy.types.Menu):
layout.operator("pose.autoside_names", text="AutoName Top/Bottom").axis = 'ZAXIS' layout.operator("pose.autoside_names", text="AutoName Top/Bottom").axis = 'ZAXIS'
layout.operator("pose.flip_names") layout.operator("pose.flip_names")
layout.operator("pose.quaternions_flip")
layout.separator() layout.separator()
@@ -1783,7 +1788,7 @@ class VIEW3D_PT_3dview_curvedisplay(bpy.types.Panel):
class VIEW3D_PT_background_image(bpy.types.Panel): class VIEW3D_PT_background_image(bpy.types.Panel):
bl_space_type = 'VIEW_3D' bl_space_type = 'VIEW_3D'
bl_region_type = 'UI' bl_region_type = 'UI'
bl_label = "Background Image" bl_label = "Background Images"
bl_default_closed = True bl_default_closed = True
def poll(self, context): def poll(self, context):
@@ -1795,34 +1800,38 @@ class VIEW3D_PT_background_image(bpy.types.Panel):
layout = self.layout layout = self.layout
view = context.space_data view = context.space_data
layout.prop(view, "display_background_image", text="") layout.prop(view, "display_background_images", text="")
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
view = context.space_data view = context.space_data
bg = view.background_image
col = layout.column()
col.operator("view3d.add_background_image", text="Add Image")
if bg: for i, bg in enumerate(view.background_images):
layout.active = view.display_background_image layout.active = view.display_background_images
box = layout.box() box = layout.box()
if (bg.image): row = box.row(align=True)
box.template_ID(bg, "image", open="image.open") row.prop(bg, "show_expanded", text="", no_bg=True)
box.template_image(bg, "image", bg.image_user, compact=True) row.label(text=getattr(bg.image, "name", "Not Set"))
else: row.operator("view3d.remove_background_image", text="", icon='X').index = i
box.template_ID(bg, "image", open="image.open")
col = layout.column() box.prop(bg, "view_axis", text="Axis")
col.label(text="Display Settings")
col = layout.column() if bg.show_expanded:
col.prop(bg, "size") row = box.row()
col.prop(bg, "transparency", slider=True) row.template_ID(bg, "image", open="image.open")
if (bg.image):
box.template_image(bg, "image", bg.image_user, compact=True)
col = layout.column() box.prop(bg, "transparency", slider=True)
col.label(text="Offset") box.prop(bg, "size")
col.prop(bg, "offset_x", text="X") row = box.row(align=True)
col.prop(bg, "offset_y", text="Y") row.prop(bg, "offset_x", text="X")
row.prop(bg, "offset_y", text="Y")
class VIEW3D_PT_transform_orientations(bpy.types.Panel): class VIEW3D_PT_transform_orientations(bpy.types.Panel):
bl_space_type = 'VIEW_3D' bl_space_type = 'VIEW_3D'

View File

@@ -500,13 +500,13 @@ class VIEW3D_PT_tools_brush(PaintPanel):
row = col.row() row = col.row()
if context.sculpt_object and brush: if context.sculpt_object and brush:
defaulttools = 8 defaultbrushes = 8
elif context.texture_paint_object and brush: elif context.texture_paint_object and brush:
defaulttools = 4 defaultbrushes = 4
else: else:
defaulttools = 2 defaultbrushes = 7
row.template_list(settings, "brushes", settings, "active_brush_index", rows=2, maxrows=defaulttools) row.template_list(settings, "brushes", settings, "active_brush_index", rows=2, maxrows=defaultbrushes)
col.template_ID(settings, "brush", new="brush.add") col.template_ID(settings, "brush", new="brush.add")
@@ -657,8 +657,9 @@ class VIEW3D_PT_tools_brush_tool(PaintPanel):
def poll(self, context): def poll(self, context):
settings = self.paint_settings(context) settings = self.paint_settings(context)
return (settings and settings.brush and (context.sculpt_object or return (settings and settings.brush and
context.texture_paint_object)) (context.sculpt_object or context.texture_paint_object or
context.vertex_paint_object or context.weight_paint_object))
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
@@ -673,10 +674,13 @@ class VIEW3D_PT_tools_brush_tool(PaintPanel):
if context.sculpt_object: if context.sculpt_object:
col.prop(brush, "sculpt_tool", expand=True) col.prop(brush, "sculpt_tool", expand=True)
elif context.texture_paint_object: elif context.texture_paint_object:
col.prop_enum(settings, "tool", 'DRAW') col.prop(brush, "imagepaint_tool", expand=True)
col.prop_enum(settings, "tool", 'SOFTEN') #col.prop_enum(settings, "tool", 'DRAW')
col.prop_enum(settings, "tool", 'CLONE') #col.prop_enum(settings, "tool", 'SOFTEN')
col.prop_enum(settings, "tool", 'SMEAR') #col.prop_enum(settings, "tool", 'CLONE')
#col.prop_enum(settings, "tool", 'SMEAR')
elif context.vertex_paint_object or context.weight_paint_object:
col.prop(brush, "vertexpaint_tool", expand=True)
class VIEW3D_PT_tools_brush_stroke(PaintPanel): class VIEW3D_PT_tools_brush_stroke(PaintPanel):
@@ -780,7 +784,6 @@ class VIEW3D_PT_tools_weightpaint(View3DPanel):
layout = self.layout layout = self.layout
col = layout.column() col = layout.column()
# col.label(text="Blend:")
col.operator("object.vertex_group_normalize_all", text="Normalize All") col.operator("object.vertex_group_normalize_all", text="Normalize All")
col.operator("object.vertex_group_normalize", text="Normalize") col.operator("object.vertex_group_normalize", text="Normalize")
col.operator("object.vertex_group_invert", text="Invert") col.operator("object.vertex_group_invert", text="Invert")
@@ -798,8 +801,6 @@ class VIEW3D_PT_tools_weightpaint_options(View3DPanel):
wpaint = context.tool_settings.weight_paint wpaint = context.tool_settings.weight_paint
col = layout.column() col = layout.column()
col.label(text="Blend:")
col.prop(wpaint, "mode", text="")
col.prop(wpaint, "all_faces") col.prop(wpaint, "all_faces")
col.prop(wpaint, "normals") col.prop(wpaint, "normals")
col.prop(wpaint, "spray") col.prop(wpaint, "spray")
@@ -830,8 +831,7 @@ class VIEW3D_PT_tools_vertexpaint(View3DPanel):
vpaint = context.tool_settings.vertex_paint vpaint = context.tool_settings.vertex_paint
col = layout.column() col = layout.column()
col.label(text="Blend:") #col.prop(vpaint, "mode", text="")
col.prop(vpaint, "mode", text="")
col.prop(vpaint, "all_faces") col.prop(vpaint, "all_faces")
col.prop(vpaint, "normals") col.prop(vpaint, "normals")
col.prop(vpaint, "spray") col.prop(vpaint, "spray")
@@ -850,7 +850,7 @@ class VIEW3D_PT_tools_projectpaint(View3DPanel):
bl_label = "Project Paint" bl_label = "Project Paint"
def poll(self, context): def poll(self, context):
return context.tool_settings.image_paint.tool != 'SMEAR' return context.tool_settings.image_paint.brush.imagepaint_tool != 'SMEAR'
def draw_header(self, context): def draw_header(self, context):
ipaint = context.tool_settings.image_paint ipaint = context.tool_settings.image_paint
@@ -893,7 +893,7 @@ class VIEW3D_PT_tools_projectpaint(View3DPanel):
col = layout.column() col = layout.column()
sub = col.column() sub = col.column()
row = sub.row() row = sub.row()
row.active = (settings.tool == 'CLONE') row.active = (settings.brush.imagepaint_tool == 'CLONE')
row.prop(ipaint, "use_clone_layer", text="Clone") row.prop(ipaint, "use_clone_layer", text="Clone")
row.menu("VIEW3D_MT_tools_projectpaint_clone", text=context.active_object.data.uv_texture_clone.name) row.menu("VIEW3D_MT_tools_projectpaint_clone", text=context.active_object.data.uv_texture_clone.name)

View File

@@ -96,7 +96,6 @@ COMLIB += $(OCGDIR)/blender/nodes_cmp/$(DEBUG_DIR)libnodes_cmp.a
COMLIB += $(OCGDIR)/blender/nodes_tex/$(DEBUG_DIR)libnodes_tex.a COMLIB += $(OCGDIR)/blender/nodes_tex/$(DEBUG_DIR)libnodes_tex.a
COMLIB += $(OCGDIR)/blender/nodes/$(DEBUG_DIR)libnodes.a COMLIB += $(OCGDIR)/blender/nodes/$(DEBUG_DIR)libnodes.a
COMLIB += $(OCGDIR)/blender/imbuf/$(DEBUG_DIR)libimbuf.a COMLIB += $(OCGDIR)/blender/imbuf/$(DEBUG_DIR)libimbuf.a
COMLIB += $(OCGDIR)/blender/blenlib/$(DEBUG_DIR)libblenlib.a
COMLIB += $(OCGDIR)/blender/ikplugin/$(DEBUG_DIR)libikplugin.a COMLIB += $(OCGDIR)/blender/ikplugin/$(DEBUG_DIR)libikplugin.a
COMLIB += $(NAN_IKSOLVER)/lib/$(DEBUG_DIR)libiksolver.a COMLIB += $(NAN_IKSOLVER)/lib/$(DEBUG_DIR)libiksolver.a
COMLIB += $(NAN_ITASC)/lib/$(DEBUG_DIR)libitasc.a COMLIB += $(NAN_ITASC)/lib/$(DEBUG_DIR)libitasc.a
@@ -184,6 +183,8 @@ COMLIB += $(NAN_MEMUTIL)/lib/libmemutil.a
COMLIB += $(NAN_PNG)/lib/libpng.a COMLIB += $(NAN_PNG)/lib/libpng.a
COMLIB += $(OCGDIR)/blender/python/$(DEBUG_DIR)libpython.a # This was a PULIB up to circa r25248 COMLIB += $(OCGDIR)/blender/python/$(DEBUG_DIR)libpython.a # This was a PULIB up to circa r25248
COMLIB += $(OCGDIR)/blender/gen_python/$(DEBUG_DIR)libgen_python.a COMLIB += $(OCGDIR)/blender/gen_python/$(DEBUG_DIR)libgen_python.a
COMLIB += $(OCGDIR)/blender/blenlib/$(DEBUG_DIR)libblenlib.a
ifeq ($(WITH_QUICKTIME), true) ifeq ($(WITH_QUICKTIME), true)
COMLIB += $(OCGDIR)/blender/blenderqt/$(DEBUG_DIR)libblenderqt.a COMLIB += $(OCGDIR)/blender/blenderqt/$(DEBUG_DIR)libblenderqt.a

View File

@@ -502,8 +502,8 @@ void makeDerivedMesh(struct Scene *scene, struct Object *ob, struct EditMesh *em
/* returns an array of deform matrices for crazyspace correction, and the /* returns an array of deform matrices for crazyspace correction, and the
number of modifiers left */ number of modifiers left */
int editmesh_get_first_deform_matrices(struct Object *, struct EditMesh *em, float (**deformmats)[3][3], int editmesh_get_first_deform_matrices(struct Scene *, struct Object *, struct EditMesh *em,
float (**deformcos)[3]); float (**deformmats)[3][3], float (**deformcos)[3]);
void weight_to_rgb(float input, float *fr, float *fg, float *fb); void weight_to_rgb(float input, float *fr, float *fg, float *fb);

View File

@@ -53,7 +53,9 @@ void animviz_free_motionpath_cache(struct bMotionPath *mpath);
void animviz_free_motionpath(struct bMotionPath *mpath); void animviz_free_motionpath(struct bMotionPath *mpath);
struct bMotionPath *animviz_verify_motionpaths(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan); struct bMotionPath *animviz_verify_motionpaths(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan);
void animviz_calc_motionpaths(struct Scene *scene, struct Object *ob);
void animviz_get_object_motionpaths(Object *ob, ListBase *targets);
void animviz_calc_motionpaths(struct Scene *scene, ListBase *targets);
/* ---------------------------------------------------- */ /* ---------------------------------------------------- */
/* Curve Paths */ /* Curve Paths */

View File

@@ -43,7 +43,7 @@ struct bContext;
struct ReportList; struct ReportList;
#define BLENDER_VERSION 250 #define BLENDER_VERSION 250
#define BLENDER_SUBVERSION 11 #define BLENDER_SUBVERSION 13
#define BLENDER_MINVERSION 250 #define BLENDER_MINVERSION 250
#define BLENDER_MINSUBVERSION 0 #define BLENDER_MINSUBVERSION 0
@@ -62,12 +62,6 @@ void BKE_userdef_free(void);
void set_blender_test_break_cb(void (*func)(void) ); void set_blender_test_break_cb(void (*func)(void) );
int blender_test_break(void); int blender_test_break(void);
void pushdata(void *data, int len);
void popfirst(void *data);
void poplast(void *data);
void free_pushpop(void);
void pushpop_test(void);
/* global undo */ /* global undo */
extern void BKE_write_undo(struct bContext *C, char *name); extern void BKE_write_undo(struct bContext *C, char *name);
extern void BKE_undo_step(struct bContext *C, int step); extern void BKE_undo_step(struct bContext *C, int step);

View File

@@ -31,9 +31,20 @@
struct CurveMapping; struct CurveMapping;
struct CurveMap; struct CurveMap;
struct Histogram;
struct ImBuf; struct ImBuf;
struct rctf; struct rctf;
#if defined _WIN32
# define DO_INLINE __inline
#elif defined (__sgi)
# define DO_INLINE
#elif defined (__sun) || defined (__sun__)
# define DO_INLINE
#else
# define DO_INLINE static inline
#endif
typedef enum CurveMappingPreset { typedef enum CurveMappingPreset {
CURVE_PRESET_LINE, CURVE_PRESET_LINE,
CURVE_PRESET_SHARP, CURVE_PRESET_SHARP,
@@ -70,6 +81,7 @@ void curvemapping_initialize(struct CurveMapping *cumap);
void curvemapping_table_RGBA(struct CurveMapping *cumap, float **array, int *size); void curvemapping_table_RGBA(struct CurveMapping *cumap, float **array, int *size);
void colorcorrection_do_ibuf(struct ImBuf *ibuf, const char *profile); void colorcorrection_do_ibuf(struct ImBuf *ibuf, const char *profile);
void histogram_update(struct Histogram *hist, struct ImBuf *ibuf);
#endif #endif

View File

@@ -128,7 +128,7 @@ struct Image *BKE_image_verify_viewer(int type, const char *name);
void BKE_image_assign_ibuf(struct Image *ima, struct ImBuf *ibuf); void BKE_image_assign_ibuf(struct Image *ima, struct ImBuf *ibuf);
/* called on frame change or before render */ /* called on frame change or before render */
void BKE_image_user_calc_imanr(struct ImageUser *iuser, int cfra, int fieldnr); void BKE_image_user_calc_frame(struct ImageUser *iuser, int cfra, int fieldnr);
/* produce image export path */ /* produce image export path */
int BKE_get_image_export_path(struct Image *im, const char *dest_dir, char *abs, int abs_size, char *rel, int rel_size); int BKE_get_image_export_path(struct Image *im, const char *dest_dir, char *abs, int abs_size, char *rel, int rel_size);

View File

@@ -279,10 +279,10 @@ void modifier_unique_name(struct ListBase *modifiers, struct ModifierData *m
void modifier_copyData(struct ModifierData *md, struct ModifierData *target); void modifier_copyData(struct ModifierData *md, struct ModifierData *target);
int modifier_dependsOnTime(struct ModifierData *md); int modifier_dependsOnTime(struct ModifierData *md);
int modifier_supportsMapping(struct ModifierData *md); int modifier_supportsMapping(struct ModifierData *md);
int modifier_couldBeCage(struct ModifierData *md); int modifier_couldBeCage(struct Scene *scene, struct ModifierData *md);
int modifier_isCorrectableDeformed(struct ModifierData *md); int modifier_isCorrectableDeformed(struct ModifierData *md);
int modifier_sameTopology(ModifierData *md); int modifier_sameTopology(ModifierData *md);
int modifier_isEnabled(struct ModifierData *md, int required_mode); int modifier_isEnabled(struct Scene *scene, struct ModifierData *md, int required_mode);
void modifier_setError(struct ModifierData *md, char *format, ...); void modifier_setError(struct ModifierData *md, char *format, ...);
void modifiers_foreachObjectLink(struct Object *ob, void modifiers_foreachObjectLink(struct Object *ob,
@@ -293,7 +293,7 @@ void modifiers_foreachIDLink(struct Object *ob,
void *userData); void *userData);
struct ModifierData *modifiers_findByType(struct Object *ob, ModifierType type); struct ModifierData *modifiers_findByType(struct Object *ob, ModifierType type);
void modifiers_clearErrors(struct Object *ob); void modifiers_clearErrors(struct Object *ob);
int modifiers_getCageIndex(struct Object *ob, int modifiers_getCageIndex(struct Scene *scene, struct Object *ob,
int *lastPossibleCageIndex_r, int virtual_); int *lastPossibleCageIndex_r, int virtual_);
int modifiers_isSoftbodyEnabled(struct Object *ob); int modifiers_isSoftbodyEnabled(struct Object *ob);
@@ -313,7 +313,8 @@ int modifiers_indexInObject(struct Object *ob, struct ModifierData *md
* evaluation, assuming the data indicated by dataMask is required at the * evaluation, assuming the data indicated by dataMask is required at the
* end of the stack. * end of the stack.
*/ */
struct LinkNode *modifiers_calcDataMasks(struct Object *ob, struct LinkNode *modifiers_calcDataMasks(struct Scene *scene,
struct Object *ob,
struct ModifierData *md, struct ModifierData *md,
CustomDataMask dataMask, CustomDataMask dataMask,
int required_mode); int required_mode);

View File

@@ -83,6 +83,7 @@ struct NlaStrip *BKE_nlastrip_find_active(struct NlaTrack *nlt);
void BKE_nlastrip_set_active(struct AnimData *adt, struct NlaStrip *strip); void BKE_nlastrip_set_active(struct AnimData *adt, struct NlaStrip *strip);
short BKE_nlastrip_within_bounds(struct NlaStrip *strip, float min, float max); short BKE_nlastrip_within_bounds(struct NlaStrip *strip, float min, float max);
void BKE_nlastrip_recalculate_bounds(struct NlaStrip *strip);
void BKE_nlastrip_validate_name(struct AnimData *adt, struct NlaStrip *strip); void BKE_nlastrip_validate_name(struct AnimData *adt, struct NlaStrip *strip);

View File

@@ -354,6 +354,8 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMaterial *mat);
#define CMP_NODE_DIST_MATTE 257 #define CMP_NODE_DIST_MATTE 257
#define CMP_NODE_VIEW_LEVELS 258 #define CMP_NODE_VIEW_LEVELS 258
#define CMP_NODE_COLOR_MATTE 259 #define CMP_NODE_COLOR_MATTE 259
#define CMP_NODE_COLORBALANCE 260
#define CMP_NODE_HUECORRECT 261
#define CMP_NODE_GLARE 301 #define CMP_NODE_GLARE 301
#define CMP_NODE_TONEMAP 302 #define CMP_NODE_TONEMAP 302

View File

@@ -67,6 +67,7 @@ void object_link_modifiers(struct Object *ob, struct Object *from);
void object_free_modifiers(struct Object *ob); void object_free_modifiers(struct Object *ob);
void object_make_proxy(struct Object *ob, struct Object *target, struct Object *gob); void object_make_proxy(struct Object *ob, struct Object *target, struct Object *gob);
void object_copy_proxy_drivers(struct Object *ob, struct Object *target);
void unlink_object(struct Scene *scene, struct Object *ob); void unlink_object(struct Scene *scene, struct Object *ob);
int exist_object(struct Object *obtest); int exist_object(struct Object *obtest);

View File

@@ -28,8 +28,8 @@
* ***** END GPL LICENSE BLOCK ***** * ***** END GPL LICENSE BLOCK *****
*/ */
#ifndef BKE_SEQUENCE_H #ifndef BKE_SEQUENCER_H
#define BKE_SEQUENCE_H #define BKE_SEQUENCER_H
struct Editing; struct Editing;
struct Sequence; struct Sequence;
@@ -77,8 +77,6 @@ void seq_array(struct Editing *ed, struct Sequence ***seqarray, int *tot, int us
seq_end(&iter); \ seq_end(&iter); \
} }
#endif
/* Wipe effect */ /* Wipe effect */
enum {DO_SINGLE_WIPE, DO_DOUBLE_WIPE, DO_BOX_WIPE, DO_CROSS_WIPE, enum {DO_SINGLE_WIPE, DO_DOUBLE_WIPE, DO_BOX_WIPE, DO_CROSS_WIPE,
@@ -238,3 +236,5 @@ struct Sequence *sequencer_add_movie_strip(struct bContext *C, ListBase *seqbase
/* copy/paste */ /* copy/paste */
extern ListBase seqbase_clipboard; extern ListBase seqbase_clipboard;
extern int seqbase_clipboard_frame; extern int seqbase_clipboard_frame;
#endif // BKE_SEQUENCER_H

View File

@@ -262,3 +262,11 @@ behaviour, though it may not be the best in practice.
#endif #endif
/*little macro so inline keyword works*/
#if defined(_MSC_VER)
#define BM_INLINE static __forceinline
#else
#define BM_INLINE static inline __attribute((always_inline))
#endif
#define BMEMSET(mem, val, size) {unsigned int _i; char *_c = (char*) mem; for (_i=0; _i<size; _i++) *_c++ = val;}

View File

@@ -84,7 +84,7 @@ void BME_CD_Create(BME_CustomData *data, BME_CustomDataInit *init, int initalloc
if(data->totlayer){ if(data->totlayer){
/*alloc memory*/ /*alloc memory*/
data->layers = MEM_callocN(sizeof(BME_CustomDataLayer)*data->totlayer, "BMesh Custom Data Layers"); data->layers = MEM_callocN(sizeof(BME_CustomDataLayer)*data->totlayer, "BMesh Custom Data Layers");
data->pool = BLI_mempool_create(data->totsize, initalloc, initalloc); data->pool = BLI_mempool_create(data->totsize, initalloc, initalloc, 0);
/*initialize layer data*/ /*initialize layer data*/
for(i=0; i < BME_CD_NUMTYPES; i++){ for(i=0; i < BME_CD_NUMTYPES; i++){
if(init->layout[i]){ if(init->layout[i]){

View File

@@ -55,10 +55,10 @@ BME_Mesh *BME_make_mesh(int allocsize[4])
/*allocate the structure*/ /*allocate the structure*/
BME_Mesh *bm = MEM_callocN(sizeof(BME_Mesh),"BMesh"); BME_Mesh *bm = MEM_callocN(sizeof(BME_Mesh),"BMesh");
/*allocate the memory pools for the mesh elements*/ /*allocate the memory pools for the mesh elements*/
bm->vpool = BLI_mempool_create(sizeof(BME_Vert), allocsize[0], allocsize[0]); bm->vpool = BLI_mempool_create(sizeof(BME_Vert), allocsize[0], allocsize[0], 0);
bm->epool = BLI_mempool_create(sizeof(BME_Edge), allocsize[1], allocsize[1]); bm->epool = BLI_mempool_create(sizeof(BME_Edge), allocsize[1], allocsize[1], 0);
bm->lpool = BLI_mempool_create(sizeof(BME_Loop), allocsize[2], allocsize[2]); bm->lpool = BLI_mempool_create(sizeof(BME_Loop), allocsize[2], allocsize[2], 0);
bm->ppool = BLI_mempool_create(sizeof(BME_Poly), allocsize[3], allocsize[3]); bm->ppool = BLI_mempool_create(sizeof(BME_Poly), allocsize[3], allocsize[3], 0);
return bm; return bm;
} }
/* /*

View File

@@ -1643,7 +1643,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
/* we always want to keep original indices */ /* we always want to keep original indices */
dataMask |= CD_MASK_ORIGINDEX; dataMask |= CD_MASK_ORIGINDEX;
datamasks = modifiers_calcDataMasks(ob, md, dataMask, required_mode); datamasks = modifiers_calcDataMasks(scene, ob, md, dataMask, required_mode);
curr = datamasks; curr = datamasks;
if(deform_r) *deform_r = NULL; if(deform_r) *deform_r = NULL;
@@ -1659,7 +1659,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
md->scene= scene; md->scene= scene;
if(!modifier_isEnabled(md, required_mode)) continue; if(!modifier_isEnabled(scene, md, required_mode)) continue;
if(useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) continue; if(useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) continue;
if(mti->type == eModifierTypeType_OnlyDeform) { if(mti->type == eModifierTypeType_OnlyDeform) {
@@ -1708,7 +1708,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
md->scene= scene; md->scene= scene;
if(!modifier_isEnabled(md, required_mode)) continue; if(!modifier_isEnabled(scene, md, required_mode)) continue;
if(mti->type == eModifierTypeType_OnlyDeform && !useDeform) continue; if(mti->type == eModifierTypeType_OnlyDeform && !useDeform) continue;
if((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) { if((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) {
modifier_setError(md, "Modifier requires original data, bad stack position."); modifier_setError(md, "Modifier requires original data, bad stack position.");
@@ -1884,12 +1884,12 @@ static float (*editmesh_getVertexCos(EditMesh *em, int *numVerts_r))[3]
return cos; return cos;
} }
static int editmesh_modifier_is_enabled(ModifierData *md, DerivedMesh *dm) static int editmesh_modifier_is_enabled(Scene *scene, ModifierData *md, DerivedMesh *dm)
{ {
ModifierTypeInfo *mti = modifierType_getInfo(md->type); ModifierTypeInfo *mti = modifierType_getInfo(md->type);
int required_mode = eModifierMode_Realtime | eModifierMode_Editmode; int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
if(!modifier_isEnabled(md, required_mode)) return 0; if(!modifier_isEnabled(scene, md, required_mode)) return 0;
if((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) { if((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) {
modifier_setError(md, "Modifier requires original data, bad stack position."); modifier_setError(md, "Modifier requires original data, bad stack position.");
return 0; return 0;
@@ -1906,7 +1906,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri
float (*deformedVerts)[3] = NULL; float (*deformedVerts)[3] = NULL;
CustomDataMask mask; CustomDataMask mask;
DerivedMesh *dm, *orcodm = NULL; DerivedMesh *dm, *orcodm = NULL;
int i, numVerts = 0, cageIndex = modifiers_getCageIndex(ob, NULL, 1); int i, numVerts = 0, cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1);
LinkNode *datamasks, *curr; LinkNode *datamasks, *curr;
int required_mode = eModifierMode_Realtime | eModifierMode_Editmode; int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
@@ -1922,7 +1922,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri
/* we always want to keep original indices */ /* we always want to keep original indices */
dataMask |= CD_MASK_ORIGINDEX; dataMask |= CD_MASK_ORIGINDEX;
datamasks = modifiers_calcDataMasks(ob, md, dataMask, required_mode); datamasks = modifiers_calcDataMasks(scene, ob, md, dataMask, required_mode);
curr = datamasks; curr = datamasks;
for(i = 0; md; i++, md = md->next, curr = curr->next) { for(i = 0; md; i++, md = md->next, curr = curr->next) {
@@ -1930,7 +1930,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri
md->scene= scene; md->scene= scene;
if(!editmesh_modifier_is_enabled(md, dm)) if(!editmesh_modifier_is_enabled(scene, md, dm))
continue; continue;
/* add an orco layer if needed by this modifier */ /* add an orco layer if needed by this modifier */
@@ -2108,7 +2108,8 @@ static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask)
{ {
Object *obact = scene->basact?scene->basact->object:NULL; Object *obact = scene->basact?scene->basact->object:NULL;
int editing = paint_facesel_test(ob); int editing = paint_facesel_test(ob);
int needMapping = editing && (ob==obact); /* weight paint and face select need original indicies because of selection buffer drawing */
int needMapping = (ob==obact) && (editing || (ob->mode & OB_MODE_WEIGHT_PAINT) || paint_facesel_test(ob));
float min[3], max[3]; float min[3], max[3];
clear_mesh_caches(ob); clear_mesh_caches(ob);
@@ -2348,12 +2349,12 @@ float *mesh_get_mapped_verts_nors(Scene *scene, Object *ob)
/* ********* crazyspace *************** */ /* ********* crazyspace *************** */
int editmesh_get_first_deform_matrices(Object *ob, EditMesh *em, float (**deformmats)[3][3], float (**deformcos)[3]) int editmesh_get_first_deform_matrices(Scene *scene, Object *ob, EditMesh *em, float (**deformmats)[3][3], float (**deformcos)[3])
{ {
ModifierData *md; ModifierData *md;
DerivedMesh *dm; DerivedMesh *dm;
int i, a, numleft = 0, numVerts = 0; int i, a, numleft = 0, numVerts = 0;
int cageIndex = modifiers_getCageIndex(ob, NULL, 1); int cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1);
float (*defmats)[3][3] = NULL, (*deformedVerts)[3] = NULL; float (*defmats)[3][3] = NULL, (*deformedVerts)[3] = NULL;
modifiers_clearErrors(ob); modifiers_clearErrors(ob);
@@ -2367,7 +2368,7 @@ int editmesh_get_first_deform_matrices(Object *ob, EditMesh *em, float (**deform
for(i = 0; md && i <= cageIndex; i++, md = md->next) { for(i = 0; md && i <= cageIndex; i++, md = md->next) {
ModifierTypeInfo *mti = modifierType_getInfo(md->type); ModifierTypeInfo *mti = modifierType_getInfo(md->type);
if(!editmesh_modifier_is_enabled(md, dm)) if(!editmesh_modifier_is_enabled(scene, md, dm))
continue; continue;
if(mti->type==eModifierTypeType_OnlyDeform && mti->deformMatricesEM) { if(mti->type==eModifierTypeType_OnlyDeform && mti->deformMatricesEM) {
@@ -2388,7 +2389,7 @@ int editmesh_get_first_deform_matrices(Object *ob, EditMesh *em, float (**deform
} }
for(; md && i <= cageIndex; md = md->next, i++) for(; md && i <= cageIndex; md = md->next, i++)
if(editmesh_modifier_is_enabled(md, dm) && modifier_isCorrectableDeformed(md)) if(editmesh_modifier_is_enabled(scene, md, dm) && modifier_isCorrectableDeformed(md))
numleft++; numleft++;
if(dm) if(dm)

View File

@@ -154,7 +154,7 @@ void animviz_free_motionpath(bMotionPath *mpath)
/* ------------------- */ /* ------------------- */
/* Setup motion paths for the given data /* Setup motion paths for the given data
* - scene: current scene (for frame ranges, etc.) * - scene: current scene (for frame ranges, etc.)
* - ob: object to add paths for (must be provided) * - ob: object to add paths for (must be provided)
* - pchan: posechannel to add paths for (optional; if not provided, object-paths are assumed) * - pchan: posechannel to add paths for (optional; if not provided, object-paths are assumed)
@@ -226,8 +226,10 @@ typedef struct MPathTarget {
/* ........ */ /* ........ */
/* get list of motion paths to be baked (assumes the list is ready to be used) */ /* get list of motion paths to be baked for the given object
static void motionpaths_get_bake_targets(Object *ob, ListBase *targets) * - assumes the given list is ready to be used
*/
void animviz_get_object_motionpaths(Object *ob, ListBase *targets)
{ {
MPathTarget *mpt; MPathTarget *mpt;
@@ -260,6 +262,8 @@ static void motionpaths_get_bake_targets(Object *ob, ListBase *targets)
} }
} }
/* ........ */
/* perform baking for the targets on the current frame */ /* perform baking for the targets on the current frame */
static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets) static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets)
{ {
@@ -270,8 +274,10 @@ static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets)
bMotionPath *mpath= mpt->mpath; bMotionPath *mpath= mpt->mpath;
bMotionPathVert *mpv; bMotionPathVert *mpv;
/* current frame must be within the range the cache works for */ /* current frame must be within the range the cache works for
if (IN_RANGE(CFRA, mpath->start_frame, mpath->end_frame) == 0) * - is inclusive of the first frame, but not the last otherwise we get buffer overruns
*/
if ((CFRA < mpath->start_frame) || (CFRA >= mpath->end_frame))
continue; continue;
/* get the relevant cache vert to write to */ /* get the relevant cache vert to write to */
@@ -297,36 +303,30 @@ static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets)
} }
} }
/* ........ */
/* Perform baking of the given object's and/or its bones' transforms to motion paths /* Perform baking of the given object's and/or its bones' transforms to motion paths
* - scene: current scene * - scene: current scene
* - ob: object whose flagged motionpaths should get calculated * - ob: object whose flagged motionpaths should get calculated
* - recalc: whether we need to * - recalc: whether we need to
*/ */
// TODO: include reports pointer? // TODO: include reports pointer?
void animviz_calc_motionpaths(Scene *scene, Object *ob) void animviz_calc_motionpaths(Scene *scene, ListBase *targets)
{ {
ListBase targets = {NULL, NULL};
MPathTarget *mpt; MPathTarget *mpt;
int sfra, efra; int sfra, efra;
int cfra; int cfra;
/* sanity checks */ /* sanity check */
if (ob == NULL) if (ELEM(NULL, targets, targets->first))
return;
/* get motion paths to affect */
motionpaths_get_bake_targets(ob, &targets);
if (targets.first == NULL)
return; return;
/* set frame values */ /* set frame values */
cfra = CFRA; cfra = CFRA;
sfra = efra = cfra; sfra = efra = cfra;
for (mpt= targets.first; mpt; mpt= mpt->next) { // TODO: this method could be improved...
// 1) max range for standard baking
// 2) minimum range for recalc baking (i.e. between keyfames, but how?)
for (mpt= targets->first; mpt; mpt= mpt->next) {
/* try to increase area to do (only as much as needed) */ /* try to increase area to do (only as much as needed) */
sfra= MIN2(sfra, mpt->mpath->start_frame); sfra= MIN2(sfra, mpt->mpath->start_frame);
efra= MAX2(efra, mpt->mpath->end_frame); efra= MAX2(efra, mpt->mpath->end_frame);
@@ -340,23 +340,29 @@ void animviz_calc_motionpaths(Scene *scene, Object *ob)
* that doesn't force complete update, but for now, this is the * that doesn't force complete update, but for now, this is the
* most accurate way! * most accurate way!
*/ */
scene_update_for_newframe(scene, ob->lay); // XXX is the layer flag too restrictive? scene_update_for_newframe(scene, scene->lay); // XXX this is the best way we can get anything moving
/* perform baking for targets */ /* perform baking for targets */
motionpaths_calc_bake_targets(scene, &targets); motionpaths_calc_bake_targets(scene, targets);
} }
/* reset original environment */ /* reset original environment */
CFRA= cfra; CFRA= cfra;
scene_update_for_newframe(scene, ob->lay); // XXX is the layer flag too restrictive? scene_update_for_newframe(scene, scene->lay); // XXX this is the best way we can get anything moving
// TODO: make an API call for this too? /* clear recalc flags from targets */
ob->avs.recalc &= ~ANIMVIZ_RECALC_PATHS; for (mpt= targets->first; mpt; mpt= mpt->next) {
if (ob->pose) bAnimVizSettings *avs;
ob->pose->avs.recalc &= ~ANIMVIZ_RECALC_PATHS;
/* get pointer to animviz settings for each target */
/* free temp data */ if (mpt->pchan)
BLI_freelistN(&targets); avs= &mpt->ob->pose->avs;
else
avs= &mpt->ob->avs;
/* clear the flag requesting recalculation of targets */
avs->recalc &= ~ANIMVIZ_RECALC_PATHS;
}
} }
/* ******************************************************************** */ /* ******************************************************************** */

View File

@@ -730,6 +730,11 @@ static short animsys_write_rna_setting (PointerRNA *ptr, char *path, int array_i
/* set value - only for animatable numerical values */ /* set value - only for animatable numerical values */
if (RNA_property_animateable(&new_ptr, prop)) if (RNA_property_animateable(&new_ptr, prop))
{ {
/* convert to radians */
if (RNA_SUBTYPE_UNIT(RNA_property_subtype(prop)) == PROP_UNIT_ROTATION) {
value *= M_PI/180.0;
}
switch (RNA_property_type(prop)) switch (RNA_property_type(prop))
{ {
case PROP_BOOLEAN: case PROP_BOOLEAN:
@@ -1466,6 +1471,11 @@ void nladata_flush_channels (ListBase *channels)
int array_index= nec->index; int array_index= nec->index;
float value= nec->value; float value= nec->value;
/* convert to radians */
if (RNA_SUBTYPE_UNIT(RNA_property_subtype(prop)) == PROP_UNIT_ROTATION) {
value *= M_PI/180.0;
}
/* write values - see animsys_write_rna_setting() to sync the code */ /* write values - see animsys_write_rna_setting() to sync the code */
switch (RNA_property_type(prop)) switch (RNA_property_type(prop))
{ {

View File

@@ -1602,7 +1602,13 @@ void armature_rebuild_pose(Object *ob, bArmature *arm)
int counter=0; int counter=0;
/* only done here */ /* only done here */
if(ob->pose==NULL) ob->pose= MEM_callocN(sizeof(bPose), "new pose"); if(ob->pose==NULL) {
/* create new pose */
ob->pose= MEM_callocN(sizeof(bPose), "new pose");
/* set default settings for animviz */
animviz_settings_init(&ob->pose->avs);
}
pose= ob->pose; pose= ob->pose;
/* clear */ /* clear */
@@ -1627,8 +1633,10 @@ void armature_rebuild_pose(Object *ob, bArmature *arm)
// printf("rebuild pose %s, %d bones\n", ob->id.name, counter); // printf("rebuild pose %s, %d bones\n", ob->id.name, counter);
/* synchronize protected layers with proxy */ /* synchronize protected layers with proxy */
if(ob->proxy) if(ob->proxy) {
object_copy_proxy_drivers(ob, ob->proxy);
pose_proxy_synchronize(ob, ob->proxy, arm->layer_protected); pose_proxy_synchronize(ob, ob->proxy, arm->layer_protected);
}
update_pose_constraint_flags(ob->pose); // for IK detection for example update_pose_constraint_flags(ob->pose); // for IK detection for example

View File

@@ -103,76 +103,6 @@ short ENDIAN_ORDER;
char versionstr[48]= ""; char versionstr[48]= "";
/* ************************************************ */
/* pushpop facility: to store data temporally, FIFO! */
ListBase ppmain={0, 0};
typedef struct PushPop {
struct PushPop *next, *prev;
void *data;
int len;
} PushPop;
void pushdata(void *data, int len)
{
PushPop *pp;
pp= MEM_mallocN(sizeof(PushPop), "pushpop");
BLI_addtail(&ppmain, pp);
pp->data= MEM_mallocN(len, "pushpop");
pp->len= len;
memcpy(pp->data, data, len);
}
void popfirst(void *data)
{
PushPop *pp;
pp= ppmain.first;
if(pp) {
memcpy(data, pp->data, pp->len);
BLI_remlink(&ppmain, pp);
MEM_freeN(pp->data);
MEM_freeN(pp);
}
else printf("error in popfirst\n");
}
void poplast(void *data)
{
PushPop *pp;
pp= ppmain.last;
if(pp) {
memcpy(data, pp->data, pp->len);
BLI_remlink(&ppmain, pp);
MEM_freeN(pp->data);
MEM_freeN(pp);
}
else printf("error in poplast\n");
}
void free_pushpop()
{
PushPop *pp;
pp= ppmain.first;
while(pp) {
BLI_remlink(&ppmain, pp);
MEM_freeN(pp->data);
MEM_freeN(pp);
}
}
void pushpop_test()
{
if(ppmain.first) printf("pushpop not empty\n");
free_pushpop();
}
/* ********** free ********** */ /* ********** free ********** */
/* only to be called on exit blender */ /* only to be called on exit blender */

View File

@@ -77,6 +77,7 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val,
EffectedPoint epoint; EffectedPoint epoint;
ListBase *effectors = bbd->sim->psys->effectors; ListBase *effectors = bbd->sim->psys->effectors;
EffectorCache *cur, *eff = NULL; EffectorCache *cur, *eff = NULL;
EffectorCache temp_eff;
EffectorData efd, cur_efd; EffectorData efd, cur_efd;
float mul = (rule->type == eBoidRuleType_Avoid ? 1.0 : -1.0); float mul = (rule->type == eBoidRuleType_Avoid ? 1.0 : -1.0);
float priority = 0.0f, len = 0.0f; float priority = 0.0f, len = 0.0f;
@@ -91,7 +92,7 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val,
if(gabr->ob && (rule->type != eBoidRuleType_Goal || gabr->ob != bpa->ground)) { if(gabr->ob && (rule->type != eBoidRuleType_Goal || gabr->ob != bpa->ground)) {
if(gabr->ob == eob) { if(gabr->ob == eob) {
/* TODO: objects without any effector and effectors with multiple points */ /* TODO: effectors with multiple points */
if(get_effector_data(cur, &efd, &epoint, 0)) { if(get_effector_data(cur, &efd, &epoint, 0)) {
if(cur->pd && cur->pd->forcefield == PFIELD_BOID) if(cur->pd && cur->pd->forcefield == PFIELD_BOID)
priority = mul * pd->f_strength * effector_falloff(cur, &efd, &epoint, bbd->part->effector_weights); priority = mul * pd->f_strength * effector_falloff(cur, &efd, &epoint, bbd->part->effector_weights);
@@ -105,7 +106,7 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val,
} }
else if(rule->type == eBoidRuleType_Goal && eob == bpa->ground) else if(rule->type == eBoidRuleType_Goal && eob == bpa->ground)
; /* skip current object */ ; /* skip current object */
else if(pd->forcefield == PFIELD_BOID && mul * pd->f_strength > 0.0f && get_effector_data(eff, &efd, &epoint, 0)) { else if(pd->forcefield == PFIELD_BOID && mul * pd->f_strength > 0.0f && get_effector_data(cur, &cur_efd, &epoint, 0)) {
float temp = mul * pd->f_strength * effector_falloff(cur, &cur_efd, &epoint, bbd->part->effector_weights); float temp = mul * pd->f_strength * effector_falloff(cur, &cur_efd, &epoint, bbd->part->effector_weights);
if(temp == 0.0f) if(temp == 0.0f)
@@ -125,11 +126,21 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val,
} }
} }
/* if the object doesn't have effector data we have to fake it */
if(eff == NULL && gabr->ob) {
memset(&temp_eff, 0, sizeof(EffectorCache));
temp_eff.ob = gabr->ob;
temp_eff.scene = bbd->sim->scene;
eff = &temp_eff;
get_effector_data(eff, &efd, &epoint, 0);
priority = 1.0f;
}
/* then use that effector */ /* then use that effector */
if(priority > (rule->type==eBoidRuleType_Avoid ? gabr->fear_factor : 0.0f)) { /* with avoid, factor is "fear factor" */ if(priority > (rule->type==eBoidRuleType_Avoid ? gabr->fear_factor : 0.0f)) { /* with avoid, factor is "fear factor" */
Object *eob = eff->ob; Object *eob = eff->ob;
PartDeflect *pd = eob->pd; PartDeflect *pd = eff->pd;
float surface = pd->shape == PFIELD_SHAPE_SURFACE ? 1.0f : 0.0f; float surface = (pd && pd->shape == PFIELD_SHAPE_SURFACE) ? 1.0f : 0.0f;
if(gabr->options & BRULE_GOAL_AVOID_PREDICT) { if(gabr->options & BRULE_GOAL_AVOID_PREDICT) {
/* estimate future location of target */ /* estimate future location of target */
@@ -219,10 +230,19 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues *
} }
/* then avoid that object */ /* then avoid that object */
if(hit.index>=0) { if(hit.index>=0) {
/* TODO: not totally happy with this part */
t = hit.dist/col.ray_len; t = hit.dist/col.ray_len;
VECCOPY(bbd->wanted_co, col.nor); /* avoid head-on collision */
if(dot_v3v3(col.nor, pa->prev_state.ave) < -0.99) {
/* don't know why, but uneven range [0.0,1.0] */
/* works much better than even [-1.0,1.0] */
bbd->wanted_co[0] = BLI_frand();
bbd->wanted_co[1] = BLI_frand();
bbd->wanted_co[2] = BLI_frand();
}
else {
VECCOPY(bbd->wanted_co, col.nor);
}
mul_v3_fl(bbd->wanted_co, (1.0f - t) * val->personal_space * pa->size); mul_v3_fl(bbd->wanted_co, (1.0f - t) * val->personal_space * pa->size);

View File

@@ -89,6 +89,8 @@ Brush *add_brush(const char *name)
brush->flag |= BRUSH_SPACE; brush->flag |= BRUSH_SPACE;
brush_curve_preset(brush, CURVE_PRESET_SMOOTH); brush_curve_preset(brush, CURVE_PRESET_SMOOTH);
default_mtex(&brush->mtex);
/* enable fake user by default */ /* enable fake user by default */
brush->id.flag |= LIB_FAKEUSER; brush->id.flag |= LIB_FAKEUSER;

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