diff options
author | Daniel Genrich <daniel.genrich@gmx.net> | 2007-12-12 20:58:06 +0300 |
---|---|---|
committer | Daniel Genrich <daniel.genrich@gmx.net> | 2007-12-12 20:58:06 +0300 |
commit | cf59579d44a91a4027d40ed532022ffb31164373 (patch) | |
tree | 1504cb3764d7681fb6e92b7d007c7f8d04eb7eb4 | |
parent | 42637b725267192bfe22731bf975cfb1a50541ee (diff) | |
parent | de17fd9ee5431788e7e55daeb8e5ad6fb07894dc (diff) |
svn merge -r 12716:12856 https://svn.blender.org/svnroot/bf-blender/trunk/blender
184 files changed, 10255 insertions, 2583 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index eabcdde1dde..d79c2220104 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -# $Id$ +# $Id: CMakeLists.txt 12480 2007-11-05 16:46:48Z sirdude $ # ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** # # This program is free software; you can redistribute it and/or @@ -65,9 +65,8 @@ OPTION(WITH_ELBEEM "Enable Elbeem (Fluid Simulation)" ON) OPTION(WITH_QUICKTIME "Enable Quicktime Support" OFF) OPTION(WITH_OPENEXR "Enable OpenEXR Support (http://www.openexr.com)" OFF) OPTION(WITH_FFMPEG "Enable FFMPeg Support (http://ffmpeg.mplayerhq.hu/)" OFF) -OPTION(WITH_OPENAL "Enable OpenAL Support (http://www.openal.org)" ON) -OPTION(YESIAMSTUPID "Enable execution on 64-bit platforms" OFF) -OPTION(WITH_OPENMP "Enable OpenMP (has to be supported by the compiler)" OFF) +OPTION(WITH_OPENAL "Enable OpenAL Support (http://www.openal.org)" ON) +OPTION(YESIAMSTUPID "Enable execution on 64-bit platforms" OFF) IF(NOT WITH_GAMEENGINE AND WITH_PLAYER) MESSAGE("WARNING: WITH_PLAYER needs WITH_GAMEENGINE") @@ -187,12 +186,6 @@ IF(UNIX) SET(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing -DXP_UNIX -Wno-char-subscripts") - IF(WITH_OPENMP) - SET(LLIBS ${LLIBS} gomp) - SET(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} "-fopenmp") - SET(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-fopenmp") - ENDIF(WITH_OPENMP) - SET(PLATFORM_LINKFLAGS "-pthread") INCLUDE_DIRECTORIES(/usr/include /usr/local/include) @@ -277,11 +270,6 @@ IF(WIN32) SET(CMAKE_C_FLAGS_MINSIZEREL "/D_CRT_NONSTDC_NO_DEPRECATE /D_CRT_SECURE_NO_DEPRECATE /D_SCL_SECURE_NO_DEPRECATE /wd4800 /wd4244 /wd4305 /O1 /Ob1 /DNDEBUG /EHsc /MT /W3 /nologo /J" CACHE STRING "MSVC MT flags " FORCE) SET(CMAKE_C_FLAGS_RELWITHDEBINFO "/D_CRT_NONSTDC_NO_DEPRECATE /D_CRT_SECURE_NO_DEPRECATE /D_SCL_SECURE_NO_DEPRECATE /wd4800 /wd4244 /wd4305 /O2 /Ob1 /DNDEBUG /EHsc /MT /W3 /nologo /Zi /J" CACHE STRING "MSVC MT flags " FORCE) - IF(WITH_OPENMP) - SET(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} "/openmp") - SET(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "/openmp") - ENDIF(WITH_OPENMP) - SET(SDL ${LIBDIR}/sdl) SET(SDL_INC ${SDL}/include) SET(SDL_LIB SDL) @@ -359,12 +347,6 @@ IF(APPLE) SET(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing") SET(PLATFORM_LINKFLAGS "-fexceptions -framework CoreServices -framework Foundation -framework IOKit -framework AppKit -framework Carbon -framework AGL -framework AudioUnit -framework AudioToolbox -framework CoreAudio -framework QuickTime") - IF(WITH_OPENMP) - SET(LLIBS ${LLIBS} gomp) - SET(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} "-fopenmp") - SET(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-fopenmp") - ENDIF(WITH_OPENMP) - SET(SDL ${LIBDIR}/sdl) SET(SDL_INC ${SDL}/include) SET(SDL_LIB SDL) diff --git a/extern/bFTGL/include/FTGL.h b/extern/bFTGL/include/FTGL.h index e92bd526012..2b76de8b8bd 100644 --- a/extern/bFTGL/include/FTGL.h +++ b/extern/bFTGL/include/FTGL.h @@ -42,7 +42,11 @@ typedef float FTGL_FLOAT; #include <OpenGL/glu.h> #else #include <GL/gl.h> - #include <GL/glu.h> + #if defined (__sun__) && !defined (__sparc__) + #include <mesa/glu.h> + #else + #include <GL/glu.h> + #endif #endif #endif diff --git a/extern/bFTGL/src/Makefile b/extern/bFTGL/src/Makefile index 064480fbd16..3ebf9bee45c 100644 --- a/extern/bFTGL/src/Makefile +++ b/extern/bFTGL/src/Makefile @@ -46,7 +46,8 @@ CCSRCS = FTBitmapGlyph.cpp FTCharmap.cpp FTContour.cpp FTExtrdGlyph.cpp \ include nan_compile.mk CPPFLAGS += -I../include -CPPFLAGS += -I$(NAN_FREETYPE)/include -I$(NAN_FREETYPE)/include/freetype2 +CPPFLAGS += -I$(NAN_FREETYPE)/include -I$(NAN_FREETYPE)/include/freetype2 +CPPFLAGS += -I$(OPENGL_HEADERS) install: all debug @[ -d $(NAN_FTGL) ] || mkdir -p $(NAN_FTGL) diff --git a/intern/elbeem/intern/isosurface.cpp b/intern/elbeem/intern/isosurface.cpp index 704f3fdacfe..14aa22d06b5 100644 --- a/intern/elbeem/intern/isosurface.cpp +++ b/intern/elbeem/intern/isosurface.cpp @@ -13,6 +13,11 @@ #include <algorithm> #include <stdio.h> +#if !defined(linux) && (defined (__sparc) || defined (__sparc__)) +#include <ieeefp.h> +#endif + + // just use default rounding for platforms where its not available #ifndef round #define round(x) (x) diff --git a/intern/elbeem/intern/solver_adap.cpp b/intern/elbeem/intern/solver_adap.cpp index ef516a578bd..b56b1c14f2c 100644 --- a/intern/elbeem/intern/solver_adap.cpp +++ b/intern/elbeem/intern/solver_adap.cpp @@ -11,6 +11,9 @@ #include "solver_relax.h" #include "particletracer.h" +#if !defined(linux) && (defined (__sparc) || defined (__sparc__)) +#include <ieeefp.h> +#endif /*****************************************************************************/ diff --git a/intern/elbeem/intern/solver_main.cpp b/intern/elbeem/intern/solver_main.cpp index 0f788af7955..3d629d673f1 100644 --- a/intern/elbeem/intern/solver_main.cpp +++ b/intern/elbeem/intern/solver_main.cpp @@ -13,6 +13,11 @@ #include "loop_tools.h" #include <stdlib.h> +#if !defined(linux) && (defined (__sparc) || defined (__sparc__)) +#include <ieeefp.h> +#endif + + /*****************************************************************************/ /*! perform a single LBM step */ /*****************************************************************************/ diff --git a/intern/iksolver/intern/IK_QSegment.cpp b/intern/iksolver/intern/IK_QSegment.cpp index a5217ed91d6..bf38c369363 100644 --- a/intern/iksolver/intern/IK_QSegment.cpp +++ b/intern/iksolver/intern/IK_QSegment.cpp @@ -61,11 +61,11 @@ static MT_Scalar EulerAngleFromMatrix(const MT_Matrix3x3& R, int axis) MT_Scalar t = sqrt(R[0][0]*R[0][0] + R[0][1]*R[0][1]); if (t > 16.0*MT_EPSILON) { - if (axis == 0) return atan2(R[1][2], R[2][2]); + if (axis == 0) return -atan2(R[1][2], R[2][2]); else if(axis == 1) return atan2(-R[0][2], t); - else return atan2(R[0][1], R[0][0]); + else return -atan2(R[0][1], R[0][0]); } else { - if (axis == 0) return atan2(-R[2][1], R[1][1]); + if (axis == 0) return -atan2(-R[2][1], R[1][1]); else if(axis == 1) return atan2(-R[0][2], t); else return 0.0f; } diff --git a/intern/opennl/intern/opennl.c b/intern/opennl/intern/opennl.c index 2d30da075d3..d779e861cb6 100644 --- a/intern/opennl/intern/opennl.c +++ b/intern/opennl/intern/opennl.c @@ -240,7 +240,7 @@ static void __nlSparseMatrixConstruct( M->storage = storage; if(storage & __NL_ROWS) { M->row = __NL_NEW_ARRAY(__NLRowColumn, m); - for(i=0; i<n; i++) { + for(i=0; i<m; i++) { __nlRowColumnConstruct(&(M->row[i])); } } else { diff --git a/po/Makefile b/po/Makefile index b7288c0e64c..35be6dd2a15 100644 --- a/po/Makefile +++ b/po/Makefile @@ -36,7 +36,7 @@ SOURCEDIR = blender/po include nan_definitions.mk -ifeq ($(INTERNTIONAL),true) +ifeq ($(INTERNATIONAL),true) LINGUAS = ar bg ca cs de es fr hr it ja nl pl pt_BR ro ru sr sr@Latn sv uk zh_CN else LINGUAS = diff --git a/projectfiles_vc7/blender/blender.sln b/projectfiles_vc7/blender/blender.sln index 0888cf7971a..60c2d8f2d4c 100644 --- a/projectfiles_vc7/blender/blender.sln +++ b/projectfiles_vc7/blender/blender.sln @@ -248,8 +248,6 @@ Global Debug = Debug Release = Release EndGlobalSection - GlobalSection(ProjectDependencies) = postSolution - EndGlobalSection GlobalSection(ProjectConfiguration) = postSolution {F78B7FC9-DE32-465E-9F26-BB0B6B7A2EAF}.3D Plugin Debug.ActiveCfg = Blender Debug|Win32 {F78B7FC9-DE32-465E-9F26-BB0B6B7A2EAF}.3D Plugin Release.ActiveCfg = Blender Release|Win32 diff --git a/projectfiles_vc7/blender/render/BRE_render.vcproj b/projectfiles_vc7/blender/render/BRE_render.vcproj index 2383f41b69b..021d8c2c82a 100644 --- a/projectfiles_vc7/blender/render/BRE_render.vcproj +++ b/projectfiles_vc7/blender/render/BRE_render.vcproj @@ -170,6 +170,9 @@ RelativePath="..\..\..\source\blender\render\intern\source\sss.c"> </File> <File + RelativePath="..\..\..\source\blender\render\intern\source\strand.c"> + </File> + <File RelativePath="..\..\..\source\blender\render\intern\source\texture.c"> </File> <File @@ -234,6 +237,9 @@ RelativePath="..\..\..\source\blender\render\intern\include\sss.h"> </File> <File + RelativePath="..\..\..\source\blender\render\intern\include\strand.h"> + </File> + <File RelativePath="..\..\..\source\blender\render\intern\include\texture.h"> </File> <File diff --git a/projectfiles_vc7/blender/src/BL_src.vcproj b/projectfiles_vc7/blender/src/BL_src.vcproj index 6cc8f27f398..9c03b21f1a8 100644 --- a/projectfiles_vc7/blender/src/BL_src.vcproj +++ b/projectfiles_vc7/blender/src/BL_src.vcproj @@ -476,6 +476,9 @@ RelativePath="..\..\..\source\blender\src\prvicons.c"> </File> <File + RelativePath="..\..\..\source\blender\src\reeb.c"> + </File> + <File RelativePath="..\..\..\source\blender\src\renderwin.c"> </File> <File @@ -888,6 +891,9 @@ RelativePath="..\..\..\source\blender\include\playanim_ext.h"> </File> <File + RelativePath="..\..\..\source\blender\include\reeb.h"> + </File> + <File RelativePath="..\..\..\source\blender\include\transform.h"> </File> <File diff --git a/release/Makefile b/release/Makefile index c55e62be003..f608accf2b0 100644 --- a/release/Makefile +++ b/release/Makefile @@ -44,7 +44,7 @@ ifeq ($(OS),beos) EXT1=".zip" COMPRESS="" EXT2="" - NOPLUGINS="true" + NOPLUGINS?=true endif ifeq ($(OS),$(findstring $(OS), "freebsd irix linux openbsd solaris")) @@ -55,6 +55,11 @@ ifeq ($(OS),$(findstring $(OS), "freebsd irix linux openbsd solaris")) COMPRESS="bzip2" COMPRESSFLAGS="-f" EXT2=".bz2" + ifeq ($(OS), solaris) + ifeq ($(CPU), i386) + NOPLUGINS?=true + endif + endif endif ifeq ($(OS),windows) @@ -62,8 +67,8 @@ ifeq ($(OS),windows) TARFLAGS="-r9" EXT0=".exe" EXT1=".zip" - NOPLUGINS="true" - NOSTRIP="true" + NOPLUGINS?=true + NOSTRIP?=true endif ifeq ($(OS),darwin) diff --git a/release/scripts/mesh_edges2curves.py b/release/scripts/mesh_edges2curves.py index 84f3cc41779..f65eccae9a4 100644 --- a/release/scripts/mesh_edges2curves.py +++ b/release/scripts/mesh_edges2curves.py @@ -12,7 +12,7 @@ __version__ = "1.0 2006/02/08" __bpydoc__ = """\ Edges to Curves -This script converts open and closed edge loops into polylines +This script converts open and closed edge loops into curve polylines Supported:<br> Polylines where each vert has no more then 2 edges attached to it. @@ -129,6 +129,7 @@ def mesh2polys(): v= poly[vIdx] cu.appendNurb([v.co.x, v.co.y, v.co.z, w, t]) + vIdx += 1 cu[i].type= 0 # Poly Line # Close the polyline if its closed. diff --git a/release/scripts/ply_export.py b/release/scripts/ply_export.py index 010ee72ec67..cecde5a0b59 100644 --- a/release/scripts/ply_export.py +++ b/release/scripts/ply_export.py @@ -7,6 +7,7 @@ Group: 'Export' Tooltip: 'Export active object to Stanford PLY format' """ +import bpy import Blender from Blender import Mesh, Scene, Window, sys, Image, Draw import BPyMesh @@ -64,7 +65,7 @@ def file_callback(filename): if not filename.lower().endswith('.ply'): filename += '.ply' - scn= Blender.Scene.GetCurrent() + scn= bpy.data.scenes.active ob= scn.objects.active if not ob: Blender.Draw.PupMenu('Error%t|Select 1 active object') @@ -89,6 +90,10 @@ def file_callback(filename): if not Draw.PupBlock('Export...', pup_block): return + is_editmode = Blender.Window.EditMode() + if is_editmode: + Blender.Window.EditMode(0, '', 0) + Window.WaitCursor(1) EXPORT_APPLY_MODIFIERS = EXPORT_APPLY_MODIFIERS.val @@ -132,7 +137,7 @@ def file_callback(filename): if vertexColors: col = f.col for j, v in enumerate(f): if smooth: - normal= v.no + normal= tuple(v.no) normal_key = rvec3d(normal) if faceUV: @@ -211,12 +216,12 @@ def file_callback(filename): file.write('\n') file.close() - - + + if is_editmode: + Blender.Window.EditMode(1, '', 0) def main(): Blender.Window.FileSelector(file_callback, 'PLY Export', Blender.sys.makename(ext='.ply')) - if __name__=='__main__': main() diff --git a/source/Makefile b/source/Makefile index 2b3ba06e90e..0a7ef2102ca 100644 --- a/source/Makefile +++ b/source/Makefile @@ -61,7 +61,6 @@ endif ############# set pyplayerlib ################## -PYPLAYERLIB ?= $(PYLIB) ############# libraries ################## # COMLIB COMmon LIBraries for all targets @@ -177,51 +176,22 @@ ifeq ($(WITH_DDS), true) endif ifeq ($(WITH_FREETYPE2), true) + COMLIB += $(OCGDIR)/blender/ftfont/$(DEBUG_DIR)libftfont.a ifeq ($(OS), windows) ifeq ($(FREE_WINDOWS), true) + COMLIB += $(NAN_FTGL)/lib/libftgl.a COMLIB += $(NAN_FREETYPE)/lib/libfreetype.a else + COMLIB += $(NAN_FTGL)/lib/ftgl_static_ST.lib COMLIB += $(NAN_FREETYPE)/lib/freetype2ST.lib endif else + COMLIB += $(NAN_FTGL)/lib/libftgl.a ifeq ($(OS), irix) COMLIB += $(NAN_FREETYPE)/lib32/libfreetype.a - else - COMLIB += $(NAN_FREETYPE)/lib/libfreetype.a - endif - endif -endif - -ifeq ($(INTERNATIONAL), true) - COMLIB += $(OCGDIR)/blender/ftfont/$(DEBUG_DIR)libftfont.a - ifeq ($(OS), windows) - ifeq ($(FREE_WINDOWS), true) - COMLIB += $(NAN_GETTEXT)/lib/freegettext.a - COMLIB += $(NAN_FTGL)/lib/libftgl.a - #COMLIB += $(NAN_ICONV)/lib/freeiconv.a - else - COMLIB += $(NAN_GETTEXT)/lib/gnu_gettext.lib - COMLIB += $(NAN_FTGL)/lib/ftgl_static_ST.lib - COMLIB += $(NAN_FREETYPE)/lib/freetype2ST.lib - COMLIB += $(NAN_ICONV)/lib/iconv.lib - endif - else - COMLIB += $(NAN_FTGL)/lib/libftgl.a - ifeq ($(OS), irix) - COMLIB += $(NAN_FREETYPE)/lib32/libfreetype.a - COMLIB += $(NAN_FREETYPE)/lib32/libintl.a else - COMLIB += $(NAN_FREETYPE)/lib/libfreetype.a - endif - endif - ifeq ($(OS), darwin) - COMLIB += $(NAN_GETTEXT)/lib/libintl.a - ifeq ($(CPU), i386) - COMLIB += $(NAN_GETTEXT)/lib/libiconv.a - endif - endif - ifeq ($(OS), solaris) - COMLIB += $(NAN_GETTEXT)/lib/libintl.a + COMLIB += $(NAN_FREETYPE)/lib/libfreetype.a + endif endif endif @@ -354,14 +324,7 @@ ifeq ($(WITH_BF_WEBPLUGIN), true) endif endif -ifdef PY_FRAMEWORK - PYLIB = -framework Python -else - PYLIB = $(NAN_PYTHON)/lib/python$(NAN_PYTHON_VERSION)/config/libpython$(NAN_PYTHON_VERSION).a -endif - ifeq ($(OS),solaris) - PYLIB += $(NAN_ZLIB)/lib/libz.a PULIB += $(NAN_ZLIB)/lib/libz.a SPLIB += $(NAN_ZLIB)/lib/libz.a endif @@ -436,14 +399,6 @@ else endif ifeq ($(OS),windows) - ifeq ($(FREE_WINDOWS),true) - PYLIB = $(NAN_PYTHON)/lib/freepy.a - else - PYLIB = $(NAN_PYTHON)/lib/python23.lib - endif - - PYPLAYERLIB = $(NAN_PYTHON)/static/*.obj - PYPLAYERLIB = $(PYLIB) # Might need to change this to $(NAN_MOZILLA_LIB)/nspr4.lib NSPLUGLIB += $(NAN_NSPR)/lib/nspr4.lib @@ -550,7 +505,7 @@ ifdef NAN_BUILDINFO $(CCC) $(REL_CFLAGS) -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_TIME='"$(BUILD_TIME)"' -DBUILD_REV='"$(BUILD_REV)"' -DBUILD_PLATFORM='"$(CONFIG_GUESS)"' -DBUILD_TYPE='"static"' $(BUILDINFO_C) -c -o $(BUILDINFO_O) -DNAN_BUILDINFO endif mkdir -p $(DIR)/$(DEBUG_DIR)bin - $(CCC) $(LDFLAGS) -o $(DIR)/$(DEBUG_DIR)bin/blenderstatic $(BUILDINFO_O) $(OBJS) $(GRPLIB) $(COMLIB) $(PULIB) $(PYLIB) $(LLIBS) $(SADD) $(LOPTS) + $(CCC) $(LDFLAGS) -o $(DIR)/$(DEBUG_DIR)bin/blenderstatic $(BUILDINFO_O) $(OBJS) $(GRPLIB) $(COMLIB) $(PULIB) $(LLIBS) $(SADD) $(LOPTS) ifdef NAN_BUILDINFO /bin/rm $(BUILDINFO_O) endif @@ -564,7 +519,7 @@ ifdef NAN_BUILDINFO $(CCC) $(REL_CFLAGS) -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_TIME='"$(BUILD_TIME)"' -DBUILD_REV='"$(BUILD_REV)"' -DBUILD_PLATFORM='"$(CONFIG_GUESS)"' -DBUILD_TYPE='"dynamic"' $(BUILDINFO_C) -c -o $(BUILDINFO_O) -DNAN_BUILDINFO endif mkdir -p $(DIR)/$(DEBUG_DIR)bin - $(CCC) $(LDFLAGS) -o $(DIR)/$(DEBUG_DIR)bin/blender$(EXT) $(BUILDINFO_O) $(OBJS) $(GRPLIB) $(COMLIB) $(PULIB) $(PYLIB) $(LLIBS) $(DADD) $(LOPTS) + $(CCC) $(LDFLAGS) -o $(DIR)/$(DEBUG_DIR)bin/blender$(EXT) $(BUILDINFO_O) $(OBJS) $(GRPLIB) $(COMLIB) $(PULIB) $(LLIBS) $(DADD) $(LOPTS) ifdef NAN_BUILDINFO /bin/rm $(BUILDINFO_O) endif @@ -578,7 +533,7 @@ ifdef NAN_BUILDINFO $(CCC) $(REL_CFLAGS) -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_TIME='"$(BUILD_TIME)"' -DBUILD_REV='"$(BUILD_REV)"' -DBUILD_PLATFORM='"$(CONFIG_GUESS)"' -DBUILD_TYPE='"dynamic"' $(BUILDINFO_C) -c -o $(BUILDINFO_O) -DNAN_BUILDINFO endif mkdir -p $(DIR)/$(DEBUG_DIR)bin - $(CCC) $(LDFLAGS) -o $(DIR)/$(DEBUG_DIR)bin/blenderplayer$(EXT) $(BUILDINFO_O) $(OBJS) $(SPLIB1) $(COMLIB) $(SPLIB) $(PYPLAYERLIB) $(LLIBS) $(DADD) $(LOPTS) + $(CCC) $(LDFLAGS) -o $(DIR)/$(DEBUG_DIR)bin/blenderplayer$(EXT) $(BUILDINFO_O) $(OBJS) $(SPLIB1) $(COMLIB) $(SPLIB) $(LLIBS) $(DADD) $(LOPTS) ifdef NAN_BUILDINFO /bin/rm $(BUILDINFO_O) endif @@ -592,7 +547,7 @@ ifdef NAN_BUILDINFO $(CCC) $(REL_CFLAGS) -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_TIME='"$(BUILD_TIME)"' -DBUILD_REV='"$(BUILD_REV)"' -DBUILD_PLATFORM='"$(CONFIG_GUESS)"' -DBUILD_TYPE='"dynamic"' $(BUILDINFO_C) -c -o $(BUILDINFO_O) -DNAN_BUILDINFO endif mkdir -p $(DIR)/$(DEBUG_DIR)bin - $(CCC) $(LDFLAGS) -o $(DIR)/$(DEBUG_DIR)bin/blenderdynplayer$(EXT) $(BUILDINFO_O) $(OBJS) $(SPLIB1) $(COMLIB) $(SPLIB) $(PYLIB) $(LLIBS) $(DADD) $(LOPTS) + $(CCC) $(LDFLAGS) -o $(DIR)/$(DEBUG_DIR)bin/blenderdynplayer$(EXT) $(BUILDINFO_O) $(OBJS) $(SPLIB1) $(COMLIB) $(SPLIB) $(LLIBS) $(DADD) $(LOPTS) ifdef NAN_BUILDINFO /bin/rm $(BUILDINFO_O) endif @@ -621,8 +576,8 @@ $(DIR)/$(DEBUG_DIR)npB3DPlg$(SOEXT): $(NSPLUGLIB) $(PLUGAPPLIB) $(COMLIB) $(SPLI ifdef NAN_BUILDINFO $(CCC) $(REL_CFLAGS) -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_TIME='"$(BUILD_TIME)"' -DBUILD_REV='"$(BUILD_REV)"' -DBUILD_PLATFORM='"$(CONFIG_GUESS)"' -DBUILD_TYPE='"dynamic"' $(BUILDINFO_C) -c -o $(BUILDINFO_O) -DNAN_BUILDINFO endif -# $(CCC) $(DYNLDFLAGS) -o $@ $(NSPLUGLIB) $(PLUGAPPLIB) $(COMLIB) $(SPLIB) $(PYLIB) $(PLUGREMLIB) $(LLIBS) $(DADD) $(LOPTS) - $(CCC) $(DYNLDFLAGS) -o $@ $(NSPLUGLIB) $(PLUGAPPLIB) $(COMLIB) $(SPLIB) $(PYLIB) $(PLUGREMLIB) $(LLIBS) $(DADD) $(LOPTS) /def:$(DEFFILE) +# $(CCC) $(DYNLDFLAGS) -o $@ $(NSPLUGLIB) $(PLUGAPPLIB) $(COMLIB) $(SPLIB) $(PLUGREMLIB) $(LLIBS) $(DADD) $(LOPTS) + $(CCC) $(DYNLDFLAGS) -o $@ $(NSPLUGLIB) $(PLUGAPPLIB) $(COMLIB) $(SPLIB) $(PLUGREMLIB) $(LLIBS) $(DADD) $(LOPTS) /def:$(DEFFILE) ifdef NAN_BUILDINFO /bin/rm $(BUILDINFO_O) endif @@ -633,7 +588,7 @@ ifdef NAN_BUILDINFO $(CCC) $(REL_CFLAGS) -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_TIME='"$(BUILD_TIME)"' -DBUILD_REV='"$(BUILD_REV)"' -DBUILD_PLATFORM='"$(CONFIG_GUESS)"' -DBUILD_TYPE='"dynamic"' $(BUILDINFO_C) -c -o $(BUILDINFO_O) -DNAN_BUILDINFO endif mkdir -p $(DIR)/$(DEBUG_DIR)bin - $(CCC) $(DYNLDFLAGS) -o $@ $(NSPLUGLIB) $(PLUGAPPLIB) $(COMLIB) $(SPLIB) $(PYLIB) $(PLUGREMLIB) $(LLIBS) $(DADD) $(LOPTS) + $(CCC) $(DYNLDFLAGS) -o $@ $(NSPLUGLIB) $(PLUGAPPLIB) $(COMLIB) $(SPLIB) $(PLUGREMLIB) $(LLIBS) $(DADD) $(LOPTS) ifdef NAN_BUILDINFO /bin/rm $(BUILDINFO_O) endif diff --git a/source/blender/Makefile b/source/blender/Makefile index c0001495210..2c1f83edf39 100644 --- a/source/blender/Makefile +++ b/source/blender/Makefile @@ -38,7 +38,7 @@ DIRS += avi imbuf render radiosity blenlib blenkernel blenpluginapi DIRS += makesdna src yafray DIRS += python nodes -ifeq ($(INTERNATIONAL), true) +ifeq ($(WITH_FREETYPE2), true) DIRS += ftfont endif diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 075405b1097..243425db139 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -44,7 +44,7 @@ struct ListBase; struct MemFile; #define BLENDER_VERSION 245 -#define BLENDER_SUBVERSION 9 +#define BLENDER_SUBVERSION 12 #define BLENDER_MINVERSION 240 #define BLENDER_MINSUBVERSION 0 diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index a8e4969ad43..be0a04ba563 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -62,8 +62,8 @@ void make_local_tface(struct Mesh *me); void make_local_mesh(struct Mesh *me); void boundbox_mesh(struct Mesh *me, float *loc, float *size); void tex_space_mesh(struct Mesh *me); -float *mesh_create_orco_render(struct Object *ob); -float *mesh_create_orco(struct Object *ob); +float *get_mesh_orco_verts(struct Object *ob); +void transform_mesh_orco_verts(struct Mesh *me, float (*orco)[3], int totvert, int invert); void test_index_face(struct MFace *mface, struct CustomData *mfdata, int mfindex, int nr); struct Mesh *get_mesh(struct Object *ob); void set_mesh(struct Object *ob, struct Mesh *me); @@ -75,7 +75,7 @@ int update_realtime_texture(struct MTFace *tface, double time); void mesh_delete_material_index(struct Mesh *me, int index); void mesh_set_smooth_flag(struct Object *meshOb, int enableSmooth); -struct BoundBox *mesh_get_bb(struct Mesh *me); +struct BoundBox *mesh_get_bb(struct Object *ob); void mesh_get_texspace(struct Mesh *me, float *loc_r, float *rot_r, float *size_r); /* if old, it converts mface->edcode to edge drawflags */ diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 48e083bbf9b..1a0b83e45c5 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -85,6 +85,10 @@ typedef enum { * be placed after any non-deformative modifier. */ eModifierTypeFlag_RequiresOriginalData = (1<<5), + + /* For modifiers that support pointcache, so we can check to see if it has files we need to deal with + */ + eModifierTypeFlag_UsesPointCache = (1<<6), } ModifierTypeFlag; typedef void (*ObjectWalkFunc)(void *userData, struct Object *ob, struct Object **obpoin); diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index afed219dbc6..c45989a6b5b 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -54,6 +54,7 @@ struct MVert; struct IpoCurve; struct LinkNode; struct KDTree; +struct RNG; typedef struct ParticleEffectorCache { struct ParticleEffectorCache *next, *prev; @@ -86,10 +87,10 @@ typedef struct ParticleReactEvent { }ParticleReactEvent; typedef struct ParticleTexture{ - float ivel; /* used in reset */ - float time, life, exist, size; /* used in init */ - float pvel[3]; /* used in physics */ - float length, clump, kink; /* used in path caching */ + float ivel; /* used in reset */ + float time, life, exist, size; /* used in init */ + float pvel[3]; /* used in physics */ + float length, clump, kink, rough; /* used in path caching */ } ParticleTexture; typedef struct BoidVecFunc{ @@ -148,6 +149,42 @@ typedef struct ParticleEdit{ int totkeys; } ParticleEdit; +typedef struct ParticleThreadContext { + /* shared */ + struct Object *ob; + struct DerivedMesh *dm; + struct ParticleSystemModifierData *psmd; + struct ParticleSystem *psys; + struct Material *ma; + + /* distribution */ + struct KDTree *tree; + + struct ParticleSeam *seams; + int totseam; + + float *jit, *jitoff, *weight; + float maxweight; + int *index, jitlevel; + + int from, cfrom, distr; + + /* path caching */ + int editupdate, between, steps; + int totchild, totparent; + + float cfra; + + float *vg_length, *vg_clump, *vg_kink; + float *vg_rough1, *vg_rough2, *vg_roughe; +} ParticleThreadContext; + +typedef struct ParticleThread { + ParticleThreadContext *ctx; + struct RNG *rng, *rng_path; + int num, tot; +} ParticleThread; + /* ----------- functions needed outside particlesystem ---------------- */ /* particle.c */ int count_particles(struct ParticleSystem *psys); @@ -170,6 +207,7 @@ int psys_in_edit_mode(struct ParticleSystem *psys); void psys_free_settings(struct ParticleSettings *part); void free_child_path_cache(struct ParticleSystem *psys); void psys_free_path_cache(struct ParticleSystem *psys); +void psys_free_render_memory(struct Object *ob, struct ParticleSystem *psys); void free_hair(struct ParticleSystem *psys); void free_keyed_keys(struct ParticleSystem *psys); void psys_free(struct Object * ob, struct ParticleSystem * psys); @@ -181,7 +219,7 @@ void psys_interpolate_uvs(struct MTFace *tface, int quad, float *uv, float *uvco void copy_particle_key(struct ParticleKey *to, struct ParticleKey *from, int time); -void psys_particle_on_emitter(struct Object *ob, struct ParticleSystemModifierData *psmd, int distr, int index, int index_dmcache, float *fuv, float foffset, float *vec, float *nor, float *utan, float *vtan); +void psys_particle_on_emitter(struct Object *ob, struct ParticleSystemModifierData *psmd, int distr, int index, int index_dmcache, float *fuv, float foffset, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor); struct ParticleSystemModifierData *psys_get_modifier(struct Object *ob, struct ParticleSystem *psys); struct ParticleSettings *psys_new_settings(char *name, struct Main *main); @@ -195,11 +233,19 @@ void psys_cache_child_paths(struct Object *ob, struct ParticleSystem *psys, floa int do_guide(struct ParticleKey *state, int pa_num, float time, struct ListBase *lb); float psys_get_size(struct Object *ob, struct Material *ma, struct ParticleSystemModifierData *psmd, struct IpoCurve *icu_size, struct ParticleSystem *psys, struct ParticleSettings *part, struct ParticleData *pa, float *vg_size); float psys_get_timestep(struct ParticleSettings *part); -float psys_get_child_time(struct ParticleSystem *psys, int child_nbr, float cfra); -float psys_get_child_size(struct ParticleSystem *psys, int child_nbr, float cfra, float *pa_time); +float psys_get_child_time(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra); +float psys_get_child_size(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra, float *pa_time); void psys_get_particle_on_path(struct Object *ob, struct ParticleSystem *psys, int pa_num, struct ParticleKey *state, int vel); int psys_get_particle_state(struct Object *ob, struct ParticleSystem *psys, int p, struct ParticleKey *state, int always); +ParticleThread *psys_threads_create(struct Object *ob, struct ParticleSystem *psys, int totthread); +int psys_threads_init_distribution(ParticleThread *threads, struct DerivedMesh *dm, int from); +int psys_threads_init_path(ParticleThread *threads, float cfra, int editupdate); +void psys_threads_free(ParticleThread *threads); + +void psys_thread_distribute_particle(ParticleThread *thread, struct ParticleData *pa, struct ChildParticle *cpa, int p); +void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, ParticleCacheKey *keys, int i); + /* particle_system.c */ int psys_count_keyed_targets(struct Object *ob, struct ParticleSystem *psys); void psys_get_reactor_target(struct Object *ob, struct ParticleSystem *psys, struct Object **target_ob, struct ParticleSystem **target_psys); @@ -219,15 +265,16 @@ void psys_vec_rot_to_face(struct DerivedMesh *dm, struct ParticleData *pa, float //void psys_vec_rot_from_face(struct DerivedMesh *dm, struct ParticleData *pa, float *vec); void psys_mat_hair_to_object(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[][4]); void psys_mat_hair_to_global(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[][4]); +void psys_mat_hair_to_orco(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[][4]); float *psys_cache_vgroup(struct DerivedMesh *dm, struct ParticleSystem *psys, int vgroup); void psys_get_texture(struct Object *ob, struct Material *ma, struct ParticleSystemModifierData *psmd, struct ParticleSystem *psys, struct ParticleData *pa, struct ParticleTexture *ptex, int event); -void psys_interpolate_face(struct MVert *mvert, struct MFace *mface, struct MTFace *tface, float *uv, float *vec, float *nor, float *utan, float *vtan); +void psys_interpolate_face(struct MVert *mvert, struct MFace *mface, struct MTFace *tface, float (*orcodata)[3], float *uv, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor); float psys_interpolate_value_from_verts(struct DerivedMesh *dm, short from, int index, float *fw, float *values); void psys_get_from_key(struct ParticleKey *key, float *loc, float *vel, float *rot, float *time); int psys_intersect_dm(struct Object *ob, struct DerivedMesh *dm, float *vert_cos, float *co1, float* co2, float *min_d, int *min_face, float *min_uv, float *face_minmax, float *pa_minmax, float radius, float *ipoint); -void psys_particle_on_dm(struct Object *ob, struct DerivedMesh *dm, int from, int index, int index_dmcache, float *fw, float foffset, float *vec, float *nor, float *utan, float *vtan); +void psys_particle_on_dm(struct Object *ob, struct DerivedMesh *dm, int from, int index, int index_dmcache, float *fw, float foffset, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor); /* particle_system.c */ void initialize_particle(struct ParticleData *pa, int p, struct Object *ob, struct ParticleSystem *psys, struct ParticleSystemModifierData *psmd); diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index afaf9dbeee2..52cc0ddcaa7 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -38,10 +38,16 @@ #define PTCACHE_CLEAR_BEFORE 2 #define PTCACHE_CLEAR_AFTER 3 +/* Add the blendfile name after blendcache_ */ #define PTCACHE_EXT ".bphys" -#define PTCACHE_PATH "//pointcache/" +#define PTCACHE_PATH "//blendcache_" -int BKE_ptcache_id_filename(struct ID *id, char *filename, int cfra, int stack_index, short do_path, short do_ext); +/* Global funcs */ +/* void BKE_ptcache_clean(void); - not implimented yet! */ + + +/* Object spesific funcs */ +int BKE_ptcache_id_filename(struct ID *id, char *filename, int cfra, int stack_index, short do_path, short do_ext); FILE * BKE_ptcache_id_fopen(struct ID *id, char mode, int cfra, int stack_index); void BKE_ptcache_id_clear(struct ID *id, char mode, int cfra, int stack_index); int BKE_ptcache_id_exist(struct ID *id, int cfra, int stack_index); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 5e688af14a4..4cc134476e4 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -1813,7 +1813,7 @@ CustomDataMask get_viewedit_datamask() View3D *view = sa->spacedata.first; if(view->drawtype == OB_SHADED) { /* this includes normals for mesh_create_shadedColors */ - mask |= CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_NORMAL; + mask |= CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_NORMAL | CD_MASK_ORCO; } if((view->drawtype == OB_TEXTURE) || ((view->drawtype == OB_SOLID) && (view->flag2 & V3D_SOLID_TEX))) { mask |= CD_MASK_MTFACE | CD_MASK_MCOL; @@ -1829,6 +1829,48 @@ CustomDataMask get_viewedit_datamask() return mask; } +static DerivedMesh *create_orco_dm(Object *ob, Mesh *me) +{ + DerivedMesh *dm; + float (*orco)[3]; + + dm= CDDM_from_mesh(me, ob); + orco= (float(*)[3])get_mesh_orco_verts(ob); + CDDM_apply_vert_coords(dm, orco); + CDDM_calc_normals(dm); + MEM_freeN(orco); + + return dm; +} + +static void add_orco_dm(Object *ob, DerivedMesh *dm, DerivedMesh *orcodm) +{ + float (*orco)[3], (*layerorco)[3]; + int totvert; + + totvert= dm->getNumVerts(dm); + + if(orcodm) { + orco= MEM_callocN(sizeof(float)*3*totvert, "dm orco"); + + if(orcodm->getNumVerts(orcodm) == totvert) + orcodm->getVertCos(orcodm, orco); + else + dm->getVertCos(dm, orco); + } + else + orco= (float(*)[3])get_mesh_orco_verts(ob); + + transform_mesh_orco_verts(ob->data, orco, totvert, 0); + + if((layerorco = DM_get_vert_data_layer(dm, CD_ORCO))) { + memcpy(layerorco, orco, sizeof(float)*totvert); + MEM_freeN(orco); + } + else + DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, orco); +} + static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], DerivedMesh **deform_r, DerivedMesh **final_r, int useRenderParams, int useDeform, @@ -1837,8 +1879,9 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], Mesh *me = ob->data; ModifierData *md = modifiers_getVirtualModifierList(ob); LinkNode *datamasks, *curr; + CustomDataMask mask; float (*deformedVerts)[3] = NULL; - DerivedMesh *dm; + DerivedMesh *dm, *orcodm, *finaldm; int numVerts = me->totvert; int fluidsimMeshUsed = 0; int required_mode; @@ -1936,6 +1979,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], * OnlyDeform ones. */ dm = NULL; + orcodm = NULL; #ifdef WITH_VERSE /* hack to make sure modifiers don't try to use mesh data from a verse @@ -1957,6 +2001,13 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], if(mti->isDisabled && mti->isDisabled(md)) continue; if(needMapping && !modifier_supportsMapping(md)) continue; + /* add an orco layer if needed by this modifier */ + if(dm && mti->requiredDataMask) { + mask = mti->requiredDataMask(md); + if(mask & CD_MASK_ORCO) + add_orco_dm(ob, dm, orcodm); + } + /* How to apply modifier depends on (a) what we already have as * a result of previous modifiers (could be a DerivedMesh or just * deformed vertices) and (b) what type the modifier is. @@ -2003,13 +2054,31 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], } } + /* create an orco derivedmesh in parallel */ + mask= (CustomDataMask)curr->link; + if(mask & CD_MASK_ORCO) { + if(!orcodm) + orcodm= create_orco_dm(ob, me); + + mask &= ~CD_MASK_ORCO; + DM_set_only_copy(orcodm, mask); + ndm = mti->applyModifier(md, ob, orcodm, useRenderParams, !inputVertexCos); + + if(ndm) { + /* if the modifier returned a new dm, release the old one */ + if(orcodm && orcodm != ndm) orcodm->release(orcodm); + orcodm = ndm; + } + } + /* set the DerivedMesh to only copy needed data */ - DM_set_only_copy(dm, (CustomDataMask)curr->link); + DM_set_only_copy(dm, mask); + /* add an origspace layer if needed */ if(((CustomDataMask)curr->link) & CD_MASK_ORIGSPACE) if(!CustomData_has_layer(&dm->faceData, CD_ORIGSPACE)) - CustomData_add_layer(&dm->faceData, CD_ORIGSPACE, CD_DEFAULT, NULL, dm->getNumFaces(dm)); - + DM_add_face_layer(dm, CD_ORIGSPACE, CD_DEFAULT, NULL); + ndm = mti->applyModifier(md, ob, dm, useRenderParams, !inputVertexCos); if(ndm) { @@ -2033,34 +2102,43 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], * DerivedMesh then we need to build one. */ if(dm && deformedVerts) { - *final_r = CDDM_copy(dm); + finaldm = CDDM_copy(dm); dm->release(dm); - CDDM_apply_vert_coords(*final_r, deformedVerts); - CDDM_calc_normals(*final_r); + CDDM_apply_vert_coords(finaldm, deformedVerts); + CDDM_calc_normals(finaldm); } else if(dm) { - *final_r = dm; + finaldm = dm; } else { #ifdef WITH_VERSE if(me->vnode) - *final_r = derivedmesh_from_versemesh(me->vnode, deformedVerts); + finaldm = derivedmesh_from_versemesh(me->vnode, deformedVerts); else { - *final_r = CDDM_from_mesh(me, ob); + finaldm = CDDM_from_mesh(me, ob); if(deformedVerts) { - CDDM_apply_vert_coords(*final_r, deformedVerts); - CDDM_calc_normals(*final_r); + CDDM_apply_vert_coords(finaldm, deformedVerts); + CDDM_calc_normals(finaldm); } } #else - *final_r = CDDM_from_mesh(me, ob); + finaldm = CDDM_from_mesh(me, ob); if(deformedVerts) { - CDDM_apply_vert_coords(*final_r, deformedVerts); - CDDM_calc_normals(*final_r); + CDDM_apply_vert_coords(finaldm, deformedVerts); + CDDM_calc_normals(finaldm); } #endif } + /* add an orco layer if needed */ + if(dataMask & CD_MASK_ORCO) + add_orco_dm(ob, finaldm, orcodm); + + *final_r = finaldm; + + if(orcodm) + orcodm->release(orcodm); + if(deformedVerts && deformedVerts != inputVertexCos) MEM_freeN(deformedVerts); @@ -2190,7 +2268,7 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r, if(((CustomDataMask)curr->link) & CD_MASK_ORIGSPACE) if(!CustomData_has_layer(&dm->faceData, CD_ORIGSPACE)) - CustomData_add_layer(&dm->faceData, CD_ORIGSPACE, CD_DEFAULT, NULL, dm->getNumFaces(dm)); + DM_add_face_layer(dm, CD_ORIGSPACE, CD_DEFAULT, NULL); ndm = mti->applyModifierEM(md, ob, em, dm); @@ -2342,6 +2420,10 @@ static void clear_mesh_caches(Object *ob) Mesh *me= ob->data; /* also serves as signal to remake texspace */ + if (ob->bb) { + MEM_freeN(ob->bb); + ob->bb = NULL; + } if (me->bb) { MEM_freeN(me->bb); me->bb = NULL; @@ -2397,7 +2479,9 @@ static void mesh_build_data(Object *ob, CustomDataMask dataMask) ob->derivedFinal->getMinMax(ob->derivedFinal, min, max); - boundbox_set_from_min_max(mesh_get_bb(ob->data), min, max); + if(!ob->bb) + ob->bb= MEM_callocN(sizeof(BoundBox), "bb"); + boundbox_set_from_min_max(ob->bb, min, max); ob->derivedFinal->needsFree = 0; ob->derivedDeform->needsFree = 0; @@ -2433,7 +2517,9 @@ static void editmesh_build_data(CustomDataMask dataMask) em->derivedFinal->getMinMax(em->derivedFinal, min, max); - boundbox_set_from_min_max(mesh_get_bb(G.obedit->data), min, max); + if(!G.obedit->bb) + G.obedit->bb= MEM_callocN(sizeof(BoundBox), "bb"); + boundbox_set_from_min_max(G.obedit->bb, min, max); em->derivedFinal->needsFree = 0; em->derivedCage->needsFree = 0; diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index e30d7dd4ac9..162ee582d74 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -433,21 +433,17 @@ static bActionStrip *get_active_strip(Object *ob) /* non clipped mapping of strip */ static float get_actionstrip_frame(bActionStrip *strip, float cframe, int invert) { - float length, actlength, repeat; + float length, actlength, repeat, scale; - if (strip->flag & ACTSTRIP_USESTRIDE) - repeat= 1.0f; - else - repeat= strip->repeat; + repeat = (strip->flag & ACTSTRIP_USESTRIDE) ? (1.0f) : (strip->repeat); + scale = abs(strip->scale); /* scale must be positive (for now) */ - length = strip->end-strip->start; - if(length==0.0f) - length= 1.0f; actlength = strip->actend-strip->actstart; + if (actlength == 0.0f) actlength = 1.0f; + length = repeat * scale * actlength; - - - if(invert) + /* invert = convert action-strip time to global time */ + if (invert) return length*(cframe - strip->actstart)/(repeat*actlength) + strip->start; else return repeat*actlength*(cframe - strip->start)/length + strip->actstart; diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 43168733b3f..4aebd099885 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -105,7 +105,7 @@ void calc_curvepath(Object *ob) cu->path= NULL; bl= cu->bev.first; - if(bl==NULL) return; + if(bl==NULL || !bl->nr) return; cu->path=path= MEM_callocN(sizeof(Path), "path"); @@ -227,6 +227,7 @@ int where_on_path(Object *ob, float ctime, float *vec, float *dir) /* returns OK /* test for cyclic */ bl= cu->bev.first; + if (!bl->nr) return 0; if(bl && bl->poly> -1) cycl= 1; ctime *= (path->len-1); @@ -538,7 +539,7 @@ static void face_duplilist(ListBase *lb, Scene *sce, Object *par) /* scale */ if(par->transflag & OB_DUPLIFACES_SCALE) { float size= v4?AreaQ3Dfl(v1, v2, v3, v4):AreaT3Dfl(v1, v2, v3); - size= sqrt(size); + size= sqrt(size) * par->dupfacesca; Mat3MulFloat(mat[0], size); } @@ -639,7 +640,7 @@ static void new_particle_duplilist(ListBase *lb, Scene *sce, Object *par, Partic pa_num = a; pa_time = psys->particles[psys->child[a - totpart].parent].time; - size=psys_get_child_size(psys, a - totpart, ctime, 0); + size=psys_get_child_size(psys, &psys->child[a - totpart], ctime, 0); } if(part->draw_as==PART_DRAW_GR) { @@ -782,7 +783,7 @@ ListBase *object_duplilist(Scene *sce, Object *ob) { ListBase *duplilist= MEM_mallocN(sizeof(ListBase), "duplilist"); duplilist->first= duplilist->last= NULL; - + if(ob->transflag & OB_DUPLI) { if(ob->transflag & OB_DUPLIPARTS) { ParticleSystem *psys = ob->particlesystem.first; @@ -807,7 +808,7 @@ ListBase *object_duplilist(Scene *sce, Object *ob) DupliObject *dob; group_duplilist(duplilist, ob, 0); /* now recursive */ - + /* make copy already, because in group dupli's deform displists can be makde, requiring parent matrices */ for(dob= duplilist->first; dob; dob= dob->next) Mat4CpyMat4(dob->ob->obmat, dob->mat); diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index ab15770c3df..6bdb663545c 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1589,11 +1589,11 @@ static void execute_posetree(Object *ob, PoseTree *tree) /* set DoF flag */ flag= 0; - if((pchan->ikflag & BONE_IK_NO_XDOF) == 0) + if(!(pchan->ikflag & BONE_IK_NO_XDOF) && !(pchan->ikflag & BONE_IK_NO_XDOF_TEMP)) flag |= IK_XDOF; - if((pchan->ikflag & BONE_IK_NO_YDOF) == 0) + if(!(pchan->ikflag & BONE_IK_NO_YDOF) && !(pchan->ikflag & BONE_IK_NO_YDOF_TEMP)) flag |= IK_YDOF; - if((pchan->ikflag & BONE_IK_NO_ZDOF) == 0) + if(!(pchan->ikflag & BONE_IK_NO_ZDOF) && !(pchan->ikflag & BONE_IK_NO_ZDOF_TEMP)) flag |= IK_ZDOF; if(tree->stretch && (pchan->ikstretch > 0.0)) { diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 3d565c2a5a3..c87c75b0190 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -874,12 +874,14 @@ static void default_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstrain /* This following macro should be used for all standard single-target *_flush_tars functions * to save typing and reduce maintainance woes. + * Note: the pointer to ct will be changed to point to the next in the list (as it gets removed) * (Hopefully all compilers will be happy with the lines with just a space on them. Those are * really just to help this code easier to read) */ #define SINGLETARGET_FLUSH_TARS(con, datatar, datasubtarget, ct, list, nocopy) \ { \ if (ct) { \ + bConstraintTarget *ctn = ct->next; \ if (nocopy == 0) { \ datatar= ct->tar; \ strcpy(datasubtarget, ct->subtarget); \ @@ -887,23 +889,27 @@ static void default_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstrain } \ \ BLI_freelinkN(list, ct); \ + ct= ctn; \ } \ } /* This following macro should be used for all standard single-target *_flush_tars functions - * to save typing and reduce maintainance woes. It does not do the subtarget related operations + * to save typing and reduce maintainance woes. It does not do the subtarget related operations. + * Note: the pointer to ct will be changed to point to the next in the list (as it gets removed) * (Hopefully all compilers will be happy with the lines with just a space on them. Those are * really just to help this code easier to read) */ #define SINGLETARGETNS_FLUSH_TARS(con, datatar, ct, list, nocopy) \ { \ if (ct) { \ + bConstraintTarget *ctn = ct->next; \ if (nocopy == 0) { \ datatar= ct->tar; \ con->tarspace= ct->space; \ } \ \ BLI_freelinkN(list, ct); \ + ct= ctn; \ } \ } @@ -1214,7 +1220,6 @@ static void kinematic_flush_tars (bConstraint *con, ListBase *list, short nocopy /* the following macro is used for all standard single-target constraints */ SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy) - ct= ct->next; SINGLETARGET_FLUSH_TARS(con, data->poletar, data->polesubtarget, ct, list, nocopy) } } diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 6676bf0e03f..c50374388a9 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -1479,7 +1479,11 @@ void makeBevelList(Object *ob) else nu= cu->nurb.first; while(nu) { - if(nu->pntsu>1) { + if(nu->pntsu<=1) { + bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList"); + BLI_addtail(&(cu->bev), bl); + bl->nr= 0; + } else { if(G.rendering && cu->resolu_ren!=0) resolu= cu->resolu_ren; else @@ -1539,8 +1543,8 @@ void makeBevelList(Object *ob) bevp->y= prevbezt->vec[1][1]; bevp->z= prevbezt->vec[1][2]; bevp->alfa= prevbezt->alfa; - bevp->f1= 1; - bevp->f2= 0; + bevp->f1= SELECT; + bevp->f2= SELECT; bevp++; bl->nr++; bl->flag= 1; @@ -1637,28 +1641,30 @@ void makeBevelList(Object *ob) /* STEP 2: DOUBLE POINTS AND AUTOMATIC RESOLUTION, REDUCE DATABLOCKS */ bl= cu->bev.first; while(bl) { - nr= bl->nr; - bevp1= (BevPoint *)(bl+1); - bevp0= bevp1+(nr-1); - nr--; - while(nr--) { - if( fabs(bevp0->x-bevp1->x)<0.00001 ) { - if( fabs(bevp0->y-bevp1->y)<0.00001 ) { - if( fabs(bevp0->z-bevp1->z)<0.00001 ) { - bevp0->f2= 1; - bl->flag++; + if (bl->nr) { /* null bevel items come from single points */ + nr= bl->nr; + bevp1= (BevPoint *)(bl+1); + bevp0= bevp1+(nr-1); + nr--; + while(nr--) { + if( fabs(bevp0->x-bevp1->x)<0.00001 ) { + if( fabs(bevp0->y-bevp1->y)<0.00001 ) { + if( fabs(bevp0->z-bevp1->z)<0.00001 ) { + bevp0->f2= SELECT; + bl->flag++; + } } } + bevp0= bevp1; + bevp1++; } - bevp0= bevp1; - bevp1++; } bl= bl->next; } bl= cu->bev.first; while(bl) { blnext= bl->next; - if(bl->flag) { + if(bl->nr && bl->flag) { nr= bl->nr- bl->flag+1; /* +1 because vectorbezier sets flag too */ blnew= MEM_mallocN(sizeof(BevList)+nr*sizeof(BevPoint), "makeBevelList"); memcpy(blnew, bl, sizeof(BevList)); @@ -1686,7 +1692,7 @@ void makeBevelList(Object *ob) bl= cu->bev.first; poly= 0; while(bl) { - if(bl->poly>=0) { + if(bl->nr && bl->poly>=0) { poly++; bl->poly= poly; bl->gat= 0; /* 'gat' is dutch for hole */ @@ -2162,7 +2168,7 @@ void calchandleNurb(BezTriple *bezt, BezTriple *prev, BezTriple *next, int mode) if(len1==0.0) len1=1.0; if(len2==0.0) len2=1.0; - if(bezt->f1 & 1) { /* order of calculation */ + if(bezt->f1 & SELECT) { /* order of calculation */ if(bezt->h2==HD_ALIGN) { /* aligned */ len= len2/len1; p2[3]= p2[0]+len*(p2[0]-p2[-3]); @@ -2238,9 +2244,9 @@ void testhandlesNurb(Nurb *nu) a= nu->pntsu; while(a--) { flag= 0; - if(bezt->f1 & 1) flag++; - if(bezt->f2 & 1) flag += 2; - if(bezt->f3 & 1) flag += 4; + if(bezt->f1 & SELECT) flag++; + if(bezt->f2 & SELECT) flag += 2; + if(bezt->f3 & SELECT) flag += 4; if( !(flag==0 || flag==7) ) { if(bezt->h1==HD_AUTO) { /* auto */ diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index aa0dc10f4e0..d8ce311b5ca 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -449,11 +449,13 @@ const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { {sizeof(MStringProperty), "MStringProperty",1,"String",NULL,NULL,NULL,NULL}, {sizeof(OrigSpaceFace), "OrigSpaceFace", 1, "UVTex", layerCopy_origspace_face, NULL, layerInterp_origspace_face, layerSwap_origspace_face, layerDefault_origspace_face}, + {sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL} }; const char *LAYERTYPENAMES[CD_NUMTYPES] = { "CDMVert", "CDMSticky", "CDMDeformVert", "CDMEdge", "CDMFace", "CDMTFace", - "CDMCol", "CDOrigIndex", "CDNormal", "CDFlags","CDMFloatProperty","CDMIntProperty","CDMStringProperty", "CDOrigSpace"}; + "CDMCol", "CDOrigIndex", "CDNormal", "CDFlags","CDMFloatProperty", + "CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco"}; const CustomDataMask CD_MASK_BAREMESH = CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE; @@ -466,8 +468,8 @@ const CustomDataMask CD_MASK_EDITMESH = CD_MASK_MCOL|CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR; const CustomDataMask CD_MASK_DERIVEDMESH = CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | - CD_MASK_MCOL | CD_MASK_ORIGINDEX | - CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_ORIGSPACE; + CD_MASK_MCOL | CD_MASK_ORIGINDEX | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | + CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO; static const LayerTypeInfo *layerType_getInfo(int type) { diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 1c5ec61a22e..1076641b4c5 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -2189,7 +2189,11 @@ void DAG_pose_sort(Object *ob) node2 = dag_get_node(dag, target); dag_add_relation(dag, node2, node, 0); dag_add_parent_relation(dag, node2, node, 0); - cti= NULL; /* trick to get next loop skipped */ + + /* uncommented this line, results in dependencies + * not being added properly for this constraint, + * what is the purpose of this? - brecht */ + /*cti= NULL;*/ /* trick to get next loop skipped */ } } } diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 6248e01432e..a9f009cd876 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -152,12 +152,9 @@ DispList *find_displist(ListBase *lb, int type) int displist_has_faces(ListBase *lb) { DispList *dl; - - dl= lb->first; - while(dl) { + for(dl= lb->first; dl; dl= dl->next) { if ELEM3(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF) return 1; - dl= dl->next; } return 0; } @@ -485,9 +482,11 @@ static void mesh_create_shadedColors(Render *re, Object *ob, int onlyForMesh, un CustomDataMask dataMask = CD_MASK_BAREMESH | CD_MASK_MCOL | CD_MASK_MTFACE | CD_MASK_NORMAL; + init_fastshade_for_ob(re, ob, &need_orco, mat, imat); - orco = (need_orco)? mesh_create_orco(ob): NULL; + if(need_orco) + dataMask |= CD_MASK_ORCO; if (onlyForMesh) dm = mesh_get_derived_deform(ob, dataMask); @@ -499,6 +498,7 @@ static void mesh_create_shadedColors(Render *re, Object *ob, int onlyForMesh, un nors = dm->getFaceDataArray(dm, CD_NORMAL); totvert = dm->getNumVerts(dm); totface = dm->getNumFaces(dm); + orco= dm->getVertDataArray(dm, CD_ORCO); if (onlyForMesh) { col1 = *col1_r; @@ -577,9 +577,6 @@ static void mesh_create_shadedColors(Render *re, Object *ob, int onlyForMesh, un } MEM_freeN(vnors); - if (orco) - MEM_freeN(orco); - dm->release(dm); end_fastshade_for_ob(ob); @@ -1426,99 +1423,102 @@ void makeDispListCurveTypes(Object *ob, int forOrco) BevPoint *bevp; int a,b; - /* exception handling; curve without bevel or extrude, with width correction */ - if(dlbev.first==NULL) { - dl= MEM_callocN(sizeof(DispList), "makeDispListbev"); - dl->verts= MEM_callocN(3*sizeof(float)*bl->nr, "dlverts"); - BLI_addtail(dispbase, dl); - - if(bl->poly!= -1) dl->type= DL_POLY; - else dl->type= DL_SEGM; - - if(dl->type==DL_SEGM) dl->flag = (DL_FRONT_CURVE|DL_BACK_CURVE); + if (bl->nr) { /* blank bevel lists can happen */ - dl->parts= 1; - dl->nr= bl->nr; - dl->col= nu->mat_nr; - dl->charidx= nu->charidx; - dl->rt= nu->flag; - - a= dl->nr; - bevp= (BevPoint *)(bl+1); - data= dl->verts; - while(a--) { - data[0]= bevp->x+widfac*bevp->sina; - data[1]= bevp->y+widfac*bevp->cosa; - data[2]= bevp->z; - bevp++; - data+=3; - } - } - else { - DispList *dlb; - - for (dlb=dlbev.first; dlb; dlb=dlb->next) { - - /* for each part of the bevel use a separate displblock */ - dl= MEM_callocN(sizeof(DispList), "makeDispListbev1"); - dl->verts= data= MEM_callocN(3*sizeof(float)*dlb->nr*bl->nr, "dlverts"); + /* exception handling; curve without bevel or extrude, with width correction */ + if(dlbev.first==NULL) { + dl= MEM_callocN(sizeof(DispList), "makeDispListbev"); + dl->verts= MEM_callocN(3*sizeof(float)*bl->nr, "dlverts"); BLI_addtail(dispbase, dl); - - dl->type= DL_SURF; - dl->flag= dlb->flag & (DL_FRONT_CURVE|DL_BACK_CURVE); - if(dlb->type==DL_POLY) dl->flag |= DL_CYCL_U; - if(bl->poly>=0) dl->flag |= DL_CYCL_V; + if(bl->poly!= -1) dl->type= DL_POLY; + else dl->type= DL_SEGM; - dl->parts= bl->nr; - dl->nr= dlb->nr; + if(dl->type==DL_SEGM) dl->flag = (DL_FRONT_CURVE|DL_BACK_CURVE); + + dl->parts= 1; + dl->nr= bl->nr; dl->col= nu->mat_nr; dl->charidx= nu->charidx; dl->rt= nu->flag; - dl->bevelSplitFlag= MEM_callocN(sizeof(*dl->col2)*((bl->nr+0x1F)>>5), "col2"); - bevp= (BevPoint *)(bl+1); - - /* for each point of poly make a bevel piece */ + + a= dl->nr; bevp= (BevPoint *)(bl+1); - for(a=0; a<bl->nr; a++,bevp++) { - float fac=1.0; - if (cu->taperobj==NULL) { - if ( (cu->bevobj!=NULL) || !((cu->flag & CU_FRONT) || (cu->flag & CU_BACK)) ) - fac = calc_curve_subdiv_radius(cu, nu, a); - } else { - fac = calc_taper(cu->taperobj, a, bl->nr); - } + data= dl->verts; + while(a--) { + data[0]= bevp->x+widfac*bevp->sina; + data[1]= bevp->y+widfac*bevp->cosa; + data[2]= bevp->z; + bevp++; + data+=3; + } + } + else { + DispList *dlb; + + for (dlb=dlbev.first; dlb; dlb=dlb->next) { + + /* for each part of the bevel use a separate displblock */ + dl= MEM_callocN(sizeof(DispList), "makeDispListbev1"); + dl->verts= data= MEM_callocN(3*sizeof(float)*dlb->nr*bl->nr, "dlverts"); + BLI_addtail(dispbase, dl); + + dl->type= DL_SURF; - if (bevp->f1) { - dl->bevelSplitFlag[a>>5] |= 1<<(a&0x1F); - } - - /* rotate bevel piece and write in data */ - fp1= dlb->verts; - for (b=0; b<dlb->nr; b++,fp1+=3,data+=3) { - if(cu->flag & CU_3D) { - float vec[3]; - - vec[0]= fp1[1]+widfac; - vec[1]= fp1[2]; - vec[2]= 0.0; - - Mat3MulVecfl(bevp->mat, vec); - - data[0]= bevp->x+ fac*vec[0]; - data[1]= bevp->y+ fac*vec[1]; - data[2]= bevp->z+ fac*vec[2]; + dl->flag= dlb->flag & (DL_FRONT_CURVE|DL_BACK_CURVE); + if(dlb->type==DL_POLY) dl->flag |= DL_CYCL_U; + if(bl->poly>=0) dl->flag |= DL_CYCL_V; + + dl->parts= bl->nr; + dl->nr= dlb->nr; + dl->col= nu->mat_nr; + dl->charidx= nu->charidx; + dl->rt= nu->flag; + dl->bevelSplitFlag= MEM_callocN(sizeof(*dl->col2)*((bl->nr+0x1F)>>5), "col2"); + bevp= (BevPoint *)(bl+1); + + /* for each point of poly make a bevel piece */ + bevp= (BevPoint *)(bl+1); + for(a=0; a<bl->nr; a++,bevp++) { + float fac=1.0; + if (cu->taperobj==NULL) { + if ( (cu->bevobj!=NULL) || !((cu->flag & CU_FRONT) || (cu->flag & CU_BACK)) ) + fac = calc_curve_subdiv_radius(cu, nu, a); + } else { + fac = calc_taper(cu->taperobj, a, bl->nr); } - else { - data[0]= bevp->x+ fac*(widfac+fp1[1])*bevp->sina; - data[1]= bevp->y+ fac*(widfac+fp1[1])*bevp->cosa; - data[2]= bevp->z+ fac*fp1[2]; + + if (bevp->f1) { + dl->bevelSplitFlag[a>>5] |= 1<<(a&0x1F); + } + + /* rotate bevel piece and write in data */ + fp1= dlb->verts; + for (b=0; b<dlb->nr; b++,fp1+=3,data+=3) { + if(cu->flag & CU_3D) { + float vec[3]; + + vec[0]= fp1[1]+widfac; + vec[1]= fp1[2]; + vec[2]= 0.0; + + Mat3MulVecfl(bevp->mat, vec); + + data[0]= bevp->x+ fac*vec[0]; + data[1]= bevp->y+ fac*vec[1]; + data[2]= bevp->z+ fac*vec[2]; + } + else { + data[0]= bevp->x+ fac*(widfac+fp1[1])*bevp->sina; + data[1]= bevp->y+ fac*(widfac+fp1[1])*bevp->cosa; + data[2]= bevp->z+ fac*fp1[2]; + } } } + + /* gl array drawing: using indices */ + displist_surf_indices(dl); } - - /* gl array drawing: using indices */ - displist_surf_indices(dl); } } diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index be63ce734be..ed944a3a4ea 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -95,7 +95,7 @@ /* ******** IMAGE PROCESSING ************* */ -/* used by sequencer */ +/* used by sequencer and image premul option - IMA_DO_PREMUL */ void converttopremul(struct ImBuf *ibuf) { int x, y, val; @@ -731,7 +731,7 @@ void BKE_add_image_extension(char *string, int imtype) if(!BLI_testextensie(string, ".hdr")) extension= ".hdr"; } - else if(imtype==R_PNG) { + else if(imtype==R_PNG || imtype==R_FFMPEG) { if(!BLI_testextensie(string, ".png")) extension= ".png"; } @@ -746,7 +746,7 @@ void BKE_add_image_extension(char *string, int imtype) extension= ".tga"; } else if(ELEM5(imtype, R_MOVIE, R_AVICODEC, R_AVIRAW, R_AVIJPEG, R_JPEG90)) { - if(!BLI_testextensie(string, ".jpg")) + if(!( BLI_testextensie(string, ".jpg") || BLI_testextensie(string, ".jpeg"))) extension= ".jpg"; } else if(imtype==R_BMP) { @@ -1062,7 +1062,7 @@ int BKE_write_ibuf(ImBuf *ibuf, char *name, int imtype, int subimtype, int quali else if ((imtype==R_RADHDR)) { ibuf->ftype= RADHDR; } - else if ((imtype==R_PNG)) { + else if (imtype==R_PNG || imtype==R_FFMPEG) { ibuf->ftype= PNG; } #ifdef WITH_DDS diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 03a34df090a..876f1c50a93 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -530,9 +530,9 @@ void testhandles_ipocurve(IpoCurve *icu) a= icu->totvert; while(a--) { flag= 0; - if(bezt->f1 & 1) flag++; - if(bezt->f2 & 1) flag += 2; - if(bezt->f3 & 1) flag += 4; + if(bezt->f1 & SELECT) flag++; + if(bezt->f2 & SELECT) flag += 2; + if(bezt->f3 & SELECT) flag += 4; if( !(flag==0 || flag==7) ) { if(bezt->h1==HD_AUTO) { /* auto */ @@ -758,44 +758,47 @@ void berekenx(float *f, float *o, int b) } } -#define TFM_WITHOUT_BONE 1 - -static void posechannel_get_local_transform(bPoseChannel *pchan, float *quat, float *eul, float *size, int flag) +/* we need the local transform = current transform - (parent transform + bone transform) */ +/* (local transform is on action channel level) */ +static void posechannel_get_local_transform(bPoseChannel *pchan, float *loc, float *eul, float *size) { - float pose_mat[3][3]; - float diff_mat[3][3], ipar_mat[3][3]; - - /* we need the local transform = current transform - (parent transform + bone transform) */ - - Mat3CpyMat4(pose_mat, pchan->pose_mat); + float diff_mat[4][4]; + float parmat[4][4], offs_bone[4][4], imat[4][4]; if (pchan->parent) { + /* get first the parent + bone transform in parmat */ - if(flag & TFM_WITHOUT_BONE) { - float par_mat[3][3]; - Mat3CpyMat4(par_mat, pchan->parent->pose_mat); - Mat3MulMat3(diff_mat, par_mat, pchan->bone->bone_mat); - } - else - Mat3CpyMat4(diff_mat, pchan->parent->pose_mat); - - Mat3Inv(ipar_mat, diff_mat); + /* bone transform itself */ + Mat4CpyMat3(offs_bone, pchan->bone->bone_mat); + /* The bone's root offset (is in the parent's coordinate system) */ + VECCOPY(offs_bone[3], pchan->bone->head); + /* Get the length translation of parent (length along y axis) */ + offs_bone[3][1]+= pchan->parent->bone->length; + + Mat4MulSerie(parmat, pchan->parent->pose_mat, offs_bone, NULL, NULL, NULL, NULL, NULL, NULL); + + /* invert it */ + Mat4Invert(imat, parmat); } else { - if(flag & TFM_WITHOUT_BONE) - Mat3Inv(ipar_mat, pchan->bone->bone_mat); - else - Mat3One(ipar_mat); + Mat4CpyMat3(offs_bone, pchan->bone->bone_mat); + VECCOPY(offs_bone[3], pchan->bone->head); + + /* invert it */ + Mat4Invert(imat, offs_bone); + } - Mat3MulMat3(diff_mat, ipar_mat, pose_mat); - - if(quat) - Mat3ToQuat(diff_mat, quat); + /* difference: current transform - (parent transform + bone transform) */ + Mat4MulMat4(diff_mat, pchan->pose_mat, imat); + + if(loc) + VECCOPY(loc, diff_mat[3]); if(eul) - Mat3ToEul(diff_mat, eul); + Mat4ToEul(diff_mat, eul); if(size) - Mat3ToSize(diff_mat, size); + Mat4ToSize(diff_mat, size); + } /* has to return a float value */ @@ -858,8 +861,6 @@ static float eval_driver(IpoDriver *driver, float ipotime) Mat4ToQuat(pchan->pose_mat, q1); Mat4ToQuat(pchan2->pose_mat, q2); - // posechannel_get_local_transform(pchan , q1, NULL, NULL, 0); - // posechannel_get_local_transform(pchan2, q2, NULL, NULL, 0); QuatInv(q1); QuatMul(quat, q1, q2); @@ -870,17 +871,17 @@ static float eval_driver(IpoDriver *driver, float ipotime) } } else { - float eul[3], size[3]; + float loc[3], eul[3], size[3]; - posechannel_get_local_transform(pchan, NULL, eul, size, TFM_WITHOUT_BONE); + posechannel_get_local_transform(pchan, loc, eul, size); switch(driver->adrcode) { case OB_LOC_X: - return pchan->loc[0]; + return loc[0]; case OB_LOC_Y: - return pchan->loc[1]; + return loc[1]; case OB_LOC_Z: - return pchan->loc[2]; + return loc[2]; case OB_ROT_X: return eul[0]/(M_PI_2/9.0); case OB_ROT_Y: @@ -2348,7 +2349,7 @@ void add_to_cfra_elem(ListBase *lb, BezTriple *bezt) if( ce->cfra==bezt->vec[1][0] ) { /* do because of double keys */ - if(bezt->f2 & 1) ce->sel= bezt->f2; + if(bezt->f2 & SELECT) ce->sel= bezt->f2; return; } else if(ce->cfra > bezt->vec[1][0]) break; diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index 64c081c27a6..2b815c28cc5 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -483,6 +483,7 @@ static int where_on_path_deform(Object *ob, float ctime, float *vec, float *dir) /* test for cyclic */ bl= cu->bev.first; + if (!bl->nr) return 0; if(bl && bl->poly> -1) cycl= 1; if(cycl==0) { diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 0699e3b8655..42cac46c241 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -687,6 +687,9 @@ static void do_init_render_material(Material *ma, int r_mode, float *amb) /* will become or-ed result of all node modes */ ma->mode_l= ma->mode; ma->mode_l &= ~MA_SHLESS; + + if(ma->strand_surfnor > 0.0f) + ma->mode_l |= MA_STR_SURFDIFF; } static void init_render_nodetree(bNodeTree *ntree, Material *basemat, int r_mode, float *amb) diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 4e551e28885..79a8afedf3f 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -454,11 +454,15 @@ void tex_space_mesh(Mesh *me) } } -BoundBox *mesh_get_bb(Mesh *me) +BoundBox *mesh_get_bb(Object *ob) { - if (!me->bb) { + Mesh *me= ob->data; + + if(ob->bb) + return ob->bb; + + if (!me->bb) tex_space_mesh(me); - } return me->bb; } @@ -474,17 +478,13 @@ void mesh_get_texspace(Mesh *me, float *loc_r, float *rot_r, float *size_r) if (size_r) VECCOPY(size_r, me->size); } -static float *make_orco_mesh_internal(Object *ob, int render) +float *get_mesh_orco_verts(Object *ob) { Mesh *me = ob->data; - float (*orcoData)[3]; int a, totvert; - float loc[3], size[3]; - DerivedMesh *dm; float (*vcos)[3] = NULL; - /* Get appropriate vertex coordinates */ - + /* Get appropriate vertex coordinates */ if(me->key && me->texcomesh==0 && me->key->refkey) { vcos= mesh_getRefKeyCos(me, &totvert); } @@ -512,40 +512,32 @@ static float *make_orco_mesh_internal(Object *ob, int render) } } - /* Apply orco-changing modifiers */ - - if (render) { - dm = mesh_create_derived_no_deform_render(ob, vcos, CD_MASK_BAREMESH); - } else { - dm = mesh_create_derived_no_deform(ob, vcos, CD_MASK_BAREMESH); - } - totvert = dm->getNumVerts(dm); + return (float*)vcos; +} - orcoData = MEM_mallocN(sizeof(*orcoData)*totvert, "orcoData"); - dm->getVertCos(dm, orcoData); - dm->release(dm); - MEM_freeN(vcos); +void transform_mesh_orco_verts(Mesh *me, float (*orco)[3], int totvert, int invert) +{ + float loc[3], size[3]; + int a; mesh_get_texspace(me->texcomesh?me->texcomesh:me, loc, NULL, size); - for(a=0; a<totvert; a++) { - float *co = orcoData[a]; - co[0] = (co[0]-loc[0])/size[0]; - co[1] = (co[1]-loc[1])/size[1]; - co[2] = (co[2]-loc[2])/size[2]; + if(invert) { + for(a=0; a<totvert; a++) { + float *co = orco[a]; + co[0] = co[0]*size[0] + loc[0]; + co[1] = co[1]*size[1] + loc[1]; + co[2] = co[2]*size[2] + loc[2]; + } + } + else { + for(a=0; a<totvert; a++) { + float *co = orco[a]; + co[0] = (co[0]-loc[0])/size[0]; + co[1] = (co[1]-loc[1])/size[1]; + co[2] = (co[2]-loc[2])/size[2]; + } } - - return (float*) orcoData; -} - -float *mesh_create_orco_render(Object *ob) -{ - return make_orco_mesh_internal(ob, 1); -} - -float *mesh_create_orco(Object *ob) -{ - return make_orco_mesh_internal(ob, 0); } /* rotates the vertices of a face in case v[2] or v[3] (vertex index) is = 0. diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index e433fb6ed88..554613b3355 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -5269,7 +5269,7 @@ static void particleSystemModifier_initData(ModifierData *md) ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md; psmd->psys= 0; psmd->dm=0; - + psmd->totdmvert= psmd->totdmedge= psmd->totdmface= 0; } static void particleSystemModifier_freeData(ModifierData *md) { @@ -5313,6 +5313,8 @@ CustomDataMask particleSystemModifier_requiredDataMask(ModifierData *md) /* particles only need this if they are after a non deform modifier, and * the modifier stack will only create them in that case. */ dataMask |= CD_MASK_ORIGSPACE; + + dataMask |= CD_MASK_ORCO; return dataMask; } @@ -5347,7 +5349,7 @@ static void particleSystemModifier_deformVerts( DerivedMesh *dm = derivedData; ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md; ParticleSystem * psys=0; - int totvert=0,totedge=0,totface=0,needsFree=0; + int needsFree=0; if(ob->particlesystem.first) psys=psmd->psys; @@ -5363,6 +5365,8 @@ static void particleSystemModifier_deformVerts( CDDM_apply_vert_coords(dm, vertexCos); //CDDM_calc_normals(dm); + + DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, get_mesh_orco_verts(ob)); needsFree=1; } @@ -5396,9 +5400,6 @@ static void particleSystemModifier_deformVerts( /* clear old dm */ if(psmd->dm){ - totvert=psmd->dm->getNumVerts(psmd->dm); - totedge=psmd->dm->getNumEdges(psmd->dm); - totface=psmd->dm->getNumFaces(psmd->dm); psmd->dm->needsFree = 1; psmd->dm->release(psmd->dm); } @@ -5416,17 +5417,18 @@ static void particleSystemModifier_deformVerts( psmd->dm->needsFree = 0; /* report change in mesh structure */ - if(psmd->dm->getNumVerts(psmd->dm)!=totvert || - psmd->dm->getNumEdges(psmd->dm)!=totedge || - psmd->dm->getNumFaces(psmd->dm)!=totface){ + if(psmd->dm->getNumVerts(psmd->dm)!=psmd->totdmvert || + psmd->dm->getNumEdges(psmd->dm)!=psmd->totdmedge || + psmd->dm->getNumFaces(psmd->dm)!=psmd->totdmface){ /* in file read dm hasn't really changed but just wasn't saved in file */ - if(psmd->flag & eParticleSystemFlag_Loaded) - psmd->flag &= ~eParticleSystemFlag_Loaded; - else{ - psys->recalc |= PSYS_RECALC_HAIR; - psys->recalc |= PSYS_DISTR; - psmd->flag |= eParticleSystemFlag_DM_changed; - } + + psys->recalc |= PSYS_RECALC_HAIR; + psys->recalc |= PSYS_DISTR; + psmd->flag |= eParticleSystemFlag_DM_changed; + + psmd->totdmvert= psmd->dm->getNumVerts(psmd->dm); + psmd->totdmedge= psmd->dm->getNumEdges(psmd->dm); + psmd->totdmface= psmd->dm->getNumFaces(psmd->dm); } if(psys){ @@ -5766,7 +5768,7 @@ static void explodeModifier_createFacepa(ExplodeModifierData *emd, /* make tree of emitter locations */ tree=BLI_kdtree_new(totpart); for(p=0,pa=psys->particles; p<totpart; p++,pa++){ - psys_particle_on_dm(ob,dm,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0); + psys_particle_on_dm(ob,psmd->dm,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,0,0); BLI_kdtree_insert(tree, p, co, NULL); } BLI_kdtree_balance(tree); @@ -6337,7 +6339,7 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd, /*duplicate & displace vertices*/ for(i=0, pa=pars; i<=totpart; i++, pa++){ if(i!=totpart){ - psys_particle_on_emitter(ob, psmd,part->from,pa->num,-1,pa->fuv,pa->foffset,loc0,nor,0,0); + psys_particle_on_emitter(ob, psmd,part->from,pa->num,-1,pa->fuv,pa->foffset,loc0,nor,0,0,0,0); Mat4MulVecfl(ob->obmat,loc0); state.time=cfra; @@ -6453,7 +6455,10 @@ static DerivedMesh * explodeModifier_applyModifier( if(psys->part==0 || psys->particles==0) return derivedData; /* 1. find faces to be exploded if needed */ - if(emd->facepa==0 || psmd->flag&eParticleSystemFlag_Pars || emd->flag&eExplodeFlag_CalcFaces){ + if(emd->facepa==0 + || psmd->flag&eParticleSystemFlag_Pars + || emd->flag&eExplodeFlag_CalcFaces + || MEM_allocN_len(emd->facepa)/sizeof(int) != dm->getNumFaces(dm)){ if(psmd->flag & eParticleSystemFlag_Pars) psmd->flag &= ~eParticleSystemFlag_Pars; @@ -6625,18 +6630,16 @@ static void meshdeformModifier_do( tmpdm->release(tmpdm); } else - cagedm= mesh_get_derived_final(mmd->object, CD_MASK_BAREMESH); + cagedm= mmd->object->derivedFinal; - /* TODO: this could give inifinite loop for circular dependency */ if(!cagedm) return; /* compute matrices to go in and out of cage object space */ - Mat4Invert(imat, (mmd->bindcos)? mmd->bindmat: mmd->object->obmat); + Mat4Invert(imat, mmd->object->obmat); Mat4MulMat4(cagemat, ob->obmat, imat); Mat4Invert(icagemat, cagemat); - Mat4Invert(imat, ob->obmat); - Mat3CpyMat4(iobmat, imat); + Mat3CpyMat4(iobmat, icagemat); /* bind weights if needed */ if(!mmd->bindcos) @@ -6658,9 +6661,16 @@ static void meshdeformModifier_do( dco= MEM_callocN(sizeof(*dco)*totcagevert, "MDefDco"); for(a=0; a<totcagevert; a++) { + /* get cage vertex in world space with binding transform */ VECCOPY(co, cagemvert[a].co); - Mat4MulVecfl(mmd->object->obmat, co); - VECSUB(dco[a], co, bindcos[a]); + + if(G.rt != 527) { + Mat4MulVecfl(mmd->bindmat, co); + /* compute difference with world space bind coord */ + VECSUB(dco[a], co, bindcos[a]); + } + else + VECCOPY(dco[a], co) } defgrp_index = -1; @@ -6707,6 +6717,7 @@ static void meshdeformModifier_do( } if(mmd->flag & MOD_MDEF_DYNAMIC_BIND) { + /* transform coordinate into cage's local space */ VECCOPY(co, vertexCos[b]); Mat4MulVecfl(cagemat, co); totweight= meshdeform_dynamic_bind(mmd, dco, co); @@ -6727,7 +6738,10 @@ static void meshdeformModifier_do( if(totweight > 0.0f) { VecMulf(co, fac/totweight); Mat3MulVecfl(iobmat, co); - VECADD(vertexCos[b], vertexCos[b], co); + if(G.rt != 527) + VECADD(vertexCos[b], vertexCos[b], co) + else + VECCOPY(vertexCos[b], co) } } @@ -7021,7 +7035,9 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti = INIT_TYPE(Boolean); mti->type = eModifierTypeType_Nonconstructive; - mti->flags = eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_RequiresOriginalData; + mti->flags = eModifierTypeFlag_AcceptsMesh + | eModifierTypeFlag_RequiresOriginalData + | eModifierTypeFlag_UsesPointCache; mti->copyData = booleanModifier_copyData; mti->isDisabled = booleanModifier_isDisabled; mti->applyModifier = booleanModifier_applyModifier; @@ -7045,7 +7061,8 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti = INIT_TYPE(ParticleSystem); mti->type = eModifierTypeType_OnlyDeform; mti->flags = eModifierTypeFlag_AcceptsMesh - | eModifierTypeFlag_SupportsMapping; + | eModifierTypeFlag_SupportsMapping + | eModifierTypeFlag_UsesPointCache; #if 0 | eModifierTypeFlag_SupportsEditmode; |eModifierTypeFlag_EnableInEditmode; @@ -7481,3 +7498,16 @@ int modifiers_indexInObject(Object *ob, ModifierData *md_seek) return i; } +int modifiers_usesPointCache(Object *ob) +{ + ModifierData *md = ob->modifiers.first; + + for (; md; md=md->next) { + ModifierTypeInfo *mti = modifierType_getInfo(md->type); + if (mti->flags & eModifierTypeFlag_UsesPointCache) { + return 1; + } + } + return 0; +} + diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index d9b2ce84fa5..15c4943f6fb 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -913,6 +913,7 @@ Object *add_only_object(int type, char *name) ob->ipowin= ID_OB; /* the ipowin shown */ ob->dupon= 1; ob->dupoff= 0; ob->dupsta= 1; ob->dupend= 100; + ob->dupfacesca = 1.0; /* Game engine defaults*/ ob->mass= ob->inertia= 1.0f; @@ -1005,12 +1006,26 @@ SoftBody *copy_softbody(SoftBody *sb) ParticleSystem *copy_particlesystem(ParticleSystem *psys) { ParticleSystem *psysn; + ParticleData *pa; + int a; psysn= MEM_dupallocN(psys); psysn->particles= MEM_dupallocN(psys->particles); - psysn->child= MEM_dupallocN(psys->child); + for(a=0, pa=psysn->particles; a<psysn->totpart; a++, pa++) { + if(pa->hair) + pa->hair= MEM_dupallocN(pa->hair); + if(pa->keys) + pa->keys= MEM_dupallocN(pa->keys); + } + + if(psys->soft) + psysn->soft= copy_softbody(psys->soft); + + psysn->pathcache= NULL; + psysn->childcache= NULL; + psysn->edit= NULL; psysn->effectors.first= psysn->effectors.last= 0; id_us_plus((ID *)psysn->part); @@ -1022,7 +1037,7 @@ static void copy_object_pose(Object *obn, Object *ob) { bPoseChannel *chan; - copy_pose(&obn->pose, ob->pose, 1); + copy_pose(&obn->pose, ob->pose, 1); /* 1 = copy constraints */ for (chan = obn->pose->chanbase.first; chan; chan=chan->next){ bConstraint *con; @@ -1034,6 +1049,14 @@ static void copy_object_pose(Object *obn, Object *ob) ListBase targets = {NULL, NULL}; bConstraintTarget *ct; + if(con->ipo) { + IpoCurve *icu; + for(icu= con->ipo->curve.first; icu; icu= icu->next) { + if(icu->driver && icu->driver->ob==ob) + icu->driver->ob= obn; + } + } + if (cti && cti->get_constraint_targets) { cti->get_constraint_targets(con, &targets); @@ -1287,6 +1310,7 @@ void object_make_proxy(Object *ob, Object *target, Object *gob) /* skip constraints, constraintchannels, nla? */ + ob->type= target->type; ob->data= target->data; id_us_plus((ID *)ob->data); /* ensures lib data becomes LIB_EXTERN */ @@ -2001,7 +2025,7 @@ BoundBox *object_get_boundbox(Object *ob) BoundBox *bb= NULL; if(ob->type==OB_MESH) { - bb = mesh_get_bb(ob->data); + bb = mesh_get_bb(ob); } else if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) { bb= ( (Curve *)ob->data )->bb; @@ -2063,7 +2087,7 @@ void minmax_object(Object *ob, float *min, float *max) me= get_mesh(ob); if(me) { - bb = *mesh_get_bb(me); + bb = *mesh_get_bb(ob); for(a=0; a<8; a++) { Mat4MulVecfl(ob->obmat, bb.vec[a]); diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 4fbe714d45c..154ca9a5716 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -56,6 +56,7 @@ #include "BLI_kdtree.h" #include "BLI_linklist.h" #include "BLI_rand.h" +#include "BLI_threads.h" #include "BKE_anim.h" @@ -75,6 +76,7 @@ #include "BKE_depsgraph.h" #include "BKE_bad_level_calls.h" #include "BKE_modifier.h" +#include "BKE_mesh.h" #include "blendef.h" #include "RE_render_ext.h" @@ -299,6 +301,27 @@ void psys_free_path_cache(ParticleSystem *psys) } free_child_path_cache(psys); } +void psys_free_render_memory(Object *ob, ParticleSystem *psys) +{ + ParticleSystemModifierData *psmd; + + /* this is a bad function, but saves a lot of memory rendering. + * particles should really be generated on the fly with render + * settings! */ + psys_free_path_cache(psys); + + if(psys->child){ + MEM_freeN(psys->child); + psys->child=0; + psys->totchild=0; + } + + psmd= psys_get_modifier(ob, psys); + psmd->flag &= ~eParticleSystemFlag_psys_updated; + + psys->recalc |= PSYS_ALLOC|PSYS_DISTR; + //DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); +} /* free everything */ void psys_free(Object *ob, ParticleSystem * psys) { @@ -395,12 +418,13 @@ static void interpolate_particle(short type, ParticleKey keys[4], float dt, Part /* Particles on a dm */ /************************************************/ /* interpolate a location on a face based on face coordinates */ -void psys_interpolate_face(MVert *mvert, MFace *mface, MTFace *tface, float *w, float *vec, float *nor, float *utan, float *vtan){ +void psys_interpolate_face(MVert *mvert, MFace *mface, MTFace *tface, float (*orcodata)[3], float *w, float *vec, float *nor, float *utan, float *vtan, float *orco,float *ornor){ float *v1=0, *v2=0, *v3=0, *v4=0; float e1[3],e2[3],s1,s2,t1,t2; float *uv1, *uv2, *uv3, *uv4; float n1[3], n2[3], n3[3], n4[3]; float tuv[4][2]; + float *o1, *o2, *o3, *o4; v1= (mvert+mface->v1)->co; v2= (mvert+mface->v2)->co; @@ -493,6 +517,37 @@ void psys_interpolate_face(MVert *mvert, MFace *mface, MTFace *tface, float *w, utan[1] = (t1*e2[1] - t2*e1[1]); utan[2] = (t1*e2[2] - t2*e1[2]); } + + if(orco) { + if(orcodata) { + o1= orcodata[mface->v1]; + o2= orcodata[mface->v2]; + o3= orcodata[mface->v3]; + + if(mface->v4) { + o4= orcodata[mface->v4]; + orco[0]= w[0]*o1[0] + w[1]*o2[0] + w[2]*o3[0] + w[3]*o4[0]; + orco[1]= w[0]*o1[1] + w[1]*o2[1] + w[2]*o3[1] + w[3]*o4[1]; + orco[2]= w[0]*o1[2] + w[1]*o2[2] + w[2]*o3[2] + w[3]*o4[2]; + + if(ornor) + CalcNormFloat4(o1, o2, o3, o4, ornor); + } + else { + orco[0]= w[0]*o1[0] + w[1]*o2[0] + w[2]*o3[0]; + orco[1]= w[0]*o1[1] + w[1]*o2[1] + w[2]*o3[1]; + orco[2]= w[0]*o1[2] + w[1]*o2[2] + w[2]*o3[2]; + + if(ornor) + CalcNormFloat(o1, o2, o3, ornor); + } + } + else { + VECCOPY(orco, vec); + if(ornor) + VECCOPY(ornor, nor); + } + } } void psys_interpolate_uvs(MTFace *tface, int quad, float *w, float *uvco){ float v10= tface->uv[0][0]; @@ -634,8 +689,10 @@ int psys_particle_dm_face_lookup(Object *ob, DerivedMesh *dm, int index, float * /* interprets particle data to get a point on a mesh in object space */ #define PARTICLE_ERROR(_nor, _vec) _vec[0]=_vec[1]=_vec[2]=0.0; if(_nor){ _nor[0]=_nor[1]=0.0; _nor[2]=1.0; } -void psys_particle_on_dm(Object *ob, DerivedMesh *dm, int from, int index, int index_dmcache, float *fw, float foffset, float *vec, float *nor, float *utan, float *vtan) +void psys_particle_on_dm(Object *ob, DerivedMesh *dm, int from, int index, int index_dmcache, float *fw, float foffset, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor) { + float (*orcodata)[3] = dm->getVertDataArray(dm, CD_ORCO); + if(index < 0){ /* 'no dm' error has happened! */ PARTICLE_ERROR(nor, vec); return; @@ -656,6 +713,12 @@ void psys_particle_on_dm(Object *ob, DerivedMesh *dm, int from, int index, int i dm->getVertNo(dm,index,nor); Normalize(nor); } + if(orco) + VECCOPY(orco, orcodata[index]) + if(ornor) { + dm->getVertNo(dm,index,nor); + Normalize(nor); + } } else { /* PART_FROM_FACE / PART_FROM_VOLUME */ MFace *mface; @@ -678,7 +741,7 @@ void psys_particle_on_dm(Object *ob, DerivedMesh *dm, int from, int index, int i } if(from==PART_FROM_VOLUME){ - psys_interpolate_face(mvert,mface,mtface,fw,vec,temp1,utan,vtan); + psys_interpolate_face(mvert,mface,mtface,orcodata,fw,vec,temp1,utan,vtan,orco,ornor); if(nor) VECCOPY(nor,temp1); Normalize(temp1); @@ -686,7 +749,7 @@ void psys_particle_on_dm(Object *ob, DerivedMesh *dm, int from, int index, int i VECADD(vec,vec,temp1); } else - psys_interpolate_face(mvert,mface,mtface,fw,vec,nor,utan,vtan); + psys_interpolate_face(mvert,mface,mtface,orcodata,fw,vec,nor,utan,vtan,orco,ornor); } } else { /* Need to support constructive modifiers, this is a bit more tricky @@ -739,7 +802,7 @@ void psys_particle_on_dm(Object *ob, DerivedMesh *dm, int from, int index, int i /* we need to modify the original weights to become weights for * the derived mesh face */ psys_origspace_to_w(osface, mface->v4, fw, fw_mod); - psys_interpolate_face(mvert,mface,mtface,fw_mod,vec,nor,utan,vtan); + psys_interpolate_face(mvert,mface,mtface,orcodata,fw_mod,vec,nor,utan,vtan,orco,ornor); } else { /* TODO PARTICLE - support verts and volume */ @@ -768,7 +831,7 @@ ParticleSystemModifierData *psys_get_modifier(Object *ob, ParticleSystem *psys) /* Particles on a shape */ /************************************************/ /* ready for future use */ -void psys_particle_on_shape(int distr, int index, float *fuv, float *vec, float *nor, float *utan, float *vtan) +void psys_particle_on_shape(int distr, int index, float *fuv, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor) { /* TODO */ float zerovec[3]={0.0f,0.0f,0.0f}; @@ -784,11 +847,17 @@ void psys_particle_on_shape(int distr, int index, float *fuv, float *vec, float if(vtan){ VECCOPY(vtan,zerovec); } + if(orco){ + VECCOPY(orco,zerovec); + } + if(ornor){ + VECCOPY(ornor,zerovec); + } } /************************************************/ /* Particles on emitter */ /************************************************/ -void psys_particle_on_emitter(Object *ob, ParticleSystemModifierData *psmd, int from, int index, int index_dmcache, float *fuv, float foffset, float *vec, float *nor, float *utan, float *vtan){ +void psys_particle_on_emitter(Object *ob, ParticleSystemModifierData *psmd, int from, int index, int index_dmcache, float *fuv, float foffset, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor){ if(psmd){ if(psmd->psys->part->distr==PART_DISTR_GRID){ if(vec){ @@ -797,10 +866,10 @@ void psys_particle_on_emitter(Object *ob, ParticleSystemModifierData *psmd, int return; } /* we cant use the num_dmcache */ - psys_particle_on_dm(ob, psmd->dm,from,index,index_dmcache,fuv,foffset,vec,nor,utan,vtan); + psys_particle_on_dm(ob, psmd->dm,from,index,index_dmcache,fuv,foffset,vec,nor,utan,vtan,orco,ornor); } else - psys_particle_on_shape(from,index,fuv,vec,nor,utan,vtan); + psys_particle_on_shape(from,index,fuv,vec,nor,utan,vtan,orco,ornor); } /************************************************/ @@ -1195,41 +1264,33 @@ static void do_rough_end(float *loc, float t, float fac, float shape, ParticleKe VECADD(state->co,state->co,rough); } -static int check_path_length(int k, int p, ParticleCacheKey **cache, ParticleCacheKey *state, float length, float *dvec) +static int check_path_length(int k, ParticleCacheKey *keys, ParticleCacheKey *state, float max_length, float *cur_length, float length, float *dvec) { - static float max_length = 1.0, cur_length = 0.0; - - if(k) { - if(cur_length + length > max_length){ - //if(p<totparent){ - // if(k<=(int)cache[totpart+p]->time){ - // /* parents need to be calculated fully first so that they don't mess up their children */ - // /* we'll make a note of where we got to though so that they're easy to finish later */ - // state->time=(max_length-cur_length)/length; - // cache[totpart+p]->time=(float)k; - // } - //} - //else{ - VecMulf(dvec, (max_length - cur_length) / length); - VECADD(state->co, (state - 1)->co, dvec); - cache[p]->steps = k; - /* something over the maximum step value */ - return k=100000; - //} - } - else { - cur_length+=length; - } + if(*cur_length + length > max_length){ + //if(p<totparent){ + // if(k<=(int)cache[totpart+p]->time){ + // /* parents need to be calculated fully first so that they don't mess up their children */ + // /* we'll make a note of where we got to though so that they're easy to finish later */ + // state->time=(max_length-*cur_length)/length; + // cache[totpart+p]->time=(float)k; + // } + //} + //else{ + VecMulf(dvec, (max_length - *cur_length) / length); + VECADD(state->co, (state - 1)->co, dvec); + keys->steps = k; + /* something over the maximum step value */ + return k=100000; + //} } - else {/* reset signal */ - max_length=length; - cur_length=0.0; + else { + *cur_length+=length; + return k; } - return k; } -static void finalize_path_length(int p, ParticleCacheKey **cache) +static void finalize_path_length(ParticleCacheKey *keys) { - ParticleCacheKey *state = cache[p]; + ParticleCacheKey *state = keys; float dvec[3]; state += state->steps; @@ -1279,64 +1340,74 @@ void psys_find_parents(Object *ob, ParticleSystemModifierData *psmd, ParticleSys KDTree *tree; ChildParticle *cpa; int p, totparent,totchild=psys->totchild; - float co[3], *orcos=0; + float co[3], orco[3]; int from=PART_FROM_FACE; totparent=(int)(totchild*part->parents*0.3); tree=BLI_kdtree_new(totparent); for(p=0,cpa=psys->child; p<totparent; p++,cpa++){ - psys_particle_on_emitter(ob,psmd,from,cpa->num,-1,cpa->fuv,cpa->foffset,co,0,0,0); - BLI_kdtree_insert(tree, p, co, NULL); + psys_particle_on_emitter(ob,psmd,from,cpa->num,-1,cpa->fuv,cpa->foffset,co,0,0,0,orco,0); + BLI_kdtree_insert(tree, p, orco, NULL); } BLI_kdtree_balance(tree); for(; p<totchild; p++,cpa++){ - psys_particle_on_emitter(ob,psmd,from,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co,0,0,0); - cpa->parent=BLI_kdtree_find_nearest(tree, co, NULL, NULL); + psys_particle_on_emitter(ob,psmd,from,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co,0,0,0,orco,0); + cpa->parent=BLI_kdtree_find_nearest(tree, orco, NULL, NULL); } BLI_kdtree_free(tree); - if(orcos) - MEM_freeN(orcos); } -void psys_cache_child_paths(Object *ob, ParticleSystem *psys, float cfra, int editupdate) + +static void get_strand_normal(Material *ma, float *surfnor, float surfdist, float *nor) { - ParticleSettings *part = psys->part; - ParticleEditSettings *pset = &G.scene->toolsettings->particle; - ParticleSystemModifierData *psmd = psys_get_modifier(ob,psys); - ParticleData *pa; - ChildParticle *cpa; - ParticleCacheKey **cache = psys->childcache, **pcache = psys->pathcache; - ParticleCacheKey *tcache, *state, *par=0, *key[4]; - ParticleTexture ptex; - Material *ma = give_current_material(ob, part->omat); + float cross[3], nstrand[3], vnor[3], blend; + + if(!((ma->mode & MA_STR_SURFDIFF) || (ma->strand_surfnor > 0.0f))) + return; - float length, pa_length = 1.0, pa_clump = 1.0, pa_kink = 1.0; - float pa_rough1 = 1.0, pa_rough2 = 1.0, pa_roughe = 1.0; - float t, rough_t; - float dvec[3], orco[3], ornor[3], imat[4][4]; - float *vg_length = 0, *vg_clump = 0, *vg_kink = 0; - float *vg_rough1 = 0, *vg_rough2 = 0, *vg_roughe = 0; - float cpa_1st[3]; + if(ma->mode & MA_STR_SURFDIFF) { + Crossf(cross, surfnor, nor); + Crossf(nstrand, nor, cross); - int k, i, totparent=0, between=0, edit=0; - int steps = (int)pow(2.0,(double)part->draw_step); - int totchild = psys->totchild; - int cpa_num; short cpa_from; + blend= INPR(nstrand, surfnor); + CLAMP(blend, 0.0f, 1.0f); - if(part->flag & PART_ANIM_BRANCHING) - BLI_srandom(31415926 + psys->seed + (int)cfra); + VecLerpf(vnor, nstrand, surfnor, blend); + Normalize(vnor); + } else - BLI_srandom(31415926 + psys->seed); + VECCOPY(vnor, nor) + + if(ma->strand_surfnor > 0.0f) { + if(ma->strand_surfnor > surfdist) { + blend= (ma->strand_surfnor - surfdist)/ma->strand_surfnor; + VecLerpf(vnor, vnor, surfnor, blend); + Normalize(vnor); + } + } + + VECCOPY(nor, vnor); +} + +int psys_threads_init_path(ParticleThread *threads, float cfra, int editupdate) +{ + ParticleThreadContext *ctx= threads[0].ctx; + Object *ob= ctx->ob; + ParticleSystem *psys= ctx->psys; + ParticleSettings *part = psys->part; + ParticleEditSettings *pset = &G.scene->toolsettings->particle; + int totparent=0, between=0; + int steps = (int)pow(2.0,(double)part->draw_step); + int totchild = psys->totchild; + int i, seed, totthread= threads[0].tot; /*---start figuring out what is actually wanted---*/ - if(psys_in_edit_mode(psys)){ + if(psys_in_edit_mode(psys)) if(G.rendering==0 && (psys->edit==NULL || pset->flag & PE_SHOW_CHILD)==0) totchild=0; - edit=1; - } if(totchild && part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){ totparent=(int)(totchild*part->parents*0.3); @@ -1346,39 +1417,44 @@ void psys_cache_child_paths(Object *ob, ParticleSystem *psys, float cfra, int ed if(G.rendering) steps=(int)pow(2.0,(double)part->ren_step); - else if(part->flag & PART_CHILD_RENDER){ - totchild=0; - } else{ totchild=(int)((float)totchild*(float)part->disp/100.0f); totparent=MIN2(totparent,totchild); } - if(totchild==0) return; + if(totchild==0) return 0; - if(editupdate && psys->childcache && !(part->flag & PART_BRANCHING) && totchild == psys->totchildcache) { - cache = psys->childcache; + /* init random number generator */ + if(ctx->psys->part->flag & PART_ANIM_BRANCHING) + seed= 31415926 + ctx->psys->seed + (int)cfra; + else + seed= 31415926 + ctx->psys->seed; + + if(part->flag & PART_BRANCHING || ctx->editupdate || totchild < 10000) + totthread= 1; + + for(i=0; i<totthread; i++) { + threads[i].rng_path= rng_new(seed); + threads[i].tot= totthread; } - else { - /* clear out old and create new empty path cache */ - free_child_path_cache(psys); - cache = psys->childcache = MEM_callocN(totchild*sizeof(void *), "Child path cache array"); - tcache = MEM_callocN(totchild * (steps + 1) * sizeof(ParticleCacheKey), "Child path cache"); - for(i=0; i<totchild; i++) - cache[i] = tcache + i * (steps + 1); - } + /* fill context values */ + ctx->between= between; + ctx->steps= steps; + ctx->totchild= totchild; + ctx->totparent= totparent; + ctx->cfra= cfra; - psys->lattice = psys_get_lattice(ob,psys); + psys->lattice = psys_get_lattice(ob, psys); /* cache all relevant vertex groups if they exist */ if(part->from!=PART_FROM_PARTICLE){ - vg_length = psys_cache_vgroup(psmd->dm,psys,PSYS_VG_LENGTH); - vg_clump = psys_cache_vgroup(psmd->dm,psys,PSYS_VG_CLUMP); - vg_kink = psys_cache_vgroup(psmd->dm,psys,PSYS_VG_KINK); - vg_rough1 = psys_cache_vgroup(psmd->dm,psys,PSYS_VG_ROUGH1); - vg_rough2 = psys_cache_vgroup(psmd->dm,psys,PSYS_VG_ROUGH2); - vg_roughe = psys_cache_vgroup(psmd->dm,psys,PSYS_VG_ROUGHE); + ctx->vg_length = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_LENGTH); + ctx->vg_clump = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_CLUMP); + ctx->vg_kink = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_KINK); + ctx->vg_rough1 = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_ROUGH1); + ctx->vg_rough2 = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_ROUGH2); + ctx->vg_roughe = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_ROUGHE); } /* set correct ipo timing */ @@ -1387,294 +1463,376 @@ void psys_cache_child_paths(Object *ob, ParticleSystem *psys, float cfra, int ed execute_ipo((ID *)part, part->ipo); } - Mat4Invert(imat,ob->obmat); - - for(i=0,cpa=psys->child; i<totchild; i++, cpa++){ - int guided=0; - float *cpa_fuv=0; - float branch_begin=0.0f, branch_end=0.0f, branch_prob=0.0f; - float branchfac, rough_rand=0.0f; - - if(part->flag & PART_BRANCHING) { - branch_begin=BLI_frand(); - branch_end=branch_begin+(1.0f-branch_begin)*BLI_frand(); - branch_prob=BLI_frand(); - rough_rand=BLI_frand(); - } - - if(i<psys->totpart){ - branch_begin=0.0f; - branch_end=1.0f; - branch_prob=0.0f; - } + return 1; +} - if(between){ - int w, needupdate; - float foffset; +/* note: this function must be thread safe, except for branching! */ +void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, ParticleCacheKey *keys, int i) +{ + ParticleThreadContext *ctx= thread->ctx; + Object *ob= ctx->ob; + ParticleSystem *psys = ctx->psys; + ParticleSettings *part = psys->part; + ParticleCacheKey **cache= psys->childcache; + ParticleCacheKey **pcache= psys->pathcache; + ParticleCacheKey *state, *par = NULL, *key[4]; + ParticleData *pa; + ParticleTexture ptex; + float *cpa_fuv=0; + float co[3], orco[3], ornor[3], t, rough_t, cpa_1st[3], dvec[3]; + float branch_begin, branch_end, branch_prob, branchfac, rough_rand; + float pa_rough1, pa_rough2, pa_roughe; + float length, pa_length, pa_clump, pa_kink; + float max_length = 1.0f, cur_length = 0.0f; + int k, cpa_num, guided=0; + short cpa_from; + + if(part->flag & PART_BRANCHING) { + branch_begin=rng_getFloat(thread->rng_path); + branch_end=branch_begin+(1.0f-branch_begin)*rng_getFloat(thread->rng_path); + branch_prob=rng_getFloat(thread->rng_path); + rough_rand=rng_getFloat(thread->rng_path); + } + else { + branch_begin= 0.0f; + branch_end= 0.0f; + branch_prob= 0.0f; + rough_rand= 0.0f; + } - if(editupdate && !(part->flag & PART_BRANCHING)) { - needupdate= 0; - w= 0; - while(w<4 && cpa->pa[w]>=0) { - if(psys->particles[cpa->pa[w]].flag & PARS_EDIT_RECALC) { - needupdate= 1; - break; - } - w++; - } + if(i<psys->totpart){ + branch_begin=0.0f; + branch_end=1.0f; + branch_prob=0.0f; + } - if(!needupdate) - continue; - else - memset(cache[i], 0, sizeof(*cache[i])*(steps+1)); - } + if(ctx->between){ + int w, needupdate; + float foffset; - /* get parent paths */ + if(ctx->editupdate && !(part->flag & PART_BRANCHING)) { + needupdate= 0; w= 0; - while(w<4 && cpa->pa[w]>=0){ - key[w] = pcache[cpa->pa[w]]; + while(w<4 && cpa->pa[w]>=0) { + if(psys->particles[cpa->pa[w]].flag & PARS_EDIT_RECALC) { + needupdate= 1; + break; + } w++; } - /* get the original coordinates (orco) for texture usage */ - cpa_num = cpa->num; - - foffset= cpa->foffset; - if(part->childtype == PART_CHILD_FACES) - foffset = -(2.0f + part->childspread); - cpa_fuv = cpa->fuv; - cpa_from = PART_FROM_FACE; + if(!needupdate) + return; + else + memset(keys, 0, sizeof(*keys)*(ctx->steps+1)); + } - psys_particle_on_emitter(ob,psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa->fuv,foffset,orco,ornor,0,0); + /* get parent paths */ + w= 0; + while(w<4 && cpa->pa[w]>=0){ + key[w] = pcache[cpa->pa[w]]; + w++; + } - /* we need to save the actual root position of the child for positioning it accurately to the surface of the emitter */ - VECCOPY(cpa_1st,orco); - Mat4MulVecfl(ob->obmat,cpa_1st); + /* get the original coordinates (orco) for texture usage */ + cpa_num = cpa->num; + + foffset= cpa->foffset; + if(part->childtype == PART_CHILD_FACES) + foffset = -(2.0f + part->childspread); + cpa_fuv = cpa->fuv; + cpa_from = PART_FROM_FACE; - pa=0; + psys_particle_on_emitter(ob,ctx->psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa->fuv,foffset,co,ornor,0,0,orco,0); + + /* we need to save the actual root position of the child for positioning it accurately to the surface of the emitter */ + VECCOPY(cpa_1st,co); + Mat4MulVecfl(ob->obmat,cpa_1st); + + pa=0; + } + else{ + if(ctx->editupdate && !(part->flag & PART_BRANCHING)) { + if(!(psys->particles[cpa->parent].flag & PARS_EDIT_RECALC)) + return; + + memset(keys, 0, sizeof(*keys)*(ctx->steps+1)); } - else{ - if(editupdate && !(part->flag & PART_BRANCHING)) { - if(!(psys->particles[cpa->parent].flag & PARS_EDIT_RECALC)) - continue; - memset(cache[i], 0, sizeof(*cache[i])*(steps+1)); - } + /* get the parent path */ + key[0]=pcache[cpa->parent]; - /* get the parent path */ - key[0]=pcache[cpa->parent]; + /* get the original coordinates (orco) for texture usage */ + pa=psys->particles+cpa->parent; - /* get the original coordinates (orco) for texture usage */ - pa=psys->particles+cpa->parent; + cpa_from=part->from; + cpa_num=pa->num; + cpa_fuv=pa->fuv; - cpa_from=part->from; - cpa_num=pa->num; - cpa_fuv=pa->fuv; + psys_particle_on_emitter(ob,ctx->psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa_fuv,pa->foffset,co,ornor,0,0,orco,0); + } - psys_particle_on_emitter(ob,psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa_fuv,pa->foffset,orco,ornor,0,0); - } + keys->steps = ctx->steps; - cache[i]->steps = steps; + /* correct child ipo timing */ + if((part->flag&PART_ABS_TIME)==0 && part->ipo){ + float dsta=part->end-part->sta; + calc_ipo(part->ipo, 100.0f*(ctx->cfra-(part->sta+dsta*cpa->rand[1]))/(part->lifetime*(1.0f - part->randlife*cpa->rand[0]))); + execute_ipo((ID *)part, part->ipo); + } - /* correct child ipo timing */ - if((part->flag&PART_ABS_TIME)==0 && part->ipo){ - float dsta=part->end-part->sta; - calc_ipo(part->ipo, 100.0f*(cfra-(part->sta+dsta*cpa->rand[1]))/(part->lifetime*(1.0f - part->randlife*cpa->rand[0]))); - execute_ipo((ID *)part, part->ipo); - } + /* get different child parameters from textures & vgroups */ + ptex.length=part->length*(1.0f - part->randlength*cpa->rand[0]); + ptex.clump=1.0; + ptex.kink=1.0; + ptex.rough= 1.0; - /* get different child parameters from textures & vgroups */ - ptex.length=part->length*(1.0f - part->randlength*cpa->rand[0]); - ptex.clump=1.0; - ptex.kink=1.0; + get_cpa_texture(ctx->dm,ctx->ma,cpa_num,cpa_fuv,orco,&ptex, + MAP_PA_LENGTH|MAP_PA_CLUMP|MAP_PA_KINK|MAP_PA_ROUGH); + + pa_length=ptex.length; + pa_clump=ptex.clump; + pa_kink=ptex.kink; + pa_rough1=ptex.rough; + pa_rough2=ptex.rough; + pa_roughe=ptex.rough; + + if(ctx->vg_length) + pa_length*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_length); + if(ctx->vg_clump) + pa_clump*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_clump); + if(ctx->vg_kink) + pa_kink*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_kink); + if(ctx->vg_rough1) + pa_rough1*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_rough1); + if(ctx->vg_rough2) + pa_rough2*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_rough2); + if(ctx->vg_roughe) + pa_roughe*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_roughe); + + /* create the child path */ + for(k=0,state=keys; k<=ctx->steps; k++,state++){ + t=(float)k/(float)ctx->steps; + + if(ctx->between){ + int w=0; - get_cpa_texture(psmd->dm,ma,cpa_num,cpa_fuv,orco,&ptex,MAP_PA_CACHE); - - pa_length=ptex.length; - pa_clump=ptex.clump; - pa_kink=ptex.kink; - pa_rough1=1.0; - pa_rough2=1.0; - pa_roughe=1.0; - - if(vg_length) - pa_length*=psys_interpolate_value_from_verts(psmd->dm,cpa_from,cpa_num,cpa_fuv,vg_length); - if(vg_clump) - pa_clump*=psys_interpolate_value_from_verts(psmd->dm,cpa_from,cpa_num,cpa_fuv,vg_clump); - if(vg_kink) - pa_kink*=psys_interpolate_value_from_verts(psmd->dm,cpa_from,cpa_num,cpa_fuv,vg_kink); - if(vg_rough1) - pa_rough1*=psys_interpolate_value_from_verts(psmd->dm,cpa_from,cpa_num,cpa_fuv,vg_rough1); - if(vg_rough2) - pa_rough2*=psys_interpolate_value_from_verts(psmd->dm,cpa_from,cpa_num,cpa_fuv,vg_rough2); - if(vg_roughe) - pa_roughe*=psys_interpolate_value_from_verts(psmd->dm,cpa_from,cpa_num,cpa_fuv,vg_roughe); - - /* create the child path */ - for(k=0,state=cache[i]; k<=steps; k++,state++){ - t=(float)k/(float)steps; - - if(between){ - int w=0; - - state->co[0] = state->co[1] = state->co[2] = 0.0f; - state->vel[0] = state->vel[1] = state->vel[2] = 0.0f; - - //QUATCOPY(state->rot,key[0]->rot); - - /* child position is the weighted sum of parent positions */ - while(w<4 && cpa->pa[w]>=0){ - state->co[0] += cpa->w[w] * key[w]->co[0]; - state->co[1] += cpa->w[w] * key[w]->co[1]; - state->co[2] += cpa->w[w] * key[w]->co[2]; - - state->vel[0] += cpa->w[w] * key[w]->vel[0]; - state->vel[1] += cpa->w[w] * key[w]->vel[1]; - state->vel[2] += cpa->w[w] * key[w]->vel[2]; - key[w]++; - w++; - } - if(k==0){ - /* calculate the offset between actual child root position and first position interpolated from parents */ - VECSUB(cpa_1st,cpa_1st,state->co); - } - /* apply offset for correct positioning */ - VECADD(state->co,state->co,cpa_1st); - } - else{ - /* offset the child from the parent position */ - offset_child(cpa, (ParticleKey*)key[0], (ParticleKey*)state, part->childflat, part->childrad); + state->co[0] = state->co[1] = state->co[2] = 0.0f; + state->vel[0] = state->vel[1] = state->vel[2] = 0.0f; - key[0]++; - } + //QUATCOPY(state->rot,key[0]->rot); - if(totparent){ - if(i>=totparent) - par = cache[cpa->parent] + k; - else - par=0; + /* child position is the weighted sum of parent positions */ + while(w<4 && cpa->pa[w]>=0){ + state->co[0] += cpa->w[w] * key[w]->co[0]; + state->co[1] += cpa->w[w] * key[w]->co[1]; + state->co[2] += cpa->w[w] * key[w]->co[2]; + + state->vel[0] += cpa->w[w] * key[w]->vel[0]; + state->vel[1] += cpa->w[w] * key[w]->vel[1]; + state->vel[2] += cpa->w[w] * key[w]->vel[2]; + key[w]++; + w++; } - else if(cpa->parent>=0){ - par=pcache[cpa->parent]+k; + if(k==0){ + /* calculate the offset between actual child root position and first position interpolated from parents */ + VECSUB(cpa_1st,cpa_1st,state->co); } + /* apply offset for correct positioning */ + VECADD(state->co,state->co,cpa_1st); + } + else{ + /* offset the child from the parent position */ + offset_child(cpa, (ParticleKey*)key[0], (ParticleKey*)state, part->childflat, part->childrad); + + key[0]++; + } - /* apply different deformations to the child path */ - if(part->flag & PART_CHILD_GUIDE) - guided = do_guide((ParticleKey*)state, i, t, &(psys->effectors)); //safe to cast, since only co and vel are used + if(ctx->totparent){ + if(i>=ctx->totparent) + /* this is not threadsafe, but should only happen for + * branching particles particles, which are not threaded */ + par = cache[cpa->parent] + k; + else + par=0; + } + else if(cpa->parent>=0){ + par=pcache[cpa->parent]+k; + } - if(guided==0){ - if(part->kink) - do_prekink((ParticleKey*)state, (ParticleKey*)par, par->rot, t, - part->kink_freq * pa_kink, part->kink_shape, part->kink_amp, part->kink, part->kink_axis, ob->obmat); - - do_clump((ParticleKey*)state, (ParticleKey*)par, t, part->clumpfac, part->clumppow, pa_clump); + /* apply different deformations to the child path */ + if(part->flag & PART_CHILD_GUIDE) + guided = do_guide((ParticleKey*)state, i, t, &(psys->effectors)); //safe to cast, since only co and vel are used + + if(guided==0){ + if(part->kink) + do_prekink((ParticleKey*)state, (ParticleKey*)par, par->rot, t, + part->kink_freq * pa_kink, part->kink_shape, part->kink_amp, part->kink, part->kink_axis, ob->obmat); + + do_clump((ParticleKey*)state, (ParticleKey*)par, t, part->clumpfac, part->clumppow, pa_clump); + + if(part->kink) + do_postkink((ParticleKey*)state, (ParticleKey*)par, par->rot, t, + part->kink_freq * pa_kink, part->kink_shape, part->kink_amp, part->kink, part->kink_axis, ob->obmat); + } - if(part->kink) - do_postkink((ParticleKey*)state, (ParticleKey*)par, par->rot, t, - part->kink_freq * pa_kink, part->kink_shape, part->kink_amp, part->kink, part->kink_axis, ob->obmat); - } + if(part->flag & PART_BRANCHING && ctx->between == 0 && part->flag & PART_ANIM_BRANCHING) + rough_t = t * rough_rand; + else + rough_t = t; - if(part->flag & PART_BRANCHING && between == 0 && part->flag & PART_ANIM_BRANCHING) - rough_t = t * rough_rand; - else - rough_t = t; + if(part->rough1 != 0.0 && pa_rough1 != 0.0) + do_rough(orco, rough_t, pa_rough1*part->rough1, part->rough1_size, 0.0, (ParticleKey*)state); - if(part->rough1 != 0.0 && pa_rough1 != 0.0) - do_rough(orco, rough_t, pa_rough1*part->rough1, part->rough1_size, 0.0, (ParticleKey*)state); + if(part->rough2 != 0.0 && pa_rough2 != 0.0) + do_rough(cpa->rand, rough_t, pa_rough2*part->rough2, part->rough2_size, part->rough2_thres, (ParticleKey*)state); - if(part->rough2 != 0.0 && pa_rough2 != 0.0) - do_rough(cpa->rand, rough_t, pa_rough2*part->rough2, part->rough2_size, part->rough2_thres, (ParticleKey*)state); + if(part->rough_end != 0.0 && pa_roughe != 0.0) + do_rough_end(cpa->rand, rough_t, pa_roughe*part->rough_end, part->rough_end_shape, (ParticleKey*)state, (ParticleKey*)par); - if(part->rough_end != 0.0 && pa_roughe != 0.0) - do_rough_end(cpa->rand, rough_t, pa_roughe*part->rough_end, part->rough_end_shape, (ParticleKey*)state, (ParticleKey*)par); + if(part->flag & PART_BRANCHING && ctx->between==0){ + if(branch_prob > part->branch_thres){ + branchfac=0.0f; + } + else{ + if(part->flag & PART_SYMM_BRANCHING){ + if(t < branch_begin || t > branch_end) + branchfac=0.0f; + else{ + if((t-branch_begin)/(branch_end-branch_begin)<0.5) + branchfac=2.0f*(t-branch_begin)/(branch_end-branch_begin); + else + branchfac=2.0f*(branch_end-t)/(branch_end-branch_begin); - if(part->flag & PART_BRANCHING && between==0){ - if(branch_prob > part->branch_thres){ - branchfac=0.0f; + CLAMP(branchfac,0.0f,1.0f); + } } else{ - if(part->flag & PART_SYMM_BRANCHING){ - if(t < branch_begin || t > branch_end) - branchfac=0.0f; - else{ - if((t-branch_begin)/(branch_end-branch_begin)<0.5) - branchfac=2.0f*(t-branch_begin)/(branch_end-branch_begin); - else - branchfac=2.0f*(branch_end-t)/(branch_end-branch_begin); - - CLAMP(branchfac,0.0f,1.0f); - } + if(t < branch_begin){ + branchfac=0.0f; } else{ - if(t < branch_begin){ - branchfac=0.0f; - } - else{ - branchfac=(t-branch_begin)/((1.0f-branch_begin)*0.5f); - CLAMP(branchfac,0.0f,1.0f); - } + branchfac=(t-branch_begin)/((1.0f-branch_begin)*0.5f); + CLAMP(branchfac,0.0f,1.0f); } } - - if(i<psys->totpart){ - VecLerpf(state->co, (pcache[i] + k)->co, state->co, branchfac); - } - else - VecLerpf(state->co, (cache[i - psys->totpart] + k)->co, state->co, branchfac); } - /* we have to correct velocity because of kink & clump */ - if(k>1){ - VECSUB((state-1)->vel,state->co,(state-2)->co); - VecMulf((state-1)->vel,0.5); - } - - /* check if path needs to be cut before actual end of data points */ - if(k){ - VECSUB(dvec,state->co,(state-1)->co); - if(part->flag&PART_ABS_LENGTH) - length=VecLength(dvec); - else - length=1.0f/(float)steps; + if(i<psys->totpart) + VecLerpf(state->co, (pcache[i] + k)->co, state->co, branchfac); + else + /* this is not threadsafe, but should only happen for + * branching particles particles, which are not threaded */ + VecLerpf(state->co, (cache[i - psys->totpart] + k)->co, state->co, branchfac); + } - k=check_path_length(k,i,cache,state,length,dvec); - } - else{ - /* initialize length calculation */ - if(part->flag&PART_ABS_LENGTH) - check_path_length(0,0,0,0,part->abslength*pa_length,0); - else - check_path_length(0,0,0,0,pa_length,0); - } + /* we have to correct velocity because of kink & clump */ + if(k>1){ + VECSUB((state-1)->vel,state->co,(state-2)->co); + VecMulf((state-1)->vel,0.5); + + if(ctx->ma && (part->draw & PART_DRAW_MAT_COL)) + get_strand_normal(ctx->ma, ornor, cur_length, (state-1)->vel); + } + + /* check if path needs to be cut before actual end of data points */ + if(k){ + VECSUB(dvec,state->co,(state-1)->co); + if(part->flag&PART_ABS_LENGTH) + length=VecLength(dvec); + else + length=1.0f/(float)ctx->steps; + + k=check_path_length(k,keys,state,max_length,&cur_length,length,dvec); + } + else{ + /* initialize length calculation */ + if(part->flag&PART_ABS_LENGTH) + max_length= part->abslength*pa_length; + else + max_length= pa_length; + + cur_length= 0.0f; + } - if(part->draw & PART_DRAW_MAT_COL) - VECCOPY(state->col, &ma->r) + if(ctx->ma && (part->draw & PART_DRAW_MAT_COL)) { + VECCOPY(state->col, &ctx->ma->r) + get_strand_normal(ctx->ma, ornor, cur_length, state->vel); } } + /* now let's finalise the interpolated parents that we might have left half done before */ - if(totchild) for(i=0,cpa=psys->child; i<totparent; i++, cpa++) - finalize_path_length(i,cache); - - if(vg_length) - MEM_freeN(vg_length); - if(vg_clump) - MEM_freeN(vg_clump); - if(vg_kink) - MEM_freeN(vg_kink); - if(vg_rough1) - MEM_freeN(vg_rough1); - if(vg_rough2) - MEM_freeN(vg_roughe); - if(vg_roughe) - MEM_freeN(vg_roughe); - - psys->totchildcache = totchild; - - if(psys->lattice){ - end_latt_deform(); - psys->lattice=0; + if(i<ctx->totparent) + finalize_path_length(keys); +} + +void *exec_child_path_cache(void *data) +{ + ParticleThread *thread= (ParticleThread*)data; + ParticleThreadContext *ctx= thread->ctx; + ParticleSystem *psys= ctx->psys; + ParticleCacheKey **cache= psys->childcache; + ChildParticle *cpa; + int i, totchild= ctx->totchild; + + cpa= psys->child + thread->num; + for(i=thread->num; i<totchild; i+=thread->tot, cpa+=thread->tot) + psys_thread_create_path(thread, cpa, cache[i], i); + + return 0; +} + +void psys_cache_child_paths(Object *ob, ParticleSystem *psys, float cfra, int editupdate) +{ + ParticleSettings *part = psys->part; + ParticleThread *pthreads; + ParticleThreadContext *ctx; + ParticleCacheKey **cache, *tcache; + ListBase threads; + int i, totchild, totparent, totthread; + + pthreads= psys_threads_create(ob, psys, G.scene->r.threads); + + if(!psys_threads_init_path(pthreads, cfra, editupdate)) { + psys_threads_free(pthreads); + return; + } + + ctx= pthreads[0].ctx; + totchild= ctx->totchild; + totparent= ctx->totparent; + + if(editupdate && psys->childcache && !(part->flag & PART_BRANCHING) && totchild == psys->totchildcache) { + cache = psys->childcache; } + else { + /* clear out old and create new empty path cache */ + free_child_path_cache(psys); + + cache = psys->childcache = MEM_callocN(totchild*sizeof(void *), "Child path cache array"); + tcache = MEM_callocN(totchild * (ctx->steps + 1) * sizeof(ParticleCacheKey), "Child path cache"); + for(i=0; i<totchild; i++) + cache[i] = tcache + i * (ctx->steps + 1); + + psys->totchildcache = totchild; + } + + totthread= pthreads[0].tot; + + if(totthread > 1) { + BLI_init_threads(&threads, exec_child_path_cache, totthread); + + for(i=0; i<totthread; i++) + BLI_insert_thread(&threads, &pthreads[i]); + + BLI_end_threads(&threads); + } + else + exec_child_path_cache(&pthreads[0]); + + psys_threads_free(pthreads); } + /* Calculates paths ready for drawing/rendering. */ /* -Usefull for making use of opengl vertex arrays for super fast strand drawing. */ /* -Makes child strands possible and creates them too into the cache. */ @@ -1753,7 +1911,7 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda psys->lattice = psys_get_lattice(ob, psys); ma= give_current_material(ob, psys->part->omat); - if(psys->part->draw & PART_DRAW_MAT_COL) + if(ma && (psys->part->draw & PART_DRAW_MAT_COL)) VECCOPY(col, &ma->r) /*---first main loop: create all actual particles' paths---*/ @@ -2083,33 +2241,59 @@ static void triatomat(float *v1, float *v2, float *v3, float (*uv)[2], float mat Crossf(mat[0], mat[1], mat[2]); } -static void psys_face_mat(DerivedMesh *dm, ParticleData *pa, float mat[][4]) +static void psys_face_mat(Object *ob, DerivedMesh *dm, ParticleData *pa, float mat[][4], int orco) { - float v1[3], v2[3], v3[3]; + float v[3][3]; MFace *mface; OrigSpaceFace *osface; + float (*orcodata)[3]; int i = pa->num_dmcache==DMCACHE_NOTFOUND ? pa->num : pa->num_dmcache; if (i==-1 || i >= dm->getNumFaces(dm)) { Mat4One(mat); return; } + mface=dm->getFaceData(dm,i,CD_MFACE); osface=dm->getFaceData(dm,i,CD_ORIGSPACE); - dm->getVertCo(dm,mface->v1,v1); - dm->getVertCo(dm,mface->v2,v2); - dm->getVertCo(dm,mface->v3,v3); + if(orco && (orcodata=dm->getVertDataArray(dm, CD_ORCO))) { + VECCOPY(v[0], orcodata[mface->v1]); + VECCOPY(v[1], orcodata[mface->v2]); + VECCOPY(v[2], orcodata[mface->v3]); + + /* ugly hack to use non-transformed orcos, since only those + * give symmetric results for mirroring in particle mode */ + transform_mesh_orco_verts(ob->data, v, 3, 1); + } + else { + dm->getVertCo(dm,mface->v1,v[0]); + dm->getVertCo(dm,mface->v2,v[1]); + dm->getVertCo(dm,mface->v3,v[2]); + } - triatomat(v1, v2, v3, (osface)? osface->uv: NULL, mat); + triatomat(v[0], v[1], v[2], (osface)? osface->uv: NULL, mat); } + void psys_mat_hair_to_object(Object *ob, DerivedMesh *dm, short from, ParticleData *pa, float hairmat[][4]) { float vec[3]; - psys_face_mat(dm, pa, hairmat); - psys_particle_on_dm(ob, dm, from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, vec, 0, 0, 0); + psys_face_mat(0, dm, pa, hairmat, 0); + psys_particle_on_dm(ob, dm, from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, vec, 0, 0, 0, 0, 0); VECCOPY(hairmat[3],vec); } +void psys_mat_hair_to_orco(Object *ob, DerivedMesh *dm, short from, ParticleData *pa, float hairmat[][4]) +{ + float vec[3], orco[3]; + + psys_face_mat(ob, dm, pa, hairmat, 1); + psys_particle_on_dm(ob, dm, from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, vec, 0, 0, 0, orco, 0); + + /* see psys_face_mat for why this function is called */ + transform_mesh_orco_verts(ob->data, orco, 1, 1); + VECCOPY(hairmat[3],orco); +} + /* void psys_key_to_geometry(DerivedMesh *dm, ParticleData *pa, ParticleKey *key) { @@ -2162,7 +2346,7 @@ void psys_vec_rot_to_face(DerivedMesh *dm, ParticleData *pa, float *vec)//to_geo { float mat[4][4]; - psys_face_mat(dm, pa, mat); + psys_face_mat(0, dm, pa, mat, 0); Mat4Transp(mat); /* cheap inverse for rotation matrix */ Mat4Mul3Vecfl(mat, vec); } @@ -2260,6 +2444,7 @@ static void default_particle_settings(ParticleSettings *part) part->childsize=1.0; part->child_nbr=10; + part->ren_child_nbr=100; part->childrad=0.2f; part->childflat=0.0f; part->clumppow=0.0f; @@ -2451,19 +2636,22 @@ static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index, float if((event & mtex->pmapto) & MAP_PA_CLUMP) ptex->clump= texture_value_blend(value,ptex->clump,value,var,blend,neg & MAP_PA_CLUMP); if((event & mtex->pmapto) & MAP_PA_KINK) - ptex->kink= texture_value_blend(value,ptex->kink,value,var,blend,neg & MAP_PA_CLUMP); + ptex->kink= texture_value_blend(value,ptex->kink,value,var,blend,neg & MAP_PA_KINK); + if((event & mtex->pmapto) & MAP_PA_ROUGH) + ptex->rough= texture_value_blend(value,ptex->rough,value,var,blend,neg & MAP_PA_ROUGH); } } - CLAMP(ptex->time,0.0,1.0); - CLAMP(ptex->length,0.0,1.0); - CLAMP(ptex->clump,0.0,1.0); - CLAMP(ptex->kink,0.0,1.0); + if(event & MAP_PA_TIME) { CLAMP(ptex->time,0.0,1.0); } + if(event & MAP_PA_LENGTH) { CLAMP(ptex->length,0.0,1.0); } + if(event & MAP_PA_CLUMP) { CLAMP(ptex->clump,0.0,1.0); } + if(event & MAP_PA_KINK) { CLAMP(ptex->kink,0.0,1.0); } + if(event & MAP_PA_ROUGH) { CLAMP(ptex->rough,0.0,1.0); } } void psys_get_texture(Object *ob, Material *ma, ParticleSystemModifierData *psmd, ParticleSystem *psys, ParticleData *pa, ParticleTexture *ptex, int event) { MTex *mtex; int m; - float value, rgba[4], texco[3]; + float value, rgba[4], co[3], texco[3]; int setvars=0; if(ma) for(m=0; m<MAX_MTEX; m++){ @@ -2491,12 +2679,14 @@ void psys_get_texture(Object *ob, Material *ma, ParticleSystemModifierData *psmd else //psys_particle_on_emitter(ob,psmd,psys->part->from,pa->num,pa->fuv,pa->foffset,texco,0,0,0); /* <jahka> anyways I think it will be too small a difference to notice, so psys_get_texture should only know about the original mesh structure.. no dm needed anywhere */ - psys_particle_on_emitter(ob,psmd,psys->part->from,pa->num,-1,pa->fuv,pa->foffset,texco,0,0,0); + /* <brecht> the code only does dm based lookup now, so passing num_dmcache anyway to avoid^ + * massive slowdown here */ + psys_particle_on_emitter(ob,psmd,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,texco, 0); } else{ //psys_particle_on_emitter(ob,psmd,psys->part->from,pa->num,pa->fuv,pa->offset,texco,0,0,0); /* ditto above */ - psys_particle_on_emitter(ob,psmd,psys->part->from,pa->num,-1,pa->fuv,pa->foffset,texco,0,0,0); + psys_particle_on_emitter(ob,psmd,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,texco, 0); } externtex(mtex, texco, &value, rgba, rgba+1, rgba+2, rgba+3); @@ -2525,14 +2715,14 @@ void psys_get_texture(Object *ob, Material *ma, ParticleSystemModifierData *psmd ptex->kink= texture_value_blend(mtex->def_var,ptex->kink,value,var,blend,neg & MAP_PA_CLUMP); } } - CLAMP(ptex->time,0.0,1.0); - CLAMP(ptex->life,0.0,1.0); - CLAMP(ptex->exist,0.0,1.0); - CLAMP(ptex->size,0.0,1.0); - CLAMP(ptex->ivel,0.0,1.0); - CLAMP(ptex->length,0.0,1.0); - CLAMP(ptex->clump,0.0,1.0); - CLAMP(ptex->kink,0.0,1.0); + if(event & MAP_PA_TIME) { CLAMP(ptex->time,0.0,1.0); } + if(event & MAP_PA_LIFE) { CLAMP(ptex->life,0.0,1.0); } + if(event & MAP_PA_DENS) { CLAMP(ptex->exist,0.0,1.0); } + if(event & MAP_PA_SIZE) { CLAMP(ptex->size,0.0,1.0); } + if(event & MAP_PA_IVEL) { CLAMP(ptex->ivel,0.0,1.0); } + if(event & MAP_PA_LENGTH) { CLAMP(ptex->length,0.0,1.0); } + if(event & MAP_PA_CLUMP) { CLAMP(ptex->clump,0.0,1.0); } + if(event & MAP_PA_KINK) { CLAMP(ptex->kink,0.0,1.0); } } /************************************************/ /* Particle State */ @@ -2566,10 +2756,9 @@ float psys_get_size(Object *ob, Material *ma, ParticleSystemModifierData *psmd, return size*part->size; } -float psys_get_child_time(ParticleSystem *psys, int child_nbr, float cfra) +float psys_get_child_time(ParticleSystem *psys, ChildParticle *cpa, float cfra) { ParticleSettings *part = psys->part; - ChildParticle *cpa=psys->child+child_nbr; if(part->childtype==PART_CHILD_FACES){ float time; @@ -2587,17 +2776,16 @@ float psys_get_child_time(ParticleSystem *psys, int child_nbr, float cfra) return (cfra-pa->time)/pa->lifetime; } } -float psys_get_child_size(ParticleSystem *psys, int child_nbr, float cfra, float *pa_time) +float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float cfra, float *pa_time) { ParticleSettings *part = psys->part; - ChildParticle *cpa = psys->child + child_nbr; float size, time; if(part->childtype==PART_CHILD_FACES){ if(pa_time) time=*pa_time; else - time=psys_get_child_time(psys,child_nbr,cfra); + time=psys_get_child_time(psys,cpa,cfra); if((part->flag&PART_ABS_TIME)==0 && part->ipo){ calc_ipo(part->ipo, 100*time); @@ -2629,7 +2817,7 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle ParticleKey *par=0, keys[4]; float t, real_t, dfra, keytime; - float orco[3]; + float co[3], orco[3]; float imat[4][4], hairmat[4][4], cpa_1st[3]; float pa_clump = 0.0, pa_kink = 0.0; int totparent = 0; @@ -2645,9 +2833,6 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle // edit=1; //} - if(G.rendering==0 && part->flag & PART_CHILD_RENDER) - totchild=0; - /* user want's cubic interpolation but only without sb it possible */ //if(interpolation==PART_INTER_CUBIC && baked && psys->softflag==OB_SB_ENABLE) // interpolation=PART_INTER_BSPLINE; @@ -2769,10 +2954,10 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle cpa_fuv = cpa->fuv; cpa_from = PART_FROM_FACE; - psys_particle_on_emitter(ob,psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa->fuv,foffset,orco,0,0,0); + psys_particle_on_emitter(ob,psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa->fuv,foffset,co,0,0,0,orco,0); /* we need to save the actual root position of the child for positioning it accurately to the surface of the emitter */ - VECCOPY(cpa_1st,orco); + VECCOPY(cpa_1st,co); //w=0; //while(w<4 && cpa->pa[w]>=0){ @@ -2801,7 +2986,7 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle cpa_num=pa->num; cpa_fuv=pa->fuv; - psys_particle_on_emitter(ob,psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa_fuv,pa->foffset,orco,0,0,0); + psys_particle_on_emitter(ob,psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa_fuv,pa->foffset,co,0,0,0,orco,0); } /* correct child ipo timing */ @@ -2814,7 +2999,7 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle ptex.clump=1.0; ptex.kink=1.0; - get_cpa_texture(psmd->dm,ma,cpa_num,cpa_fuv,orco,&ptex,MAP_PA_CACHE-MAP_PA_LENGTH); + get_cpa_texture(psmd->dm,ma,cpa_num,cpa_fuv,orco,&ptex,MAP_PA_CLUMP|MAP_PA_KINK); pa_clump=ptex.clump; pa_kink=ptex.kink; @@ -2907,8 +3092,6 @@ int psys_get_particle_state(Object *ob, ParticleSystem *psys, int p, ParticleKey cfra=bsystem_time(0,(float)G.scene->r.cfra,0.0); if(psys->totchild && p>=totpart){ - if(G.rendering==0 && part->flag&PART_CHILD_RENDER) - return 0; if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){ between=1; } @@ -2919,7 +3102,7 @@ int psys_get_particle_state(Object *ob, ParticleSystem *psys, int p, ParticleKey pa=psys->particles+p; if(between){ - state->time = psys_get_child_time(psys,p-totpart,cfra); + state->time = psys_get_child_time(psys,&psys->child[p-totpart],cfra); if(always==0) if((state->time<0.0 && (part->flag & PART_UNBORN)==0) diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 1c7d235cd90..414b64cae6a 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -57,6 +57,7 @@ #include "BLI_blenlib.h" #include "BLI_kdtree.h" #include "BLI_linklist.h" +#include "BLI_threads.h" #include "BKE_anim.h" #include "BKE_bad_level_calls.h" @@ -74,6 +75,7 @@ #include "BKE_depsgraph.h" #include "BKE_lattice.h" #include "BKE_pointcache.h" +#include "BKE_mesh.h" #include "BKE_modifier.h" #include "BSE_headerbuttons.h" @@ -106,7 +108,7 @@ static int get_current_display_percentage(ParticleSystem *psys) static void alloc_particles(ParticleSystem *psys, int new_totpart) { ParticleData *newpars = 0, *pa; - int i, totpart, totsaved = 0; + int i, child_nbr, totpart, totsaved = 0; if(new_totpart<0){ if(psys->part->distr==PART_DISTR_GRID){ @@ -134,13 +136,14 @@ static void alloc_particles(ParticleSystem *psys, int new_totpart) } psys->particles=newpars; - if(psys->part->child_nbr && psys->part->childtype){ + child_nbr= (G.rendering)? psys->part->ren_child_nbr: psys->part->child_nbr; + if(child_nbr && psys->part->childtype){ if(psys->child) MEM_freeN(psys->child); psys->child = NULL; if(totpart) - psys->child= MEM_callocN(totpart*psys->part->child_nbr*sizeof(ChildParticle), "child_particles"); - psys->totchild=totpart*psys->part->child_nbr; + psys->child= MEM_callocN(totpart*child_nbr*sizeof(ChildParticle), "child_particles"); + psys->totchild=totpart*child_nbr; } else if(psys->child){ MEM_freeN(psys->child); @@ -462,6 +465,298 @@ static int binary_search_distribution(float *sum, int n, float value) return low; } +/* note: this function must be thread safe, for from == PART_FROM_CHILD */ +#define ONLY_WORKING_WITH_PA_VERTS 0 +void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, ChildParticle *cpa, int p) +{ + ParticleThreadContext *ctx= thread->ctx; + Object *ob= ctx->ob; + DerivedMesh *dm= ctx->dm; + ParticleData *tpars=0, *tpa; + ParticleSettings *part= ctx->psys->part; + float *v1, *v2, *v3, *v4, nor[3], orco1[3], co1[3], co2[3], nor1[3], ornor1[3]; + float cur_d, min_d; + int from= ctx->from; + int cfrom= ctx->cfrom; + int distr= ctx->distr; + int i, intersect, tot; + + if(from == PART_FROM_VERT) { + /* TODO_PARTICLE - use original index */ + pa->num= ctx->index[p]; + pa->fuv[0] = 1.0f; + pa->fuv[1] = pa->fuv[2] = pa->fuv[3] = 0.0; + //pa->verts[0] = pa->verts[1] = pa->verts[2] = 0; + +#if ONLY_WORKING_WITH_PA_VERTS + if(ctx->tree){ + KDTreeNearest ptn[3]; + int w, maxw; + + psys_particle_on_dm(ctx->ob,ctx->dm,from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co1,0,0,0,orco1,0); + maxw = BLI_kdtree_find_n_nearest(ctx->tree,3,orco1,NULL,ptn); + + for(w=0; w<maxw; w++){ + pa->verts[w]=ptn->num; + } + } +#endif + } + else if(from == PART_FROM_FACE || from == PART_FROM_VOLUME) { + MFace *mface; + + pa->num = i = ctx->index[p]; + mface = dm->getFaceData(dm,i,CD_MFACE); + + switch(distr){ + case PART_DISTR_JIT: + ctx->jitoff[i] = fmod(ctx->jitoff[i],(float)ctx->jitlevel); + psys_uv_to_w(ctx->jit[2*(int)ctx->jitoff[i]], ctx->jit[2*(int)ctx->jitoff[i]+1], mface->v4, pa->fuv); + ctx->jitoff[i]++; + //ctx->jitoff[i]=(float)fmod(ctx->jitoff[i]+ctx->maxweight/ctx->weight[i],(float)ctx->jitlevel); + break; + case PART_DISTR_RAND: + psys_uv_to_w(rng_getFloat(thread->rng), rng_getFloat(thread->rng), mface->v4, pa->fuv); + break; + } + pa->foffset= 0.0f; + + /* + pa->verts[0] = mface->v1; + pa->verts[1] = mface->v2; + pa->verts[2] = mface->v3; + */ + + /* experimental */ + if(from==PART_FROM_VOLUME){ + MVert *mvert=dm->getVertDataArray(dm,CD_MVERT); + + tot=dm->getNumFaces(dm); + + psys_interpolate_face(mvert,mface,0,0,pa->fuv,co1,nor,0,0,0,0); + + Normalize(nor); + VecMulf(nor,-100.0); + + VECADD(co2,co1,nor); + + min_d=2.0; + intersect=0; + + for(i=0,mface=dm->getFaceDataArray(dm,CD_MFACE); i<tot; i++,mface++){ + if(i==pa->num) continue; + + v1=mvert[mface->v1].co; + v2=mvert[mface->v2].co; + v3=mvert[mface->v3].co; + + if(LineIntersectsTriangle(co1, co2, v2, v3, v1, &cur_d, 0)){ + if(cur_d<min_d){ + min_d=cur_d; + pa->foffset=cur_d*50.0f; /* to the middle of volume */ + intersect=1; + } + } + if(mface->v4){ + v4=mvert[mface->v4].co; + + if(LineIntersectsTriangle(co1, co2, v4, v1, v3, &cur_d, 0)){ + if(cur_d<min_d){ + min_d=cur_d; + pa->foffset=cur_d*50.0f; /* to the middle of volume */ + intersect=1; + } + } + } + } + if(intersect==0) + pa->foffset=0.0; + else switch(distr){ + case PART_DISTR_JIT: + pa->foffset*= ctx->jit[2*(int)ctx->jitoff[i]]; + break; + case PART_DISTR_RAND: + pa->foffset*=BLI_frand(); + break; + } + } + } + else if(from == PART_FROM_PARTICLE) { + //pa->verts[0]=0; /* not applicable */ + //pa->verts[1]=0; + //pa->verts[2]=0; + + tpa=tpars+ctx->index[p]; + pa->num=ctx->index[p]; + pa->fuv[0]=tpa->fuv[0]; + pa->fuv[1]=tpa->fuv[1]; + /* abusing foffset a little for timing in near reaction */ + pa->foffset=ctx->weight[ctx->index[p]]; + ctx->weight[ctx->index[p]]+=ctx->maxweight; + } + else if(from == PART_FROM_CHILD) { + MFace *mf; + + if(ctx->index[p] < 0) { + cpa->num=0; + cpa->fuv[0]=cpa->fuv[1]=cpa->fuv[2]=cpa->fuv[3]=0.0f; + cpa->pa[0]=cpa->pa[1]=cpa->pa[2]=cpa->pa[3]=0; + cpa->rand[0]=cpa->rand[1]=cpa->rand[2]=0.0f; + return; + } + + mf= dm->getFaceData(dm, ctx->index[p], CD_MFACE); + + //switch(distr){ + // case PART_DISTR_JIT: + // i=index[p]; + // psys_uv_to_w(ctx->jit[2*(int)ctx->jitoff[i]], ctx->jit[2*(int)ctx->jitoff[i]+1], mf->v4, cpa->fuv); + // ctx->jitoff[i]=(float)fmod(ctx->jitoff[i]+ctx->maxweight/ctx->weight[i],(float)ctx->jitlevel); + // break; + // case PART_DISTR_RAND: + psys_uv_to_w(rng_getFloat(thread->rng), rng_getFloat(thread->rng), mf->v4, cpa->fuv); + // break; + //} + + cpa->rand[0] = rng_getFloat(thread->rng); + cpa->rand[1] = rng_getFloat(thread->rng); + cpa->rand[2] = rng_getFloat(thread->rng); + cpa->num = ctx->index[p]; + + if(ctx->tree){ + KDTreeNearest ptn[10]; + int w,maxw, do_seams; + float maxd,mind,dd,totw=0.0; + int parent[10]; + float pweight[10]; + + do_seams= (part->flag&PART_CHILD_SEAMS && ctx->seams); + + psys_particle_on_dm(ob,dm,cfrom,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co1,nor1,0,0,orco1,ornor1); + maxw = BLI_kdtree_find_n_nearest(ctx->tree,(do_seams)?10:4,orco1,ornor1,ptn); + + maxd=ptn[maxw-1].dist; + mind=ptn[0].dist; + dd=maxd-mind; + + /* the weights here could be done better */ + for(w=0; w<maxw; w++){ + parent[w]=ptn[w].index; + pweight[w]=(float)pow(2.0,(double)(-6.0f*ptn[w].dist/maxd)); + //pweight[w]= (1.0f - ptn[w].dist*ptn[w].dist/(maxd*maxd)); + //pweight[w] *= pweight[w]; + } + for(;w<10; w++){ + parent[w]=-1; + pweight[w]=0.0f; + } + if(do_seams){ + ParticleSeam *seam=ctx->seams; + float temp[3],temp2[3],tan[3]; + float inp,cur_len,min_len=10000.0f; + int min_seam=0, near_vert=0; + /* find closest seam */ + for(i=0; i<ctx->totseam; i++, seam++){ + VecSubf(temp,co1,seam->v0); + inp=Inpf(temp,seam->dir)/seam->length2; + if(inp<0.0f){ + cur_len=VecLenf(co1,seam->v0); + } + else if(inp>1.0f){ + cur_len=VecLenf(co1,seam->v1); + } + else{ + VecCopyf(temp2,seam->dir); + VecMulf(temp2,inp); + cur_len=VecLenf(temp,temp2); + } + if(cur_len<min_len){ + min_len=cur_len; + min_seam=i; + if(inp<0.0f) near_vert=-1; + else if(inp>1.0f) near_vert=1; + else near_vert=0; + } + } + seam=ctx->seams+min_seam; + + VecCopyf(temp,seam->v0); + + if(near_vert){ + if(near_vert==-1) + VecSubf(tan,co1,seam->v0); + else{ + VecSubf(tan,co1,seam->v1); + VecCopyf(temp,seam->v1); + } + + Normalize(tan); + } + else{ + VecCopyf(tan,seam->tan); + VecSubf(temp2,co1,temp); + if(Inpf(tan,temp2)<0.0f) + VecMulf(tan,-1.0f); + } + for(w=0; w<maxw; w++){ + VecSubf(temp2,ptn[w].co,temp); + if(Inpf(tan,temp2)<0.0f){ + parent[w]=-1; + pweight[w]=0.0f; + } + } + + } + + for(w=0,i=0; w<maxw && i<4; w++){ + if(parent[w]>=0){ + cpa->pa[i]=parent[w]; + cpa->w[i]=pweight[w]; + totw+=pweight[w]; + i++; + } + } + for(;i<4; i++){ + cpa->pa[i]=-1; + cpa->w[i]=0.0f; + } + + if(totw>0.0f) for(w=0; w<4; w++) + cpa->w[w]/=totw; + + cpa->parent=cpa->pa[0]; + } + } +} + +void *exec_distribution(void *data) +{ + ParticleThread *thread= (ParticleThread*)data; + ParticleSystem *psys= thread->ctx->psys; + ParticleData *pa; + ChildParticle *cpa; + int p, totpart; + + if(thread->ctx->from == PART_FROM_CHILD) { + totpart= psys->totchild; + cpa= psys->child + thread->num; + + rng_skip(thread->rng, 5*thread->num); + for(p=thread->num; p<totpart; p+=thread->tot, cpa+=thread->tot) { + psys_thread_distribute_particle(thread, NULL, cpa, p); + rng_skip(thread->rng, 5*(thread->tot-1)); + } + } + else { + totpart= psys->totpart; + pa= psys->particles + thread->num; + for(p=thread->num; p<totpart; p+=thread->tot, pa+=thread->tot) + psys_thread_distribute_particle(thread, pa, NULL, p); + } + + return 0; +} + /* creates a distribution of coordinates on a DerivedMesh */ /* */ /* 1. lets check from what we are emitting */ @@ -477,39 +772,39 @@ static int binary_search_distribution(float *sum, int n, float value) /* 6. and we're done! */ /* This is to denote functionality that does not yet work with mesh - only derived mesh */ -#define ONLY_WORKING_WITH_PA_VERTS 0 -static void distribute_particles_on_dm(DerivedMesh *finaldm, Object *ob, ParticleSystem *psys, int from) +int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm, int from) { + ParticleThreadContext *ctx= threads[0].ctx; + Object *ob= ctx->ob; + ParticleSystem *psys= ctx->psys; Object *tob; - ParticleData *pa=0, *tpars=0, *tpa; + ParticleData *pa=0, *tpars; ParticleSettings *part; ParticleSystem *tpsys; + ParticleSeam *seams= 0; ChildParticle *cpa=0; KDTree *tree=0; - ParticleSeam *seams=0; + DerivedMesh *dm= NULL; float *jit= NULL; - int p=0,i; + int i, seed, p=0, totthread= threads[0].tot; int no_distr=0, cfrom=0; int tot=0, totpart, *index=0, children=0, totseam=0; //int *vertpart=0; - int jitlevel= 1, intersect, distr; + int jitlevel= 1, distr; float *weight=0,*sum=0,*jitoff=0; - float cur, maxweight=0.0,tweight; - float *v1, *v2, *v3, *v4, co[3], nor[3], co1[3], co2[3], nor1[3]; - float cur_d, min_d; - DerivedMesh *dm= NULL; + float cur, maxweight=0.0, tweight, totweight, co[3], nor[3], orco[3], ornor[3]; if(ob==0 || psys==0 || psys->part==0) - return; + return 0; part=psys->part; totpart=psys->totpart; if(totpart==0) - return; + return 0; if (!finaldm->deformedOnly && !CustomData_has_layer( &finaldm->faceData, CD_ORIGINDEX ) ) { error("Can't paint with the current modifier stack, disable destructive modifiers"); - return; + return 0; } BLI_srandom(31415926 + psys->seed); @@ -524,8 +819,8 @@ static void distribute_particles_on_dm(DerivedMesh *finaldm, Object *ob, Particl tree=BLI_kdtree_new(totpart); for(p=0,pa=psys->particles; p<totpart; p++,pa++){ - psys_particle_on_dm(ob,dm,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,nor,0,0); - BLI_kdtree_insert(tree, p, co, nor); + psys_particle_on_dm(ob,dm,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,nor,0,0,orco,ornor); + BLI_kdtree_insert(tree, p, orco, ornor); } BLI_kdtree_balance(tree); @@ -579,7 +874,9 @@ static void distribute_particles_on_dm(DerivedMesh *finaldm, Object *ob, Particl } else{ /* no need to figure out distribution */ - for(i=0; i<part->child_nbr; i++){ + int child_nbr= (G.rendering)? part->ren_child_nbr: part->child_nbr; + + for(i=0; i<child_nbr; i++){ for(p=0; p<psys->totpart; p++,cpa++){ float length=2.0; cpa->parent=p; @@ -600,7 +897,7 @@ static void distribute_particles_on_dm(DerivedMesh *finaldm, Object *ob, Particl } } - return; + return 0; } } else{ @@ -610,19 +907,26 @@ static void distribute_particles_on_dm(DerivedMesh *finaldm, Object *ob, Particl if(part->distr==PART_DISTR_GRID){ distribute_particles_in_grid(dm,psys); dm->release(dm); - return; + return 0; } + /* we need orco for consistent distributions */ + DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, get_mesh_orco_verts(ob)); + distr=part->distr; pa=psys->particles; if(from==PART_FROM_VERT){ - MVert *mv= dm->getVertDataArray(dm,0); + MVert *mv= dm->getVertDataArray(dm, CD_MVERT); + float (*orcodata)[3]= dm->getVertDataArray(dm, CD_ORCO); int totvert = dm->getNumVerts(dm); tree=BLI_kdtree_new(totvert); - for(p=0; p<totvert; p++,mv++){ - VECCOPY(co,mv->co); + for(p=0; p<totvert; p++){ + if(orcodata) + VECCOPY(co,orcodata[p]) + else + VECCOPY(co,mv[p].co) BLI_kdtree_insert(tree,p,co,NULL); } @@ -674,7 +978,7 @@ static void distribute_particles_on_dm(DerivedMesh *finaldm, Object *ob, Particl } if(dm != finaldm) dm->release(dm); - return; + return 0; } /* 2. */ @@ -686,20 +990,34 @@ static void distribute_particles_on_dm(DerivedMesh *finaldm, Object *ob, Particl /* 2.1 */ if((part->flag&PART_EDISTR || children) && ELEM(from,PART_FROM_PARTICLE,PART_FROM_VERT)==0){ - float totarea=0.0; + float totarea=0.0, *co1, *co2, *co3, *co4; + float (*orcodata)[3]; + + orcodata= dm->getVertDataArray(dm, CD_ORCO); for(i=0; i<tot; i++){ MFace *mf=dm->getFaceData(dm,i,CD_MFACE); - MVert *mv1=dm->getVertData(dm,mf->v1,CD_MVERT); - MVert *mv2=dm->getVertData(dm,mf->v2,CD_MVERT); - MVert *mv3=dm->getVertData(dm,mf->v3,CD_MVERT); + + if(orcodata) { + co1= orcodata[mf->v1]; + co2= orcodata[mf->v2]; + co3= orcodata[mf->v3]; + } + else { + co1= ((MVert*)dm->getVertData(dm,mf->v1,CD_MVERT))->co; + co2= ((MVert*)dm->getVertData(dm,mf->v2,CD_MVERT))->co; + co3= ((MVert*)dm->getVertData(dm,mf->v3,CD_MVERT))->co; + } if (mf->v4){ - MVert *mv4=dm->getVertData(dm,mf->v4,CD_MVERT); - cur= AreaQ3Dfl(mv1->co,mv2->co,mv3->co,mv4->co); + if(orcodata) + co4= orcodata[mf->v4]; + else + co4= ((MVert*)dm->getVertData(dm,mf->v4,CD_MVERT))->co; + cur= AreaQ3Dfl(co1, co2, co3, co4); } else - cur= AreaT3Dfl(mv1->co,mv2->co,mv3->co); + cur= AreaT3Dfl(co1, co2, co3); if(cur>maxweight) maxweight=cur; @@ -756,9 +1074,16 @@ static void distribute_particles_on_dm(DerivedMesh *finaldm, Object *ob, Particl } /* 3. */ + totweight= 0.0f; + for(i=0;i<tot; i++) + totweight += weight[i]; + + if(totweight > 0.0f) + totweight= 1.0f/totweight; + sum[0]= 0.0f; for(i=0;i<tot; i++) - sum[i+1]= sum[i]+weight[i]; + sum[i+1]= sum[i]+weight[i]*totweight; if(part->flag&PART_TRAND){ float pos; @@ -766,6 +1091,7 @@ static void distribute_particles_on_dm(DerivedMesh *finaldm, Object *ob, Particl for(p=0; p<totpart; p++) { pos= BLI_frand(); index[p]= binary_search_distribution(sum, tot, pos); + index[p]= MIN2(tot-1, index[p]); jitoff[index[p]]= pos; } } @@ -781,10 +1107,15 @@ static void distribute_particles_on_dm(DerivedMesh *finaldm, Object *ob, Particl i++; index[p]= MIN2(tot-1, i); + if(p == totpart-1 && weight[index[p]] == 0.0f) + index[p]= index[p-1]; + jitoff[index[p]]= pos; } } + MEM_freeN(sum); + /* weights are no longer used except for FROM_PARTICLE, which needs them zeroed for indexing */ if(from==PART_FROM_PARTICLE){ for(i=0; i<tot; i++) @@ -809,277 +1140,71 @@ static void distribute_particles_on_dm(DerivedMesh *finaldm, Object *ob, Particl } /* 5. */ - if(children) from=PART_FROM_CHILD; - for(p=0,pa=psys->particles; p<totpart; p++,pa++,cpa++){ - switch(from){ - case PART_FROM_VERT: - /* TODO_PARTICLE - use original index */ - pa->num=index[p]; - pa->fuv[0] = 1.0f; - pa->fuv[1] = pa->fuv[2] = pa->fuv[3] = 0.0; - //pa->verts[0] = pa->verts[1] = pa->verts[2] = 0; - -#if ONLY_WORKING_WITH_PA_VERTS - if(tree){ - KDTreeNearest ptn[3]; - int w,maxw; - - psys_particle_on_dm(ob,dm,from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co1,0,0,0); - maxw = BLI_kdtree_find_n_nearest(tree,3,co1,NULL,ptn); - - for(w=0; w<maxw; w++){ - pa->verts[w]=ptn->num; - } - } -#endif - break; - case PART_FROM_FACE: - case PART_FROM_VOLUME: - { - MFace *mface; - pa->num = i = index[p]; - mface = dm->getFaceData(dm,i,CD_MFACE); - - switch(distr){ - case PART_DISTR_JIT: - jitoff[i] = fmod(jitoff[i],(float)jitlevel); - psys_uv_to_w(jit[2*(int)jitoff[i]], jit[2*(int)jitoff[i]+1], mface->v4, pa->fuv); - jitoff[i]++; - //jitoff[i]=(float)fmod(jitoff[i]+maxweight/weight[i],(float)jitlevel); - break; - case PART_DISTR_RAND: - psys_uv_to_w(BLI_frand(), BLI_frand(), mface->v4, pa->fuv); - break; - } - pa->foffset= 0.0f; - - /* - pa->verts[0] = mface->v1; - pa->verts[1] = mface->v2; - pa->verts[2] = mface->v3; - */ - - /* experimental */ - if(from==PART_FROM_VOLUME){ - MVert *mvert=dm->getVertDataArray(dm,CD_MVERT); - - tot=dm->getNumFaces(dm); - - psys_interpolate_face(mvert,mface,0,pa->fuv,co1,nor,0,0); - - Normalize(nor); - VecMulf(nor,-100.0); - - VECADD(co2,co1,nor); - - min_d=2.0; - intersect=0; - - for(i=0,mface=dm->getFaceDataArray(dm,CD_MFACE); i<tot; i++,mface++){ - if(i==pa->num) continue; - - v1=mvert[mface->v1].co; - v2=mvert[mface->v2].co; - v3=mvert[mface->v3].co; - - if(LineIntersectsTriangle(co1, co2, v2, v3, v1, &cur_d, 0)){ - if(cur_d<min_d){ - min_d=cur_d; - pa->foffset=cur_d*50.0f; /* to the middle of volume */ - intersect=1; - } - } - if(mface->v4){ - v4=mvert[mface->v4].co; + if(children) + from=PART_FROM_CHILD; + + ctx->tree= tree; + ctx->seams= seams; + ctx->totseam= totseam; + ctx->psys= psys; + ctx->index= index; + ctx->jit= jit; + ctx->jitlevel= jitlevel; + ctx->jitoff= jitoff; + ctx->weight= weight; + ctx->maxweight= maxweight; + ctx->from= from; + ctx->cfrom= cfrom; + ctx->distr= distr; + ctx->dm= dm; + + seed= 31415926 + ctx->psys->seed; + + if(from!=PART_FROM_CHILD || psys->totchild < 10000) + totthread= 1; + + for(i=0; i<totthread; i++) { + threads[i].rng= rng_new(seed); + threads[i].tot= totthread; + } - if(LineIntersectsTriangle(co1, co2, v4, v1, v3, &cur_d, 0)){ - if(cur_d<min_d){ - min_d=cur_d; - pa->foffset=cur_d*50.0f; /* to the middle of volume */ - intersect=1; - } - } - } - } - if(intersect==0) - pa->foffset=0.0; - else switch(distr){ - case PART_DISTR_JIT: - pa->foffset*= jit[2*(int)jitoff[i]]; - break; - case PART_DISTR_RAND: - pa->foffset*=BLI_frand(); - break; - } - } - break; - } - case PART_FROM_PARTICLE: - - //pa->verts[0]=0; /* not applicable */ - //pa->verts[1]=0; - //pa->verts[2]=0; - - tpa=tpars+index[p]; - pa->num=index[p]; - pa->fuv[0]=tpa->fuv[0]; - pa->fuv[1]=tpa->fuv[1]; - /* abusing foffset a little for timing in near reaction */ - pa->foffset=weight[index[p]]; - weight[index[p]]+=maxweight; - break; - case PART_FROM_CHILD: - if(index[p]>=0){ - MFace *mf; + return 1; +} - mf=dm->getFaceData(dm,index[p],CD_MFACE); - - //switch(distr){ - // case PART_DISTR_JIT: - // i=index[p]; - // psys_uv_to_w(jit[2*(int)jitoff[i]], jit[2*(int)jitoff[i]+1], mf->v4, cpa->fuv); - // jitoff[i]=(float)fmod(jitoff[i]+maxweight/weight[i],(float)jitlevel); - // break; - // case PART_DISTR_RAND: - psys_uv_to_w(BLI_frand(), BLI_frand(), mf->v4, cpa->fuv); - // break; - //} - - cpa->rand[0] = BLI_frand(); - cpa->rand[1] = BLI_frand(); - cpa->rand[2] = BLI_frand(); - cpa->num = index[p]; - - if(tree){ - KDTreeNearest ptn[10]; - int w,maxw, do_seams; - float maxd,mind,dd,totw=0.0; - int parent[10]; - float pweight[10]; - - do_seams= (part->flag&PART_CHILD_SEAMS && seams); - - psys_particle_on_dm(ob,dm,cfrom,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co1,nor1,0,0); - maxw = BLI_kdtree_find_n_nearest(tree,(do_seams)?10:4,co1,nor1,ptn); - - maxd=ptn[maxw-1].dist; - mind=ptn[0].dist; - dd=maxd-mind; - - /* the weights here could be done better */ - for(w=0; w<maxw; w++){ - parent[w]=ptn[w].index; - pweight[w]=(float)pow(2.0,(double)(-6.0f*ptn[w].dist/maxd)); - //totw+=cpa->w[w]; - } - for(;w<10; w++){ - parent[w]=-1; - pweight[w]=0.0f; - } - if(do_seams){ - ParticleSeam *seam=seams; - float temp[3],temp2[3],tan[3]; - float inp,cur_len,min_len=10000.0f; - int min_seam=0, near_vert=0; - /* find closest seam */ - for(i=0; i<totseam; i++, seam++){ - VecSubf(temp,co1,seam->v0); - inp=Inpf(temp,seam->dir)/seam->length2; - if(inp<0.0f){ - cur_len=VecLenf(co1,seam->v0); - } - else if(inp>1.0f){ - cur_len=VecLenf(co1,seam->v1); - } - else{ - VecCopyf(temp2,seam->dir); - VecMulf(temp2,inp); - cur_len=VecLenf(temp,temp2); - } - if(cur_len<min_len){ - min_len=cur_len; - min_seam=i; - if(inp<0.0f) near_vert=-1; - else if(inp>1.0f) near_vert=1; - else near_vert=0; - } - } - seam=seams+min_seam; - - VecCopyf(temp,seam->v0); - - if(near_vert){ - if(near_vert==-1) - VecSubf(tan,co1,seam->v0); - else{ - VecSubf(tan,co1,seam->v1); - VecCopyf(temp,seam->v1); - } +static void distribute_particles_on_dm(DerivedMesh *finaldm, Object *ob, ParticleSystem *psys, int from) +{ + ListBase threads; + ParticleThread *pthreads; + ParticleThreadContext *ctx; + int i, totthread; - Normalize(tan); - } - else{ - VecCopyf(tan,seam->tan); - VecSubf(temp2,co1,temp); - if(Inpf(tan,temp2)<0.0f) - VecMulf(tan,-1.0f); - } - for(w=0; w<maxw; w++){ - VecSubf(temp2,ptn[w].co,temp); - if(Inpf(tan,temp2)<0.0f){ - parent[w]=-1; - pweight[w]=0.0f; - } - } + pthreads= psys_threads_create(ob, psys, G.scene->r.threads); - } + if(!psys_threads_init_distribution(pthreads, finaldm, from)) { + psys_threads_free(pthreads); + return; + } - for(w=0,i=0; w<maxw && i<4; w++){ - if(parent[w]>=0){ - cpa->pa[i]=parent[w]; - cpa->w[i]=pweight[w]; - totw+=pweight[w]; - i++; - } - } - for(;i<4; i++){ - cpa->pa[i]=-1; - cpa->w[i]=0.0f; - } + totthread= pthreads[0].tot; + if(totthread > 1) { + BLI_init_threads(&threads, exec_distribution, totthread); - if(totw>0.0f) for(w=0; w<4; w++) - cpa->w[w]/=totw; + for(i=0; i<totthread; i++) + BLI_insert_thread(&threads, &pthreads[i]); - cpa->parent=cpa->pa[0]; - } - } - else{ - cpa->num=0; - cpa->fuv[0]=cpa->fuv[1]=cpa->fuv[2]=cpa->fuv[3]=0.0f; - cpa->pa[0]=cpa->pa[1]=cpa->pa[2]=cpa->pa[3]=0; - cpa->rand[0]=cpa->rand[1]=cpa->rand[2]=0.0f; - } - break; - } + BLI_end_threads(&threads); } + else + exec_distribution(&pthreads[0]); - /* 6. */ - if(jit) MEM_freeN(jit); - if(sum) MEM_freeN(sum); - if(jitoff) MEM_freeN(jitoff); - if(weight){ - MEM_freeN(weight); - weight=0; - } - if(index) MEM_freeN(index); - if(seams) MEM_freeN(seams); - //if(vertpart) MEM_freeN(vertpart); - BLI_kdtree_free(tree); - if (from == PART_FROM_FACE) psys_calc_dmfaces(ob, finaldm, psys); - - if(dm != finaldm) dm->release(dm); + + ctx= pthreads[0].ctx; + if(ctx->dm != finaldm) + ctx->dm->release(ctx->dm); + + psys_threads_free(pthreads); } /* ready for future use, to emit particles without geometry */ @@ -1124,6 +1249,79 @@ static void distribute_particles(Object *ob, ParticleSystem *psys, int from) } } } + +/* threaded child particle distribution and path caching */ +ParticleThread *psys_threads_create(struct Object *ob, struct ParticleSystem *psys, int totthread) +{ + ParticleThread *threads; + ParticleThreadContext *ctx; + int i; + + threads= MEM_callocN(sizeof(ParticleThread)*totthread, "ParticleThread"); + ctx= MEM_callocN(sizeof(ParticleThreadContext), "ParticleThreadContext"); + + ctx->ob= ob; + ctx->psys= psys; + ctx->psmd= psys_get_modifier(ob, psys); + ctx->dm= ctx->psmd->dm; + ctx->ma= give_current_material(ob, psys->part->omat); + + memset(threads, 0, sizeof(ParticleThread)*totthread); + + for(i=0; i<totthread; i++) { + threads[i].ctx= ctx; + threads[i].num= i; + threads[i].tot= totthread; + } + + return threads; +} + +void psys_threads_free(ParticleThread *threads) +{ + ParticleThreadContext *ctx= threads[0].ctx; + int i, totthread= threads[0].tot; + + /* path caching */ + if(ctx->vg_length) + MEM_freeN(ctx->vg_length); + if(ctx->vg_clump) + MEM_freeN(ctx->vg_clump); + if(ctx->vg_kink) + MEM_freeN(ctx->vg_kink); + if(ctx->vg_rough1) + MEM_freeN(ctx->vg_rough1); + if(ctx->vg_rough2) + MEM_freeN(ctx->vg_roughe); + if(ctx->vg_roughe) + MEM_freeN(ctx->vg_roughe); + + if(ctx->psys->lattice){ + end_latt_deform(); + ctx->psys->lattice=0; + } + + /* distribution */ + if(ctx->jit) MEM_freeN(ctx->jit); + if(ctx->jitoff) MEM_freeN(ctx->jitoff); + if(ctx->weight) MEM_freeN(ctx->weight); + if(ctx->index) MEM_freeN(ctx->index); + if(ctx->seams) MEM_freeN(ctx->seams); + //if(ctx->vertpart) MEM_freeN(ctx->vertpart); + BLI_kdtree_free(ctx->tree); + + /* threads */ + for(i=0; i<totthread; i++) { + if(threads[i].rng) + rng_free(threads[i].rng); + if(threads[i].rng_path) + rng_free(threads[i].rng_path); + } + + MEM_freeN(ctx); + MEM_freeN(threads); +} + /* set particle parameters that don't change during particle's life */ void initialize_particle(ParticleData *pa, int p, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd) { @@ -1341,7 +1539,7 @@ void reset_particle(ParticleData *pa, ParticleSystem *psys, ParticleSystemModifi where_is_object_time(ob,pa->time); /* get birth location from object */ - psys_particle_on_emitter(ob,psmd,part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,utan,vtan); + psys_particle_on_emitter(ob,psmd,part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,utan,vtan,0,0); /* save local coordinates for later */ VECCOPY(tloc,loc); @@ -2240,7 +2438,7 @@ static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemMo ec->locations=MEM_callocN(totpart*3*sizeof(float),"particle locations"); for(p=0,pa=psys->particles; p<totpart; p++, pa++){ - psys_particle_on_emitter(ob,psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,0,0,0); + psys_particle_on_emitter(ob,psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,0,0,0,0,0); Mat4MulVecfl(ob->obmat,loc); ec->distances[p]=VecLenf(loc,vec); VECSUB(loc,loc,vec); @@ -2950,7 +3148,7 @@ static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, Part } else{ /* get deflection point & normal */ - psys_interpolate_face(mvert,mface,0,min_w,ipoint,unit_nor,0,0); + psys_interpolate_face(mvert,mface,0,0,min_w,ipoint,unit_nor,0,0,0,0); if(global){ Mat4Mul3Vecfl(ob->obmat,unit_nor); Mat4MulVecfl(ob->obmat,ipoint); @@ -3163,7 +3361,7 @@ static int boid_see_mesh(ListBase *lb, Object *pob, ParticleSystem *psys, float mvert=dm->getVertDataArray(dm,CD_MVERT); /* get deflection point & normal */ - psys_interpolate_face(mvert,mface,0,min_w,loc,nor,0,0); + psys_interpolate_face(mvert,mface,0,0,min_w,loc,nor,0,0,0,0); VECADD(nor,nor,loc); Mat4MulVecfl(ob->obmat,loc); @@ -3659,7 +3857,7 @@ static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys, mvert=dm->getVertDataArray(dm,CD_MVERT); /* get deflection point & normal */ - psys_interpolate_face(mvert,mface,0,min_w,loc,nor,0,0); + psys_interpolate_face(mvert,mface,0,0,min_w,loc,nor,0,0,0,0); Mat4MulVecfl(zob->obmat,loc); Mat4Mul3Vecfl(zob->obmat,nor); @@ -3969,8 +4167,9 @@ static void psys_update_path_cache(Object *ob, ParticleSystemModifierData *psmd, ParticleSettings *part=psys->part; ParticleEditSettings *pset=&G.scene->toolsettings->particle; int distr=0,alloc=0; + int child_nbr= (G.rendering)? part->ren_child_nbr: part->child_nbr; - if((psys->part->childtype && psys->totchild != psys->totpart*part->child_nbr) || psys->recalc&PSYS_ALLOC) + if((psys->part->childtype && psys->totchild != psys->totpart*child_nbr) || psys->recalc&PSYS_ALLOC) alloc=1; if(alloc || psys->recalc&PSYS_DISTR || (psys->vgroup[PSYS_VG_DENSITY] && (G.f & G_WEIGHTPAINT))) @@ -3992,9 +4191,9 @@ static void psys_update_path_cache(Object *ob, ParticleSystemModifierData *psmd, || part->draw_as==PART_DRAW_PATH || part->draw&PART_DRAW_KEYS)){ psys_cache_paths(ob, psys, cfra, 0); - if(part->childtype){ - if((G.rendering || (part->flag&PART_CHILD_RENDER)==0) - || (psys_in_edit_mode(psys) && (pset->flag&PE_SHOW_CHILD))) + /* for render, child particle paths are computed on the fly */ + if(part->childtype) { + if(((psys->totchild!=0)) || (psys_in_edit_mode(psys) && (pset->flag&PE_SHOW_CHILD))) psys_cache_child_paths(ob, psys, cfra, 0); } } @@ -4122,6 +4321,7 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier int totpart,oldtotpart=0,p; float disp, *vg_vel=0, *vg_tan=0, *vg_rot=0, *vg_size=0; int init=0,distr=0,alloc=0; + int child_nbr; /*----start validity checks----*/ @@ -4186,7 +4386,8 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier else totpart = psys->part->totpart; - if(oldtotpart != totpart || psys->recalc&PSYS_ALLOC || (psys->part->childtype && psys->totchild != psys->totpart*part->child_nbr)) + child_nbr= (G.rendering)? part->ren_child_nbr: part->child_nbr; + if(oldtotpart != totpart || psys->recalc&PSYS_ALLOC || (psys->part->childtype && psys->totchild != psys->totpart*child_nbr)) alloc = 1; if(alloc || psys->recalc&PSYS_DISTR || (psys->vgroup[PSYS_VG_DENSITY] && (G.f & G_WEIGHTPAINT) && ob==OBACT)) @@ -4271,7 +4472,7 @@ void psys_to_softbody(Object *ob, ParticleSystem *psys, int force_recalc) if((psys->softflag&OB_SB_ENABLE)==0) return; - if(ob->recalc && (ob->recalc&OB_RECALC_TIME)==0) + if(psys->recalc || force_recalc) psys->softflag|=OB_SB_REDO; /* let's replace the object's own softbody with the particle softbody */ @@ -4284,12 +4485,6 @@ void psys_to_softbody(Object *ob, ParticleSystem *psys, int force_recalc) /* swich to new ones */ ob->soft=psys->soft; ob->softflag=psys->softflag; - - /* signal for before/free bake */ - //if(psys->flag & PSYS_SOFT_BAKE || force_recalc){ - // sbObjectToSoftbody(ob); - // psys->flag &= ~PSYS_SOFT_BAKE; - //} /* do softbody */ sbObjectStep(ob, (float)G.scene->r.cfra, NULL, psys_count_keys(psys)); @@ -4363,7 +4558,7 @@ void particle_system_update(Object *ob, ParticleSystem *psys){ if(psys->softflag&OB_SB_ENABLE) psys_to_softbody(ob,psys,1); } - + system_step(ob,psys,psmd,cfra); Mat4CpyMat4(psys->imat, ob->imat); /* used for duplicators */ diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index c4ef437019e..2afcf19427c 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -59,7 +59,17 @@ static int ptcache_path(char *filename) { - sprintf(filename, PTCACHE_PATH); + char dir[FILE_MAX], file[FILE_MAX]; /* we dont want the dir, only the file */ + int i; + + BLI_split_dirfile(G.sce, dir, file); + i = strlen(file); + + /* remove .blend */ + if (i > 6) + file[i-6] = '\0'; + + sprintf(filename, PTCACHE_PATH"%s/", file); /* add blend file name to pointcache dir */ BLI_convertstringcode(filename, G.sce, 0); return strlen(filename); } @@ -72,6 +82,8 @@ int BKE_ptcache_id_filename(struct ID *id, char *filename, int cfra, int stack_i filename[0] = '\0'; newname = filename; + if (!G.relbase_valid) return 0; /* save blend fiel before using pointcache */ + /* start with temp dir */ if (do_path) { len = ptcache_path(filename); @@ -100,6 +112,8 @@ FILE *BKE_ptcache_id_fopen(struct ID *id, char mode, int cfra, int stack_index) FILE *fp = NULL; char filename[(FILE_MAXDIR+FILE_MAXFILE)*2]; + if (!G.relbase_valid) return NULL; /* save blend fiel before using pointcache */ + BKE_ptcache_id_filename(id, filename, cfra, stack_index, 1, 1); if (mode=='r') { @@ -135,6 +149,8 @@ void BKE_ptcache_id_clear(struct ID *id, char mode, int cfra, int stack_index) char filename[(FILE_MAXDIR+FILE_MAXFILE)*2]; char path_full[(FILE_MAXDIR+FILE_MAXFILE)*2]; + if (!G.relbase_valid) return; /* save blend fiel before using pointcache */ + /* clear all files in the temp dir with the prefix of the ID and the ".bphys" suffix */ switch (mode) { case PTCACHE_CLEAR_ALL: diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h index 11a1fd277da..54999b1f72b 100644 --- a/source/blender/blenlib/BLI_arithb.h +++ b/source/blender/blenlib/BLI_arithb.h @@ -54,6 +54,12 @@ extern "C" { #define M_SQRT1_2 0.70710678118654752440 #endif +#ifdef WIN32 + #ifndef FREE_WINDOWS + #define isnan(n) _isnan(n) + #endif +#endif + #define MAT4_UNITY {{ 1.0, 0.0, 0.0, 0.0},\ { 0.0, 1.0, 0.0, 0.0},\ { 0.0, 0.0, 1.0, 0.0},\ diff --git a/source/blender/blenlib/BLI_rand.h b/source/blender/blenlib/BLI_rand.h index da2ecb79651..638f36b7414 100644 --- a/source/blender/blenlib/BLI_rand.h +++ b/source/blender/blenlib/BLI_rand.h @@ -52,6 +52,9 @@ double rng_getDouble (struct RNG* rng); float rng_getFloat (struct RNG* rng); void rng_shuffleArray(struct RNG *rng, void *data, int elemSize, int numElems); + /** Note that skipping is as slow as generating n numbers! */ +void rng_skip (struct RNG *rng, int n); + /** Seed the random number generator */ void BLI_srand (unsigned int seed); diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index 15ea647361f..1197e710806 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -1211,7 +1211,7 @@ void QuatToMat4( float *q, float m[][4]) m[3][3]= 1.0f; } -void Mat3ToQuat( float wmat[][3], float *q) /* from Sig.Proc.85 pag 253 */ +void Mat3ToQuat(float wmat[][3], float *q) { double tr, s; float mat[3][3]; @@ -1225,34 +1225,38 @@ void Mat3ToQuat( float wmat[][3], float *q) /* from Sig.Proc.85 pag 253 */ if(tr>FLT_EPSILON) { s= sqrt( tr); q[0]= (float)s; - s*= 4.0; - q[1]= (float)((mat[1][2]-mat[2][1])/s); - q[2]= (float)((mat[2][0]-mat[0][2])/s); - q[3]= (float)((mat[0][1]-mat[1][0])/s); + s= 1.0/(4.0*s); + q[1]= (float)((mat[1][2]-mat[2][1])*s); + q[2]= (float)((mat[2][0]-mat[0][2])*s); + q[3]= (float)((mat[0][1]-mat[1][0])*s); } else { - q[0]= 0.0f; - s= -0.5*(mat[1][1]+mat[2][2]); - - if(s>FLT_EPSILON) { - s= sqrt(s); - q[1]= (float)s; - q[2]= (float)(mat[0][1]/(2*s)); - q[3]= (float)(mat[0][2]/(2*s)); + if(mat[0][0] > mat[1][1] && mat[0][0] > mat[2][2]) { + s= 2.0*sqrtf(1.0 + mat[0][0] - mat[1][1] - mat[2][2]); + q[1]= (float)(0.25*s); + + s= 1.0/s; + q[0]= (float)((mat[2][1] - mat[1][2])*s); + q[2]= (float)((mat[1][0] + mat[0][1])*s); + q[3]= (float)((mat[2][0] + mat[0][2])*s); + } + else if(mat[1][1] > mat[2][2]) { + s= 2.0*sqrtf(1.0 + mat[1][1] - mat[0][0] - mat[2][2]); + q[2]= (float)(0.25*s); + + s= 1.0/s; + q[0]= (float)((mat[2][0] - mat[0][2])*s); + q[1]= (float)((mat[1][0] + mat[0][1])*s); + q[3]= (float)((mat[2][1] + mat[1][2])*s); } else { - q[1]= 0.0f; - s= 0.5*(1.0-mat[2][2]); - - if(s>FLT_EPSILON) { - s= sqrt(s); - q[2]= (float)s; - q[3]= (float)(mat[1][2]/(2*s)); - } - else { - q[2]= 0.0f; - q[3]= 1.0f; - } + s= 2.0*sqrtf(1.0 + mat[2][2] - mat[0][0] - mat[1][1]); + q[3]= (float)(0.25*s); + + s= 1.0/s; + q[0]= (float)((mat[1][0] - mat[0][1])*s); + q[1]= (float)((mat[2][0] + mat[0][2])*s); + q[2]= (float)((mat[2][1] + mat[1][2])*s); } } NormalQuat(q); diff --git a/source/blender/blenlib/intern/rand.c b/source/blender/blenlib/intern/rand.c index df01288aab8..71df0ede037 100644 --- a/source/blender/blenlib/intern/rand.c +++ b/source/blender/blenlib/intern/rand.c @@ -116,6 +116,14 @@ void rng_shuffleArray(RNG *rng, void *data, int elemSize, int numElems) free(temp); } +void rng_skip(RNG *rng, int n) +{ + int i; + + for(i=0; i<n; i++) + rng_getInt(rng); +} + /***/ static RNG theBLI_rng = {0}; diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c index 9e8fe80ae30..dc2e53483db 100644 --- a/source/blender/blenlib/intern/util.c +++ b/source/blender/blenlib/intern/util.c @@ -324,9 +324,10 @@ void BLI_sortlist(ListBase *listbase, int (*cmp)(void *, void *)) if (listbase->first != listbase->last) { - for( previous = listbase->first, current = previous->next; current; previous = current, current = next ) + for( previous = listbase->first, current = previous->next; current; current = next ) { next = current->next; + previous = current->prev; BLI_remlink(listbase, current); @@ -335,14 +336,7 @@ void BLI_sortlist(ListBase *listbase, int (*cmp)(void *, void *)) previous = previous->prev; } - if (previous == NULL) - { - BLI_addhead(listbase, current); - } - else - { - BLI_insertlinkafter(listbase, previous, current); - } + BLI_insertlinkafter(listbase, previous, current); } } } @@ -1023,6 +1017,7 @@ int BLI_convertstringcode(char *path, const char *basepath, int framenum) return wasrelative; } +/* copy di to fi without directory only */ void BLI_splitdirstring(char *di, char *fi) { char *lslash= BLI_last_slash(di); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 81ae152a17c..096ead210d3 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -481,7 +481,27 @@ static void cleanup_path(const char *relabase, char *name) strcat(name, filename); } -static Main *blo_find_main(ListBase *mainlist, const char *name, const char *relabase) +static void read_file_version(FileData *fd, Main *main) +{ + BHead *bhead; + + for (bhead= blo_firstbhead(fd); bhead; bhead= blo_nextbhead(fd, bhead)) { + if (bhead->code==GLOB) { + FileGlobal *fg= read_struct(fd, bhead, "Global"); + if(fg) { + main->subversionfile= fg->subversion; + main->minversionfile= fg->minversion; + main->minsubversionfile= fg->minsubversion; + MEM_freeN(fg); + } + else if (bhead->code==ENDB) + break; + } + } +} + + +static Main *blo_find_main(FileData *fd, ListBase *mainlist, const char *name, const char *relabase) { Main *m; Library *lib; @@ -510,6 +530,8 @@ static Main *blo_find_main(ListBase *mainlist, const char *name, const char *rel m->curlib= lib; + read_file_version(fd, m); + if(G.f & G_DEBUG) printf("blo_find_main: added new lib %s\n", name); return m; } @@ -730,26 +752,6 @@ BHead *blo_nextbhead(FileData *fd, BHead *thisblock) return(bhead); } -#if 0 -static void get_blender_subversion(FileData *fd) -{ - BHead *bhead; - - for (bhead= blo_firstbhead(fd); bhead; bhead= blo_nextbhead(fd, bhead)) { - if (bhead->code==GLOB) { - FileGlobal *fg= read_struct(fd, bhead, "Global"); - fd->filesubversion= fg->subversion; - fd->fileminversion= fg->minversion; - fd->fileminsubversion= fg->minsubversion; - MEM_freeN(fg); - return; - } - else if (bhead->code==ENDB) - break; - } -} -#endif - static void decode_blender_header(FileData *fd) { char header[SIZEOFBLENDERHEADER], num[4]; @@ -1622,7 +1624,7 @@ static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist) con->type= CONSTRAINT_TYPE_NULL; } /* own ipo, all constraints have it */ - con->ipo= newlibadr(fd, id->lib, con->ipo); + con->ipo= newlibadr_us(fd, id->lib, con->ipo); switch (con->type) { case CONSTRAINT_TYPE_PYTHON: @@ -3000,7 +3002,6 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) psmd->dm=0; psmd->psys=newdataadr(fd, psmd->psys); - psmd->flag |= eParticleSystemFlag_Loaded; psmd->flag &= ~eParticleSystemFlag_psys_updated; } else if (md->type==eModifierType_Explode) { ExplodeModifierData *psmd = (ExplodeModifierData*) md; @@ -6673,7 +6674,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) else wrld->ao_samp_method = WO_AOSAMP_HAMMERSLEY; - wrld->ao_adapt_thresh = 0.005; + wrld->ao_adapt_thresh = 0.005f; } for(la=main->lamp.first; la; la= la->id.next) { @@ -6687,11 +6688,13 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } if(main->versionfile <= 245) { + Scene *sce; bScreen *sc; Object *ob; Image *ima; Lamp *la; Material *ma; + ParticleSettings *part; /* unless the file was created 2.44.3 but not 2.45, update the constraints */ if ( !(main->versionfile==244 && main->subversionfile==3) && @@ -6854,7 +6857,31 @@ static void do_versions(FileData *fd, Library *lib, Main *main) ma->fadeto_mir = MA_RAYMIR_FADETOSKY; } } - + + for(part=main->particle.first; part; part=part->id.next) + if(part->ren_child_nbr==0) + part->ren_child_nbr= part->child_nbr; + if (main->versionfile < 245 || main->subversionfile < 12) + { + /* initialize skeleton generation toolsettings */ + for(sce=main->scene.first; sce; sce = sce->id.next) + { + sce->toolsettings->skgen_resolution = 50; + sce->toolsettings->skgen_threshold_internal = 0.01f; + sce->toolsettings->skgen_threshold_external = 0.01f; + sce->toolsettings->skgen_angle_limit = 45.0f; + sce->toolsettings->skgen_length_ratio = 1.3f; + sce->toolsettings->skgen_length_limit = 1.5f; + sce->toolsettings->skgen_correlation_limit = 0.98f; + sce->toolsettings->skgen_symmetry_limit = 0.1f; + sce->toolsettings->skgen_postpro = SKGEN_SMOOTH; + sce->toolsettings->skgen_postpro_passes = 1; + sce->toolsettings->skgen_options = SKGEN_FILTER_INTERNAL|SKGEN_FILTER_EXTERNAL|SKGEN_SUB_CORRELATION; + sce->toolsettings->skgen_subdivisions[0] = SKGEN_SUB_CORRELATION; + sce->toolsettings->skgen_subdivisions[1] = SKGEN_SUB_LENGTH; + sce->toolsettings->skgen_subdivisions[2] = SKGEN_SUB_ANGLE; + } + } } if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 2)) { @@ -7096,7 +7123,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) /* convert settings from old particle system */ /* general settings */ - part->totpart = paf->totpart; + part->totpart = MIN2(paf->totpart, 100000); part->sta = paf->sta; part->end = paf->end; part->lifetime = paf->lifetime; @@ -7170,7 +7197,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } - for(sce= main->scene.first; sce; sce=sce->id.next) { ParticleEditSettings *pset= &sce->toolsettings->particle; int a; @@ -7202,6 +7228,40 @@ static void do_versions(FileData *fd, Library *lib, Main *main) if(ma->mtex[a] && ma->mtex[a]->tex) ma->mtex[a]->normapspace = MTEX_NSPACE_TANGENT; } + + if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 10)) { + Object *ob; + + /* dupliface scale */ + for(ob= main->object.first; ob; ob= ob->id.next) + ob->dupfacesca = 1.0f; + } + + if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 11)) { + Object *ob; + bActionStrip *strip; + + /* nla-strips - scale */ + for (ob= main->object.first; ob; ob= ob->id.next) { + for (strip= ob->nlastrips.first; strip; strip= strip->next) { + float length, actlength, repeat; + + if (strip->flag & ACTSTRIP_USESTRIDE) + repeat= 1.0f; + else + repeat= strip->repeat; + + length = strip->end-strip->start; + if (length == 0.0f) length= 1.0f; + actlength = strip->actend-strip->actstart; + + strip->scale = length / (repeat * actlength); + if (strip->scale == 0.0f) strip->scale= 1.0f; + } + } + } + + /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ /* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */ @@ -7393,7 +7453,7 @@ static void expand_doit(FileData *fd, Main *mainvar, void *old) if(bheadlib) { Library *lib= read_struct(fd, bheadlib, "Library"); - Main *ptr= blo_find_main(&fd->mainlist, lib->name, fd->filename); + Main *ptr= blo_find_main(fd, &fd->mainlist, lib->name, fd->filename); id= is_yet_read(fd, ptr, bhead); @@ -7595,6 +7655,10 @@ static void expand_constraints(FileData *fd, Main *mainvar, ListBase *lb) bConstraint *curcon; for (curcon=lb->first; curcon; curcon=curcon->next) { + + if (curcon->ipo) + expand_doit(fd, mainvar, curcon->ipo); + switch (curcon->type) { case CONSTRAINT_TYPE_NULL: break; @@ -8159,7 +8223,7 @@ static Library* library_append( Scene *scene, char* file, char *dir, int idcode, blo_split_main(&fd->mainlist, G.main); /* which one do we need? */ - mainl = blo_find_main(&fd->mainlist, dir, G.sce); + mainl = blo_find_main(fd, &fd->mainlist, dir, G.sce); mainl->versionfile= fd->fileversion; /* needed for do_version */ @@ -8368,6 +8432,9 @@ static void read_libraries(FileData *basefd, ListBase *mainlist) mainptr->curlib->filedata= fd; mainptr->versionfile= fd->fileversion; + + /* subversion */ + read_file_version(fd, mainptr); } else mainptr->curlib->filedata= NULL; diff --git a/source/blender/ftfont/intern/Makefile b/source/blender/ftfont/intern/Makefile index 064ec5dc597..4668241c5c8 100644 --- a/source/blender/ftfont/intern/Makefile +++ b/source/blender/ftfont/intern/Makefile @@ -47,6 +47,7 @@ CPPFLAGS += -I$(NAN_FTGL)/include CPPFLAGS += -I$(NAN_FTGL)/include/FTGL CPPFLAGS += -I$(NAN_GETTEXT)/include CPPFLAGS += -I$(NAN_FREETYPE)/include +CPPFLAGS += -I$(OPENGL_HEADERS) ifeq ($(OS), windows) CPPFLAGS += -I$(NAN_ICONV)/include ifeq ($(FREE_WINDOWS), true) diff --git a/source/blender/include/BIF_editaction.h b/source/blender/include/BIF_editaction.h index fe6f81b9416..dcd4be86733 100644 --- a/source/blender/include/BIF_editaction.h +++ b/source/blender/include/BIF_editaction.h @@ -104,6 +104,7 @@ struct ListBase; /* Key operations */ void transform_action_keys(int mode, int dummy); void duplicate_action_keys(void); +void snap_cfra_action(void); void snap_action_keys(short mode); void mirror_action_keys(short mode); void insertkey_action(void); @@ -138,6 +139,7 @@ void deselect_action_channels(short test); void deselect_actionchannels(struct bAction *act, short test); int select_channel(struct bAction *act, struct bActionChannel *achan, int selectmode); void select_actionchannel_by_name(struct bAction *act, char *name, int select); +void selectkeys_leftright (short leftright, short select_mode); /* ShapeKey stuff */ struct Key *get_action_mesh_key(void); diff --git a/source/blender/include/BIF_editarmature.h b/source/blender/include/BIF_editarmature.h index 903c663e5f3..31a5cc2ec4c 100644 --- a/source/blender/include/BIF_editarmature.h +++ b/source/blender/include/BIF_editarmature.h @@ -101,6 +101,8 @@ void make_trans_bones (char mode); int do_pose_selectbuffer(struct Base *base, unsigned int *buffer, short hits); +void generateSkeleton(void); + void mouse_armature(void); void remake_editArmature(void); void selectconnected_armature(void); @@ -117,8 +119,8 @@ void hide_selected_pose_bones(void); void hide_unselected_pose_bones(void); void show_all_pose_bones(void); -int bone_looper(Object *ob, struct Bone *bone, void *data, - int (*bone_func)(Object *, struct Bone *, void *)); +int bone_looper(struct Object *ob, struct Bone *bone, void *data, + int (*bone_func)(struct Object *, struct Bone *, void *)); void undo_push_armature(char *name); void armature_bone_rename(struct bArmature *arm, char *oldname, char *newname); diff --git a/source/blender/include/BIF_editparticle.h b/source/blender/include/BIF_editparticle.h index d4c6a92b8c8..08f5813560f 100644 --- a/source/blender/include/BIF_editparticle.h +++ b/source/blender/include/BIF_editparticle.h @@ -45,6 +45,7 @@ void PE_create_particle_edit(struct Object *ob, struct ParticleSystem *psys); void PE_free_particle_edit(struct ParticleSystem *psys); void PE_change_act(void *ob_v, void *act_v); +int PE_can_edit(struct ParticleSystem *psys); /* access */ struct ParticleSystem *PE_get_current(struct Object *ob); @@ -80,6 +81,7 @@ int PE_brush_particles(void); void PE_delete_particle(void); void PE_remove_doubles(void); void PE_mirror_x(int tagged); +void PE_selectbrush_menu(void); /* undo */ void PE_undo_push(char *str); diff --git a/source/blender/include/BIF_gl.h b/source/blender/include/BIF_gl.h index 215e88dc002..611cefca51c 100644 --- a/source/blender/include/BIF_gl.h +++ b/source/blender/include/BIF_gl.h @@ -57,8 +57,12 @@ #include <OpenGL/glu.h> #else #include <GL/gl.h> +#if defined(__sun__) && !defined(__sparc__) +#include <mesa/glu.h> +#else #include <GL/glu.h> #endif +#endif /* * these should be phased out. cpack should be replaced in * code with calls to glColor3ub, lrectwrite probably should diff --git a/source/blender/include/BIF_interface.h b/source/blender/include/BIF_interface.h index 453e4e628fe..4fadfe12297 100644 --- a/source/blender/include/BIF_interface.h +++ b/source/blender/include/BIF_interface.h @@ -188,7 +188,7 @@ void uiGetMouse(int win, short *adr); void uiComposeLinks(uiBlock *block); void uiSetButLock(int val, char *lockstr); void uiClearButLock(void); -int uiDoBlocks(struct ListBase *lb, int event); +int uiDoBlocks(struct ListBase *lb, int event, int movemouse_quit); void uiSetCurFont(uiBlock *block, int index); void uiDefFont(unsigned int index, void *xl, void *large, void *medium, void *small); void uiFreeBlock(uiBlock *block); diff --git a/source/blender/include/BIF_poseobject.h b/source/blender/include/BIF_poseobject.h index a640d3abe84..ec7df157b06 100644 --- a/source/blender/include/BIF_poseobject.h +++ b/source/blender/include/BIF_poseobject.h @@ -61,11 +61,12 @@ void paste_posebuf (int flip); void pose_adds_vgroups(struct Object *meshobj, int heatweights); void pose_calculate_path(struct Object *ob); +void pose_recalculate_paths(struct Object *ob); void pose_clear_paths(struct Object *ob); void pose_flip_names(void); void pose_activate_flipped_bone(void); void pose_movetolayer(void); - +void pose_relax(void); #endif diff --git a/source/blender/include/BIF_resources.h b/source/blender/include/BIF_resources.h index f03364f099b..5c6c0384042 100644 --- a/source/blender/include/BIF_resources.h +++ b/source/blender/include/BIF_resources.h @@ -494,6 +494,7 @@ enum { TH_NORMAL, TH_FACE_DOT, TH_FACEDOT_SIZE, + TH_CFRAME, TH_SYNTAX_B, TH_SYNTAX_V, diff --git a/source/blender/include/BSE_drawview.h b/source/blender/include/BSE_drawview.h index 9c577746da9..c425cbc62ea 100644 --- a/source/blender/include/BSE_drawview.h +++ b/source/blender/include/BSE_drawview.h @@ -58,7 +58,7 @@ struct ImBuf *read_backbuf(short xmin, short ymin, short xmax, short ymax); unsigned int sample_backbuf_rect(short mval[2], int size, unsigned int min, unsigned int max, int *dist, short strict, unsigned int (*indextest)(unsigned int index)); void drawview3dspace(struct ScrArea *sa, void *spacedata); -void drawview3d_render(struct View3D *v3d, int winx, int winy); +void drawview3d_render(struct View3D *v3d, int winx, int winy, float winmat[][4]); int update_time(void); void calc_viewborder(struct View3D *v3d, struct rctf *viewborder_r); diff --git a/source/blender/include/BSE_editipo.h b/source/blender/include/BSE_editipo.h index 9e95eedc25e..11691cfbd23 100644 --- a/source/blender/include/BSE_editipo.h +++ b/source/blender/include/BSE_editipo.h @@ -151,6 +151,7 @@ void transform_ipo(int mode); void actstrip_map_ipo_keys(struct Object *ob, struct Ipo *ipo, short restore, short only_keys); void sethandles_ipo_keys(struct Ipo *ipo, int code); +void snap_cfra_ipo_keys(struct Ipo *ipo, short mode); void snap_ipo_keys(struct Ipo *ipo, short snaptype); void mirror_ipo_keys(struct Ipo *ipo, short mirror_mode); void setipotype_ipo(struct Ipo *ipo, int code); diff --git a/source/blender/include/blendef.h b/source/blender/include/blendef.h index 55fa1fd8840..8f9de747c2a 100644 --- a/source/blender/include/blendef.h +++ b/source/blender/include/blendef.h @@ -121,7 +121,9 @@ #define ISPOIN3(a, b, c, d) ( (a->b) && (a->c) && (a->d) ) #define ISPOIN4(a, b, c, d, e) ( (a->b) && (a->c) && (a->d) && (a->e) ) -#define BEZSELECTED(bezt) (((bezt)->f1 & 1) || ((bezt)->f2 & 1) || ((bezt)->f3 & 1)) +#define BEZSELECTED(bezt) (((bezt)->f1 & SELECT) || ((bezt)->f2 & SELECT) || ((bezt)->f3 & SELECT)) +/* for curve objects in editmode that can have hidden handles - may use for IPO's later */ +#define BEZSELECTED_HIDDENHANDLES(bezt) ((G.f & G_HIDDENHANDLES) ? (bezt)->f2 & SELECT : BEZSELECTED(bezt)) /* psfont */ #define FNT_PDRAW 1 diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h index a23ac48d7c2..d43d2603c63 100644 --- a/source/blender/include/butspace.h +++ b/source/blender/include/butspace.h @@ -427,6 +427,8 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la #define B_SETTFACE_RND 2082 #define B_SETMCOL_RND 2083 +#define B_GEN_SKELETON 2090 + /* *********************** */ #define B_VGROUPBUTS 2100 @@ -740,8 +742,8 @@ enum { #define B_PART_INIT_CHILD 3433 #define B_PART_RECALC_CHILD 3434 #define B_PART_EDITABLE 3435 - #define B_PART_REKEY 3436 +#define B_PART_ENABLE 3437 #define B_MODIFIER_BUTS 3600 diff --git a/source/blender/include/reeb.h b/source/blender/include/reeb.h new file mode 100644 index 00000000000..c8352aedec5 --- /dev/null +++ b/source/blender/include/reeb.h @@ -0,0 +1,127 @@ +/** + * $Id: + * + * ***** 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * Contributor(s): Martin Poirier + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef REEB_H_ +#define REEB_H_ + +#include "DNA_listBase.h" + +struct EdgeHash; +struct ReebArc; +struct ReebEdge; +struct ReebNode; + +typedef struct ReebGraph { + ListBase arcs; + ListBase nodes; + int totnodes; + struct EdgeHash *emap; +} ReebGraph; + +typedef struct EmbedBucket { + float val; + int nv; + float p[3]; +} EmbedBucket; + +typedef struct ReebNode { + struct ReebNode *next, *prev; + struct ReebArc **arcs; + int index; + int degree; + float weight; + float p[3]; + int flags; +} ReebNode; + +typedef struct ReebEdge { + struct ReebEdge *next, *prev; + struct ReebArc *arc; + struct ReebNode *v1, *v2; + struct ReebEdge *nextEdge; +} ReebEdge; + +typedef struct ReebArc { + struct ReebArc *next, *prev; + ListBase edges; + struct ReebNode *v1, *v2; + struct EmbedBucket *buckets; + int bcount; + int flags; +} ReebArc; + +typedef struct ReebArcIterator { + struct ReebArc *arc; + int index; + int start; + int end; + int stride; +} ReebArcIterator; + +struct EditMesh; + +int weightToHarmonic(struct EditMesh *em); +int weightFromDistance(struct EditMesh *em); +int weightFromLoc(struct EditMesh *me, int axis); +void weightToVCol(struct EditMesh *em); +void renormalizeWeight(struct EditMesh *em, float newmax); + +ReebGraph * generateReebGraph(struct EditMesh *me, int subdivisions); +void freeGraph(ReebGraph *rg); +void exportGraph(ReebGraph *rg, int count); + +#define OTHER_NODE(arc, node) ((arc->v1 == node) ? arc->v2 : arc->v1) + +void initArcIterator(struct ReebArcIterator *iter, struct ReebArc *arc, struct ReebNode *head); +void initArcIterator2(struct ReebArcIterator *iter, struct ReebArc *arc, int start, int end); +struct EmbedBucket * nextBucket(struct ReebArcIterator *iter); + +/* Filtering */ +void filterNullReebGraph(ReebGraph *rg); +int filterExternalReebGraph(ReebGraph *rg, float threshold); +int filterInternalReebGraph(ReebGraph *rg, float threshold); + +/* Post-Build processing */ +void repositionNodes(ReebGraph *rg); +void postprocessGraph(ReebGraph *rg, char mode); +void removeNormalNodes(ReebGraph *rg); + +/* Graph processing */ +void buildAdjacencyList(ReebGraph *rg); + +void sortNodes(ReebGraph *rg); +void sortArcs(ReebGraph *rg); + +int subtreeDepth(ReebNode *node, ReebArc *rootArc); +int countConnectedArcs(ReebGraph *rg, ReebNode *node); +int hasAdjacencyList(ReebGraph *rg); +int isGraphCyclic(ReebGraph *rg); + +/* Sanity check */ +void verifyBuckets(ReebGraph *rg); + +#endif /*REEB_H_*/ diff --git a/source/blender/include/transform.h b/source/blender/include/transform.h index 623514a1a32..52eb3edf19f 100644 --- a/source/blender/include/transform.h +++ b/source/blender/include/transform.h @@ -45,6 +45,7 @@ struct Object; struct View3D; struct ScrArea; struct bPose; +struct bConstraint; typedef struct NumInput { @@ -142,6 +143,7 @@ typedef struct TransData { float smtx[3][3]; /* Transformation matrix from global space to data space */ float axismtx[3][3];/* Axis orientation matrix of the data */ struct Object *ob; + struct bConstraint *con; /* for objects/bones, the first constraint in its constraint stack */ TransDataExtension *ext; /* for objects, poses. 1 single malloc per TransInfo! */ TransDataIpokey *tdi; /* for objects, ipo keys. per transdata a malloc */ void *tdmir; /* mirrored element pointer, in editmode mesh to EditVert */ diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index 3c5ef7c94e6..707460d0fb6 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -39,7 +39,6 @@ struct Object; /* PoseChannel stores the results of Actions (ipos) and transform information with respect to the restposition of Armature bones */ - typedef struct bPoseChannel { struct bPoseChannel *next, *prev; ListBase constraints;/* Constraints that act on this PoseChannel */ @@ -50,7 +49,7 @@ typedef struct bPoseChannel { short ikflag; /* settings for IK bones */ short selectflag; /* copy of bone flag, so you can work with library armatures */ short protectflag; /* protect channels from being transformed */ - short pad2; + short customCol; /* index of custom color set to use (0=default - used for all old files) */ int pathlen; /* for drawing paths, the amount of frames */ int pathsf; /* for drawing paths, the start frame number */ @@ -84,7 +83,6 @@ typedef struct bPoseChannel { float *path; /* totpath x 3 x float */ struct Object *custom; /* draws custom object instead of this channel */ - } bPoseChannel; /* Pose-Object. It is only found under ob->pose. It is not library data, even @@ -217,7 +215,11 @@ typedef enum PCHAN_IKFLAG { BONE_IK_XLIMIT = (1<<3), BONE_IK_YLIMIT = (1<<4), - BONE_IK_ZLIMIT = (1<<5) + BONE_IK_ZLIMIT = (1<<5), + + BONE_IK_NO_XDOF_TEMP = (1<<10), + BONE_IK_NO_YDOF_TEMP = (1<<11), + BONE_IK_NO_ZDOF_TEMP = (1<<12) } PCHAN_IKFLAG; diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h index f5eacede809..4ae94675ea7 100644 --- a/source/blender/makesdna/DNA_armature_types.h +++ b/source/blender/makesdna/DNA_armature_types.h @@ -68,7 +68,7 @@ typedef struct Bone { float size[3]; /* patch for upward compat, UNUSED! */ short layer; short segments; /* for B-bones */ -}Bone; +} Bone; typedef struct bArmature { ID id; @@ -84,76 +84,78 @@ typedef struct bArmature { int ghostsf, ghostef; /* start and end frames of ghost-drawing range */ int pathsf, pathef; /* start and end frames of path-calculation range for all bones */ int pathbc, pathac; /* number of frames before/after current frame of path-calculation for all bones */ -}bArmature; +} bArmature; /* armature->flag */ /* dont use bit 7, was saved in files to disable stuff */ - -/* armature->flag */ -#define ARM_RESTPOS 0x001 - /* XRAY is here only for backwards converting */ -#define ARM_DRAWXRAY 0x002 -#define ARM_DRAWAXES 0x004 -#define ARM_DRAWNAMES 0x008 -#define ARM_POSEMODE 0x010 -#define ARM_EDITMODE 0x020 -#define ARM_DELAYDEFORM 0x040 -#define ARM_DONT_USE 0x080 -#define ARM_MIRROR_EDIT 0x100 -#define ARM_AUTO_IK 0x200 - /* made option negative, for backwards compat */ -#define ARM_NO_CUSTOM 0x400 -#define ARM_COL_CUSTOM 0x800 +typedef enum eArmature_Flag { + ARM_RESTPOS = (1<<0), + ARM_DRAWXRAY = (1<<1), /* XRAY is here only for backwards converting */ + ARM_DRAWAXES = (1<<2), + ARM_DRAWNAMES = (1<<3), + ARM_POSEMODE = (1<<4), + ARM_EDITMODE = (1<<5), + ARM_DELAYDEFORM = (1<<6), + ARM_DONT_USE = (1<<7), + ARM_MIRROR_EDIT = (1<<8), + ARM_AUTO_IK = (1<<9), + ARM_NO_CUSTOM = (1<<10), /* made option negative, for backwards compat */ + ARM_COL_CUSTOM = (1<<11), /* draw custom colours - not yet used... */ + ARM_GHOST_ONLYSEL = (1<<12) /* when ghosting, only show selected bones (this should belong to ghostflag instead) */ +} eArmature_Flag; /* armature->drawtype */ -#define ARM_OCTA 0 -#define ARM_LINE 1 -#define ARM_B_BONE 2 -#define ARM_ENVELOPE 3 +typedef enum eArmature_Drawtype { + ARM_OCTA = 0, + ARM_LINE, + ARM_B_BONE, + ARM_ENVELOPE +} eArmature_Drawtype; /* armature->deformflag */ -#define ARM_DEF_VGROUP 1 -#define ARM_DEF_ENVELOPE 2 -#define ARM_DEF_QUATERNION 4 -#define ARM_DEF_B_BONE_REST 8 -#define ARM_DEF_INVERT_VGROUP 16 +typedef enum eArmature_DeformFlag { + ARM_DEF_VGROUP = (1<<0), + ARM_DEF_ENVELOPE = (1<<1), + ARM_DEF_QUATERNION = (1<<2), + ARM_DEF_B_BONE_REST = (1<<3), + ARM_DEF_INVERT_VGROUP = (1<<4) +} eArmature_DeformFlag; /* armature->pathflag */ -#define ARM_PATH_FNUMS (1<<0) -#define ARM_PATH_KFRAS (1<<1) -#define ARM_PATH_HEADS (1<<2) -#define ARM_PATH_ACFRA (1<<3) +typedef enum eArmature_PathFlag { + ARM_PATH_FNUMS = (1<<0), + ARM_PATH_KFRAS = (1<<1), + ARM_PATH_HEADS = (1<<2), + ARM_PATH_ACFRA = (1<<3), + ARM_PATH_KFNOS = (1<<4) +} eArmature_PathFlag; /* armature->ghosttype */ -#define ARM_GHOST_CUR 0 -#define ARM_GHOST_RANGE 1 +typedef enum eArmature_GhostType { + ARM_GHOST_CUR = 0, + ARM_GHOST_RANGE, + ARM_GHOST_KEYS +} eArmature_GhostType; /* bone->flag */ -#define BONE_SELECTED 1 -#define BONE_ROOTSEL 2 -#define BONE_TIPSEL 4 - /* Used instead of BONE_SELECTED during transform */ -#define BONE_TRANSFORM 8 -#define BONE_CONNECTED 16 - /* 32 used to be quatrot, was always set in files, do not reuse unless you clear it always */ - /* hidden Bones when drawing Posechannels */ -#define BONE_HIDDEN_P 64 - /* For detecting cyclic dependancies */ -#define BONE_DONE 128 - /* active is on mouse clicks only */ -#define BONE_ACTIVE 256 - /* No parent rotation or scale */ -#define BONE_HINGE 512 - /* hidden Bones when drawing Armature Editmode */ -#define BONE_HIDDEN_A 1024 - /* multiplies vgroup with envelope */ -#define BONE_MULT_VG_ENV 2048 -#define BONE_NO_DEFORM 4096 - /* set to prevent destruction of its unkeyframed pose (after transform) */ -#define BONE_UNKEYED 8192 - /* set to prevent hinge child bones from influencing the transform center */ -#define BONE_HINGE_CHILD_TRANSFORM 16384 - /* No parent scale */ -#define BONE_NO_SCALE (1<<15) +typedef enum eBone_Flag { + BONE_SELECTED = (1<<0), + BONE_ROOTSEL = (1<<1), + BONE_TIPSEL = (1<<2), + BONE_TRANSFORM = (1<<3), /* Used instead of BONE_SELECTED during transform */ + BONE_CONNECTED = (1<<4), + /* 32 used to be quatrot, was always set in files, do not reuse unless you clear it always */ + BONE_HIDDEN_P = (1<<6), /* hidden Bones when drawing PoseChannels */ + BONE_DONE = (1<<7), /* For detecting cyclic dependancies */ + BONE_ACTIVE = (1<<8), /* active is on mouse clicks only */ + BONE_HINGE = (1<<9), /* No parent rotation or scale */ + BONE_HIDDEN_A = (1<<10), /* hidden Bones when drawing Armature Editmode */ + BONE_MULT_VG_ENV = (1<<11), /* multiplies vgroup with envelope */ + BONE_NO_DEFORM = (1<<12), + BONE_UNKEYED = (1<<13), /* set to prevent destruction of its unkeyframed pose (after transform) */ + BONE_HINGE_CHILD_TRANSFORM = (1<<14), /* set to prevent hinge child bones from influencing the transform center */ + BONE_NO_SCALE = (1<<15), /* No parent scale */ + BONE_HIDDEN_PG = (1<<16) /* hidden bone when drawing PoseChannels (for ghost drawing) */ +} eBone_Flag; #endif diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index 72506b0eb57..1b289650e2c 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -294,7 +294,7 @@ typedef struct bRotLimitConstraint { float ymin, ymax; float zmin, zmax; short flag; - short pad1; + short flag2; } bRotLimitConstraint; /* Limit Scaling Constraint */ @@ -303,7 +303,7 @@ typedef struct bSizeLimitConstraint { float ymin, ymax; float zmin, zmax; short flag; - short pad1; + short flag2; } bSizeLimitConstraint; /* ------------------------------------------ */ @@ -471,9 +471,11 @@ typedef enum B_CONSTRAINTCHANNEL_FLAG { #define LIMIT_YROT 0x02 #define LIMIT_ZROT 0x04 -/* not used anymore - for older Limit Location constraints only */ + /* not used anymore - for older Limit Location constraints only */ #define LIMIT_NOPARENT 0x01 - + /* for all Limit constraints - allow to be used during transform? */ +#define LIMIT_TRANSFORM 0x02 + /* python constraint -> flag */ #define PYCON_USETARGETS 0x01 #define PYCON_SCRIPTERROR 0x02 diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h index 249a4a5c36c..09af11fa64b 100644 --- a/source/blender/makesdna/DNA_customdata_types.h +++ b/source/blender/makesdna/DNA_customdata_types.h @@ -68,7 +68,8 @@ typedef struct CustomData { #define CD_PROP_INT 11 #define CD_PROP_STR 12 #define CD_ORIGSPACE 13 /* for modifier stack face location mapping */ -#define CD_NUMTYPES 14 +#define CD_ORCO 14 +#define CD_NUMTYPES 15 /* Bits for CustomDataMask */ #define CD_MASK_MVERT (1 << CD_MVERT) @@ -85,6 +86,7 @@ typedef struct CustomData { #define CD_MASK_PROP_INT (1 << CD_PROP_INT) #define CD_MASK_PROP_STR (1 << CD_PROP_STR) #define CD_MASK_ORIGSPACE (1 << CD_ORIGSPACE) +#define CD_MASK_ORCO (1 << CD_ORCO) /* CustomData.flag */ diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index c7301d4f974..22585e59c7b 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -84,11 +84,11 @@ typedef struct Material { int mode, mode_l; /* mode_l is the or-ed result of all layer modes */ short flarec, starc, linec, ringc; float hasize, flaresize, subsize, flareboost; - float strand_sta, strand_end, strand_ease; + float strand_sta, strand_end, strand_ease, strand_surfnor; char strand_uvname[32]; float sbias; /* shadow bias */ - float shad_alpha, padf; /* in use for irregular shadowbuffer */ + float shad_alpha; /* in use for irregular shadowbuffer */ /* for buttons and render*/ char rgbsel, texact, pr_type, use_nodes; @@ -121,6 +121,7 @@ typedef struct Material { float fhdist, xyfrict; short dynamode, pad2; + /* subsurface scattering */ float sss_radius[3], sss_col[3]; float sss_error, sss_scale, sss_ior; float sss_colfac, sss_texfac; @@ -191,6 +192,7 @@ typedef struct Material { #define MA_GROUP_NOLAY 0x10000000 #define MA_FACETEXTURE_ALPHA 0x20000000 #define MA_STR_B_UNITS 0x40000000 +#define MA_STR_SURFDIFF 0x80000000 #define MA_MODE_MASK 0x4fffffff /* all valid mode bits */ @@ -296,9 +298,10 @@ typedef struct Material { /* physics */ #define MAP_PA_PVEL 64 /* path cache */ -#define MAP_PA_CACHE 384 +#define MAP_PA_CACHE 912 #define MAP_PA_CLUMP 128 #define MAP_PA_KINK 256 +#define MAP_PA_ROUGH 512 /* pr_type */ #define MA_FLAT 0 diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 1bb8ce99c88..384ac37484d 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -425,7 +425,8 @@ typedef struct ParticleSystemModifierData { ModifierData modifier; struct ParticleSystem *psys; struct DerivedMesh *dm; - short flag, rt[3]; + int totdmvert, totdmedge, totdmface; + short flag, rt; } ParticleSystemModifierData; typedef enum { diff --git a/source/blender/makesdna/DNA_nla_types.h b/source/blender/makesdna/DNA_nla_types.h index d7ccfe01085..e9a0a3d0602 100644 --- a/source/blender/makesdna/DNA_nla_types.h +++ b/source/blender/makesdna/DNA_nla_types.h @@ -70,17 +70,17 @@ typedef struct bActionStrip { struct Object *object; /* For groups, the actual object being nla'ed */ float start, end; /* The range of frames covered by this strip */ float actstart, actend; /* The range of frames taken from the action */ - float actoffs, padf; /* Offset within action, for cycles and striding */ + float actoffs; /* Offset within action, for cycles and striding */ float stridelen; /* The stridelength (considered when flag & ACT_USESTRIDE) */ float repeat; /* The number of times to repeat the action range */ + float scale; /* The amount the action range is scaled by */ float blendin, blendout; /* The number of frames on either end of the strip's length to fade in/out */ char stridechannel[32]; /* Instead of stridelen, it uses an action channel */ char offs_bone[32]; /* if repeat, use this bone/channel for defining offset */ - struct ListBase modifiers; /* modifier stack */ - + ListBase modifiers; /* modifier stack */ } bActionStrip; /* strip->mode (these defines aren't really used, but are here for reference) */ @@ -88,18 +88,20 @@ typedef struct bActionStrip { #define ACTSTRIPMODE_ADD 1 /* strip->flag */ -#define ACTSTRIP_SELECT 0x01 -#define ACTSTRIP_USESTRIDE 0x02 -#define ACTSTRIP_BLENDTONEXT 0x04 /* Not implemented. Is not used anywhere */ -#define ACTSTRIP_HOLDLASTFRAME 0x08 -#define ACTSTRIP_ACTIVE 0x10 -#define ACTSTRIP_LOCK_ACTION 0x20 -#define ACTSTRIP_MUTE 0x40 -#define ACTSTRIP_REVERSE 0x80 /* This has yet to be implemented. To indicate that a strip should be played backwards */ -#define ACTSTRIP_CYCLIC_USEX 0x100 -#define ACTSTRIP_CYCLIC_USEY 0x200 -#define ACTSTRIP_CYCLIC_USEZ 0x400 -#define ACTSTRIP_AUTO_BLENDS 0x800 +typedef enum eActStrip_Flag { + ACTSTRIP_SELECT = (1<<0), + ACTSTRIP_USESTRIDE = (1<<1), + ACTSTRIP_BLENDTONEXT = (1<<2), /* Not implemented. Is not used anywhere */ + ACTSTRIP_HOLDLASTFRAME = (1<<3), + ACTSTRIP_ACTIVE = (1<<4), + ACTSTRIP_LOCK_ACTION = (1<<5), + ACTSTRIP_MUTE = (1<<6), + ACTSTRIP_REVERSE = (1<<7), /* This has yet to be implemented. To indicate that a strip should be played backwards */ + ACTSTRIP_CYCLIC_USEX = (1<<8), + ACTSTRIP_CYCLIC_USEY = (1<<9), + ACTSTRIP_CYCLIC_USEZ = (1<<10), + ACTSTRIP_AUTO_BLENDS = (1<<11) +} eActStrip_Flag; #endif diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 5b875780f8b..1080388bfab 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -141,8 +141,9 @@ typedef struct Object { char dt, dtx; char totcol; /* copy of mesh or curve or meta */ char actcol; /* currently selected material in the user interface */ - char empty_drawtype, pad1[7]; + char empty_drawtype, pad1[3]; float empty_drawsize; + float dupfacesca; /* dupliface scale */ ScriptLink scriptlink; ListBase prop; @@ -312,7 +313,16 @@ extern Object workob; #define OB_TEXTURE 5 /* this condition has been made more complex since editmode can draw textures */ -#define CHECK_OB_DRAWTEXTURE(vd, dt) ((vd->drawtype==OB_TEXTURE && dt>OB_SOLID) || (vd->drawtype==OB_SOLID && vd->flag2 & V3D_SOLID_TEX)) +#define CHECK_OB_DRAWTEXTURE(vd, dt) \ + ((vd->drawtype==OB_TEXTURE && dt>OB_SOLID) || \ + (vd->drawtype==OB_SOLID && vd->flag2 & V3D_SOLID_TEX)) + +#define CHECK_OB_DRAWFACEDOT(sce, vd, dt) \ + ( (sce->selectmode & SCE_SELECT_FACE) && \ + (vd->drawtype<=OB_SOLID) && \ + (((vd->drawtype==OB_SOLID) && (dt>=OB_SOLID) && (vd->flag2 & V3D_SOLID_TEX) && (vd->flag & V3D_ZBUF_SELECT)) == 0) \ + ) + /* dtx: flags, char! */ #define OB_AXIS 2 diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index f41a0d63142..fc2fa7cab20 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -134,9 +134,9 @@ typedef struct ParticleSettings { /* global physical properties */ float acc[3], dragfac, brownfac, dampfac; /* length */ - float length, abslength, randlength; + float length, abslength, randlength, pad; /* children */ - int child_nbr; + int child_nbr, ren_child_nbr; float parents, childsize, childrandsize; float childrad, childflat, childspread; /* clumping */ @@ -204,7 +204,7 @@ typedef struct ParticleSystem{ /* no special why's, just seem reasonable */ /* changing these (atleast upwards) should not cause any major problems */ #define MAX_PARTS 100000 /* real particles/system */ -#define MAX_PART_CHILDREN 1000 /* child particles/real particles */ +#define MAX_PART_CHILDREN 10000 /* child particles/real particles */ #define MAX_BOIDNEIGHBOURS 10 /* neigbours considered/boid */ /* part->type */ @@ -299,9 +299,10 @@ typedef struct ParticleSystem{ #define PART_DRAW_NUM 512 #define PART_DRAW_RAND_GR 1024 #define PART_DRAW_REN_ADAPT 2048 -#define PART_DRAW_VEL_LENGTH (1<<12) -#define PART_DRAW_MAT_COL (1<<13) -#define PART_DRAW_WHOLE_GR (1<<14) +#define PART_DRAW_VEL_LENGTH (1<<12) +#define PART_DRAW_MAT_COL (1<<13) +#define PART_DRAW_WHOLE_GR (1<<14) +#define PART_DRAW_REN_STRAND (1<<15) /* part->bb_align */ #define PART_BB_X 0 diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index f9418d1fc85..2dfe0ac43b6 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -364,7 +364,7 @@ typedef struct ToolSettings { short uvcalc_flag; short pad2; - + /* Image Paint (8 byte aligned please!) */ struct ImagePaintSettings imapaint; @@ -385,7 +385,21 @@ typedef struct ToolSettings { /* Multires */ char multires_subdiv_type; - char pad4[2]; + /* Skeleton generation */ + short skgen_resolution; + float skgen_threshold_internal; + float skgen_threshold_external; + float skgen_length_ratio; + float skgen_length_limit; + float skgen_angle_limit; + float skgen_correlation_limit; + float skgen_symmetry_limit; + short skgen_options; + char skgen_postpro; + char skgen_postpro_passes; + char skgen_subdivisions[3]; + + char pad3[5]; } ToolSettings; /* Used by all brushes to store their properties, which can be directly set @@ -723,6 +737,24 @@ typedef struct Scene { #define RETOPO_LINE 2 #define RETOPO_ELLIPSE 4 +/* toolsettings->skgen_options */ +#define SKGEN_FILTER_INTERNAL 1 +#define SKGEN_FILTER_EXTERNAL 2 +#define SKGEN_SYMMETRY 4 +#define SKGEN_CUT_LENGTH 8 +#define SKGEN_CUT_ANGLE 16 +#define SKGEN_CUT_CORRELATION 32 + +#define SKGEN_SUB_LENGTH 0 +#define SKGEN_SUB_ANGLE 1 +#define SKGEN_SUB_CORRELATION 2 +#define SKGEN_SUB_TOTAL 3 + +/* toolsettings->skgen_postpro */ +#define SKGEN_SMOOTH 0 +#define SKGEN_AVERAGE 1 +#define SKGEN_SHARPEN 2 + #ifdef __cplusplus } #endif diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 47c00813913..c37b332929d 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -41,8 +41,7 @@ /* themes; defines in BIF_resource.h */ struct ColorBand; -// global, button colors - +/* global, button colors */ typedef struct ThemeUI { char outline[4]; char neutral[4]; @@ -68,8 +67,9 @@ typedef struct ThemeUI { } ThemeUI; -// try to put them all in one, if needed a special struct can be created as well -// for example later on, when we introduce wire colors for ob types or so... +/* try to put them all in one, if needed a special struct can be created as well + * for example later on, when we introduce wire colors for ob types or so... + */ typedef struct ThemeSpace { char back[4]; char text[4]; @@ -94,6 +94,7 @@ typedef struct ThemeSpace { char normal[4]; char bone_solid[4], bone_pose[4]; char strip[4], strip_select[4]; + char cframe[4], pad[4]; char vertex_size, facedot_size; char bpad[2]; @@ -104,16 +105,25 @@ typedef struct ThemeSpace { char movie[4], image[4], scene[4], audio[4]; // for sequence editor char effect[4], plugin[4], transition[4], meta[4]; char editmesh_active[4]; - } ThemeSpace; +/* set of colors for use as a custom color set for Objects/Bones wire drawing */ +typedef struct ThemeWireColor { + char unselected[3]; + char selected[3]; + char active[3]; + char pad[7]; +} ThemeWireColor; +/* A theme */ typedef struct bTheme { struct bTheme *next, *prev; char name[32]; + /* Interface Elements (buttons, menus, icons) */ ThemeUI tui; + /* Individual Spacetypes */ ThemeSpace tbuts; ThemeSpace tv3d; ThemeSpace tfile; @@ -129,9 +139,12 @@ typedef struct bTheme { ThemeSpace toops; ThemeSpace ttime; ThemeSpace tnode; + + /* 20 sets of bone colors for this theme */ + ThemeWireColor tarm[20]; + /*ThemeWireColor tobj[20];*/ unsigned char bpad[4], bpad1[4]; - } bTheme; typedef struct SolidLight { @@ -214,6 +227,7 @@ extern UserDef U; /* from usiblender.c !!!! */ #define USER_CUSTOM_RANGE (1 << 17) #define USER_ADD_EDITMODE (1 << 18) #define USER_ADD_VIEWALIGNED (1 << 19) +#define USER_ADD_VIEWALIGNED (1 << 19) /* viewzom */ @@ -244,6 +258,7 @@ extern UserDef U; /* from usiblender.c !!!! */ #define USER_SHOW_VIEWPORTNAME (1 << 18) #define USER_KEYINSERTNEED (1 << 19) #define USER_ZOOM_TO_MOUSEPOS (1 << 20) +#define USER_SHOW_FPS (1 << 21) /* transopts */ diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_normalize.c b/source/blender/nodes/intern/CMP_nodes/CMP_normalize.c index 7f76cb40948..a62e4be4015 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_normalize.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_normalize.c @@ -85,11 +85,8 @@ static void node_composit_exec_normalize(void *data, bNode *node, bNodeStack **i min = *val; } } - min = MIN2(0.1, min); - max = MAX2(0.9, max); - mult = 1.0f/(max-min); - + printf("min %f max %f\n", min, max); composit3_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, NULL, &min, NULL, &mult, do_normalize, CB_VAL, CB_VAL, CB_VAL); diff --git a/source/blender/nodes/intern/CMP_nodes/Makefile b/source/blender/nodes/intern/CMP_nodes/Makefile index 036812548b4..3564bf9034b 100644 --- a/source/blender/nodes/intern/CMP_nodes/Makefile +++ b/source/blender/nodes/intern/CMP_nodes/Makefile @@ -45,3 +45,4 @@ CPPFLAGS += -I../../../blenlib CPPFLAGS += -I../../../include CPPFLAGS += -I../../../imbuf CPPFLAGS += -I../../../render/extern/include +CPPFLAGS += -I$(OPENGL_HEADERS) diff --git a/source/blender/nodes/intern/Makefile b/source/blender/nodes/intern/Makefile index bae9a8dcf1d..3b7783c5d1e 100644 --- a/source/blender/nodes/intern/Makefile +++ b/source/blender/nodes/intern/Makefile @@ -45,3 +45,4 @@ CPPFLAGS += -I../../blenlib CPPFLAGS += -I../../include CPPFLAGS += -I../../imbuf CPPFLAGS += -I../../render/extern/include +CPPFLAGS += -I$(OPENGL_HEADERS) diff --git a/source/blender/nodes/intern/SHD_nodes/Makefile b/source/blender/nodes/intern/SHD_nodes/Makefile index 6344af4a5cb..0ab6134ac93 100644 --- a/source/blender/nodes/intern/SHD_nodes/Makefile +++ b/source/blender/nodes/intern/SHD_nodes/Makefile @@ -45,3 +45,4 @@ CPPFLAGS += -I../../../blenlib CPPFLAGS += -I../../../include CPPFLAGS += -I../../../imbuf CPPFLAGS += -I../../../render/extern/include +CPPFLAGS += -I$(OPENGL_HEADERS) diff --git a/source/blender/python/BPY_interface.c b/source/blender/python/BPY_interface.c index 9c8203cf3fd..770fbf13931 100644 --- a/source/blender/python/BPY_interface.c +++ b/source/blender/python/BPY_interface.c @@ -1071,10 +1071,13 @@ static int bpy_pydriver_create_dict(void) mod = PyImport_ImportModule("math"); if (mod) { + PyDict_Merge(d, PyModule_GetDict(mod), 0); /* 0 - dont overwrite existing values */ + + /* Only keep for backwards compat! - just import all math into root, they are standard */ PyDict_SetItemString(d, "math", mod); PyDict_SetItemString(d, "m", mod); Py_DECREF(mod); - } + } mod = PyImport_ImportModule("Blender.Noise"); if (mod) { @@ -1106,7 +1109,8 @@ static int bpy_pydriver_create_dict(void) Py_DECREF(fcn); } } - + + /* TODO - change these */ /* me(meshname) == Blender.Mesh.Get(meshname) */ mod = PyImport_ImportModule("Blender.Mesh"); if (mod) { @@ -1311,7 +1315,7 @@ void BPY_pyconstraint_eval(bPythonConstraint *con, bConstraintOb *cob, ListBase tarmats= PyList_New(con->tarnum); for (ct=targets->first, index=0; ct; ct=ct->next, index++) { tarmat = newMatrixObject((float *)ct->matrix, 4, 4, Py_NEW); - PyList_SetItem(tarmats, index, tarmat); + PyList_SET_ITEM(tarmats, index, tarmat); } @@ -1712,7 +1716,7 @@ struct Object **BPY_pydriver_get_objects(IpoDriver *driver) float BPY_pydriver_eval(IpoDriver *driver) { char *expr = NULL; - PyObject *retval, *floatval, *bpy_ob = NULL; + PyObject *retval, *bpy_ob = NULL; float result = 0.0f; /* default return */ int setitem_retval; @@ -1750,15 +1754,11 @@ float BPY_pydriver_eval(IpoDriver *driver) return pydriver_error(driver); } - floatval = PyNumber_Float(retval); - Py_DECREF(retval); - - if (floatval == NULL) + result = ( float )PyFloat_AsDouble( retval ); + + if (result == -1 && PyErr_Occurred()) return pydriver_error(driver); - result = (float)PyFloat_AsDouble(floatval); - Py_DECREF(floatval); - /* remove 'self', since this dict is also used by py buttons */ if (setitem_retval == 0) PyDict_DelItemString(bpy_pydriver_Dict, "self"); @@ -1965,13 +1965,11 @@ void BPY_do_pyscript( ID * id, short event ) disable_where_scriptlink( (short)during_slink ); /* set globals in Blender module to identify scriptlink */ - EXPP_dict_set_item_str( g_blenderdict, "bylink", EXPP_incr_ret_True() ); - + PyDict_SetItemString( g_blenderdict, "bylink", Py_True); EXPP_dict_set_item_str( g_blenderdict, "link", value ); EXPP_dict_set_item_str( g_blenderdict, "event", PyString_FromString( event_to_name ( event ) ) ); - if (event == SCRIPT_POSTRENDER) event = SCRIPT_RENDER; for( index = 0; index < scriptlink->totscript; index++ ) { @@ -2007,10 +2005,9 @@ void BPY_do_pyscript( ID * id, short event ) /* cleanup bylink flag and clear link so PyObject * can be released */ - EXPP_dict_set_item_str( g_blenderdict, "bylink", EXPP_incr_ret_False() ); + PyDict_SetItemString(g_blenderdict, "bylink", Py_False); PyDict_SetItemString( g_blenderdict, "link", Py_None ); - EXPP_dict_set_item_str( g_blenderdict, "event", - PyString_FromString( "" ) ); + EXPP_dict_set_item_str( g_blenderdict, "event", PyString_FromString( "" ) ); } } @@ -2191,12 +2188,11 @@ int BPY_do_spacehandlers( ScrArea *sa, unsigned short event, } /* set globals in Blender module to identify space handler scriptlink */ - EXPP_dict_set_item_str(g_blenderdict, "bylink", EXPP_incr_ret_True()); + PyDict_SetItemString(g_blenderdict, "bylink", Py_True); /* unlike normal scriptlinks, here Blender.link is int (space event type) */ EXPP_dict_set_item_str(g_blenderdict, "link", PyInt_FromLong(space_event)); /* note: DRAW space_events set event to 0 */ EXPP_dict_set_item_str(g_blenderdict, "event", PyInt_FromLong(event)); - /* now run all assigned space handlers for this space and space_event */ for( index = 0; index < scriptlink->totscript; index++ ) { @@ -2251,7 +2247,7 @@ int BPY_do_spacehandlers( ScrArea *sa, unsigned short event, } - EXPP_dict_set_item_str(g_blenderdict, "bylink", EXPP_incr_ret_False()); + PyDict_SetItemString(g_blenderdict, "bylink", Py_False); PyDict_SetItemString(g_blenderdict, "link", Py_None ); EXPP_dict_set_item_str(g_blenderdict, "event", PyString_FromString("")); } diff --git a/source/blender/python/api2_2x/Armature.c b/source/blender/python/api2_2x/Armature.c index 6c22e831bd4..05caca1cc2f 100644 --- a/source/blender/python/api2_2x/Armature.c +++ b/source/blender/python/api2_2x/Armature.c @@ -882,9 +882,9 @@ AttributeError: static PyObject *Armature_getVertexGroups(BPy_Armature *self, void *closure) { if (self->armature->deformflag & ARM_DEF_VGROUP) - return EXPP_incr_ret(Py_True); + Py_RETURN_TRUE; else - return EXPP_incr_ret(Py_False); + Py_RETURN_FALSE; } //------------------------Armature.vertexGroups (setter) static int Armature_setVertexGroups(BPy_Armature *self, PyObject *value, void *closure) diff --git a/source/blender/python/api2_2x/CurNurb.c b/source/blender/python/api2_2x/CurNurb.c index e98b0da8f3d..6b334c01c41 100644 --- a/source/blender/python/api2_2x/CurNurb.c +++ b/source/blender/python/api2_2x/CurNurb.c @@ -776,9 +776,9 @@ static PyObject *CurNurb_isNurb( BPy_CurNurb * self ) */ if( self->nurb->bp ) { - return EXPP_incr_ret_True(); + Py_RETURN_TRUE; } else { - return EXPP_incr_ret_False(); + Py_RETURN_FALSE; } } @@ -792,9 +792,9 @@ static PyObject *CurNurb_isCyclic( BPy_CurNurb * self ) /* supposing that the flagu is always set */ if( self->nurb->flagu & CU_CYCLIC ) { - return EXPP_incr_ret_True(); + Py_RETURN_TRUE; } else { - return EXPP_incr_ret_False(); + Py_RETURN_FALSE; } } diff --git a/source/blender/python/api2_2x/Curve.c b/source/blender/python/api2_2x/Curve.c index e88ab0eeeff..adf7c39b45c 100644 --- a/source/blender/python/api2_2x/Curve.c +++ b/source/blender/python/api2_2x/Curve.c @@ -821,9 +821,9 @@ static PyObject *Curve_appendNurb( BPy_Curve * self, PyObject * value ) new_nurb->type = CU_BEZIER; new_nurb->bezt->h1 = HD_ALIGN; new_nurb->bezt->h2 = HD_ALIGN; - new_nurb->bezt->f1 = 1; - new_nurb->bezt->f2 = 1; - new_nurb->bezt->f3 = 1; + new_nurb->bezt->f1 = SELECT; + new_nurb->bezt->f2 = SELECT; + new_nurb->bezt->f3 = SELECT; new_nurb->bezt->hide = 0; /* calchandlesNurb( new_nurb ); */ } else { /* set up bp */ diff --git a/source/blender/python/api2_2x/Draw.c b/source/blender/python/api2_2x/Draw.c index 54ff927a2b3..9d151bee092 100644 --- a/source/blender/python/api2_2x/Draw.c +++ b/source/blender/python/api2_2x/Draw.c @@ -730,7 +730,7 @@ void BPY_spacescript_do_pywin_event( SpaceScript * sc, unsigned short event, if (val) { - if (uiDoBlocks( &curarea->uiblocks, event ) != UI_NOTHING) event = 0; + if (uiDoBlocks( &curarea->uiblocks, event, 1 ) != UI_NOTHING) event = 0; if (event == UI_BUT_EVENT) { /* check that event is in free range for script button events; @@ -1117,7 +1117,7 @@ static PyObject *Method_UIBlock( PyObject * self, PyObject * args ) /* Done clearing events */ uiBoundsBlock(uiblock, 5); - uiDoBlocks(&listb, 0); + uiDoBlocks(&listb, 0, 1); } uiFreeBlocks(&listb); uiblock = NULL; diff --git a/source/blender/python/api2_2x/Lamp.c b/source/blender/python/api2_2x/Lamp.c index d40cc5a2cfc..f864570395a 100644 --- a/source/blender/python/api2_2x/Lamp.c +++ b/source/blender/python/api2_2x/Lamp.c @@ -1503,7 +1503,7 @@ static PyObject *Lamp_oldsetType( BPy_Lamp * self, PyObject * value ) /* build tuple, call wrapper */ - arg = PyInt_FromLong( (long)type ); + arg = Py_BuildValue( "(i)", type ); error = EXPP_setterWrapper ( (void *)self, arg, (setter)Lamp_setType ); Py_DECREF ( arg ); return error; @@ -1562,7 +1562,7 @@ static PyObject *Lamp_oldsetMode( BPy_Lamp * self, PyObject * args ) /* build tuple, call wrapper */ - value = PyInt_FromLong( (long)flag ); + value = Py_BuildValue( "(i)", flag ); error = EXPP_setterWrapper ( (void *)self, value, (setter)Lamp_setMode ); Py_DECREF ( value ); return error; diff --git a/source/blender/python/api2_2x/Modifier.c b/source/blender/python/api2_2x/Modifier.c index a1b052eb674..704daf306e2 100644 --- a/source/blender/python/api2_2x/Modifier.c +++ b/source/blender/python/api2_2x/Modifier.c @@ -776,8 +776,6 @@ static PyObject *array_getter( BPy_Modifier * self, int type ) return PyFloat_FromDouble( md->length ); else if( type == EXPP_MOD_MERGE_DIST ) return PyFloat_FromDouble( md->merge_dist ); - else if( type == EXPP_MOD_MERGE_DIST ) - return PyFloat_FromDouble( md->merge_dist ); else if( type == EXPP_MOD_OFFSET_VEC) return newVectorObject( md->offset, 3, Py_NEW ); else if( type == EXPP_MOD_SCALE_VEC) @@ -1505,6 +1503,8 @@ static PyObject *M_Modifier_TypeDict( void ) PyInt_FromLong( eModifierType_Smooth ) ); PyConstant_Insert( d, "CAST", PyInt_FromLong( eModifierType_Cast ) ); + PyConstant_Insert( d, "DISPLACE", + PyInt_FromLong( eModifierType_Displace ) ); } return S; } diff --git a/source/blender/python/api2_2x/Object.c b/source/blender/python/api2_2x/Object.c index 6b3735a6cfd..f151653e356 100644 --- a/source/blender/python/api2_2x/Object.c +++ b/source/blender/python/api2_2x/Object.c @@ -172,6 +172,7 @@ enum obj_consts { EXPP_OBJ_ATTR_DUPOFF, EXPP_OBJ_ATTR_DUPSTA, EXPP_OBJ_ATTR_DUPEND, + EXPP_OBJ_ATTR_DUPFACESCALEFAC, EXPP_OBJ_ATTR_TIMEOFFSET, EXPP_OBJ_ATTR_DRAWSIZE, EXPP_OBJ_ATTR_PARENT_TYPE, @@ -276,6 +277,8 @@ enum obj_consts { #define EXPP_OBJECT_SBINSPRINGMAX 0.999f #define EXPP_OBJECT_SBINFRICTMIN 0.0f #define EXPP_OBJECT_SBINFRICTMAX 10.0f +#define EXPP_OBJECT_DUPFACESCALEFACMIN 0.001f +#define EXPP_OBJECT_DUPFACESCALEFACMAX 10000.0f /*****************************************************************************/ /* Python API function prototypes for the Blender module. */ @@ -1481,7 +1484,7 @@ static PyObject *Object_getBoundBox( BPy_Object * self ) switch ( self->object->type ) { case OB_MESH: me = self->object->data; - vec = (float*) mesh_get_bb(me)->vec; + vec = (float*) mesh_get_bb(self->object)->vec; break; case OB_CURVE: case OB_FONT: @@ -3843,6 +3846,9 @@ static PyObject *getFloatAttr( BPy_Object *self, void *type ) case EXPP_OBJ_ATTR_SB_INFRICT: param = object->soft->infrict; break; + case EXPP_OBJ_ATTR_DUPFACESCALEFAC: + param = object->dupfacesca; + break; default: return EXPP_ReturnPyObjError( PyExc_RuntimeError, "undefined type in getFloatAttr" ); @@ -3990,6 +3996,12 @@ static int setFloatAttrClamp( BPy_Object *self, PyObject *value, void *type ) max = EXPP_OBJECT_SBINFRICTMAX; param = &self->object->soft->infrict; break; + case EXPP_OBJ_ATTR_DUPFACESCALEFAC: + min = EXPP_OBJECT_DUPFACESCALEFACMIN; + max = EXPP_OBJECT_DUPFACESCALEFACMAX; + param = &self->object->dupfacesca; + break; + default: return EXPP_ReturnIntError( PyExc_RuntimeError, "undefined type in setFloatAttrClamp" ); @@ -4984,6 +4996,10 @@ static PyGetSetDef BPy_Object_getseters[] = { (getter)Object_getTransflagBits, (setter)Object_setTransflagBits, "Use face scale to scale all dupliFaces", (void *)OB_DUPLIFACES_SCALE}, + {"dupFacesScaleFac", + (getter)getFloatAttr, (setter)setFloatAttr, + "Use face scale to scale all dupliFaces", + (void *)EXPP_OBJ_ATTR_DUPFACESCALEFAC}, {"enableDupFrames", (getter)Object_getTransflagBits, (setter)Object_setTransflagBits, "Make copy of object for every frame", diff --git a/source/blender/python/api2_2x/Window.c b/source/blender/python/api2_2x/Window.c index c5c0860a921..8c0b3ce74a9 100644 --- a/source/blender/python/api2_2x/Window.c +++ b/source/blender/python/api2_2x/Window.c @@ -197,7 +197,6 @@ static char M_Window_EditMode_doc[] = Returns the current status. This function is mostly useful to leave\n\ edit mode before applying changes to a mesh (otherwise the changes will\n\ be lost) and then returning to it upon leaving."; - static char M_Window_PoseMode_doc[] = "() - Get the current status -- 0: not in pose mode; 1: in edit mode"; @@ -1508,8 +1507,7 @@ static PyObject *M_Window_SetPivot( PyObject * self, PyObject * value) G.vd->around = pivot; } Py_RETURN_NONE; -} - +} /*****************************************************************************/ diff --git a/source/blender/python/api2_2x/doc/Modifier.py b/source/blender/python/api2_2x/doc/Modifier.py index 0c53f470b63..1d7d2e121c9 100644 --- a/source/blender/python/api2_2x/doc/Modifier.py +++ b/source/blender/python/api2_2x/doc/Modifier.py @@ -49,6 +49,7 @@ Example:: @var Types: Constant Modifier dict used for L{ModSeq.append} to a modifier sequence and comparing with L{Modifier.type}: - ARMATURE - type value for Armature modifiers + - ARRAY - type value for Array modifiers - BOOLEAN - type value for Boolean modifiers - BUILD - type value for Build modifiers - CURVE - type value for Curve modifiers diff --git a/source/blender/python/api2_2x/doc/Object.py b/source/blender/python/api2_2x/doc/Object.py index 34cdd4b7821..08ad7c68dca 100644 --- a/source/blender/python/api2_2x/doc/Object.py +++ b/source/blender/python/api2_2x/doc/Object.py @@ -428,6 +428,8 @@ class Object: @type enableDupFaces: boolean @ivar enableDupFacesScale: The DupliFacesScale status of the object. @type enableDupFacesScale: boolean + @ivar dupFacesScaleFac: Scale factor for dupliface instance, 1.0 by default. + @type dupFacesScaleFac: float @ivar enableDupFrames: The DupliFrames status of the object. Does not indicate that this object has any dupliFrames, (as returned by L{DupObjects}) just that dupliFrames are enabled. diff --git a/source/blender/python/api2_2x/doc/Render.py b/source/blender/python/api2_2x/doc/Render.py index 61c8eda9026..d75e07de8e3 100644 --- a/source/blender/python/api2_2x/doc/Render.py +++ b/source/blender/python/api2_2x/doc/Render.py @@ -293,11 +293,11 @@ class RenderData: @type oversampling: boolean @ivar fps: Frames per second. Values are clamped to the range [1,120]. - @ivar fps_base: Frames per second base: used to generate fractional frames + @ivar fpsBase: Frames per second base: used to generate fractional frames per second values. For example, setting fps to 30 and fps_base to 1.001 will approximate the NTSC frame rate of 29.97 fps. Values are clamped to the range [1,120]. - @type fps_base: float + @type fpsBase: float @ivar timeCode: Get the current frame in HH:MM:SS:FF format. Read-only. @type timeCode: string @ivar environmentMap: Environment map rendering enabled. diff --git a/source/blender/python/api2_2x/sceneRender.c b/source/blender/python/api2_2x/sceneRender.c index 187df27e79a..aecd1d5b356 100644 --- a/source/blender/python/api2_2x/sceneRender.c +++ b/source/blender/python/api2_2x/sceneRender.c @@ -2566,7 +2566,7 @@ static PyGetSetDef BPy_RenderData_getseters[] = { (getter)RenderData_getIValueAttr, (setter)RenderData_setIValueAttrClamp, "Frames per second", (void *)EXPP_RENDER_ATTR_FPS}, - {"fps_base", + {"fpsBase", (getter)RenderData_getFloatAttr, (setter)RenderData_setFloatAttrClamp, "Frames per second base", (void *)EXPP_RENDER_ATTR_FPS_BASE}, diff --git a/source/blender/python/api2_2x/sceneSequence.c b/source/blender/python/api2_2x/sceneSequence.c index fee1bde149c..5db09b11aee 100644 --- a/source/blender/python/api2_2x/sceneSequence.c +++ b/source/blender/python/api2_2x/sceneSequence.c @@ -531,7 +531,44 @@ static PyObject *Sequence_getImages( BPy_Sequence * self ) return ret; } - +static int Sequence_setImages( BPy_Sequence * self, PyObject *value ) +{ + Strip *strip; + StripElem *se; + int i; + PyObject *list, *item; + char *basepath, *name; + + if (self->seq->type != SEQ_IMAGE) { + return EXPP_ReturnIntError( PyExc_TypeError, + "Sequence is not an image type" ); + } + + if( !PyArg_ParseTuple + ( value, "sO!", &basepath, &PyList_Type, &list ) ) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected string and optional list argument" ); + + strip = self->seq->strip; + se = strip->stripdata; + + /* for now dont support different image list sizes */ + if (PyList_Size(list) != strip->len) { + return EXPP_ReturnIntError( PyExc_TypeError, + "at the moment only image lista with the same number of images as the strip are supported" ); + } + + strncpy(strip->dir, basepath, sizeof(strip->dir)); + + for (i=0; i<strip->len; i++, se++) { + name = PyString_AsString(PyList_GetItem(list, i)); + if (name) { + strncpy(se->name, name, sizeof(se->name)); + } + } + + return 0; +} /* * get floating point attributes @@ -569,7 +606,7 @@ static PyObject *getIntAttr( BPy_Sequence *self, void *type ) break; default: return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "undefined type in getFloatAttr" ); + "undefined type in getIntAttr" ); } return PyInt_FromLong( param ); @@ -724,7 +761,7 @@ static PyGetSetDef BPy_Sequence_getseters[] = { "Sequence name", NULL}, {"images", - (getter)Sequence_getImages, (setter)NULL, + (getter)Sequence_getImages, (setter)Sequence_setImages, "Sequence scene", NULL}, diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index a8abf85a285..d202ea1eed5 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -81,6 +81,7 @@ typedef struct RenderLayer { float *rectf; /* 4 float, standard rgba buffer (read not above!) */ float *acolrect; /* 4 float, optional transparent buffer, needs storage for display updates */ + float *scolrect; /* 4 float, optional strand buffer, needs storage for display updates */ ListBase passes; @@ -121,7 +122,7 @@ typedef struct RenderResult { } RenderResult; typedef struct RenderStats { - int totface, totvert, tothalo, totlamp, totpart; + int totface, totvert, totstrand, tothalo, totlamp, totpart; short curfield, curblur, curpart, partsdone, convertdone; double starttime, lastframetime; char *infostr; @@ -213,6 +214,7 @@ void RE_zbuf_accumulate_vecblur(struct NodeBlurData *nbd, int xsize, int ysize, void RE_Database_Baking(struct Render *re, struct Scene *scene, int type, struct Object *actob); void RE_DataBase_GetView(struct Render *re, float mat[][4]); +void RE_GetCameraWindow(struct Render *re, struct Object *camera, int frame, float mat[][4]); #endif /* RE_PIPELINE_H */ diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h index 7717d6fdc48..8a4f6bb2ec8 100644 --- a/source/blender/render/extern/include/RE_shader_ext.h +++ b/source/blender/render/extern/include/RE_shader_ext.h @@ -120,7 +120,7 @@ typedef struct ShadeInput /* end direct copy from material */ /* individual copies: */ - int har; + int har; /* hardness */ float layerfac; /* texture coordinates */ @@ -154,6 +154,8 @@ typedef struct ShadeInput /* stored copy of original face normal (facenor) * before flipping. Used in Front/back output on geometry node */ float orignor[3]; + /* for strand shading, normal at the surface */ + float surfnor[3], surfdist; /* from initialize, part or renderlayer */ short do_preview; /* for nodes, in previewrender */ diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index c20d27bfcdc..f7f2222e98d 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -48,6 +48,7 @@ struct MemArena; struct VertTableNode; struct VlakTableNode; struct GHash; +struct RenderBuckets; #define TABLEINITSIZE 1024 #define LAMPINITSIZE 256 @@ -159,7 +160,7 @@ struct Render float cfra; /* render database */ - int totvlak, totvert, tothalo, totlamp; + int totvlak, totvert, tothalo, totstrand, totlamp; ListBase lights; /* GroupObject pointers */ ListBase lampren; /* storage, for free */ @@ -167,9 +168,13 @@ struct Render struct VertTableNode *vertnodes; int vlaknodeslen; struct VlakTableNode *vlaknodes; + int strandnodeslen; + struct StrandTableNode *strandnodes; int blohalen; struct HaloRen **bloha; ListBase objecttable; + ListBase strandbufs; + struct RenderBuckets *strandbuckets; struct Image *backbuf, *bakebuf; @@ -234,7 +239,7 @@ typedef struct ShadBuf { typedef struct ObjectRen { struct ObjectRen *next, *prev; struct Object *ob, *par; - int index, startvert, endvert, startface, endface; + int index, startvert, endvert, startface, endface, startstrand, endstrand; float *vectors; } ObjectRen; @@ -297,6 +302,36 @@ typedef struct HaloRen struct Material *mat; } HaloRen; +typedef struct StrandVert { + float co[3]; + float strandco; +} StrandVert; + +typedef struct StrandBuffer { + struct StrandBuffer *next, *prev; + struct StrandVert *vert; + int totvert; + + struct Object *ob; + struct Material *ma; + unsigned int lay; + int overrideuv; + int flag, maxdepth; + float adaptcos; + + float winmat[4][4]; + int winx, winy; +} StrandBuffer; + +typedef struct StrandRen { + StrandVert *vert; + StrandBuffer *buffer; + int totvert, flag; + int clip, index; + float orco[3]; +} StrandRen; + + struct LampRen; struct MTex; @@ -417,6 +452,9 @@ typedef struct LampRen { #define R_SNPROJ_Z 4 #define R_FLIPPED_NO 8 +/* strandbuffer->flag */ +#define R_STRAND_BSPLINE 1 +#define R_STRAND_B_UNITS 2 #endif /* RENDER_TYPES_H */ diff --git a/source/blender/render/intern/include/renderdatabase.h b/source/blender/render/intern/include/renderdatabase.h index dc70ade25ae..febf90d9d6e 100644 --- a/source/blender/render/intern/include/renderdatabase.h +++ b/source/blender/render/intern/include/renderdatabase.h @@ -39,6 +39,8 @@ struct Render; struct MCol; struct MTFace; struct CustomData; +struct StrandBuffer; +struct StrandRen; #define RE_QUAD_MASK 0x7FFFFFF #define RE_QUAD_OFFS 0x8000000 @@ -59,9 +61,20 @@ typedef struct VlakTableNode { struct MTFace **mtface; struct MCol **mcol; int totmtface, totmcol; + float *surfnor; struct CustomDataNames **names; } VlakTableNode; +typedef struct StrandTableNode { + struct StrandRen *strand; + float *winspeed; + float *surfnor; + struct MCol **mcol; + float **uv; + int totuv, totmcol; + struct CustomDataNames **names; +} StrandTableNode; + typedef struct CustomDataNames{ struct CustomDataNames *next, *prev; @@ -75,18 +88,20 @@ void free_renderdata_vertnodes(struct VertTableNode *vertnodes); void free_renderdata_vlaknodes(struct VlakTableNode *vlaknodes); void set_normalflags(Render *re); -void project_renderdata(struct Render *re, void (*projectfunc)(float *, float mat[][4], float *), int do_pano, float xoffs); +void project_renderdata(struct Render *re, void (*projectfunc)(float *, float mat[][4], float *), int do_pano, float xoffs, int do_buckets); /* functions are not exported... so wrong names */ struct VlakRen *RE_findOrAddVlak(struct Render *re, int nr); struct VertRen *RE_findOrAddVert(struct Render *re, int nr); +struct StrandRen *RE_findOrAddStrand(struct Render *re, int nr); struct HaloRen *RE_findOrAddHalo(struct Render *re, int nr); struct HaloRen *RE_inithalo(struct Render *re, struct Material *ma, float *vec, float *vec1, float *orco, float hasize, float vectsize, int seed); struct HaloRen *RE_inithalo_particle(struct Render *re, struct DerivedMesh *dm, struct Material *ma, float *vec, float *vec1, float *orco, float *uvco, float hasize, float vectsize, int seed); -void RE_addRenderObject(struct Render *re, struct Object *ob, struct Object *par, int index, int sve, int eve, int sfa, int efa); +void RE_addRenderObject(struct Render *re, struct Object *ob, struct Object *par, int index, int sve, int eve, int sfa, int efa, int sst, int est); +struct StrandBuffer *RE_addStrandBuffer(struct Render *re, struct Object *ob, int totvert); float *RE_vertren_get_sticky(struct Render *re, struct VertRen *ver, int verify); float *RE_vertren_get_stress(struct Render *re, struct VertRen *ver, int verify); @@ -97,6 +112,12 @@ float *RE_vertren_get_winspeed(struct Render *re, struct VertRen *ver, int verif struct MTFace *RE_vlakren_get_tface(struct Render *re, VlakRen *ren, int n, char **name, int verify); struct MCol *RE_vlakren_get_mcol(struct Render *re, VlakRen *ren, int n, char **name, int verify); +float *RE_vlakren_get_surfnor(struct Render *re, VlakRen *ren, int verify); + +float *RE_strandren_get_winspeed(struct Render *re, struct StrandRen *strand, int verify); +float *RE_strandren_get_surfnor(struct Render *re, struct StrandRen *strand, int verify); +float *RE_strandren_get_uv(struct Render *re, struct StrandRen *strand, int n, char **name, int verify); +struct MCol *RE_strandren_get_mcol(struct Render *re, struct StrandRen *strand, int n, char **name, int verify); struct VertRen *RE_vertren_copy(struct Render *re, struct VertRen *ver); struct VlakRen *RE_vlakren_copy(struct Render *re, struct VlakRen *vlr); diff --git a/source/blender/render/intern/include/shading.h b/source/blender/render/intern/include/shading.h index 902899bce94..3390c32ebfe 100644 --- a/source/blender/render/intern/include/shading.h +++ b/source/blender/render/intern/include/shading.h @@ -29,6 +29,9 @@ struct RenderPart; struct RenderLayer; struct PixStr; struct LampRen; +struct VlakRen; +struct StrandSegment; +struct StrandPoint; /* shadeinput.c */ @@ -56,6 +59,8 @@ void shade_input_set_viewco(struct ShadeInput *shi, float x, float y, float z); void shade_input_set_uv(struct ShadeInput *shi); void shade_input_set_normals(struct ShadeInput *shi); void shade_input_set_shade_texco(struct ShadeInput *shi); +void shade_input_set_strand(struct ShadeInput *shi, struct StrandRen *strand, struct StrandPoint *spoint); +void shade_input_set_strand_texco(struct ShadeInput *shi, struct StrandRen *strand, struct StrandVert *svert, struct StrandPoint *spoint); void shade_input_do_shade(struct ShadeInput *shi, struct ShadeResult *shr); void shade_input_initialize(struct ShadeInput *shi, struct RenderPart *pa, struct RenderLayer *rl, int sample); diff --git a/source/blender/render/intern/include/strand.h b/source/blender/render/intern/include/strand.h new file mode 100644 index 00000000000..55c789de764 --- /dev/null +++ b/source/blender/render/intern/include/strand.h @@ -0,0 +1,192 @@ +/* + * $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: none of this file. + * + * Contributor(s): Brecht Van Lommel. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef STRAND_H +#define STRAND_H + +struct StrandVert; +struct StrandRen; +struct StrandBuffer; +struct ShadeSample; +struct StrandPart; +struct Render; +struct RenderPart; +struct RenderBuckets; +struct RenderPrimitiveIterator; +struct ZSpan; + +typedef struct StrandPoint { + /* position within segment */ + float t; + + /* camera space */ + float co[3]; + float nor[3]; + float tan[3]; + float strandco; + float width; + + /* derivatives */ + float dtco[3], dsco[3]; + float dtstrandco; + + /* outer points */ + float co1[3], co2[3]; + float hoco1[4], hoco2[4]; + float zco1[3], zco2[3]; + + /* screen space */ + float hoco[4]; + float x, y; +} StrandPoint; + +typedef struct StrandSegment { + struct StrandVert *v[4]; + struct StrandRen *strand; + struct StrandBuffer *buffer; + float sqadaptcos; + + StrandPoint point1, point2; + int shaded; +} StrandSegment; + +void strand_eval_point(StrandSegment *sseg, StrandPoint *spoint); +void render_strand_segment(struct Render *re, struct StrandPart *spart, struct ZSpan *zspan, StrandSegment *sseg); +void project_strands(Render *re, void (*projectfunc)(float *, float mat[][4], float *), int do_pano, int do_buckets); + +struct RenderBuckets *init_buckets(struct Render *re); +void add_buckets_primitive(struct RenderBuckets *buckets, float *min, float *max, void *prim); +void free_buckets(struct RenderBuckets *buckets); +void project_hoco_to_bucket(struct RenderBuckets *buckets, float *hoco, float *bucketco); + +struct RenderPrimitiveIterator *init_primitive_iterator(struct Render *re, struct RenderBuckets *buckets, struct RenderPart *pa); +void *next_primitive_iterator(struct RenderPrimitiveIterator *iter); +void free_primitive_iterator(struct RenderPrimitiveIterator *iter); + +#endif + +/* + * $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: none of this file. + * + * Contributor(s): Brecht Van Lommel. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef STRAND_H +#define STRAND_H + +struct StrandVert; +struct StrandRen; +struct StrandBuffer; +struct ShadeSample; +struct StrandPart; +struct Render; +struct RenderPart; +struct RenderBuckets; +struct RenderPrimitiveIterator; +struct ZSpan; + +typedef struct StrandPoint { + /* position within segment */ + float t; + + /* camera space */ + float co[3]; + float nor[3]; + float tan[3]; + float strandco; + float width; + + /* derivatives */ + float dtco[3], dsco[3]; + float dtstrandco; + + /* outer points */ + float co1[3], co2[3]; + float hoco1[4], hoco2[4]; + float zco1[3], zco2[3]; + + /* screen space */ + float hoco[4]; + float x, y; +} StrandPoint; + +typedef struct StrandSegment { + struct StrandVert *v[4]; + struct StrandRen *strand; + struct StrandBuffer *buffer; + float sqadaptcos; + + StrandPoint point1, point2; + int shaded; +} StrandSegment; + +void strand_eval_point(StrandSegment *sseg, StrandPoint *spoint); +void render_strand_segment(struct Render *re, struct StrandPart *spart, struct ZSpan *zspan, StrandSegment *sseg); +void project_strands(Render *re, void (*projectfunc)(float *, float mat[][4], float *), int do_pano, int do_buckets); + +struct RenderBuckets *init_buckets(struct Render *re); +void add_buckets_primitive(struct RenderBuckets *buckets, float *min, float *max, void *prim); +void free_buckets(struct RenderBuckets *buckets); +void project_hoco_to_bucket(struct RenderBuckets *buckets, float *hoco, float *bucketco); + +struct RenderPrimitiveIterator *init_primitive_iterator(struct Render *re, struct RenderBuckets *buckets, struct RenderPart *pa); +void *next_primitive_iterator(struct RenderPrimitiveIterator *iter); +void free_primitive_iterator(struct RenderPrimitiveIterator *iter); + +#endif + diff --git a/source/blender/render/intern/include/zbuf.h b/source/blender/render/intern/include/zbuf.h index ed3f93adfdd..0d88d40e7ac 100644 --- a/source/blender/render/intern/include/zbuf.h +++ b/source/blender/render/intern/include/zbuf.h @@ -50,6 +50,7 @@ void set_part_zbuf_clipflag(struct RenderPart *pa); void zbuffer_shadow(struct Render *re, struct LampRen *lar, int *rectz, int size, float jitx, float jity); void zbuffer_solid(struct RenderPart *pa, unsigned int layer, short layflag); unsigned short *zbuffer_transp_shade(struct RenderPart *pa, struct RenderLayer *rl, float *pass); +unsigned short *zbuffer_strands_shade(struct Render *re, struct RenderPart *pa, struct RenderLayer *rl, float *pass); void convert_zbuf_to_distbuf(struct RenderPart *pa, struct RenderLayer *rl); void zbuffer_sss(RenderPart *pa, unsigned int lay, void *handle, void (*func)(void *, int, int, int, int)); diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index f64ff1501cb..9280b457a4c 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -966,9 +966,7 @@ static float *get_object_orco(Render *re, Object *ob) orco = BLI_ghash_lookup(re->orco_hash, ob); if (!orco) { - if (ob->type==OB_MESH) { - orco = mesh_create_orco_render(ob); - } else if (ELEM(ob->type, OB_CURVE, OB_FONT)) { + if (ELEM(ob->type, OB_CURVE, OB_FONT)) { orco = make_orco_curve(ob); } else if (ob->type==OB_SURF) { orco = make_orco_surf(ob); @@ -981,6 +979,14 @@ static float *get_object_orco(Render *re, Object *ob) return orco; } +static void set_object_orco(Render *re, void *ob, float *orco) +{ + if (!re->orco_hash) + re->orco_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); + + BLI_ghash_insert(re->orco_hash, ob, orco); +} + static void free_mesh_orco_hash(Render *re) { if (re->orco_hash) { @@ -1212,12 +1218,10 @@ static void render_particle_system(Render *re, Object *ob, Object *par, PartEff if(useFluidsimParticles) { ma->alpha = iniAlpha; }// FSPARTICLE restore... } -/* ------------------------------------------------------------------------- */ - /* future thread problem... */ -static void static_particle_strand(Render *re, Object *ob, Material *ma, float *orco, float *uvco, int totuv, - float *vec, float *vec1, float ctime, int first, int line, - int adapt, float adapt_angle, float adapt_pix, int override_uv) +static void static_particle_strand(Render *re, Object *ob, Material *ma, float *orco, float *surfnor, + float *uvco, int totuv, float *vec, float *vec1, float ctime, + int first, int line, int adapt, float adapt_angle, float adapt_pix, int override_uv) { static VertRen *v1= NULL, *v2= NULL; VlakRen *vlr; @@ -1314,6 +1318,11 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float * vlr->ec= ME_V2V3; vlr->lay= ob->lay; + if(surfnor) { + float *snor= RE_vlakren_get_surfnor(re, vlr, 1); + VECCOPY(snor, surfnor); + } + if(uvco){ for(i=0; i<totuv; i++){ MTFace *mtf; @@ -1428,6 +1437,11 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float * vlr->ec= ME_V2V3; vlr->lay= ob->lay; + if(surfnor) { + float *snor= RE_vlakren_get_surfnor(re, vlr, 1); + VECCOPY(snor, surfnor); + } + if(uvco){ for(i=0; i<totuv; i++){ MTFace *mtf; @@ -1683,7 +1697,7 @@ static void particle_billboard(Render *re, Object *ob, Material *ma, Object *bb_ } } static void render_new_particle(Render *re, Object *ob, DerivedMesh *dm, Material *ma, int path, int first, int line, - float time, float *loc, float *loc1, float *orco, int totuv, float *uvco, + float time, float *loc, float *loc1, float *orco, float *surfnor, int totuv, float *uvco, float size, int seed, int override_uv, int adapt, float adapt_angle, float adapt_pix) { HaloRen *har=0; @@ -1695,7 +1709,7 @@ static void render_new_particle(Render *re, Object *ob, DerivedMesh *dm, Materia if(har) har->lay= ob->lay; } else - static_particle_strand(re, ob, ma, orco, uvco, totuv, loc, loc1, time, first, line, adapt, adapt_angle, adapt_pix, override_uv); + static_particle_strand(re, ob, ma, orco, surfnor, uvco, totuv, loc, loc1, time, first, line, adapt, adapt_angle, adapt_pix, override_uv); } else{ har= RE_inithalo_particle(re, dm, ma, loc, NULL, orco, uvco, size, 0.0, seed); @@ -1715,8 +1729,12 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps ParticleKey *states=0; ParticleKey state; ParticleCacheKey *cache=0; - float loc[3],loc1[3],loc0[3],vel[3],imat[4][4], time; - float *orco=0,*uvco=0; + StrandBuffer *strandbuf=0; + StrandVert *svert=0; + StrandRen *strand=0; + RNG *rng= 0; + float loc[3],loc1[3],loc0[3],vel[3],mat[4][4],nmat[3][3],co[3],nor[3],time; + float *orco=0,*surfnor=0,*uvco=0, strandlen=0.0f, curlen=0.0f; float hasize, pa_size, pa_time, r_tilt, cfra=bsystem_time(ob,(float)CFRA,0.0); float loc_tex[3], size_tex[3], adapt_angle=0.0, adapt_pix=0.0, random; int i, a, k, max_k=0, totpart, totvlako, totverto, totuv=0, override_uv=-1; @@ -1749,9 +1767,13 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps if(!(psmd->modifier.mode & eModifierMode_Render)) return 0; + if(G.rendering == 0) { /* preview render */ + totchild = (int)((float)totchild * (float)part->disp / 100.0f); + } + psys->flag|=PSYS_DRAWING; - BLI_srandom(psys->seed); + rng= rng_new(psys->seed); ma= give_render_material(re, ob, part->omat); @@ -1766,9 +1788,15 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps RE_vlakren_set_customdata_names(re, &psmd->dm->faceData); totuv=CustomData_number_of_layers(&psmd->dm->faceData,CD_MTFACE); - if(ma->texco & TEXCO_UV && totuv) + if(ma->texco & TEXCO_UV && totuv) { uvco = MEM_callocN(totuv*2*sizeof(float),"particle_uvs"); + if(ma->strand_uvname[0]) { + override_uv= CustomData_get_named_layer_index(&psmd->dm->faceData,CD_MTFACE,ma->strand_uvname); + override_uv-= CustomData_get_layer_index(&psmd->dm->faceData,CD_MTFACE); + } + } + if(part->draw_as==PART_DRAW_BB){ int first_uv=CustomData_get_layer_index(&psmd->dm->faceData,CD_MTFACE); @@ -1812,7 +1840,10 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps re->flag |= R_HALO; - Mat4Invert(imat,ob->obmat); + MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat); + MTC_Mat4Invert(ob->imat, mat); /* need to be that way, for imat texture */ + Mat3CpyMat4(nmat, ob->imat); + Mat3Transp(nmat); totvlako= re->totvlak; totverto= re->totvert; @@ -1831,22 +1862,38 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps //if(part->phystype==PART_PHYS_KEYED && (psys->flag&PSYS_BAKED)==0) // path_nbr*=psys->totkeyed; - if(path_nbr){ - if((ma->mode & (MA_HALO|MA_WIRE))==0){ + if(path_nbr) { + if((ma->mode & (MA_HALO|MA_WIRE))==0) { orco= MEM_mallocN(3*sizeof(float)*(totpart+totchild), "particle orcos"); - if (!re->orco_hash) - re->orco_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); - BLI_ghash_insert(re->orco_hash, psys, orco); + set_object_orco(re, psys, orco); } path=1; } - if(part->draw&PART_DRAW_REN_ADAPT){ + if(part->draw&PART_DRAW_REN_ADAPT) { adapt=1; adapt_pix=(float)part->adapt_pix; adapt_angle=cos((float)part->adapt_angle*(float)(M_PI/180.0)); } + if(re->r.renderer==R_INTERN && part->draw&PART_DRAW_REN_STRAND) { + strandbuf= RE_addStrandBuffer(re, ob, (totpart+totchild)*(path_nbr+1)); + strandbuf->ma= ma; + strandbuf->lay= ob->lay; + Mat4CpyMat4(strandbuf->winmat, re->winmat); + strandbuf->winx= re->winx; + strandbuf->winy= re->winy; + strandbuf->maxdepth= 2; /* TODO */ + strandbuf->adaptcos= cos((float)part->adapt_angle*(float)(M_PI/180.0)); + strandbuf->overrideuv= override_uv; + + if(part->flag & PART_HAIR_BSPLINE) + strandbuf->flag |= R_STRAND_BSPLINE; + if(ma->mode & MA_STR_B_UNITS) + strandbuf->flag |= R_STRAND_B_UNITS; + + svert= strandbuf->vert; + } } } else if(keys_possible && part->draw&PART_DRAW_KEYS){ @@ -1865,7 +1912,8 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps /* 3. start creating renderable things */ for(a=0,pa=pars; a<totpart+totchild; a++, pa++) { - random = BLI_frand(); + random = rng_getFloat(rng); + if(a<totpart){ if(pa->flag & PARS_UNEXIST) continue; @@ -1888,10 +1936,10 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps /* get orco */ if(tpsys && (part->from==PART_FROM_PARTICLE || part->phystype==PART_PHYS_NO)){ tpa=tpsys->particles+pa->num; - psys_particle_on_emitter(ob, psmd,tpart->from,tpa->num, -1,tpa->fuv,tpa->foffset,orco,0,0,0); + psys_particle_on_emitter(ob, psmd,tpart->from,tpa->num, -1,tpa->fuv,tpa->foffset,co,nor,0,0,orco,0); } else - psys_particle_on_emitter(ob, psmd,part->from,pa->num,-1,pa->fuv,pa->foffset,orco,0,0,0); + psys_particle_on_emitter(ob, psmd,part->from,pa->num,-1,pa->fuv,pa->foffset,co,nor,0,0,orco,0); if(uvco && ELEM(part->from,PART_FROM_FACE,PART_FROM_VOLUME)){ layer=psmd->dm->faceData.layers + CustomData_get_layer_index(&psmd->dm->faceData,CD_MFACE); @@ -1906,8 +1954,6 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps psys_interpolate_uvs(mtface,mface->v4,pa->fuv,uvco+2*n); } - override_uv=CustomData_get_named_layer_index(&psmd->dm->faceData,CD_MTFACE,ma->strand_uvname)- - CustomData_get_layer_index(&psmd->dm->faceData,CD_MTFACE); } pa_size=pa->size; @@ -1923,7 +1969,8 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps } else{ ChildParticle *cpa= psys->child+a-totpart; - pa_time=psys_get_child_time(psys, a-totpart, cfra); + + pa_time=psys_get_child_time(psys, cpa, cfra); if((part->flag&PART_ABS_TIME)==0){ if(ma->ipo){ @@ -1938,14 +1985,14 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps } } - pa_size=psys_get_child_size(psys, a-totpart, cfra, &pa_time); + pa_size=psys_get_child_size(psys, cpa, cfra, &pa_time); r_tilt=2.0f*cpa->rand[2]; /* get orco */ psys_particle_on_emitter(ob, psmd, (part->childtype == PART_CHILD_FACES)? PART_FROM_FACE: PART_FROM_PARTICLE, - cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,orco,0,0,0); + cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co,nor,0,0,orco,0); if(uvco){ layer=psmd->dm->faceData.layers + CustomData_get_layer_index(&psmd->dm->faceData,CD_MFACE); @@ -1984,7 +2031,7 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps } } - if(path_nbr){ + if(path_nbr) { cache = psys->childcache[a-totpart]; max_k = (int)cache->steps; } @@ -1996,9 +2043,49 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps orco[2] = (orco[2]-loc_tex[2])/size_tex[2]; } + /* surface normal shading setup */ + if(ma->mode_l & MA_STR_SURFDIFF) { + Mat3MulVecfl(nmat, nor); + surfnor= nor; + } + else + surfnor= NULL; + + /* strand render setup */ + if(strandbuf) { + strand= RE_findOrAddStrand(re, re->totstrand++); + strand->buffer= strandbuf; + strand->vert= svert; + VECCOPY(strand->orco, orco); + + if(surfnor) { + float *snor= RE_strandren_get_surfnor(re, strand, 1); + VECCOPY(snor, surfnor); + } + + if(uvco){ + for(i=0; i<totuv; i++){ + if(i != override_uv) { + float *uv= RE_strandren_get_uv(re, strand, i, NULL, 1); + + uv[0]= uvco[2*i]; + uv[1]= uvco[2*i+1]; + } + } + } + } + + /* strandco computation setup */ + if(path_nbr) { + strandlen= 0.0f; + curlen= 0.0f; + for(k=1; k<=path_nbr; k++) + if(k<=max_k) + strandlen += VecLenf((cache+k-1)->co, (cache+k)->co); + } + for(k=0; k<=path_nbr; k++){ if(path_nbr){ - time=(float)k/(float)path_nbr; if(k<=max_k){ //bti->convert_bake_key(bsys,cache+k,0,(void*)&state); //copy_particle_key(&state,cache+k,0); @@ -2007,6 +2094,10 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps } else continue; + + if(k > 0) + curlen += VecLenf((cache+k-1)->co, (cache+k)->co); + time= curlen/strandlen; } else{ time=0.0f; @@ -2019,7 +2110,7 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps if(part->draw_as!=PART_DRAW_BB) MTC_Mat4MulVecfl(re->viewmat,loc); - if(part->draw_as==PART_DRAW_LINE){ + if(part->draw_as==PART_DRAW_LINE) { VECCOPY(vel,state.vel); //VECADD(vel,vel,state.co); MTC_Mat4Mul3Vecfl(re->viewmat,vel); @@ -2031,27 +2122,33 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps VECADDFAC(loc1,loc,vel,part->draw_line[1]); render_new_particle(re,ob,psmd->dm,ma,1,0,1,0.0f,loc0,loc1, - orco,totuv,uvco,hasize,seed,override_uv,0,0,0); + orco,surfnor,totuv,uvco,hasize,seed,override_uv,0,0,0); } - else if(part->draw_as==PART_DRAW_BB){ + else if(part->draw_as==PART_DRAW_BB) { VECCOPY(vel,state.vel); //MTC_Mat4Mul3Vecfl(re->viewmat,vel); particle_billboard(re,ob,ma,bb_ob,loc,vel,pa_size,part->bb_tilt*(1.0f-part->bb_rand_tilt*r_tilt), part->bb_align,part->draw&PART_DRAW_BB_LOCK, a,totpart+totchild,part->bb_uv_split,part->bb_anim,part->bb_split_offset,random,pa_time,part->bb_offset,uv); } + else if(strandbuf) { + VECCOPY(svert->co, loc); + svert->strandco= -1.0f + 2.0f*time; + svert++; + strand->totvert++; + } else{ if(k==1){ VECSUB(loc0,loc1,loc); VECADD(loc0,loc1,loc0); render_new_particle(re,ob,psmd->dm,ma,path,1,0,0.0f,loc1,loc0, - orco,totuv,uvco,hasize,seed,override_uv, + orco,surfnor,totuv,uvco,hasize,seed,override_uv, adapt,adapt_angle,adapt_pix); } if(path_nbr==0 || k) render_new_particle(re,ob,psmd->dm,ma,path,0,0,time,loc,loc1, - orco,totuv,uvco,hasize,seed,override_uv, + orco,surfnor,totuv,uvco,hasize,seed,override_uv, adapt,adapt_angle,adapt_pix); VECCOPY(loc1,loc); @@ -2060,6 +2157,9 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps if(orco1==0) orco+=3; + + if(re->test_break()) + break; } /* 4. clean up */ @@ -2076,6 +2176,8 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps if(states) MEM_freeN(states); + + rng_free(rng); psys->flag &= ~PSYS_DRAWING; @@ -2084,9 +2186,9 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps psys->lattice=0; } - if(path && (ma->mode & MA_TANGENT_STR)==0) + if(path && (ma->mode_l & MA_TANGENT_STR)==0) calc_vertexnormals(re, totverto, totvlako, 0); - + return 1; } @@ -2124,9 +2226,7 @@ static void render_static_particle_system(Render *re, Object *ob, PartEff *paf) /* orcos */ if(!(ma->mode & (MA_HALO|MA_WIRE))) { orco= MEM_mallocN(3*sizeof(float)*paf->totpart, "static particle orcos"); - if (!re->orco_hash) - re->orco_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); - BLI_ghash_insert(re->orco_hash, paf, orco); /* pointer is particles, otherwise object uses it */ + set_object_orco(re, paf, orco); } mesh_get_texspace(ob->data, loc_tex, NULL, size_tex); @@ -2242,7 +2342,7 @@ static void render_static_particle_system(Render *re, Object *ob, PartEff *paf) if(ctime + paf->staticstep < mtime) strandco= (ctime-pa->time)/(mtime-pa->time); - static_particle_strand(re, ob, ma, orco, 0, 0, vec, vec1, strandco, first, 0,0,0,0,-1); + static_particle_strand(re, ob, ma, orco, 0, 0, 0, vec, vec1, strandco, first, 0,0,0,0,-1); } } @@ -2569,6 +2669,7 @@ static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts MSticky *ms = NULL; PartEff *paf; DerivedMesh *dm; + CustomDataMask mask; float xn, yn, zn, imat[3][3], mat[4][4]; //nor[3], float *orco=0; int a, a1, ok, need_orco=0, need_stress=0, need_tangent=0, totvlako, totverto, vertofs; @@ -2632,14 +2733,22 @@ static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts if(test_for_displace(re, ob ) ) only_verts= 0; + mask= CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL; if(!only_verts) - if(need_orco) orco = get_object_orco(re, ob); + if(need_orco) + mask |= CD_MASK_ORCO; - dm = mesh_create_derived_render(ob, - CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL); - + dm= mesh_create_derived_render(ob, mask); if(dm==NULL) return; /* in case duplicated object fails? */ + if(mask & CD_MASK_ORCO) { + orco= dm->getVertDataArray(dm, CD_ORCO); + if(orco) { + orco= MEM_dupallocN(orco); + set_object_orco(re, ob, orco); + } + } + if((ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) && (ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN)&& (ob->fluidsimSettings->meshSurface) ) { @@ -2933,8 +3042,13 @@ static void initshadowbuf(Render *re, LampRen *lar, float mat[][4]) static void area_lamp_vectors(LampRen *lar) { - float xsize= 0.5*lar->area_size, ysize= 0.5*lar->area_sizey; + float xsize= 0.5*lar->area_size, ysize= 0.5*lar->area_sizey, multifac; + /* make it smaller, so area light can be multisampled */ + multifac= 1.0f/sqrt((float)lar->ray_totsamp); + xsize *= multifac; + ysize *= multifac; + /* corner vectors */ lar->area[0][0]= lar->co[0] - xsize*lar->mat[0][0] - ysize*lar->mat[1][0]; lar->area[0][1]= lar->co[1] - xsize*lar->mat[0][1] - ysize*lar->mat[1][1]; @@ -3069,6 +3183,7 @@ static GroupObject *add_render_lamp(Render *re, Object *ob) } area_lamp_vectors(lar); + init_jitter_plane(lar); // subsamples } else lar->ray_totsamp= 0; @@ -3691,10 +3806,11 @@ static void init_render_object(Render *re, Object *ob, Object *par, int index, i static double lasttime= 0.0; double time; float mat[4][4]; - int startface, startvert, allow_render=1; + int startface, startvert, startstrand, allow_render=1; startface=re->totvlak; startvert=re->totvert; + startstrand=re->totstrand; ob->flag |= OB_DONE; @@ -3735,18 +3851,20 @@ static void init_render_object(Render *re, Object *ob, Object *par, int index, i if(allow_render==0 && ob->type==OB_MESH) dm = mesh_create_derived_render(ob, CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL); - for(; psys; psys=psys->next) + for(; psys; psys=psys->next) { render_new_particle_system(re, ob, psys); + psys_free_render_memory(ob, psys); + } if(dm) dm->release(dm); } /* generic post process here */ - if(startvert!=re->totvert) { - - RE_addRenderObject(re, ob, par, index, startvert, re->totvert, startface, re->totvlak); + if(startvert!=re->totvert || startstrand!=re->totstrand) + RE_addRenderObject(re, ob, par, index, startvert, re->totvert, startface, re->totvlak, startstrand, re->totstrand); + if(startvert!=re->totvert) { /* the exception below is because displace code now is in init_render_mesh call, I will look at means to have autosmooth enabled for all object types and have it as general postprocess, like displace */ @@ -3765,6 +3883,7 @@ static void init_render_object(Render *re, Object *ob, Object *par, int index, i /* clumsy copying still */ re->i.totvert= re->totvert; re->i.totface= re->totvlak; + re->i.totstrand= re->totstrand; re->i.tothalo= re->tothalo; re->i.totlamp= re->totlamp; re->stats_draw(&re->i); @@ -3828,7 +3947,7 @@ void RE_Database_Free(Render *re) free_sss(re); - re->totvlak=re->totvert=re->totlamp=re->tothalo= 0; + re->totvlak=re->totvert=re->totstrand=re->totlamp=re->tothalo= 0; re->i.convertdone= 0; if(re->scene) @@ -4094,7 +4213,7 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view) /* XXX add test if dbase was filled already? */ re->memArena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE); - re->totvlak=re->totvert=re->totlamp=re->tothalo= 0; + re->totvlak=re->totvert=re->totstrand=re->totlamp=re->tothalo= 0; re->lights.first= re->lights.last= NULL; re->lampren.first= re->lampren.last= NULL; @@ -4210,7 +4329,7 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view) Object *obd= dob->ob; if (obd->restrictflag & OB_RESTRICT_RENDER) continue; - + Mat4CpyMat4(obd->obmat, dob->mat); /* group duplis need to set ob matrices correct, for deform. so no_draw is part handled */ @@ -4298,6 +4417,7 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view) /* for now some clumsy copying still */ re->i.totvert= re->totvert; re->i.totface= re->totvlak; + re->i.totstrand= re->totstrand; re->i.tothalo= re->tothalo; re->i.totlamp= re->totlamp; re->stats_draw(&re->i); @@ -4341,7 +4461,7 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view) } if(!re->test_break()) - project_renderdata(re, projectverto, re->r.mode & R_PANORAMA, 0); + project_renderdata(re, projectverto, re->r.mode & R_PANORAMA, 0, 1); /* SSS */ if((re->r.mode & R_SSS) && !re->test_break()) @@ -4372,8 +4492,8 @@ static void database_fromscene_vectors(Render *re, Scene *scene, int timeoffset) /* XXX add test if dbase was filled already? */ re->memArena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE); - re->totvlak=re->totvert=re->totlamp=re->tothalo= 0; - re->i.totface=re->i.totvert=re->i.totlamp=re->i.tothalo= 0; + re->totvlak=re->totvert=re->totstrand=re->totlamp=re->tothalo= 0; + re->i.totface=re->i.totvert=re->i.totstrand=re->i.totlamp=re->i.tothalo= 0; re->lights.first= re->lights.last= NULL; slurph_opt= 0; @@ -4451,14 +4571,14 @@ static void database_fromscene_vectors(Render *re, Scene *scene, int timeoffset) } if(!re->test_break()) - project_renderdata(re, projectverto, re->r.mode & R_PANORAMA, 0); + project_renderdata(re, projectverto, re->r.mode & R_PANORAMA, 0, 1); /* do this in end, particles for example need cfra */ G.scene->r.cfra-=timeoffset; } /* choose to use static, to prevent giving too many args to this call */ -static void speedvector_project(Render *re, float *zco, VertRen *ver) +static void speedvector_project(Render *re, float *zco, float *co, float *ho) { static float pixelphix=0.0f, pixelphiy=0.0f, zmulx=0.0f, zmuly=0.0f; static int pano= 0; @@ -4486,14 +4606,14 @@ static void speedvector_project(Render *re, float *zco, VertRen *ver) } /* now map hocos to screenspace, uses very primitive clip still */ - if(ver->ho[3]<0.1f) div= 10.0f; - else div= 1.0f/ver->ho[3]; + if(ho[3]<0.1f) div= 10.0f; + else div= 1.0f/ho[3]; /* use cylinder projection */ if(pano) { float vec[3], ang; - /* angle between (0,0,-1) and (ver->co) */ - VECCOPY(vec, ver->co); + /* angle between (0,0,-1) and (co) */ + VECCOPY(vec, co); ang= saacos(-vec[2]/sqrt(vec[0]*vec[0] + vec[2]*vec[2])); if(vec[0]<0.0f) ang= -ang; @@ -4504,57 +4624,84 @@ static void speedvector_project(Render *re, float *zco, VertRen *ver) } else { - zco[0]= zmulx*(1.0f+ver->ho[0]*div); - zco[1]= zmuly*(1.0f+ver->ho[1]*div); + zco[0]= zmulx*(1.0f+ho[0]*div); + zco[1]= zmuly*(1.0f+ho[1]*div); + } +} + +static void calculate_speedvector(float *vectors, int step, float winsq, float winroot, float *co, float *ho, float *speed) +{ + float zco[2], len; + + speedvector_project(NULL, zco, co, ho); + + zco[0]= vectors[0] - zco[0]; + zco[1]= vectors[1] - zco[1]; + + /* enable nice masks for hardly moving stuff or float inaccuracy */ + if(zco[0]<0.1f && zco[0]>-0.1f && zco[1]<0.1f && zco[1]>-0.1f ) { + zco[0]= 0.0f; + zco[1]= 0.0f; + } + + /* maximize speed for image width, otherwise it never looks good */ + len= zco[0]*zco[0] + zco[1]*zco[1]; + if(len > winsq) { + len= winroot/sqrt(len); + zco[0]*= len; + zco[1]*= len; + } + + /* note; in main vecblur loop speedvec is negated again */ + if(step) { + speed[2]= -zco[0]; + speed[3]= -zco[1]; + } + else { + speed[0]= zco[0]; + speed[1]= zco[1]; } } -static void calculate_speedvectors(Render *re, float *vectors, int startvert, int endvert, int step) +static void calculate_speedvectors(Render *re, ObjectRen *obren, float *vectors, int step) { VertRen *ver= NULL; - float *speed, zco[2]; - float len; + StrandRen *strand= NULL; + float *speed, ho[4]; float winsq= re->winx*re->winy, winroot= sqrt(winsq); - int a; - - /* set first vertex OK */ - a= startvert-1; - ver= re->vertnodes[a>>8].vert + (a & 255); + int a, startvert, endvert, startstrand, endstrand; + + startvert= obren->startvert; + endvert= obren->endvert; + startstrand= obren->startstrand; + endstrand= obren->endstrand; - for(a=startvert; a<endvert; a++, vectors+=2) { - if((a & 255)==0) - ver= re->vertnodes[a>>8].vert; - else - ver++; - - speedvector_project(NULL, zco, ver); + if(re->vertnodes) { + /* set first vertex OK */ + a= startvert-1; + ver= re->vertnodes[a>>8].vert + (a & 255); - zco[0]= vectors[0] - zco[0]; - zco[1]= vectors[1] - zco[1]; - - /* enable nice masks for hardly moving stuff or float inaccuracy */ - if(zco[0]<0.1f && zco[0]>-0.1f && zco[1]<0.1f && zco[1]>-0.1f ) { - zco[0]= 0.0f; - zco[1]= 0.0f; - } - - /* maximize speed for image width, otherwise it never looks good */ - len= zco[0]*zco[0] + zco[1]*zco[1]; - if(len > winsq) { - len= winroot/sqrt(len); - zco[0]*= len; - zco[1]*= len; + for(a=startvert; a<endvert; a++, vectors+=2) { + if((a & 255)==0) ver= re->vertnodes[a>>8].vert; + else ver++; + + speed= RE_vertren_get_winspeed(re, ver, 1); + calculate_speedvector(vectors, step, winsq, winroot, ver->co, ver->ho, speed); } + } + + if(re->strandnodes) { + /* set first strand OK */ + a= startstrand-1; + strand= re->strandnodes[a>>8].strand + (a & 255); - speed= RE_vertren_get_winspeed(re, ver, 1); - /* note; in main vecblur loop speedvec is negated again */ - if(step) { - speed[2]= -zco[0]; - speed[3]= -zco[1]; - } - else { - speed[0]= zco[0]; - speed[1]= zco[1]; + for(a=startstrand; a<endstrand; a++, vectors+=2) { + if((a & 255)==0) strand= re->strandnodes[a>>8].strand; + else strand++; + + speed= RE_strandren_get_winspeed(re, strand, 1); + projectverto(strand->vert->co, re->winmat, ho); + calculate_speedvector(vectors, step, winsq, winroot, strand->vert->co, ho, speed); } } } @@ -4639,26 +4786,45 @@ static void copy_dbase_object_vectors(Render *re, ListBase *lb) { ObjectRen *obren, *obrenlb; VertRen *ver; - float *vec; - int a; - + StrandRen *strand; + float *vec, ho[4]; + int a, totvector; + for(obren= re->objecttable.first; obren; obren= obren->next) { obrenlb= MEM_dupallocN(obren); BLI_addtail(lb, obrenlb); - if(obren->endvert>obren->startvert) { - vec= obrenlb->vectors= MEM_mallocN(2*sizeof(float)*(obren->endvert- obren->startvert), "vector array"); - /* first vertex */ - a= obren->startvert-1; - ver= re->vertnodes[a>>8].vert + (a & 255); + totvector= obren->endvert - obren->startvert; + totvector+= obren->endstrand - obren->startstrand; - for(a=obren->startvert; a<obren->endvert; a++, vec+=2) { - if((a & 255)==0) - ver= re->vertnodes[a>>8].vert; - else - ver++; - - speedvector_project(NULL, vec, ver); + if(totvector > 0) { + vec= obrenlb->vectors= MEM_mallocN(2*sizeof(float)*totvector, "vector array"); + + if(obren->endvert > obren->startvert) { + /* first vertex */ + a= obren->startvert-1; + ver= re->vertnodes[a>>8].vert + (a & 255); + + for(a=obren->startvert; a<obren->endvert; a++, vec+=2) { + if((a & 255)==0) ver= re->vertnodes[a>>8].vert; + else ver++; + + speedvector_project(NULL, vec, ver->co, ver->ho); + } + } + + if(obren->endstrand > obren->startstrand) { + /* first strand */ + a= obren->startstrand-1; + strand= re->strandnodes[a>>8].strand + (a & 255); + + for(a=obren->startstrand; a<obren->endstrand; a++, vec+=2) { + if((a & 255)==0) strand= re->strandnodes[a>>8].strand; + else strand++; + + projectverto(strand->vert->co, re->winmat, ho); + speedvector_project(NULL, vec, strand->vert->co, ho); + } } } } @@ -4684,7 +4850,7 @@ void RE_Database_FromScene_Vectors(Render *re, Scene *sce) re->i.infostr= "Calculating previous vectors"; re->r.mode |= R_SPEED; - speedvector_project(re, NULL, NULL); /* initializes projection code */ + speedvector_project(re, NULL, NULL, NULL); /* initializes projection code */ /* creates entire dbase */ database_fromscene_vectors(re, sce, -1); @@ -4745,12 +4911,13 @@ void RE_Database_FromScene_Vectors(Render *re, Scene *sce) load_fluidsimspeedvectors(re, oldobren->vectors, obren->startvert, obren->endvert, step, obren->ob); } else { /* check if both have same amounts of vertices */ - if(obren->endvert-obren->startvert != oldobren->endvert-oldobren->startvert) { + if(obren->endvert-obren->startvert != oldobren->endvert-oldobren->startvert || + obren->endstrand-obren->startstrand != oldobren->endstrand-oldobren->startstrand) { printf("Warning: object %s has different amount of vertices on other frame\n", obren->ob->id.name+2); continue; } - calculate_speedvectors(re, oldobren->vectors, obren->startvert, obren->endvert, step); + calculate_speedvectors(re, obren, oldobren->vectors, step); } // not fluidsim } } @@ -4767,7 +4934,7 @@ void RE_Database_FromScene_Vectors(Render *re, Scene *sce) /* exported call to recalculate hoco for vertices, when winmat changed */ void RE_DataBase_ApplyWindow(Render *re) { - project_renderdata(re, projectverto, 0, 0); + project_renderdata(re, projectverto, 0, 0, 0); } /* setup for shaded view or bake, so only lamps and materials are initialized */ @@ -4806,7 +4973,7 @@ void RE_Database_Baking(Render *re, Scene *scene, int type, Object *actob) if(type!=RE_BAKE_LIGHT) re->memArena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE); - re->totvlak=re->totvert=re->totlamp=re->tothalo= 0; + re->totvlak=re->totvert=re->totstrand=re->totlamp=re->tothalo= 0; re->lights.first= re->lights.last= NULL; re->lampren.first= re->lampren.last= NULL; diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c index ebb444833e8..cec96c1ab92 100644 --- a/source/blender/render/intern/source/envmap.c +++ b/source/blender/render/intern/source/envmap.c @@ -156,6 +156,9 @@ static Render *envmap_render_copy(Render *re, EnvMap *env) envre->bloha= re->bloha; envre->vlaknodeslen= re->vlaknodeslen; envre->vlaknodes= re->vlaknodes; + envre->strandnodeslen= re->strandnodeslen; + envre->strandnodes= re->strandnodes; + envre->strandbuckets= re->strandbuckets; envre->customdata_names= re->customdata_names; envre->raytree= re->raytree; @@ -176,6 +179,9 @@ static void envmap_free_render_copy(Render *envre) envre->bloha= NULL; envre->vlaknodeslen= 0; envre->vlaknodes= NULL; + envre->strandnodeslen= 0; + envre->strandnodes= NULL; + envre->strandbuckets= NULL; envre->customdata_names.first= envre->customdata_names.last= NULL; envre->raytree= NULL; @@ -403,7 +409,7 @@ static void render_envmap(Render *re, EnvMap *env) env_rotate_scene(envre, tmat, 1); init_render_world(envre); - project_renderdata(envre, projectverto, 0, 0); + project_renderdata(envre, projectverto, 0, 0, 1); env_layerflags(envre, env->notlay); env_hideobject(envre, env->object); env_set_imats(envre); diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c index ff0b5f3d3cb..8d9f687a32e 100644 --- a/source/blender/render/intern/source/imagetexture.c +++ b/source/blender/render/intern/source/imagetexture.c @@ -244,6 +244,14 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, float *texvec, TexResult *texre if(tex->flag & TEX_NEGALPHA) texres->ta= 1.0f-texres->ta; + /* de-premul, this is being premulled in shade_input_do_shade() */ + if(texres->ta!=1.0f && texres->ta!=0.0f) { + fx= 1.0f/texres->ta; + texres->tr*= fx; + texres->tg*= fx; + texres->tb*= fx; + } + return retval; } diff --git a/source/blender/render/intern/source/initrender.c b/source/blender/render/intern/source/initrender.c index 83c0be6283b..3ea8c6edffa 100644 --- a/source/blender/render/intern/source/initrender.c +++ b/source/blender/render/intern/source/initrender.c @@ -543,7 +543,7 @@ void RE_SetCamera(Render *re, Object *camera) re->viewdx= pixsize; re->viewdy= re->ycor*pixsize; - + if(re->r.mode & R_ORTHO) RE_SetOrtho(re, &viewplane, clipsta, clipend); else @@ -557,6 +557,13 @@ void RE_SetPixelSize(Render *re, float pixsize) re->viewdy= re->ycor*pixsize; } +void RE_GetCameraWindow(struct Render *re, struct Object *camera, int frame, float mat[][4]) +{ + re->r.cfra= frame; + RE_SetCamera(re, camera); + Mat4CpyMat4(mat, re->winmat); +} + /* ~~~~~~~~~~~~~~~~ part (tile) calculus ~~~~~~~~~~~~~~~~~~~~~~ */ diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 61bc6a84556..1c3867a702c 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -171,8 +171,9 @@ void RE_FreeRenderResult(RenderResult *res) RenderLayer *rl= res->layers.first; if(rl->rectf) MEM_freeN(rl->rectf); - /* acolrect is optionally allocated in shade_tile, only free here since it can be used for drawing */ + /* acolrect and scolrect are optionally allocated in shade_tile, only free here since it can be used for drawing */ if(rl->acolrect) MEM_freeN(rl->acolrect); + if(rl->scolrect) MEM_freeN(rl->scolrect); while(rl->passes.first) { RenderPass *rpass= rl->passes.first; @@ -1250,6 +1251,7 @@ static void render_tile_processor(Render *re, int firsttile) } freeparts(re); + R.strandbuckets= NULL; } /* calculus for how much 1 pixel rendered should rotate the 3d geometry */ @@ -1307,7 +1309,7 @@ static RenderPart *find_next_pano_slice(Render *re, int *minx, rctf *viewplane) Mat4CpyMat4(R.winmat, re->winmat); /* rotate database according to part coordinates */ - project_renderdata(re, projectverto, 1, -R.panodxp*phi); + project_renderdata(re, projectverto, 1, -R.panodxp*phi, 1); R.panosi= sin(R.panodxp*phi); R.panoco= cos(R.panodxp*phi); } @@ -1483,7 +1485,7 @@ static void threaded_tile_processor(Render *re) BLI_end_threads(&threads); freeparts(re); re->viewplane= viewplane; /* restore viewplane, modified by pano render */ - + R.strandbuckets= NULL; } /* currently only called by preview renders and envmap */ diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 5141841e157..a9699104e01 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -579,6 +579,9 @@ void init_jitter_plane(LampRen *lar) float *fp; int x, iter=12, tot= lar->ray_totsamp; + /* test if already initialized */ + if(lar->jitter) return; + /* at least 4, or max threads+1 tables */ if(BLENDER_MAX_THREADS < 4) x= 4; else x= BLENDER_MAX_THREADS+1; diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 636bee32e05..f5f1f6cec17 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -887,7 +887,7 @@ void zbufshadeDA_tile(RenderPart *pa) if(R.flag & R_HALO) if(rl->layflag & SCE_LAY_HALO) halo_tile(pa, rl->rectf, rl->lay); - + /* transp layer */ if(R.flag & R_ZTRA) { if(rl->layflag & SCE_LAY_ZTRA) { @@ -904,7 +904,7 @@ void zbufshadeDA_tile(RenderPart *pa) /* zbuffer transp only returns ztramask if there's solid rendered */ if(ztramask) solidmask= make_solid_mask(pa); - + if(ztramask && solidmask) { unsigned short *sps= solidmask, *spz= ztramask; unsigned short fullmask= (1<<R.osa)-1; @@ -929,6 +929,47 @@ void zbufshadeDA_tile(RenderPart *pa) if(ztramask) MEM_freeN(ztramask); } } + + /* strand rendering */ + if((rl->layflag & SCE_LAY_STRAND) && R.strandbufs.first) { + float *fcol, *scol; + unsigned short *strandmask, *solidmask= NULL; /* 16 bits, MAX_OSA */ + int x; + + /* allocate, but not free here, for asynchronous display of this rect in main thread */ + rl->scolrect= MEM_callocN(4*sizeof(float)*pa->rectx*pa->recty, "strand layer"); + + /* swap for live updates, and it is used in zbuf.c!!! */ + SWAP(float*, rl->scolrect, rl->rectf); + strandmask= zbuffer_strands_shade(&R, pa, rl, rl->rectf); + SWAP(float*, rl->scolrect, rl->rectf); + + /* zbuffer strands only returns strandmask if there's solid rendered */ + if(strandmask) + solidmask= make_solid_mask(pa); + + if(strandmask && solidmask) { + unsigned short *sps= solidmask, *spz= strandmask; + unsigned short fullmask= (1<<R.osa)-1; + + fcol= rl->rectf; scol= rl->scolrect; + for(x=pa->rectx*pa->recty; x>0; x--, scol+=4, fcol+=4, sps++, spz++) { + if(*sps == fullmask) + addAlphaOverFloat(fcol, scol); + else + addAlphaOverFloatMask(fcol, scol, *sps, *spz); + } + } + else { + fcol= rl->rectf; scol= rl->scolrect; + for(x=pa->rectx*pa->recty; x>0; x--, scol+=4, fcol+=4) + addAlphaOverFloat(fcol, scol); + } + + if(solidmask) MEM_freeN(solidmask); + if(strandmask) MEM_freeN(strandmask); + } + /* sky before edge */ if(rl->layflag & SCE_LAY_SKY) sky_tile(pa, rl->rectf); @@ -1081,6 +1122,24 @@ void zbufshade_tile(RenderPart *pa) } } } + + /* strand rendering */ + if((rl->layflag & SCE_LAY_STRAND) && R.strandbufs.first) { + float *fcol, *scol; + int x; + + /* allocate, but not free here, for asynchronous display of this rect in main thread */ + rl->scolrect= MEM_callocN(4*sizeof(float)*pa->rectx*pa->recty, "strand layer"); + + /* swap for live updates */ + SWAP(float*, rl->scolrect, rl->rectf); + zbuffer_strands_shade(&R, pa, rl, rl->rectf); + SWAP(float*, rl->scolrect, rl->rectf); + + fcol= rl->rectf; scol= rl->scolrect; + for(x=pa->rectx*pa->recty; x>0; x--, scol+=4, fcol+=4) + addAlphaOverFloat(fcol, scol); + } /* sky before edge */ if(rl->layflag & SCE_LAY_SKY) @@ -1207,8 +1266,6 @@ static void shade_sample_sss(ShadeSample *ssamp, Material *mat, VlakRen *vlr, in *area= VecLength(shi->dxco)*VecLength(shi->dyco); *area= MIN2(*area, 2.0f*orthoarea); - shi->osatex= 0; - shade_input_set_uv(shi); shade_input_set_normals(shi); @@ -1594,7 +1651,7 @@ void add_halo_flare(Render *re) mode= R.r.mode; R.r.mode &= ~R_PANORAMA; - project_renderdata(&R, projectverto, 0, 0); + project_renderdata(&R, projectverto, 0, 0, 0); for(a=0; a<R.tothalo; a++) { if((a & 255)==0) har= R.bloha[a>>8]; diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c index 6939e70a71b..1d490637222 100644 --- a/source/blender/render/intern/source/renderdatabase.c +++ b/source/blender/render/intern/source/renderdatabase.c @@ -79,6 +79,7 @@ #include "render_types.h" #include "renderdatabase.h" #include "texture.h" +#include "strand.h" #include "zbuf.h" /* ------------------------------------------------------------------------- */ @@ -100,6 +101,8 @@ #define RE_WINSPEED_ELEMS 4 #define RE_MTFACE_ELEMS 1 #define RE_MCOL_ELEMS 4 +#define RE_UV_ELEMS 2 +#define RE_SURFNOR_ELEMS 3 float *RE_vertren_get_sticky(Render *re, VertRen *ver, int verify) { @@ -368,6 +371,21 @@ MCol *RE_vlakren_get_mcol(Render *re, VlakRen *vlr, int n, char **name, int veri return node->mcol[index]; } +float *RE_vlakren_get_surfnor(Render *re, VlakRen *vlak, int verify) +{ + float *surfnor; + int nr= vlak->index>>8; + + surfnor= re->vlaknodes[nr].surfnor; + if(surfnor==NULL) { + if(verify) + surfnor= re->vlaknodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor table"); + else + return NULL; + } + return surfnor + (vlak->index & 255)*RE_SURFNOR_ELEMS; +} + VlakRen *RE_vlakren_copy(Render *re, VlakRen *vlr) { VlakRen *vlr1 = RE_findOrAddVlak(re, re->totvlak++); @@ -375,6 +393,7 @@ VlakRen *RE_vlakren_copy(Render *re, VlakRen *vlr) MCol *mcol, *mcol1; VlakTableNode *node = &re->vlaknodes[vlr->index>>8]; VlakTableNode *node1 = &re->vlaknodes[vlr1->index>>8]; + float *surfnor, *surfnor1; int i, index = vlr1->index; char *name; @@ -391,6 +410,12 @@ VlakRen *RE_vlakren_copy(Render *re, VlakRen *vlr) memcpy(mcol1, mcol, sizeof(MCol)*RE_MCOL_ELEMS); } + surfnor= RE_vlakren_get_surfnor(re, vlr, 0); + if(surfnor) { + surfnor1= RE_vlakren_get_surfnor(re, vlr1, 1); + VECCOPY(surfnor1, surfnor); + } + if (node->names && node1->names) node1->names[vlr1->index&255] = node->names[vlr->index&255]; @@ -480,7 +505,183 @@ VlakRen *RE_findOrAddVlak(Render *re, int nr) /* ------------------------------------------------------------------------ */ -void RE_addRenderObject(Render *re, Object *ob, Object *par, int index, int sve, int eve, int sfa, int efa) +float *RE_strandren_get_winspeed(Render *re, StrandRen *strand, int verify) +{ + float *winspeed; + int nr= strand->index>>8; + + winspeed= re->strandnodes[nr].winspeed; + if(winspeed==NULL) { + if(verify) + winspeed= re->strandnodes[nr].winspeed= MEM_callocN(256*RE_WINSPEED_ELEMS*sizeof(float), "winspeed table"); + else + return NULL; + } + return winspeed + (strand->index & 255)*RE_WINSPEED_ELEMS; +} + +float *RE_strandren_get_surfnor(Render *re, StrandRen *strand, int verify) +{ + float *surfnor; + int nr= strand->index>>8; + + surfnor= re->strandnodes[nr].surfnor; + if(surfnor==NULL) { + if(verify) + surfnor= re->strandnodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor table"); + else + return NULL; + } + return surfnor + (strand->index & 255)*RE_SURFNOR_ELEMS; +} + +float *RE_strandren_get_uv(Render *re, StrandRen *strand, int n, char **name, int verify) +{ + StrandTableNode *node; + int nr= strand->index>>8, strandindex= (strand->index&255); + int index= (n<<8) + strandindex; + + node= &re->strandnodes[nr]; + + if(verify) { + if(n>=node->totuv) { + float **uv= node->uv; + int size= (n+1)*256; + + node->uv= MEM_callocN(size*sizeof(float*), "Strand uv"); + + if(uv) { + size= node->totuv*256; + memcpy(node->uv, uv, size*sizeof(float*)); + MEM_freeN(uv); + } + + node->totuv= n+1; + + if (!node->names) { + size= sizeof(*node->names)*256; + node->names= MEM_callocN(size, "Strand names"); + } + } + + if(node->uv[index]==NULL) { + node->uv[index]= BLI_memarena_alloc(re->memArena, + sizeof(float)*RE_UV_ELEMS); + + node->names[strandindex]= re->customdata_names.last; + } + } + else { + if(n>=node->totuv || node->uv[index]==NULL) + return NULL; + + if(name) *name= node->names[strandindex]->mtface[n]; + } + + return node->uv[index]; +} + +MCol *RE_strandren_get_mcol(Render *re, StrandRen *strand, int n, char **name, int verify) +{ + StrandTableNode *node; + int nr= strand->index>>8, strandindex= (strand->index&255); + int index= (n<<8) + strandindex; + + node= &re->strandnodes[nr]; + + if(verify) { + if(n>=node->totmcol) { + MCol **mcol= node->mcol; + int size= (n+1)*256; + + node->mcol= MEM_callocN(size*sizeof(MCol*), "Strand mcol"); + + if(mcol) { + size= node->totmcol*256; + memcpy(node->mcol, mcol, size*sizeof(MCol*)); + MEM_freeN(mcol); + } + + node->totmcol= n+1; + + if (!node->names) { + size= sizeof(*node->names)*256; + node->names= MEM_callocN(size, "Strand names"); + } + } + + if(node->mcol[index]==NULL) { + node->mcol[index]= BLI_memarena_alloc(re->memArena, + sizeof(MCol)*RE_MCOL_ELEMS); + + node->names[strandindex]= re->customdata_names.last; + } + } + else { + if(n>=node->totmcol || node->mcol[index]==NULL) + return NULL; + + if(name) *name= node->names[strandindex]->mcol[n]; + } + + return node->mcol[index]; +} + +StrandRen *RE_findOrAddStrand(Render *re, int nr) +{ + StrandTableNode *temp; + StrandRen *v; + int a; + + if(nr<0) { + printf("error in findOrAddStrand: %d\n",nr); + return re->strandnodes[0].strand; + } + a= nr>>8; + + if (a>=re->strandnodeslen-1){ /* Need to allocate more columns..., and keep last element NULL for free loop */ + temp= re->strandnodes; + + re->strandnodes= MEM_mallocN(sizeof(StrandTableNode)*(re->strandnodeslen+TABLEINITSIZE) , "strandnodes"); + if(temp) memcpy(re->strandnodes, temp, re->strandnodeslen*sizeof(StrandTableNode)); + memset(re->strandnodes+re->strandnodeslen, 0, TABLEINITSIZE*sizeof(StrandTableNode)); + + re->strandnodeslen+=TABLEINITSIZE; /*Does this really need to be power of 2?*/ + if(temp) MEM_freeN(temp); + } + + v= re->strandnodes[a].strand; + + if(v==NULL) { + int i; + + v= (StrandRen *)MEM_callocN(256*sizeof(StrandRen),"findOrAddStrand"); + re->strandnodes[a].strand= v; + + for(i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++) + v[a].index= i; + } + v+= (nr & 255); + return v; +} + +StrandBuffer *RE_addStrandBuffer(Render *re, Object *ob, int totvert) +{ + StrandBuffer *strandbuf; + + strandbuf= MEM_callocN(sizeof(StrandBuffer), "StrandBuffer"); + strandbuf->vert= MEM_callocN(sizeof(StrandVert)*totvert, "StrandVert"); + strandbuf->totvert= totvert; + strandbuf->ob= ob; + + BLI_addtail(&re->strandbufs, strandbuf); + + return strandbuf; +} + +/* ------------------------------------------------------------------------ */ + +void RE_addRenderObject(Render *re, Object *ob, Object *par, int index, int sve, int eve, int sfa, int efa, int sst, int est) { ObjectRen *obr= MEM_mallocN(sizeof(ObjectRen), "object render struct"); @@ -492,6 +693,8 @@ void RE_addRenderObject(Render *re, Object *ob, Object *par, int index, int sve, obr->endvert= eve; obr->startface= sfa; obr->endface= efa; + obr->startstrand= sst; + obr->endstrand= est; } void free_renderdata_vertnodes(VertTableNode *vertnodes) @@ -533,6 +736,8 @@ void free_renderdata_vlaknodes(VlakTableNode *vlaknodes) MEM_freeN(vlaknodes[a].mtface); if(vlaknodes[a].mcol) MEM_freeN(vlaknodes[a].mcol); + if(vlaknodes[a].surfnor) + MEM_freeN(vlaknodes[a].surfnor); if(vlaknodes[a].names) MEM_freeN(vlaknodes[a].names); } @@ -540,10 +745,35 @@ void free_renderdata_vlaknodes(VlakTableNode *vlaknodes) MEM_freeN(vlaknodes); } +void free_renderdata_strandnodes(StrandTableNode *strandnodes) +{ + int a; + + if(strandnodes==NULL) return; + + for(a=0; strandnodes[a].strand; a++) { + MEM_freeN(strandnodes[a].strand); + + if(strandnodes[a].uv) + MEM_freeN(strandnodes[a].uv); + if(strandnodes[a].mcol) + MEM_freeN(strandnodes[a].mcol); + if(strandnodes[a].winspeed) + MEM_freeN(strandnodes[a].winspeed); + if(strandnodes[a].surfnor) + MEM_freeN(strandnodes[a].surfnor); + if(strandnodes[a].names) + MEM_freeN(strandnodes[a].names); + } + + MEM_freeN(strandnodes); +} + void free_renderdata_tables(Render *re) { - int a=0; + StrandBuffer *strandbuf; CustomDataNames *cdn; + int a=0; if(re->bloha) { for(a=0; re->bloha[a]; a++) @@ -566,6 +796,17 @@ void free_renderdata_tables(Render *re) re->vlaknodeslen= 0; } + if(re->strandnodes) { + free_renderdata_strandnodes(re->strandnodes); + re->strandnodes= NULL; + re->strandnodeslen= 0; + } + + if(re->strandbuckets) { + free_buckets(re->strandbuckets); + re->strandbuckets= NULL; + } + for(cdn=re->customdata_names.first; cdn; cdn=cdn->next) { if(cdn->mtface) MEM_freeN(cdn->mtface); @@ -573,6 +814,10 @@ void free_renderdata_tables(Render *re) MEM_freeN(cdn->mcol); } + for(strandbuf=re->strandbufs.first; strandbuf; strandbuf=strandbuf->next) + if(strandbuf->vert) MEM_freeN(strandbuf->vert); + BLI_freelistN(&re->strandbufs); + BLI_freelistN(&re->customdata_names); BLI_freelistN(&re->objecttable); } @@ -906,14 +1151,14 @@ static int panotestclip(Render *re, int do_pano, float *v) - shadow buffering (shadbuf.c) */ -void project_renderdata(Render *re, void (*projectfunc)(float *, float mat[][4], float *), int do_pano, float xoffs) +void project_renderdata(Render *re, void (*projectfunc)(float *, float mat[][4], float *), int do_pano, float xoffs, int do_buckets) { VlakRen *vlr = NULL; VertRen *ver = NULL; HaloRen *har = NULL; float zn, vec[3], hoco[4]; int a; - + if(do_pano) { float panophi= xoffs; @@ -1029,6 +1274,7 @@ void project_renderdata(Render *re, void (*projectfunc)(float *, float mat[][4], vlr->flag &= ~R_VISIBLE; } + project_strands(re, projectfunc, do_pano, do_buckets); } /* ------------------------------------------------------------------------- */ diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c index 5e010080ac0..006a26dc82e 100644 --- a/source/blender/render/intern/source/shadbuf.c +++ b/source/blender/render/intern/source/shadbuf.c @@ -403,7 +403,7 @@ void makeshadowbuf(Render *re, LampRen *lar) /* temp, will be restored */ MTC_Mat4SwapMat4(shb->persmat, re->winmat); - project_renderdata(re, projectvert, 0, 0); + project_renderdata(re, projectvert, 0, 0, 0); /* zbuffering */ rectz= MEM_mapallocN(sizeof(int)*shb->size*shb->size, "makeshadbuf"); diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c index 52a65b19824..acd04910565 100644 --- a/source/blender/render/intern/source/shadeinput.c +++ b/source/blender/render/intern/source/shadeinput.c @@ -48,6 +48,7 @@ #include "rendercore.h" #include "shadbuf.h" #include "shading.h" +#include "strand.h" #include "texture.h" /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ @@ -300,6 +301,252 @@ void shade_input_copy_triangle(ShadeInput *shi, ShadeInput *from) memcpy(shi, from, sizeof(struct ShadeInputCopy)); } +/* copy data from strand to shadeinput */ +void shade_input_set_strand(ShadeInput *shi, StrandRen *strand, StrandPoint *spoint) +{ + /* note, shi->mat is set in node shaders */ + shi->mat= shi->mat_override? shi->mat_override: strand->buffer->ma; + + shi->osatex= (shi->mat->texco & TEXCO_OSA); + shi->mode= shi->mat->mode_l; /* or-ed result for all nodes */ + + shi->puno= 0; /* always faces camera automatically */ + + /* shade_input_set_viewco equivalent */ + VECCOPY(shi->co, spoint->co); + VECCOPY(shi->view, shi->co); + Normalize(shi->view); + + shi->xs= (int)spoint->x; + shi->ys= (int)spoint->y; + + if(shi->osatex || (R.r.mode & R_SHADOW)) { + VECCOPY(shi->dxco, spoint->dtco); + VECCOPY(shi->dyco, spoint->dsco); + } + + /* dxview, dyview, not supported */ + + /* facenormal, simply viewco flipped */ + VECCOPY(shi->facenor, spoint->nor); + VECCOPY(shi->orignor, shi->facenor); + + /* shade_input_set_normals equivalent */ + if(shi->mat->mode & MA_TANGENT_STR) + VECCOPY(shi->vn, spoint->tan) + else + VECCOPY(shi->vn, spoint->nor) + + VECCOPY(shi->vno, shi->vn); +} + +void shade_input_set_strand_texco(ShadeInput *shi, StrandRen *strand, StrandVert *svert, StrandPoint *spoint) +{ + StrandBuffer *strandbuf= strand->buffer; + StrandVert *sv; + int mode= shi->mode; /* or-ed result for all nodes */ + short texco= shi->mat->texco; + + if((shi->mat->texco & TEXCO_REFL)) { + /* shi->dxview, shi->dyview, not supported */ + } + + if(shi->osatex && (texco & (TEXCO_NORM|TEXCO_REFL))) { + /* not supported */ + } + + if(mode & (MA_TANGENT_V|MA_NORMAP_TANG)) { + VECCOPY(shi->tang, spoint->tan); + } + + if(mode & MA_STR_SURFDIFF) { + float *surfnor= RE_strandren_get_surfnor(&R, strand, 0); + + if(surfnor) + VECCOPY(shi->surfnor, surfnor) + else + VECCOPY(shi->surfnor, shi->vn) + + if(shi->mat->strand_surfnor > 0.0f) { + shi->surfdist= 0.0f; + for(sv=strand->vert; sv!=svert; sv++) + shi->surfdist+=VecLenf(sv->co, (sv+1)->co); + shi->surfdist += 0.5f*(spoint->strandco+1.0f)*VecLenf(sv->co, (sv+1)->co); + } + } + + if(R.r.mode & R_SPEED) { + float *speed; + + speed= RE_strandren_get_winspeed(&R, strand, 0); + if(speed) + QUATCOPY(shi->winspeed, speed) + else + shi->winspeed[0]= shi->winspeed[1]= shi->winspeed[2]= shi->winspeed[3]= 0.0f; + } + + /* shade_input_set_shade_texco equivalent */ + if(texco & NEED_UV) { + if(texco & TEXCO_ORCO) { + VECCOPY(shi->lo, strand->orco); + /* no shi->osatex, orco derivatives are zero */ + } + + if(texco & TEXCO_GLOB) { + VECCOPY(shi->gl, shi->co); + MTC_Mat4MulVecfl(R.viewinv, shi->gl); + + if(shi->osatex) { + VECCOPY(shi->dxgl, shi->dxco); + MTC_Mat3MulVecfl(R.imat, shi->dxco); + VECCOPY(shi->dygl, shi->dyco); + MTC_Mat3MulVecfl(R.imat, shi->dyco); + } + } + + if(texco & TEXCO_STRAND) { + shi->strand= spoint->strandco; + + if(shi->osatex) { + shi->dxstrand= spoint->dtstrandco; + shi->dystrand= 0.0f; + } + } + + if((texco & TEXCO_UV) || (mode & (MA_VERTEXCOL|MA_VERTEXCOLP|MA_FACETEXTURE))) { + MCol *mcol; + float *uv; + char *name; + int i; + + shi->totuv= 0; + shi->totcol= 0; + + if(mode & (MA_VERTEXCOL|MA_VERTEXCOLP)) { + for (i=0; (mcol=RE_strandren_get_mcol(&R, strand, i, &name, 0)); i++) { + ShadeInputCol *scol= &shi->col[i]; + char *cp= (char*)mcol; + + shi->totcol++; + scol->name= name; + + scol->col[0]= cp[0]/255.0f; + scol->col[1]= cp[1]/255.0f; + scol->col[2]= cp[2]/255.0f; + } + + if(shi->totcol) { + shi->vcol[0]= shi->col[0].col[0]; + shi->vcol[1]= shi->col[0].col[1]; + shi->vcol[2]= shi->col[0].col[2]; + } + else { + shi->vcol[0]= 0.0f; + shi->vcol[1]= 0.0f; + shi->vcol[2]= 0.0f; + } + } + + for (i=0; (uv=RE_strandren_get_uv(&R, strand, i, &name, 0)); i++) { + ShadeInputUV *suv= &shi->uv[i]; + + shi->totuv++; + suv->name= name; + + if(strandbuf->overrideuv == i) { + suv->uv[0]= -1.0f; + suv->uv[1]= spoint->strandco; + suv->uv[2]= 0.0f; + } + else { + suv->uv[0]= -1.0f + 2.0f*uv[0]; + suv->uv[1]= -1.0f + 2.0f*uv[1]; + suv->uv[2]= 0.0f; /* texture.c assumes there are 3 coords */ + } + + if(shi->osatex) { + suv->dxuv[0]= 0.0f; + suv->dxuv[1]= 0.0f; + suv->dyuv[0]= 0.0f; + suv->dyuv[1]= 0.0f; + } + + if((mode & MA_FACETEXTURE) && i==0) { + if((mode & (MA_VERTEXCOL|MA_VERTEXCOLP))==0) { + shi->vcol[0]= 1.0f; + shi->vcol[1]= 1.0f; + shi->vcol[2]= 1.0f; + } + } + } + + if(shi->totuv == 0) { + ShadeInputUV *suv= &shi->uv[0]; + + suv->uv[0]= 0.0f; + suv->uv[1]= spoint->strandco; + suv->uv[2]= 0.0f; /* texture.c assumes there are 3 coords */ + + if(mode & MA_FACETEXTURE) { + /* no tface? set at 1.0f */ + shi->vcol[0]= 1.0f; + shi->vcol[1]= 1.0f; + shi->vcol[2]= 1.0f; + } + } + + } + + if(texco & TEXCO_NORM) { + shi->orn[0]= -shi->vn[0]; + shi->orn[1]= -shi->vn[1]; + shi->orn[2]= -shi->vn[2]; + } + + if(mode & MA_RADIO) { + /* not supported */ + } + + if(texco & TEXCO_REFL) { + /* mirror reflection color textures (and envmap) */ + calc_R_ref(shi); /* wrong location for normal maps! XXXXXXXXXXXXXX */ + } + + if(texco & TEXCO_STRESS) { + /* not supported */ + } + + if(texco & TEXCO_TANGENT) { + if((mode & MA_TANGENT_V)==0) { + /* just prevent surprises */ + shi->tang[0]= shi->tang[1]= shi->tang[2]= 0.0f; + } + } + } + + shi->rad[0]= shi->rad[1]= shi->rad[2]= 0.0f; + + /* this only avalailable for scanline renders */ + if(shi->depth==0) { + if(texco & TEXCO_WINDOW) { + shi->winco[0]= -1.0f + 2.0f*spoint->x/(float)R.winx; + shi->winco[1]= -1.0f + 2.0f*spoint->y/(float)R.winy; + shi->winco[2]= 0.0f; + + /* not supported */ + if(shi->osatex) { + shi->dxwin[0]= 0.0f; + shi->dywin[1]= 0.0f; + shi->dxwin[0]= 0.0f; + shi->dywin[1]= 0.0f; + } + } + + if(texco & TEXCO_STICKY) { + /* not supported */ + } + } +} /* scanline pixel coordinates */ /* requires set_triangle */ @@ -571,6 +818,17 @@ void shade_input_set_shade_texco(ShadeInput *shi) else shi->tang[0]= shi->tang[1]= shi->tang[2]= 0.0f; } } + + if(mode & MA_STR_SURFDIFF) { + float *surfnor= RE_vlakren_get_surfnor(&R, shi->vlr, 0); + + if(surfnor) + VECCOPY(shi->surfnor, surfnor) + else + VECCOPY(shi->surfnor, shi->vn) + + shi->surfdist= 0.0f; + } if(R.r.mode & R_SPEED) { float *s1, *s2, *s3; diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c index 56cb226560a..037a3aa8409 100644 --- a/source/blender/render/intern/source/shadeoutput.c +++ b/source/blender/render/intern/source/shadeoutput.c @@ -421,17 +421,21 @@ static double saacos_d(double fac) } /* Stoke's form factor. Need doubles here for extreme small area sizes */ -static float area_lamp_energy(float *co, float *vn, LampRen *lar) +static float area_lamp_energy(float (*area)[3], float *co, float *vn) { double fac; double vec[4][3]; /* vectors of rendered co to vertices lamp */ double cross[4][3]; /* cross products of this */ double rad[4]; /* angles between vecs */ - VECSUB(vec[0], co, lar->area[0]); - VECSUB(vec[1], co, lar->area[1]); - VECSUB(vec[2], co, lar->area[2]); - VECSUB(vec[3], co, lar->area[3]); + /* extra test for dot */ + if ( INPR(co, vn) <= 0.0f) + return 0.0f; + + VECSUB(vec[0], co, area[0]); + VECSUB(vec[1], co, area[1]); + VECSUB(vec[2], co, area[2]); + VECSUB(vec[3], co, area[3]); Normalize_d(vec[0]); Normalize_d(vec[1]); @@ -467,7 +471,35 @@ static float area_lamp_energy(float *co, float *vn, LampRen *lar) fac+= rad[3]*(vn[0]*cross[3][0]+ vn[1]*cross[3][1]+ vn[2]*cross[3][2]); if(fac<=0.0) return 0.0; - return pow(fac*lar->areasize, lar->k); // corrected for buttons size and lar->dist^2 + return fac; +} + +static float area_lamp_energy_multisample(LampRen *lar, float *co, float *vn) +{ + /* corner vectors are moved around according lamp jitter */ + float *jitlamp= lar->jitter, vec[3]; + float area[4][3], intens= 0.0f; + int a= lar->ray_totsamp; + + + while(a--) { + vec[0]= jitlamp[0]; + vec[1]= jitlamp[1]; + vec[2]= 0.0f; + Mat3MulVecfl(lar->mat, vec); + + VECADD(area[0], lar->area[0], vec); + VECADD(area[1], lar->area[1], vec); + VECADD(area[2], lar->area[2], vec); + VECADD(area[3], lar->area[3], vec); + + intens+= area_lamp_energy(area, co, vn); + + jitlamp+= 2; + } + intens /= (float)lar->ray_totsamp; + + return pow(intens*lar->areasize, lar->k); // corrected for buttons size and lar->dist^2 } static float spec(float inp, int hard) @@ -1057,10 +1089,10 @@ float lamp_get_visibility(LampRen *lar, float *co, float *lv, float *dist) /* area type has no quad or sphere option */ if(lar->type==LA_AREA) { /* area is single sided */ - if(INPR(lv, lar->vec) > 0.0f) - visifac= 1.0f; - else - visifac= 0.0f; + //if(INPR(lv, lar->vec) > 0.0f) + // visifac= 1.0f; + //else + // visifac= 0.0f; } else { switch(lar->falloff_type) @@ -1180,13 +1212,35 @@ static void shade_one_light(LampRen *lar, ShadeInput *shi, ShadeResult *shr, int lacol[2]= lar->b; if(lar->mode & LA_TEXTURE) do_lamp_tex(lar, lv, shi, lacol); - - /* tangent case; calculate fake face normal, aligned with lampvector */ - /* note, vnor==vn is used as tangent trigger for buffer shadow */ + + /* tangent case; calculate fake face normal, aligned with lampvector */ + /* note, vnor==vn is used as tangent trigger for buffer shadow */ if(vlr->flag & R_TANGENT) { - float cross[3]; - Crossf(cross, lv, vn); - Crossf(vnor, cross, vn); + float cross[3], nstrand[3], blend; + + if(ma->mode & MA_STR_SURFDIFF) { + Crossf(cross, shi->surfnor, vn); + Crossf(nstrand, vn, cross); + + blend= INPR(nstrand, shi->surfnor); + CLAMP(blend, 0.0f, 1.0f); + + VecLerpf(vnor, nstrand, shi->surfnor, blend); + Normalize(vnor); + } + else { + Crossf(cross, lv, vn); + Crossf(vnor, cross, vn); + } + + if(ma->strand_surfnor > 0.0f) { + if(ma->strand_surfnor > shi->surfdist) { + blend= (ma->strand_surfnor - shi->surfdist)/ma->strand_surfnor; + VecLerpf(vnor, vnor, shi->surfnor, blend); + Normalize(vnor); + } + } + vnor[0]= -vnor[0];vnor[1]= -vnor[1];vnor[2]= -vnor[2]; vn= vnor; } @@ -1206,7 +1260,7 @@ static void shade_one_light(LampRen *lar, ShadeInput *shi, ShadeResult *shr, int /* this complex construction screams for a nicer implementation! (ton) */ if(R.r.mode & R_SHADOW) { if(ma->mode & MA_SHADOW) { - if(lar->type==LA_HEMI); + if(lar->type==LA_HEMI || lar->type==LA_AREA); else if((ma->mode & MA_RAYBIAS) && (lar->mode & LA_SHAD_RAY) && (vlr->flag & R_SMOOTH)) { float thresh= vlr->ob->smoothresh; if(inp>thresh) @@ -1233,7 +1287,7 @@ static void shade_one_light(LampRen *lar, ShadeInput *shi, ShadeResult *shr, int else { if(lar->type==LA_AREA) - inp= area_lamp_energy(shi->co, vn, lar); + inp= area_lamp_energy_multisample(lar, shi->co, vn); /* diffuse shaders (oren nayer gets inp from area light) */ if(ma->diff_shader==MA_DIFF_ORENNAYAR) is= OrenNayar_Diff(inp, vn, lv, view, ma->roughness); diff --git a/source/blender/render/intern/source/sss.c b/source/blender/render/intern/source/sss.c index c4438a22ce5..09a3b9ef66d 100644 --- a/source/blender/render/intern/source/sss.c +++ b/source/blender/render/intern/source/sss.c @@ -234,11 +234,7 @@ static void approximate_Rd_rgb(ScatterSettings **ss, float rr, float *rd) float indexf, t, idxf; int index; - if(rr > (RD_TABLE_RANGE_2*RD_TABLE_RANGE_2)) { - rd[0]= Rd_rsquare(ss[0], rr); - rd[1]= Rd_rsquare(ss[1], rr); - rd[2]= Rd_rsquare(ss[2], rr); - } + if(rr > (RD_TABLE_RANGE_2*RD_TABLE_RANGE_2)); else if(rr > RD_TABLE_RANGE) { rr= sqrt(rr); indexf= rr*(RD_TABLE_SIZE/RD_TABLE_RANGE_2); @@ -246,9 +242,12 @@ static void approximate_Rd_rgb(ScatterSettings **ss, float rr, float *rd) idxf= (float)index; t= indexf - idxf; - rd[0]= (ss[0]->tableRd2[index]*(1-t) + ss[0]->tableRd2[index+1]*t); - rd[1]= (ss[1]->tableRd2[index]*(1-t) + ss[1]->tableRd2[index+1]*t); - rd[2]= (ss[2]->tableRd2[index]*(1-t) + ss[2]->tableRd2[index+1]*t); + if(index >= 0 && index < RD_TABLE_SIZE) { + rd[0]= (ss[0]->tableRd2[index]*(1-t) + ss[0]->tableRd2[index+1]*t); + rd[1]= (ss[1]->tableRd2[index]*(1-t) + ss[1]->tableRd2[index+1]*t); + rd[2]= (ss[2]->tableRd2[index]*(1-t) + ss[2]->tableRd2[index+1]*t); + return; + } } else { indexf= rr*(RD_TABLE_SIZE/RD_TABLE_RANGE); @@ -256,10 +255,18 @@ static void approximate_Rd_rgb(ScatterSettings **ss, float rr, float *rd) idxf= (float)index; t= indexf - idxf; - rd[0]= (ss[0]->tableRd[index]*(1-t) + ss[0]->tableRd[index+1]*t); - rd[1]= (ss[1]->tableRd[index]*(1-t) + ss[1]->tableRd[index+1]*t); - rd[2]= (ss[2]->tableRd[index]*(1-t) + ss[2]->tableRd[index+1]*t); + if(index >= 0 && index < RD_TABLE_SIZE) { + rd[0]= (ss[0]->tableRd[index]*(1-t) + ss[0]->tableRd[index+1]*t); + rd[1]= (ss[1]->tableRd[index]*(1-t) + ss[1]->tableRd[index+1]*t); + rd[2]= (ss[2]->tableRd[index]*(1-t) + ss[2]->tableRd[index+1]*t); + return; + } } + + /* fallback to slow Rd computation */ + rd[0]= Rd_rsquare(ss[0], rr); + rd[1]= Rd_rsquare(ss[1], rr); + rd[2]= Rd_rsquare(ss[2], rr); } static void build_Rd_table(ScatterSettings *ss) diff --git a/source/blender/render/intern/source/strand.c b/source/blender/render/intern/source/strand.c new file mode 100644 index 00000000000..0c1590c216b --- /dev/null +++ b/source/blender/render/intern/source/strand.c @@ -0,0 +1,1166 @@ +/** + * $Id$ + * + * ***** 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: none of this file. + * + * Contributors: Brecht Van Lommel. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <math.h> +#include <string.h> +#include <stdlib.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_key_types.h" +#include "DNA_material_types.h" + +#include "BLI_arithb.h" +#include "BLI_blenlib.h" +#include "BLI_ghash.h" +#include "BLI_memarena.h" + +#include "BKE_key.h" +#include "BKE_utildefines.h" + +#include "render_types.h" +#include "initrender.h" +#include "rendercore.h" +#include "renderdatabase.h" +#include "renderpipeline.h" +#include "pixelblending.h" +#include "shading.h" +#include "strand.h" +#include "zbuf.h" + +/* to be removed */ +void merge_transp_passes(RenderLayer *rl, ShadeResult *shr); +void add_transp_passes(RenderLayer *rl, int offset, ShadeResult *shr, float alpha); +void hoco_to_zco(ZSpan *zspan, float *zco, float *hoco); +void zspan_scanconvert_strand(ZSpan *zspan, void *handle, float *v1, float *v2, float *v3, void (*func)(void *, int, int, float, float, float) ); +void zbufsinglewire(ZSpan *zspan, int zvlnr, float *ho1, float *ho2); +int addtosamp_shr(ShadeResult *samp_shr, ShadeSample *ssamp, int addpassflag); +void add_transp_speed(RenderLayer *rl, int offset, float *speed, float alpha, long *rdrect); +void reset_sky_speedvectors(RenderPart *pa, RenderLayer *rl, float *rectf); + +/* *************** */ + +#define BUCKETPRIMS_SIZE 256 + +typedef struct BucketPrims { + struct BucketPrims *next, *prev; + void *prim[BUCKETPRIMS_SIZE]; + int totprim; +} BucketPrims; + +typedef struct RenderBuckets { + ListBase all; + ListBase *inside; + ListBase *overlap; + int x, y; + float insize[2]; + float zmulx, zmuly, zofsx, zofsy; +} RenderBuckets; + +static void add_bucket_prim(ListBase *lb, void *prim) +{ + BucketPrims *bpr= lb->last; + + if(!bpr || bpr->totprim == BUCKETPRIMS_SIZE) { + bpr= MEM_callocN(sizeof(BucketPrims), "BucketPrims"); + BLI_addtail(lb, bpr); + } + + bpr->prim[bpr->totprim++]= prim; +} + +RenderBuckets *init_buckets(Render *re) +{ + RenderBuckets *buckets; + RenderPart *pa; + float scalex, scaley, cropx, cropy; + int x, y, tempparts= 0; + + buckets= MEM_callocN(sizeof(RenderBuckets), "RenderBuckets"); + + if(!re->parts.first) { + initparts(re); + tempparts= 1; + } + + pa= re->parts.first; + if(!pa) + return buckets; + + x= re->xparts+1; + y= re->yparts+1; + buckets->x= x; + buckets->y= y; + + scalex= (2.0f - re->xparts*re->partx/(float)re->winx); + scaley= (2.0f - re->yparts*re->party/(float)re->winy); + + cropx= pa->crop/(float)re->partx; + cropy= pa->crop/(float)re->party; + + buckets->insize[0]= 1.0f - 2.0f*cropx; + buckets->insize[1]= 1.0f - 2.0f*cropy; + + buckets->zmulx= re->xparts*scalex; + buckets->zmuly= re->yparts*scaley; + buckets->zofsx= scalex*(1.0f - cropx); + buckets->zofsy= scaley*(1.0f - cropy); + + buckets->inside= MEM_callocN(sizeof(ListBase)*x*y, "BucketPrimsInside"); + buckets->overlap= MEM_callocN(sizeof(ListBase)*x*y, "BucketPrimsOverlap"); + + if(tempparts) + freeparts(re); + + return buckets; +} + +void add_buckets_primitive(RenderBuckets *buckets, float *min, float *max, void *prim) +{ + float end[3]; + int x, y, a; + + x= (int)min[0]; + y= (int)min[1]; + + if(x >= 0 && x < buckets->x && y >= 0 && y < buckets->y) { + a= y*buckets->x + x; + + end[0]= x + buckets->insize[0]; + end[1]= y + buckets->insize[1]; + + if(max[0] <= end[0] && max[1] <= end[1]) { + add_bucket_prim(&buckets->inside[a], prim); + return; + } + else { + end[0]= x + 2; + end[1]= y + 2; + + if(max[0] <= end[0] && max[1] <= end[1]) { + add_bucket_prim(&buckets->overlap[a], prim); + return; + } + } + } + + add_bucket_prim(&buckets->all, prim); +} + +void free_buckets(RenderBuckets *buckets) +{ + int a, size; + + BLI_freelistN(&buckets->all); + + size= buckets->x*buckets->y; + for(a=0; a<size; a++) { + BLI_freelistN(&buckets->inside[a]); + BLI_freelistN(&buckets->overlap[a]); + } + + if(buckets->inside) + MEM_freeN(buckets->inside); + if(buckets->overlap) + MEM_freeN(buckets->overlap); + + MEM_freeN(buckets); +} + +void project_hoco_to_bucket(RenderBuckets *buckets, float *hoco, float *bucketco) +{ + float div; + + div= 1.0f/hoco[3]; + bucketco[0]= buckets->zmulx*(0.5 + 0.5f*hoco[0]*div) + buckets->zofsx; + bucketco[1]= buckets->zmuly*(0.5 + 0.5f*hoco[1]*div) + buckets->zofsy; +} + +typedef struct RenderPrimitiveIterator { + Render *re; + RenderBuckets *buckets; + ListBase *list[6]; + int listindex, totlist; + BucketPrims *bpr; + int bprindex; + + StrandRen *strand; + int index, tot; +} RenderPrimitiveIterator; + +RenderPrimitiveIterator *init_primitive_iterator(Render *re, RenderBuckets *buckets, RenderPart *pa) +{ + RenderPrimitiveIterator *iter; + int nr, x, y, width; + + iter= MEM_callocN(sizeof(RenderPrimitiveIterator), "RenderPrimitiveIterator"); + iter->re= re; + + if(buckets) { + iter->buckets= buckets; + + nr= BLI_findindex(&re->parts, pa); + width= buckets->x - 1; + x= (nr % width) + 1; + y= (nr / width) + 1; + + iter->list[iter->totlist++]= &buckets->all; + iter->list[iter->totlist++]= &buckets->inside[y*buckets->x + x]; + iter->list[iter->totlist++]= &buckets->overlap[y*buckets->x + x]; + iter->list[iter->totlist++]= &buckets->overlap[y*buckets->x + (x-1)]; + iter->list[iter->totlist++]= &buckets->overlap[(y-1)*buckets->x + (x-1)]; + iter->list[iter->totlist++]= &buckets->overlap[(y-1)*buckets->x + x]; + } + else { + iter->index= 0; + iter->tot= re->totstrand; + } + + return iter; +} + +void *next_primitive_iterator(RenderPrimitiveIterator *iter) +{ + if(iter->buckets) { + if(iter->bpr && iter->bprindex >= iter->bpr->totprim) { + iter->bpr= iter->bpr->next; + iter->bprindex= 0; + } + + while(iter->bpr == NULL) { + if(iter->listindex == iter->totlist) + return NULL; + + iter->bpr= iter->list[iter->listindex++]->first; + iter->bprindex= 0; + } + + return iter->bpr->prim[iter->bprindex++]; + } + else { + if(iter->index < iter->tot) { + if((iter->index & 255)==0) + iter->strand= iter->re->strandnodes[iter->index>>8].strand; + else + iter->strand++; + + return iter->strand; + } + else + return NULL; + } +} + +void free_primitive_iterator(RenderPrimitiveIterator *iter) +{ + MEM_freeN(iter); +} + +/* *************** */ + +static float strand_eval_width(Material *ma, float strandco) +{ + float fac; + + strandco= 0.5f*(strandco + 1.0f); + + if(ma->strand_ease!=0.0f) { + if(ma->strand_ease<0.0f) + fac= pow(strandco, 1.0+ma->strand_ease); + else + fac= pow(strandco, 1.0/(1.0f-ma->strand_ease)); + } + else fac= strandco; + + return ((1.0f-fac)*ma->strand_sta + (fac)*ma->strand_end); +} + +void strand_eval_point(StrandSegment *sseg, StrandPoint *spoint) +{ + Material *ma; + StrandBuffer *strandbuf; + float p[4][3], data[4], cross[3], w, dx, dy, t; + int type; + + strandbuf= sseg->buffer; + ma= sseg->buffer->ma; + t= spoint->t; + type= (strandbuf->flag & R_STRAND_BSPLINE)? KEY_BSPLINE: KEY_CARDINAL; + + VECCOPY(p[0], sseg->v[0]->co); + VECCOPY(p[1], sseg->v[1]->co); + VECCOPY(p[2], sseg->v[2]->co); + VECCOPY(p[3], sseg->v[3]->co); + + if(t == 0.0f) { + VECCOPY(spoint->co, sseg->v[1]->co); + spoint->strandco= sseg->v[1]->strandco; + + spoint->dtstrandco= (sseg->v[2]->strandco - sseg->v[0]->strandco); + if(sseg->v[0] != sseg->v[1]) + spoint->dtstrandco *= 0.5f; + } + else if(t == 1.0f) { + VECCOPY(spoint->co, sseg->v[2]->co); + spoint->strandco= sseg->v[2]->strandco; + + spoint->dtstrandco= (sseg->v[3]->strandco - sseg->v[1]->strandco); + if(sseg->v[3] != sseg->v[2]) + spoint->dtstrandco *= 0.5f; + } + else { + set_four_ipo(t, data, type); + spoint->co[0]= data[0]*p[0][0] + data[1]*p[1][0] + data[2]*p[2][0] + data[3]*p[3][0]; + spoint->co[1]= data[0]*p[0][1] + data[1]*p[1][1] + data[2]*p[2][1] + data[3]*p[3][1]; + spoint->co[2]= data[0]*p[0][2] + data[1]*p[1][2] + data[2]*p[2][2] + data[3]*p[3][2]; + spoint->strandco= (1.0f-t)*sseg->v[1]->strandco + t*sseg->v[2]->strandco; + } + + set_afgeleide_four_ipo(t, data, type); + spoint->dtco[0]= data[0]*p[0][0] + data[1]*p[1][0] + data[2]*p[2][0] + data[3]*p[3][0]; + spoint->dtco[1]= data[0]*p[0][1] + data[1]*p[1][1] + data[2]*p[2][1] + data[3]*p[3][1]; + spoint->dtco[2]= data[0]*p[0][2] + data[1]*p[1][2] + data[2]*p[2][2] + data[3]*p[3][2]; + + VECCOPY(spoint->tan, spoint->dtco); + Normalize(spoint->tan); + + VECCOPY(spoint->nor, spoint->co); + VECMUL(spoint->nor, -1.0f); + Normalize(spoint->nor); + + spoint->width= strand_eval_width(ma, spoint->strandco); + + /* outer points */ + Crossf(cross, spoint->co, spoint->tan); + + if(strandbuf->flag & R_STRAND_B_UNITS) + Normalize(cross); + + w= spoint->co[2]*strandbuf->winmat[2][3] + strandbuf->winmat[3][3]; + dx= strandbuf->winx*cross[0]*strandbuf->winmat[0][0]/w; + dy= strandbuf->winy*cross[1]*strandbuf->winmat[1][1]/w; + w= sqrt(dx*dx + dy*dy); + + if(w > 0.0f) { + if(strandbuf->flag & R_STRAND_B_UNITS) { + w= 1.0f/w; + + if(spoint->width < w) + spoint->width= w; + VecMulf(cross, spoint->width*0.5f); + } + else + VecMulf(cross, spoint->width/w); + } + + VecSubf(spoint->co1, spoint->co, cross); + VecAddf(spoint->co2, spoint->co, cross); + + VECCOPY(spoint->dsco, cross); +} + +/* *************** */ + +typedef struct StrandPart { + Render *re; + ZSpan *zspan; + + RenderLayer *rl; + ShadeResult *result; + float *pass; + int *rectz, *outrectz; + unsigned short *mask; + int rectx, recty; + int addpassflag, addzbuf, sample; + + StrandSegment *segment; + GHash *hash; + StrandPoint point1, point2; + ShadeSample ssamp1, ssamp2, ssamp; + float t[3]; +} StrandPart; + +typedef struct StrandSortSegment { + struct StrandSortSegment *next; + int strand, segment; + float z; +} StrandSortSegment; + +static int compare_strand_segment(const void *poin1, const void *poin2) +{ + const StrandSortSegment *seg1= (const StrandSortSegment*)poin1; + const StrandSortSegment *seg2= (const StrandSortSegment*)poin2; + + if(seg1->z < seg2->z) + return -1; + else if(seg1->z == seg2->z) + return 0; + else + return 1; +} + +static void interpolate_vec3(float *v1, float *v2, float t, float negt, float *v) +{ + v[0]= negt*v1[0] + t*v2[0]; + v[1]= negt*v1[1] + t*v2[1]; + v[2]= negt*v1[2] + t*v2[2]; +} + +static void interpolate_vec4(float *v1, float *v2, float t, float negt, float *v) +{ + v[0]= negt*v1[0] + t*v2[0]; + v[1]= negt*v1[1] + t*v2[1]; + v[2]= negt*v1[2] + t*v2[2]; + v[3]= negt*v1[3] + t*v2[3]; +} + +static void interpolate_shade_result(ShadeResult *shr1, ShadeResult *shr2, float t, ShadeResult *shr, int addpassflag) +{ + float negt= 1.0f - t; + + interpolate_vec4(shr1->combined, shr2->combined, t, negt, shr->combined); + + if(addpassflag & SCE_PASS_VECTOR) { + interpolate_vec4(shr1->winspeed, shr2->winspeed, t, negt, shr->winspeed); + } + /* optim... */ + if(addpassflag & ~(SCE_PASS_VECTOR)) { + if(addpassflag & SCE_PASS_RGBA) + interpolate_vec4(shr1->col, shr2->col, t, negt, shr->col); + if(addpassflag & SCE_PASS_NORMAL) { + interpolate_vec3(shr1->nor, shr2->nor, t, negt, shr->nor); + Normalize(shr->nor); + } + if(addpassflag & SCE_PASS_DIFFUSE) + interpolate_vec3(shr1->diff, shr2->diff, t, negt, shr->diff); + if(addpassflag & SCE_PASS_SPEC) + interpolate_vec3(shr1->spec, shr2->spec, t, negt, shr->spec); + if(addpassflag & SCE_PASS_SHADOW) + interpolate_vec3(shr1->shad, shr2->shad, t, negt, shr->shad); + if(addpassflag & SCE_PASS_AO) + interpolate_vec3(shr1->ao, shr2->ao, t, negt, shr->ao); + if(addpassflag & SCE_PASS_REFLECT) + interpolate_vec3(shr1->refl, shr2->refl, t, negt, shr->refl); + if(addpassflag & SCE_PASS_REFRACT) + interpolate_vec3(shr1->refr, shr2->refr, t, negt, shr->refr); + if(addpassflag & SCE_PASS_RADIO) + interpolate_vec3(shr1->rad, shr2->rad, t, negt, shr->rad); + } +} + +static void add_strand_obindex(RenderLayer *rl, int offset, Object *ob) +{ + RenderPass *rpass; + + for(rpass= rl->passes.first; rpass; rpass= rpass->next) { + if(rpass->passtype == SCE_PASS_INDEXOB) { + float *fp= rpass->rect + offset; + *fp= (float)ob->index; + break; + } + } +} + +static void do_strand_point_project(Render *re, ZSpan *zspan, float *co, float *hoco, float *zco) +{ + projectvert(co, re->winmat, hoco); + hoco_to_zco(zspan, zco, hoco); +} + +static void strand_project_point(float winmat[][4], float winx, float winy, StrandPoint *spoint) +{ + float div; + + projectvert(spoint->co, winmat, spoint->hoco); + + div= 1.0f/spoint->hoco[3]; + spoint->x= spoint->hoco[0]*div*winx*0.5f; + spoint->y= spoint->hoco[1]*div*winy*0.5f; +} + +#include "BLI_rand.h" +void strand_shade_point(Render *re, ShadeSample *ssamp, StrandSegment *sseg, StrandPoint *spoint); + +static void strand_shade_get(StrandPart *spart, int lookup, ShadeSample *ssamp, StrandPoint *spoint, StrandVert *svert, StrandSegment *sseg) +{ + ShadeResult *hashshr; + + if(lookup) { + hashshr= BLI_ghash_lookup(spart->hash, svert); + + if(!hashshr) { + strand_shade_point(spart->re, ssamp, sseg, spoint); + + hashshr= MEM_callocN(sizeof(ShadeResult), "HashShadeResult"); + *hashshr= ssamp->shr[0]; + BLI_ghash_insert(spart->hash, svert, hashshr); + } + else { + ssamp->shr[0]= *hashshr; + BLI_ghash_remove(spart->hash, svert, NULL, (GHashValFreeFP)MEM_freeN); + } + } + else + strand_shade_point(spart->re, ssamp, sseg, spoint); +} + +static void strand_shade_segment(StrandPart *spart) +{ + StrandSegment *sseg= spart->segment; + int first, last; + + if(!sseg->shaded) { + first= (sseg->v[1] == &sseg->strand->vert[0]); + last= (sseg->v[2] == &sseg->strand->vert[sseg->strand->totvert-1]); + + strand_shade_get(spart, !first, &spart->ssamp1, &sseg->point1, sseg->v[1], sseg); + strand_shade_get(spart, !last, &spart->ssamp2, &sseg->point2, sseg->v[2], sseg); + sseg->shaded= 1; + } + +#if 0 + float c[3]; + + c[0]= BLI_frand(); + c[1]= BLI_frand(); + c[2]= BLI_frand(); + + spart->ssamp1.shr[0].combined[0] *= c[0]; + spart->ssamp1.shr[0].combined[1] *= c[1]; + spart->ssamp1.shr[0].combined[2] *= c[2]; + + spart->ssamp2.shr[0].combined[0] *= c[0]; + spart->ssamp2.shr[0].combined[1] *= c[1]; + spart->ssamp2.shr[0].combined[2] *= c[2]; +#endif +} + +static void do_strand_blend(void *handle, int x, int y, float u, float v, float z) +{ + StrandPart *spart= (StrandPart*)handle; + StrandBuffer *buffer= spart->segment->buffer; + ShadeResult *shr; + float /**pass,*/ t; + int offset, zverg; + + /* check again solid z-buffer */ + offset = y*spart->rectx + x; + zverg= (int)z; + + if(zverg < spart->rectz[offset]) { + /* fill in output z-buffer if needed */ + if(spart->addzbuf) + if(zverg < spart->outrectz[offset]) + spart->outrectz[offset]= zverg; + + /* check alpha limit */ + shr= spart->result + offset*(spart->re->osa? spart->re->osa: 1); + if(shr[spart->sample].combined[3]>0.999f) + return; + + /* shade points if not shaded yet */ + strand_shade_segment(spart); + + /* interpolate shading from two control points */ + t = u*spart->t[0] + v*spart->t[1] + (1.0f-u-v)*spart->t[2]; + interpolate_shade_result(spart->ssamp1.shr, spart->ssamp2.shr, t, + spart->ssamp.shr, spart->addpassflag); + + /* add in shaderesult array for part */ + spart->ssamp.shi[0].mask= (1<<spart->sample); + addtosamp_shr(shr, &spart->ssamp, spart->addpassflag); + spart->mask[offset] |= (1<<spart->sample); + +#if 0 + /* fill in pass for preview */ + if(spart->sample == 0) { + pass= spart->pass + offset*4; + QUATCOPY(pass, shr->combined); + } +#endif + + if(spart->addpassflag & SCE_PASS_INDEXOB) + add_strand_obindex(spart->rl, offset, buffer->ob); + } +} + +static int strand_test_clip(Render *re, ZSpan *zspan, float *bounds, float *co, float *zcomp) +{ + float hoco[4]; + int clipflag= 0; + + projectvert(co, re->winmat, hoco); + + /* we compare z without perspective division for segment sorting */ + *zcomp= hoco[2]; + + if(hoco[0] > bounds[1]*hoco[3]) clipflag |= 1; + else if(hoco[0]< bounds[0]*hoco[3]) clipflag |= 2; + else if(hoco[1] > bounds[3]*hoco[3]) clipflag |= 4; + else if(hoco[1]< bounds[2]*hoco[3]) clipflag |= 8; + + return clipflag; +} + +void strand_shade_point(Render *re, ShadeSample *ssamp, StrandSegment *sseg, StrandPoint *spoint) +{ + ShadeInput *shi= ssamp->shi; + ShadeResult *shr= ssamp->shr; + VlakRen vlr; + + memset(&vlr, 0, sizeof(vlr)); + vlr.flag= R_SMOOTH|R_VISIBLE; + vlr.lay= sseg->strand->buffer->lay; + vlr.ob= sseg->strand->buffer->ob; + if(sseg->buffer->ma->mode & MA_TANGENT_STR) + vlr.flag |= R_TANGENT; + shi->vlr= &vlr; + + /* cache for shadow */ + shi->samplenr++; + + shade_input_set_strand(shi, sseg->strand, spoint); + shade_input_set_strand_texco(shi, sseg->strand, sseg->v[1], spoint); + + /* init material vars */ + // note, keep this synced with render_types.h + memcpy(&shi->r, &shi->mat->r, 23*sizeof(float)); + shi->har= shi->mat->har; + + /* shade */ + shade_samples_do_AO(ssamp); + shade_input_do_shade(shi, shr); + + /* include lamphalos for strand, since halo layer was added already */ + if(re->flag & R_LAMPHALO) + if(shi->layflag & SCE_LAY_HALO) + renderspothalo(shi, shr->combined, shr->combined[3]); +} + +static void do_scanconvert_strand(Render *re, StrandPart *spart, ZSpan *zspan, float t, float dt, float *co1, float *co2, float *co3, float *co4, int sample) +{ + float jco1[3], jco2[3], jco3[3], jco4[3], jx, jy; + + VECCOPY(jco1, co1); + VECCOPY(jco2, co2); + VECCOPY(jco3, co3); + VECCOPY(jco4, co4); + + if(re->osa) { + jx= -re->jit[sample][0]; + jy= -re->jit[sample][1]; + + jco1[0] += jx; jco1[1] += jy; + jco2[0] += jx; jco2[1] += jy; + jco3[0] += jx; jco3[1] += jy; + jco4[0] += jx; jco4[1] += jy; + } + else if(re->i.curblur) { + jx= -re->jit[re->i.curblur-1][0]; + jy= -re->jit[re->i.curblur-1][1]; + + jco1[0] += jx; jco1[1] += jy; + jco2[0] += jx; jco2[1] += jy; + jco3[0] += jx; jco3[1] += jy; + jco4[0] += jx; jco4[1] += jy; + } + + spart->sample= sample; + + spart->t[0]= t-dt; + spart->t[1]= t-dt; + spart->t[2]= t; + zspan_scanconvert_strand(zspan, spart, jco1, jco2, jco3, do_strand_blend); + spart->t[0]= t-dt; + spart->t[1]= t; + spart->t[2]= t; + zspan_scanconvert_strand(zspan, spart, jco1, jco3, jco4, do_strand_blend); +} + +static void strand_render(Render *re, StrandPart *spart, ZSpan *zspan, StrandPoint *p1, StrandPoint *p2) +{ + if(spart) { + float t= p2->t; + float dt= p2->t - p1->t; + int a; + + if(re->osa) { + for(a=0; a<re->osa; a++) + do_scanconvert_strand(re, spart, zspan, t, dt, p1->zco2, p1->zco1, p2->zco1, p2->zco2, a); + } + else + do_scanconvert_strand(re, spart, zspan, t, dt, p1->zco2, p1->zco1, p2->zco1, p2->zco2, 0); + } + else { + float hoco1[4], hoco2[3]; + + projectvert(p1->co, re->winmat, hoco1); + projectvert(p2->co, re->winmat, hoco2); + + /* render both strand and single pixel wire to counter aliasing */ + zbufclip4(zspan, 0, p1->hoco2, p1->hoco1, p2->hoco1, p2->hoco2, 0, 0, 0, 0); + zbufsinglewire(zspan, 0, hoco1, hoco2); + } +} + +static int strand_segment_recursive(Render *re, StrandPart *spart, ZSpan *zspan, StrandSegment *sseg, StrandPoint *p1, StrandPoint *p2, int depth) +{ + StrandPoint p; + StrandBuffer *buffer= sseg->buffer; + float dot, d1[2], d2[2], len1, len2; + + if(depth == buffer->maxdepth) + return 0; + + p.t= (p1->t + p2->t)*0.5f; + strand_eval_point(sseg, &p); + strand_project_point(buffer->winmat, buffer->winx, buffer->winy, &p); + + d1[0]= (p.x - p1->x); + d1[1]= (p.y - p1->y); + len1= d1[0]*d1[0] + d1[1]*d1[1]; + + d2[0]= (p2->x - p.x); + d2[1]= (p2->y - p.y); + len2= d2[0]*d2[0] + d2[1]*d2[1]; + + if(len1 == 0.0f || len2 == 0.0f) + return 0; + + dot= d1[0]*d2[0] + d1[1]*d2[1]; + if(dot*dot > sseg->sqadaptcos*len1*len2) + return 0; + + if(spart) { + do_strand_point_project(re, zspan, p.co1, p.hoco1, p.zco1); + do_strand_point_project(re, zspan, p.co2, p.hoco2, p.zco2); + } + else { + projectvert(p.co1, re->winmat, p.hoco1); + projectvert(p.co2, re->winmat, p.hoco2); + } + + if(!strand_segment_recursive(re, spart, zspan, sseg, p1, &p, depth+1)) + strand_render(re, spart, zspan, p1, &p); + if(!strand_segment_recursive(re, spart, zspan, sseg, &p, p2, depth+1)) + strand_render(re, spart, zspan, &p, p2); + + return 1; +} + +void render_strand_segment(Render *re, StrandPart *spart, ZSpan *zspan, StrandSegment *sseg) +{ + StrandBuffer *buffer= sseg->buffer; + StrandPoint *p1= &sseg->point1; + StrandPoint *p2= &sseg->point2; + + p1->t= 0.0f; + p2->t= 1.0f; + + strand_eval_point(sseg, p1); + strand_project_point(buffer->winmat, buffer->winx, buffer->winy, p1); + strand_eval_point(sseg, p2); + strand_project_point(buffer->winmat, buffer->winx, buffer->winy, p2); + + if(spart) { + do_strand_point_project(re, zspan, p1->co1, p1->hoco1, p1->zco1); + do_strand_point_project(re, zspan, p1->co2, p1->hoco2, p1->zco2); + do_strand_point_project(re, zspan, p2->co1, p2->hoco1, p2->zco1); + do_strand_point_project(re, zspan, p2->co2, p2->hoco2, p2->zco2); + } + else { + projectvert(p1->co1, re->winmat, p1->hoco1); + projectvert(p1->co2, re->winmat, p1->hoco2); + projectvert(p2->co1, re->winmat, p2->hoco1); + projectvert(p2->co2, re->winmat, p2->hoco2); + } + + if(!strand_segment_recursive(re, spart, zspan, sseg, p1, p2, 0)) + strand_render(re, spart, zspan, p1, p2); +} + +static void zbuffer_strands_filter(Render *re, RenderPart *pa, RenderLayer *rl, StrandPart *spart, float *pass) +{ + RenderResult *rr= pa->result; + ShadeResult *shr, *shrrect= spart->result; + float *passrect= pass; + long *rdrect; + int osa, x, y, a, crop= 0, offs=0, od; + + osa= (re->osa? re->osa: 1); + + /* filtered render, for now we assume only 1 filter size */ + if(pa->crop) { + crop= 1; + offs= pa->rectx + 1; + passrect+= 4*offs; + shrrect+= offs*osa; + } + + rdrect= pa->rectdaps; + + /* zero alpha pixels get speed vector max again */ + if(spart->addpassflag & SCE_PASS_VECTOR) + if(rl->layflag & SCE_LAY_SOLID) + reset_sky_speedvectors(pa, rl, rl->scolrect); + + /* init scanline updates */ + rr->renrect.ymin= 0; + rr->renrect.ymax= -pa->crop; + rr->renlay= rl; + + /* filter the shade results */ + for(y=pa->disprect.ymin+crop; y<pa->disprect.ymax-crop; y++, rr->renrect.ymax++) { + pass= passrect; + shr= shrrect; + od= offs; + + for(x=pa->disprect.xmin+crop; x<pa->disprect.xmax-crop; x++, shr+=osa, pass+=4, od++) { + if(spart->mask[od] == 0) { + if(spart->addpassflag & SCE_PASS_VECTOR) + add_transp_speed(rl, od, NULL, 0.0f, rdrect); + } + else { + if(re->osa == 0) { + addAlphaUnderFloat(pass, shr->combined); + } + else { + for(a=0; a<re->osa; a++) + add_filt_fmask(1<<a, shr[a].combined, pass, rr->rectx); + } + + if(spart->addpassflag) { + /* merge all in one, and then add */ + merge_transp_passes(rl, shr); + add_transp_passes(rl, od, shr, pass[3]); + + if(spart->addpassflag & SCE_PASS_VECTOR) + add_transp_speed(rl, od, shr->winspeed, pass[3], rdrect); + } + } + } + + shrrect+= pa->rectx*osa; + passrect+= 4*pa->rectx; + offs+= pa->rectx; + } + + /* disable scanline updating */ + rr->renlay= NULL; +} + +/* render call to fill in strands */ +unsigned short *zbuffer_strands_shade(Render *re, RenderPart *pa, RenderLayer *rl, float *pass) +{ + struct RenderPrimitiveIterator *iter; + ZSpan zspan; + StrandRen *strand=0; + StrandVert *svert; + StrandPart spart; + StrandSegment sseg; + StrandSortSegment *sortsegments = NULL, *sortseg, *firstseg; + MemArena *memarena; + float z[4], bounds[4]; + int a, b, resultsize, totsegment, clip[4]; + + if(re->test_break()) + return NULL; + if(re->strandbufs.first == NULL) + return NULL; + + /* setup StrandPart */ + memset(&spart, 0, sizeof(spart)); + + spart.re= re; + spart.rl= rl; + spart.pass= pass; + spart.rectx= pa->rectx; + spart.recty= pa->recty; + spart.rectz= pa->rectz; + spart.addpassflag= rl->passflag & ~(SCE_PASS_Z|SCE_PASS_COMBINED); + spart.addzbuf= rl->passflag & SCE_PASS_Z; + + if(re->osa) resultsize= pa->rectx*pa->recty*re->osa; + else resultsize= pa->rectx*pa->recty; + spart.result= MEM_callocN(sizeof(ShadeResult)*resultsize, "StrandPartResult"); + spart.mask= MEM_callocN(pa->rectx*pa->recty*sizeof(short), "StrandPartMask"); + + if(spart.addpassflag & SCE_PASS_VECTOR) { + /* initialize speed vectors */ + for(a=0; a<resultsize; a++) { + spart.result[a].winspeed[0]= PASS_VECTOR_MAX; + spart.result[a].winspeed[1]= PASS_VECTOR_MAX; + spart.result[a].winspeed[2]= PASS_VECTOR_MAX; + spart.result[a].winspeed[3]= PASS_VECTOR_MAX; + } + } + + if(spart.addzbuf) { + /* duplicate rectz so we can read from the old buffer, while + * writing new z values */ + spart.rectz= MEM_dupallocN(pa->rectz); + spart.outrectz= pa->rectz; + } + + shade_sample_initialize(&spart.ssamp1, pa, rl); + shade_sample_initialize(&spart.ssamp2, pa, rl); + shade_sample_initialize(&spart.ssamp, pa, rl); + spart.ssamp1.shi[0].sample= 0; + spart.ssamp2.shi[0].sample= 1; + spart.ssamp1.tot= 1; + spart.ssamp2.tot= 1; + spart.ssamp.tot= 1; + + zbuf_alloc_span(&zspan, pa->rectx, pa->recty); + + /* needed for transform from hoco to zbuffer co */ + zspan.zmulx= ((float)re->winx)/2.0; + zspan.zmuly= ((float)re->winy)/2.0; + + zspan.zofsx= -pa->disprect.xmin; + zspan.zofsy= -pa->disprect.ymin; + + /* to center the sample position */ + zspan.zofsx -= 0.5f; + zspan.zofsy -= 0.5f; + + /* clipping setup */ + bounds[0]= (2*pa->disprect.xmin - re->winx-1)/(float)re->winx; + bounds[1]= (2*pa->disprect.xmax - re->winx+1)/(float)re->winx; + bounds[2]= (2*pa->disprect.ymin - re->winy-1)/(float)re->winy; + bounds[3]= (2*pa->disprect.ymax - re->winy+1)/(float)re->winy; + + /* sort segments */ + iter= init_primitive_iterator(re, re->strandbuckets, pa); + + memarena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE); + firstseg= NULL; + sortseg= sortsegments; + totsegment= 0; + + while((strand = next_primitive_iterator(iter))) { + if(re->test_break()) + break; + + if(strand->clip) + continue; + + svert= strand->vert; + + /* keep clipping and z depth for 4 control points */ + clip[1]= strand_test_clip(re, &zspan, bounds, svert->co, &z[1]); + clip[2]= strand_test_clip(re, &zspan, bounds, (svert+1)->co, &z[2]); + clip[0]= clip[1]; z[0]= z[1]; + + for(b=0; b<strand->totvert-1; b++, svert++) { + /* compute 4th point clipping and z depth */ + if(b < strand->totvert-2) { + clip[3]= strand_test_clip(re, &zspan, bounds, (svert+2)->co, &z[3]); + } + else { + clip[3]= clip[2]; z[3]= z[2]; + } + + /* check clipping and add to sortsegments buffer */ + if(!(clip[0] & clip[1] & clip[2] & clip[3])) { + sortseg= BLI_memarena_alloc(memarena, sizeof(StrandSortSegment)); + sortseg->strand= strand->index; + sortseg->segment= b; + + sortseg->z= 0.5f*(z[1] + z[2]); + + sortseg->next= firstseg; + firstseg= sortseg; + totsegment++; + } + + /* shift clipping and z depth */ + clip[0]= clip[1]; z[0]= z[1]; + clip[1]= clip[2]; z[1]= z[2]; + clip[2]= clip[3]; z[2]= z[3]; + } + } + + free_primitive_iterator(iter); + + if(!re->test_break()) { + /* convert list to array and sort */ + sortsegments= MEM_mallocN(sizeof(StrandSortSegment)*totsegment, "StrandSortSegment"); + for(a=0, sortseg=firstseg; a<totsegment; a++, sortseg=sortseg->next) + sortsegments[a]= *sortseg; + qsort(sortsegments, totsegment, sizeof(StrandSortSegment), compare_strand_segment); + } + + BLI_memarena_free(memarena); + + spart.hash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); + + if(!re->test_break()) { + /* render segments in sorted order */ + sortseg= sortsegments; + for(a=0; a<totsegment; a++, sortseg++) { + if(re->test_break()) + break; + + sseg.strand= RE_findOrAddStrand(re, sortseg->strand); + sseg.buffer= sseg.strand->buffer; + sseg.sqadaptcos= sseg.buffer->adaptcos; + sseg.sqadaptcos *= sseg.sqadaptcos; + + svert= sseg.strand->vert + sortseg->segment; + sseg.v[0]= (sortseg->segment > 0)? (svert-1): svert; + sseg.v[1]= svert; + sseg.v[2]= svert+1; + sseg.v[3]= (sortseg->segment < sseg.strand->totvert-2)? svert+2: svert+1; + sseg.shaded= 0; + + spart.segment= &sseg; + + render_strand_segment(re, &spart, &zspan, &sseg); + } + } + + // TODO printf(">>> %d\n", BLI_ghash_size(spart.hash)); + BLI_ghash_free(spart.hash, NULL, (GHashValFreeFP)MEM_freeN); + + zbuffer_strands_filter(re, pa, rl, &spart, pass); + + /* free */ + MEM_freeN(spart.result); + + if(spart.addzbuf) + MEM_freeN(spart.rectz); + + if(sortsegments) + MEM_freeN(sortsegments); + + zbuf_free_span(&zspan); + + if(!(re->osa && (rl->layflag & SCE_LAY_SOLID))) { + MEM_freeN(spart.mask); + spart.mask= NULL; + } + + return spart.mask; +} + +void project_strands(Render *re, void (*projectfunc)(float *, float mat[][4], float *), int do_pano, int do_buckets) +{ + StrandRen *strand = NULL; + StrandVert *svert; + float hoco[4], min[2], max[2], bucketco[2], vec[3]; + int a, b; + /* float bmin[3], bmax[3], bpad[3], padding[2]; */ + + if(re->strandbuckets) { + free_buckets(re->strandbuckets); + re->strandbuckets= NULL; + } + + if(do_buckets) + re->strandbuckets= init_buckets(re); + + /* calculate view coordinates (and zbuffer value) */ + for(a=0; a<re->totstrand; a++) { + if((a & 255)==0) strand= re->strandnodes[a>>8].strand; + else strand++; + + strand->clip= ~0; + +#if 0 + if(!(strand->buffer->flag & R_STRAND_BSPLINE)) { + INIT_MINMAX(bmin, bmax); + svert= strand->vert; + for(b=0; b<strand->totvert; b++, svert++) + DO_MINMAX(svert->co, bmin, bmax) + + bpad[0]= (bmax[0]-bmin[0])*0.2f; + bpad[1]= (bmax[1]-bmin[1])*0.2f; + bpad[2]= (bmax[2]-bmin[2])*0.2f; + } + else + bpad[0]= bpad[1]= bpad[2]= 0.0f; + + ma= strand->buffer->ma; + width= MAX2(ma->strand_sta, ma->strand_end); + if(strand->buffer->flag & R_STRAND_B_UNITS) { + bpad[0] += 0.5f*width; + bpad[1] += 0.5f*width; + bpad[2] += 0.5f*width; + } +#endif + + INIT_MINMAX2(min, max); + svert= strand->vert; + for(b=0; b<strand->totvert; b++, svert++) { + //VECADD(vec, svert->co, bpad); + + /* same as VertRen */ + if(do_pano) { + vec[0]= re->panoco*svert->co[0] + re->panosi*svert->co[2]; + vec[1]= svert->co[1]; + vec[2]= -re->panosi*svert->co[0] + re->panoco*svert->co[2]; + } + else + VECCOPY(vec, svert->co) + + /* Go from wcs to hcs ... */ + projectfunc(vec, re->winmat, hoco); + /* ... and clip in that system. */ + strand->clip &= testclip(hoco); + + if(do_buckets) { + project_hoco_to_bucket(re->strandbuckets, hoco, bucketco); + DO_MINMAX2(bucketco, min, max); + } + } + + if(do_buckets) { +#if 0 + if(strand->buffer->flag & R_STRAND_BSPLINE) { + min[0] -= width; + min[1] -= width; + max[0] += width; + max[1] += width; + } + else { + /* catmull-rom stays within 1.2f bounds in object space, + * is this still true after projection? */ + min[0] -= width + (max[0]-min[0])*0.2f; + min[1] -= width + (max[1]-min[1])*0.2f; + max[0] += width + (max[0]-min[0])*0.2f; + max[1] += width + (max[1]-min[1])*0.2f; + } +#endif + + add_buckets_primitive(re->strandbuckets, min, max, strand); + } + } +} + diff --git a/source/blender/render/intern/source/texture.c b/source/blender/render/intern/source/texture.c index accd39170e4..41a46679e95 100644 --- a/source/blender/render/intern/source/texture.c +++ b/source/blender/render/intern/source/texture.c @@ -1272,6 +1272,24 @@ void texture_rgb_blend(float *in, float *tex, float *out, float fact, float facg in[2]= 1.0 - (facm+fact*(1.0-tex[2])) * (1.0-out[2]); break; + case MTEX_OVERLAY: + fact*= facg; + facm= 1.0-facg; + + if(out[0] < 0.5f) + in[0] = out[0] * (facm + 2.0f*fact*tex[0]); + else + in[0] = 1.0f - (facm + 2.0f*fact*(1.0 - tex[0])) * (1.0 - out[0]); + if(out[1] < 0.5f) + in[1] = out[1] * (facm + 2.0f*fact*tex[1]); + else + in[1] = 1.0f - (facm + 2.0f*fact*(1.0 - tex[1])) * (1.0 - out[1]); + if(out[2] < 0.5f) + in[2] = out[2] * (facm + 2.0f*fact*tex[2]); + else + in[2] = 1.0f - (facm + 2.0f*fact*(1.0 - tex[2])) * (1.0 - out[2]); + break; + case MTEX_SUB: fact= -fact; case MTEX_ADD: diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index 80b20a8e18e..cb92f8cefb3 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -39,8 +39,8 @@ #include "BLI_arithb.h" #include "BLI_blenlib.h" -#include "BLI_threads.h" #include "BLI_jitter.h" +#include "BLI_threads.h" #include "MTC_matrixops.h" #include "MEM_guardedalloc.h" @@ -69,6 +69,7 @@ #include "shadbuf.h" #include "shading.h" #include "sss.h" +#include "strand.h" /* own includes */ #include "zbuf.h" @@ -861,7 +862,7 @@ static int clipline(float *v1, float *v2) /* return 0: do not draw */ return 0; } -static void hoco_to_zco(ZSpan *zspan, float *zco, float *hoco) +void hoco_to_zco(ZSpan *zspan, float *zco, float *hoco) { float div; @@ -977,6 +978,34 @@ void zbufclipwire(ZSpan *zspan, int zvlnr, VlakRen *vlr) } +void zbufsinglewire(ZSpan *zspan, int zvlnr, float *ho1, float *ho2) +{ + float f1[4], f2[4]; + int c1, c2; + + c1= testclip(ho1); + c2= testclip(ho2); + + if(c1 | c2) { /* not in the middle */ + if(!(c1 & c2)) { /* not out completely */ + QUATCOPY(f1, ho1); + QUATCOPY(f2, ho2); + + if(clipline(f1, f2)) { + hoco_to_zco(zspan, f1, f1); + hoco_to_zco(zspan, f2, f2); + zspan->zbuflinefunc(zspan, zvlnr, f1, f2); + } + } + } + else { + hoco_to_zco(zspan, f1, ho1); + hoco_to_zco(zspan, f2, ho2); + + zspan->zbuflinefunc(zspan, zvlnr, f1, f2); + } +} + /** * Fill the z buffer, but invert z order, and add the face index to * the corresponing face buffer. @@ -1312,7 +1341,105 @@ static void zbuffillGL_onlyZ(ZSpan *zspan, int zvlnr, float *v1, float *v2, floa } /* 2d scanconvert for tria, calls func for each x,y coordinate and gives UV barycentrics */ -/* zspan should be initialized, has rect size and span buffers */ +void zspan_scanconvert_strand(ZSpan *zspan, void *handle, float *v1, float *v2, float *v3, void (*func)(void *, int, int, float, float, float) ) +{ + float x0, y0, x1, y1, x2, y2, z0, z1, z2, z; + float u, v, uxd, uyd, vxd, vyd, uy0, vy0, zxd, zyd, zy0, xx1; + float *span1, *span2; + int x, y, sn1, sn2, rectx= zspan->rectx, my0, my2; + + /* init */ + zbuf_init_span(zspan); + + /* set spans */ + zbuf_add_to_span(zspan, v1, v2); + zbuf_add_to_span(zspan, v2, v3); + zbuf_add_to_span(zspan, v3, v1); + + /* clipped */ + if(zspan->minp2==NULL || zspan->maxp2==NULL) return; + + if(zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1; + if(zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1; + + // printf("my %d %d\n", my0, my2); + if(my2<my0) return; + + /* ZBUF DX DY, in floats still */ + x1= v1[0]- v2[0]; + x2= v2[0]- v3[0]; + y1= v1[1]- v2[1]; + y2= v2[1]- v3[1]; + z1= v1[2]- v2[2]; + z2= v2[2]- v3[2]; + + x0= y1*z2-z1*y2; + y0= z1*x2-x1*z2; + z0= x1*y2-y1*x2; + + if(z0==0.0f) return; + + xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2]; + zxd= -(double)x0/(double)z0; + zyd= -(double)y0/(double)z0; + zy0= ((double)my2)*zyd + (double)xx1; + + z1= 1.0f; // (u1 - u2) + z2= 0.0f; // (u2 - u3) + + x0= y1*z2-z1*y2; + y0= z1*x2-x1*z2; + + xx1= (x0*v1[0] + y0*v1[1])/z0 + 1.0f; + uxd= -(double)x0/(double)z0; + uyd= -(double)y0/(double)z0; + uy0= ((double)my2)*uyd + (double)xx1; + + z1= -1.0f; // (v1 - v2) + z2= 1.0f; // (v2 - v3) + + x0= y1*z2-z1*y2; + y0= z1*x2-x1*z2; + + xx1= (x0*v1[0] + y0*v1[1])/z0; + vxd= -(double)x0/(double)z0; + vyd= -(double)y0/(double)z0; + vy0= ((double)my2)*vyd + (double)xx1; + + /* correct span */ + sn1= (my0 + my2)/2; + if(zspan->span1[sn1] < zspan->span2[sn1]) { + span1= zspan->span1+my2; + span2= zspan->span2+my2; + } + else { + span1= zspan->span2+my2; + span2= zspan->span1+my2; + } + + for(y=my2; y>=my0; y--, span1--, span2--) { + + sn1= floor(*span1); + sn2= floor(*span2); + sn1++; + + if(sn2>=rectx) sn2= rectx-1; + if(sn1<0) sn1= 0; + + u= (double)sn1*uxd + uy0; + v= (double)sn1*vxd + vy0; + z= (double)sn1*zxd + zy0; + + for(x= sn1; x<=sn2; x++, u+=uxd, v+=vxd, z+=zxd) + func(handle, x, y, u, v, z); + + uy0 -= uyd; + vy0 -= vyd; + zy0 -= zyd; + } +} + +/* scanconvert for strand triangles, calls func for each x,y coordinate and gives UV barycentrics and z */ void zspan_scanconvert(ZSpan *zspan, void *handle, float *v1, float *v2, float *v3, void (*func)(void *, int, int, float, float) ) { @@ -1957,7 +2084,10 @@ void zbuffer_shadow(Render *re, LampRen *lar, int *rectz, int size, float jitx, ZSpan zspan; VlakRen *vlr= NULL; Material *ma= NULL; - int a, ok=1, lay= -1; + StrandSegment sseg; + StrandRen *strand= NULL; + StrandVert *svert; + int a, b, ok=1, lay= -1; if(lar->mode & LA_LAYER) lay= lar->lay; @@ -2002,6 +2132,39 @@ void zbuffer_shadow(Render *re, LampRen *lar, int *rectz, int size, float jitx, } } } + + /* shadow */ + for(a=0; a<re->totstrand; a++) { + if((a & 255)==0) strand= re->strandnodes[a>>8].strand; + else strand++; + + if(strand->clip) + continue; + + sseg.buffer= strand->buffer; + sseg.sqadaptcos= sseg.buffer->adaptcos; + sseg.sqadaptcos *= sseg.sqadaptcos; + sseg.strand= strand; + svert= strand->vert; + + /* note, these conditions are copied in shadowbuf_autoclip() */ + if(sseg.buffer->ma!= ma) { + ma= sseg.buffer->ma; + ok= 1; + if((ma->mode & MA_SHADBUF)==0) ok= 0; + } + + if(ok && (sseg.buffer->lay & lay)) { + for(b=0; b<strand->totvert-1; b++, svert++) { + sseg.v[0]= (b > 0)? (svert-1): svert; + sseg.v[1]= svert; + sseg.v[2]= svert+1; + sseg.v[3]= (b < strand->totvert-2)? svert+2: svert+1; + + render_strand_segment(re, NULL, &zspan, &sseg); + } + } + } /* merge buffers */ if(lar->buftype==LA_SHADBUF_HALFWAY) { @@ -2019,7 +2182,6 @@ static void zbuffill_sss(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v double zxd, zyd, zy0, z; float x0, y0, x1, y1, x2, y2, z0, z1, z2, xx1, *span1, *span2; int x, y, sn1, sn2, rectx= zspan->rectx, my0, my2; - /* init */ zbuf_init_span(zspan); @@ -2824,7 +2986,7 @@ static int zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, un /* speed pointer NULL = sky, we clear */ /* else if either alpha is full or no solid was filled in: copy speed */ /* else fill in minimum speed */ -static void add_transp_speed(RenderLayer *rl, int offset, float *speed, float alpha, long *rdrect) +void add_transp_speed(RenderLayer *rl, int offset, float *speed, float alpha, long *rdrect) { RenderPass *rpass; @@ -2852,7 +3014,6 @@ static void add_transp_speed(RenderLayer *rl, int offset, float *speed, float al fp[2]= speed[2]; fp[3]= speed[3]; } - } break; } @@ -2877,7 +3038,7 @@ static void add_transp_obindex(RenderLayer *rl, int offset, int facenr) /* ONLY OSA! merge all shaderesult samples to one */ /* target should have been cleared */ -static void merge_transp_passes(RenderLayer *rl, ShadeResult *shr) +void merge_transp_passes(RenderLayer *rl, ShadeResult *shr) { RenderPass *rpass; float weight= 1.0f/((float)R.osa); @@ -2961,7 +3122,7 @@ static void merge_transp_passes(RenderLayer *rl, ShadeResult *shr) } -static void add_transp_passes(RenderLayer *rl, int offset, ShadeResult *shr, float alpha) +void add_transp_passes(RenderLayer *rl, int offset, ShadeResult *shr, float alpha) { RenderPass *rpass; @@ -3113,11 +3274,11 @@ static void addvecmul(float *v1, float *v2, float fac) v1[2]= v1[2]+fac*v2[2]; } -static int addtosamp_shr(ShadeResult *samp_shr, ShadeSample *ssamp, int addpassflag) +int addtosamp_shr(ShadeResult *samp_shr, ShadeSample *ssamp, int addpassflag) { - int a, sample, retval = R.osa; + int a, sample, osa = (R.osa? R.osa: 1), retval = osa; - for(a=0; a < R.osa; a++, samp_shr++) { + for(a=0; a < osa; a++, samp_shr++) { ShadeInput *shi= ssamp->shi; ShadeResult *shr= ssamp->shr; @@ -3159,7 +3320,7 @@ static int addtosamp_shr(ShadeResult *samp_shr, ShadeSample *ssamp, int addpassf addvecmul(samp_shr->refr, shr->refr, fac); if(addpassflag & SCE_PASS_RADIO) - addvecmul(samp_shr->refr, shr->rad, fac); + addvecmul(samp_shr->rad, shr->rad, fac); } } } @@ -3169,7 +3330,7 @@ static int addtosamp_shr(ShadeResult *samp_shr, ShadeSample *ssamp, int addpassf return retval; } -static void reset_sky_speedvectors(RenderPart *pa, RenderLayer *rl) +void reset_sky_speedvectors(RenderPart *pa, RenderLayer *rl, float *rectf) { /* speed vector exception... if solid render was done, sky pixels are set to zero already */ /* for all pixels with alpha zero, we re-initialize speed again then */ @@ -3178,7 +3339,7 @@ static void reset_sky_speedvectors(RenderPart *pa, RenderLayer *rl) fp= RE_RenderLayerGetPass(rl, SCE_PASS_VECTOR); if(fp==NULL) return; - col= rl->acolrect+3; + col= rectf+3; for(a= 4*pa->rectx*pa->recty -4; a>=0; a-=4) { if(col[a]==0.0f) { @@ -3222,7 +3383,10 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas /* general shader info, passes */ shade_sample_initialize(&ssamp, pa, rl); addpassflag= rl->passflag & ~(SCE_PASS_Z|SCE_PASS_COMBINED); - addzbuf= rl->passflag & SCE_PASS_Z; + if((rl->layflag & SCE_LAY_STRAND) && R.strandbufs.first) + addzbuf= 1; /* strands layer needs the z-buffer */ + else + addzbuf= rl->passflag & SCE_PASS_Z; if(R.osa) sampalpha= 1.0f/(float)R.osa; @@ -3251,7 +3415,7 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas /* zero alpha pixels get speed vector max again */ if(addpassflag & SCE_PASS_VECTOR) if(rl->layflag & SCE_LAY_SOLID) - reset_sky_speedvectors(pa, rl); + reset_sky_speedvectors(pa, rl, rl->acolrect); /* filtered render, for now we assume only 1 filter size */ if(pa->crop) { diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 05fed2f8fbc..db86f14ad76 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -521,14 +521,14 @@ void do_common_editbuts(unsigned short event) // old name, is a mix of object an while(a--) { if(bezt->hide==0) { if(event==B_MATSEL) { - bezt->f1 |= 1; - bezt->f2 |= 1; - bezt->f3 |= 1; + bezt->f1 |= SELECT; + bezt->f2 |= SELECT; + bezt->f3 |= SELECT; } else { - bezt->f1 &= ~1; - bezt->f2 &= ~1; - bezt->f3 &= ~1; + bezt->f1 &= ~SELECT; + bezt->f2 &= ~SELECT; + bezt->f3 &= ~SELECT; } } bezt++; @@ -539,8 +539,8 @@ void do_common_editbuts(unsigned short event) // old name, is a mix of object an bp= nu->bp; while(a--) { if(bp->hide==0) { - if(event==B_MATSEL) bp->f1 |= 1; - else bp->f1 &= ~1; + if(event==B_MATSEL) bp->f1 |= SELECT; + else bp->f1 &= ~SELECT; } bp++; } @@ -1645,10 +1645,13 @@ static void modifiers_psysEnable(void *ob_v, void *md_v) { ParticleSystemModifierData *psmd = (ParticleSystemModifierData*) md_v; - if(psmd->modifier.mode & eModifierMode_Realtime) + if(psmd->modifier.mode & eModifierMode_Realtime) { psmd->psys->flag |= PSYS_ENABLED; - else + } + else { psmd->psys->flag &= ~PSYS_ENABLED; + PE_free_particle_edit(psmd->psys); + } } static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco, int *yco, int index, int cageIndex, int lastCageIndex) @@ -4001,10 +4004,14 @@ static void editing_panel_armature_visuals(Object *ob, bArmature *arm) uiDefBut(block, LABEL, 0, "Ghost Options", 10,180,150,20, 0, 0, 0, 0, 0, ""); uiBlockBeginAlign(block); - uiDefButS(block, MENU, REDRAWVIEW3D, "Ghosts %t|Around Current Frame %x0|In Range %x1", - 10, 160, 150, 20, &arm->ghosttype, 0, 0, 0, 0, "Choose range of Ghosts to draw for current Action"); - - uiDefButS(block, NUM, REDRAWVIEW3D, "GStep: ", 10,140,150,20, &arm->ghostsize, 1.0f, 20.0f, 0, 0, "How many frames between Ghost instances"); + uiDefButS(block, MENU, REDRAWVIEW3D, "Ghosts %t|Around Current Frame %x0|In Range %x1|On Keyframes %x2", + 10, 160, 150, 20, &arm->ghosttype, 0, 0, 0, 0, "Choose range of Ghosts to draw for current Action"); + + if (arm->ghosttype != ARM_GHOST_KEYS) + uiDefButS(block, NUM, REDRAWVIEW3D, "GStep: ", 10,140,120,20, &arm->ghostsize, 1.0f, 20.0f, 0, 0, "How many frames between Ghost instances"); + else + uiDefBut(block, LABEL, REDRAWVIEW3D, "GStep: N/A", 10,140,120,20, NULL, 0.0f, 0.0f, 0, 0, "How many frames between Ghost instances"); + uiDefButBitI(block, TOG, ARM_GHOST_ONLYSEL, REDRAWVIEW3D, "Sel", 130, 140, 30, 20, &arm->flag, 0, 0, 0, 0, "Only show Ghosts for selected bones"); uiBlockEndAlign(block); uiBlockBeginAlign(block); @@ -4012,7 +4019,7 @@ static void editing_panel_armature_visuals(Object *ob, bArmature *arm) /* range is around current frame */ uiDefButS(block, NUM, REDRAWVIEW3D, "Ghost: ", 10,110,150,20, &arm->ghostep, 0.0f, 30.0f, 0, 0, "Draw Ghosts around current frame, for current Action"); } - else if (arm->ghosttype == ARM_GHOST_RANGE) { + else if (ELEM(arm->ghosttype, ARM_GHOST_RANGE, ARM_GHOST_KEYS)) { /* range is defined by start+end frame below */ uiDefButI(block, NUM,REDRAWVIEW3D,"GSta:",10,110,150,20, &arm->ghostsf,1.0,MAXFRAMEF, 0, 0, "The start frame for Ghost display range"); uiDefButI(block, NUM,REDRAWVIEW3D,"GEnd:",10,90,150,20, &arm->ghostef,arm->ghostsf,MAXFRAMEF, 0, 0, "The end frame for Ghost display range"); @@ -4020,30 +4027,38 @@ static void editing_panel_armature_visuals(Object *ob, bArmature *arm) uiBlockEndAlign(block); /* Bone Path Drawing Options */ - uiDefBut(block, LABEL, 0, "Bone Paths", 165,180,150,20, 0, 0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "Bone Paths Drawing:", 165,180,170,20, 0, 0, 0, 0, 0, ""); uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, ARM_PATH_FNUMS, REDRAWVIEW3D, "Frame Nums", 170, 160, 80, 20, &arm->pathflag, 0, 0, 0, 0, "Show frame numbers on path"); - uiDefButS(block, NUM, REDRAWVIEW3D, "PStep:",250,160,80,20, &arm->pathsize,1,100, 10, 50, "Frames between highlighted points on bone path"); - uiDefButBitS(block, TOG, ARM_PATH_KFRAS, REDRAWVIEW3D, "Show Keys", 170, 140, 160, 20, &arm->pathflag, 0, 0, 0, 0, "Show key frames on path"); + uiDefButS(block, NUM, REDRAWVIEW3D, "PStep:",170,160,80,20, &arm->pathsize,1,100, 10, 50, "Frames between highlighted points on bone path"); + uiDefButBitS(block, TOG, ARM_PATH_FNUMS, REDRAWVIEW3D, "Frame Nums", 250, 160, 80, 20, &arm->pathflag, 0, 0, 0, 0, "Show frame numbers on path"); + + uiDefButBitS(block, TOG, ARM_PATH_KFRAS, REDRAWVIEW3D, "Show Keys", 170, 140, 80, 20, &arm->pathflag, 0, 0, 0, 0, "Show key frames on path"); + uiDefButBitS(block, TOG, ARM_PATH_KFNOS, REDRAWVIEW3D, "Keyframe Nums", 250, 140, 80, 20, &arm->pathflag, 0, 0, 0, 0, "Show frame numbers of key frames on path"); uiBlockEndAlign(block); uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, ARM_PATH_ACFRA, REDRAWVIEW3D, "Around Current Frame", 170, 105, 160, 20, &arm->pathflag, 0, 0, 0, 0, "Calculate Bone Path around the current frame"); - if (arm->pathflag & ARM_PATH_ACFRA) { - uiDefButI(block, NUM,REDRAWVIEW3D,"PPre:",170,85,80,20, &arm->pathbc, 1.0, MAXFRAMEF/2, 0, 0, "The number of frames before current frame for Bone Path display range"); - uiDefButI(block, NUM,REDRAWVIEW3D,"PPost:",250,85,80,20, &arm->pathac, 1.0, MAXFRAMEF/2, 0, 0, "The number of frames after current frame for Bone Path display range"); - } - else { - uiDefButI(block, NUM,REDRAWVIEW3D,"PSta:",170,85,80,20, &arm->pathsf, 1.0, MAXFRAMEF, 0, 0, "The start frame for Bone Path display range"); - uiDefButI(block, NUM,REDRAWVIEW3D,"PEnd:",250,85,80,20, &arm->pathef, arm->pathsf, MAXFRAMEF, 0, 0, "The end frame for Bone Path display range"); - } - uiDefButBitS(block, TOG, ARM_PATH_HEADS, REDRAWVIEW3D, "Bone-Head Path", 170, 65, 160, 20, &arm->pathflag, 0, 0, 0, 0, "Calculate the Path travelled by the Bone's Head instead of Tail"); + uiDefButBitS(block, TOG, ARM_PATH_ACFRA, REDRAWVIEW3D, "Around Current Frame", 170, 110, 160, 20, &arm->pathflag, 0, 0, 0, 0, "Only show Bone Path around the current frame"); + + /* only show extra ranges when needed */ + if (arm->pathflag & ARM_PATH_ACFRA) { + uiDefButI(block, NUM, REDRAWVIEW3D,"PPre:",170,90,80,20, &arm->pathbc, 1.0, MAXFRAMEF/2, 0, 0, "The number of frames before current frame for Bone Path display range"); + uiDefButI(block, NUM, REDRAWVIEW3D,"PPost:",250,90,80,20, &arm->pathac, 1.0, MAXFRAMEF/2, 0, 0, "The number of frames after current frame for Bone Path display range"); + } + uiBlockEndAlign(block); + + /* Bone Path Calculation Options */ + uiDefBut(block, LABEL, 0, "Bone Paths Calc.", 10,50,170,20, 0, 0, 0, 0, 0, ""); + + uiBlockBeginAlign(block); + uiDefBut(block, BUT, B_ARM_CALCPATHS, "Calculate Paths", 10,30,155,20, 0, 0, 0, 0, 0, "(Re)calculates the paths of the selected bones"); + uiDefBut(block, BUT, B_ARM_CLEARPATHS, "Clear Paths", 10,10,155,20, 0, 0, 0, 0, 0, "Clears bone paths of the selected bones"); uiBlockEndAlign(block); uiBlockBeginAlign(block); - uiDefBut(block, BUT, B_ARM_CALCPATHS, "Calculate Paths", 170,30,160,20, 0, 0, 0, 0, 0, "(Re)calculates the paths of the selected bones"); - uiDefBut(block, BUT, B_ARM_CLEARPATHS, "Clear All Paths", 170,10,160,20, 0, 0, 0, 0, 0, "Clears all bone paths"); + uiDefButBitS(block, TOG, ARM_PATH_HEADS, REDRAWVIEW3D, "Bone-Head Path", 170, 30, 160, 20, &arm->pathflag, 0, 0, 0, 0, "Calculate the Path travelled by the Bone's Head instead of Tail"); + uiDefButI(block, NUM,REDRAWVIEW3D,"PSta:",170,10,80,20, &arm->pathsf, 1.0, MAXFRAMEF, 0, 0, "The start frame for Bone Path display range"); + uiDefButI(block, NUM,REDRAWVIEW3D,"PEnd:",250,10,80,20, &arm->pathef, arm->pathsf, MAXFRAMEF, 0, 0, "The end frame for Bone Path display range"); uiBlockEndAlign(block); } @@ -4624,6 +4639,9 @@ void do_meshbuts(unsigned short event) case B_JOINTRIA: join_triangles(); break; + case B_GEN_SKELETON: + generateSkeleton(); + break; } /* WATCH IT: previous events only in editmode! */ @@ -4674,6 +4692,7 @@ static void editing_panel_mesh_tools(Object *ob, Mesh *me) uiDefButS(block, NUM, B_DIFF, "Turns:", 210,55,115,19, &G.scene->toolsettings->turn,1.0,360.0, 0, 0, "Specifies the number of revolutions the screw turns"); uiDefButBitS(block, TOG, B_KEEPORIG, B_DIFF, "Keep Original",10,35,200,19, &G.scene->toolsettings->editbutflag, 0, 0, 0, 0, "Keeps a copy of the original vertices and faces after executing tools"); uiDefButBitS(block, TOG, B_CLOCKWISE, B_DIFF, "Clockwise", 210,35,115,19, &G.scene->toolsettings->editbutflag, 0, 0, 0, 0, "Specifies the direction for 'Screw' and 'Spin'"); + uiBlockEndAlign(block); uiBlockBeginAlign(block); uiDefBut(block, BUT,B_EXTREP, "Extrude Dup", 10,10,150,19, 0, 0, 0, 0, 0, "Creates copies of the selected vertices in a straight line away from the current viewport"); @@ -4697,7 +4716,81 @@ static void verify_vertexgroup_name_func(void *datav, void *data2_unused) unique_vertexgroup_name((bDeformGroup*)datav, OBACT); } +static void skgen_reorder(void *option, void *arg2) +{ + char tmp; + switch ((int)option) + { + case 0: + tmp = G.scene->toolsettings->skgen_subdivisions[0]; + G.scene->toolsettings->skgen_subdivisions[0] = G.scene->toolsettings->skgen_subdivisions[1]; + G.scene->toolsettings->skgen_subdivisions[1] = tmp; + break; + case 1: + tmp = G.scene->toolsettings->skgen_subdivisions[2]; + G.scene->toolsettings->skgen_subdivisions[2] = G.scene->toolsettings->skgen_subdivisions[1]; + G.scene->toolsettings->skgen_subdivisions[1] = tmp; + break; + case 2: + tmp = G.scene->toolsettings->skgen_subdivisions[0]; + G.scene->toolsettings->skgen_subdivisions[0] = G.scene->toolsettings->skgen_subdivisions[2]; + G.scene->toolsettings->skgen_subdivisions[2] = G.scene->toolsettings->skgen_subdivisions[1]; + G.scene->toolsettings->skgen_subdivisions[1] = tmp; + break; + } +} + +static void editing_panel_mesh_skgen(Object *ob, Mesh *me) +{ + uiBlock *block; + uiBut *but; + int i; + + block= uiNewBlock(&curarea->uiblocks, "editing_panel_mesh_skgen", UI_EMBOSS, UI_HELV, curarea->win); + if(uiNewPanel(curarea, block, "Skeleton Generator", "Editing", 960, 0, 318, 204)==0) return; + + uiDefBut(block, BUT, B_GEN_SKELETON, "Generate Skeleton", 1025,170,250,19, 0, 0, 0, 0, 0, "Generate Skeleton from Mesh"); + uiBlockBeginAlign(block); + uiDefButS(block, NUM, B_DIFF, "Resolution:", 1025,150,250,19, &G.scene->toolsettings->skgen_resolution,10.0,1000.0, 0, 0, "Specifies the resolution of the graph's embedding"); + uiDefButBitS(block, TOG, SKGEN_FILTER_INTERNAL, B_DIFF, "Filter In", 1025,130, 83,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Filter internal small arcs from graph"); + uiDefButF(block, NUM, B_DIFF, "T:", 1111,130,164,19, &G.scene->toolsettings->skgen_threshold_internal,0.0, 1.0, 10, 0, "Specify the threshold ratio for filtering internal arcs"); + uiDefButBitS(block, TOG, SKGEN_FILTER_EXTERNAL, B_DIFF, "Filter Ex", 1025,110, 83,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Filter external small arcs from graph"); + uiDefButF(block, NUM, B_DIFF, "T:", 1111,110,164,19, &G.scene->toolsettings->skgen_threshold_external,0.0, 1.0, 10, 0, "Specify the threshold ratio for filtering external arcs"); + + for(i = 0; i < SKGEN_SUB_TOTAL; i++) + { + int y = 90 - 20 * i; + + but = uiDefIconBut(block, BUT, B_MODIFIER_RECALC, VICON_MOVE_DOWN, 1025, y, 16, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Change the order the subdivisions algorithm are applied"); + uiButSetFunc(but, skgen_reorder, (void *)i, NULL); + + switch(G.scene->toolsettings->skgen_subdivisions[i]) + { + case SKGEN_SUB_LENGTH: + uiDefButBitS(block, TOG, SKGEN_CUT_LENGTH, B_DIFF, "Length", 1041, y, 67,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Subdivide arcs in bones of equal length"); + uiDefButF(block, NUM, B_DIFF, "T:", 1111, y, 82,19, &G.scene->toolsettings->skgen_length_ratio,1.0, 4.0, 10, 0, "Specify the ratio limit between straight arc and embeddings to trigger equal subdivisions"); + uiDefButF(block, NUM, B_DIFF, "L:", 1193, y, 82,19, &G.scene->toolsettings->skgen_length_limit,0.1,50.0, 10, 0, "Maximum length of the bones when subdividing"); + break; + case SKGEN_SUB_ANGLE: + uiDefButBitS(block, TOG, SKGEN_CUT_ANGLE, B_DIFF, "Angle", 1041, y, 67,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Subdivide arcs based on angle"); + uiDefButF(block, NUM, B_DIFF, "T:", 1111, y,164,19, &G.scene->toolsettings->skgen_angle_limit,0.0, 90.0, 10, 0, "Specify the threshold angle in degrees for subdivision"); + break; + case SKGEN_SUB_CORRELATION: + uiDefButBitS(block, TOG, SKGEN_CUT_CORRELATION, B_DIFF, "Correlation", 1041, y, 67,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Subdivide arcs based on correlation"); + uiDefButF(block, NUM, B_DIFF, "T:", 1111, y,164,19, &G.scene->toolsettings->skgen_correlation_limit,0.0, 1.0, 0.01, 0, "Specify the threshold correlation for subdivision"); + break; + } + } + + uiDefButBitS(block, TOG, SKGEN_SYMMETRY, B_DIFF, "Symmetry", 1025, 30,125,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Restore symmetries based on topology"); + uiDefButF(block, NUM, B_DIFF, "T:", 1150, 30,125,19, &G.scene->toolsettings->skgen_symmetry_limit,0.0, 1.0, 10, 0, "Specify the threshold distance for considering potential symmetric arcs"); + uiDefButC(block, NUM, B_DIFF, "P:", 1025, 10, 62,19, &G.scene->toolsettings->skgen_postpro_passes, 0, 10, 10, 0, "Specify the number of processing passes on the embeddings"); + uiDefButC(block, ROW, B_DIFF, "Smooth", 1087, 10, 63,19, &G.scene->toolsettings->skgen_postpro, 5.0, (float)SKGEN_SMOOTH, 0, 0, "Smooth embeddings"); + uiDefButC(block, ROW, B_DIFF, "Average", 1150, 10, 62,19, &G.scene->toolsettings->skgen_postpro, 5.0, (float)SKGEN_AVERAGE, 0, 0, "Average embeddings"); + uiDefButC(block, ROW, B_DIFF, "Sharpen", 1212, 10, 63,19, &G.scene->toolsettings->skgen_postpro, 5.0, (float)SKGEN_SHARPEN, 0, 0, "Sharpen embeddings"); + uiBlockEndAlign(block); +} static void editing_panel_mesh_tools1(Object *ob, Mesh *me) { @@ -4749,7 +4842,7 @@ char *get_vertexgroup_menustr(Object *ob) { bDeformGroup *dg; int defCount, min, index; - char (*qsort_ptr)[sizeof(dg->name)+5] = NULL; // +5 for "%x99|" + char (*qsort_ptr)[sizeof(dg->name)+6] = NULL; // +6 for "%x999|" max 999 groups selectable char *s, *menustr; int printed; @@ -4767,7 +4860,7 @@ char *get_vertexgroup_menustr(Object *ob) "qsort_ptr"); for (index = 1, dg = ob->defbase.first; dg; index++, dg=dg->next) { printed = snprintf (qsort_ptr[index - 1], sizeof (dg->name), dg->name); - snprintf (qsort_ptr[index - 1]+printed, 5+1, "%%x%d|", index); // +1 to move the \0 + snprintf (qsort_ptr[index - 1]+printed, 6+1, "%%x%d|", index); // +1 to move the \0 see above 999 max here too } qsort (qsort_ptr, defCount, sizeof (qsort_ptr[0]), @@ -5954,6 +6047,8 @@ void editing_panels() if(G.obedit) { editing_panel_mesh_tools(ob, ob->data); editing_panel_mesh_tools1(ob, ob->data); + uiNewPanelTabbed("Mesh Tools 1", "Editing"); + editing_panel_mesh_skgen(ob, ob->data); editing_panel_mesh_uvautocalculation(); if (EM_texFaceCheck()) editing_panel_mesh_texface(); diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 3360dab61f8..fcb05c8f00e 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -462,7 +462,6 @@ static void draw_constraint_spaceselect (uiBlock *block, bConstraint *con, short bwidth = 125; tarx = 120; ownx = 0; - } else if (target == -1) { bwidth = 125; @@ -531,7 +530,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s uiBlockSetEmboss(block, UI_EMBOSSN); /* rounded header */ - rb_col= (con->flag & CONSTRAINT_ACTIVE)?40:20; + rb_col= (con->flag & CONSTRAINT_ACTIVE)?50:20; uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-1, width+40, 22, NULL, 5.0, 0.0, (con->flag & CONSTRAINT_EXPAND)?3:15 , rb_col-20, ""); @@ -1088,8 +1087,8 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s } uiBlockEndAlign(block); - uiDefButBitI(block, TOG, 0, B_CONSTRAINT_TEST, "Sticky", *xco, *yco-24, 44, 18, &data->flag, 0, 24, 0, 0, "Immobilize object while constrained"); - uiDefButBitI(block, TOG, 2, B_CONSTRAINT_TEST, "Use Rot", *xco+44, *yco-24, 64, 18, &data->flag, 0, 24, 0, 0, "Use target object rotation"); + uiDefButBitI(block, TOG, MINMAX_STICKY, B_CONSTRAINT_TEST, "Sticky", *xco, *yco-24, 44, 18, &data->flag, 0, 24, 0, 0, "Immobilize object while constrained"); + uiDefButBitI(block, TOG, MINMAX_USEROT, B_CONSTRAINT_TEST, "Use Rot", *xco+44, *yco-24, 64, 18, &data->flag, 0, 24, 0, 0, "Use target object rotation"); uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Max/Min:", *xco-8, *yco-64, 54, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); @@ -1253,7 +1252,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s int togButWidth = 50; int textButWidth = ((width/2)-togButWidth); - height = 106; + height = 136; uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); /* Draw Pairs of LimitToggle+LimitValue */ @@ -1287,8 +1286,11 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+(width-textButWidth-5), *yco-72, (textButWidth-5), 18, &(data->zmax), -1000, 1000, 0.1,0.5,"Highest z value to allow"); uiBlockEndAlign(block); + /* special option(s) */ + uiDefButBitS(block, TOG, LIMIT_TRANSFORM, B_CONSTRAINT_TEST, "For Transform", *xco+(width/4), *yco-100, (width/2), 18, &data->flag2, 0, 24, 0, 0, "Transforms are affected by this constraint as well"); + /* constraint space settings */ - draw_constraint_spaceselect(block, con, *xco, *yco-100, is_armature_owner(ob), -1); + draw_constraint_spaceselect(block, con, *xco, *yco-130, is_armature_owner(ob), -1); } break; case CONSTRAINT_TYPE_ROTLIMIT: @@ -2419,15 +2421,17 @@ static void object_panel_anim(Object *ob) uiDefButBitS(block, TOG, OB_DUPLIVERTS, B_DUPLI_VERTS, "DupliVerts", 119,130,95,20, &ob->transflag, 0, 0, 0, 0, "Duplicate child objects on all vertices"); uiDefButBitS(block, TOG, OB_DUPLIFACES, B_DUPLI_FACES, "DupliFaces", 214,130,102,20, &ob->transflag, 0, 0, 0, 0, "Duplicate child objects on all faces"); uiDefButBitS(block, TOG, OB_DUPLIGROUP, B_DUPLI_GROUP, "DupliGroup", 24,110,150,20, &ob->transflag, 0, 0, 0, 0, "Enable group instancing"); - if(ob->transflag & OB_DUPLIFRAMES) + if(ob->transflag & OB_DUPLIFRAMES) { uiDefButBitS(block, TOG, OB_DUPLINOSPEED, REDRAWVIEW3D, "No Speed", 174,110,142,20, &ob->transflag, 0, 0, 0, 0, "Set dupliframes to still, regardless of frame"); - else if(ob->transflag & OB_DUPLIVERTS) + } else if(ob->transflag & OB_DUPLIVERTS) { uiDefButBitS(block, TOG, OB_DUPLIROT, REDRAWVIEW3D, "Rot", 174,110,142,20, &ob->transflag, 0, 0, 0, 0, "Rotate dupli according to vertex normal"); - else if(ob->transflag & OB_DUPLIFACES) - uiDefButBitS(block, TOG, OB_DUPLIFACES_SCALE, REDRAWVIEW3D, "Scale", 174,110,142,20, &ob->transflag, 0, 0, 0, 0, "Scale dupli based on face size"); - else + } else if(ob->transflag & OB_DUPLIFACES) { + uiDefButBitS(block, TOG, OB_DUPLIFACES_SCALE, REDRAWVIEW3D, "Scale", 174,110,80,20, &ob->transflag, 0, 0, 0, 0, "Scale dupli based on face size"); + uiDefButF(block, NUM, REDRAWVIEW3D, "", 254,110,62,20, &ob->dupfacesca, 0.001, 10000.0, 0, 0, "Scale the DupliFace objects"); + } else { uiDefIDPoinBut(block, test_grouppoin_but, ID_GR, B_GROUP_RELINK, "GR:", 174,110,142,20, &ob->dup_group, "Instance an existing group"); - + } + uiBlockBeginAlign(block); /* DupSta and DupEnd are both shorts, so the maxframe is greater then their range just limit the buttons to the max short */ @@ -2852,6 +2856,23 @@ void do_effects_panels(unsigned short event) allqueue(REDRAWOOPS, 0); } break; + case B_PART_ENABLE: + if(psys) { + ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys); + if(psys->flag & PSYS_ENABLED) { + psmd->modifier.mode |= eModifierMode_Realtime; + } + else { + psmd->modifier.mode &= ~eModifierMode_Realtime; + PE_free_particle_edit(psys); + } + + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSOBJECT, 0); + allqueue(REDRAWBUTSEDIT, 0); + } + break; case B_PART_RECALC: case B_PART_RECALC_CHILD: if(psys){ @@ -3651,8 +3672,7 @@ static void object_panel_particle_children(Object *ob) uiNewPanelTabbed("Extras", "Particle"); if(uiNewPanel(curarea, block, "Children", "Particle", 1300, 0, 318, 204)==0) return; - uiDefButS(block, MENU, B_PART_ALLOC_CHILD, "Children from:%t|Faces%x2|Particles%x1|None%x0", butx,buty,butw/2,buth, &part->childtype, 14.0, 0.0, 0, 0, "Create child particles"); - uiDefButBitI(block, TOG, PART_CHILD_RENDER, B_PART_RECALC_CHILD, "Only Render", butx+butw/2,buty,butw/2,buth, &part->flag, 0, 0, 0, 0, "Create child particles only when rendering"); + uiDefButS(block, MENU, B_PART_ALLOC_CHILD, "Children from:%t|Faces%x2|Particles%x1|None%x0", butx,buty,butw,buth, &part->childtype, 14.0, 0.0, 0, 0, "Create child particles"); if(part->childtype==0) return; @@ -3663,26 +3683,32 @@ static void object_panel_particle_children(Object *ob) } uiBlockBeginAlign(block); + + buty -= buth/2; + uiDefButI(block, NUM, B_PART_ALLOC_CHILD, "Amount:", butx,(buty-=buth),butw,buth, &part->child_nbr, 0.0, MAX_PART_CHILDREN, 0, 0, "Amount of children/parent"); + uiDefButI(block, NUM, B_DIFF, "Render Amount:", butx,(buty-=buth),butw,buth, &part->ren_child_nbr, 0.0, MAX_PART_CHILDREN, 0, 0, "Amount of children/parent for rendering"); if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES) { - uiDefButI(block, NUM, B_PART_ALLOC_CHILD, "Amount:", butx,(buty-=2*buth),butw,buth, &part->child_nbr, 0.0, MAX_PART_CHILDREN, 0, 0, "Amount of children/parent"); uiDefButF(block, NUMSLI, B_PART_DISTR_CHILD, "VParents:", butx,(buty-=buth),butw,buth, &part->parents, 0.0, 1.0, 1, 3, "Relative amount of virtual parents"); } else { - uiDefButI(block, NUM, B_PART_ALLOC_CHILD, "Amount:", butx,(buty-=2*buth),butw,buth, &part->child_nbr, 0.0, MAX_PART_CHILDREN, 0, 0, "Amount of children/parent"); uiDefButF(block, NUM, B_PART_RECALC_CHILD, "Rad:", butx,(buty-=buth),butw,buth, &part->childrad, 0.0, 10.0, 1, 3, "Radius of children around parent"); uiDefButF(block, NUMSLI, B_PART_RECALC_CHILD, "Round:", butx,(buty-=buth),butw,buth, &part->childflat, 0.0, 1.0, 1, 3, "Roundness of children around parent"); } uiBlockEndAlign(block); + buty -= buth/2; + /* clump */ uiBlockBeginAlign(block); uiDefButF(block, NUMSLI, B_PART_RECALC_CHILD, "Clump:", butx,(buty-=buth),butw,buth, &part->clumpfac, -1.0, 1.0, 1, 3, "Amount of clumpimg"); uiDefButF(block, NUMSLI, B_PART_RECALC_CHILD, "Shape:", butx,(buty-=buth),butw,buth, &part->clumppow, -0.999, 0.999, 1, 3, "Shape of clumpimg"); uiBlockEndAlign(block); + buty -= buth/2; + uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_PART_REDRAW, "Size:", butx,(buty-=2*buth),butw/2,buth, &part->childsize, 0.01, 100, 10, 1, "A multiplier for the child particle size"); + uiDefButF(block, NUM, B_PART_REDRAW, "Size:", butx,(buty-=buth),butw/2,buth, &part->childsize, 0.01, 100, 10, 1, "A multiplier for the child particle size"); uiDefButF(block, NUM, B_PART_REDRAW, "Rand:", butx+butw/2,buty,butw/2,buth, &part->childrandsize, 0.0, 1.0, 10, 1, "Random variation to the size of the child particles"); if(part->childtype==PART_CHILD_FACES) { uiDefButF(block, NUM, B_PART_REDRAW, "Spread:",butx,(buty-=buth),butw/2,buth, &part->childspread, -1.0, 1.0, 10, 1, "Spread children from the faces"); @@ -3693,10 +3719,11 @@ static void object_panel_particle_children(Object *ob) butx=160; buty=180; - uiDefButBitS(block, TOG, 1, B_PART_REDRAW, "Kink/Branch", butx,(buty-=buth),butw,buth, &kink_ui, 0, 0, 0, 0, "Show kink and branch options"); if(kink_ui) { + buty -= buth/2; + /* kink */ uiBlockBeginAlign(block); if(part->kink) { @@ -3725,15 +3752,19 @@ static void object_panel_particle_children(Object *ob) } else { /* rough */ + buty -= buth/2; + uiBlockBeginAlign(block); - uiDefButF(block, NUMSLI, B_PART_RECALC_CHILD, "Rough1:", butx,(buty-=2*buth),butw,buth, &part->rough1, 0.0, 10.0, 1, 3, "Amount of location dependant rough"); + uiDefButF(block, NUMSLI, B_PART_RECALC_CHILD, "Rough1:", butx,(buty-=buth),butw,buth, &part->rough1, 0.0, 10.0, 1, 3, "Amount of location dependant rough"); uiDefButF(block, NUM, B_PART_RECALC_CHILD, "Size1:", butx,(buty-=buth),butw,buth, &part->rough1_size, 0.01, 10.0, 1, 3, "Size of location dependant rough"); uiBlockEndAlign(block); + buty -= buth/2; uiBlockBeginAlign(block); uiDefButF(block, NUMSLI, B_PART_RECALC_CHILD, "Rough2:", butx,(buty-=buth),butw,buth, &part->rough2, 0.0, 10.0, 1, 3, "Amount of random rough"); uiDefButF(block, NUM, B_PART_RECALC_CHILD, "Size2:", butx,(buty-=buth),butw,buth, &part->rough2_size, 0.01, 10.0, 1, 3, "Size of random rough"); uiDefButF(block, NUMSLI, B_PART_RECALC_CHILD, "Thresh:", butx,(buty-=buth),butw,buth, &part->rough2_thres, 0.00, 1.0, 1, 3, "Amount of particles left untouched by random rough"); uiBlockEndAlign(block); + buty -= buth/2; uiBlockBeginAlign(block); uiDefButF(block, NUMSLI, B_PART_RECALC_CHILD, "RoughE:", butx,(buty-=buth),butw,buth, &part->rough_end, 0.0, 10.0, 1, 3, "Amount of end point rough"); uiDefButF(block, NUMSLI, B_PART_RECALC_CHILD, "Shape:", butx,(buty-=buth),butw,buth, &part->rough_end_shape, 0.0, 10.0, 1, 3, "Shape of end point rough"); @@ -3820,7 +3851,7 @@ static void object_panel_particle_extra(Object *ob) uiDefButS(block, MENU, B_PART_REDRAW, "Attribute%t|TanRot%x10|TanVel%x9|Size%x8|RoughE%x7|Rough2%x6|Rough1%x5|Kink%x4|Clump%x3|Length%x2|Velocity%x1|Density%x0", butx,(buty-=buth),butw-40,buth, &vgnum, 14.0, 0.0, 0, 0, "Attribute effected by vertex group"); but=uiDefButBitS(block, TOG, (1<<vgnum), B_PART_REDRAW, "Neg", butx+butw-40,buty,40,buth, &psys->vg_neg, 0, 0, 0, 0, "Negate the effect of the vertex group"); - uiButSetFunc(but, particle_set_vg, (void *)psys, (void *)(&vgnum)); + uiButSetFunc(but, particle_set_vg, (void *)ob, (void *)(&vgnum)); butx+=butw; @@ -3909,7 +3940,7 @@ static void object_panel_particle_visual(Object *ob) uiDefBut(block, LABEL, 0, "Render:", butx,(buty-=buth),butw,buth, NULL, 0.0, 0, 0, 0, ""); uiBlockBeginAlign(block); uiDefButS(block, NUM, B_PART_DISTR, "Material:", butx,(buty-=buth),butw-30,buth, &part->omat, 1.0, 16.0, 0, 0, "Specify material used for the particles"); - uiDefButBitS(block, TOG, PART_DRAW_MAT_COL, B_PART_REDRAW, "Col", butx+butw-30,buty,30,buth, &part->draw, 0, 0, 0, 0, "Draw particles using material's diffuse color"); + uiDefButBitS(block, TOG, PART_DRAW_MAT_COL, B_PART_RECALC, "Col", butx+butw-30,buty,30,buth, &part->draw, 0, 0, 0, 0, "Draw particles using material's diffuse color"); uiDefButBitS(block, TOG, PART_DRAW_EMITTER, B_PART_REDRAW, "Emitter", butx,(buty-=buth),butw/2,buth, &part->draw, 0, 0, 0, 0, "Render emitter Object also"); uiDefButBitS(block, TOG, PART_DRAW_PARENT, B_PART_REDRAW, "Parents", butx+butw/2,buty,butw/2,buth, &part->draw, 0, 0, 0, 0, "Render parent particles"); uiDefButBitI(block, TOG, PART_UNBORN, B_PART_REDRAW, "Unborn", butx,(buty-=buth),butw/2,buth, &part->flag, 0, 0, 0, 0, "Show particles before they are emitted"); @@ -3965,10 +3996,16 @@ static void object_panel_particle_visual(Object *ob) uiDefButBitI(block, TOG, PART_HAIR_BSPLINE, B_PART_RECALC, "B-Spline", butx,(buty-=buth),butw,buth, &part->flag, 0, 0, 0, 0, "Interpolate hair using B-Splines"); uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, PART_DRAW_REN_ADAPT, B_PART_REDRAW, "Adaptive render", butx,buty-=buth,butw,buth, &part->draw, 0, 0, 0, 0, "Draw steps of the particle path"); - if(part->draw & PART_DRAW_REN_ADAPT) { + uiDefButBitS(block, TOG, PART_DRAW_REN_STRAND, B_PART_REDRAW, "Strand render", butx,buty-=buth,butw,buth, &part->draw, 0, 0, 0, 0, "Use the strand primitive for rendering"); + if(part->draw & PART_DRAW_REN_STRAND) { uiDefButS(block, NUM, B_PART_REDRAW, "Angle:", butx,(buty-=buth),butw,buth, &part->adapt_angle, 0.0, 45.0, 0, 0, "How many degrees path has to curve to make another render segment"); - uiDefButS(block, NUM, B_PART_REDRAW, "Pixel:", butx,(buty-=buth),butw,buth, &part->adapt_pix, 0.0, 50.0, 0, 0, "How many pixels path has to cover to make another render segment"); + } + else { + uiDefButBitS(block, TOG, PART_DRAW_REN_ADAPT, B_PART_REDRAW, "Adaptive render", butx,buty-=buth,butw,buth, &part->draw, 0, 0, 0, 0, "Draw steps of the particle path"); + if(part->draw & PART_DRAW_REN_ADAPT) { + uiDefButS(block, NUM, B_PART_REDRAW, "Angle:", butx,(buty-=buth),butw/2,buth, &part->adapt_angle, 0.0, 45.0, 0, 0, "How many degrees path has to curve to make another render segment"); + uiDefButS(block, NUM, B_PART_REDRAW, "Pixel:", butx+butw/2,buty,(butw+1)/2,buth, &part->adapt_pix, 0.0, 50.0, 0, 0, "How many pixels path has to cover to make another render segment"); + } } } else { @@ -4137,9 +4174,9 @@ static void object_panel_particle_physics(Object *ob) butw=103; uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_PART_RECALC, "AccX:", butx,(buty-=buth),butw,buth, part->acc, -200.0, 200.0, 100, 0, "Specify a constant acceleration along the X-axis"); - uiDefButF(block, NUM, B_PART_RECALC, "AccY:", butx+butw,buty,butw,buth, part->acc+1,-200.0, 200.0, 100, 0, "Specify a constant acceleration along the Y-axis"); - uiDefButF(block, NUM, B_PART_RECALC, "AccZ:", butx+2*butw,buty,butw+1,buth, part->acc+2, -200.0, 200.0, 100, 0, "Specify a constant acceleration along the Z-axis"); + uiDefButF(block, NUM, B_PART_RECALC, "AccX:", butx,(buty-=buth),butw,buth, part->acc, -200.0, 200.0, 10, 0, "Specify a constant acceleration along the X-axis"); + uiDefButF(block, NUM, B_PART_RECALC, "AccY:", butx+butw,buty,butw,buth, part->acc+1,-200.0, 200.0, 10, 0, "Specify a constant acceleration along the Y-axis"); + uiDefButF(block, NUM, B_PART_RECALC, "AccZ:", butx+2*butw,buty,butw+1,buth, part->acc+2, -200.0, 200.0, 10, 0, "Specify a constant acceleration along the Z-axis"); uiDefButF(block, NUM, B_PART_RECALC, "Drag:", butx,(buty-=buth),butw,buth, &part->dragfac, 0.0, 1.0, 1, 0, "Specify the amount of air-drag"); uiDefButF(block, NUM, B_PART_RECALC, "Brown:", butx+butw,buty,butw,buth, &part->brownfac, 0.0, 200.0, 1, 0, "Specify the amount of brownian motion"); @@ -4230,7 +4267,7 @@ static void object_panel_particle_system(Object *ob) butx=0; buty-=5; - uiDefButBitI(block, TOG, PSYS_ENABLED, B_PART_REDRAW, "Enabled", 0,(buty-=buth),100,buth, &psys->flag, 0, 0, 0, 0, "Sets particle system to be calculated and shown"); + uiDefButBitI(block, TOG, PSYS_ENABLED, B_PART_ENABLE, "Enabled", 0,(buty-=buth),100,buth, &psys->flag, 0, 0, 0, 0, "Sets particle system to be calculated and shown"); if(part->type == PART_HAIR){ if(psys->flag & PSYS_EDITED) diff --git a/source/blender/src/buttons_scene.c b/source/blender/src/buttons_scene.c index 9da6cff1387..7a4093dd965 100644 --- a/source/blender/src/buttons_scene.c +++ b/source/blender/src/buttons_scene.c @@ -1967,11 +1967,12 @@ static void render_panel_layers(void) uiBlockBeginAlign(block); uiDefButBitI(block, TOG, SCE_LAY_ALL_Z, B_NOP,"AllZ", 10, 85, 40, 20, &srl->layflag, 0, 0, 0, 0, "Fill in Z values for all not-rendered faces, for masking"); uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, SCE_LAY_SOLID, B_NOP,"Solid", 50, 85, 60, 20, &srl->layflag, 0, 0, 0, 0, "Render Solid faces in this Layer"); - uiDefButBitI(block, TOG, SCE_LAY_HALO, B_NOP,"Halo", 110, 85, 55, 20, &srl->layflag, 0, 0, 0, 0, "Render Halos in this Layer (on top of Solid)"); - uiDefButBitI(block, TOG, SCE_LAY_ZTRA, B_NOP,"Ztra", 165, 85, 55, 20, &srl->layflag, 0, 0, 0, 0, "Render Z-Transparent faces in this Layer (On top of Solid and Halos)"); - uiDefButBitI(block, TOG, SCE_LAY_SKY, B_NOP,"Sky", 220, 85, 40, 20, &srl->layflag, 0, 0, 0, 0, "Render Sky or backbuffer in this Layer"); - uiDefButBitI(block, TOG, SCE_LAY_EDGE, B_NOP,"Edge", 260, 85, 50, 20, &srl->layflag, 0, 0, 0, 0, "Render Edge-enhance in this Layer (only works for Solid faces)"); + uiDefButBitI(block, TOG, SCE_LAY_SOLID, B_NOP,"Solid", 50, 85, 45, 20, &srl->layflag, 0, 0, 0, 0, "Render Solid faces in this Layer"); + uiDefButBitI(block, TOG, SCE_LAY_HALO, B_NOP,"Halo", 95, 85, 40, 20, &srl->layflag, 0, 0, 0, 0, "Render Halos in this Layer (on top of Solid)"); + uiDefButBitI(block, TOG, SCE_LAY_ZTRA, B_NOP,"Ztra", 135, 85, 40, 20, &srl->layflag, 0, 0, 0, 0, "Render Z-Transparent faces in this Layer (On top of Solid and Halos)"); + uiDefButBitI(block, TOG, SCE_LAY_SKY, B_NOP,"Sky", 175, 85, 40, 20, &srl->layflag, 0, 0, 0, 0, "Render Sky or backbuffer in this Layer"); + uiDefButBitI(block, TOG, SCE_LAY_EDGE, B_NOP,"Edge", 215, 85, 45, 20, &srl->layflag, 0, 0, 0, 0, "Render Edge-enhance in this Layer (only works for Solid faces)"); + uiDefButBitI(block, TOG, SCE_LAY_STRAND, B_NOP,"Strand",260, 85, 50, 20, &srl->layflag, 0, 0, 0, 0, "Render Strands in this Layer"); uiDefIDPoinBut(block, test_grouppoin_but, ID_GR, B_SET_PASS, "Light:", 10, 65, 150, 20, &(srl->light_override), "Name of Group to use as Lamps instead"); uiDefIDPoinBut(block, test_matpoin_but, ID_MA, B_SET_PASS, "Mat:", 160, 65, 150, 20, &(srl->mat_override), "Name of Material to use as Materials instead"); diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c index f21272f53da..dafd156524f 100644 --- a/source/blender/src/buttons_shading.c +++ b/source/blender/src/buttons_shading.c @@ -1171,14 +1171,13 @@ void uiblock_image_panel(uiBlock *block, Image **ima_pp, ImageUser *iuser, /* fields */ uiBlockBeginAlign(block); - but= uiDefButBitS(block, TOG, IMA_FIELDS, imagechanged, "Fields", 10, 90, 100, 20, &ima->flag, 0, 0, 0, 0, "Click to enable use of fields in Image"); + but= uiDefButBitS(block, TOG, IMA_FIELDS, imagechanged, "Fields", 10, 90, 65, 20, &ima->flag, 0, 0, 0, 0, "Click to enable use of fields in Image"); uiButSetFunc(but, image_field_test, ima, iuser); - uiDefButBitS(block, TOG, IMA_STD_FIELD, B_NOP, "Odd", 10, 70, 100, 20, &ima->flag, 0, 0, 0, 0, "Standard Field Toggle"); + uiDefButBitS(block, TOG, IMA_STD_FIELD, B_NOP, "Odd", 75, 90, 45, 20, &ima->flag, 0, 0, 0, 0, "Standard Field Toggle"); - uiBlockBeginAlign(block); uiBlockSetFunc(block, image_reload_cb, ima, iuser); - uiDefButBitS(block, TOG, IMA_ANTIALI, B_NOP, "Anti", 10, 35, 100, 20, &ima->flag, 0, 0, 0, 0, "Toggles Image anti-aliasing, only works with solid colors"); - uiDefButBitS(block, TOG, IMA_DO_PREMUL, imagechanged, "Premul", 110, 35, 100, 20, &ima->flag, 0, 0, 0, 0, "Toggles premultiplying alpha"); + uiDefButBitS(block, TOG, IMA_ANTIALI, B_NOP, "Anti", 10, 70, 45, 20, &ima->flag, 0, 0, 0, 0, "Toggles Image anti-aliasing, only works with solid colors"); + uiDefButBitS(block, TOG, IMA_DO_PREMUL, imagechanged, "Premul", 55, 70, 65, 20, &ima->flag, 0, 0, 0, 0, "Toggles premultiplying alpha"); uiBlockEndAlign(block); if( ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) { @@ -1975,7 +1974,7 @@ static void world_panel_mapto(World *wrld) uiDefButF(block, NUMSLI, B_WORLDPRV, "G ", 10,60,135,19, &(mtex->g), 0.0, 1.0, B_MTEXCOL, 0, "The default color for textures that don't return RGB"); uiDefButF(block, NUMSLI, B_WORLDPRV, "B ", 10,40,135,19, &(mtex->b), 0.0, 1.0, B_MTEXCOL, 0, "The default color for textures that don't return RGB"); uiBlockEndAlign(block); - uiDefButF(block, NUMSLI, B_WORLDPRV, "DVar ", 10,10,135,19, &(mtex->def_var), 0.0, 1.0, 0, 0, "The default value for textures to mix with values (not RGB)"); + uiDefButF(block, NUMSLI, B_WORLDPRV, "DVar ", 10,10,135,19, &(mtex->def_var), 0.0, 1.0, 0, 0, "Value to use for Ref, Spec, Amb, Emit, Alpha, RayMir, TransLu and Hard"); /* MAP TO */ uiBlockBeginAlign(block); @@ -2234,20 +2233,20 @@ static void world_panel_world(World *wrld) uiSetButLock(wrld->id.lib!=0, ERROR_LIBDATA_MESSAGE); uiBlockSetCol(block, TH_AUTO); - uiDefButF(block, COL, B_WORLDPRV, "", 10,150,145,19, &wrld->horr, 0, 0, 0, B_COLHOR, ""); - uiDefButF(block, COL, B_WORLDPRV, "", 160,150,145,19, &wrld->zenr, 0, 0, 0, B_COLZEN, ""); - uiBlockBeginAlign(block); + uiDefButF(block, COL, B_WORLDPRV, "", 10,150,145,19, &wrld->horr, 0, 0, 0, B_COLHOR, ""); uiDefButF(block, NUMSLI,B_WORLDPRV,"HoR ", 10,130,145,19, &(wrld->horr), 0.0, 1.0, B_COLHOR,0, "Sets the amount of red color at the horizon"); uiDefButF(block, NUMSLI,B_WORLDPRV,"HoG ", 10,110,145,19, &(wrld->horg), 0.0, 1.0, B_COLHOR,0, "Sets the amount of green color at the horizon"); uiDefButF(block, NUMSLI,B_WORLDPRV,"HoB ", 10,90,145,19, &(wrld->horb), 0.0, 1.0, B_COLHOR,0, "Sets the amount of blue color at the horizon"); uiBlockBeginAlign(block); + uiDefButF(block, COL, B_WORLDPRV, "", 160,150,145,19, &wrld->zenr, 0, 0, 0, B_COLZEN, ""); uiDefButF(block, NUMSLI,B_WORLDPRV,"ZeR ", 160,130,145,19, &(wrld->zenr), 0.0, 1.0, B_COLZEN,0, "Sets the amount of red color at the zenith"); uiDefButF(block, NUMSLI,B_WORLDPRV,"ZeG ", 160,110,145,19, &(wrld->zeng), 0.0, 1.0, B_COLZEN,0, "Sets the amount of green color at the zenith"); uiDefButF(block, NUMSLI,B_WORLDPRV,"ZeB ", 160,90,145,19, &(wrld->zenb), 0.0, 1.0, B_COLZEN,0, "Sets the amount of blue color at the zenith"); uiBlockBeginAlign(block); + uiDefButF(block, COL, B_WORLDPRV, "", 10,70,145,19, &wrld->ambr, 0, 0, 0, 0, ""); uiDefButF(block, NUMSLI,B_WORLDPRV,"AmbR ", 10,50,145,19, &(wrld->ambr), 0.0, 1.0 ,0,0, "Sets the amount of red ambient color"); uiDefButF(block, NUMSLI,B_WORLDPRV,"AmbG ", 10,30,145,19, &(wrld->ambg), 0.0, 1.0 ,0,0, "Sets the amount of green ambient color"); uiDefButF(block, NUMSLI,B_WORLDPRV,"AmbB ", 10,10,145,19, &(wrld->ambb), 0.0, 1.0 ,0,0, "Sets the amount of blue ambient color"); @@ -2406,7 +2405,7 @@ static void lamp_panel_mapto(Object *ob, Lamp *la) uiDefButF(block, NUMSLI, B_LAMPPRV, "G ", 10,60,135,19, &(mtex->g), 0.0, 1.0, B_MTEXCOL, 0, "The default color for textures that don't return RGB"); uiDefButF(block, NUMSLI, B_LAMPPRV, "B ", 10,40,135,19, &(mtex->b), 0.0, 1.0, B_MTEXCOL, 0, "The default color for textures that don't return RGB"); uiBlockEndAlign(block); - uiDefButF(block, NUMSLI, B_LAMPPRV, "DVar ", 10,10,135,19, &(mtex->def_var), 0.0, 1.0, 0, 0, "The default value the textures uses to mix with"); + uiDefButF(block, NUMSLI, B_LAMPPRV, "DVar ", 10,10,135,19, &(mtex->def_var), 0.0, 1.0, 0, 0, "Value to use for Ref, Spec, Amb, Emit, Alpha, RayMir, TransLu and Hard"); /* MAP TO */ uiDefButBitS(block, TOG, MAP_COL, B_LAMPPRV, "Col", 10,180,135,19, &(mtex->mapto), 0, 0, 0, 0, "Lets the texture affect the basic color of the lamp"); @@ -3147,7 +3146,7 @@ static void material_panel_map_to(Object *ob, Material *ma, int from_nodes) } uiBlockEndAlign(block); - uiDefButF(block, NUMSLI, B_MATPRV, "DVar ", 10,10,135,19, &(mtex->def_var), 0.0, 1.0, 0, 0, "The default value the texture uses to mix with (not RGB)"); + uiDefButF(block, NUMSLI, B_MATPRV, "DVar ", 10,10,135,19, &(mtex->def_var), 0.0, 1.0, 0, 0, "Value to use for Ref, Spec, Amb, Emit, Alpha, RayMir, TransLu and Hard"); /* MAP TO */ uiBlockBeginAlign(block); @@ -3165,7 +3164,7 @@ static void material_panel_map_to(Object *ob, Material *ma, int from_nodes) but=uiDefButBitS(block, TOG3, MAP_PA_DENS, B_MAT_PARTICLE, "Dens", 130,180,60,19, &(mtex->pmapto), 0, 0, 0, 0, "Causes the texture to affect the density of particles"); //uiButSetFunc(but, particle_recalc_material, ma, NULL); uiDefButBitS(block, TOG3, MAP_PA_IVEL, B_MAT_PARTICLE, "IVel", 190,180,60,19, &(mtex->pmapto), 0, 0, 0, 0, "Causes the texture to affect the initial velocity of particles"); - uiDefButBitS(block, TOG3, MAP_PA_PVEL, B_MAT_PARTICLE, "PVel", 250,180,60,19, &(mtex->pmapto), 0, 0, 0, 0, "Causes the texture to affect the velocity of particles"); + uiDefButBitS(block, TOG3, MAP_PA_ROUGH, B_MAT_PARTICLE, "Rough", 250,180,60,19, &(mtex->pmapto), 0, 0, 0, 0, "Causes the texture to affect the roughness of child particles"); but=uiDefButBitS(block, TOG3, MAP_PA_SIZE, B_MAT_PARTICLE, "Size", 10,160,60,19, &(mtex->pmapto), 0, 0, 0, 0, "Causes the texture to affect the size of particles"); //uiButSetFunc(but, particle_recalc_material, ma, NULL); @@ -3853,25 +3852,30 @@ static uiBlock *strand_menu(void *mat_v) { Material *ma= mat_v; uiBlock *block; - + block= uiNewBlock(&curarea->uiblocks, "strand menu", UI_EMBOSS, UI_HELV, curarea->win); /* use this for a fake extra empy space around the buttons */ - uiDefBut(block, LABEL, 0, "", 0, 0, 250, 120, NULL, 0, 0, 0, 0, ""); - + uiDefBut(block, LABEL, 0, "", 0, 0, 250, 170, NULL, 0, 0, 0, 0, ""); + + uiBlockBeginAlign(block); + /* event return 0, to prevent menu to close */ + + uiDefButBitI(block, TOG, MA_TANGENT_STR, 0, "Use Tangent Shading", 10,140,230,20, &(ma->mode), 0, 0, 0, 0, "Uses direction of strands as normal for tangent-shading"); + uiDefButBitI(block, TOG, MA_STR_SURFDIFF, 0, "Surface Diffuse", 10,120,115,20, &(ma->mode), 0, 0, 0, 0, "Make diffuse shading more similar to shading the surface"); + uiDefButF(block, NUM, 0, "Dist", 125,120,115,20, &ma->strand_surfnor, 0.0f, 10.0f, 2, 0, "Distance in Blender units over which to blend in the surface normal"); + uiBlockBeginAlign(block); - /* event return 0, to prevent menu to close */ - uiDefButBitI(block, TOG, MA_TANGENT_STR, 0, "Use Tangent Shading", 10,90,115,20, &(ma->mode), 0, 0, 0, 0, "Uses direction of strands as normal for tangent-shading"); - uiDefButBitI(block, TOG, MA_STR_B_UNITS, 0, "Use Blender Units", 125,90,115,20, &(ma->mode), 0, 0, 0, 0, "Use actual Blender units for widths instead of pixels"); - if(ma->mode & MA_STR_B_UNITS){ - uiDefButF(block, NUMSLI, 0, "Start ", 10, 70, 230,20, &ma->strand_sta, 0.0001, 2.0, 2, 0, "Start size of strands in Blender units"); - uiDefButF(block, NUMSLI, 0, "End ", 10, 50, 230,20, &ma->strand_end, 0.0001, 1.0, 2, 0, "End size of strands in Blender units"); - } - else{ - uiDefButF(block, NUMSLI, 0, "Start ", 10, 70, 230,20, &ma->strand_sta, 0.25, 20.0, 2, 0, "Start size of strands in pixels"); - uiDefButF(block, NUMSLI, 0, "End ", 10, 50, 230,20, &ma->strand_end, 0.25, 10.0, 2, 0, "End size of strands in pixels"); - } - uiDefButF(block, NUMSLI, 0, "Shape ", 10, 30, 230,20, &ma->strand_ease, -0.9, 0.9, 2, 0, "Shape of strands, positive value makes it rounder, negative makes it spiky"); + uiDefButBitI(block, TOG, MA_STR_B_UNITS, 0, "Use Blender Units", 10,95,230,20, &(ma->mode), 0, 0, 0, 0, "Use actual Blender units for widths instead of pixels"); + if(ma->mode & MA_STR_B_UNITS){ + uiDefButF(block, NUMSLI, 0, "Start ", 10, 75, 230,20, &ma->strand_sta, 0.0001, 2.0, 2, 0, "Start size of strands in Blender units"); + uiDefButF(block, NUMSLI, 0, "End ", 10, 55, 230,20, &ma->strand_end, 0.0001, 1.0, 2, 0, "End size of strands in Blender units"); + } + else{ + uiDefButF(block, NUMSLI, 0, "Start ", 10, 75, 230,20, &ma->strand_sta, 0.25, 20.0, 2, 0, "Start size of strands in pixels"); + uiDefButF(block, NUMSLI, 0, "End ", 10, 55, 230,20, &ma->strand_end, 0.25, 10.0, 2, 0, "End size of strands in pixels"); + } + uiDefButF(block, NUMSLI, 0, "Shape ", 10, 35, 230,20, &ma->strand_ease, -0.9, 0.9, 2, 0, "Shape of strands, positive value makes it rounder, negative makes it spiky"); uiDefBut(block, TEX, B_MATPRV, "UV:", 10,10,230,20, ma->strand_uvname, 0, 31, 0, 0, "Set name of UV layer to override"); uiBlockSetDirection(block, UI_TOP); diff --git a/source/blender/src/drawaction.c b/source/blender/src/drawaction.c index 183558b65bc..3cfe3731367 100644 --- a/source/blender/src/drawaction.c +++ b/source/blender/src/drawaction.c @@ -362,7 +362,7 @@ void draw_cfra_action (void) vec[0]*= G.scene->r.framelen; vec[1]= G.v2d->cur.ymin; - glColor3ub(0x60, 0xc0, 0x40); + BIF_ThemeColor(TH_CFRAME); glLineWidth(2.0); glBegin(GL_LINE_STRIP); @@ -373,10 +373,10 @@ void draw_cfra_action (void) /* Draw dark green line if slow-parenting/time-offset is enabled */ ob= (G.scene->basact) ? (G.scene->basact->object) : 0; - if(ob && ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) { + if ((ob) && (ob->sf!=0.0) && (ob->ipoflag & OB_OFFS_OB)) { vec[0]-= ob->sf; - glColor3ub(0x10, 0x60, 0); + BIF_ThemeColorShade(TH_CFRAME, -30); glBegin(GL_LINE_STRIP); glVertex2fv(vec); diff --git a/source/blender/src/drawarmature.c b/source/blender/src/drawarmature.c index c907bab5a23..9ec688b5d8d 100644 --- a/source/blender/src/drawarmature.c +++ b/source/blender/src/drawarmature.c @@ -1211,7 +1211,7 @@ static void draw_pose_dofs(Object *ob) for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { bone= pchan->bone; - if(bone && !(bone->flag & BONE_HIDDEN_P)) { + if(bone && !(bone->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG))) { if(bone->flag & BONE_SELECTED) { if(bone->layer & arm->layer) { if(pchan->ikflag & (BONE_IK_XLIMIT|BONE_IK_ZLIMIT)) { @@ -1346,7 +1346,7 @@ static void draw_pose_channels(Base *base, int dt) for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { bone= pchan->bone; - if(bone && !(bone->flag & (BONE_HIDDEN_P|BONE_NO_DEFORM))) { + if(bone && !(bone->flag & (BONE_HIDDEN_P|BONE_NO_DEFORM|BONE_HIDDEN_PG))) { if(bone->flag & (BONE_SELECTED)) if(bone->layer & arm->layer) draw_sphere_bone_dist(smat, imat, bone->flag, pchan, NULL); @@ -1369,14 +1369,14 @@ static void draw_pose_channels(Base *base, int dt) for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { bone= pchan->bone; - if(bone && !(bone->flag & BONE_HIDDEN_P)) { + if(bone && !(bone->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG))) { if(bone->layer & arm->layer) { glPushMatrix(); glMultMatrixf(pchan->pose_mat); /* catch exception for bone with hidden parent */ flag= bone->flag; - if(bone->parent && (bone->parent->flag & BONE_HIDDEN_P)) + if(bone->parent && (bone->parent->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG))) flag &= ~BONE_CONNECTED; if(pchan->custom && !(arm->flag & ARM_NO_CUSTOM)) @@ -1395,7 +1395,7 @@ static void draw_pose_channels(Base *base, int dt) } if (index!= -1) index+= 0x10000; // pose bones count in higher 2 bytes only } - /* very very confusing... but in object mode, solid draw, we cannot do glLoadName yet, stick bones are dawn in next loop */ + /* very very confusing... but in object mode, solid draw, we cannot do glLoadName yet, stick bones are drawn in next loop */ if(arm->drawtype!=ARM_LINE) { glLoadName (index & 0xFFFF); // object tag, for bordersel optim index= -1; @@ -1418,7 +1418,7 @@ static void draw_pose_channels(Base *base, int dt) for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { bone= pchan->bone; - if(bone && !(bone->flag & BONE_HIDDEN_P)) { + if(bone && !(bone->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG))) { if(bone->layer & arm->layer) { if (do_dashed && bone->parent) { /* Draw a line from our root to the parent's tip */ @@ -1456,7 +1456,7 @@ static void draw_pose_channels(Base *base, int dt) /* catch exception for bone with hidden parent */ flag= bone->flag; - if(bone->parent && (bone->parent->flag & BONE_HIDDEN_P)) + if(bone->parent && (bone->parent->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG))) flag &= ~BONE_CONNECTED; /* extra draw service for pose mode */ @@ -1510,7 +1510,7 @@ static void draw_pose_channels(Base *base, int dt) if(G.vd->zbuf) glDisable(GL_DEPTH_TEST); for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - if((pchan->bone->flag & BONE_HIDDEN_P)==0) { + if((pchan->bone->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG))==0) { if(pchan->bone->layer & arm->layer) { if (arm->flag & (ARM_EDITMODE|ARM_POSEMODE)) { bone= pchan->bone; @@ -1727,20 +1727,26 @@ static void draw_ebones(Object *ob, int dt) } } -/* in view space */ +/* ****************************** Armature Visualisation ******************************** */ + +/* ---------- Paths --------- */ + +/* draw bone paths + * - in view space + */ static void draw_pose_paths(Object *ob) { bArmature *arm= ob->data; bPoseChannel *pchan; bAction *act; bActionChannel *achan; - CfraElem *ce; - ListBase ak; - float *fp; + ActKeyColumn *ak; + ListBase keys; + float *fp, *fp_start; int a, stepsize; - int sfra, efra; + int sfra, efra, len; - if(G.vd->zbuf) glDisable(GL_DEPTH_TEST); + if (G.vd->zbuf) glDisable(GL_DEPTH_TEST); glPushMatrix(); glLoadMatrixf(G.vd->viewmat); @@ -1759,59 +1765,105 @@ static void draw_pose_paths(Object *ob) } /* get frame ranges */ - sfra= pchan->pathsf; - efra = sfra + pchan->pathlen; - - /* draw curve-line of path */ - if ((CFRA > sfra) && (CFRA < efra)) { - /* Show before/after current frame with slight difference in colour intensity - * This is done in two loops, as there seems to be some problems with changing color - * or something during a loop (noted somewhere in the codebase) + if (arm->pathflag & ARM_PATH_ACFRA) { + int sind; + + /* With "Around Current", we only choose frames from around + * the current frame to draw. However, this range is still + * restricted by the limits of the original path. */ + sfra= CFRA - arm->pathbc; + efra= CFRA + arm->pathac; + if (sfra < pchan->pathsf) sfra= pchan->pathsf; + if (efra > pchan->pathef) efra= pchan->pathef; - /* before cfra (darker) */ - BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.2); - glBegin(GL_LINE_STRIP); - for (a=0, fp=pchan->path; (sfra+a)<=CFRA; a++, fp+=3) - glVertex3fv(fp); - glEnd(); + len= efra - sfra; - /* after cfra (lighter) - backtrack a bit so that we don't have gaps */ - BIF_ThemeColorBlend(TH_WIRE, TH_BONE_POSE, 0.7); - glBegin(GL_LINE_STRIP); - for (--a, fp-=3; a<pchan->pathlen; a++, fp+=3) - glVertex3fv(fp); - glEnd(); + sind= sfra - pchan->pathsf; + fp_start= (pchan->path + (3*sind)); } else { - /* show both directions with same intensity (cfra somewhere else) */ - BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7); - glBegin(GL_LINE_STRIP); - for (a=0, fp= pchan->path; a<pchan->pathlen; a++, fp+=3) - glVertex3fv(fp); - glEnd(); + sfra= pchan->pathsf; + efra = sfra + pchan->pathlen; + len = pchan->pathlen; + fp_start = pchan->path; + } + + /* draw curve-line of path */ + glShadeModel(GL_SMOOTH); + + glBegin(GL_LINE_STRIP); + for (a=0, fp=fp_start; a<len; a++, fp+=3) { + float intensity; /* how faint */ + + /* set colour + * - more intense for active/selected bones, less intense for unselected bones + * - black for before current frame, green for current frame, blue for after current frame + * - intensity decreases as distance from current frame increases + */ + #define SET_INTENSITY(A, B, C, min, max) (((1.0f - ((C - B) / (C - A))) * (max-min)) + min) + if ((a+sfra) < CFRA) { + /* black - before cfra */ + if (pchan->bone->flag & BONE_SELECTED) { + // intensity= 0.5; + intensity = SET_INTENSITY(sfra, a, CFRA, 0.25f, 0.75f); + } + else { + //intensity= 0.8; + intensity = SET_INTENSITY(sfra, a, CFRA, 0.68f, 0.92f); + } + BIF_ThemeColorBlend(TH_WIRE, TH_BACK, intensity); + } + else if ((a+sfra) > CFRA) { + /* blue - after cfra */ + if (pchan->bone->flag & BONE_SELECTED) { + //intensity = 0.5; + intensity = SET_INTENSITY(CFRA, a, efra, 0.25f, 0.75f); + } + else { + //intensity = 0.8; + intensity = SET_INTENSITY(CFRA, a, efra, 0.68f, 0.92f); + } + BIF_ThemeColorBlend(TH_BONE_POSE, TH_BACK, intensity); + } + else { + /* green - on cfra */ + if (pchan->bone->flag & BONE_SELECTED) { + intensity= 0.3; + } + else { + intensity= 0.8; + } + BIF_ThemeColorBlend(TH_CFRAME, TH_BACK, intensity); + } + + /* draw a vertex with this colour */ + glVertex3fv(fp); } + glEnd(); + glShadeModel(GL_FLAT); + glPointSize(1.0); /* draw little black point at each frame * NOTE: this is not really visible/noticable */ glBegin(GL_POINTS); - for(a=0, fp= pchan->path; a<pchan->pathlen; a++, fp+=3) + for (a=0, fp=fp_start; a<len; a++, fp+=3) glVertex3fv(fp); glEnd(); /* Draw little white dots at each framestep value */ BIF_ThemeColor(TH_TEXT_HI); glBegin(GL_POINTS); - for (a=0, fp= pchan->path; a<pchan->pathlen; a+=stepsize, fp+=(stepsize*3)) + for (a=0, fp=fp_start; a<len; a+=stepsize, fp+=(stepsize*3)) glVertex3fv(fp); glEnd(); /* Draw frame numbers at each framestep value */ if (arm->pathflag & ARM_PATH_FNUMS) { - for(a=0, fp= pchan->path; a<pchan->pathlen; a+=stepsize, fp+=(stepsize*3)) { + for (a=0, fp=fp_start; a<len; a+=stepsize, fp+=(stepsize*3)) { char str[32]; /* only draw framenum if several consecutive highlighted points don't occur on same point */ @@ -1820,7 +1872,7 @@ static void draw_pose_paths(Object *ob) sprintf(str, " %d\n", (a+sfra)); BMF_DrawString(G.font, str); } - else if ((a > stepsize) && (a < pchan->pathlen-stepsize)) { + else if ((a > stepsize) && (a < len-stepsize)) { if ((VecEqual(fp, fp-(stepsize*3))==0) || (VecEqual(fp, fp+(stepsize*3))==0)) { glRasterPos3fv(fp); sprintf(str, " %d\n", (a+sfra)); @@ -1833,30 +1885,34 @@ static void draw_pose_paths(Object *ob) /* Keyframes - dots and numbers */ if (arm->pathflag & ARM_PATH_KFRAS) { /* build list of all keyframes in active action for pchan */ - ak.first = ak.last = NULL; + keys.first = keys.last = NULL; act= ob_get_action(ob); if (act) { achan= get_action_channel(act, pchan->name); if (achan) - ipo_to_keylist(achan->ipo, &ak, NULL); + ipo_to_keylist(achan->ipo, &keys, NULL); } - /* Draw little yellow dots at each keyframe */ + /* Draw slightly-larger yellow dots at each keyframe */ BIF_ThemeColor(TH_VERTEX_SELECT); + glPointSize(5.0); + glBegin(GL_POINTS); - for(a=0, fp= pchan->path; a<pchan->pathlen; a++, fp+=3) { - for (ce= ak.first; ce; ce= ce->next) { - if (ce->cfra == (a+sfra)) + for (a=0, fp=fp_start; a<len; a++, fp+=3) { + for (ak= keys.first; ak; ak= ak->next) { + if (ak->cfra == (a+sfra)) glVertex3fv(fp); } } glEnd(); + glPointSize(1.0); + /* Draw frame numbers of keyframes */ - if (arm->pathflag & ARM_PATH_FNUMS) { - for(a=0, fp= pchan->path; a<pchan->pathlen; a++, fp+=3) { - for (ce= ak.first; ce; ce= ce->next) { - if (ce->cfra == (a+sfra)) { + if ((arm->pathflag & ARM_PATH_FNUMS) || (arm->pathflag & ARM_PATH_KFNOS)) { + for(a=0, fp=fp_start; a<len; a++, fp+=3) { + for (ak= keys.first; ak; ak= ak->next) { + if (ak->cfra == (a+sfra)) { char str[32]; glRasterPos3fv(fp); @@ -1867,18 +1923,51 @@ static void draw_pose_paths(Object *ob) } } - BLI_freelistN(&ak); + BLI_freelistN(&keys); } } } } - if(G.vd->zbuf) glEnable(GL_DEPTH_TEST); + if (G.vd->zbuf) glEnable(GL_DEPTH_TEST); glPopMatrix(); } + +/* ---------- Ghosts --------- */ + +/* helper function for ghost drawing - sets/removes flags for temporarily + * hiding unselected bones while drawing ghosts + */ +static void ghost_poses_tag_unselected(Object *ob, short unset) +{ + bArmature *arm= ob->data; + bPose *pose= ob->pose; + bPoseChannel *pchan; + + /* don't do anything if no hiding any bones */ + if ((arm->flag & ARM_GHOST_ONLYSEL)==0) + return; + + /* loop over all pchans, adding/removing tags as appropriate */ + for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) { + if ((pchan->bone) && (arm->layer & pchan->bone->layer)) { + if (unset) { + /* remove tags from all pchans if cleaning up */ + pchan->bone->flag &= ~BONE_HIDDEN_PG; + } + else { + /* set tags on unselected pchans only */ + if ((pchan->bone->flag & BONE_SELECTED)==0) + pchan->bone->flag |= BONE_HIDDEN_PG; + } + } + } +} + /* draw ghosts that occur within a frame range - * note: object should be in posemode */ + * note: object should be in posemode + */ static void draw_ghost_poses_range(Base *base) { Object *ob= base->object; @@ -1889,7 +1978,7 @@ static void draw_ghost_poses_range(Base *base) start = arm->ghostsf; end = arm->ghostef; - if (end<=start) + if (end <= start) return; stepsize= (float)(arm->ghostsize); @@ -1908,12 +1997,13 @@ static void draw_ghost_poses_range(Base *base) copy_pose(&posen, ob->pose, 1); ob->pose= posen; armature_rebuild_pose(ob, ob->data); /* child pointers for IK */ + ghost_poses_tag_unselected(ob, 0); /* hide unselected bones if need be */ glEnable(GL_BLEND); - if(G.vd->zbuf) glDisable(GL_DEPTH_TEST); + if (G.vd->zbuf) glDisable(GL_DEPTH_TEST); /* draw from first frame of range to last */ - for(CFRA= start; CFRA<end; CFRA+=stepsize) { + for (CFRA= start; CFRA<end; CFRA+=stepsize) { colfac = (end-CFRA)/range; BIF_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0f*sqrt(colfac))); @@ -1922,8 +2012,9 @@ static void draw_ghost_poses_range(Base *base) draw_pose_channels(base, OB_WIRE); } glDisable(GL_BLEND); - if(G.vd->zbuf) glEnable(GL_DEPTH_TEST); + if (G.vd->zbuf) glEnable(GL_DEPTH_TEST); + ghost_poses_tag_unselected(ob, 1); /* unhide unselected bones if need be */ free_pose_channels(posen); MEM_freeN(posen); @@ -1934,10 +2025,89 @@ static void draw_ghost_poses_range(Base *base) armature_rebuild_pose(ob, ob->data); ob->flag |= OB_POSEMODE; ob->ipoflag= ipoflago; +} +/* draw ghosts on keyframes in action within range + * - object should be in posemode + */ +static void draw_ghost_poses_keys(Base *base) +{ + Object *ob= base->object; + bAction *act= ob_get_action(ob); + bArmature *arm= ob->data; + bPose *posen, *poseo; + ListBase keys= {NULL, NULL}; + ActKeyColumn *ak, *akn; + float start, end, range, colfac, i; + int cfrao, flago, ipoflago; + + start = arm->ghostsf; + end = arm->ghostef; + if (end <= start) + return; + + /* get keyframes - then clip to only within range */ + action_to_keylist(act, &keys, NULL); + range= 0; + for (ak= keys.first; ak; ak= akn) { + akn= ak->next; + + if ((ak->cfra < start) || (ak->cfra > end)) + BLI_freelinkN(&keys, ak); + else + range++; + } + if (range == 0) return; + + /* store values */ + ob->flag &= ~OB_POSEMODE; + cfrao= CFRA; + flago= arm->flag; + arm->flag &= ~(ARM_DRAWNAMES|ARM_DRAWAXES); + ipoflago= ob->ipoflag; + ob->ipoflag |= OB_DISABLE_PATH; + + /* copy the pose */ + poseo= ob->pose; + copy_pose(&posen, ob->pose, 1); + ob->pose= posen; + armature_rebuild_pose(ob, ob->data); /* child pointers for IK */ + ghost_poses_tag_unselected(ob, 0); /* hide unselected bones if need be */ + + glEnable(GL_BLEND); + if (G.vd->zbuf) glDisable(GL_DEPTH_TEST); + + /* draw from first frame of range to last */ + for (ak=keys.first, i=0; ak; ak=ak->next, i++) { + colfac = i/range; + BIF_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0f*sqrt(colfac))); + + CFRA= (int)ak->cfra; + + do_all_pose_actions(ob); + where_is_pose(ob); + draw_pose_channels(base, OB_WIRE); + } + glDisable(GL_BLEND); + if (G.vd->zbuf) glEnable(GL_DEPTH_TEST); + + ghost_poses_tag_unselected(ob, 1); /* unhide unselected bones if need be */ + free_pose_channels(posen); + BLI_freelistN(&keys); + MEM_freeN(posen); + + /* restore */ + CFRA= cfrao; + ob->pose= poseo; + arm->flag= flago; + armature_rebuild_pose(ob, ob->data); + ob->flag |= OB_POSEMODE; + ob->ipoflag= ipoflago; } -/* object is supposed to be armature in posemode */ +/* draw ghosts around current frame + * - object is supposed to be armature in posemode + */ static void draw_ghost_poses(Base *base) { Object *ob= base->object; @@ -1948,11 +2118,11 @@ static void draw_ghost_poses(Base *base) int cfrao, maptime, flago, ipoflago; /* pre conditions, get an action with sufficient frames */ - if(ob->action==NULL) + if (ob->action==NULL) return; calc_action_range(ob->action, &start, &end, 0); - if(start==end) + if (start == end) return; stepsize= (float)(arm->ghostsize); @@ -1960,7 +2130,7 @@ static void draw_ghost_poses(Base *base) /* we only map time for armature when an active strip exists */ for (strip=ob->nlastrips.first; strip; strip=strip->next) - if(strip->flag & ACTSTRIP_ACTIVE) + if (strip->flag & ACTSTRIP_ACTIVE) break; maptime= (strip!=NULL); @@ -1968,7 +2138,7 @@ static void draw_ghost_poses(Base *base) /* store values */ ob->flag &= ~OB_POSEMODE; cfrao= CFRA; - if(maptime) actframe= get_action_frame(ob, (float)CFRA); + if (maptime) actframe= get_action_frame(ob, (float)CFRA); else actframe= CFRA; flago= arm->flag; arm->flag &= ~(ARM_DRAWNAMES|ARM_DRAWAXES); @@ -1980,24 +2150,23 @@ static void draw_ghost_poses(Base *base) copy_pose(&posen, ob->pose, 1); ob->pose= posen; armature_rebuild_pose(ob, ob->data); /* child pointers for IK */ + ghost_poses_tag_unselected(ob, 0); /* hide unselected bones if need be */ glEnable(GL_BLEND); - if(G.vd->zbuf) glDisable(GL_DEPTH_TEST); + if (G.vd->zbuf) glDisable(GL_DEPTH_TEST); /* draw from darkest blend to lowest */ for(cur= stepsize; cur<range; cur+=stepsize) { - ctime= cur - fmod((float)cfrao, stepsize); /* ensures consistant stepping */ colfac= ctime/range; BIF_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0f*sqrt(colfac))); /* only within action range */ - if(actframe+ctime >= start && actframe+ctime <= end) { - - if(maptime) CFRA= (int)get_action_frame_inv(ob, actframe+ctime); + if (actframe+ctime >= start && actframe+ctime <= end) { + if (maptime) CFRA= (int)get_action_frame_inv(ob, actframe+ctime); else CFRA= (int)floor(actframe+ctime); - if(CFRA!=cfrao) { + if (CFRA!=cfrao) { do_all_pose_actions(ob); where_is_pose(ob); draw_pose_channels(base, OB_WIRE); @@ -2009,12 +2178,11 @@ static void draw_ghost_poses(Base *base) BIF_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0f*sqrt(colfac))); /* only within action range */ - if(actframe-ctime >= start && actframe-ctime <= end) { - - if(maptime) CFRA= (int)get_action_frame_inv(ob, actframe-ctime); + if ((actframe-ctime >= start) && (actframe-ctime <= end)) { + if (maptime) CFRA= (int)get_action_frame_inv(ob, actframe-ctime); else CFRA= (int)floor(actframe-ctime); - - if(CFRA!=cfrao) { + + if (CFRA != cfrao) { do_all_pose_actions(ob); where_is_pose(ob); draw_pose_channels(base, OB_WIRE); @@ -2022,8 +2190,9 @@ static void draw_ghost_poses(Base *base) } } glDisable(GL_BLEND); - if(G.vd->zbuf) glEnable(GL_DEPTH_TEST); + if (G.vd->zbuf) glEnable(GL_DEPTH_TEST); + ghost_poses_tag_unselected(ob, 1); /* unhide unselected bones if need be */ free_pose_channels(posen); MEM_freeN(posen); @@ -2034,9 +2203,10 @@ static void draw_ghost_poses(Base *base) armature_rebuild_pose(ob, ob->data); ob->flag |= OB_POSEMODE; ob->ipoflag= ipoflago; - } +/* ********************************** Armature Drawing - Main ************************* */ + /* called from drawobject.c, return 1 if nothing was drawn */ int draw_armature(Base *base, int dt) { @@ -2072,10 +2242,13 @@ int draw_armature(Base *base, int dt) arm->flag |= ARM_POSEMODE; } else if(ob->flag & OB_POSEMODE) { - if (arm->ghosttype == ARM_GHOST_RANGE){ + if (arm->ghosttype == ARM_GHOST_RANGE) { draw_ghost_poses_range(base); } - else { + else if (arm->ghosttype == ARM_GHOST_KEYS) { + draw_ghost_poses_keys(base); + } + else if (arm->ghosttype == ARM_GHOST_CUR) { if (arm->ghostep) draw_ghost_poses(base); } diff --git a/source/blender/src/drawimasel.c b/source/blender/src/drawimasel.c index 257c5831813..88b6beb54c5 100644 --- a/source/blender/src/drawimasel.c +++ b/source/blender/src/drawimasel.c @@ -51,10 +51,11 @@ #include "DNA_material_types.h" #include "BLI_blenlib.h" +#include "BLI_storage_types.h" #ifdef WIN32 #include "BLI_winstuff.h" #endif -#include "BLI_storage_types.h" + #include "BKE_global.h" #include "BKE_library.h" diff --git a/source/blender/src/drawipo.c b/source/blender/src/drawipo.c index 94832561b86..fd3fa0df927 100644 --- a/source/blender/src/drawipo.c +++ b/source/blender/src/drawipo.c @@ -1190,7 +1190,7 @@ static void draw_ipovertices(int sel) ok= 0; if(ei->flag & IPO_EDIT) { - if( (bezt->f2 & 1) == sel ) ok= 1; + if( (bezt->f2 & SELECT) == sel ) ok= 1; } else ok= 1; @@ -1212,15 +1212,15 @@ static void draw_ipovertices(int sel) if(ei->flag & IPO_EDIT) { if(ei->icu->ipo==IPO_BEZ) { /* Draw the editmode hendels for a bezier curve */ - if( (bezt->f1 & 1) == sel)/* && G.v2d->cur.xmin < bezt->vec[0][0] < G.v2d->cur.xmax)*/ + if( (bezt->f1 & SELECT) == sel)/* && G.v2d->cur.xmin < bezt->vec[0][0] < G.v2d->cur.xmax)*/ bglVertex3fv(bezt->vec[0]); - if( (bezt->f3 & 1) == sel)/* && G.v2d->cur.xmin < bezt->vec[2][0] < G.v2d->cur.xmax)*/ + if( (bezt->f3 & SELECT) == sel)/* && G.v2d->cur.xmin < bezt->vec[2][0] < G.v2d->cur.xmax)*/ bglVertex3fv(bezt->vec[2]); } - if( (bezt->f2 & 1) == sel) /* && G.v2d->cur.xmin < bezt->vec[1][0] < G.v2d->cur.xmax)*/ + if( (bezt->f2 & SELECT) == sel) /* && G.v2d->cur.xmin < bezt->vec[1][0] < G.v2d->cur.xmax)*/ bglVertex3fv(bezt->vec[1]); } @@ -1261,7 +1261,7 @@ static void draw_ipohandles(int sel) b= ei->icu->totvert; while(b--) { - if( (bezt->f2 & 1)==sel) { + if( (bezt->f2 & SELECT)==sel) { fp= bezt->vec[0]; cpack(col[bezt->h1]); @@ -1282,7 +1282,7 @@ static void draw_ipohandles(int sel) glVertex2fv(fp); glVertex2fv(fp+3); glEnd(); } - else if( (bezt->f3 & 1)==sel) { + else if( (bezt->f3 & SELECT)==sel) { fp= bezt->vec[1]; cpack(col[bezt->h2]); @@ -1560,7 +1560,7 @@ static void draw_cfra(SpaceIpo *sipo) vec[0]*= G.scene->r.framelen; vec[1]= v2d->cur.ymin; - glColor3ub(0x60, 0xc0, 0x40); // no theme, should be global color once... + BIF_ThemeColor(TH_CFRAME); glLineWidth(2.0); glBegin(GL_LINE_STRIP); @@ -1571,7 +1571,7 @@ static void draw_cfra(SpaceIpo *sipo) if(sipo->blocktype==ID_OB) { ob= (G.scene->basact) ? (G.scene->basact->object) : 0; - if(ob && ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) { + if (ob && (ob->sf!=0.0) && (ob->ipoflag & OB_OFFS_OB) ) { vec[0]-= ob->sf; BIF_ThemeColorShade(TH_HILITE, -30); @@ -1730,16 +1730,16 @@ static void ipo_editvertex_buts(uiBlock *block, SpaceIpo *si, float min, float m b= ei->icu->totvert; while(b--) { // all three selected - if(bezt->f2 & 1) { + if(bezt->f2 & SELECT) { VecAddf(median, median, bezt->vec[1]); tot++; } else { - if(bezt->f1 & 1) { + if(bezt->f1 & SELECT) { VecAddf(median, median, bezt->vec[0]); tot++; } - if(bezt->f3 & 1) { + if(bezt->f3 & SELECT) { VecAddf(median, median, bezt->vec[2]); tot++; } @@ -1824,16 +1824,16 @@ static void ipo_editvertex_buts(uiBlock *block, SpaceIpo *si, float min, float m b= ei->icu->totvert; while(b--) { // all three selected - if(bezt->f2 & 1) { + if(bezt->f2 & SELECT) { VecAddf(bezt->vec[0], bezt->vec[0], median); VecAddf(bezt->vec[1], bezt->vec[1], median); VecAddf(bezt->vec[2], bezt->vec[2], median); } else { - if(bezt->f1 & 1) { + if(bezt->f1 & SELECT) { VecAddf(bezt->vec[0], bezt->vec[0], median); } - if(bezt->f3 & 1) { + if(bezt->f3 & SELECT) { VecAddf(bezt->vec[2], bezt->vec[2], median); } } @@ -2032,7 +2032,7 @@ static char *ipodriver_channelselect_pup(int is_armature) tmp+= sprintf(tmp, "|Scale Y %%x%d", OB_SIZE_Y); tmp+= sprintf(tmp, "|Scale Z %%x%d", OB_SIZE_Z); if(is_armature) - tmp+= sprintf(tmp, "|Rotation Differance %%x%d", OB_ROT_DIFF); + tmp+= sprintf(tmp, "|Rotation Difference %%x%d", OB_ROT_DIFF); return (string); } diff --git a/source/blender/src/drawnla.c b/source/blender/src/drawnla.c index 0394fcce80b..ea49c05b322 100644 --- a/source/blender/src/drawnla.c +++ b/source/blender/src/drawnla.c @@ -446,11 +446,13 @@ static void draw_nla_strips_keys(SpaceNla *snla) #define B_NLA_PANEL 121 #define B_NLA_LOCK 122 -#define B_NLA_MOD_ADD 123 -#define B_NLA_MOD_NEXT 124 -#define B_NLA_MOD_PREV 125 -#define B_NLA_MOD_DEL 126 -#define B_NLA_MOD_DEPS 127 +#define B_NLA_SCALE 123 +#define B_NLA_SCALE2 124 +#define B_NLA_MOD_ADD 125 +#define B_NLA_MOD_NEXT 126 +#define B_NLA_MOD_PREV 127 +#define B_NLA_MOD_DEL 128 +#define B_NLA_MOD_DEPS 129 /* For now just returns the first selected strip */ bActionStrip *get_active_nlastrip(Object **obpp) @@ -491,9 +493,37 @@ void do_nlabuts(unsigned short event) allqueue (REDRAWNLA, 0); allqueue (REDRAWVIEW3D, 0); break; + case B_NLA_SCALE: + { + float actlen= strip->actend - strip->actstart; + float mapping= strip->scale * strip->repeat; + + strip->end = (actlen * mapping) + strip->start; + + allqueue (REDRAWNLA, 0); + allqueue (REDRAWIPO, 0); + allqueue (REDRAWACTION, 0); + allqueue (REDRAWVIEW3D, 0); + } + break; + case B_NLA_SCALE2: + { + float actlen= strip->actend - strip->actstart; + float len= strip->end - strip->start; + + strip->scale= len / (actlen * strip->repeat); + + allqueue (REDRAWNLA, 0); + allqueue (REDRAWIPO, 0); + allqueue (REDRAWACTION, 0); + allqueue (REDRAWVIEW3D, 0); + } + break; case B_NLA_LOCK: synchronize_action_strips(); + allqueue (REDRAWNLA, 0); + allqueue (REDRAWIPO, 0); allqueue (REDRAWACTION, 0); allqueue (REDRAWVIEW3D, 0); break; @@ -576,7 +606,7 @@ static void nla_panel_properties(short cntrl) // NLA_HANDLER_PROPERTIES uiBlockBeginAlign(block); uiDefButF(block, NUM, B_NLA_PANEL, "Strip Start:", 10,160,150,19, &strip->start, -1000.0, strip->end-1, 100, 0, "First frame in the timeline"); - uiDefButF(block, NUM, B_NLA_PANEL, "Strip End:", 160,160,150,19, &strip->end, strip->start+1, MAXFRAMEF, 100, 0, "Last frame in the timeline"); + uiDefButF(block, NUM, B_NLA_SCALE2, "Strip End:", 160,160,150,19, &strip->end, strip->start+1, MAXFRAMEF, 100, 0, "Last frame in the timeline"); uiDefIconButBitS(block, ICONTOG, ACTSTRIP_LOCK_ACTION, B_NLA_LOCK, ICON_UNLOCKED, 10,140,20,19, &(strip->flag), 0, 0, 0, 0, "Toggles Action end/start to be automatic mapped to strip duration"); if(strip->flag & ACTSTRIP_LOCK_ACTION) { @@ -607,7 +637,15 @@ static void nla_panel_properties(short cntrl) // NLA_HANDLER_PROPERTIES uiDefButBitS(block, TOG, ACTSTRIP_MUTE, B_NLA_PANEL, "Mute", 10,60,145,19, &strip->flag, 0, 0, 0, 0, "Toggles whether the strip contributes to the NLA solution"); uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_NLA_PANEL, "Repeat:", 160,100,150,19, &strip->repeat, 0.001, 1000.0f, 100, 0, "Number of times the action should repeat"); + // FIXME: repeat and scale are too cramped! + uiDefButF(block, NUM, B_NLA_SCALE, "Repeat:", 160,100,75,19, &strip->repeat, 0.001, 1000.0f, 100, 0, "Number of times the action should repeat"); + if ((strip->actend - strip->actstart) < 1.0f) { + uiBlockSetCol(block, TH_REDALERT); + uiDefButF(block, NUM, B_NLA_SCALE, "Scale:", 235,100,75,19, &strip->scale, 0.001, 1000.0f, 100, 0, "Please run Alt-S to fix up this error"); + uiBlockSetCol(block, TH_AUTO); + } + else + uiDefButF(block, NUM, B_NLA_SCALE, "Scale:", 235,100,75,19, &strip->scale, 0.001, 1000.0f, 100, 0, "Amount the action should be scaled by"); but= uiDefButC(block, TEX, B_NLA_PANEL, "OffsBone:", 160,80,150,19, strip->offs_bone, 0, 31.0f, 0, 0, "Name of Bone that defines offset for repeat"); uiButSetCompleteFunc(but, autocomplete_bone, (void *)ob); uiDefButBitS(block, TOG, ACTSTRIP_HOLDLASTFRAME, B_NLA_PANEL, "Hold", 160,60,75,19, &strip->flag, 0, 0, 0, 0, "Toggles whether to continue displaying the last frame past the end of the strip"); diff --git a/source/blender/src/drawnode.c b/source/blender/src/drawnode.c index 52372b51167..b0c55d104f3 100644 --- a/source/blender/src/drawnode.c +++ b/source/blender/src/drawnode.c @@ -1949,25 +1949,40 @@ static void draw_nodespace_back(ScrArea *sa, SpaceNode *snode) Image *ima= BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); if(ibuf) { - int x, y; - /* somehow the offset has to be calculated inverse */ + int x, y; + float zoom = 1.0; + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); glaDefine2DArea(&sa->winrct); - /* ortho at pixel level curarea */ - myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375); - x = (sa->winx-ibuf->x)/2 + snode->xof; - y = (sa->winx-ibuf->y)/2 + snode->yof; + if(ibuf->x > sa->winx || ibuf->y > sa->winy) { + float zoomx, zoomy; + zoomx= (float)sa->winx/ibuf->x; + zoomy= (float)sa->winy/ibuf->y; + zoom = MIN2(zoomx, zoomy); + } + + x = (sa->winx-zoom*ibuf->x)/2 + snode->xof; + y = (sa->winy-zoom*ibuf->y)/2 + snode->yof; + + glPixelZoom(zoom, zoom); + glColor4f(1.0, 1.0, 1.0, 1.0); if(ibuf->rect) - glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); + glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, ibuf->rect); else if(ibuf->channels==4) - glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_FLOAT, ibuf->rect_float); - - /* sort this out, this should not be needed */ - myortho2(snode->v2d.cur.xmin, snode->v2d.cur.xmax, snode->v2d.cur.ymin, snode->v2d.cur.ymax); - bwin_clear_viewmat(sa->win); /* clear buttons view */ - glLoadIdentity(); + glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_FLOAT, ibuf->rect_float); + + glPixelZoom(1.0, 1.0); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); } } } diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index 899fda103bd..26858f657a6 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -1132,7 +1132,7 @@ static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel) int uxt = (u==0 || u==lt->pntsu-1); if(!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) { if(bp->hide==0) { - if((bp->f1 & 1)==sel) { + if((bp->f1 & SELECT)==sel) { bglVertex3fv(dl?co:bp->vec); } } @@ -1698,9 +1698,7 @@ static void draw_em_fancy_verts(EditMesh *em, DerivedMesh *cageDM, EditVert *eve draw_dm_verts(cageDM, sel, eve_act); } - if( (G.scene->selectmode & SCE_SELECT_FACE) && - (G.vd->drawtype<=OB_SOLID) - ) { + if( CHECK_OB_DRAWFACEDOT(G.scene, G.vd, G.obedit->dt) ) { glPointSize(fsize); glColor4ubv((GLubyte *)fcol); draw_dm_face_centers(cageDM, sel); @@ -2432,8 +2430,7 @@ static int draw_mesh_object(Base *base, int dt, int flag) } else { /* don't create boundbox here with mesh_get_bb(), the derived system will make it, puts deformed bb's OK */ - - if(me->totface<=4 || boundbox_clip(ob->obmat, me->bb)) { + if(me->totface<=4 || boundbox_clip(ob->obmat, (ob->bb)? ob->bb: me->bb)) { if(dt==OB_SOLID) has_alpha= init_gl_materials(ob, (base->flag & OB_FROMDUPLI)==0); draw_mesh_fancy(base, dt, flag); @@ -3030,7 +3027,7 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys) psys->flag|=PSYS_DRAWING; - if(part->flag&PART_CHILD_RENDER || !psys->childcache) + if(!psys->childcache) totchild=0; else totchild=psys->totchild*part->disp/100; @@ -3200,16 +3197,18 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys) } } else{ - pa_time=psys_get_child_time(psys,a-totpart,cfra); + ChildParticle *cpa= &psys->child[a-totpart]; + + pa_time=psys_get_child_time(psys,cpa,cfra); if((part->flag&PART_ABS_TIME)==0 && part->ipo){ calc_ipo(part->ipo, 100*pa_time); execute_ipo((ID *)part, part->ipo); } - pa_size=psys_get_child_size(psys,a-totpart,cfra,0); + pa_size=psys_get_child_size(psys,cpa,cfra,0); - r_tilt=2.0f*psys->child[a-totpart].rand[2]; + r_tilt=2.0f*cpa->rand[2]; if(path_nbr){ cache=psys->childcache[a-totpart]; k_max=(int)(cache->steps); @@ -3729,7 +3728,7 @@ static void tekenhandlesN(Nurb *nu, short sel) a= nu->pntsu; while(a--) { if(bezt->hide==0) { - if( (bezt->f2 & 1)==sel) { + if( (bezt->f2 & SELECT)==sel) { fp= bezt->vec[0]; cpack(col[bezt->h1]); @@ -3740,14 +3739,14 @@ static void tekenhandlesN(Nurb *nu, short sel) glVertex3fv(fp+3); glVertex3fv(fp+6); } - else if( (bezt->f1 & 1)==sel) { + else if( (bezt->f1 & SELECT)==sel) { fp= bezt->vec[0]; cpack(col[bezt->h1]); glVertex3fv(fp); glVertex3fv(fp+3); } - else if( (bezt->f3 & 1)==sel) { + else if( (bezt->f3 & SELECT)==sel) { fp= bezt->vec[1]; cpack(col[bezt->h2]); @@ -3785,11 +3784,11 @@ static void tekenvertsN(Nurb *nu, short sel) while(a--) { if(bezt->hide==0) { if (G.f & G_HIDDENHANDLES) { - if((bezt->f2 & 1)==sel) bglVertex3fv(bezt->vec[1]); + if((bezt->f2 & SELECT)==sel) bglVertex3fv(bezt->vec[1]); } else { - if((bezt->f1 & 1)==sel) bglVertex3fv(bezt->vec[0]); - if((bezt->f2 & 1)==sel) bglVertex3fv(bezt->vec[1]); - if((bezt->f3 & 1)==sel) bglVertex3fv(bezt->vec[2]); + if((bezt->f1 & SELECT)==sel) bglVertex3fv(bezt->vec[0]); + if((bezt->f2 & SELECT)==sel) bglVertex3fv(bezt->vec[1]); + if((bezt->f3 & SELECT)==sel) bglVertex3fv(bezt->vec[2]); } } bezt++; @@ -3800,7 +3799,7 @@ static void tekenvertsN(Nurb *nu, short sel) a= nu->pntsu*nu->pntsv; while(a--) { if(bp->hide==0) { - if((bp->f1 & 1)==sel) bglVertex3fv(bp->vec); + if((bp->f1 & SELECT)==sel) bglVertex3fv(bp->vec); } bp++; } @@ -3843,7 +3842,7 @@ static void draw_editnurb(Object *ob, Nurb *nurb, int sel) for(a=nu->pntsu-1; a>0; a--, bp++) { if(bp->hide==0 && bp1->hide==0) { if(sel) { - if( (bp->f1 & 1) && ( bp1->f1 & 1) ) { + if( (bp->f1 & SELECT) && ( bp1->f1 & SELECT ) ) { cpack(nurbcol[5]); glBegin(GL_LINE_STRIP); @@ -3853,7 +3852,7 @@ static void draw_editnurb(Object *ob, Nurb *nurb, int sel) } } else { - if( (bp->f1 & 1) && ( bp1->f1 & 1) ); + if( (bp->f1 & SELECT) && ( bp1->f1 & SELECT) ); else { cpack(nurbcol[1]); @@ -3876,7 +3875,7 @@ static void draw_editnurb(Object *ob, Nurb *nurb, int sel) for(a=nu->pntsv-1; a>0; a--, bp+=ofs) { if(bp->hide==0 && bp1->hide==0) { if(sel) { - if( (bp->f1 & 1) && ( bp1->f1 & 1) ) { + if( (bp->f1 & SELECT) && ( bp1->f1 & SELECT) ) { cpack(nurbcol[7]); glBegin(GL_LINE_STRIP); @@ -3886,7 +3885,7 @@ static void draw_editnurb(Object *ob, Nurb *nurb, int sel) } } else { - if( (bp->f1 & 1) && ( bp1->f1 & 1) ); + if( (bp->f1 & SELECT) && ( bp1->f1 & SELECT) ); else { cpack(nurbcol[3]); @@ -3940,8 +3939,9 @@ static void drawnurb(Base *base, Nurb *nurb, int dt) if(G.vd->zbuf) glEnable(GL_DEPTH_TEST); - /* direction vectors for 3d curve paths */ - if(cu->flag & CU_3D) { + /* direction vectors for 3d curve paths + when at its lowest, dont render normals */ + if(cu->flag & CU_3D && G.scene->editbutsize > 0.0015) { BIF_ThemeColor(TH_WIRE); for (bl=cu->bev.first,nu=nurb; nu && bl; bl=bl->next,nu=nu->next) { BevPoint *bevp= (BevPoint *)(bl+1); @@ -3949,7 +3949,7 @@ static void drawnurb(Base *base, Nurb *nurb, int dt) int skip= nu->resolu/16; float fac; - while (nr-->0) { + while (nr-->0) { /* accounts for empty bevel lists */ float ox,oy,oz; // Offset perpendicular to the curve float dx,dy,dz; // Delta along the curve @@ -4481,7 +4481,7 @@ static void draw_bounding_volume(Object *ob) BoundBox *bb=0; if(ob->type==OB_MESH) { - bb= mesh_get_bb(ob->data); + bb= mesh_get_bb(ob); } else if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) { bb= ( (Curve *)ob->data )->bb; @@ -4707,10 +4707,13 @@ void draw_object(Base *base, int flag) /* xray delay? */ if((flag & DRAW_PICKING)==0 && (base->flag & OB_FROMDUPLI)==0) { - /* xray and transp are set when it is drawing the 2nd/3rd pass */ - if(!G.vd->xray && !G.vd->transp && (ob->dtx & OB_DRAWXRAY)) { - add_view3d_after(G.vd, base, V3D_XRAY); - return; + /* don't do xray in particle mode, need the z-buffer */ + if(!(G.f & G_PARTICLEEDIT)) { + /* xray and transp are set when it is drawing the 2nd/3rd pass */ + if(!G.vd->xray && !G.vd->transp && (ob->dtx & OB_DRAWXRAY)) { + add_view3d_after(G.vd, base, V3D_XRAY); + return; + } } } @@ -5327,9 +5330,7 @@ static int bbs_mesh_solid_EM(DerivedMesh *dm, int facecol) if (facecol) { dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, (void*)(long) 1, 0); - if( (G.scene->selectmode & SCE_SELECT_FACE) && - (G.vd->drawtype<=OB_SOLID) - ) { + if( CHECK_OB_DRAWFACEDOT(G.scene, G.vd, G.obedit->dt) ) { glPointSize(BIF_GetThemeValuef(TH_FACEDOT_SIZE)); bglBegin(GL_POINTS); diff --git a/source/blender/src/drawsound.c b/source/blender/src/drawsound.c index fd82430e3b7..17d340b802c 100644 --- a/source/blender/src/drawsound.c +++ b/source/blender/src/drawsound.c @@ -176,8 +176,8 @@ static void draw_cfra_sound(SpaceSound *ssound) vec[0]*= G.scene->r.framelen; vec[1]= G.v2d->cur.ymin; - glColor3ub(0x20, 0x90, 0x20); - glLineWidth(4.0); + BIF_ThemeColor(TH_CFRAME); + glLineWidth(2.0); glBegin(GL_LINE_STRIP); glVertex2fv(vec); @@ -186,7 +186,6 @@ static void draw_cfra_sound(SpaceSound *ssound) glEnd(); glLineWidth(1.0); - } void drawsoundspace(ScrArea *sa, void *spacedata) diff --git a/source/blender/src/drawtext.c b/source/blender/src/drawtext.c index 1ea29886850..7addda70932 100644 --- a/source/blender/src/drawtext.c +++ b/source/blender/src/drawtext.c @@ -725,25 +725,37 @@ static void draw_cursor(SpaceText *st) { static void calc_text_rcts(SpaceText *st) { - short barheight, barstart; + short barheight, barstart, blank_lines; int lbarstart, lbarh, ltexth; + int pix_available, pix_top_margin, pix_bottom_margin; lbarstart= st->top; lbarh= st->viewlines; - ltexth= txt_get_span(st->text->lines.first, st->text->lines.last)+1; - - barheight= (lbarh*(curarea->winy-4))/ltexth; - if (barheight<20) barheight=20; - - barstart= (lbarstart*(curarea->winy-4))/ltexth + 8; + pix_top_margin = 8; + pix_bottom_margin = 4; + pix_available = curarea->winy - pix_top_margin - pix_bottom_margin; + ltexth= txt_get_span(st->text->lines.first, st->text->lines.last); + blank_lines = st->viewlines / 2; + + if(ltexth + blank_lines < lbarstart + st->viewlines) + blank_lines = lbarstart + st->viewlines - ltexth; + + ltexth += blank_lines; + + barstart = (lbarstart*pix_available)/ltexth; + barheight = (lbarh*pix_available)/ltexth; + if (barheight<20){ + barstart = ((pix_available + barheight - 20 )*lbarstart)/ltexth; + barheight=20; + } st->txtbar.xmin= 5; st->txtbar.xmax= 17; - st->txtbar.ymax= curarea->winy - barstart; + st->txtbar.ymax= curarea->winy - pix_top_margin - barstart; st->txtbar.ymin= st->txtbar.ymax - barheight; - CLAMP(st->txtbar.ymin, 2, curarea->winy-2); - CLAMP(st->txtbar.ymax, 2, curarea->winy-2); + CLAMP(st->txtbar.ymin, pix_bottom_margin, curarea->winy - pix_top_margin); + CLAMP(st->txtbar.ymax, pix_bottom_margin, curarea->winy - pix_top_margin); st->pix_per_line= (float) ltexth/curarea->winy; if (st->pix_per_line<.1) st->pix_per_line=.1f; @@ -752,18 +764,18 @@ static void calc_text_rcts(SpaceText *st) txt_get_span(st->text->lines.first, st->text->sell)); lbarh= abs(txt_get_span(st->text->lines.first, st->text->curl)-txt_get_span(st->text->lines.first, st->text->sell)); - barheight= (lbarh*(curarea->winy-4))/ltexth; + barheight= (lbarh*pix_available)/ltexth; if (barheight<2) barheight=2; - barstart= (lbarstart*(curarea->winy-4))/ltexth + 8; + barstart= (lbarstart*pix_available)/ltexth; st->txtscroll.xmin= 5; st->txtscroll.xmax= 17; st->txtscroll.ymax= curarea->winy-barstart; st->txtscroll.ymin= st->txtscroll.ymax - barheight; - CLAMP(st->txtscroll.ymin, 2, curarea->winy-2); - CLAMP(st->txtscroll.ymax, 2, curarea->winy-2); + CLAMP(st->txtscroll.ymin, pix_bottom_margin, curarea->winy - pix_top_margin); + CLAMP(st->txtscroll.ymax, pix_bottom_margin, curarea->winy - pix_top_margin); } static void draw_textscroll(SpaceText *st) diff --git a/source/blender/src/drawtime.c b/source/blender/src/drawtime.c index d4c4c091aa0..3743d6c963e 100644 --- a/source/blender/src/drawtime.c +++ b/source/blender/src/drawtime.c @@ -93,7 +93,7 @@ static void draw_cfra_time(SpaceTime *stime) vec[0]*= G.scene->r.framelen; vec[1]= G.v2d->cur.ymin; - glColor3ub(0x60, 0xc0, 0x40); // no theme, should be global color once... + BIF_ThemeColor(TH_CFRAME); // no theme, should be global color once... glLineWidth(3.0); glBegin(GL_LINES); diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 93915a0e92e..19df0f67297 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -1637,18 +1637,18 @@ static void v3d_editvertex_buts(uiBlock *block, Object *ob, float lim) bezt= nu->bezt; a= nu->pntsu; while(a--) { - if(bezt->f2 & 1) { + if(bezt->f2 & SELECT) { VecAddf(median, median, bezt->vec[1]); tot++; median[4]+= bezt->weight; totweight++; } else { - if(bezt->f1 & 1) { + if(bezt->f1 & SELECT) { VecAddf(median, median, bezt->vec[0]); tot++; } - if(bezt->f3 & 1) { + if(bezt->f3 & SELECT) { VecAddf(median, median, bezt->vec[2]); tot++; } @@ -1660,7 +1660,7 @@ static void v3d_editvertex_buts(uiBlock *block, Object *ob, float lim) bp= nu->bp; a= nu->pntsu*nu->pntsv; while(a--) { - if(bp->f1 & 1) { + if(bp->f1 & SELECT) { VecAddf(median, median, bp->vec); median[3]+= bp->vec[3]; totw++; @@ -1811,17 +1811,17 @@ static void v3d_editvertex_buts(uiBlock *block, Object *ob, float lim) bezt= nu->bezt; a= nu->pntsu; while(a--) { - if(bezt->f2 & 1) { + if(bezt->f2 & SELECT) { VecAddf(bezt->vec[0], bezt->vec[0], median); VecAddf(bezt->vec[1], bezt->vec[1], median); VecAddf(bezt->vec[2], bezt->vec[2], median); bezt->weight+= median[4]; } else { - if(bezt->f1 & 1) { + if(bezt->f1 & SELECT) { VecAddf(bezt->vec[0], bezt->vec[0], median); } - if(bezt->f3 & 1) { + if(bezt->f3 & SELECT) { VecAddf(bezt->vec[2], bezt->vec[2], median); } } @@ -1832,7 +1832,7 @@ static void v3d_editvertex_buts(uiBlock *block, Object *ob, float lim) bp= nu->bp; a= nu->pntsu*nu->pntsv; while(a--) { - if(bp->f1 & 1) { + if(bp->f1 & SELECT) { VecAddf(bp->vec, bp->vec, median); bp->vec[3]+= median[3]; bp->weight+= median[4]; @@ -2774,6 +2774,40 @@ void view3d_update_depths(View3D *v3d) } } +/* Enable sculpting in wireframe mode by drawing sculpt object only to the depth buffer */ +static void draw_sculpt_depths(View3D *v3d) +{ + Object *ob = OBACT; + + int dt= MIN2(v3d->drawtype, ob->dt); + if(v3d->zbuf==0 && dt>OB_WIRE) + dt= OB_WIRE; + if(dt == OB_WIRE) { + GLboolean depth_on; + int orig_vdt = v3d->drawtype; + int orig_zbuf = v3d->zbuf; + int orig_odt = ob->dt; + + glGetBooleanv(GL_DEPTH_TEST, &depth_on); + v3d->drawtype = ob->dt = OB_SOLID; + v3d->zbuf = 1; + + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + glEnable(GL_DEPTH_TEST); + draw_object(BASACT, 0); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + if(!depth_on) + glDisable(GL_DEPTH_TEST); + + v3d->drawtype = orig_vdt; + v3d->zbuf = orig_zbuf; + ob->dt = orig_odt; + } +} + +static void draw_viewport_fps(ScrArea *sa); + + void drawview3dspace(ScrArea *sa, void *spacedata) { View3D *v3d= spacedata; @@ -2921,8 +2955,10 @@ void drawview3dspace(ScrArea *sa, void *spacedata) } } - if(!retopo && sculpt && !(obact && (obact->dtx & OB_DRAWXRAY))) + if(!retopo && sculpt && !(obact && (obact->dtx & OB_DRAWXRAY))) { + draw_sculpt_depths(v3d); view3d_update_depths(v3d); + } if(G.moving) { BIF_drawConstraint(); @@ -2936,9 +2972,11 @@ void drawview3dspace(ScrArea *sa, void *spacedata) /* Transp and X-ray afterdraw stuff */ view3d_draw_xray(v3d, 0); // clears zbuffer if it is used! view3d_draw_transp(v3d, 0); - - if(!retopo && sculpt && (obact && (OBACT->dtx & OB_DRAWXRAY))) + + if(!retopo && sculpt && (obact && (OBACT->dtx & OB_DRAWXRAY))) { + draw_sculpt_depths(v3d); view3d_update_depths(v3d); + } if(v3d->flag & V3D_CLIPPING) view3d_clr_clipping(); @@ -3047,8 +3085,12 @@ void drawview3dspace(ScrArea *sa, void *spacedata) draw_view_axis(); else draw_view_icon(); - if(U.uiflag & USER_SHOW_VIEWPORTNAME) + + if(U.uiflag & USER_SHOW_FPS && G.f & G_PLAYANIM) { + draw_viewport_fps(sa); + } else if(U.uiflag & USER_SHOW_VIEWPORTNAME) { draw_viewport_name(sa); + } ob= OBACT; if(ob && (U.uiflag & USER_DRAWVIEWINFO)) @@ -3090,22 +3132,26 @@ void drawview3dspace(ScrArea *sa, void *spacedata) } -void drawview3d_render(struct View3D *v3d, int winx, int winy) +void drawview3d_render(struct View3D *v3d, int winx, int winy, float winmat[][4]) { Base *base; Scene *sce; - float winmat[4][4]; + float v3dwinmat[4][4]; - update_for_newframe_muted(); /* first, since camera can be animated */ + if(!winmat) + setwinmatrixview3d(winx, winy, NULL); - setwinmatrixview3d(winx, winy, NULL); - setviewmatrixview3d(); myloadmatrix(v3d->viewmat); + + /* when winmat is not NULL, it overrides the regular window matrix */ glMatrixMode(GL_PROJECTION); - mygetmatrix(winmat); + if(winmat) + myloadmatrix(winmat); + mygetmatrix(v3dwinmat); glMatrixMode(GL_MODELVIEW); - Mat4MulMat4(v3d->persmat, v3d->viewmat, winmat); + + Mat4MulMat4(v3d->persmat, v3d->viewmat, v3dwinmat); Mat4Invert(v3d->persinv, v3d->persmat); Mat4Invert(v3d->viewinv, v3d->viewmat); @@ -3217,6 +3263,10 @@ static ScrArea *oldsa; static double swaptime; static int curmode; +/* used for fps display */ +static double redrawtime; +static double lredrawtime; + int update_time(void) { static double ltime; @@ -3235,6 +3285,31 @@ int update_time(void) return (tottime < 0.0); } +static void draw_viewport_fps(ScrArea *sa) +{ + float fps; + char printable[16]; + + + if (lredrawtime == redrawtime) + return; + + printable[0] = '\0'; + fps = (float)(1.0/(lredrawtime-redrawtime)); + + /* is this more then half a frame behind? */ + if (fps+0.5 < FPS) { + BIF_ThemeColor(TH_REDALERT); + sprintf(printable, "fps: %.2f", (float)fps); + } else { + BIF_ThemeColor(TH_TEXT_HI); + sprintf(printable, "fps: %i", (int)(fps+0.5)); + } + + glRasterPos2i(10, sa->winy-20); + BMF_DrawString(G.fonts, printable); +} + static void inner_play_prefetch_frame(int mode, int cfra) { ScrArea *sa; @@ -3302,7 +3377,7 @@ static int cached_dynamics(int sfra, int efra) Object *ob; ModifierData *md; ParticleSystem *psys; - int i, stack_index, cached=1; + int i, stack_index=-1, cached=1; while(base && cached) { ob = base->object; @@ -3349,6 +3424,9 @@ void inner_play_anim_loop(int init, int mode) curmode= mode; last_cfra = -1; cached = cached_dynamics(PSFRA,PEFRA); + + redrawtime = 1.0/FPS; + lredrawtime = 0.0; return; } @@ -3372,7 +3450,7 @@ void inner_play_anim_loop(int init, int mode) if (sa->spacetype == SPACE_SEQ) { scrarea_do_windraw(sa); } - } + } sa= sa->next; } @@ -3484,7 +3562,10 @@ int play_anim(int mode) screen_swapbuffers(); while(TRUE) { - + + if (U.uiflag & USER_SHOW_FPS) + lredrawtime = PIL_check_seconds_timer(); + while(qtest()) { /* we test events first because of MKEY event */ @@ -3510,8 +3591,13 @@ int play_anim(int mode) if(ELEM3(event, ESCKEY, SPACEKEY, RIGHTMOUSE)) break; inner_play_anim_loop(0, 0); + + screen_swapbuffers(); - + + if (U.uiflag & USER_SHOW_FPS) + redrawtime = lredrawtime; + if((mode & 2) && CFRA==PEFRA) break; /* no replay */ } diff --git a/source/blender/src/edit.c b/source/blender/src/edit.c index accdd4b8990..fcd38ef16a7 100644 --- a/source/blender/src/edit.c +++ b/source/blender/src/edit.c @@ -728,7 +728,7 @@ void countall() a= nu->pntsu*nu->pntsv; while(a--) { G.totvert++; - if(bp->f1 & 1) G.totvertsel++; + if(bp->f1 & SELECT) G.totvertsel++; bp++; } } @@ -752,7 +752,7 @@ void countall() a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw; while(a--) { G.totvert++; - if(bp->f1 & 1) G.totvertsel++; + if(bp->f1 & SELECT) G.totvertsel++; bp++; } } @@ -1077,26 +1077,26 @@ static void make_trans_verts(float *min, float *max, int mode) bezt= nu->bezt; while(a--) { if(bezt->hide==0) { - if((mode & 1) || (bezt->f1 & 1)) { + if((mode & 1) || (bezt->f1 & SELECT)) { VECCOPY(tv->oldloc, bezt->vec[0]); tv->loc= bezt->vec[0]; - tv->flag= bezt->f1 & 1; + tv->flag= bezt->f1 & SELECT; tv++; tottrans++; } - if((mode & 1) || (bezt->f2 & 1)) { + if((mode & 1) || (bezt->f2 & SELECT)) { VECCOPY(tv->oldloc, bezt->vec[1]); tv->loc= bezt->vec[1]; tv->val= &(bezt->alfa); tv->oldval= bezt->alfa; - tv->flag= bezt->f2 & 1; + tv->flag= bezt->f2 & SELECT; tv++; tottrans++; } - if((mode & 1) || (bezt->f3 & 1)) { + if((mode & 1) || (bezt->f3 & SELECT)) { VECCOPY(tv->oldloc, bezt->vec[2]); tv->loc= bezt->vec[2]; - tv->flag= bezt->f3 & 1; + tv->flag= bezt->f3 & SELECT; tv++; tottrans++; } @@ -1109,12 +1109,12 @@ static void make_trans_verts(float *min, float *max, int mode) bp= nu->bp; while(a--) { if(bp->hide==0) { - if((mode & 1) || (bp->f1 & 1)) { + if((mode & 1) || (bp->f1 & SELECT)) { VECCOPY(tv->oldloc, bp->vec); tv->loc= bp->vec; tv->val= &(bp->alfa); tv->oldval= bp->alfa; - tv->flag= bp->f1 & 1; + tv->flag= bp->f1 & SELECT; tv++; tottrans++; } @@ -1147,11 +1147,11 @@ static void make_trans_verts(float *min, float *max, int mode) a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw; while(a--) { - if((mode & 1) || (bp->f1 & 1)) { + if((mode & 1) || (bp->f1 & SELECT)) { if(bp->hide==0) { VECCOPY(tv->oldloc, bp->vec); tv->loc= bp->vec; - tv->flag= bp->f1 & 1; + tv->flag= bp->f1 & SELECT; tv++; tottrans++; } diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c index 48a39875cc2..dc13e5d3019 100644 --- a/source/blender/src/editaction.c +++ b/source/blender/src/editaction.c @@ -136,7 +136,7 @@ bActionChannel *get_hilighted_action_channel (bAction *action) return NULL; for (achan= action->chanbase.first; achan; achan= achan->next) { - if(VISIBLE_ACHAN(achan)) { + if (VISIBLE_ACHAN(achan)) { if (SEL_ACHAN(achan) && (achan->flag & ACHAN_HILIGHTED)) return achan; } @@ -779,6 +779,45 @@ void duplicate_action_keys (void) transform_action_keys('g', 0); } +/* this function is responsible for snapping the current frame to selected data */ +void snap_cfra_action() +{ + ListBase act_data = {NULL, NULL}; + bActListElem *ale; + int filter; + void *data; + short datatype; + + /* get data */ + data= get_action_context(&datatype); + if (data == NULL) return; + + /* filter data */ + filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS); + actdata_filter(&act_data, filter, data, datatype); + + /* snap current frame to selected data */ + snap_cfra_ipo_keys(NULL, -1); + + for (ale= act_data.first; ale; ale= ale->next) { + if (NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) { + actstrip_map_ipo_keys(OBACT, ale->key_data, 0, 1); + snap_cfra_ipo_keys(ale->key_data, 0); + actstrip_map_ipo_keys(OBACT, ale->key_data, 1, 1); + } + else + snap_cfra_ipo_keys(ale->key_data, 0); + } + BLI_freelistN(&act_data); + + snap_cfra_ipo_keys(NULL, 1); + + BIF_undo_push("Snap Current Frame to Keys"); + allqueue(REDRAWACTION, 0); + allqueue(REDRAWIPO, 0); + allqueue(REDRAWNLA, 0); +} + /* this function is responsible for snapping keyframes to frame-times */ void snap_action_keys(short mode) { @@ -1968,6 +2007,59 @@ void markers_selectkeys_between (void) BLI_freelistN(&act_data); } +void selectkeys_leftright (short leftright, short select_mode) +{ + ListBase act_data = {NULL, NULL}; + bActListElem *ale; + int filter; + void *data; + short datatype; + float min, max; + + if (select_mode==SELECT_REPLACE) { + select_mode=SELECT_ADD; + deselect_action_keys(0, 0); + } + + /* determine what type of data we are operating on */ + data = get_action_context(&datatype); + if (data == NULL) return; + + if (leftright==1) { + min = -MAXFRAMEF; + max = (float)CFRA+0.1f; + } + else { + min = (float)CFRA-0.1f; + max = MAXFRAMEF; + } + + /* filter data */ + filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS); + actdata_filter(&act_data, filter, data, datatype); + + /* select keys to the right */ + for (ale= act_data.first; ale; ale= ale->next) { + if(NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) { + actstrip_map_ipo_keys(OBACT, ale->key_data, 0, 1); + borderselect_ipo_key(ale->key_data, min, max, SELECT_ADD); + actstrip_map_ipo_keys(OBACT, ale->key_data, 1, 1); + } + else { + borderselect_ipo_key(ale->key_data, min, max, SELECT_ADD); + } + } + + /* Cleanup */ + BLI_freelistN(&act_data); + + allqueue(REDRAWNLA, 0); + allqueue(REDRAWACTION, 0); + allqueue(REDRAWIPO, 0); + +} + + /* ----------------------------------------- */ /* This function makes a list of the selected keyframes @@ -2037,7 +2129,7 @@ void column_select_action_keys(int mode) actdata_filter(&act_data, filter, data, datatype); for (ale= act_data.first; ale; ale= ale->next) { - for(ce= elems.first; ce; ce= ce->next) { + for (ce= elems.first; ce; ce= ce->next) { for (icu= ale->key_data; icu; icu= icu->next) { BezTriple *bezt; int verts = 0; @@ -2576,7 +2668,7 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt) data= get_action_context(&datatype); if (val) { - if ( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0; + if ( uiDoBlocks(&curarea->uiblocks, event, 1)!=UI_NOTHING ) event= 0; /* swap mouse buttons based on user preference */ if (U.flag & USER_LMOUSESELECT) { @@ -2599,7 +2691,7 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt) case HOMEKEY: do_action_buttons(B_ACTHOME); // header break; - + case AKEY: if (mval[0]<NAMEWIDTH) { deselect_action_channels (1); @@ -2625,7 +2717,7 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } } break; - + case BKEY: if (G.qual & LR_CTRLKEY) { borderselect_markers(); @@ -2635,14 +2727,14 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt) borderselect_action(); } break; - + case CKEY: /* scroll the window so the current * frame is in the center. */ center_currframe(); break; - + case DKEY: if (mval[0]>ACTWIDTH) { if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY)) @@ -2740,7 +2832,12 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt) case SKEY: if (mval[0]>=ACTWIDTH) { - if (G.qual & LR_SHIFTKEY) { + if (G.qual == (LR_SHIFTKEY|LR_CTRLKEY)) { + if (data) { + snap_cfra_action(); + } + } + else if (G.qual & LR_SHIFTKEY) { if (data) { if (G.saction->flag & SACTION_DRAWTIME) val = pupmenu("Snap Keys To%t|Nearest Second%x4|Current Time%x2|Nearest Marker %x3"); @@ -2830,18 +2927,18 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt) * based on user preference USER_LMOUSESELECT */ case LEFTMOUSE: - if(view2dmove(LEFTMOUSE)) // only checks for sliders + if (view2dmove(LEFTMOUSE)) /* only checks for sliders */ break; else if ((G.v2d->mask.xmin==0) || (mval[0]>ACTWIDTH)) { + /* moving time-marker / current frame */ do { getmouseco_areawin(mval); - areamouseco_to_ipoco(G.v2d, mval, &dx, &dy); cfra= (int)dx; - if(cfra< 1) cfra= 1; + if (cfra < 1) cfra= 1; - if( cfra!=CFRA ) { + if (cfra != CFRA) { CFRA= cfra; update_for_newframe(); force_draw_all(0); @@ -2883,6 +2980,12 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt) /* Clicking in the main area of the action window * selects keys and markers */ + else if (G.qual & LR_ALTKEY) { + areamouseco_to_ipoco(G.v2d, mval, &dx, &dy); + + /* sends a 1 for left and 0 for right */ + selectkeys_leftright((dx < (float)CFRA), select_mode); + } else mouse_action(select_mode); } diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c index 9dcb190509f..7c25afc94c2 100644 --- a/source/blender/src/editarmature.c +++ b/source/blender/src/editarmature.c @@ -62,6 +62,7 @@ #include "BLI_blenlib.h" #include "BLI_arithb.h" #include "BLI_editVert.h" +#include "BLI_ghash.h" #include "BKE_action.h" #include "BKE_armature.h" @@ -103,6 +104,8 @@ #include "PIL_time.h" +#include "reeb.h" // FIX ME + #include "mydevice.h" #include "blendef.h" #include "nla.h" @@ -332,7 +335,7 @@ void editbones_to_armature (ListBase *list, Object *ob) fix_bonelist_roll (&arm->bonebase, list); /* so all users of this armature should get rebuilt */ - for(obt= G.main->object.first; obt; obt= obt->id.next) { + for (obt= G.main->object.first; obt; obt= obt->id.next) { if(obt->data==arm) armature_rebuild_pose(obt, arm); } @@ -2947,7 +2950,7 @@ static int hide_selected_pose_bone(Object *ob, Bone *bone, void *ptr) if(arm->layer & bone->layer) { if (bone->flag & BONE_SELECTED) { bone->flag |= BONE_HIDDEN_P; - bone->flag &= ~BONE_SELECTED; + bone->flag &= ~(BONE_SELECTED|BONE_ACTIVE); } } return 0; @@ -2977,6 +2980,7 @@ static int hide_unselected_pose_bone(Object *ob, Bone *bone, void *ptr) if(arm->layer & bone->layer) { if (~bone->flag & BONE_SELECTED) { bone->flag |= BONE_HIDDEN_P; + bone->flag &= ~BONE_ACTIVE; } } return 0; @@ -3277,5 +3281,1108 @@ void transform_armature_mirror_update(void) } +/*****************************************************************************************************/ +/*************************************** SKELETON GENERATOR ******************************************/ +/*****************************************************************************************************/ + +/**************************************** SYMMETRY HANDLING ******************************************/ + +void markdownSymmetryArc(ReebArc *arc, ReebNode *node, int level); + +void mirrorAlongAxis(float v[3], float center[3], float axis[3]) +{ + float dv[3], pv[3]; + + VecSubf(dv, v, center); + Projf(pv, dv, axis); + VecMulf(pv, -2); + VecAddf(v, v, pv); +} + +/* Helper structure for radial symmetry */ +typedef struct RadialArc +{ + ReebArc *arc; + float n[3]; /* normalized vector joining the nodes of the arc */ +} RadialArc; + +void reestablishRadialSymmetry(ReebNode *node, int depth, float axis[3]) +{ + RadialArc *ring = NULL; + RadialArc *unit; + float limit = G.scene->toolsettings->skgen_symmetry_limit; + int symmetric = 1; + int count = 0; + int i; + + /* count the number of arcs in the symmetry ring */ + for (i = 0; node->arcs[i] != NULL; i++) + { + ReebArc *connectedArc = node->arcs[i]; + + /* depth is store as a negative in flag. symmetry level is positive */ + if (connectedArc->flags == -depth) + { + count++; + } + } + + ring = MEM_callocN(sizeof(RadialArc) * count, "radial symmetry ring"); + unit = ring; + + /* fill in the ring */ + for (unit = ring, i = 0; node->arcs[i] != NULL; i++) + { + ReebArc *connectedArc = node->arcs[i]; + + /* depth is store as a negative in flag. symmetry level is positive */ + if (connectedArc->flags == -depth) + { + ReebNode *otherNode = OTHER_NODE(connectedArc, node); + float vec[3]; + + unit->arc = connectedArc; + + /* project the node to node vector on the symmetry plane */ + VecSubf(unit->n, otherNode->p, node->p); + Projf(vec, unit->n, axis); + VecSubf(unit->n, unit->n, vec); + + Normalize(unit->n); + + unit++; + } + } + + /* sort ring */ + for (i = 0; i < count - 1; i++) + { + float minAngle = 3; /* arbitrary high value, higher than 2, at least */ + int minIndex = -1; + int j; + + for (j = i + 1; j < count; j++) + { + float angle = Inpf(ring[i].n, ring[j].n); + + /* map negative values to 1..2 */ + if (angle < 0) + { + angle = 1 - angle; + } + + if (angle < minAngle) + { + minIndex = j; + minAngle = angle; + } + } + + /* swap if needed */ + if (minIndex != i + 1) + { + RadialArc tmp; + tmp = ring[i + 1]; + ring[i + 1] = ring[minIndex]; + ring[minIndex] = tmp; + } + } + + for (i = 0; i < count && symmetric; i++) + { + ReebNode *node1, *node2; + float tangent[3]; + float normal[3]; + float p[3]; + int j = (i + 1) % count; /* next arc in the circular list */ + + VecAddf(tangent, ring[i].n, ring[j].n); + Crossf(normal, tangent, axis); + + node1 = OTHER_NODE(ring[i].arc, node); + node2 = OTHER_NODE(ring[j].arc, node); + + VECCOPY(p, node2->p); + mirrorAlongAxis(p, node->p, normal); + + /* check if it's within limit before continuing */ + if (VecLenf(node1->p, p) > limit) + { + symmetric = 0; + } + + } + + if (symmetric) + { + /* first pass, merge incrementally */ + for (i = 0; i < count - 1; i++) + { + ReebNode *node1, *node2; + float tangent[3]; + float normal[3]; + int j = i + 1; + + VecAddf(tangent, ring[i].n, ring[j].n); + Crossf(normal, tangent, axis); + + node1 = OTHER_NODE(ring[i].arc, node); + node2 = OTHER_NODE(ring[j].arc, node); + + /* mirror first node and mix with the second */ + mirrorAlongAxis(node1->p, node->p, normal); + VecLerpf(node2->p, node2->p, node1->p, 1.0f / (j + 1)); + + /* Merge buckets + * there shouldn't be any null arcs here, but just to be safe + * */ + if (ring[i].arc->bcount > 0 && ring[j].arc->bcount > 0) + { + ReebArcIterator iter1, iter2; + EmbedBucket *bucket1 = NULL, *bucket2 = NULL; + + initArcIterator(&iter1, ring[i].arc, node); + initArcIterator(&iter2, ring[j].arc, node); + + bucket1 = nextBucket(&iter1); + bucket2 = nextBucket(&iter2); + + /* Make sure they both start at the same value */ + while(bucket1 && bucket1->val < bucket2->val) + { + bucket1 = nextBucket(&iter1); + } + + while(bucket2 && bucket2->val < bucket1->val) + { + bucket2 = nextBucket(&iter2); + } + + + for ( ;bucket1 && bucket2; bucket1 = nextBucket(&iter1), bucket2 = nextBucket(&iter2)) + { + bucket2->nv += bucket1->nv; /* add counts */ + + /* mirror on axis */ + mirrorAlongAxis(bucket1->p, node->p, normal); + /* add bucket2 in bucket1 */ + VecLerpf(bucket2->p, bucket2->p, bucket1->p, (float)bucket1->nv / (float)(bucket2->nv)); + } + } + } + + /* second pass, mirror back on previous arcs */ + for (i = count - 1; i > 0; i--) + { + ReebNode *node1, *node2; + float tangent[3]; + float normal[3]; + int j = i - 1; + + VecAddf(tangent, ring[i].n, ring[j].n); + Crossf(normal, tangent, axis); + + node1 = OTHER_NODE(ring[i].arc, node); + node2 = OTHER_NODE(ring[j].arc, node); + + /* copy first node than mirror */ + VECCOPY(node2->p, node1->p); + mirrorAlongAxis(node2->p, node->p, normal); + + /* Copy buckets + * there shouldn't be any null arcs here, but just to be safe + * */ + if (ring[i].arc->bcount > 0 && ring[j].arc->bcount > 0) + { + ReebArcIterator iter1, iter2; + EmbedBucket *bucket1 = NULL, *bucket2 = NULL; + + initArcIterator(&iter1, ring[i].arc, node); + initArcIterator(&iter2, ring[j].arc, node); + + bucket1 = nextBucket(&iter1); + bucket2 = nextBucket(&iter2); + + /* Make sure they both start at the same value */ + while(bucket1 && bucket1->val < bucket2->val) + { + bucket1 = nextBucket(&iter1); + } + + while(bucket2 && bucket2->val < bucket1->val) + { + bucket2 = nextBucket(&iter2); + } + + + for ( ;bucket1 && bucket2; bucket1 = nextBucket(&iter1), bucket2 = nextBucket(&iter2)) + { + /* copy and mirror back to bucket2 */ + bucket2->nv = bucket1->nv; + VECCOPY(bucket2->p, bucket1->p); + mirrorAlongAxis(bucket2->p, node->p, normal); + } + } + } + } + + MEM_freeN(ring); +} + +void reestablishAxialSymmetry(ReebNode *node, int depth, float axis[3]) +{ + ReebArc *arc1 = NULL; + ReebArc *arc2 = NULL; + ReebNode *node1 = NULL, *node2 = NULL; + float limit = G.scene->toolsettings->skgen_symmetry_limit; + float nor[3], vec[3], p[3]; + int i; + + for (i = 0; node->arcs[i] != NULL; i++) + { + ReebArc *connectedArc = node->arcs[i]; + + /* depth is store as a negative in flag. symmetry level is positive */ + if (connectedArc->flags == -depth) + { + if (arc1 == NULL) + { + arc1 = connectedArc; + node1 = OTHER_NODE(arc1, node); + } + else + { + arc2 = connectedArc; + node2 = OTHER_NODE(arc2, node); + break; /* Can stop now, the two arcs have been found */ + } + } + } + + /* shouldn't happen, but just to be sure */ + if (node1 == NULL || node2 == NULL) + { + return; + } + + VecSubf(p, node1->p, node->p); + Crossf(vec, p, axis); + Crossf(nor, vec, axis); + + /* mirror node2 along axis */ + VECCOPY(p, node2->p); + mirrorAlongAxis(p, node->p, nor); + + /* check if it's within limit before continuing */ + if (VecLenf(node1->p, p) <= limit) + { + + /* average with node1 */ + VecAddf(node1->p, node1->p, p); + VecMulf(node1->p, 0.5f); + + /* mirror back on node2 */ + VECCOPY(node2->p, node1->p); + mirrorAlongAxis(node2->p, node->p, nor); + + /* Merge buckets + * there shouldn't be any null arcs here, but just to be safe + * */ + if (arc1->bcount > 0 && arc2->bcount > 0) + { + ReebArcIterator iter1, iter2; + EmbedBucket *bucket1 = NULL, *bucket2 = NULL; + + initArcIterator(&iter1, arc1, node); + initArcIterator(&iter2, arc2, node); + + bucket1 = nextBucket(&iter1); + bucket2 = nextBucket(&iter2); + + /* Make sure they both start at the same value */ + while(bucket1 && bucket1->val < bucket2->val) + { + bucket1 = nextBucket(&iter1); + } + + while(bucket2 && bucket2->val < bucket1->val) + { + bucket2 = nextBucket(&iter2); + } + + + for ( ;bucket1 && bucket2; bucket1 = nextBucket(&iter1), bucket2 = nextBucket(&iter2)) + { + bucket1->nv += bucket2->nv; /* add counts */ + + /* mirror on axis */ + mirrorAlongAxis(bucket2->p, node->p, nor); + /* add bucket2 in bucket1 */ + VecLerpf(bucket1->p, bucket1->p, bucket2->p, (float)bucket2->nv / (float)(bucket1->nv)); + + /* copy and mirror back to bucket2 */ + bucket2->nv = bucket1->nv; + VECCOPY(bucket2->p, bucket1->p); + mirrorAlongAxis(bucket2->p, node->p, nor); + } + } + } +} + +void markdownSecondarySymmetry(ReebNode *node, int depth, int level) +{ + float axis[3] = {0, 0, 0}; + int count = 0; + int i; + + /* Only reestablish spatial symmetry if needed */ + if (G.scene->toolsettings->skgen_options & SKGEN_SYMMETRY) + { + /* count the number of branches in this symmetry group + * and determinte the axis of symmetry + * */ + for (i = 0; node->arcs[i] != NULL; i++) + { + ReebArc *connectedArc = node->arcs[i]; + + /* depth is store as a negative in flag. symmetry level is positive */ + if (connectedArc->flags == -depth) + { + count++; + } + /* If arc is on the axis */ + else if (connectedArc->flags == level) + { + VecAddf(axis, axis, connectedArc->v1->p); + VecSubf(axis, axis, connectedArc->v2->p); + } + } + + Normalize(axis); + + /* Split between axial and radial symmetry */ + if (count == 2) + { + reestablishAxialSymmetry(node, depth, axis); + } + else + { + reestablishRadialSymmetry(node, depth, axis); + } + } + + /* markdown secondary symetries */ + for (i = 0; node->arcs[i] != NULL; i++) + { + ReebArc *connectedArc = node->arcs[i]; + + if (connectedArc->flags == -depth) + { + /* markdown symmetry for branches corresponding to the depth */ + markdownSymmetryArc(connectedArc, node, level + 1); + } + } +} + +void markdownSymmetryArc(ReebArc *arc, ReebNode *node, int level) +{ + int i; + arc->flags = level; + + node = OTHER_NODE(arc, node); + + for (i = 0; node->arcs[i] != NULL; i++) + { + ReebArc *connectedArc = node->arcs[i]; + + if (connectedArc != arc) + { + ReebNode *connectedNode = OTHER_NODE(connectedArc, node); + + /* symmetry level is positive value, negative values is subtree depth */ + connectedArc->flags = -subtreeDepth(connectedNode, connectedArc); + } + } + + arc = NULL; + + for (i = 0; node->arcs[i] != NULL; i++) + { + int issymmetryAxis = 0; + ReebArc *connectedArc = node->arcs[i]; + + /* only arcs not already marked as symetric */ + if (connectedArc->flags < 0) + { + int j; + + /* true by default */ + issymmetryAxis = 1; + + for (j = 0; node->arcs[j] != NULL && issymmetryAxis == 1; j++) + { + ReebArc *otherArc = node->arcs[j]; + + /* different arc, same depth */ + if (otherArc != connectedArc && otherArc->flags == connectedArc->flags) + { + /* not on the symmetry axis */ + issymmetryAxis = 0; + } + } + } + + /* arc could be on the symmetry axis */ + if (issymmetryAxis == 1) + { + /* no arc as been marked previously, keep this one */ + if (arc == NULL) + { + arc = connectedArc; + } + else + { + /* there can't be more than one symmetry arc */ + arc = NULL; + break; + } + } + } + + /* go down the arc continuing the symmetry axis */ + if (arc) + { + markdownSymmetryArc(arc, node, level); + } + + + /* secondary symmetry */ + for (i = 0; node->arcs[i] != NULL; i++) + { + ReebArc *connectedArc = node->arcs[i]; + + /* only arcs not already marked as symetric and is not the next arc on the symmetry axis */ + if (connectedArc->flags < 0) + { + /* subtree depth is store as a negative value in the flag */ + markdownSecondarySymmetry(node, -connectedArc->flags, level); + } + } +} + +void markdownSymmetry(ReebGraph *rg) +{ + ReebNode *node; + ReebArc *arc; + /* only for Acyclic graphs */ + int cyclic = isGraphCyclic(rg); + + /* mark down all arcs as non-symetric */ + for (arc = rg->arcs.first; arc; arc = arc->next) + { + arc->flags = 0; + } + + /* mark down all nodes as not on the symmetry axis */ + for (node = rg->nodes.first; node; node = node->next) + { + node->flags = 0; + } + + /* node list is sorted, so lowest node is always the head (by design) */ + node = rg->nodes.first; + + /* only work on acyclic graphs and if only one arc is incident on the first node */ + if (cyclic == 0 && countConnectedArcs(rg, node) == 1) + { + arc = node->arcs[0]; + + markdownSymmetryArc(arc, node, 1); + + /* mark down non-symetric arcs */ + for (arc = rg->arcs.first; arc; arc = arc->next) + { + if (arc->flags < 0) + { + arc->flags = 0; + } + else + { + /* mark down nodes with the lowest level symmetry axis */ + if (arc->v1->flags == 0 || arc->v1->flags > arc->flags) + { + arc->v1->flags = arc->flags; + } + if (arc->v2->flags == 0 || arc->v2->flags > arc->flags) + { + arc->v2->flags = arc->flags; + } + } + } + } +} + +/**************************************** SUBDIVISION ALGOS ******************************************/ + +EditBone * subdivideByAngle(ReebArc *arc, ReebNode *head, ReebNode *tail) +{ + EditBone *lastBone = NULL; + if (G.scene->toolsettings->skgen_options & SKGEN_CUT_ANGLE) + { + ReebArcIterator iter; + EmbedBucket *current = NULL; + EmbedBucket *previous = NULL; + EditBone *child = NULL; + EditBone *parent = NULL; + EditBone *root = NULL; + float angleLimit = (float)cos(G.scene->toolsettings->skgen_angle_limit * M_PI / 180.0f); + + parent = add_editbone("Bone"); + parent->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL; + VECCOPY(parent->head, head->p); + + root = parent; + + for (initArcIterator(&iter, arc, head), previous = nextBucket(&iter), current = nextBucket(&iter); + current; + previous = current, current = nextBucket(&iter)) + { + float vec1[3], vec2[3]; + float len1, len2; + + VecSubf(vec1, previous->p, parent->head); + VecSubf(vec2, current->p, previous->p); + + len1 = Normalize(vec1); + len2 = Normalize(vec2); + + if (len1 > 0.0f && len2 > 0.0f && Inpf(vec1, vec2) < angleLimit) + { + VECCOPY(parent->tail, previous->p); + + child = add_editbone("Bone"); + VECCOPY(child->head, parent->tail); + child->parent = parent; + child->flag |= BONE_CONNECTED|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL; + + parent = child; /* new child is next parent */ + } + } + VECCOPY(parent->tail, tail->p); + + /* If the bone wasn't subdivided, delete it and return NULL + * to let subsequent subdivision methods do their thing. + * */ + if (parent == root) + { + delete_bone(parent); + parent = NULL; + } + + lastBone = parent; /* set last bone in the chain */ + } + + return lastBone; +} + +float calcCorrelation(ReebArc *arc, int start, int end, float v0[3], float n[3]) +{ + int len = 2 + abs(end - start); + + if (len > 2) + { + ReebArcIterator iter; + EmbedBucket *bucket = NULL; + float avg_t = 0.0f; + float s_t = 0.0f; + float s_xyz = 0.0f; + + /* First pass, calculate average */ + for (initArcIterator2(&iter, arc, start, end), bucket = nextBucket(&iter); + bucket; + bucket = nextBucket(&iter)) + { + float v[3]; + + VecSubf(v, bucket->p, v0); + avg_t += Inpf(v, n); + } + + avg_t /= Inpf(n, n); + avg_t += 1.0f; /* adding start (0) and end (1) values */ + avg_t /= len; + + /* Second pass, calculate s_xyz and s_t */ + for (initArcIterator2(&iter, arc, start, end), bucket = nextBucket(&iter); + bucket; + bucket = nextBucket(&iter)) + { + float v[3], d[3]; + float dt; + + VecSubf(v, bucket->p, v0); + Projf(d, v, n); + VecSubf(v, v, d); + + dt = VecLength(d) - avg_t; + + s_t += dt * dt; + s_xyz += Inpf(v, v); + } + + /* adding start(0) and end(1) values to s_t */ + s_t += (avg_t * avg_t) + (1 - avg_t) * (1 - avg_t); + + return 1.0f - s_xyz / s_t; + } + else + { + return 1.0f; + } +} + +EditBone * subdivideByCorrelation(ReebArc *arc, ReebNode *head, ReebNode *tail) +{ + ReebArcIterator iter; + float n[3]; + float CORRELATION_THRESHOLD = G.scene->toolsettings->skgen_correlation_limit; + EditBone *lastBone = NULL; + + /* init iterator to get start and end from head */ + initArcIterator(&iter, arc, head); + + /* Calculate overall */ + VecSubf(n, arc->buckets[iter.end].p, head->p); + + if (G.scene->toolsettings->skgen_options & SKGEN_CUT_CORRELATION && + calcCorrelation(arc, iter.start, iter.end, head->p, n) < CORRELATION_THRESHOLD) + { + EmbedBucket *bucket = NULL; + EmbedBucket *previous = NULL; + EditBone *child = NULL; + EditBone *parent = NULL; + int boneStart = iter.start; + + parent = add_editbone("Bone"); + parent->flag = BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL; + VECCOPY(parent->head, head->p); + + for (previous = nextBucket(&iter), bucket = nextBucket(&iter); + bucket; + previous = bucket, bucket = nextBucket(&iter)) + { + /* Calculate normal */ + VecSubf(n, bucket->p, parent->head); + + if (calcCorrelation(arc, boneStart, iter.index, parent->head, n) < CORRELATION_THRESHOLD) + { + VECCOPY(parent->tail, previous->p); + + child = add_editbone("Bone"); + VECCOPY(child->head, parent->tail); + child->parent = parent; + child->flag |= BONE_CONNECTED|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL; + + parent = child; // new child is next parent + boneStart = iter.index; // start from end + } + } + + VECCOPY(parent->tail, tail->p); + + lastBone = parent; /* set last bone in the chain */ + } + + return lastBone; +} + +float arcLengthRatio(ReebArc *arc) +{ + float arcLength = 0.0f; + float embedLength = 0.0f; + int i; + + arcLength = VecLenf(arc->v1->p, arc->v2->p); + + if (arc->bcount > 0) + { + /* Add the embedding */ + for ( i = 1; i < arc->bcount; i++) + { + embedLength += VecLenf(arc->buckets[i - 1].p, arc->buckets[i].p); + } + /* Add head and tail -> embedding vectors */ + embedLength += VecLenf(arc->v1->p, arc->buckets[0].p); + embedLength += VecLenf(arc->v2->p, arc->buckets[arc->bcount - 1].p); + } + else + { + embedLength = arcLength; + } + + return embedLength / arcLength; +} + +EditBone * subdivideByLength(ReebArc *arc, ReebNode *head, ReebNode *tail) +{ + EditBone *lastBone = NULL; + if ((G.scene->toolsettings->skgen_options & SKGEN_CUT_LENGTH) && + arcLengthRatio(arc) >= G.scene->toolsettings->skgen_length_ratio) + { + ReebArcIterator iter; + EmbedBucket *bucket = NULL; + EmbedBucket *previous = NULL; + EditBone *child = NULL; + EditBone *parent = NULL; + float lengthLimit = G.scene->toolsettings->skgen_length_limit; + int same = 0; + + parent = add_editbone("Bone"); + parent->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL; + VECCOPY(parent->head, head->p); + + initArcIterator(&iter, arc, head); + + bucket = nextBucket(&iter); + + while (bucket != NULL) + { + float *vec0 = NULL; + float *vec1 = bucket->p; + + /* first bucket. Previous is head */ + if (previous == NULL) + { + vec0 = head->p; + } + /* Previous is a valid bucket */ + else + { + vec0 = previous->p; + } + + /* If lengthLimit hits the current segment */ + if (VecLenf(vec1, parent->head) > lengthLimit) + { + if (same == 0) + { + float dv[3], off[3]; + float a, b, c, f; + + /* Solve quadratic distance equation */ + VecSubf(dv, vec1, vec0); + a = Inpf(dv, dv); + + VecSubf(off, vec0, parent->head); + b = 2 * Inpf(dv, off); + + c = Inpf(off, off) - (lengthLimit * lengthLimit); + + f = (-b + (float)sqrt(b * b - 4 * a * c)) / (2 * a); + + //printf("a %f, b %f, c %f, f %f\n", a, b, c, f); + + if (isnan(f) == 0 && f < 1.0f) + { + VECCOPY(parent->tail, dv); + VecMulf(parent->tail, f); + VecAddf(parent->tail, parent->tail, vec0); + } + else + { + VECCOPY(parent->tail, vec1); + } + } + else + { + float dv[3]; + + VecSubf(dv, vec1, vec0); + Normalize(dv); + + VECCOPY(parent->tail, dv); + VecMulf(parent->tail, lengthLimit); + VecAddf(parent->tail, parent->tail, parent->head); + } + + child = add_editbone("Bone"); + VECCOPY(child->head, parent->tail); + child->parent = parent; + child->flag |= BONE_CONNECTED|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL; + + parent = child; // new child is next parent + + same = 1; // mark as same + } + else + { + previous = bucket; + bucket = nextBucket(&iter); + same = 0; // Reset same + } + } + VECCOPY(parent->tail, tail->p); + + lastBone = parent; /* set last bone in the chain */ + } + + return lastBone; +} + +/***************************************** MAIN ALGORITHM ********************************************/ + +void generateSkeletonFromReebGraph(ReebGraph *rg) +{ + GHash *arcBoneMap = NULL; + ReebArc *arc = NULL; + ReebNode *node = NULL; + Object *src = NULL; + Object *dst = NULL; + + src = BASACT->object; + + if (G.obedit != NULL) + { + exit_editmode(EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); // freedata, and undo + } + + setcursor_space(SPACE_VIEW3D, CURSOR_WAIT); + + dst = add_object(OB_ARMATURE); + base_init_from_view3d(BASACT, G.vd); + G.obedit= BASACT->object; + + /* Copy orientation from source */ + VECCOPY(dst->loc, src->obmat[3]); + Mat4ToEul(src->obmat, dst->rot); + Mat4ToSize(src->obmat, dst->size); + + where_is_object(G.obedit); + + make_editArmature(); + + arcBoneMap = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); + + markdownSymmetry(rg); + + for (arc = rg->arcs.first; arc; arc = arc->next) + { + EditBone *lastBone = NULL; + ReebNode *head, *tail; + int i; + + /* Find out the direction of the arc through simple heuristics (in order of priority) : + * + * 1- Arcs on primary symmetry axis (flags == 1) point up (head: high weight -> tail: low weight) + * 2- Arcs starting on a primary axis point away from it (head: node on primary axis) + * 3- Arcs point down (head: low weight -> tail: high weight) + * + * Finally, the arc direction is stored in its flags: 1 (low -> high), -1 (high -> low) + */ + + /* if arc is a symmetry axis, internal bones go up the tree */ + if (arc->flags == 1 && arc->v2->degree != 1) + { + head = arc->v2; + tail = arc->v1; + + arc->flags = -1; /* mark arc direction */ + } + /* Bones point AWAY from the symmetry axis */ + else if (arc->v1->flags == 1) + { + head = arc->v1; + tail = arc->v2; + + arc->flags = 1; /* mark arc direction */ + } + else if (arc->v2->flags == 1) + { + head = arc->v2; + tail = arc->v1; + + arc->flags = -1; /* mark arc direction */ + } + /* otherwise, always go from low weight to high weight */ + else + { + head = arc->v1; + tail = arc->v2; + + arc->flags = 1; /* mark arc direction */ + } + + /* Loop over subdivision methods */ + for (i = 0; lastBone == NULL && i < SKGEN_SUB_TOTAL; i++) + { + switch(G.scene->toolsettings->skgen_subdivisions[i]) + { + case SKGEN_SUB_LENGTH: + lastBone = subdivideByLength(arc, head, tail); + break; + case SKGEN_SUB_ANGLE: + lastBone = subdivideByAngle(arc, head, tail); + break; + case SKGEN_SUB_CORRELATION: + lastBone = subdivideByCorrelation(arc, head, tail); + break; + } + } + + if (lastBone == NULL) + { + EditBone *bone; + bone = add_editbone("Bone"); + bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL; + + VECCOPY(bone->head, head->p); + VECCOPY(bone->tail, tail->p); + + /* set first and last bone, since there's only one */ + lastBone = bone; + } + + BLI_ghash_insert(arcBoneMap, arc, lastBone); + } + + /* Second pass, setup parent relationship between arcs */ + for (node = rg->nodes.first; node; node = node->next) + { + ReebArc *incomingArc = NULL; + int i; + + for (i = 0; node->arcs[i] != NULL; i++) + { + arc = node->arcs[i]; + + /* if arc is incoming into the node */ + if ((arc->v1 == node && arc->flags == -1) || (arc->v2 == node && arc->flags == 1)) + { + if (incomingArc == NULL) + { + incomingArc = arc; + /* loop further to make sure there's only one incoming arc */ + } + else + { + /* skip this node if more than one incomingArc */ + incomingArc = NULL; + break; /* No need to look further, we are skipping already */ + } + } + } + + if (incomingArc != NULL) + { + EditBone *parentBone = BLI_ghash_lookup(arcBoneMap, incomingArc); + + /* Look for outgoing arcs and parent their bones */ + for (i = 0; node->arcs[i] != NULL; i++) + { + arc = node->arcs[i]; + + /* if arc is outgoing from the node */ + if ((arc->v1 == node && arc->flags == 1) || (arc->v2 == node && arc->flags == -1)) + { + EditBone *childBone = BLI_ghash_lookup(arcBoneMap, arc); + + /* find the root bone */ + while(childBone->parent != NULL) + { + childBone = childBone->parent; + } + + childBone->parent = parentBone; + childBone->flag |= BONE_CONNECTED; + } + } + } + } + + BLI_ghash_free(arcBoneMap, NULL, NULL); + + setcursor_space(SPACE_VIEW3D, CURSOR_EDIT); + + BIF_undo_push("Generate Skeleton"); +} + +void generateSkeleton(void) +{ + EditMesh *em = G.editMesh; + ReebGraph *rg = NULL; + int i; + + if (em == NULL) + return; + + setcursor_space(SPACE_VIEW3D, CURSOR_WAIT); + + if (weightFromDistance(em) == 0) + { + error("No selected vertex\n"); + return; + } + + weightToHarmonic(em); + + renormalizeWeight(em, 1.0f); + +//#ifdef DEBUG_REEB + weightToVCol(em); +//#endif + + rg = generateReebGraph(em, G.scene->toolsettings->skgen_resolution); + + verifyBuckets(rg); + + /* Remove arcs without embedding */ + filterNullReebGraph(rg); + + verifyBuckets(rg); + + + i = 1; + /* filter until there's nothing more to do */ + while (i == 1) + { + i = 0; /* no work done yet */ + + if (G.scene->toolsettings->skgen_options & SKGEN_FILTER_EXTERNAL) + { + i |= filterExternalReebGraph(rg, G.scene->toolsettings->skgen_threshold_external * G.scene->toolsettings->skgen_resolution); + } + + verifyBuckets(rg); + + if (G.scene->toolsettings->skgen_options & SKGEN_FILTER_INTERNAL) + { + i |= filterInternalReebGraph(rg, G.scene->toolsettings->skgen_threshold_internal * G.scene->toolsettings->skgen_resolution); + } + } + + verifyBuckets(rg); + + repositionNodes(rg); + + verifyBuckets(rg); + + /* Filtering might have created degree 2 nodes, so remove them */ + removeNormalNodes(rg); + + verifyBuckets(rg); + + for(i = 0; i < G.scene->toolsettings->skgen_postpro_passes; i++) + { + postprocessGraph(rg, G.scene->toolsettings->skgen_postpro); + } + buildAdjacencyList(rg); + + sortNodes(rg); + + sortArcs(rg); + + generateSkeletonFromReebGraph(rg); + freeGraph(rg); +} diff --git a/source/blender/src/editcurve.c b/source/blender/src/editcurve.c index 358e6332d6d..8d845c4ba14 100644 --- a/source/blender/src/editcurve.c +++ b/source/blender/src/editcurve.c @@ -158,7 +158,7 @@ static short select_bpoint(BPoint *bp, short selstatus, short flag, short hidden static short swap_selection_beztriple(BezTriple *bezt) { - if(bezt->f2 & 1) + if(bezt->f2 & SELECT) return select_beztriple(bezt, DESELECT, 1, VISIBLE); else return select_beztriple(bezt, SELECT, 1, VISIBLE); @@ -166,7 +166,7 @@ static short swap_selection_beztriple(BezTriple *bezt) static short swap_selection_bpoint(BPoint *bp) { - if(bp->f1 & 1) + if(bp->f1 & SELECT) return select_bpoint(bp, DESELECT, 1, VISIBLE); else return select_bpoint(bp, SELECT, 1, VISIBLE); @@ -182,7 +182,7 @@ short isNurbsel(Nurb *nu) bezt= nu->bezt; a= nu->pntsu; while(a--) { - if( (bezt->f1 & 1) || (bezt->f2 & 1) || (bezt->f3 & 1) ) return 1; + if( (bezt->f1 & SELECT) || (bezt->f2 & SELECT) || (bezt->f3 & SELECT) ) return 1; bezt++; } } @@ -190,7 +190,7 @@ short isNurbsel(Nurb *nu) bp= nu->bp; a= nu->pntsu*nu->pntsv; while(a--) { - if( (bp->f1 & 1) ) return 1; + if( (bp->f1 & SELECT) ) return 1; bp++; } } @@ -207,7 +207,7 @@ int isNurbsel_count(Nurb *nu) bezt= nu->bezt; a= nu->pntsu; while(a--) { - if( (bezt->f1 & 1) || (bezt->f2 & 1) || (bezt->f3 & 1) ) sel++; + if (BEZSELECTED_HIDDENHANDLES(bezt)) sel++; bezt++; } } @@ -215,7 +215,7 @@ int isNurbsel_count(Nurb *nu) bp= nu->bp; a= nu->pntsu*nu->pntsv; while(a--) { - if( (bp->f1 & 1) ) sel++; + if( (bp->f1 & SELECT) ) sel++; bp++; } } @@ -1319,9 +1319,9 @@ static void select_adjacent_cp(short next, short cont, short selstatus) while(a--) { if(a-abs(next) < 0) break; sel= 0; - if((lastsel==0) && (bezt->hide==0) && ((bezt->f2 & 1) || (selstatus==0))) { + if((lastsel==0) && (bezt->hide==0) && ((bezt->f2 & SELECT) || (selstatus==0))) { bezt+=next; - if(!(bezt->f2 & 1) || (selstatus==0)) { + if(!(bezt->f2 & SELECT) || (selstatus==0)) { sel= select_beztriple(bezt, selstatus, 1, VISIBLE); if((sel==1) && (cont==0)) lastsel= 1; } @@ -1341,9 +1341,9 @@ static void select_adjacent_cp(short next, short cont, short selstatus) while(a--) { if(a-abs(next) < 0) break; sel=0; - if((lastsel==0) && (bp->hide==0) && ((bp->f1 & 1) || (selstatus==0))) { + if((lastsel==0) && (bp->hide==0) && ((bp->f1 & SELECT) || (selstatus==0))) { bp+=next; - if(!(bp->f1 & 1) || (selstatus==0)) { + if(!(bp->f1 & SELECT) || (selstatus==0)) { sel= select_bpoint(bp, selstatus, 1, VISIBLE); if((sel==1) && (cont==0)) lastsel= 1; } @@ -1372,9 +1372,9 @@ static short nurb_has_selected_cps() bezt= nu->bezt; while(a--) { if(bezt->hide==0) { - if((bezt->f1 & 1) - || (bezt->f2 & 1) - || (bezt->f3 & 1)) return 1; + if((bezt->f1 & SELECT) + || (bezt->f2 & SELECT) + || (bezt->f3 & SELECT)) return 1; } bezt++; } @@ -1383,7 +1383,7 @@ static short nurb_has_selected_cps() a= nu->pntsu*nu->pntsv; bp= nu->bp; while(a--) { - if((bp->hide==0) && (bp->f1 & 1)) return 1; + if((bp->hide==0) && (bp->f1 & SELECT)) return 1; bp++; } } @@ -1428,7 +1428,7 @@ void hideNurb(int swap) a= nu->pntsu; sel= 0; while(a--) { - if(BEZSELECTED(bezt)) { + if(BEZSELECTED_HIDDENHANDLES(bezt)) { select_beztriple(bezt, DESELECT, 1, HIDDEN); bezt->hide= 1; } @@ -1442,11 +1442,11 @@ void hideNurb(int swap) a= nu->pntsu*nu->pntsv; sel= 0; while(a--) { - if(swap==0 && (bp->f1 & 1)) { + if(swap==0 && (bp->f1 & SELECT)) { select_bpoint(bp, DESELECT, 1, HIDDEN); bp->hide= 1; } - else if(swap && (bp->f1 & 1)==0) { + else if(swap && (bp->f1 & SELECT)==0) { select_bpoint(bp, DESELECT, 1, HIDDEN); bp->hide= 1; } @@ -1520,12 +1520,11 @@ void selectswapNurb() a= nu->pntsu; while(a--) { if(bezt->hide==0) { - if(bezt->f1 & 1) bezt->f1 &= ~1; - else bezt->f1 |= 1; - if(bezt->f2 & 1) bezt->f2 &= ~1; - else bezt->f2 |= 1; - if(bezt->f3 & 1) bezt->f3 &= ~1; - else bezt->f3 |= 1; + bezt->f2 ^= SELECT; /* always do the center point */ + if ((G.f & G_HIDDENHANDLES)==0) { + bezt->f1 ^= SELECT; + bezt->f3 ^= SELECT; + } } bezt++; } @@ -1584,7 +1583,7 @@ void subdivideNurb() bezt= prevbezt+1; } while(a--) { - if( BEZSELECTED(prevbezt) && BEZSELECTED(bezt) ) amount++; + if( BEZSELECTED_HIDDENHANDLES(prevbezt) && BEZSELECTED_HIDDENHANDLES(bezt) ) amount++; prevbezt= bezt; bezt++; } @@ -1608,7 +1607,7 @@ void subdivideNurb() memcpy(beztn, prevbezt, sizeof(BezTriple)); beztn++; - if( BEZSELECTED(prevbezt) && BEZSELECTED(bezt) ) { + if( BEZSELECTED_HIDDENHANDLES(prevbezt) && BEZSELECTED_HIDDENHANDLES(bezt) ) { memcpy(beztn, bezt, sizeof(BezTriple)); /* midpoint subdividing */ @@ -1667,7 +1666,7 @@ void subdivideNurb() bp= prevbp+1; } while(a--) { - if( (bp->f1 & 1) && (prevbp->f1 & 1) ) amount++; + if( (bp->f1 & SELECT) && (prevbp->f1 & SELECT) ) amount++; prevbp= bp; bp++; } @@ -1692,7 +1691,7 @@ void subdivideNurb() memcpy(bpn, prevbp, sizeof(BPoint)); bpn++; - if( (bp->f1 & 1) && (prevbp->f1 & 1) ) { + if( (bp->f1 & SELECT) && (prevbp->f1 & SELECT) ) { // printf("*** subdivideNurb: insert 'linear' point\n"); memcpy(bpn, bp, sizeof(BPoint)); bpn->vec[0]= (prevbp->vec[0]+bp->vec[0])/2.0; @@ -1768,7 +1767,7 @@ void subdivideNurb() bp= nu->bp; for(a=0; a<nu->pntsv; a++) { for(b=0; b<nu->pntsu; b++) { - if(bp->f1 & 1) { + if(bp->f1 & SELECT) { usel[b]++; vsel[a]++; sel++; @@ -2000,7 +1999,7 @@ static void findselectedNurbvert(Nurb **nu, BezTriple **bezt, BPoint **bp) bezt1= nu1->bezt; a= nu1->pntsu; while(a--) { - if( (bezt1->f1 & 1) || (bezt1->f2 & 1) || (bezt1->f3 & 1) ) { + if( (bezt1->f1 & SELECT) || (bezt1->f2 & SELECT) || (bezt1->f3 & SELECT) ) { if(*nu!=0 && *nu!= nu1) { *nu= 0; *bp= 0; @@ -2238,7 +2237,7 @@ int is_u_selected(Nurb *nu, int u) /* what about resolu == 2? */ bp= nu->bp+u; for(v=0; v<nu->pntsv-1; v++, bp+=nu->pntsu) { - if(v) if(bp->f1 & 1) return 1; + if(v) if(bp->f1 & SELECT) return 1; } return 0; @@ -2517,7 +2516,7 @@ void addsegment_nurb() if(isNurbsel_count(nu)==1) { /* only 1 selected, not first or last, a little complex, but intuitive */ if(nu->pntsv==1) { - if( (nu->bp->f1 & 1) || ((nu->bp+nu->pntsu-1)->f1 & 1)); + if( (nu->bp->f1 & SELECT) || ((nu->bp+nu->pntsu-1)->f1 & SELECT)); else break; } } @@ -2535,23 +2534,23 @@ void addsegment_nurb() if( (nu->type & 7)==CU_BEZIER ) { bezt= nu->bezt; if(nu1==0) { - if( BEZSELECTED(bezt) ) nu1= nu; + if( BEZSELECTED_HIDDENHANDLES(bezt) ) nu1= nu; else { bezt= bezt+(nu->pntsu-1); - if( BEZSELECTED(bezt) ) { + if( BEZSELECTED_HIDDENHANDLES(bezt) ) { nu1= nu; switchdirectionNurb(nu); } } } else if(nu2==0) { - if( BEZSELECTED(bezt) ) { + if( BEZSELECTED_HIDDENHANDLES(bezt) ) { nu2= nu; switchdirectionNurb(nu); } else { bezt= bezt+(nu->pntsu-1); - if( BEZSELECTED(bezt) ) { + if( BEZSELECTED_HIDDENHANDLES(bezt) ) { nu2= nu; } } @@ -2561,23 +2560,23 @@ void addsegment_nurb() else if(nu->pntsv==1) { bp= nu->bp; if(nu1==0) { - if( bp->f1 & 1) nu1= nu; + if( bp->f1 & SELECT) nu1= nu; else { bp= bp+(nu->pntsu-1); - if( bp->f1 & 1 ) { + if( bp->f1 & SELECT ) { nu1= nu; switchdirectionNurb(nu); } } } else if(nu2==0) { - if( bp->f1 & 1) { + if( bp->f1 & SELECT ) { nu2= nu; switchdirectionNurb(nu); } else { bp= bp+(nu->pntsu-1); - if( bp->f1 & 1 ) { + if( bp->f1 & SELECT ) { nu2= nu; } } @@ -2670,8 +2669,8 @@ void mouse_nurb() if(bezt) { if(hand==1) select_beztriple(bezt, SELECT, 1, HIDDEN); - else if(hand==0) bezt->f1|= 1; - else bezt->f3|= 1; + else if(hand==0) bezt->f1|= SELECT; + else bezt->f3|= SELECT; } else { lastselbp= bp; @@ -2683,28 +2682,16 @@ void mouse_nurb() else { if(bezt) { if(hand==1) { - if(bezt->f2 & 1) select_beztriple(bezt, DESELECT, 1, HIDDEN); + if(bezt->f2 & SELECT) select_beztriple(bezt, DESELECT, 1, HIDDEN); else select_beztriple(bezt, SELECT, 1, HIDDEN); - } - else if(hand==0) { - if(bezt->f1 & 1) { - bezt->f1 &= ~1; - } - else { - bezt->f1 |= 1; - } - } - else { - if(bezt->f3 & 1) { - bezt->f3 &= ~1; - } - else { - bezt->f3 |= 1; - } + } else if(hand==0) { + bezt->f1 ^= SELECT; + } else { + bezt->f3 ^= SELECT; } } else { - if(bp->f1 & 1) select_bpoint(bp, DESELECT, 1, HIDDEN); + if(bp->f1 & SELECT) select_bpoint(bp, DESELECT, 1, HIDDEN); else { select_bpoint(bp, SELECT, 1, HIDDEN); lastselbp= bp; @@ -2863,7 +2850,7 @@ void addvert_Nurb(int mode) (BezTriple*)MEM_callocN((nu->pntsu+1) * sizeof(BezTriple), "addvert_Nurb"); memcpy(newbezt+1, bezt, nu->pntsu*sizeof(BezTriple)); *newbezt= *bezt; - newbezt->f1= newbezt->f2= newbezt->f3= 1; + newbezt->f1= newbezt->f2= newbezt->f3= SELECT; if(newbezt->h1 >= 0) newbezt->h2= newbezt->h1; else newbezt->h2= newbezt->h1= HD_ALIGN; /* does this ever happen? */ VECCOPY(temp, bezt->vec[1]); @@ -2881,7 +2868,7 @@ void addvert_Nurb(int mode) MEM_freeN(nu->bezt); nu->bezt= newbezt; newbezt+= nu->pntsu; - newbezt->f1= newbezt->f2= newbezt->f3= 1; + newbezt->f1= newbezt->f2= newbezt->f3= SELECT; if(newbezt->h1 >= 0) newbezt->h2= newbezt->h1; else newbezt->h2= newbezt->h1= HD_ALIGN; /* does this ever happen? */ bezt= nu->bezt+nu->pntsu-1; @@ -2991,10 +2978,7 @@ void extrude_nurb() } if(nu) { addvert_Nurb('e'); - } - else { - - + } else { ok= extrudeflagNurb(1); /* '1'= flag */ if(ok) { @@ -3024,7 +3008,7 @@ void makecyclicNurb() a= nu->pntsu; bp= nu->bp; while(a--) { - if( bp->f1 & 1 ) { + if( bp->f1 & SELECT ) { if(nu->flagu & CU_CYCLIC) nu->flagu--; else nu->flagu++; break; @@ -3036,7 +3020,7 @@ void makecyclicNurb() a= nu->pntsu; bezt= nu->bezt; while(a--) { - if( BEZSELECTED(bezt) ) { + if( BEZSELECTED_HIDDENHANDLES(bezt) ) { if(nu->flagu & CU_CYCLIC) nu->flagu--; else nu->flagu++; break; @@ -3049,7 +3033,7 @@ void makecyclicNurb() a= nu->pntsu; bp= nu->bp; while(a--) { - if( bp->f1 & 1 ) { + if( bp->f1 & SELECT ) { if(nu->flagu & CU_CYCLIC) nu->flagu--; else { nu->flagu++; @@ -3077,7 +3061,7 @@ void makecyclicNurb() bp= nu->bp; while(a--) { - if( bp->f1 & 1) { + if( bp->f1 & SELECT) { if(cyclmode==1 && nu->pntsu>1) { if(nu->flagu & CU_CYCLIC) nu->flagu--; else { @@ -3167,7 +3151,7 @@ void selectrow_nurb() for(v=0; v<nu->pntsv; v++) { for(u=0; u<nu->pntsu; u++, bp++) { if(bp==lastselbp) { - if(bp->f1 & 1) { + if(bp->f1 & SELECT) { ok= 1; break; } @@ -3305,18 +3289,18 @@ void select_more_nurb() bp= nu->bp; selbpoints= MEM_callocN(sizeof(short)*a-nu->pntsu, "selectlist"); while(a > 0) { - if((selbpoints[a]!=1) && (bp->hide==0) && (bp->f1 & 1)) { + if((selbpoints[a]!=1) && (bp->hide==0) && (bp->f1 & SELECT)) { /* upper control point */ if(a%nu->pntsu != 0) { tempbp= bp-1; - if(!(tempbp->f1 & 1)) select_bpoint(tempbp, SELECT, 1, VISIBLE); + if(!(tempbp->f1 & SELECT)) select_bpoint(tempbp, SELECT, 1, VISIBLE); } /* left control point. select only if it is not selected already */ if(a-nu->pntsu > 0) { sel= 0; tempbp= bp+nu->pntsu; - if(!(tempbp->f1 & 1)) sel= select_bpoint(tempbp, SELECT, 1, VISIBLE); + if(!(tempbp->f1 & SELECT)) sel= select_bpoint(tempbp, SELECT, 1, VISIBLE); /* make sure selected bpoint is discarded */ if(sel == 1) selbpoints[a-nu->pntsu]= 1; } @@ -3324,7 +3308,7 @@ void select_more_nurb() /* right control point */ if(a+nu->pntsu < nu->pntsu*nu->pntsv) { tempbp= bp-nu->pntsu; - if(!(tempbp->f1 & 1)) select_bpoint(tempbp, SELECT, 1, VISIBLE); + if(!(tempbp->f1 & SELECT)) select_bpoint(tempbp, SELECT, 1, VISIBLE); } /* lower control point. skip next bp in case selection was made */ @@ -3374,7 +3358,7 @@ void select_less_nurb() bp= nu->bp; selbpoints= MEM_callocN(sizeof(short)*a, "selectlist"); while(a--) { - if((bp->hide==0) && (bp->f1 & 1)) { + if((bp->hide==0) && (bp->f1 & SELECT)) { sel= 0; /* check if neighbours have been selected */ @@ -3382,28 +3366,28 @@ void select_less_nurb() if((a+1)%nu->pntsu==0) sel++; else { bp--; - if((selbpoints[a+1]==1) || ((bp->hide==0) && (bp->f1 & 1))) sel++; + if((selbpoints[a+1]==1) || ((bp->hide==0) && (bp->f1 & SELECT))) sel++; bp++; } if((a+1)%nu->pntsu==1) sel++; else { bp++; - if((bp->hide==0) && (bp->f1 & 1)) sel++; + if((bp->hide==0) && (bp->f1 & SELECT)) sel++; bp--; } if(a+1 > nu->pntsu*nu->pntsv-nu->pntsu) sel++; else { bp-=nu->pntsu; - if((selbpoints[a+nu->pntsu]==1) || ((bp->hide==0) && (bp->f1 & 1))) sel++; + if((selbpoints[a+nu->pntsu]==1) || ((bp->hide==0) && (bp->f1 & SELECT))) sel++; bp+=nu->pntsu; } if(a < nu->pntsu) sel++; else { bp+=nu->pntsu; - if((bp->hide==0) && (bp->f1 & 1)) sel++; + if((bp->hide==0) && (bp->f1 & SELECT)) sel++; bp-=nu->pntsu; } @@ -3428,7 +3412,7 @@ void select_less_nurb() a= nu->pntsu; bezt= nu->bezt; while(a--) { - if((bezt->hide==0) && (bezt->f2 & 1)) { + if((bezt->hide==0) && (bezt->f2 & SELECT)) { if(lastsel==1) sel= 1; else sel= 0; @@ -3437,22 +3421,22 @@ void select_less_nurb() if(a==nu->pntsu-1) sel++; else { bezt--; - if((bezt->hide==0) && (bezt->f2 & 1)) sel++; + if((bezt->hide==0) && (bezt->f2 & SELECT)) sel++; bezt++; } if(a==0) sel++; else { bezt++; - if((bezt->hide==0) && (bezt->f2 & 1)) sel++; + if((bezt->hide==0) && (bezt->f2 & SELECT)) sel++; bezt--; } - + if(sel!=2) { select_beztriple(bezt, DESELECT, 1, VISIBLE); - lastsel= 1; - } - else lastsel= 0; + lastsel= 1; + } + else lastsel= 0; } else lastsel= 0; @@ -3463,7 +3447,7 @@ void select_less_nurb() a= nu->pntsu*nu->pntsv; bp= nu->bp; while(a--) { - if((lastsel==0) && (bp->hide==0) && (bp->f1 & 1)) { + if((lastsel==0) && (bp->hide==0) && (bp->f1 & SELECT)) { if(lastsel!=0) sel= 1; else sel= 0; @@ -3471,14 +3455,14 @@ void select_less_nurb() if(a==nu->pntsu*nu->pntsv-1) sel++; else { bp--; - if((bp->hide==0) && (bp->f1 & 1)) sel++; + if((bp->hide==0) && (bp->f1 & SELECT)) sel++; bp++; } if(a==0) sel++; else { bp++; - if((bp->hide==0) && (bp->f1 & 1)) sel++; + if((bp->hide==0) && (bp->f1 & SELECT)) sel++; bp--; } @@ -3650,7 +3634,7 @@ void delNurb() a= nu->pntsu; if(a) { while(a) { - if( BEZSELECTED(bezt) ); + if( BEZSELECTED_HIDDENHANDLES(bezt) ); else break; a--; bezt++; @@ -3666,7 +3650,7 @@ void delNurb() a= nu->pntsu*nu->pntsv; if(a) { while(a) { - if(bp->f1 & 1 ); + if(bp->f1 & SELECT); else break; a--; bp++; @@ -3687,7 +3671,7 @@ void delNurb() if( (nu->type & 7)==CU_BEZIER ) { bezt= nu->bezt; for(a=0;a<nu->pntsu;a++) { - if( BEZSELECTED(bezt) ) { + if( BEZSELECTED_HIDDENHANDLES(bezt) ) { memcpy(bezt, bezt+1, (nu->pntsu-a-1)*sizeof(BezTriple)); nu->pntsu--; a--; @@ -3708,7 +3692,7 @@ void delNurb() bp= nu->bp; for(a=0;a<nu->pntsu;a++) { - if( bp->f1 & 1 ) { + if( bp->f1 & SELECT ) { memcpy(bp, bp+1, (nu->pntsu-a-1)*sizeof(BPoint)); nu->pntsu--; a--; @@ -3740,14 +3724,14 @@ void delNurb() if( (nu->type & 7)==CU_BEZIER ) { bezt= nu->bezt; for(a=0; a<nu->pntsu-1; a++) { - if( BEZSELECTED(bezt) ) { + if( BEZSELECTED_HIDDENHANDLES(bezt) ) { bezt1= bezt; bezt2= bezt+1; - if( (bezt2->f1 & 1) || (bezt2->f2 & 1) || (bezt2->f3 & 1) ) ; + if( (bezt2->f1 & SELECT) || (bezt2->f2 & SELECT) || (bezt2->f3 & SELECT) ) ; else { /* maybe do not make cyclic */ if(a==0 && (nu->flagu & 1) ) { bezt2= bezt+(nu->pntsu-1); - if( (bezt2->f1 & 1) || (bezt2->f2 & 1) || (bezt2->f3 & 1) ) { + if( (bezt2->f1 & SELECT) || (bezt2->f2 & SELECT) || (bezt2->f3 & SELECT) ) { nu->flagu--; DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA); allqueue(REDRAWVIEW3D, 0); @@ -3767,7 +3751,7 @@ void delNurb() else if(nu->pntsv==1) { bp= nu->bp; for(a=0; a<nu->pntsu-1; a++) { - if( bp->f1 & 1 ) { + if( bp->f1 & SELECT ) { bp1= bp; bp2= bp+1; if( bp2->f1 & 1 ) ; @@ -4056,7 +4040,7 @@ Nurb *addNurbprim(int type, int stype, int newname) (BezTriple*)MEM_callocN(2 * sizeof(BezTriple), "addNurbprim1"); bezt= nu->bezt; bezt->h1= bezt->h2= HD_ALIGN; - bezt->f1= bezt->f2= bezt->f3= 1; + bezt->f1= bezt->f2= bezt->f3= SELECT; bezt->radius = 1.0; for(a=0;a<3;a++) { @@ -4071,7 +4055,7 @@ Nurb *addNurbprim(int type, int stype, int newname) bezt++; bezt->h1= bezt->h2= HD_ALIGN; - bezt->f1= bezt->f2= bezt->f3= 1; + bezt->f1= bezt->f2= bezt->f3= SELECT; bezt->radius = bezt->weight = 1.0; for(a=0;a<3;a++) { @@ -4093,7 +4077,7 @@ Nurb *addNurbprim(int type, int stype, int newname) for(a=0;a<4;a++, bp++) { VECCOPY(bp->vec, cent); bp->vec[3]= 1.0; - bp->f1= 1; + bp->f1= SELECT; bp->radius = bp->weight = 1.0; } @@ -4130,7 +4114,7 @@ Nurb *addNurbprim(int type, int stype, int newname) for(a=0;a<5;a++, bp++) { VECCOPY(bp->vec, cent); bp->vec[3]= 1.0; - bp->f1= 1; + bp->f1= SELECT; bp->radius = bp->weight = 1.0; } @@ -4167,7 +4151,7 @@ Nurb *addNurbprim(int type, int stype, int newname) VECCOPY(bezt->vec[a], cent); } bezt->h1= bezt->h2= HD_AUTO; - bezt->f1= bezt->f2= bezt->f3= 1; + bezt->f1= bezt->f2= bezt->f3= SELECT; bezt->vec[1][0]+= -grid; for(a=0;a<3;a++) Mat3MulVecfl(imat,bezt->vec[a]); bezt->radius = bezt->weight = 1.0; @@ -4177,7 +4161,7 @@ Nurb *addNurbprim(int type, int stype, int newname) VECCOPY(bezt->vec[a], cent); } bezt->h1= bezt->h2= HD_AUTO; - bezt->f1= bezt->f2= bezt->f3= 1; + bezt->f1= bezt->f2= bezt->f3= SELECT; bezt->vec[1][1]+= grid; for(a=0;a<3;a++) Mat3MulVecfl(imat,bezt->vec[a]); bezt->radius = bezt->weight = 1.0; @@ -4187,7 +4171,7 @@ Nurb *addNurbprim(int type, int stype, int newname) VECCOPY(bezt->vec[a], cent); } bezt->h1= bezt->h2= HD_AUTO; - bezt->f1= bezt->f2= bezt->f3= 1; + bezt->f1= bezt->f2= bezt->f3= SELECT; bezt->vec[1][0]+= grid; for(a=0;a<3;a++) Mat3MulVecfl(imat,bezt->vec[a]); bezt->radius = bezt->weight = 1.0; @@ -4197,7 +4181,7 @@ Nurb *addNurbprim(int type, int stype, int newname) VECCOPY(bezt->vec[a], cent); } bezt->h1= bezt->h2= HD_AUTO; - bezt->f1= bezt->f2= bezt->f3= 1; + bezt->f1= bezt->f2= bezt->f3= SELECT; bezt->vec[1][1]+= -grid; for(a=0;a<3;a++) Mat3MulVecfl(imat,bezt->vec[a]); bezt->radius = bezt->weight = 1.0; @@ -4213,7 +4197,7 @@ Nurb *addNurbprim(int type, int stype, int newname) bp= nu->bp; for(a=0; a<8; a++) { - bp->f1= 1; + bp->f1= SELECT; VECCOPY(bp->vec, cent); if(xzproj==0) { @@ -4255,7 +4239,7 @@ Nurb *addNurbprim(int type, int stype, int newname) for(a=0; a<4; a++) { for(b=0; b<4; b++) { VECCOPY(bp->vec, cent); - bp->f1= 1; + bp->f1= SELECT; fac= (float)a -1.5; bp->vec[0]+= fac*grid; fac= (float)b -1.5; @@ -4299,7 +4283,7 @@ Nurb *addNurbprim(int type, int stype, int newname) a= nu->pntsu*nu->pntsv; bp= nu->bp; while(a-- >0) { - bp->f1 |= 1; + bp->f1 |= SELECT; bp++; } } @@ -4322,7 +4306,7 @@ Nurb *addNurbprim(int type, int stype, int newname) bp= nu->bp; for(a=0; a<5; a++) { - bp->f1= 1; + bp->f1= SELECT; VECCOPY(bp->vec, cent); bp->vec[0]+= nurbcircle[a][0]*grid; bp->vec[2]+= nurbcircle[a][1]*grid; @@ -4343,7 +4327,7 @@ Nurb *addNurbprim(int type, int stype, int newname) a= nu->pntsu*nu->pntsv; bp= nu->bp; while(a-- >0) { - bp->f1 |= 1; + bp->f1 |= SELECT; bp++; } BLI_remlink(&editNurb, nu); @@ -4371,7 +4355,7 @@ Nurb *addNurbprim(int type, int stype, int newname) a= nu->pntsu*nu->pntsv; bp= nu->bp; while(a-- >0) { - bp->f1 |= 1; + bp->f1 |= SELECT; bp++; } @@ -4546,7 +4530,7 @@ void clear_tilt() bezt= nu->bezt; a= nu->pntsu; while(a--) { - if(BEZSELECTED(bezt)) bezt->alfa= 0.0; + if(BEZSELECTED_HIDDENHANDLES(bezt)) bezt->alfa= 0.0; bezt++; } } @@ -4554,7 +4538,7 @@ void clear_tilt() bp= nu->bp; a= nu->pntsu*nu->pntsv; while(a--) { - if(bp->f1 & 1) bp->alfa= 0.0; + if(bp->f1 & SELECT) bp->alfa= 0.0; bp++; } } @@ -4582,9 +4566,9 @@ int bezt_compare (const void *e1, const void *e2) /* Check selected flags : Ensures that selected keys will be listed first */ - if ((b1->f2 & 1) && !(b2->f2 & 1)) + if ((b1->f2 & SELECT) && !(b2->f2 & SELECT)) return -1; - if (!(b1->f2 & 1) && (b2->f2 & 1)) + if (!(b1->f2 & SELECT) && (b2->f2 & SELECT)) return 1; return 0; diff --git a/source/blender/src/editimasel.c b/source/blender/src/editimasel.c index d57df3aaccf..cf6a86917b7 100644 --- a/source/blender/src/editimasel.c +++ b/source/blender/src/editimasel.c @@ -859,7 +859,7 @@ void winqreadimaselspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if(val) { if( event!=RETKEY && event!=PADENTER) - if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0; + if( uiDoBlocks(&curarea->uiblocks, event, 1)!=UI_NOTHING ) event= 0; switch(event) { diff --git a/source/blender/src/editipo.c b/source/blender/src/editipo.c index d0442196bb4..54aea493e88 100644 --- a/source/blender/src/editipo.c +++ b/source/blender/src/editipo.c @@ -1273,11 +1273,11 @@ void get_status_editipo(void) b= ei->icu->totvert; while(b--) { if(ei->icu->ipo==IPO_BEZ) { - if(bezt->f1 & 1) totipo_vertsel++; - if(bezt->f3 & 1) totipo_vertsel++; + if(bezt->f1 & SELECT) totipo_vertsel++; + if(bezt->f3 & SELECT) totipo_vertsel++; totipo_vert+= 2; } - if(bezt->f2 & 1) totipo_vertsel++; + if(bezt->f2 & SELECT) totipo_vertsel++; totipo_vert++; bezt++; @@ -1318,14 +1318,14 @@ void update_editipo_flags(void) for(a=0; a<G.sipo->totipo; a++) { if(ik->data[a]) { if(ik->flag & 1) { - ik->data[a]->f1 |= 1; - ik->data[a]->f2 |= 1; - ik->data[a]->f3 |= 1; + ik->data[a]->f1 |= SELECT; + ik->data[a]->f2 |= SELECT; + ik->data[a]->f3 |= SELECT; } else { - ik->data[a]->f1 &= ~1; - ik->data[a]->f2 &= ~1; - ik->data[a]->f3 &= ~1; + ik->data[a]->f1 &= ~SELECT; + ik->data[a]->f2 &= ~SELECT; + ik->data[a]->f3 &= ~SELECT; } } } @@ -1412,7 +1412,7 @@ static short findnearest_ipovert(IpoCurve **icu, BezTriple **bezt) } else temp= abs(mval[0]- sco[1][0])+ abs(mval[1]- sco[1][1]); - if( bezt1->f2 & 1) temp+=5; + if( bezt1->f2 & SELECT) temp+=5; if(temp<dist) { hpoint= 1; *bezt= bezt1; @@ -1514,16 +1514,16 @@ void mouse_select_ipo(void) bezt->f1= bezt->f2= bezt->f3= 0; } else { - bezt->f1= bezt->f2= bezt->f3= 1; + bezt->f1= bezt->f2= bezt->f3= SELECT; } } else if(hand==0) { - if(bezt->f1 & 1) bezt->f1= 0; - else bezt->f1= 1; + if(bezt->f1 & SELECT) bezt->f1= 0; + else bezt->f1= SELECT; } else { - if(bezt->f3 & 1) bezt->f3= 0; - else bezt->f3= 1; + if(bezt->f3 & SELECT) bezt->f3= 0; + else bezt->f3= SELECT; } } } @@ -1532,10 +1532,10 @@ void mouse_select_ipo(void) if(bezt) { if(hand==1) { - bezt->f1|= 1; bezt->f2|= 1; bezt->f3|= 1; + bezt->f1|= SELECT; bezt->f2|= SELECT; bezt->f3|= SELECT; } - else if(hand==0) bezt->f1|= 1; - else bezt->f3|= 1; + else if(hand==0) bezt->f1 |= SELECT; + else bezt->f3 |= SELECT; } } } @@ -3275,7 +3275,7 @@ void common_insertkey(void) /* recalculate bone-paths on adding new keyframe? */ // TODO: currently, there is no setting to turn this on/off globally if (recalc_bonepaths) - pose_calculate_path(ob); + pose_recalculate_paths(ob); allqueue(REDRAWIPO, 0); @@ -3409,7 +3409,7 @@ void add_duplicate_editipo(void) b= icu->totvert; bezt= icu->bezt; while(b--) { - if(bezt->f2 & 1) tot++; + if(bezt->f2 & SELECT) tot++; bezt++; } @@ -3420,7 +3420,7 @@ void add_duplicate_editipo(void) b= icu->totvert-tot; while(b--) { *beztn= *bezt; - if(bezt->f2 & 1) { + if(bezt->f2 & SELECT) { beztn->f1= beztn->f2= beztn->f3= 0; beztn++; *beztn= *bezt; @@ -3474,7 +3474,7 @@ void remove_doubles_ipo(void) while(b--) { /* can we remove? */ - if(mode==2 || (bezt->f2 & 1)) { + if(mode==2 || (bezt->f2 & SELECT)) { /* are the points different? */ if( fabs( bezt->vec[1][0]-newb->vec[1][0] ) > 0.9 ) { @@ -3788,7 +3788,7 @@ void join_ipo(int mode) b= icu->totvert; bezt= icu->bezt; while(b--) { - if(bezt->f2 & 1) tot++; + if(bezt->f2 & SELECT) tot++; bezt++; } @@ -3805,7 +3805,7 @@ void join_ipo(int mode) b= icu->totvert+tot+1; while(b--) { - if(bezt->f2 & 1) { + if(bezt->f2 & SELECT) { if(tot==0) *newb= *bezt; else { VecAddf(newb->vec[0], newb->vec[0], bezt->vec[0]); @@ -3923,7 +3923,7 @@ void ipo_snap(short event) while(a--) { ok= 0; if(totipo_vert) { - if(bezt->f2 & 1) ok= 1; + if(bezt->f2 & SELECT) ok= 1; } else ok= 1; @@ -4033,7 +4033,7 @@ void ipo_mirror(short mode) while(a--) { ok= 0; if(totipo_vert) { - if(bezt->f2 & 1) ok= 1; + if(bezt->f2 & SELECT) ok= 1; } else ok= 1; @@ -4521,7 +4521,7 @@ void add_to_ipokey(ListBase *lb, BezTriple *bezt, int nr, int len) if( ik->val==bezt->vec[1][0] ) { if(ik->data[nr]==0) { /* double points! */ ik->data[nr]= bezt; - if(bezt->f2 & 1) ik->flag= 1; + if(bezt->f2 & SELECT) ik->flag= 1; return; } } @@ -4538,7 +4538,7 @@ void add_to_ipokey(ListBase *lb, BezTriple *bezt, int nr, int len) ikn->data[nr]= bezt; ikn->val= bezt->vec[1][0]; - if(bezt->f2 & 1) ikn->flag= 1; + if(bezt->f2 & SELECT) ikn->flag= 1; } void make_ipokey(void) @@ -4576,7 +4576,7 @@ void make_ipokey(void) for(a=0; a<G.sipo->totipo; a++) { if(ik->data[a]) { bezt= ik->data[a]; - if(bezt->f2 & 1) sel++; + if(bezt->f2 & SELECT) sel++; else desel++; } } @@ -4585,14 +4585,14 @@ void make_ipokey(void) if(ik->data[a]) { bezt= ik->data[a]; if(sel) { - bezt->f1 |= 1; - bezt->f2 |= 1; - bezt->f3 |= 1; + bezt->f1 |= SELECT; + bezt->f2 |= SELECT; + bezt->f3 |= SELECT; } else { - bezt->f1 &= ~1; - bezt->f2 &= ~1; - bezt->f3 &= ~1; + bezt->f1 &= ~SELECT; + bezt->f2 &= ~SELECT; + bezt->f3 &= ~SELECT; } } } @@ -4690,7 +4690,7 @@ void make_ipokey_transform(Object *ob, ListBase *lb, int sel) bezt= icu->bezt; a= icu->totvert; while(a--) { - if(sel==0 || (bezt->f2 & 1)) { + if(sel==0 || (bezt->f2 & SELECT)) { add_to_ipokey(lb, bezt, adrcode, OB_TOTIPO); } bezt++; @@ -5045,14 +5045,14 @@ void make_ipo_transdata (TransInfo *t) for (b=0; b < ei->icu->totvert; b++, bezt++) { /* only include handles if selected, and interpolaton mode uses beztriples */ if (ei->icu->ipo==IPO_BEZ) { - if (bezt->f1 & 1) + if (bezt->f1 & SELECT) bezt_to_transdata(td++, td2d++, bezt->vec[0], bezt->vec[1], 1, onlytime); - if (bezt->f3 & 1) + if (bezt->f3 & SELECT) bezt_to_transdata(td++, td2d++, bezt->vec[2], bezt->vec[1], 1, onlytime); } /* only include main vert if selected */ - if (bezt->f2 & 1) { + if (bezt->f2 & SELECT) { bezt_to_transdata(td++, td2d++, bezt->vec[1], bezt->vec[1], 1, onlytime); } } @@ -5198,7 +5198,7 @@ static void beztmap_to_data (TransInfo *t, EditIpo *ei, BeztMap *bezms, int totv if (totipo_vertsel) { /* only selected verts */ if (ei->icu->ipo==IPO_BEZ) { - if (bezm->bezt->f1 & 1) { + if (bezm->bezt->f1 & SELECT) { if (td->loc2d == bezm->bezt->vec[0]) { if (bezm->swapHs == 1) td->loc2d= (bezts + bezm->newIndex)->vec[2]; @@ -5207,7 +5207,7 @@ static void beztmap_to_data (TransInfo *t, EditIpo *ei, BeztMap *bezms, int totv adjusted[j] = 1; } } - if (bezm->bezt->f3 & 1) { + if (bezm->bezt->f3 & SELECT) { if (td->loc2d == bezm->bezt->vec[2]) { if (bezm->swapHs == 1) td->loc2d= (bezts + bezm->newIndex)->vec[0]; @@ -5217,7 +5217,7 @@ static void beztmap_to_data (TransInfo *t, EditIpo *ei, BeztMap *bezms, int totv } } } - if (bezm->bezt->f2 & 1) { + if (bezm->bezt->f2 & SELECT) { if (td->loc2d == bezm->bezt->vec[1]) { td->loc2d= (bezts + bezm->newIndex)->vec[1]; adjusted[j] = 1; diff --git a/source/blender/src/editipo_lib.c b/source/blender/src/editipo_lib.c index b0d15910d95..41044ad13d7 100644 --- a/source/blender/src/editipo_lib.c +++ b/source/blender/src/editipo_lib.c @@ -299,7 +299,7 @@ void boundbox_ipocurve(IpoCurve *icu, int selectedonly) bezt= icu->bezt; while(a--) { if(icu->vartype & IPO_BITS) { - if((bezt->f2 & 1) || !selectedonly) { + if((bezt->f2 & SELECT) || !selectedonly) { vec[0]= bezt->vec[1][0]; vec[1]= 0.0; DO_MINMAX(vec, min, max); @@ -309,13 +309,13 @@ void boundbox_ipocurve(IpoCurve *icu, int selectedonly) } } else { - if((bezt->f1 & 1) || !selectedonly) { + if((bezt->f1 & SELECT) || !selectedonly) { if(icu->ipo==IPO_BEZ && a!=icu->totvert-1) DO_MINMAX(bezt->vec[0], min, max); } - if((bezt->f2 & 1) || !selectedonly) + if((bezt->f2 & SELECT) || !selectedonly) DO_MINMAX(bezt->vec[1], min, max); - if((bezt->f3 & 1) || !selectedonly) { + if((bezt->f3 & SELECT) || !selectedonly) { if(icu->ipo==IPO_BEZ && a!=0) DO_MINMAX(bezt->vec[2], min, max); } diff --git a/source/blender/src/editipo_mods.c b/source/blender/src/editipo_mods.c index c0fea15ac88..ae283ce8c0b 100644 --- a/source/blender/src/editipo_mods.c +++ b/source/blender/src/editipo_mods.c @@ -139,7 +139,7 @@ void swap_selectall_editipo(void) bezt->f1= bezt->f2= bezt->f3= 0; } else { - bezt->f1= bezt->f2= bezt->f3= 1; + bezt->f1= bezt->f2= bezt->f3= SELECT; } bezt++; } @@ -375,32 +375,32 @@ static int selected_bezier_loop(int (*looptest)(EditIpo *), int select_bezier_add(BezTriple *bezt) { /* Select the bezier triple */ - bezt->f1 |= 1; - bezt->f2 |= 1; - bezt->f3 |= 1; + bezt->f1 |= SELECT; + bezt->f2 |= SELECT; + bezt->f3 |= SELECT; return 0; } int select_bezier_subtract(BezTriple *bezt) { /* Deselect the bezier triple */ - bezt->f1 &= ~1; - bezt->f2 &= ~1; - bezt->f3 &= ~1; + bezt->f1 &= ~SELECT; + bezt->f2 &= ~SELECT; + bezt->f3 &= ~SELECT; return 0; } int select_bezier_invert(BezTriple *bezt) { /* Invert the selection for the bezier triple */ - bezt->f2 ^= 1; - if ( bezt->f2 & 1 ) { - bezt->f1 |= 1; - bezt->f3 |= 1; + bezt->f2 ^= SELECT; + if ( bezt->f2 & SELECT ) { + bezt->f1 |= SELECT; + bezt->f3 |= SELECT; } else { - bezt->f1 &= ~1; - bezt->f3 &= ~1; + bezt->f1 &= ~SELECT; + bezt->f3 &= ~SELECT; } return 0; } @@ -723,6 +723,53 @@ void mirror_ipo_keys(Ipo *ipo, short mirror_type) } } +/* This function is called to calculate the average location of the + * selected keyframes, and place the current frame at that location. + * + * It must be called like so: + * snap_cfra_ipo_keys(NULL, -1); // initialise the static vars first + * for (ipo...) snap_cfra_ipo_keys(ipo, 0); // sum up keyframe times + * snap_cfra_ipo_keys(NULL, 1); // set current frame after taking average + */ +void snap_cfra_ipo_keys(Ipo *ipo, short mode) +{ + static int cfra; + static int tot; + + IpoCurve *icu; + BezTriple *bezt; + int a; + + + if (mode == -1) { + /* initialise a new snap-operation */ + cfra= 0; + tot= 0; + } + else if (mode == 1) { + /* set current frame - using average frame */ + if (tot != 0) + CFRA = cfra / tot; + } + else { + /* loop through keys in ipo, summing the frame + * numbers of those that are selected + */ + if (ipo == NULL) + return; + + for (icu= ipo->curve.first; icu; icu= icu->next) { + for (a=0, bezt=icu->bezt; a < icu->totvert; a++, bezt++) { + if (BEZSELECTED(bezt)) { + cfra += bezt->vec[1][0]; + tot++; + } + } + } + } +} + + /* currently only used by some action editor tools, but may soon get used by ipo editor */ /* restore = whether to map points back to ipo-time * only_keys = whether to only adjust the location of the center point of beztriples @@ -976,11 +1023,11 @@ void borderselect_ipo(void) int bit= (val==LEFTMOUSE); if(BLI_in_rctf(&rectf, bezt->vec[0][0], bezt->vec[0][1])) - bezt->f1 = (bezt->f1&~1) | bit; + bezt->f1 = (bezt->f1&~SELECT) | bit; if(BLI_in_rctf(&rectf, bezt->vec[1][0], bezt->vec[1][1])) - bezt->f2 = (bezt->f2&~1) | bit; + bezt->f2 = (bezt->f2&~SELECT) | bit; if(BLI_in_rctf(&rectf, bezt->vec[2][0], bezt->vec[2][1])) - bezt->f3 = (bezt->f3&~1) | bit; + bezt->f3 = (bezt->f3&~SELECT) | bit; bezt++; } diff --git a/source/blender/src/editlattice.c b/source/blender/src/editlattice.c index 9aa363a654f..f3073cf886a 100644 --- a/source/blender/src/editlattice.c +++ b/source/blender/src/editlattice.c @@ -240,7 +240,7 @@ static void findnearestLattvert__doClosest(void *userData, BPoint *bp, int x, in struct { BPoint *bp; short dist, select, mval[2]; } *data = userData; float temp = abs(data->mval[0]-x) + abs(data->mval[1]-y); - if ((bp->f1&1)==data->select) temp += 5; + if ((bp->f1 & SELECT)==data->select) temp += 5; if (temp<data->dist) { data->dist = temp; @@ -274,17 +274,13 @@ void mouse_lattice(void) if((G.qual & LR_SHIFTKEY)==0) { setflagsLatt(0); - bp->f1 |= 1; + bp->f1 |= SELECT; allqueue(REDRAWVIEW3D, 0); } else { - - if(bp->f1 & 1) bp->f1 &= ~1; - else bp->f1 |= 1; - + bp->f1 ^= SELECT; /* swap */ allqueue(REDRAWVIEW3D, 0); - } countall(); diff --git a/source/blender/src/editmesh_mods.c b/source/blender/src/editmesh_mods.c index a74bd851aeb..b165a141daa 100644 --- a/source/blender/src/editmesh_mods.c +++ b/source/blender/src/editmesh_mods.c @@ -714,7 +714,7 @@ static void unified_select_draw(EditVert *eve, EditEdge *eed, EditFace *efa) } } - if(G.scene->selectmode & SCE_SELECT_FACE && (G.vd->drawtype!=OB_TEXTURE)) { + if( CHECK_OB_DRAWFACEDOT(G.scene, G.vd, G.obedit->dt) ) { if(efa->fgonf==0) { glPointSize(BIF_GetThemeValuef(TH_FACEDOT_SIZE)); BIF_ThemeColor((efa->f & SELECT)?TH_FACE_DOT:TH_WIRE); diff --git a/source/blender/src/editnla.c b/source/blender/src/editnla.c index ec3b1c834e5..fc79c265f8d 100644 --- a/source/blender/src/editnla.c +++ b/source/blender/src/editnla.c @@ -198,11 +198,12 @@ void synchronize_action_strips(void) calc_action_range(strip->act, &actstart, &actend, 1); - if(strip->actstart!=actstart || strip->actend!=actend) { - float mapping= (strip->end - strip->start)/(strip->actend - strip->actstart); + if ((strip->actstart!=actstart) || (strip->actend!=actend)) { + float offset = strip->scale * (actstart - strip->actstart); + float actlen = actend - actstart; - strip->start+= mapping*(actstart - strip->actstart); - strip->end+= mapping*(actend - strip->actend); + strip->start += offset; + strip->end = (strip->scale * strip->repeat * actlen) + strip->start; strip->actstart= actstart; strip->actend= actend; @@ -371,15 +372,41 @@ void reset_action_strips(int val) for (strip = base->object->nlastrips.last; strip; strip=strip->prev) { if (strip->flag & ACTSTRIP_SELECT) { - if(val==2) { - calc_action_range(strip->act, &strip->actstart, &strip->actend, 1); - } - else if(val==1) { - float mapping= (strip->actend - strip->actstart)/(strip->end - strip->start); - - strip->end= strip->start + mapping*(strip->end - strip->start); + switch (val) { + case 1: + { + /* clear scaling - reset to 1.0 without touching keys */ + float actlen= (strip->actend - strip->actstart); + + strip->scale= 1.0f; + strip->end= (strip->repeat * actlen) + strip->start; + } + break; + case 2: + { + /* reset action-range */ + calc_action_range(strip->act, &strip->actstart, &strip->actend, 1); + } + break; + case 3: + { + /* apply scale to keys - scale is reset to 1.0f, but keys stay at the same times */ + bActionChannel *achan; + + if (strip->act) { + for (achan= strip->act->chanbase.first; achan; achan= achan->next) { + actstrip_map_ipo_keys(base->object, achan->ipo, 0, 0); + } + + /* now we can reset scale */ + calc_action_range(strip->act, &strip->actstart, &strip->actend, 1); + strip->scale= 1.0f; + strip->end = (strip->repeat * (strip->actend - strip->actstart)) + strip->start; + } + } + break; } - base->object->ctime= -1234567.0f; // eveil! + base->object->ctime= -1234567.0f; // evil! DAG_object_flush_update(G.scene, base->object, OB_RECALC_OB|OB_RECALC_DATA); } } @@ -1690,7 +1717,7 @@ void winqreadnlaspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if (!snla) return; if(val) { - if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0; + if( uiDoBlocks(&curarea->uiblocks, event, 1)!=UI_NOTHING ) event= 0; /* swap mouse buttons based on user preference */ if (U.flag & USER_LMOUSESELECT) { @@ -1849,14 +1876,12 @@ void winqreadnlaspace(ScrArea *sa, void *spacedata, BWinEvent *evt) break; case SKEY: - if(G.qual==LR_ALTKEY) { - val= pupmenu("Action Strip Scale%t|Clear Strip Scale%x1|Remap Start/End%x2"); - if(val==1) - reset_action_strips(1); - else if(val==2) - reset_action_strips(2); + if (G.qual==LR_ALTKEY) { + val= pupmenu("Action Strip Scale%t|Reset Strip Scale%x1|Remap Action Start/End%x2|Apply Scale%x3"); + if (val > 0) + reset_action_strips(val); } - else if(G.qual & LR_SHIFTKEY) { + else if (G.qual & LR_SHIFTKEY) { if (snla->flag & SNLA_DRAWTIME) val= pupmenu("Snap To%t|Nearest Second%x3|Current Time%x2"); else diff --git a/source/blender/src/editnode.c b/source/blender/src/editnode.c index e5e83152ae2..a14b0ccc389 100644 --- a/source/blender/src/editnode.c +++ b/source/blender/src/editnode.c @@ -1427,7 +1427,7 @@ void snode_autoconnect(SpaceNode *snode, bNode *node_to, int flag) bNode *node, *nodefrom[8]; int totsock= 0, socktype=0; - if(node_to->inputs.first==NULL) + if(node_to==NULL || node_to->inputs.first==NULL) return; /* no inputs for node allowed (code it) */ @@ -2073,7 +2073,7 @@ static int node_uiDoBlocks(ScrArea *sa, short event) ((struct Link *)block)->next= NULL; lb->first= lb->last= block; - retval= uiDoBlocks(lb, event); + retval= uiDoBlocks(lb, event, 1); ((struct Link *)block)->prev= prev; ((struct Link *)block)->next= next; diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index 597e1515499..134794b8d30 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -1161,7 +1161,7 @@ void make_vertex_parent(void) bezt= nu->bezt; a= nu->pntsu; while(a--) { - if(BEZSELECTED(bezt)) { + if(BEZSELECTED_HIDDENHANDLES(bezt)) { if(v1==0) v1= nr; else if(v2==0) v2= nr; else if(v3==0) v3= nr; @@ -2827,44 +2827,51 @@ void convertmenu(void) * level==-1 then toggle subsurf, else set to level. * *set allows to toggle multiple selections */ -static void object_flip_subdivison(Object *ob, int *set, int level, int mode) +static void object_flip_subdivison(Object *ob, int *set, int level, int mode, int ingroup) { ModifierData *md; - if(ob->type!=OB_MESH) - return; - - md = modifiers_findByType(ob, eModifierType_Subsurf); - - if (md) { - SubsurfModifierData *smd = (SubsurfModifierData*) md; - - if (level == -1) { - if(*set == -1) - *set= smd->modifier.mode&(mode); - - if (*set) { - smd->modifier.mode &= ~(mode); + if(ob->type==OB_MESH) { + md = modifiers_findByType(ob, eModifierType_Subsurf); + + if (md) { + SubsurfModifierData *smd = (SubsurfModifierData*) md; + + if (level == -1) { + if(*set == -1) + *set= smd->modifier.mode&(mode); + + if (*set) { + smd->modifier.mode &= ~(mode); + } else { + smd->modifier.mode |= (mode); + } } else { - smd->modifier.mode |= (mode); + smd->levels = level; } - } else { - smd->levels = level; - } - } - else if(*set != 0) { - SubsurfModifierData *smd = (SubsurfModifierData*) modifier_new(eModifierType_Subsurf); + } + else if(!ingroup && *set != 0) { + SubsurfModifierData *smd = (SubsurfModifierData*) modifier_new(eModifierType_Subsurf); - BLI_addtail(&ob->modifiers, smd); + BLI_addtail(&ob->modifiers, smd); - if (level!=-1) { - smd->levels = level; + if (level!=-1) { + smd->levels = level; + } + + if(*set == -1) + *set= 1; } - - if(*set == -1) - *set= 1; + + ob->recalc |= OB_RECALC_DATA; + } + + if(ob->dup_group) { + GroupObject *go; + + for(go= ob->dup_group->gobject.first; go; go= go->next) + object_flip_subdivison(go->ob, set, level, mode, 1); } - ob->recalc |= OB_RECALC_DATA; } /* Change subdivision properties of mesh object ob, if @@ -2882,16 +2889,9 @@ void flip_subdivison(int level) else mode= eModifierMode_Render|eModifierMode_Realtime; - for(base= G.scene->base.first; base; base= base->next) { - if(((level==-1) && (TESTBASE(base))) || (TESTBASELIB(base))) { - object_flip_subdivison(base->object, &set, level, mode); - if(base->object->dup_group) { - GroupObject *go; - for(go= base->object->dup_group->gobject.first; go; go= go->next) - object_flip_subdivison(go->ob, &set, level, mode); - } - } - } + for(base= G.scene->base.first; base; base= base->next) + if(((level==-1) && (TESTBASE(base))) || (TESTBASELIB(base))) + object_flip_subdivison(base->object, &set, level, mode, 0); countall(); allqueue(REDRAWVIEW3D, 0); diff --git a/source/blender/src/editparticle.c b/source/blender/src/editparticle.c index c9cf745fa44..411a45d0a53 100644 --- a/source/blender/src/editparticle.c +++ b/source/blender/src/editparticle.c @@ -56,6 +56,7 @@ #include "BKE_global.h" #include "BKE_object.h" +#include "BKE_mesh.h" #include "BKE_modifier.h" #include "BKE_particle.h" #include "BKE_scene.h" @@ -133,7 +134,7 @@ void PE_free_particle_edit(ParticleSystem *psys) /************************************************/ /* Edit Mode Helpers */ /************************************************/ -static int PE_can_edit(ParticleSystem *psys) +int PE_can_edit(ParticleSystem *psys) { return (psys && psys->edit && (G.f & G_PARTICLEEDIT)); } @@ -155,9 +156,12 @@ void PE_change_act(void *ob_v, void *act_v) if(act>=0){ if((psys=BLI_findlink(&ob->particlesystem,act))) { psys->flag |= PSYS_CURRENT; - if(G.f & G_PARTICLEEDIT && !psys->edit) - PE_create_particle_edit(ob, psys); - PE_recalc_world_cos(ob, psys); + + if(psys->flag & PSYS_ENABLED) { + if(G.f & G_PARTICLEEDIT && !psys->edit) + PE_create_particle_edit(ob, psys); + PE_recalc_world_cos(ob, psys); + } } } } @@ -182,7 +186,7 @@ ParticleSystem *PE_get_current(Object *ob) psys->flag |= PSYS_CURRENT; } - if(psys && ob == OBACT && (G.f & G_PARTICLEEDIT)) + if(psys && (psys->flag & PSYS_ENABLED) && ob == OBACT && (G.f & G_PARTICLEEDIT)) if(psys->part->type == PART_HAIR && psys->flag & PSYS_EDITED) if(psys->edit == NULL) PE_create_particle_edit(ob, psys); @@ -546,7 +550,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys) /* insert particles into kd tree */ LOOP_PARTICLES(i,pa) { - psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, pa, mat); + psys_mat_hair_to_orco(ob, psmd->dm, psys->part->from, pa, mat); VECCOPY(co, pa->hair[0].co); Mat4MulVecfl(mat, co); BLI_kdtree_insert(tree, i, co, NULL); @@ -557,9 +561,9 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys) /* lookup particles and set in mirror cache */ if(!edit->mirror_cache) edit->mirror_cache= MEM_callocN(sizeof(int)*totpart, "PE mirror cache"); - + LOOP_PARTICLES(i,pa) { - psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, pa, mat); + psys_mat_hair_to_orco(ob, psmd->dm, psys->part->from, pa, mat); VECCOPY(co, pa->hair[0].co); Mat4MulVecfl(mat, co); co[0]= -co[0]; @@ -596,11 +600,11 @@ static void PE_mirror_particle(Object *ob, DerivedMesh *dm, ParticleSystem *psys edit= psys->edit; i= pa - psys->particles; + if(!edit->mirror_cache) + PE_update_mirror_cache(ob, psys); + /* find mirrored particle if needed */ if(!mpa) { - if(!edit->mirror_cache) - PE_update_mirror_cache(ob, psys); - mi= edit->mirror_cache[i]; if(mi == -1) return; @@ -628,8 +632,8 @@ static void PE_mirror_particle(Object *ob, DerivedMesh *dm, ParticleSystem *psys } /* mirror positions and tags */ - psys_mat_hair_to_object(ob, dm, psys->part->from, pa, mat); - psys_mat_hair_to_object(ob, dm, psys->part->from, mpa, mmat); + psys_mat_hair_to_orco(ob, dm, psys->part->from, pa, mat); + psys_mat_hair_to_orco(ob, dm, psys->part->from, mpa, mmat); Mat4Invert(immat, mmat); hkey=pa->hair; @@ -1098,9 +1102,11 @@ void PE_set_particle_edit(void) if((G.f & G_PARTICLEEDIT)==0){ if(psys && psys->part->type == PART_HAIR && psys->flag & PSYS_EDITED) { - if(psys->edit==0) - PE_create_particle_edit(ob, psys); - PE_recalc_world_cos(ob, psys); + if(psys->flag & PSYS_ENABLED) { + if(psys->edit==0) + PE_create_particle_edit(ob, psys); + PE_recalc_world_cos(ob, psys); + } } G.f |= G_PARTICLEEDIT; @@ -2272,7 +2278,7 @@ static void brush_add(Object *ob, ParticleSystem *psys, short *mval, short numbe tree=BLI_kdtree_new(psys->totpart); for(i=0, pa=psys->particles; i<totpart; i++, pa++) { - psys_particle_on_dm(ob,psmd->dm,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,cur_co,0,0,0); + psys_particle_on_dm(ob,psmd->dm,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,cur_co,0,0,0,0,0); BLI_kdtree_insert(tree, i, cur_co, NULL); } @@ -2311,7 +2317,7 @@ static void brush_add(Object *ob, ParticleSystem *psys, short *mval, short numbe int w, maxw; float maxd, mind, dd, totw=0.0, weight[3]; - psys_particle_on_dm(ob,psmd->dm,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co1,0,0,0); + psys_particle_on_dm(ob,psmd->dm,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co1,0,0,0,0,0); maxw = BLI_kdtree_find_n_nearest(tree,3,co1,NULL,ptn); maxd = ptn[maxw-1].dist; @@ -2582,6 +2588,7 @@ int PE_brush_particles(void) if(pset->brushtype == PE_BRUSH_ADD && (pset->flag & PE_X_MIRROR)) PE_mirror_x(1); PE_recalc_world_cos(ob,psys); + psys_free_path_cache(psys); DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); } else @@ -2768,6 +2775,21 @@ void PE_mirror_x(int tagged) } } +void PE_selectbrush_menu(void) +{ + ParticleEditSettings *pset= PE_settings(); + int val; + + pupmenu_set_active(pset->brushtype); + + val= pupmenu("Select Brush%t|None %x0|Comb %x1|Smooth %x7|Weight %x6|Add %x5|Length %x3|Puff %x4|Cut %x2"); + + if(val>=0) { + pset->brushtype= val-1; + allqueue(REDRAWVIEW3D, 1); + } +} + /************************************************/ /* Particle Edit Undo */ /************************************************/ diff --git a/source/blender/src/editscreen.c b/source/blender/src/editscreen.c index da6884d4394..b843d820ba5 100644 --- a/source/blender/src/editscreen.c +++ b/source/blender/src/editscreen.c @@ -531,7 +531,7 @@ static void scrarea_dispatch_header_events(ScrArea *sa) while(bwin_qread(sa->headwin, &evt)) { if(evt.val) { - if( uiDoBlocks(&curarea->uiblocks, evt.event)!=UI_NOTHING ) evt.event= 0; + if( uiDoBlocks(&curarea->uiblocks, evt.event, 1)!=UI_NOTHING ) evt.event= 0; switch(evt.event) { case UI_BUT_EVENT: diff --git a/source/blender/src/editseq.c b/source/blender/src/editseq.c index 27ee7a14315..75ac58285a2 100644 --- a/source/blender/src/editseq.c +++ b/source/blender/src/editseq.c @@ -114,6 +114,15 @@ char last_sounddir[FILE_MAXDIR+FILE_MAXFILE]= ""; static int test_overlap_seq(Sequence *); static void shuffle_seq(Sequence *); +typedef struct TransSeq { + int start, machine; + int startstill, endstill; + int startdisp, enddisp; + int startofs, endofs; + int final_left, final_right; + int len; +} TransSeq; + Sequence *get_last_seq() { if(!_last_seq_init) { @@ -325,6 +334,16 @@ int sequence_is_free_transformable(Sequence * seq) || (get_sequence_effect_num_inputs(seq->type) == 0); } +char mouse_cfra_side( int frame ) { + short mval[2]; + float xmouse, ymouse; + getmouseco_areawin(mval); + + /* choose the side based on which side of the playhead the mouse is on */ + areamouseco_to_ipoco(G.v2d, mval, &xmouse, &ymouse); + return (xmouse > frame) ? 'R' : 'L'; +} + Sequence *find_neighboring_sequence(Sequence *test, int lr, int sel) { /* looks to the left on lr==1, to the right on lr==2 sel - 0==unselected, 1==selected, -1==done care*/ @@ -2147,139 +2166,274 @@ void del_seq(void) allqueue(REDRAWSEQ, 0); } +static Sequence *dupli_seq(Sequence *seq) { + Sequence *seqn = NULL; + + if(seq->type==SEQ_META) { + seqn= MEM_dupallocN(seq); + seq->tmp= seqn; + + seqn->strip= MEM_dupallocN(seq->strip); + seqn->strip->stripdata = 0; + seqn->strip->tstripdata = 0; + + seqn->seqbase.first= seqn->seqbase.last= 0; + /* WATCH OUT!!! - This metastrip is not recursively duplicated here - do this after!!! */ + /* - recurs_dupli_seq(&seq->seqbase,&seqn->seqbase);*/ + } + else if(seq->type == SEQ_SCENE) { + seqn= MEM_dupallocN(seq); + seq->tmp= seqn; + + seqn->strip= MEM_dupallocN(seq->strip); + seqn->strip->stripdata = 0; + seqn->strip->tstripdata = 0; + } + else if(seq->type == SEQ_MOVIE) { + seqn= MEM_dupallocN(seq); + seq->tmp= seqn; + + seqn->strip= MEM_dupallocN(seq->strip); + seqn->strip->stripdata = + MEM_dupallocN(seq->strip->stripdata); + seqn->strip->tstripdata = 0; + seqn->anim= 0; + } + else if(seq->type == SEQ_RAM_SOUND) { + seqn= MEM_dupallocN(seq); + seq->tmp= seqn; + + seqn->strip= MEM_dupallocN(seq->strip); + seqn->strip->stripdata = + MEM_dupallocN(seq->strip->stripdata); + seqn->strip->tstripdata = 0; + + seqn->anim= 0; + seqn->sound->id.us++; + if(seqn->ipo) seqn->ipo->id.us++; + } + else if(seq->type == SEQ_HD_SOUND) { + seqn= MEM_dupallocN(seq); + seq->tmp= seqn; + + seqn->strip= MEM_dupallocN(seq->strip); + seqn->strip->stripdata = + MEM_dupallocN(seq->strip->stripdata); + seqn->strip->tstripdata = 0; + seqn->anim= 0; + seqn->hdaudio = 0; + if(seqn->ipo) seqn->ipo->id.us++; + } else if(seq->type == SEQ_IMAGE) { + seqn= MEM_dupallocN(seq); + seq->tmp= seqn; + + seqn->strip= MEM_dupallocN(seq->strip); + seqn->strip->stripdata = + MEM_dupallocN(seq->strip->stripdata); + seqn->strip->tstripdata = 0; + } else if(seq->type >= SEQ_EFFECT) { + seqn= MEM_dupallocN(seq); + seq->tmp= seqn; + + if(seq->seq1 && seq->seq1->tmp) seqn->seq1= seq->seq1->tmp; + if(seq->seq2 && seq->seq2->tmp) seqn->seq2= seq->seq2->tmp; + if(seq->seq3 && seq->seq3->tmp) seqn->seq3= seq->seq3->tmp; + + if(seqn->ipo) seqn->ipo->id.us++; + + if (seq->type & SEQ_EFFECT) { + struct SeqEffectHandle sh; + sh = get_sequence_effect(seq); + if(sh.copy) + sh.copy(seq, seqn); + } + + seqn->strip= MEM_dupallocN(seq->strip); + seqn->strip->stripdata = 0; + seqn->strip->tstripdata = 0; + + } else { + fprintf(stderr, "Aiiiiekkk! sequence type not " + "handled in duplicate!\nExpect a crash" + " now...\n"); + } + + return seqn; +} + static void recurs_dupli_seq(ListBase *old, ListBase *new) { Sequence *seq; Sequence *seqn = 0; Sequence *last_seq = get_last_seq(); - seq= old->first; - - while(seq) { + for(seq= old->first; seq; seq= seq->next) { seq->tmp= NULL; if(seq->flag & SELECT) { - if(seq->type==SEQ_META) { - seqn= MEM_dupallocN(seq); - seq->tmp= seqn; - BLI_addtail(new, seqn); - - seqn->strip= MEM_dupallocN(seq->strip); - seqn->strip->stripdata = 0; - seqn->strip->tstripdata = 0; - - seq->flag &= SEQ_DESEL; - seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL); - - seqn->seqbase.first= seqn->seqbase.last= 0; - recurs_dupli_seq(&seq->seqbase,&seqn->seqbase); - - } - else if(seq->type == SEQ_SCENE) { - seqn= MEM_dupallocN(seq); - seq->tmp= seqn; - BLI_addtail(new, seqn); - - seqn->strip= MEM_dupallocN(seq->strip); - seqn->strip->stripdata = 0; - seqn->strip->tstripdata = 0; - + seqn = dupli_seq(seq); + if (seqn) { /*should never fail */ seq->flag &= SEQ_DESEL; seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL); - } - else if(seq->type == SEQ_MOVIE) { - seqn= MEM_dupallocN(seq); - seq->tmp= seqn; + BLI_addtail(new, seqn); - - seqn->strip= MEM_dupallocN(seq->strip); - seqn->strip->stripdata = - MEM_dupallocN(seq->strip->stripdata); - seqn->strip->tstripdata = 0; - seqn->anim= 0; - - seq->flag &= SEQ_DESEL; - seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL); + if(seq->type==SEQ_META) + recurs_dupli_seq(&seq->seqbase,&seqn->seqbase); + + if (seq == last_seq) { + set_last_seq(seqn); + } } - else if(seq->type == SEQ_RAM_SOUND) { - seqn= MEM_dupallocN(seq); - seq->tmp= seqn; - BLI_addtail(new, seqn); - - seqn->strip= MEM_dupallocN(seq->strip); - seqn->strip->stripdata = - MEM_dupallocN(seq->strip->stripdata); - seqn->strip->tstripdata = 0; + } + } +} - seqn->anim= 0; - seqn->sound->id.us++; - if(seqn->ipo) seqn->ipo->id.us++; +/* like duplicate, but only duplicate and cut overlapping strips, + * strips to the left of the cutframe are ignored and strips to the right are moved into the new list */ +static void recurs_cut_seq(ListBase *old, ListBase *new, int cutframe) +{ + Sequence *seq, *seq_next; + Sequence *seqn = 0; + + TransSeq ts; - seq->flag &= SEQ_DESEL; - seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL); + seq= old->first; + + while(seq) { + seq_next = seq->next; /* we need this because we may remove seq */ + + seq->tmp= NULL; + if(seq->flag & SELECT) { + if(cutframe > seq->startdisp && cutframe < seq->enddisp) { + + /* backup values */ + ts.start= seq->start; + ts.machine= seq->machine; + ts.startstill= seq->startstill; + ts.endstill= seq->endstill; + ts.startdisp= seq->startdisp; + ts.enddisp= seq->enddisp; + ts.startofs= seq->startofs; + ts.endofs= seq->endofs; + ts.len= seq->len; + + /* First Strip! */ + /* strips with extended stillfames before */ + if(seq->type!=SEQ_META) { + + if ((seq->startstill) && (cutframe <seq->start)) { + seq->start= cutframe -1; + seq->startstill= cutframe -seq->startdisp -1; + seq->len= 1; + seq->endstill= 0; + } + + /* normal strip */ + else if ((cutframe >=seq->start)&&(cutframe <=(seq->start+seq->len))) { + seq->endofs = (seq->start+seq->len) - cutframe; + } + + /* strips with extended stillframes after */ + else if (((seq->start+seq->len) < cutframe) && (seq->endstill)) { + seq->endstill -= seq->enddisp - cutframe; + } + + calc_sequence(seq); + } + + /* Duplicate AFTER the first change */ + seqn = dupli_seq(seq); + + if (seqn) { /* should never fail */ + seqn->flag |= SELECT; + + + BLI_addtail(new, seqn); + + /* dont transform meta's - just do their children then recalc */ + if(seq->type==SEQ_META) { + recurs_cut_seq(&seq->seqbase,&seqn->seqbase, cutframe); + } else { + /* Second Strip! */ + /* strips with extended stillframes before */ + if ((seqn->startstill) && (cutframe == seqn->start + 1)) { + seqn->start = ts.start; + seqn->startstill= ts.start- cutframe; + seqn->len = ts.len; + seqn->endstill = ts.endstill; + } + + /* normal strip */ + else if ((cutframe>=seqn->start)&&(cutframe<=(seqn->start+seqn->len))) { + seqn->startstill = 0; + seqn->startofs = cutframe - ts.start; + seqn->endofs = ts.endofs; + seqn->endstill = ts.endstill; + } + + /* strips with extended stillframes after */ + else if (((seqn->start+seqn->len) < cutframe) && (seqn->endstill)) { + seqn->start = cutframe - ts.len +1; + seqn->startofs = ts.len-1; + seqn->endstill = ts.enddisp - cutframe -1; + seqn->startstill = 0; + } + } + + if(seq->type==SEQ_META) /* account for strips within changing */ + calc_sequence(seq); + + calc_sequence(seqn); + } + } else if (seq->enddisp <= cutframe) { + /* do nothing */ + } else if (seq->startdisp >= cutframe) { + /* move into new list */ + BLI_remlink(old, seq); + BLI_addtail(new, seq); } - else if(seq->type == SEQ_HD_SOUND) { - seqn= MEM_dupallocN(seq); - seq->tmp= seqn; - BLI_addtail(new, seqn); - - seqn->strip= MEM_dupallocN(seq->strip); - seqn->strip->stripdata = - MEM_dupallocN(seq->strip->stripdata); - seqn->strip->tstripdata = 0; - seqn->anim= 0; - seqn->hdaudio = 0; - if(seqn->ipo) seqn->ipo->id.us++; - - seq->flag &= SEQ_DESEL; - seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL); - } else if(seq->type == SEQ_IMAGE) { - seqn= MEM_dupallocN(seq); - seq->tmp= seqn; - BLI_addtail(new, seqn); - - seqn->strip= MEM_dupallocN(seq->strip); - seqn->strip->stripdata = - MEM_dupallocN(seq->strip->stripdata); - seqn->strip->tstripdata = 0; - - seq->flag &= SEQ_DESEL; - - seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL); - } else if(seq->type >= SEQ_EFFECT) { - seqn= MEM_dupallocN(seq); - seq->tmp= seqn; - BLI_addtail(new, seqn); - - if(seq->seq1 && seq->seq1->tmp) seqn->seq1= seq->seq1->tmp; - if(seq->seq2 && seq->seq2->tmp) seqn->seq2= seq->seq2->tmp; - if(seq->seq3 && seq->seq3->tmp) seqn->seq3= seq->seq3->tmp; - - if(seqn->ipo) seqn->ipo->id.us++; + } + seq = seq_next; + } +} - if (seq->type & SEQ_EFFECT) { - struct SeqEffectHandle sh; - sh = get_sequence_effect(seq); - if(sh.copy) - sh.copy(seq, seqn); +void seq_cut(int cutframe) +{ + Editing *ed; + ListBase newlist; + char side; + ed= G.scene->ed; + if(ed==0) return; + + newlist.first= newlist.last= NULL; + + recurs_cut_seq(ed->seqbasep, &newlist, cutframe); + + if (newlist.first) { /* simple check to see if anything was done */ + Sequence *seq; + addlisttolist(ed->seqbasep, &newlist); + + + /* change the selection, not strictly needed but nice */ + side = mouse_cfra_side(cutframe); + + WHILE_SEQ(ed->seqbasep) { + if (side=='L') { + if ( seq->startdisp >= cutframe ) { + seq->flag &= ~SELECT; } - - seqn->strip= MEM_dupallocN(seq->strip); - seqn->strip->stripdata = 0; - seqn->strip->tstripdata = 0; - - seq->flag &= SEQ_DESEL; - - seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL); } else { - fprintf(stderr, "Aiiiiekkk! sequence type not " - "handled in duplicate!\nExpect a crash" - " now...\n"); - } - if (seq == last_seq) { - set_last_seq(seqn); + if ( seq->enddisp <= cutframe ) { + seq->flag &= ~SELECT; + } } } - seq= seq->next; + END_SEQ; + + /* as last: */ + sort_seq(); + + allqueue(REDRAWSEQ, 0); + BIF_undo_push("Cut Strips, Sequencer"); } } @@ -2524,7 +2678,9 @@ void make_meta(void) seqm->strip->us= 1; set_meta_stripdata(seqm); - + + if( test_overlap_seq(seqm) ) shuffle_seq(seqm); + BIF_undo_push("Make Meta Strip, Sequencer"); allqueue(REDRAWSEQ, 0); } @@ -2663,15 +2819,6 @@ static int seq_get_snaplimit(void) return (int)(x - xmouse); } -typedef struct TransSeq { - int start, machine; - int startstill, endstill; - int startdisp, enddisp; - int startofs, endofs; - int final_left, final_right; - int len; -} TransSeq; - /* use to impose limits when dragging/extending - so impossible situations dont happen */ static void transform_grab_xlimits(Sequence *seq, int leftflag, int rightflag) { @@ -2749,6 +2896,8 @@ void transform_seq(int mode, int context) int *oldframe = NULL, totmark=0, a; TimeMarker *marker; + /* looping on sequences, WHILE_SEQ macro allocates memory each time */ + int totseq_index, seq_index; Sequence **seqar; if(mode!='g' && mode!='e') return; /* from gesture */ @@ -2756,18 +2905,23 @@ void transform_seq(int mode, int context) ed= G.scene->ed; if(ed==0) return; - WHILE_SEQ(ed->seqbasep) { + /* Build the sequence array once, be sure to free it */ + build_seqar( ed->seqbasep, &seqar, &totseq_index ); + + for(seq_index=0, seq=seqar[0]; seq_index < totseq_index; seq=seqar[++seq_index]) { if(seq->flag & SELECT) totstrip++; } - END_SEQ - if (sseq->flag & SEQ_MARKER_TRANS) { for(marker= G.scene->markers.first; marker; marker= marker->next) { if(marker->flag & SELECT) totmark++; } } - if(totstrip==0 && totmark==0) return; + + if(totstrip==0 && totmark==0) { + if(seqar) MEM_freeN(seqar); + return; + } G.moving= 1; @@ -2775,8 +2929,7 @@ void transform_seq(int mode, int context) ts=transmain= MEM_callocN(totstrip*sizeof(TransSeq), "transseq"); - WHILE_SEQ(ed->seqbasep) { - + for(seq_index=0, seq=seqar[0]; seq_index < totseq_index; seq=seqar[++seq_index]) { if(seq->flag & SELECT) { ts->start= seq->start; ts->machine= seq->machine; @@ -2793,16 +2946,12 @@ void transform_seq(int mode, int context) ts++; } } - END_SEQ getmouseco_areawin(mval); /* choose the side based on which side of the playhead the mouse is on */ - if (mode=='e') { - float xmouse, ymouse; - areamouseco_to_ipoco(G.v2d, mval, &xmouse, &ymouse); - side = (xmouse > cfra) ? 'R' : 'L'; - } + if (mode=='e') + side = mouse_cfra_side(cfra); /* Markers */ if (sseq->flag & SEQ_MARKER_TRANS && totmark) { @@ -2887,7 +3036,7 @@ void transform_seq(int mode, int context) int bounds_left = MAXFRAME*2; int bounds_right = -(MAXFRAME*2); - WHILE_SEQ(ed->seqbasep) { + for(seq_index=0, seq=seqar[0]; seq_index < totseq_index; seq=seqar[++seq_index]) { if(seq->flag & SELECT) { if(seq_tx_check_left(seq)) bounds_left = MIN2(bounds_left, seq_tx_get_final_left(seq)); @@ -2895,7 +3044,6 @@ void transform_seq(int mode, int context) bounds_right = MAX2(bounds_right,seq_tx_get_final_right(seq)); } } - END_SEQ /* its possible there were no points to set on either side */ if (bounds_left != MAXFRAME*2) @@ -2967,7 +3115,7 @@ void transform_seq(int mode, int context) if (mode=='g' && !snapskip) { /* Grab */ - WHILE_SEQ(ed->seqbasep) { + for(seq_index=0, seq=seqar[0]; seq_index < totseq_index; seq=seqar[++seq_index]) { if(seq->flag & SELECT) { int myofs; // SEQ_DEBUG_INFO(seq); @@ -2996,7 +3144,6 @@ void transform_seq(int mode, int context) ts++; } } - END_SEQ /* Markers */ if (sseq->flag & SEQ_MARKER_TRANS) { @@ -3020,7 +3167,7 @@ void transform_seq(int mode, int context) int move_left, move_right; /* Extend, Similar to grab but operate on one side of the cursor */ - WHILE_SEQ(ed->seqbasep) { + for(seq_index=0, seq=seqar[0]; seq_index < totseq_index; seq=seqar[++seq_index]) { if(seq->flag & SELECT) { /* only move the contents of the metastrip otherwise the transformation is applied twice */ if (sequence_is_free_transformable(seq) && seq->type != SEQ_META) { @@ -3100,7 +3247,6 @@ void transform_seq(int mode, int context) ts++; } } - END_SEQ /* markers */ if (sseq->flag & SEQ_MARKER_TRANS) { @@ -3133,7 +3279,7 @@ void transform_seq(int mode, int context) yo= mval[1]; /* test for effect and overlap */ - WHILE_SEQ(ed->seqbasep) { + for(seq_index=0, seq=seqar[0]; seq_index < totseq_index; seq=seqar[++seq_index]) { if(seq->flag & SELECT) { seq->flag &= ~SEQ_OVERLAP; if( test_overlap_seq(seq) ) { @@ -3146,7 +3292,6 @@ void transform_seq(int mode, int context) else if(seq->seq3 && seq->seq3->flag & SELECT) calc_sequence(seq); } } - END_SEQ; force_draw(0); @@ -3183,7 +3328,7 @@ void transform_seq(int mode, int context) if((event==ESCKEY) || (event==RIGHTMOUSE)) { ts= transmain; - WHILE_SEQ(ed->seqbasep) { + for(seq_index=0, seq=seqar[0]; seq_index < totseq_index; seq=seqar[++seq_index]) { if(seq->flag & SELECT) { seq->start= ts->start; seq->machine= ts->machine; @@ -3202,9 +3347,7 @@ void transform_seq(int mode, int context) else if(seq->seq3 && seq->seq3->flag & SELECT) calc_sequence(seq); } } - END_SEQ - - + /* Markers */ if (sseq->flag & SEQ_MARKER_TRANS) { for(a=0, marker= G.scene->markers.first; marker; marker= marker->next) { @@ -3220,7 +3363,7 @@ void transform_seq(int mode, int context) } else { /* images, effects and overlap */ - WHILE_SEQ(ed->seqbasep) { + for(seq_index=0, seq=seqar[0]; seq_index < totseq_index; seq=seqar[++seq_index]) { /* fixes single image strips - makes sure their start is not out of bounds ideally this would be done during transform since data is rendered at that time @@ -3239,12 +3382,14 @@ void transform_seq(int mode, int context) } else if(seq->type & SEQ_EFFECT) calc_sequence(seq); } - END_SEQ /* as last: */ sort_seq(); } - + + /* free sequence array */ + if(seqar) MEM_freeN(seqar); + G.moving= 0; MEM_freeN(transmain); @@ -3276,137 +3421,6 @@ void transform_seq_nomarker(int mode, int context) { sseq->flag = flag_back; } -void seq_cut(int cutframe) -{ - Editing *ed; - Sequence *seq; - TransSeq *ts, *transmain; - int tot=0; - ListBase newlist; - - ed= G.scene->ed; - if(ed==0) return; - - /* test for validity */ - for(seq= ed->seqbasep->first; seq; seq= seq->next) { - if(seq->flag & SELECT) { - if(cutframe > seq->startdisp && cutframe < seq->enddisp) - if(seq->type==SEQ_META) break; - } - } - if(seq) { - error("Cannot Cut Meta Strips"); - return; - } - - /* we build an array of TransSeq, to denote which strips take part in cutting */ - for(seq= ed->seqbasep->first; seq; seq= seq->next) { - if(seq->flag & SELECT) { - if(cutframe > seq->startdisp && cutframe < seq->enddisp) - tot++; - else - seq->flag &= ~SELECT; // bad code, but we need it for recurs_dupli_seq... note that this ~SELECT assumption is used in loops below too (ton) - } - } - - if(tot==0) { - error("No Strips to Cut"); - return; - } - - ts=transmain= MEM_callocN(tot*sizeof(TransSeq), "transseq"); - - for(seq= ed->seqbasep->first; seq; seq= seq->next) { - if(seq->flag & SELECT) { - - ts->start= seq->start; - ts->machine= seq->machine; - ts->startstill= seq->startstill; - ts->endstill= seq->endstill; - ts->startdisp= seq->startdisp; - ts->enddisp= seq->enddisp; - ts->startofs= seq->startofs; - ts->endofs= seq->endofs; - ts->len= seq->len; - - ts++; - } - } - - for(seq= ed->seqbasep->first; seq; seq= seq->next) { - if(seq->flag & SELECT) { - - /* strips with extended stillframes before */ - if ((seq->startstill) && (cutframe <seq->start)) { - seq->start= cutframe -1; - seq->startstill= cutframe -seq->startdisp -1; - seq->len= 1; - seq->endstill= 0; - } - - /* normal strip */ - else if ((cutframe >=seq->start)&&(cutframe <=(seq->start+seq->len))) { - seq->endofs = (seq->start+seq->len) - cutframe; - } - - /* strips with extended stillframes after */ - else if (((seq->start+seq->len) < cutframe) && (seq->endstill)) { - seq->endstill -= seq->enddisp - cutframe; - } - - calc_sequence(seq); - } - } - - newlist.first= newlist.last= NULL; - - /* now we duplicate the cut strip and move it into place afterwards */ - recurs_dupli_seq(ed->seqbasep, &newlist); - addlisttolist(ed->seqbasep, &newlist); - - ts= transmain; - - /* go through all the strips and correct them based on their stored values */ - for(seq= ed->seqbasep->first; seq; seq= seq->next) { - if(seq->flag & SELECT) { - - /* strips with extended stillframes before */ - if ((seq->startstill) && (cutframe == seq->start + 1)) { - seq->start = ts->start; - seq->startstill= ts->start- cutframe; - seq->len = ts->len; - seq->endstill = ts->endstill; - } - - /* normal strip */ - else if ((cutframe>=seq->start)&&(cutframe<=(seq->start+seq->len))) { - seq->startstill = 0; - seq->startofs = cutframe - ts->start; - seq->endofs = ts->endofs; - seq->endstill = ts->endstill; - } - - /* strips with extended stillframes after */ - else if (((seq->start+seq->len) < cutframe) && (seq->endstill)) { - seq->start = cutframe - ts->len +1; - seq->startofs = ts->len-1; - seq->endstill = ts->enddisp - cutframe -1; - seq->startstill = 0; - } - calc_sequence(seq); - - ts++; - } - } - - /* as last: */ - sort_seq(); - MEM_freeN(transmain); - - allqueue(REDRAWSEQ, 0); - BIF_undo_push("Cut Strips, Sequencer"); -} - void seq_separate_images(void) { Editing *ed; @@ -3599,14 +3613,22 @@ void seq_snap(short event) /* also check metas */ WHILE_SEQ(ed->seqbasep) { - if(seq->flag & SELECT) { - if(sequence_is_free_transformable(seq)) seq->start= CFRA-seq->startofs+seq->startstill; + if (seq->flag & SELECT && sequence_is_free_transformable(seq)) { + if((seq->flag & (SEQ_LEFTSEL+SEQ_RIGHTSEL))==0) { + seq->start= CFRA-seq->startofs+seq->startstill; + } else { + if(seq->flag & SEQ_LEFTSEL) { + seq_tx_set_final_left(seq, CFRA); + } else { /* SEQ_RIGHTSEL */ + seq_tx_set_final_right(seq, CFRA); + } + transform_grab_xlimits(seq, seq->flag & SEQ_LEFTSEL, seq->flag & SEQ_RIGHTSEL); + } calc_sequence(seq); } } END_SEQ - /* test for effects and overlap */ WHILE_SEQ(ed->seqbasep) { if(seq->flag & SELECT) { diff --git a/source/blender/src/editsima.c b/source/blender/src/editsima.c index ce1d70527ed..eb70a32b5a9 100644 --- a/source/blender/src/editsima.c +++ b/source/blender/src/editsima.c @@ -2216,7 +2216,7 @@ void reload_image_sima(void) void new_image_sima(void) { - static int width= 256, height= 256; + static int width= 1024, height= 1024; static short uvtestgrid= 0; static float color[] = {0, 0, 0, 1}; char name[22]; @@ -2225,8 +2225,8 @@ void new_image_sima(void) strcpy(name, "Untitled"); add_numbut(0, TEX, "Name:", 0, 21, name, NULL); - add_numbut(1, NUM|INT, "Width:", 1, 5000, &width, NULL); - add_numbut(2, NUM|INT, "Height:", 1, 5000, &height, NULL); + add_numbut(1, NUM|INT, "Width:", 1, 16384, &width, NULL); + add_numbut(2, NUM|INT, "Height:", 1, 16384, &height, NULL); add_numbut(3, COL, "", 0, 0, &color, NULL); add_numbut(4, NUM|FLO, "Alpha:", 0.0, 1.0, &color[3], NULL); add_numbut(5, TOG|SHO, "UV Test Grid", 0, 0, &uvtestgrid, NULL); diff --git a/source/blender/src/editsound.c b/source/blender/src/editsound.c index 2e333b9f43e..befcd574ac4 100644 --- a/source/blender/src/editsound.c +++ b/source/blender/src/editsound.c @@ -123,7 +123,7 @@ void winqreadsoundspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if(val) { - if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0; + if( uiDoBlocks(&curarea->uiblocks, event, 1)!=UI_NOTHING ) event= 0; /* swap mouse buttons based on user preference */ if (U.flag & USER_LMOUSESELECT) { diff --git a/source/blender/src/edittime.c b/source/blender/src/edittime.c index f90fd1c2eda..f5c6fe5a95e 100644 --- a/source/blender/src/edittime.c +++ b/source/blender/src/edittime.c @@ -836,7 +836,7 @@ void winqreadtimespace(ScrArea *sa, void *spacedata, BWinEvent *evt) if(val) { - if( uiDoBlocks(&sa->uiblocks, event)!=UI_NOTHING ) event= 0; + if( uiDoBlocks(&sa->uiblocks, event, 1)!=UI_NOTHING ) event= 0; /* swap mouse buttons based on user preference */ if (U.flag & USER_LMOUSESELECT) { diff --git a/source/blender/src/editview.c b/source/blender/src/editview.c index f1e4017c264..b3252487fa6 100644 --- a/source/blender/src/editview.c +++ b/source/blender/src/editview.c @@ -533,18 +533,18 @@ static void do_lasso_select_curve__doSelect(void *userData, Nurb *nu, BPoint *bp if (lasso_inside(data->mcords, data->moves, x, y)) { if (bp) { - bp->f1 = data->select?(bp->f1|1):(bp->f1&~1); + bp->f1 = data->select?(bp->f1|SELECT):(bp->f1&~SELECT); } else { if (G.f & G_HIDDENHANDLES) { /* can only be beztindex==0 here since handles are hidden */ - bezt->f1 = bezt->f2 = bezt->f3 = data->select?(bezt->f1|1):(bezt->f1&~1); + bezt->f1 = bezt->f2 = bezt->f3 = data->select?(bezt->f2|SELECT):(bezt->f2&~SELECT); } else { if (beztindex==0) { - bezt->f1 = data->select?(bezt->f1|1):(bezt->f1&~1); + bezt->f1 = data->select?(bezt->f1|SELECT):(bezt->f1&~SELECT); } else if (beztindex==1) { - bezt->f2 = data->select?(bezt->f2|1):(bezt->f2&~1); + bezt->f2 = data->select?(bezt->f2|SELECT):(bezt->f2&~SELECT); } else { - bezt->f3 = data->select?(bezt->f3|1):(bezt->f3&~1); + bezt->f3 = data->select?(bezt->f3|SELECT):(bezt->f3&~SELECT); } } } @@ -566,7 +566,7 @@ static void do_lasso_select_lattice__doSelect(void *userData, BPoint *bp, int x, struct { short (*mcords)[2]; short moves; short select; } *data = userData; if (lasso_inside(data->mcords, data->moves, x, y)) { - bp->f1 = data->select?(bp->f1|1):(bp->f1&~1); + bp->f1 = data->select?(bp->f1|SELECT):(bp->f1&~SELECT); } } static void do_lasso_select_lattice(short mcords[][2], short moves, short select) @@ -1599,18 +1599,18 @@ static void do_nurbs_box_select__doSelect(void *userData, Nurb *nu, BPoint *bp, if (BLI_in_rcti(data->rect, x, y)) { if (bp) { - bp->f1 = data->select?(bp->f1|1):(bp->f1&~1); + bp->f1 = data->select?(bp->f1|SELECT):(bp->f1&~SELECT); } else { if (G.f & G_HIDDENHANDLES) { /* can only be beztindex==0 here since handles are hidden */ - bezt->f1 = bezt->f2 = bezt->f3 = data->select?(bezt->f1|1):(bezt->f1&~1); + bezt->f1 = bezt->f2 = bezt->f3 = data->select?(bezt->f2|SELECT):(bezt->f2&~SELECT); } else { if (beztindex==0) { - bezt->f1 = data->select?(bezt->f1|1):(bezt->f1&~1); + bezt->f1 = data->select?(bezt->f1|SELECT):(bezt->f1&~SELECT); } else if (beztindex==1) { - bezt->f2 = data->select?(bezt->f2|1):(bezt->f2&~1); + bezt->f2 = data->select?(bezt->f2|SELECT):(bezt->f2&~SELECT); } else { - bezt->f3 = data->select?(bezt->f3|1):(bezt->f3&~1); + bezt->f3 = data->select?(bezt->f3|SELECT):(bezt->f3&~SELECT); } } } @@ -1631,7 +1631,7 @@ static void do_lattice_box_select__doSelect(void *userData, BPoint *bp, int x, i struct { rcti *rect; int select; } *data = userData; if (BLI_in_rcti(data->rect, x, y)) { - bp->f1 = data->select?(bp->f1|1):(bp->f1&~1); + bp->f1 = data->select?(bp->f1|SELECT):(bp->f1&~SELECT); } } static void do_lattice_box_select(rcti *rect, int select) @@ -2051,14 +2051,14 @@ static void nurbscurve_selectionCB__doSelect(void *userData, Nurb *nu, BPoint *b if (r<=data->radius) { if (bp) { - bp->f1 = data->select?(bp->f1|1):(bp->f1&~1); + bp->f1 = data->select?(bp->f1|SELECT):(bp->f1&~SELECT); } else { if (beztindex==0) { - bezt->f1 = data->select?(bezt->f1|1):(bezt->f1&~1); + bezt->f1 = data->select?(bezt->f1|SELECT):(bezt->f1&~SELECT); } else if (beztindex==1) { - bezt->f2 = data->select?(bezt->f2|1):(bezt->f2&~1); + bezt->f2 = data->select?(bezt->f2|SELECT):(bezt->f2&~SELECT); } else { - bezt->f3 = data->select?(bezt->f3|1):(bezt->f3&~1); + bezt->f3 = data->select?(bezt->f3|SELECT):(bezt->f3&~SELECT); } } } @@ -2083,7 +2083,7 @@ static void latticecurve_selectionCB__doSelect(void *userData, BPoint *bp, int x float r = sqrt(mx*mx + my*my); if (r<=data->radius) { - bp->f1 = data->select?(bp->f1|1):(bp->f1&~1); + bp->f1 = data->select?(bp->f1|SELECT):(bp->f1&~SELECT); } } static void lattice_selectionCB(int selecting, Object *editobj, short *mval, float rad) @@ -2144,9 +2144,12 @@ void set_render_border(void) allqueue(REDRAWVIEWCAM, 1); - /* drawing a border surrounding the entire camera view switches off border rendering */ - if (G.scene->r.border.xmin <= 0.0 && G.scene->r.border.xmax >= 1.0 && - G.scene->r.border.ymin <= 0.0 && G.scene->r.border.ymax >= 1.0) + /* drawing a border surrounding the entire camera view switches off border rendering + * or the border covers no pixels */ + if ((G.scene->r.border.xmin <= 0.0 && G.scene->r.border.xmax >= 1.0 && + G.scene->r.border.ymin <= 0.0 && G.scene->r.border.ymax >= 1.0) || + (G.scene->r.border.xmin == G.scene->r.border.xmax || + G.scene->r.border.ymin == G.scene->r.border.ymax )) { G.scene->r.mode &= ~R_BORDER; } else { diff --git a/source/blender/src/filesel.c b/source/blender/src/filesel.c index 599c6d5aae2..d4e41e56e75 100644 --- a/source/blender/src/filesel.c +++ b/source/blender/src/filesel.c @@ -34,6 +34,12 @@ #include <string.h> #include <math.h> +#include <sys/stat.h> +#include <sys/types.h> +#include "MEM_guardedalloc.h" + +#include "BMF_Api.h" + #ifdef WIN32 #include <io.h> #include <direct.h> @@ -43,12 +49,6 @@ #include <sys/times.h> #endif -#include <sys/stat.h> -#include <sys/types.h> -#include "MEM_guardedalloc.h" - -#include "BMF_Api.h" - #include "BLI_blenlib.h" #include "BLI_arithb.h" #include "BLI_linklist.h" @@ -1812,7 +1812,7 @@ void winqreadfilespace(ScrArea *sa, void *spacedata, BWinEvent *evt) if(val) { if( event!=RETKEY && event!=PADENTER) - if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0; + if( uiDoBlocks(&curarea->uiblocks, event, 1)!=UI_NOTHING ) event= 0; switch(event) { diff --git a/source/blender/src/header_action.c b/source/blender/src/header_action.c index 4a803926a94..6d01dcf6bab 100644 --- a/source/blender/src/header_action.c +++ b/source/blender/src/header_action.c @@ -102,7 +102,9 @@ enum { ACTMENU_SEL_ALL_CHAN, ACTMENU_SEL_ALL_MARKERS, ACTMENU_SEL_INVERSE_KEYS, - ACTMENU_SEL_INVERSE_MARKERS + ACTMENU_SEL_INVERSE_MARKERS, + ACTMENU_SEL_LEFTKEYS, + ACTMENU_SEL_RIGHTKEYS }; enum { @@ -156,6 +158,7 @@ enum { ACTMENU_KEY_SNAP_CURFRAME, ACTMENU_KEY_SNAP_NEARMARK, ACTMENU_KEY_SNAP_NEARTIME, + ACTMENU_KEY_SNAP_CFRA2KEY, }; enum { @@ -513,6 +516,14 @@ static void do_action_selectmenu(void *arg, int event) deselect_markers(0, 2); allqueue(REDRAWMARKER, 0); break; + + case ACTMENU_SEL_LEFTKEYS: + selectkeys_leftright(1, SELECT_REPLACE); + break; + + case ACTMENU_SEL_RIGHTKEYS: + selectkeys_leftright(0, SELECT_REPLACE); + break; } } @@ -565,6 +576,19 @@ static uiBlock *action_selectmenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, + "Back In Time|Alt RMB", 0, yco-=20, + menuwidth, 19, NULL, 0.0, 0.0, 0, + ACTMENU_SEL_LEFTKEYS, ""); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, + "Ahead In Time|Alt RMB", 0, yco-=20, + menuwidth, 19, NULL, 0.0, 0.0, 0, + ACTMENU_SEL_RIGHTKEYS, ""); + + uiDefBut(block, SEPR, 0, "", 0, yco-=6, + menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + uiDefIconTextBlockBut(block, action_selectmenu_columnmenu, NULL, ICON_RIGHTARROW_THIN, "Column Select Keys", 0, yco-=20, 120, 20, ""); @@ -849,6 +873,10 @@ static void do_action_keymenu_snapmenu(void *arg, int event) case ACTMENU_KEY_SNAP_NEARTIME: snap_action_keys(event); break; + + case ACTMENU_KEY_SNAP_CFRA2KEY: + snap_cfra_action(); + break; } scrarea_queue_winredraw(curarea); @@ -865,27 +893,35 @@ static uiBlock *action_keymenu_snapmenu(void *arg_unused) if (G.saction->flag & SACTION_DRAWTIME) { uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Nearest Second|Shift S, 1", 0, yco-=20, + "Key -> Nearest Second|Shift S, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_KEY_SNAP_NEARTIME, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Current Time|Shift S, 2", 0, yco-=20, + "Key -> Current Time|Shift S, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_KEY_SNAP_CURFRAME, ""); } else { uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Nearest Frame|Shift S, 1", 0, yco-=20, + "Key -> Nearest Frame|Shift S, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_KEY_SNAP_NEARFRAME, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Current Frame|Shift S, 2", 0, yco-=20, + "Key -> Current Frame|Shift S, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_KEY_SNAP_CURFRAME, ""); } uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Nearest Marker|Shift S, 3", 0, yco-=20, + "Key -> Nearest Marker|Shift S, 3", 0, yco-=20, + menuwidth, 19, NULL, 0.0, 0.0, 0, + ACTMENU_KEY_SNAP_NEARMARK, ""); + + uiDefBut(block, SEPR, 0, "", 0, yco-=6, + menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, + "Current Frame -> Key|Ctrl Shift S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_KEY_SNAP_NEARMARK, ""); diff --git a/source/blender/src/header_nla.c b/source/blender/src/header_nla.c index 96ea6c3d792..3b614ebfb7c 100644 --- a/source/blender/src/header_nla.c +++ b/source/blender/src/header_nla.c @@ -331,7 +331,7 @@ static void do_nla_stripmenu(void *arg, int event) case 7: /* Move Down */ shift_nlastrips_down(); break; - case 8: /* size */ + case 8: /* reset scale */ reset_action_strips(1); break; case 9: /* reset start/end of action */ @@ -340,6 +340,9 @@ static void do_nla_stripmenu(void *arg, int event) case 10: /* add new action as new action strip */ add_empty_nlablock(); break; + case 11: /* apply scale */ + reset_action_strips(3); + break; } } @@ -353,10 +356,11 @@ static uiBlock *nla_stripmenu(void *arg_unused) uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Strip Properties...|N", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, ""); uiDefIconTextBlockBut(block, nla_strip_transformmenu, NULL, ICON_RIGHTARROW_THIN, "Transform", 0, yco-=20, 120, 20, ""); - uiDefIconTextBlockBut(block, nla_strip_snapmenu, NULL, ICON_RIGHTARROW_THIN, "Snap To Frame", 0, yco-=20, 120, 20, ""); + uiDefIconTextBlockBut(block, nla_strip_snapmenu, NULL, ICON_RIGHTARROW_THIN, "Snap", 0, yco-=20, 120, 20, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset Strip Size|Alt S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset Strip Scale|Alt S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset Action Start/End|Alt S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 9, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Apply Strip Scaling|Alt S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 11, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); diff --git a/source/blender/src/header_node.c b/source/blender/src/header_node.c index 83aff8bcbe1..ebdd42690f5 100644 --- a/source/blender/src/header_node.c +++ b/source/blender/src/header_node.c @@ -662,7 +662,7 @@ void node_buttons(ScrArea *sa) xco+= 80; uiDefButBitS(block, TOG, R_COMP_FREE, B_NOP, "Free Unused", xco+5,0,80,19, &G.scene->r.scemode, 0.0f, 0.0f, 0, 0, "Free Nodes that are not used while composite"); xco+= 80; - uiDefButBitS(block, TOG, SNODE_BACKDRAW, B_NOP, "Backdrop", xco+5,0,80,19, &snode->flag, 0.0f, 0.0f, 0, 0, "Use active Viewer Node output as backdrop"); + uiDefButBitS(block, TOG, SNODE_BACKDRAW, REDRAWNODE, "Backdrop", xco+5,0,80,19, &snode->flag, 0.0f, 0.0f, 0, 0, "Use active Viewer Node output as backdrop"); xco+= 80; } diff --git a/source/blender/src/header_seq.c b/source/blender/src/header_seq.c index 4075371108b..e26ab4a157a 100644 --- a/source/blender/src/header_seq.c +++ b/source/blender/src/header_seq.c @@ -481,10 +481,12 @@ static uiBlock *seq_editmenu(void *arg_unused) } -/* if (last_seq != NULL && last_seq->type == SEQ_MOVIE) { - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Set Filter Y|F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, ""); + if (last_seq != NULL && last_seq->type == SEQ_MOVIE) { +/* uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Set Filter Y|F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, ""); */ + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Remap Paths...|Shift R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 15, ""); } -*/ + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Make Meta Strip...|M", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, ""); diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index f212a467b99..1085b8598a1 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -4091,6 +4091,9 @@ static void do_view3d_pose_armaturemenu(void *arg, int event) case 14: /* move bone to layer / change armature layer */ pose_movetolayer(); break; + case 15: + pose_relax(); + break; } allqueue(REDRAWVIEW3D, 0); @@ -4115,6 +4118,10 @@ static uiBlock *view3d_pose_armaturemenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Relax Pose|W", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 15, ""); + + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Copy Current Pose", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Paste Pose", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Paste Flipped Pose", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, ""); diff --git a/source/blender/src/interface.c b/source/blender/src/interface.c index 07debe8f864..a17e488ef13 100644 --- a/source/blender/src/interface.c +++ b/source/blender/src/interface.c @@ -135,6 +135,7 @@ uiBut *UIbuttip; static char but_copypaste_str[256]=""; static double but_copypaste_val=0.0; static float but_copypaste_rgb[3]; +static ColorBand but_copypaste_coba; /* ************* PROTOTYPES ***************** */ @@ -525,7 +526,6 @@ static int ui_but_copy_paste(uiBut *but, char mode) } } else if(but->type==TEX) { - if(poin==NULL); else if(mode=='c') { strncpy(but_copypaste_str, but->poin, but->max); @@ -545,7 +545,6 @@ static int ui_but_copy_paste(uiBut *but, char mode) } } else if(but->type==IDPOIN) { - if(mode=='c') { ID *id= *but->idpoin_idpp; if(id) strncpy(but_copypaste_str, id->name+2, 22); @@ -556,8 +555,24 @@ static int ui_but_copy_paste(uiBut *but, char mode) return 1; } } - - + else if(but->type==BUT_COLORBAND) { + if(mode=='c') { + if (!but->poin) { + return 0; + } + memcpy( &but_copypaste_coba, but->poin, sizeof(ColorBand) ); + } else { + if (but_copypaste_coba.tot==0) { + return 0; + } + if (!but->poin) { + but->poin= MEM_callocN( sizeof(ColorBand), "colorband"); + } + memcpy( but->poin, &but_copypaste_coba, sizeof(ColorBand) ); + return 1; + } + } + return 0; } @@ -1289,7 +1304,7 @@ static int ui_do_but_MENU(uiBut *but) for(bt= block->buttons.first; bt; bt= bt->next) bt->win= block->win; bwin_getsinglematrix(block->win, block->winmat); - event= uiDoBlocks(&listb, 0); + event= uiDoBlocks(&listb, 0, 1); menudata_free(md); @@ -2336,7 +2351,7 @@ static int ui_do_but_ICONROW(uiBut *but) this is needs better implementation */ block->win= G.curscreen->mainwin; - uiDoBlocks(&listb, 0); + uiDoBlocks(&listb, 0, 1); but->flag &= ~UI_SELECT; ui_check_but(but); @@ -2409,7 +2424,7 @@ static int ui_do_but_ICONTEXTROW(uiBut *but) uiBoundsBlock(block, 3); - uiDoBlocks(&listb, 0); + uiDoBlocks(&listb, 0, 1); menudata_free(md); @@ -3287,7 +3302,7 @@ static int ui_do_but_COL(uiBut *but) for(bt= block->buttons.first; bt; bt= bt->next) bt->win= block->win; bwin_getsinglematrix(block->win, block->winmat); - event= uiDoBlocks(&listb, 0); + event= uiDoBlocks(&listb, 0, 1); if(but->pointype==CHA) ui_set_but_vectorf(but, colstore); @@ -4291,7 +4306,7 @@ int uiIsMenu(int *x, int *y, int *sizex, int *sizey) * UI_CONT don't pass event to other ui's * UI_RETURN something happened, return, swallow event */ -static int ui_do_block(uiBlock *block, uiEvent *uevent) +static int ui_do_block(uiBlock *block, uiEvent *uevent, int movemouse_quit) { uiBut *but, *bt; int butevent, event, retval=UI_NOTHING, count, act=0; @@ -4778,7 +4793,7 @@ static int ui_do_block(uiBlock *block, uiEvent *uevent) if((uevent->event==RETKEY || uevent->event==PADENTER) && uevent->val==1) return UI_RETURN_OK; /* check outside */ - if(inside==0) { + if(inside==0 && movemouse_quit) { uiBlock *tblock= NULL; /* check for all parent rects, enables arrowkeys to be used */ @@ -4920,7 +4935,7 @@ static void ui_do_but_tip(uiBut *buttip) } /* returns UI_NOTHING, if nothing happened */ -int uiDoBlocks(ListBase *lb, int event) +int uiDoBlocks(ListBase *lb, int event, int movemouse_quit) { /* return when: firstblock != BLOCK_LOOP * @@ -4975,7 +4990,7 @@ int uiDoBlocks(ListBase *lb, int event) } block->in_use= 1; // bit awkward, but now we can detect if frontbuf flush should be set - retval |= ui_do_block(block, &uevent); /* we 'or' because 2nd loop can return to here, and we we want 'out' to return */ + retval |= ui_do_block(block, &uevent, movemouse_quit); /* we 'or' because 2nd loop can return to here, and we we want 'out' to return */ block->in_use= 0; if(retval & UI_EXIT_LOOP) break; @@ -5019,7 +5034,7 @@ int uiDoBlocks(ListBase *lb, int event) if(uevent.event) { block->in_use= 1; // bit awkward, but now we can detect if frontbuf flush should be set - retval= ui_do_block(block, &uevent); + retval= ui_do_block(block, &uevent, movemouse_quit); block->in_use= 0; if(block->needflush) { // flush (old menu) now, maybe new menu was opened @@ -6515,7 +6530,7 @@ short pupmenu(char *instr) uiBoundsBlock(block, 1); - event= uiDoBlocks(&listb, 0); + event= uiDoBlocks(&listb, 0, 1); /* calculate last selected */ if(event & UI_RETURN_OK) { @@ -6673,7 +6688,7 @@ short pupmenu_col(char *instr, int maxrow) uiBoundsBlock(block, 1); - event= uiDoBlocks(&listb, 0); + event= uiDoBlocks(&listb, 0, 1); menudata_free(md); diff --git a/source/blender/src/meshlaplacian.c b/source/blender/src/meshlaplacian.c index d711419a927..292fcba055e 100644 --- a/source/blender/src/meshlaplacian.c +++ b/source/blender/src/meshlaplacian.c @@ -974,7 +974,7 @@ void rigid_deform_end(int cancel) #define MESHDEFORM_LEN_THRESHOLD 1e-6 -#define MESHDEFORM_MIN_INFLUENCE 0.005 +#define MESHDEFORM_MIN_INFLUENCE 0.0005 static int MESHDEFORM_OFFSET[7][3] = {{0,0,0}, {1,0,0}, {-1,0,0}, {0,1,0}, {0,-1,0}, {0,0,1}, {0,0,-1}}; diff --git a/source/blender/src/meshtools.c b/source/blender/src/meshtools.c index d06208ea503..bcf07c9b594 100644 --- a/source/blender/src/meshtools.c +++ b/source/blender/src/meshtools.c @@ -686,7 +686,7 @@ static void mesh_octree_add_nodes(MocNode **basetable, float *co, float *offs, f } -static long mesh_octree_find_index(MocNode **bt, MVert *mvert, float *co) +static long mesh_octree_find_index(MocNode **bt, float (*orco)[3], MVert *mvert, float *co) { float *vec; int a; @@ -697,7 +697,12 @@ static long mesh_octree_find_index(MocNode **bt, MVert *mvert, float *co) for(a=0; a<MOC_NODE_RES; a++) { if((*bt)->index[a]) { /* does mesh verts and editmode, code looks potential dangerous, octree should really be filled OK! */ - if(mvert) { + if(orco) { + vec= orco[(*bt)->index[a]-1]; + if(FloatCompare(vec, co, MOC_THRESH)) + return (*bt)->index[a]-1; + } + else if(mvert) { vec= (mvert+(*bt)->index[a]-1)->co; if(FloatCompare(vec, co, MOC_THRESH)) return (*bt)->index[a]-1; @@ -711,84 +716,118 @@ static long mesh_octree_find_index(MocNode **bt, MVert *mvert, float *co) else return -1; } if( (*bt)->next) - return mesh_octree_find_index(&(*bt)->next, mvert, co); + return mesh_octree_find_index(&(*bt)->next, orco, mvert, co); return -1; } +static struct { + MocNode **table; + float offs[3], div[3]; + float (*orco)[3]; + float orcoloc[3]; +} MeshOctree = {NULL, {0, 0, 0}, {0, 0, 0}, NULL}; /* mode is 's' start, or 'e' end, or 'u' use */ /* if end, ob can be NULL */ long mesh_octree_table(Object *ob, float *co, char mode) { MocNode **bt; - static MocNode **basetable= NULL; - static float offs[3], div[3]; if(mode=='u') { /* use table */ - if(basetable==NULL) + if(MeshOctree.table==NULL) mesh_octree_table(ob, NULL, 's'); - if(basetable) { + if(MeshOctree.table) { Mesh *me= ob->data; - bt= basetable + mesh_octree_get_base_offs(co, offs, div); + bt= MeshOctree.table + mesh_octree_get_base_offs(co, MeshOctree.offs, MeshOctree.div); if(ob==G.obedit) - return mesh_octree_find_index(bt, NULL, co); + return mesh_octree_find_index(bt, NULL, NULL, co); else - return mesh_octree_find_index(bt, me->mvert, co); + return mesh_octree_find_index(bt, MeshOctree.orco, me->mvert, co); } return -1; } else if(mode=='s') { /* start table */ Mesh *me= ob->data; - BoundBox *bb = mesh_get_bb(me); + float min[3], max[3]; + + /* we compute own bounding box and don't reuse ob->bb because + * we are using the undeformed coordinates*/ + INIT_MINMAX(min, max); + + if(ob==G.obedit) { + EditVert *eve; + + for(eve= G.editMesh->verts.first; eve; eve= eve->next) + DO_MINMAX(eve->co, min, max) + } + else { + MVert *mvert; + float *co; + int a, totvert; + + MeshOctree.orco= mesh_getRefKeyCos(me, &totvert); + mesh_get_texspace(me, MeshOctree.orcoloc, NULL, NULL); + + for(a=0, mvert= me->mvert; a<me->totvert; a++, mvert++) { + co= (MeshOctree.orco)? MeshOctree.orco[a]: mvert->co; + DO_MINMAX(co, min, max); + } + } /* for quick unit coordinate calculus */ - VECCOPY(offs, bb->vec[0]); - offs[0]-= MOC_THRESH; /* we offset it 1 threshold unit extra */ - offs[1]-= MOC_THRESH; - offs[2]-= MOC_THRESH; - - VecSubf(div, bb->vec[6], bb->vec[0]); - div[0]+= 2*MOC_THRESH; /* and divide with 2 threshold unit more extra (try 8x8 unit grid on paint) */ - div[1]+= 2*MOC_THRESH; - div[2]+= 2*MOC_THRESH; + VECCOPY(MeshOctree.offs, min); + MeshOctree.offs[0]-= MOC_THRESH; /* we offset it 1 threshold unit extra */ + MeshOctree.offs[1]-= MOC_THRESH; + MeshOctree.offs[2]-= MOC_THRESH; - VecMulf(div, 1.0f/MOC_RES); - if(div[0]==0.0f) div[0]= 1.0f; - if(div[1]==0.0f) div[1]= 1.0f; - if(div[2]==0.0f) div[2]= 1.0f; + VecSubf(MeshOctree.div, max, min); + MeshOctree.div[0]+= 2*MOC_THRESH; /* and divide with 2 threshold unit more extra (try 8x8 unit grid on paint) */ + MeshOctree.div[1]+= 2*MOC_THRESH; + MeshOctree.div[2]+= 2*MOC_THRESH; + + VecMulf(MeshOctree.div, 1.0f/MOC_RES); + if(MeshOctree.div[0]==0.0f) MeshOctree.div[0]= 1.0f; + if(MeshOctree.div[1]==0.0f) MeshOctree.div[1]= 1.0f; + if(MeshOctree.div[2]==0.0f) MeshOctree.div[2]= 1.0f; - if(basetable) /* happens when entering this call without ending it */ + if(MeshOctree.table) /* happens when entering this call without ending it */ mesh_octree_table(ob, co, 'e'); - basetable= MEM_callocN(MOC_RES*MOC_RES*MOC_RES*sizeof(void *), "sym table"); + MeshOctree.table= MEM_callocN(MOC_RES*MOC_RES*MOC_RES*sizeof(void *), "sym table"); if(ob==G.obedit) { EditVert *eve; for(eve= G.editMesh->verts.first; eve; eve= eve->next) { - mesh_octree_add_nodes(basetable, eve->co, offs, div, (long)(eve)); + mesh_octree_add_nodes(MeshOctree.table, eve->co, MeshOctree.offs, MeshOctree.div, (long)(eve)); } } else { MVert *mvert; - long a; + float *co; + int a; - for(a=1, mvert= me->mvert; a<=me->totvert; a++, mvert++) { - mesh_octree_add_nodes(basetable, mvert->co, offs, div, a); + for(a=0, mvert= me->mvert; a<me->totvert; a++, mvert++) { + co= (MeshOctree.orco)? MeshOctree.orco[a]: mvert->co; + mesh_octree_add_nodes(MeshOctree.table, co, MeshOctree.offs, MeshOctree.div, a+1); } } } else if(mode=='e') { /* end table */ - if(basetable) { + if(MeshOctree.table) { int a; - for(a=0, bt=basetable; a<MOC_RES*MOC_RES*MOC_RES; a++, bt++) { + for(a=0, bt=MeshOctree.table; a<MOC_RES*MOC_RES*MOC_RES; a++, bt++) { if(*bt) mesh_octree_free_node(bt); } - MEM_freeN(basetable); - basetable= NULL; + MEM_freeN(MeshOctree.table); + MeshOctree.table= NULL; + } + if(MeshOctree.orco) { + MEM_freeN(MeshOctree.orco); + MeshOctree.orco= NULL; } } return 0; @@ -797,12 +836,22 @@ long mesh_octree_table(Object *ob, float *co, char mode) int mesh_get_x_mirror_vert(Object *ob, int index) { Mesh *me= ob->data; - MVert *mvert= me->mvert+index; + MVert *mvert; float vec[3]; - vec[0]= -mvert->co[0]; - vec[1]= mvert->co[1]; - vec[2]= mvert->co[2]; + if(MeshOctree.orco) { + float *loc= MeshOctree.orcoloc; + + vec[0]= -(MeshOctree.orco[index][0] + loc[0]) - loc[0]; + vec[1]= MeshOctree.orco[index][1]; + vec[2]= MeshOctree.orco[index][2]; + } + else { + mvert= me->mvert+index; + vec[0]= -mvert->co[0]; + vec[1]= mvert->co[1]; + vec[2]= mvert->co[2]; + } return mesh_octree_table(ob, vec, 'u'); } @@ -875,7 +924,6 @@ int *mesh_get_x_mirror_faces(Object *ob) MFace mirrormf, *mf, *hashmf, *mface= me->mface; GHash *fhash; int *mirrorverts, *mirrorfaces; - float vec[3]; int a; mirrorverts= MEM_callocN(sizeof(int)*me->totvert, "MirrorVerts"); @@ -883,12 +931,8 @@ int *mesh_get_x_mirror_faces(Object *ob) mesh_octree_table(ob, NULL, 's'); - for(a=0, mv=mvert; a<me->totvert; a++, mv++) { - vec[0]= -mv->co[0]; - vec[1]= mv->co[1]; - vec[2]= mv->co[2]; - mirrorverts[a]= mesh_octree_table(ob, vec, 'u'); - } + for(a=0, mv=mvert; a<me->totvert; a++, mv++) + mirrorverts[a]= mesh_get_x_mirror_vert(ob, a); mesh_octree_table(ob, NULL, 'e'); @@ -1011,7 +1055,7 @@ void objects_bake_render(short event) prev_wo_amb_occ = (G.scene->world->mode & WO_AMB_OCC) != 0; G.scene->world->mode |= WO_AMB_OCC; } - if(event==RE_BAKE_AO || actob) { + if(event==RE_BAKE_AO || active) { prev_r_raytrace = (G.scene->r.mode & R_RAYTRACE) != 0; G.scene->r.mode |= R_RAYTRACE; } @@ -1021,7 +1065,7 @@ void objects_bake_render(short event) g_break= 0; G.afbreek= 0; /* blender_test_break uses this global */ - RE_Database_Baking(re, G.scene, event, actob); + RE_Database_Baking(re, G.scene, event, (active)? actob: NULL); /* baking itself is threaded, cannot use test_break in threads. we also update optional imagewindow */ @@ -1029,7 +1073,7 @@ void objects_bake_render(short event) bkr.re= re; bkr.event= event; bkr.ready= 0; - bkr.actob= actob; + bkr.actob= (active)? actob: NULL; BLI_insert_thread(&threads, &bkr); while(bkr.ready==0) { @@ -1074,7 +1118,7 @@ void objects_bake_render(short event) if(prev_wo_amb_occ == 0) G.scene->world->mode &= ~WO_AMB_OCC; - if(event==RE_BAKE_AO || actob) + if(event==RE_BAKE_AO || active) if(prev_r_raytrace == 0) G.scene->r.mode &= ~R_RAYTRACE; diff --git a/source/blender/src/playanim.c b/source/blender/src/playanim.c index 65853a841d6..828ff8e774e 100644 --- a/source/blender/src/playanim.c +++ b/source/blender/src/playanim.c @@ -201,11 +201,11 @@ static void toscreen(Pict *picture, struct ImBuf *ibuf) pupdate_time(); - if(picture && (qualN & LMOUSE)) { + if(picture && (qualN & (SHIFT|LMOUSE))) { char str[256]; cpack(-1); glRasterPos2f(0.02f, 0.03f); - sprintf(str, "%s", picture->name); + sprintf(str, "%s | %.2f frames/s\n", picture->name, 1.0 / swaptime); BMF_DrawString(G.fonts, str); } @@ -657,7 +657,10 @@ void playanim(int argc, char **argv) swaptime = 1.0 / 30.0; break; case PAD4: - swaptime = 1.0 / 25.0; + if (qualN & SHIFT) + swaptime = 1.0 / 24.0; + else + swaptime = 1.0 / 25.0; break; case PAD5: swaptime = 1.0 / 20.0; diff --git a/source/blender/src/poseobject.c b/source/blender/src/poseobject.c index 68af3d7c64c..8add5b3dce9 100644 --- a/source/blender/src/poseobject.c +++ b/source/blender/src/poseobject.c @@ -37,6 +37,7 @@ #include "DNA_action_types.h" #include "DNA_armature_types.h" #include "DNA_constraint_types.h" +#include "DNA_curve_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" @@ -56,6 +57,7 @@ #include "BKE_modifier.h" #include "BKE_object.h" #include "BKE_utildefines.h" +#include "BKE_ipo.h" #include "BIF_editarmature.h" #include "BIF_editaction.h" @@ -77,6 +79,9 @@ #include "mydevice.h" #include "blendef.h" +#include "transform.h" + +#include "BIF_transform.h" /* for autokey TFM_TRANSLATION, etc */ void enter_posemode(void) { @@ -219,7 +224,9 @@ int pose_channel_in_IK_chain(Object *ob, bPoseChannel *pchan) /* ********************************************** */ -/* for the object with pose/action: create path curves for selected bones */ +/* For the object with pose/action: create path curves for selected bones + * This recalculates the WHOLE path within the pchan->pathsf and pchan->pathef range + */ void pose_calculate_path(Object *ob) { bArmature *arm; @@ -238,56 +245,58 @@ void pose_calculate_path(Object *ob) arm->pathsf = SFRA; arm->pathef = EFRA; } - if ((arm->pathbc == 0) || (arm->pathac == 0)) { - arm->pathbc = 15; - arm->pathac = 15; - } if (arm->pathsize == 0) { arm->pathsize = 1; } /* set frame values */ cfra= CFRA; - if (arm->pathflag & ARM_PATH_ACFRA) { - sfra = cfra - arm->pathbc; - efra = cfra + arm->pathac; + sfra = arm->pathsf; + efra = arm->pathef; + if (efra <= sfra) { + error("Can't calculate paths when pathlen <= 0"); + return; } - else { - sfra = arm->pathsf; - efra = arm->pathef; + + waitcursor(1); + + /* hack: for unsaved files, set OB_RECALC so that paths can get calculated */ + if ((ob->recalc & OB_RECALC)==0) { + ob->recalc |= OB_RECALC; + DAG_object_update_flags(G.scene, ob, screen_view3d_layers()); } - if (efra<=sfra) return; + else + DAG_object_update_flags(G.scene, ob, screen_view3d_layers()); - DAG_object_update_flags(G.scene, ob, screen_view3d_layers()); /* malloc the path blocks */ - for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - if(pchan->bone && (pchan->bone->flag & BONE_SELECTED)) { - if(arm->layer & pchan->bone->layer) { + for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED)) { + if (arm->layer & pchan->bone->layer) { pchan->pathlen= efra-sfra+1; pchan->pathsf= sfra; pchan->pathef= efra+1; - if(pchan->path) + if (pchan->path) MEM_freeN(pchan->path); pchan->path= MEM_callocN(3*pchan->pathlen*sizeof(float), "pchan path"); } } } - for(CFRA=sfra; CFRA<=efra; CFRA++) { + for (CFRA=sfra; CFRA<=efra; CFRA++) { /* do all updates */ - for(base= FIRSTBASE; base; base= base->next) { - if(base->object->recalc) { + for (base= FIRSTBASE; base; base= base->next) { + if (base->object->recalc) { int temp= base->object->recalc; object_handle_update(base->object); base->object->recalc= temp; } } - for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - if(pchan->bone && (pchan->bone->flag & BONE_SELECTED)) { - if(arm->layer & pchan->bone->layer) { - if(pchan->path) { + for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED)) { + if (arm->layer & pchan->bone->layer) { + if (pchan->path) { fp= pchan->path+3*(CFRA-sfra); if (arm->pathflag & ARM_PATH_HEADS) { @@ -304,25 +313,113 @@ void pose_calculate_path(Object *ob) } } + waitcursor(0); + CFRA= cfra; allqueue(REDRAWVIEW3D, 0); /* recalc tags are still there */ allqueue(REDRAWBUTSEDIT, 0); } +/* For the object with pose/action: update paths for those that have got them + * This should selectively update paths that exist... + */ +void pose_recalculate_paths(Object *ob) +{ + bArmature *arm; + bPoseChannel *pchan; + Base *base; + float *fp; + int cfra; + int sfra, efra; + + if (ob==NULL || ob->pose==NULL) + return; + arm= ob->data; + + /* set frame values */ + cfra = CFRA; + sfra = efra = cfra; + for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + if ((pchan->bone) && (arm->layer & pchan->bone->layer)) { + if (pchan->path) { + /* if the pathsf and pathef aren't initialised, abort! */ + if (ELEM(0, pchan->pathsf, pchan->pathef)) + return; + + /* try to increase area to do (only as much as needed) */ + sfra= MIN2(sfra, pchan->pathsf); + efra= MAX2(efra, pchan->pathef); + } + } + } + if (efra <= sfra) return; + + waitcursor(1); + + /* hack: for unsaved files, set OB_RECALC so that paths can get calculated */ + if ((ob->recalc & OB_RECALC)==0) { + ob->recalc |= OB_RECALC; + DAG_object_update_flags(G.scene, ob, screen_view3d_layers()); + } + else + DAG_object_update_flags(G.scene, ob, screen_view3d_layers()); + + for (CFRA=sfra; CFRA<=efra; CFRA++) { + /* do all updates */ + for (base= FIRSTBASE; base; base= base->next) { + if (base->object->recalc) { + int temp= base->object->recalc; + object_handle_update(base->object); + base->object->recalc= temp; + } + } + + for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + if ((pchan->bone) && (arm->layer & pchan->bone->layer)) { + if (pchan->path) { + /* only update if: + * - in range of this pchan's existing path + * - ... insert evil filtering/optimising conditions here... + */ + if (IN_RANGE(CFRA, pchan->pathsf, pchan->pathef)) { + fp= pchan->path+3*(CFRA-sfra); + + if (arm->pathflag & ARM_PATH_HEADS) { + VECCOPY(fp, pchan->pose_head); + } + else { + VECCOPY(fp, pchan->pose_tail); + } + + Mat4MulVecfl(ob->obmat, fp); + } + } + } + } + } + + waitcursor(0); + + CFRA= cfra; + allqueue(REDRAWVIEW3D, 0); /* recalc tags are still there */ + allqueue(REDRAWBUTSEDIT, 0); +} -/* for the object with pose/action: clear all path curves */ +/* for the object with pose/action: clear path curves for selected bones only */ void pose_clear_paths(Object *ob) { bPoseChannel *pchan; - if(ob==NULL || ob->pose==NULL) + if (ob==NULL || ob->pose==NULL) return; /* free the path blocks */ - for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - if(pchan->path) { - MEM_freeN(pchan->path); - pchan->path= NULL; + for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED)) { + if (pchan->path) { + MEM_freeN(pchan->path); + pchan->path= NULL; + } } } @@ -387,7 +484,7 @@ void pose_special_editmenu(void) if(!ob && !ob->pose) return; if(ob==G.obedit || (ob->flag & OB_POSEMODE)==0) return; - nr= pupmenu("Specials%t|Select Constraint Target%x1|Flip Left-Right Names%x2|Calculate Paths%x3|Clear All Paths%x4|Clear User Transform %x5"); + nr= pupmenu("Specials%t|Select Constraint Target%x1|Flip Left-Right Names%x2|Calculate Paths%x3|Clear Paths%x4|Clear User Transform %x5|Relax Pose %x6"); if(nr==1) { pose_select_constraint_target(); } @@ -405,6 +502,9 @@ void pose_special_editmenu(void) DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); BIF_undo_push("Clear User Transform Pose"); } + else if(nr==6) { + pose_relax(); + } } void pose_add_IK(void) @@ -978,3 +1078,181 @@ void pose_movetolayer(void) allqueue(REDRAWBUTSEDIT, 0); } } + + +/* for use with pose_relax only */ +static int pose_relax_icu(struct IpoCurve *icu, float framef, float *val, float *frame_prev, float *frame_next) +{ + if (!icu) { + return 0; + } else { + BezTriple *bezt = icu->bezt; + + BezTriple *bezt_prev=NULL, *bezt_next=NULL; + float w1, w2, wtot; + int i; + + for (i=0; i < icu->totvert; i++, bezt++) { + if (bezt->vec[1][0] < framef - 0.5) { + bezt_prev = bezt; + } else { + break; + } + } + + if (bezt_prev==NULL) return 0; + + /* advance to the next, dont need to advance i */ + bezt = bezt_prev+1; + + for (; i < icu->totvert; i++, bezt++) { + if (bezt->vec[1][0] > framef + 0.5) { + bezt_next = bezt; + break; + } + } + + if (bezt_next==NULL) return 0; + + if (val) { + w1 = framef - bezt_prev->vec[1][0]; + w2 = bezt_next->vec[1][0] - framef; + wtot = w1 + w2; + w1=w1/wtot; + w2=w2/wtot; +#if 0 + val = (bezt_prev->vec[1][1] * w2) + (bezt_next->vec[1][1] * w1); +#else + /* apply the value with a hard coded 6th */ + *val = (((bezt_prev->vec[1][1] * w2) + (bezt_next->vec[1][1] * w1)) + (*val * 5.0f)) / 6.0f; +#endif + } + + if (frame_prev) *frame_prev = bezt_prev->vec[1][0]; + if (frame_next) *frame_next = bezt_next->vec[1][0]; + + return 1; + } +} + +void pose_relax() +{ + Object *ob = OBACT; + bPose *pose; + bAction *act; + bArmature *arm; + + IpoCurve *icu_w, *icu_x, *icu_y, *icu_z; + + bPoseChannel *pchan; + bActionChannel *achan; + float framef = F_CFRA; + float frame_prev, frame_next; + float quat_prev[4], quat_next[4], quat_interp[4], quat_orig[4]; + + /*int do_scale = 0; + int do_loc = 0; + int do_quat = 0; + int flag = 0;*/ + int do_w, do_x, do_y, do_z; + + if (!ob) return; + + pose = ob->pose; + act = ob->action; + arm = (bArmature *)ob->data; + + if (!pose || !act || !arm) return; + + for (pchan=pose->chanbase.first; pchan; pchan= pchan->next){ + if(pchan->bone->layer & arm->layer) { + if(pchan->bone->flag & BONE_SELECTED) { + /* do we have an ipo curve? */ + achan= get_action_channel(act, pchan->name); + if(achan && achan->ipo) { + /*calc_ipo(achan->ipo, ctime);*/ + + do_x = pose_relax_icu(find_ipocurve(achan->ipo, AC_LOC_X), framef, &pchan->loc[0], NULL, NULL); + do_y = pose_relax_icu(find_ipocurve(achan->ipo, AC_LOC_Y), framef, &pchan->loc[1], NULL, NULL); + do_z = pose_relax_icu(find_ipocurve(achan->ipo, AC_LOC_Z), framef, &pchan->loc[2], NULL, NULL); + /* do_loc = do_x + do_y + do_z */ + + if (G.flags & G_RECORDKEYS) { + if (do_x) insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_X, 0); + if (do_y) insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Y, 0); + if (do_z) insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Z, 0); + } + + do_x = pose_relax_icu(find_ipocurve(achan->ipo, AC_SIZE_X), framef, &pchan->size[0], NULL, NULL); + do_y = pose_relax_icu(find_ipocurve(achan->ipo, AC_SIZE_Y), framef, &pchan->size[1], NULL, NULL); + do_z = pose_relax_icu(find_ipocurve(achan->ipo, AC_SIZE_Z), framef, &pchan->size[2], NULL, NULL); + /* do_scale = do_x + do_y + do_z */ + + if (G.flags & G_RECORDKEYS) { + if (do_x) insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_X, 0); + if (do_y) insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Y, 0); + if (do_z) insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Z, 0); + } + + if( ((icu_w = find_ipocurve(achan->ipo, AC_QUAT_W))) && + ((icu_x = find_ipocurve(achan->ipo, AC_QUAT_X))) && + ((icu_y = find_ipocurve(achan->ipo, AC_QUAT_Y))) && + ((icu_z = find_ipocurve(achan->ipo, AC_QUAT_Z))) ) + { + /* use the quatw keyframe as a basis for others */ + if (pose_relax_icu(icu_w, framef, NULL, &frame_prev, &frame_next)) { + /* get 2 quats */ + quat_prev[0] = eval_icu(icu_w, frame_prev); + quat_prev[1] = eval_icu(icu_x, frame_prev); + quat_prev[2] = eval_icu(icu_y, frame_prev); + quat_prev[3] = eval_icu(icu_z, frame_prev); + + quat_next[0] = eval_icu(icu_w, frame_next); + quat_next[1] = eval_icu(icu_x, frame_next); + quat_next[2] = eval_icu(icu_y, frame_next); + quat_next[3] = eval_icu(icu_z, frame_next); + +#if 0 + /* apply the setting, completely smooth */ + QuatInterpol(pchan->quat, quat_prev, quat_next, (framef-frame_prev) / (frame_next-frame_prev) ); +#else + /* tricky interpolation */ + QuatInterpol(quat_interp, quat_prev, quat_next, (framef-frame_prev) / (frame_next-frame_prev) ); + QUATCOPY(quat_orig, pchan->quat); + QuatInterpol(pchan->quat, quat_orig, quat_interp, 1.0f/6.0f); + /* done */ +#endif + /*do_quat++;*/ + + if (G.flags & G_RECORDKEYS) { + insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_X, 0); + insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Y, 0); + insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Z, 0); + insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_W, 0); + } + } + } + + if (G.flags & G_RECORDKEYS) { + pchan->bone->flag &= ~BONE_UNKEYED; + } + } + } + } + } + + ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK); + +#if 0 +// /* auto-keyframing - dosnt work, no idea why, do manually above */ + if (do_loc) flag |= TFM_TRANSLATION; + if (do_scale) flag |= TFM_RESIZE; + if (do_quat) flag |= TFM_ROTATION; + autokeyframe_pose_cb_func(ob, flag, 0); +#endif + + + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + BIF_undo_push("Relax Pose"); + +} diff --git a/source/blender/src/reeb.c b/source/blender/src/reeb.c new file mode 100644 index 00000000000..85fb5815c3e --- /dev/null +++ b/source/blender/src/reeb.c @@ -0,0 +1,1923 @@ +/** + * $Id: + * + * ***** 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * Contributor(s): Martin Poirier + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <math.h> +#include <string.h> // for memcpy +#include <stdio.h> +#include <stdlib.h> // for qsort + +#include "DNA_listBase.h" +#include "DNA_scene_types.h" +#include "DNA_space_types.h" +#include "DNA_meshdata_types.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "BLI_editVert.h" +#include "BLI_edgehash.h" + +#include "BDR_editobject.h" + +#include "BIF_editmesh.h" +#include "BIF_editarmature.h" +#include "BIF_interface.h" +#include "BIF_toolbox.h" +#include "BIF_graphics.h" + +#include "BKE_global.h" +#include "BKE_utildefines.h" +#include "BKE_customdata.h" + +#include "blendef.h" + +#include "ONL_opennl.h" + +#include "reeb.h" + +/* + * Skeleton generation algorithm based on: + * "Harmonic Skeleton for Realistic Character Animation" + * Gregoire Aujay, Franck Hetroy, Francis Lazarus and Christine Depraz + * SIGGRAPH 2007 + * + * Reeb graph generation algorithm based on: + * "Robust On-line Computation of Reeb Graphs: Simplicity and Speed" + * Valerio Pascucci, Giorgio Scorzelli, Peer-Timo Bremer and Ajith Mascarenhas + * SIGGRAPH 2007 + * + * */ + +int mergeArcs(ReebGraph *rg, ReebArc *a0, ReebArc *a1); +int mergeConnectedArcs(ReebGraph *rg, ReebArc *a0, ReebArc *a1); +EditEdge * NextEdgeForVert(EditMesh *em, EditVert *v); + +/***************************************** BUCKET UTILS **********************************************/ + +void addVertToBucket(EmbedBucket *b, float co[3]) +{ + b->nv++; + VecLerpf(b->p, b->p, co, 1.0f / b->nv); +} + +void removeVertFromBucket(EmbedBucket *b, float co[3]) +{ + VecMulf(b->p, (float)b->nv); + VecSubf(b->p, b->p, co); + b->nv--; + VecMulf(b->p, 1.0f / (float)b->nv); +} + +void mergeBuckets(EmbedBucket *bDst, EmbedBucket *bSrc) +{ + if (bDst->nv > 0 && bSrc->nv > 0) + { + bDst->nv += bSrc->nv; + VecLerpf(bDst->p, bDst->p, bSrc->p, (float)bSrc->nv / (float)(bDst->nv)); + } + else if (bSrc->nv > 0) + { + bDst->nv = bSrc->nv; + VECCOPY(bDst->p, bSrc->p); + } +} + +void mergeArcBuckets(ReebArc *aDst, ReebArc *aSrc, float start, float end) +{ + if (aDst->bcount > 0 && aSrc->bcount > 0) + { + int indexDst = 0, indexSrc = 0; + + start = MAX3(start, aDst->buckets[0].val, aSrc->buckets[0].val); + + while(indexDst < aDst->bcount && aDst->buckets[indexDst].val < start) + { + indexDst++; + } + + while(indexSrc < aSrc->bcount && aSrc->buckets[indexSrc].val < start) + { + indexSrc++; + } + + for( ; indexDst < aDst->bcount && + indexSrc < aSrc->bcount && + aDst->buckets[indexDst].val <= end && + aSrc->buckets[indexSrc].val <= end + + ; indexDst++, indexSrc++) + { + mergeBuckets(aDst->buckets + indexDst, aSrc->buckets + indexSrc); + } + } +} + +void allocArcBuckets(ReebArc *arc) +{ + int i; + float start = ceil(arc->v1->weight); + arc->bcount = (int)(floor(arc->v2->weight) - start) + 1; + + if (arc->bcount > 0) + { + arc->buckets = MEM_callocN(sizeof(EmbedBucket) * arc->bcount, "embed bucket"); + + for(i = 0; i < arc->bcount; i++) + { + arc->buckets[i].val = start + i; + } + } + else + { + arc->buckets = NULL; + } + +} + +void resizeArcBuckets(ReebArc *arc) +{ + EmbedBucket *oldBuckets = arc->buckets; + int oldBCount = arc->bcount; + + allocArcBuckets(arc); + + if (oldBCount != 0 && arc->bcount != 0) + { + int oldStart = (int)oldBuckets[0].val; + int oldEnd = (int)oldBuckets[oldBCount - 1].val; + int newStart = (int)arc->buckets[0].val; + int newEnd = (int)arc->buckets[arc->bcount - 1].val; + int oldOffset = 0; + int newOffset = 0; + int len; + + if (oldStart < newStart) + { + oldOffset = newStart - oldStart; + } + else + { + newOffset = oldStart - newStart; + } + + len = MIN2(oldEnd - (oldStart + oldOffset) + 1, newEnd - (newStart - newOffset) + 1); + + memcpy(arc->buckets + newOffset, oldBuckets + oldOffset, len * sizeof(EmbedBucket)); + } + + if (oldBuckets != NULL) + { + MEM_freeN(oldBuckets); + } +} +/***************************************** UTILS **********************************************/ + +ReebEdge * copyEdge(ReebEdge *edge) +{ + ReebEdge *newEdge = NULL; + + newEdge = MEM_callocN(sizeof(ReebEdge), "reeb edge"); + memcpy(newEdge, edge, sizeof(ReebEdge)); + + newEdge->next = NULL; + newEdge->prev = NULL; + + return newEdge; +} + +void printArc(ReebArc *arc) +{ + ReebEdge *edge; + printf("arc: (%i)%f -> (%i)%f\n", arc->v1->index, arc->v1->weight, arc->v2->index, arc->v2->weight); + + for(edge = arc->edges.first; edge ; edge = edge->next) + { + printf("\tedge (%i, %i)\n", edge->v1->index, edge->v2->index); + } +} + +void freeArc(ReebArc *arc) +{ + BLI_freelistN(&arc->edges); + + if (arc->buckets) + MEM_freeN(arc->buckets); + + MEM_freeN(arc); +} + +void freeGraph(ReebGraph *rg) +{ + ReebArc *arc; + ReebNode *node; + + // free nodes + for( node = rg->nodes.first; node; node = node->next ) + { + // Free adjacency lists + if (node->arcs != NULL) + { + MEM_freeN(node->arcs); + } + } + BLI_freelistN(&rg->nodes); + + // free arcs + arc = rg->arcs.first; + while( arc ) + { + ReebArc *next = arc->next; + freeArc(arc); + arc = next; + } + + // free edge map + BLI_edgehash_free(rg->emap, NULL); + + MEM_freeN(rg); +} + +void repositionNodes(ReebGraph *rg) +{ + ReebArc *arc = NULL; + ReebNode *node = NULL; + + // Reset node positions + for(node = rg->nodes.first; node; node = node->next) + { + node->p[0] = node->p[1] = node->p[2] = 0; + } + + for(arc = rg->arcs.first; arc; arc = arc->next) + { + if (arc->bcount > 0) + { + float p[3]; + + VECCOPY(p, arc->buckets[0].p); + VecMulf(p, 1.0f / arc->v1->degree); + VecAddf(arc->v1->p, arc->v1->p, p); + + VECCOPY(p, arc->buckets[arc->bcount - 1].p); + VecMulf(p, 1.0f / arc->v2->degree); + VecAddf(arc->v2->p, arc->v2->p, p); + } + } +} + +void verifyNodeDegree(ReebGraph *rg) +{ + ReebNode *node = NULL; + ReebArc *arc = NULL; + + for(node = rg->nodes.first; node; node = node->next) + { + int count = 0; + for(arc = rg->arcs.first; arc; arc = arc->next) + { + if (arc->v1 == node || arc->v2 == node) + { + count++; + } + } + if (count != node->degree) + { + printf("degree error in node %i: expected %i got %i\n", node->index, count, node->degree); + } + } +} + +void verifyBuckets(ReebGraph *rg) +{ +#ifdef DEBUG_REEB + ReebArc *arc = NULL; + for(arc = rg->arcs.first; arc; arc = arc->next) + { + if (arc->bcount > 0) + { + int i; + for(i = 0; i < arc->bcount; i++) + { + if (arc->buckets[i].nv == 0) + { + printArc(arc); + printf("count error in bucket %i/%i\n", i+1, arc->bcount); + } + } + + if (ceil(arc->v1->weight) < arc->buckets[0].val) + { + printArc(arc); + printf("alloc error in first bucket: %f should be %f \n", arc->buckets[0].val, ceil(arc->v1->weight)); + } + if (floor(arc->v2->weight) < arc->buckets[arc->bcount - 1].val) + { + printArc(arc); + printf("alloc error in last bucket: %f should be %f \n", arc->buckets[arc->bcount - 1].val, floor(arc->v2->weight)); + } + } + } +#endif +} + +/************************************** ADJACENCY LIST *************************************************/ + +void addArcToNodeAdjacencyList(ReebNode *node, ReebArc *arc) +{ + ReebArc **arclist; + + for(arclist = node->arcs; *arclist; arclist++) + { } + + *arclist = arc; +} + +void buildAdjacencyList(ReebGraph *rg) +{ + ReebNode *node = NULL; + ReebArc *arc = NULL; + + for(node = rg->nodes.first; node; node = node->next) + { + if (node->arcs != NULL) + { + MEM_freeN(node->arcs); + } + + node->arcs = MEM_callocN((node->degree + 1) * sizeof(ReebArc*), "adjacency list"); + } + + for(arc = rg->arcs.first; arc; arc= arc->next) + { + addArcToNodeAdjacencyList(arc->v1, arc); + addArcToNodeAdjacencyList(arc->v2, arc); + } +} + +int hasAdjacencyList(ReebGraph *rg) +{ + ReebNode *node; + + for(node = rg->nodes.first; node; node = node->next) + { + if (node->arcs == NULL) + { + return 0; + } + } + + return 1; +} + +int countConnectedArcs(ReebGraph *rg, ReebNode *node) +{ + int count = 0; + + /* use adjacency list if present */ + if (node->arcs) + { + ReebArc **arcs; + + for(arcs = node->arcs; *arcs; arcs++) + { + count++; + } + } + else + { + ReebArc *arc; + for(arc = rg->arcs.first; arc; arc = arc->next) + { + if (arc->v1 == node || arc->v2 == node) + { + count++; + } + } + } + + return count; +} + +/****************************************** SMOOTHING **************************************************/ + +void postprocessGraph(ReebGraph *rg, char mode) +{ + ReebArc *arc; + float fac1 = 0, fac2 = 1, fac3 = 0; + + switch(mode) + { + case SKGEN_AVERAGE: + fac1 = fac2 = fac3 = 1.0f / 3.0f; + break; + case SKGEN_SMOOTH: + fac1 = fac3 = 0.25f; + fac2 = 0.5f; + break; + case SKGEN_SHARPEN: + fac1 = fac2 = -0.25f; + fac2 = 1.5f; + break; + default: + error("Unknown post processing mode"); + return; + } + + for(arc = rg->arcs.first; arc; arc = arc->next) + { + EmbedBucket *buckets = arc->buckets; + int bcount = arc->bcount; + int index; + + for(index = 1; index < bcount - 1; index++) + { + VecLerpf(buckets[index].p, buckets[index].p, buckets[index - 1].p, fac1 / (fac1 + fac2)); + VecLerpf(buckets[index].p, buckets[index].p, buckets[index + 1].p, fac3 / (fac1 + fac2 + fac3)); + } + } +} + +/********************************************SORTING****************************************************/ + +int compareNodesWeight(void *vnode1, void *vnode2) +{ + ReebNode *node1 = (ReebNode*)vnode1; + ReebNode *node2 = (ReebNode*)vnode2; + + if (node1->weight < node2->weight) + { + return -1; + } + if (node1->weight > node2->weight) + { + return 1; + } + else + { + return 0; + } +} + +void sortNodes(ReebGraph *rg) +{ + BLI_sortlist(&rg->nodes, compareNodesWeight); +} + +int compareArcsWeight(void *varc1, void *varc2) +{ + ReebArc *arc1 = (ReebArc*)varc1; + ReebArc *arc2 = (ReebArc*)varc2; + + if (arc1->v1->weight < arc2->v1->weight) + { + return -1; + } + if (arc1->v1->weight > arc2->v1->weight) + { + return 1; + } + else + { + return 0; + } +} + +void sortArcs(ReebGraph *rg) +{ + BLI_sortlist(&rg->arcs, compareArcsWeight); +} + +/****************************************** FILTERING **************************************************/ + +int compareArcs(void *varc1, void *varc2) +{ + ReebArc *arc1 = (ReebArc*)varc1; + ReebArc *arc2 = (ReebArc*)varc2; + float len1 = arc1->v2->weight - arc1->v1->weight; + float len2 = arc2->v2->weight - arc2->v1->weight; + + if (len1 < len2) + { + return -1; + } + if (len1 > len2) + { + return 1; + } + else + { + return 0; + } +} + +void filterArc(ReebGraph *rg, ReebNode *newNode, ReebNode *removedNode, ReebArc * srcArc, int merging) +{ + ReebArc *arc = NULL, *nextArc = NULL; + + /* first pass, merge buckets for arcs that spawned the two nodes into the source arc*/ + for(arc = rg->arcs.first; arc; arc = arc->next) + { + if (arc->v1 == srcArc->v1 && arc->v2 == srcArc->v2 && arc != srcArc) + { + mergeArcBuckets(srcArc, arc, srcArc->v1->weight, srcArc->v2->weight); + } + } + + /* second pass, replace removedNode by newNode, remove arcs that are collapsed in a loop */ + arc = rg->arcs.first; + while(arc) + { + nextArc = arc->next; + + if (arc->v1 == removedNode || arc->v2 == removedNode) + { + if (arc->v1 == removedNode) + { + arc->v1 = newNode; + } + else + { + arc->v2 = newNode; + } + + // Remove looped arcs + if (arc->v1 == arc->v2) + { + // v1 or v2 was already newNode, since we're removing an arc, decrement degree + newNode->degree--; + + // If it's safeArc, it'll be removed later, so keep it for now + if (arc != srcArc) + { + BLI_remlink(&rg->arcs, arc); + freeArc(arc); + } + } + // Remove flipped arcs + else if (arc->v1->weight > arc->v2->weight) + { + // Decrement degree from the other node + OTHER_NODE(arc, newNode)->degree--; + + BLI_remlink(&rg->arcs, arc); + freeArc(arc); + } + else + { + newNode->degree++; // incrementing degree since we're adding an arc + + if (merging) + { + // resize bucket list + resizeArcBuckets(arc); + mergeArcBuckets(arc, srcArc, arc->v1->weight, arc->v2->weight); + } + } + } + + arc = nextArc; + } +} + +void filterNullReebGraph(ReebGraph *rg) +{ + ReebArc *arc = NULL, *nextArc = NULL; + + arc = rg->arcs.first; + while(arc) + { + nextArc = arc->next; + // Only collapse arcs too short to have any embed bucket + if (arc->bcount == 0) + { + ReebNode *newNode = arc->v1; + ReebNode *removedNode = arc->v2; + float blend; + + blend = (float)newNode->degree / (float)(newNode->degree + removedNode->degree); // blending factors + + //newNode->weight = FloatLerpf(newNode->weight, removedNode->weight, blend); + VecLerpf(newNode->p, newNode->p, removedNode->p, blend); + + filterArc(rg, newNode, removedNode, arc, 0); + + // Reset nextArc, it might have changed + nextArc = arc->next; + + BLI_remlink(&rg->arcs, arc); + freeArc(arc); + + BLI_freelinkN(&rg->nodes, removedNode); + } + + arc = nextArc; + } +} + +int filterInternalReebGraph(ReebGraph *rg, float threshold) +{ + ReebArc *arc = NULL, *nextArc = NULL; + int value = 0; + + BLI_sortlist(&rg->arcs, compareArcs); + + arc = rg->arcs.first; + while(arc) + { + nextArc = arc->next; + + // Only collapse non-terminal arcs that are shorter than threshold + if ((arc->v1->degree > 1 && arc->v2->degree > 1 && arc->v2->weight - arc->v1->weight < threshold)) + { + ReebNode *newNode = NULL; + ReebNode *removedNode = NULL; + + /* Keep the node with the highestn number of connected arcs */ + if (arc->v1->degree >= arc->v2->degree) + { + newNode = arc->v1; + removedNode = arc->v2; + } + else + { + newNode = arc->v2; + removedNode = arc->v1; + } + + filterArc(rg, newNode, removedNode, arc, 1); + + // Reset nextArc, it might have changed + nextArc = arc->next; + + BLI_remlink(&rg->arcs, arc); + freeArc(arc); + + BLI_freelinkN(&rg->nodes, removedNode); + value = 1; + } + + arc = nextArc; + } + + return value; +} + +int filterExternalReebGraph(ReebGraph *rg, float threshold) +{ + ReebArc *arc = NULL, *nextArc = NULL; + int value = 0; + + BLI_sortlist(&rg->arcs, compareArcs); + + arc = rg->arcs.first; + while(arc) + { + nextArc = arc->next; + + // Only collapse terminal arcs that are shorter than threshold + if ((arc->v1->degree == 1 || arc->v2->degree == 1) && arc->v2->weight - arc->v1->weight < threshold) + { + ReebNode *terminalNode = NULL; + ReebNode *middleNode = NULL; + ReebNode *newNode = NULL; + ReebNode *removedNode = NULL; + int merging = 0; + + // Assign terminal and middle nodes + if (arc->v1->degree == 1) + { + terminalNode = arc->v1; + middleNode = arc->v2; + } + else + { + terminalNode = arc->v2; + middleNode = arc->v1; + } + + // If middle node is a normal node, merge to terminal node + if (middleNode->degree == 2) + { + merging = 1; + newNode = terminalNode; + removedNode = middleNode; + } + // Otherwise, just plain remove of the arc + else + { + merging = 0; + newNode = middleNode; + removedNode = terminalNode; + } + + // Merging arc + if (merging) + { + filterArc(rg, newNode, removedNode, arc, 1); + } + else + { + // removing arc, so we need to decrease the degree of the remaining node + newNode->degree--; + } + + // Reset nextArc, it might have changed + nextArc = arc->next; + + BLI_remlink(&rg->arcs, arc); + freeArc(arc); + + BLI_freelinkN(&rg->nodes, removedNode); + value = 1; + } + + arc = nextArc; + } + + return value; +} + +/************************************** WEIGHT SPREADING ***********************************************/ + +int compareVerts( const void* a, const void* b ) +{ + EditVert *va = *(EditVert**)a; + EditVert *vb = *(EditVert**)b; + int value = 0; + + if (va->tmp.fp < vb->tmp.fp) + { + value = -1; + } + else if (va->tmp.fp > vb->tmp.fp) + { + value = 1; + } + + return value; +} + +void spreadWeight(EditMesh *em) +{ + EditVert **verts, *eve; + float lastWeight = 0.0f; + int totvert = BLI_countlist(&em->verts); + int i; + int work_needed = 1; + + verts = MEM_callocN(sizeof(EditVert*) * totvert, "verts array"); + + for(eve = em->verts.first, i = 0; eve; eve = eve->next, i++) + { + verts[i] = eve; + } + + while(work_needed == 1) + { + work_needed = 0; + qsort(verts, totvert, sizeof(EditVert*), compareVerts); + + for(i = 0; i < totvert; i++) + { + eve = verts[i]; + + if (i == 0 || (eve->tmp.fp - lastWeight) > FLT_EPSILON) + { + lastWeight = eve->tmp.fp; + } + else + { + work_needed = 1; + eve->tmp.fp = lastWeight + FLT_EPSILON * 2; + lastWeight = eve->tmp.fp; + } + } + } + + MEM_freeN(verts); +} +/*********************************** GRAPH AS TREE FUNCTIONS *******************************************/ + +int subtreeDepth(ReebNode *node, ReebArc *rootArc) +{ + int depth = 0; + + /* Base case, no arcs leading away */ + if (node->arcs == NULL || *(node->arcs) == NULL) + { + return 0; + } + else + { + ReebArc ** pArc; + + for(pArc = node->arcs; *pArc; pArc++) + { + ReebArc *arc = *pArc; + + /* only arcs that go down the tree */ + if (arc != rootArc) + { + ReebNode *newNode = OTHER_NODE(arc, node); + depth = MAX2(depth, subtreeDepth(newNode, arc)); + } + } + } + + return depth + 1; +} + +/*************************************** CYCLE DETECTION ***********************************************/ + +int detectCycle(ReebNode *node, ReebArc *srcArc) +{ + int value = 0; + + if (node->flags == 0) + { + ReebArc ** pArc; + + /* mark node as visited */ + node->flags = 1; + + for(pArc = node->arcs; *pArc && value == 0; pArc++) + { + ReebArc *arc = *pArc; + + /* don't go back on the source arc */ + if (arc != srcArc) + { + value = detectCycle(OTHER_NODE(arc, node), arc); + } + } + } + else + { + value = 1; + } + + return value; +} + +int isGraphCyclic(ReebGraph *rg) +{ + ReebNode *node; + int value = 0; + + /* NEED TO CHECK IF ADJACENCY LIST EXIST */ + + /* Mark all nodes as not visited */ + for(node = rg->nodes.first; node; node = node->next) + { + node->flags = 0; + } + + /* detectCycles in subgraphs */ + for(node = rg->nodes.first; node && value == 0; node = node->next) + { + /* only for nodes in subgraphs that haven't been visited yet */ + if (node->flags == 0) + { + value = value || detectCycle(node, NULL); + } + } + + return value; +} + +/******************************************** EXPORT ***************************************************/ + +void exportNode(FILE *f, char *text, ReebNode *node) +{ + fprintf(f, "%s i:%i w:%f d:%i %f %f %f\n", text, node->index, node->weight, node->degree, node->p[0], node->p[1], node->p[2]); +} + +void exportGraph(ReebGraph *rg, int count) +{ +#ifdef DEBUG_REEB + ReebArc *arc; + char filename[128]; + FILE *f; + + if (count == -1) + { + sprintf(filename, "test.txt"); + } + else + { + sprintf(filename, "test%05i.txt", count); + } + f = fopen(filename, "w"); + + for(arc = rg->arcs.first; arc; arc = arc->next) + { + int i; + + exportNode(f, "v1", arc->v1); + + for(i = 0; i < arc->bcount; i++) + { + fprintf(f, "b nv:%i %f %f %f\n", arc->buckets[i].nv, arc->buckets[i].p[0], arc->buckets[i].p[1], arc->buckets[i].p[2]); + } + + exportNode(f, "v2", arc->v2); + } + + fclose(f); +#endif +} + +/***************************************** MAIN ALGORITHM **********************************************/ + +ReebArc * findConnectedArc(ReebGraph *rg, ReebArc *arc, ReebNode *v) +{ + ReebArc *nextArc = arc->next; + + for(nextArc = rg->arcs.first; nextArc; nextArc = nextArc->next) + { + if (arc != nextArc && (nextArc->v1 == v || nextArc->v2 == v)) + { + break; + } + } + + return nextArc; +} + +void removeNormalNodes(ReebGraph *rg) +{ + ReebArc *arc; + + // Merge degree 2 nodes + for(arc = rg->arcs.first; arc; arc = arc->next) + { + while (arc->v1->degree == 2 || arc->v2->degree == 2) + { + // merge at v1 + if (arc->v1->degree == 2) + { + ReebArc *nextArc = findConnectedArc(rg, arc, arc->v1); + + // Merge arc only if needed + if (arc->v1 == nextArc->v2) + { + mergeConnectedArcs(rg, arc, nextArc); + } + // Otherwise, mark down vert + else + { + arc->v1->degree = 3; + } + } + + // merge at v2 + if (arc->v2->degree == 2) + { + ReebArc *nextArc = findConnectedArc(rg, arc, arc->v2); + + // Merge arc only if needed + if (arc->v2 == nextArc->v1) + { + mergeConnectedArcs(rg, arc, nextArc); + } + // Otherwise, mark down vert + else + { + arc->v2->degree = 3; + } + } + } + } + +} + +int edgeEquals(ReebEdge *e1, ReebEdge *e2) +{ + return (e1->v1 == e2->v1 && e1->v2 == e2->v2); +} + +ReebArc *nextArcMappedToEdge(ReebArc *arc, ReebEdge *e) +{ + ReebEdge *nextEdge = NULL; + ReebEdge *edge = NULL; + ReebArc *result = NULL; + + /* Find the ReebEdge in the edge list */ + for(edge = arc->edges.first; edge && !edgeEquals(edge, e); edge = edge->next) + { } + + nextEdge = edge->nextEdge; + + if (nextEdge != NULL) + { + result = nextEdge->arc; + } + + return result; +} + +typedef enum { + MERGE_LOWER, + MERGE_HIGHER, + MERGE_APPEND +} MergeDirection; + +void mergeArcEdges(ReebGraph *rg, ReebArc *aDst, ReebArc *aSrc, MergeDirection direction) +{ + ReebEdge *e = NULL; + + if (direction == MERGE_APPEND) + { + for(e = aSrc->edges.first; e; e = e->next) + { + e->arc = aDst; // Edge is stolen by new arc + } + + addlisttolist(&aDst->edges , &aSrc->edges); + } + else + { + for(e = aSrc->edges.first; e; e = e->next) + { + ReebEdge *newEdge = copyEdge(e); + + newEdge->arc = aDst; + + BLI_addtail(&aDst->edges, newEdge); + + if (direction == MERGE_LOWER) + { + void **p = BLI_edgehash_lookup_p(rg->emap, e->v1->index, e->v2->index); + + newEdge->nextEdge = e; + + // if edge was the first in the list, point the edit edge to the new reeb edge instead. + if (*p == e) + { + *p = (void*)newEdge; + } + // otherwise, advance in the list until the predecessor is found then insert it there + else + { + ReebEdge *previous = (ReebEdge*)*p; + + while(previous->nextEdge != e) + { + previous = previous->nextEdge; + } + + previous->nextEdge = newEdge; + } + } + else + { + newEdge->nextEdge = e->nextEdge; + e->nextEdge = newEdge; + } + } + } +} + +// return 1 on full merge +int mergeConnectedArcs(ReebGraph *rg, ReebArc *a0, ReebArc *a1) +{ + int result = 0; + ReebNode *removedNode = NULL; + + mergeArcEdges(rg, a0, a1, MERGE_APPEND); + + // Bring a0 to the combine length of both arcs + if (a0->v2 == a1->v1) + { + removedNode = a0->v2; + a0->v2 = a1->v2; + } + else if (a0->v1 == a1->v2) + { + removedNode = a0->v1; + a0->v1 = a1->v1; + } + + resizeArcBuckets(a0); + // Merge a1 in a0 + mergeArcBuckets(a0, a1, a0->v1->weight, a0->v2->weight); + + // remove a1 from graph + BLI_remlink(&rg->arcs, a1); + freeArc(a1); + + BLI_freelinkN(&rg->nodes, removedNode); + result = 1; + + return result; +} +// return 1 on full merge +int mergeArcs(ReebGraph *rg, ReebArc *a0, ReebArc *a1) +{ + int result = 0; + // TRIANGLE POINTS DOWN + if (a0->v1->weight == a1->v1->weight) // heads are the same + { + if (a0->v2->weight == a1->v2->weight) // tails also the same, arcs can be totally merge together + { + mergeArcEdges(rg, a0, a1, MERGE_APPEND); + + mergeArcBuckets(a0, a1, a0->v1->weight, a0->v2->weight); + + // Adjust node degree + a1->v1->degree--; + a1->v2->degree--; + + // remove a1 from graph + BLI_remlink(&rg->arcs, a1); + + freeArc(a1); + result = 1; + } + else if (a0->v2->weight > a1->v2->weight) // a1->v2->weight is in the middle + { + mergeArcEdges(rg, a1, a0, MERGE_LOWER); + + // Adjust node degree + a0->v1->degree--; + a1->v2->degree++; + + mergeArcBuckets(a1, a0, a1->v1->weight, a1->v2->weight); + a0->v1 = a1->v2; + resizeArcBuckets(a0); + } + else // a0>n2 is in the middle + { + mergeArcEdges(rg, a0, a1, MERGE_LOWER); + + // Adjust node degree + a1->v1->degree--; + a0->v2->degree++; + + mergeArcBuckets(a0, a1, a0->v1->weight, a0->v2->weight); + a1->v1 = a0->v2; + resizeArcBuckets(a1); + } + } + // TRIANGLE POINTS UP + else if (a0->v2->weight == a1->v2->weight) // tails are the same + { + if (a0->v1->weight > a1->v1->weight) // a0->v1->weight is in the middle + { + mergeArcEdges(rg, a0, a1, MERGE_HIGHER); + + // Adjust node degree + a1->v2->degree--; + a0->v1->degree++; + + mergeArcBuckets(a0, a1, a0->v1->weight, a0->v2->weight); + a1->v2 = a0->v1; + resizeArcBuckets(a1); + } + else // a1->v1->weight is in the middle + { + mergeArcEdges(rg, a1, a0, MERGE_HIGHER); + + // Adjust node degree + a0->v2->degree--; + a1->v1->degree++; + + mergeArcBuckets(a1, a0, a1->v1->weight, a1->v2->weight); + a0->v2 = a1->v1; + resizeArcBuckets(a0); + } + } + else + { + // Need something here (OR NOT) + } + + return result; +} + +void glueByMergeSort(ReebGraph *rg, ReebArc *a0, ReebArc *a1, ReebEdge *e0, ReebEdge *e1) +{ + int total = 0; + while (total == 0 && a0 != a1 && a0 != NULL && a1 != NULL) + { + total = mergeArcs(rg, a0, a1); + + if (total == 0) // if it wasn't a total merge, go forward + { + if (a0->v2->weight < a1->v2->weight) + { + a0 = nextArcMappedToEdge(a0, e0); + } + else + { + a1 = nextArcMappedToEdge(a1, e1); + } + } + } +} + +void mergePaths(ReebGraph *rg, ReebEdge *e0, ReebEdge *e1, ReebEdge *e2) +{ + ReebArc *a0, *a1, *a2; + a0 = e0->arc; + a1 = e1->arc; + a2 = e2->arc; + + glueByMergeSort(rg, a0, a1, e0, e1); + glueByMergeSort(rg, a0, a2, e0, e2); +} + +ReebNode * addNode(ReebGraph *rg, EditVert *eve, float weight) +{ + ReebNode *node = NULL; + + node = MEM_callocN(sizeof(ReebNode), "reeb node"); + + node->flags = 0; // clear flags on init + node->arcs = NULL; + node->degree = 0; + node->weight = weight; + node->index = rg->totnodes; + VECCOPY(node->p, eve->co); + + BLI_addtail(&rg->nodes, node); + rg->totnodes++; + + return node; +} + +ReebEdge * createArc(ReebGraph *rg, ReebNode *node1, ReebNode *node2) +{ + ReebEdge *edge; + + edge = BLI_edgehash_lookup(rg->emap, node1->index, node2->index); + + // Only add existing edges that haven't been added yet + if (edge == NULL) + { + ReebArc *arc; + ReebNode *v1, *v2; + float len, offset; + int i; + + arc = MEM_callocN(sizeof(ReebArc), "reeb arc"); + edge = MEM_callocN(sizeof(ReebEdge), "reeb edge"); + + arc->flags = 0; // clear flags on init + + if (node1->weight <= node2->weight) + { + v1 = node1; + v2 = node2; + } + else + { + v1 = node2; + v2 = node1; + } + + arc->v1 = v1; + arc->v2 = v2; + + // increase node degree + v1->degree++; + v2->degree++; + + BLI_edgehash_insert(rg->emap, node1->index, node2->index, edge); + + edge->arc = arc; + edge->nextEdge = NULL; + edge->v1 = v1; + edge->v2 = v2; + + BLI_addtail(&rg->arcs, arc); + BLI_addtail(&arc->edges, edge); + + /* adding buckets for embedding */ + allocArcBuckets(arc); + + offset = arc->v1->weight; + len = arc->v2->weight - arc->v1->weight; + +#if 0 + /* This is the actual embedding filling described in the paper + * the problem is that it only works with really dense meshes + */ + if (arc->bcount > 0) + { + addVertToBucket(&(arc->buckets[0]), arc->v1->co); + addVertToBucket(&(arc->buckets[arc->bcount - 1]), arc->v2->co); + } +#else + for(i = 0; i < arc->bcount; i++) + { + float co[3]; + float f = (arc->buckets[i].val - offset) / len; + + VecLerpf(co, v1->p, v2->p, f); + addVertToBucket(&(arc->buckets[i]), co); + } +#endif + + } + + return edge; +} + +void addTriangleToGraph(ReebGraph *rg, ReebNode * n1, ReebNode * n2, ReebNode * n3) +{ + ReebEdge *re1, *re2, *re3; + ReebEdge *e1, *e2, *e3; + float len1, len2, len3; + + re1 = createArc(rg, n1, n2); + re2 = createArc(rg, n2, n3); + re3 = createArc(rg, n3, n1); + + len1 = (float)fabs(n1->weight - n2->weight); + len2 = (float)fabs(n2->weight - n3->weight); + len3 = (float)fabs(n3->weight - n1->weight); + + /* The rest of the algorithm assumes that e1 is the longest edge */ + + if (len1 >= len2 && len1 >= len3) + { + e1 = re1; + e2 = re2; + e3 = re3; + } + else if (len2 >= len1 && len2 >= len3) + { + e1 = re2; + e2 = re1; + e3 = re3; + } + else + { + e1 = re3; + e2 = re2; + e3 = re1; + } + + /* And e2 is the lowest edge + * If e3 is lower than e2, swap them + */ + if (e3->v1->weight < e2->v1->weight) + { + ReebEdge *etmp = e2; + e2 = e3; + e3 = etmp; + } + + + mergePaths(rg, e1, e2, e3); +} + +ReebGraph * generateReebGraph(EditMesh *em, int subdivisions) +{ + ReebGraph *rg; + struct DynamicList * dlist; + EditVert *eve; + EditFace *efa; + int index; + int totvert; + int totfaces; + +#ifdef DEBUG_REEB + int countfaces = 0; +#endif + + rg = MEM_callocN(sizeof(ReebGraph), "reeb graph"); + + rg->totnodes = 0; + rg->emap = BLI_edgehash_new(); + + totvert = BLI_countlist(&em->verts); + totfaces = BLI_countlist(&em->faces); + + renormalizeWeight(em, 1.0f); + + /* Spread weight to minimize errors */ + spreadWeight(em); + + renormalizeWeight(em, (float)subdivisions); + + /* Adding vertice */ + for(index = 0, eve = em->verts.first; eve; index++, eve = eve->next) + { + eve->hash = index; + eve->f2 = 0; + eve->tmp.p = addNode(rg, eve, eve->tmp.fp); + } + + /* Temporarely convert node list to dynamic list, for indexed access */ + dlist = BLI_dlist_from_listbase(&rg->nodes); + + /* Adding face, edge per edge */ + for(efa = em->faces.first; efa; efa = efa->next) + { + ReebNode *n1, *n2, *n3; + + n1 = (ReebNode*)BLI_dlist_find_link(dlist, efa->v1->hash); + n2 = (ReebNode*)BLI_dlist_find_link(dlist, efa->v2->hash); + n3 = (ReebNode*)BLI_dlist_find_link(dlist, efa->v3->hash); + + addTriangleToGraph(rg, n1, n2, n3); + + if (efa->v4) + { + ReebNode *n4 = (ReebNode*)efa->v4->tmp.p; + addTriangleToGraph(rg, n1, n3, n4); + } + +#ifdef DEBUG_REEB + countfaces++; + if (countfaces % 100 == 0) + { + printf("face %i of %i\n", countfaces, totfaces); + } +#endif + + + } + BLI_listbase_from_dlist(dlist, &rg->nodes); + + removeNormalNodes(rg); + + return rg; +} + +/***************************************** WEIGHT UTILS **********************************************/ + +void renormalizeWeight(EditMesh *em, float newmax) +{ + EditVert *eve; + float minimum, maximum, range; + + if (em == NULL || BLI_countlist(&em->verts) == 0) + return; + + /* First pass, determine maximum and minimum */ + eve = em->verts.first; + minimum = eve->tmp.fp; + maximum = eve->tmp.fp; + for(eve = em->verts.first; eve; eve = eve->next) + { + maximum = MAX2(maximum, eve->tmp.fp); + minimum = MIN2(minimum, eve->tmp.fp); + } + + range = maximum - minimum; + + /* Normalize weights */ + for(eve = em->verts.first; eve; eve = eve->next) + { + eve->tmp.fp = (eve->tmp.fp - minimum) / range * newmax; + } +} + + +int weightFromLoc(EditMesh *em, int axis) +{ + EditVert *eve; + + if (em == NULL || BLI_countlist(&em->verts) == 0 || axis < 0 || axis > 2) + return 0; + + /* Copy coordinate in weight */ + for(eve = em->verts.first; eve; eve = eve->next) + { + eve->tmp.fp = eve->co[axis]; + } + + return 1; +} + +static float cotan_weight(float *v1, float *v2, float *v3) +{ + float a[3], b[3], c[3], clen; + + VecSubf(a, v2, v1); + VecSubf(b, v3, v1); + Crossf(c, a, b); + + clen = VecLength(c); + + if (clen == 0.0f) + return 0.0f; + + return Inpf(a, b)/clen; +} + +int weightToHarmonic(EditMesh *em) +{ + NLboolean success; + EditVert *eve; + EditEdge *eed; + EditFace *efa; + int totvert = 0; + int index; + int rval; + + /* Find local extrema */ + for(eve = em->verts.first; eve; eve = eve->next) + { + totvert++; + } + + /* Solve with openNL */ + + nlNewContext(); + + nlSolverParameteri(NL_NB_VARIABLES, totvert); + + nlBegin(NL_SYSTEM); + + /* Find local extrema */ + for(index = 0, eve = em->verts.first; eve; index++, eve = eve->next) + { + EditEdge *eed; + int maximum = 1; + int minimum = 1; + + eve->hash = index; /* Assign index to vertex */ + + NextEdgeForVert(NULL, NULL); /* Reset next edge */ + for(eed = NextEdgeForVert(em, eve); eed && (maximum || minimum); eed = NextEdgeForVert(em, eve)) + { + EditVert *eve2; + + if (eed->v1 == eve) + { + eve2 = eed->v2; + } + else + { + eve2 = eed->v1; + } + + /* Adjacent vertex is bigger, not a local maximum */ + if (eve2->tmp.fp > eve->tmp.fp) + { + maximum = 0; + } + /* Adjacent vertex is smaller, not a local minimum */ + else if (eve2->tmp.fp < eve->tmp.fp) + { + minimum = 0; + } + } + + if (maximum || minimum) + { + float w = eve->tmp.fp; + eve->f1 = 0; + nlSetVariable(0, index, w); + nlLockVariable(index); + } + else + { + eve->f1 = 1; + } + } + + nlBegin(NL_MATRIX); + + /* Zero edge weight */ + for(eed = em->edges.first; eed; eed = eed->next) + { + eed->tmp.l = 0; + } + + /* Add faces count to the edge weight */ + for(efa = em->faces.first; efa; efa = efa->next) + { + efa->e1->tmp.l++; + efa->e2->tmp.l++; + efa->e3->tmp.l++; + } + + /* Add faces angle to the edge weight */ + for(efa = em->faces.first; efa; efa = efa->next) + { + /* Angle opposite e1 */ + float t1= cotan_weight(efa->v1->co, efa->v2->co, efa->v3->co) / efa->e2->tmp.l; + + /* Angle opposite e2 */ + float t2 = cotan_weight(efa->v2->co, efa->v3->co, efa->v1->co) / efa->e3->tmp.l; + + /* Angle opposite e3 */ + float t3 = cotan_weight(efa->v3->co, efa->v1->co, efa->v2->co) / efa->e1->tmp.l; + + int i1 = efa->v1->hash; + int i2 = efa->v2->hash; + int i3 = efa->v3->hash; + + nlMatrixAdd(i1, i1, t2+t3); + nlMatrixAdd(i2, i2, t1+t3); + nlMatrixAdd(i3, i3, t1+t2); + + nlMatrixAdd(i1, i2, -t3); + nlMatrixAdd(i2, i1, -t3); + + nlMatrixAdd(i2, i3, -t1); + nlMatrixAdd(i3, i2, -t1); + + nlMatrixAdd(i3, i1, -t2); + nlMatrixAdd(i1, i3, -t2); + } + + nlEnd(NL_MATRIX); + + nlEnd(NL_SYSTEM); + + success = nlSolveAdvanced(NULL, NL_TRUE); + + if (success) + { + rval = 1; + for(index = 0, eve = em->verts.first; eve; index++, eve = eve->next) + { + eve->tmp.fp = nlGetVariable(0, index); + } + } + else + { + rval = 0; + } + + nlDeleteContext(nlGetCurrent()); + + return rval; +} + + +EditEdge * NextEdgeForVert(EditMesh *em, EditVert *v) +{ + static EditEdge *e = NULL; + + /* Reset method, call with NULL mesh pointer */ + if (em == NULL) + { + e = NULL; + return NULL; + } + + /* first pass, start at the head of the list */ + if (e == NULL) + { + e = em->edges.first; + } + /* subsequent passes, start on the next edge */ + else + { + e = e->next; + } + + for( ; e ; e = e->next) + { + if (e->v1 == v || e->v2 == v) + { + break; + } + } + + return e; +} + +int weightFromDistance(EditMesh *em) +{ + EditVert *eve; + int totedge = 0; + int vCount = 0; + + if (em == NULL || BLI_countlist(&em->verts) == 0) + { + return 0; + } + + totedge = BLI_countlist(&em->edges); + + if (totedge == 0) + { + return 0; + } + + /* Initialize vertice flags and find at least one selected vertex */ + for(eve = em->verts.first; eve && vCount == 0; eve = eve->next) + { + eve->f1 = 0; + if (eve->f & SELECT) + { + vCount = 1; + } + } + + if (vCount == 0) + { + return 0; /* no selected vert, failure */ + } + else + { + EditVert *eve, *current_eve = NULL; + /* Apply dijkstra spf for each selected vert */ + for(eve = em->verts.first; eve; eve = eve->next) + { + if (eve->f & SELECT) + { + current_eve = eve; + eve->f1 = 1; + + { + EditEdge *eed = NULL; + EditEdge *select_eed = NULL; + EditEdge **edges = NULL; + float currentWeight = 0; + int eIndex = 0; + + edges = MEM_callocN(totedge * sizeof(EditEdge*), "Edges"); + + /* Calculate edge weight and initialize edge flags */ + for(eed= em->edges.first; eed; eed= eed->next) + { + eed->tmp.fp = VecLenf(eed->v1->co, eed->v2->co); + eed->f1 = 0; + } + + do { + int i; + + current_eve->f1 = 1; /* mark vertex as selected */ + + /* Add all new edges connected to current_eve to the list */ + NextEdgeForVert(NULL, NULL); // Reset next edge + for(eed = NextEdgeForVert(em, current_eve); eed; eed = NextEdgeForVert(em, current_eve)) + { + if (eed->f1 == 0) + { + edges[eIndex] = eed; + eed->f1 = 1; + eIndex++; + } + } + + /* Find next shortest edge */ + select_eed = NULL; + for(i = 0; i < eIndex; i++) + { + eed = edges[i]; + + if (eed->f1 != 2 && (eed->v1->f1 == 0 || eed->v2->f1 == 0)) /* eed is not selected yet and leads to a new node */ + { + float newWeight = 0; + if (eed->v1->f1 == 1) + { + newWeight = eed->v1->tmp.fp + eed->tmp.fp; + } + else + { + newWeight = eed->v2->tmp.fp + eed->tmp.fp; + } + + if (select_eed == NULL || newWeight < currentWeight) /* no selected edge or current smaller than selected */ + { + currentWeight = newWeight; + select_eed = eed; + } + } + } + + if (select_eed != NULL) + { + select_eed->f1 = 2; + + if (select_eed->v1->f1 == 0) /* v1 is the new vertex */ + { + current_eve = select_eed->v1; + } + else /* otherwise, it's v2 */ + { + current_eve = select_eed->v2; + } + current_eve->tmp.fp = currentWeight; + } + } while (select_eed != NULL); + + MEM_freeN(edges); + } + } + } + } + + return 1; +} + +MCol MColFromWeight(EditVert *eve) +{ + MCol col; + col.a = 255; + col.b = (char)(eve->tmp.fp * 255); + col.g = 0; + col.r = (char)((1.0f - eve->tmp.fp) * 255); + return col; +} + +void weightToVCol(EditMesh *em) +{ + EditFace *efa; + MCol *mcol; + if (!EM_vertColorCheck()) { + return; + } + + for(efa=em->faces.first; efa; efa=efa->next) { + mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL); + + mcol[0] = MColFromWeight(efa->v1); + mcol[1] = MColFromWeight(efa->v2); + mcol[2] = MColFromWeight(efa->v3); + + if(efa->v4) { + mcol[3] = MColFromWeight(efa->v4); + } + } +} + +/****************************************** BUCKET ITERATOR **************************************************/ + +void initArcIterator(ReebArcIterator *iter, ReebArc *arc, ReebNode *head) +{ + iter->arc = arc; + + if (head == arc->v1) + { + iter->start = 0; + iter->end = arc->bcount - 1; + iter->stride = 1; + } + else + { + iter->start = arc->bcount - 1; + iter->end = 0; + iter->stride = -1; + } + + iter->index = iter->start - iter->stride; +} + +void initArcIterator2(ReebArcIterator *iter, ReebArc *arc, int start, int end) +{ + iter->arc = arc; + + iter->start = start; + iter->end = end; + + if (end > start) + { + iter->stride = 1; + } + else + { + iter->stride = -1; + } + + iter->index = iter->start - iter->stride; +} + +EmbedBucket * nextBucket(ReebArcIterator *iter) +{ + EmbedBucket *result = NULL; + + if (iter->index != iter->end) + { + iter->index += iter->stride; + result = &(iter->arc->buckets[iter->index]); + } + + return result; +} diff --git a/source/blender/src/renderwin.c b/source/blender/src/renderwin.c index 2d56b78b026..8250ba4902d 100644 --- a/source/blender/src/renderwin.c +++ b/source/blender/src/renderwin.c @@ -894,11 +894,11 @@ void make_renderinfo_string(RenderStats *rs, char *str) else if(G.scene->r.scemode & R_SINGLE_LAYER) spos+= sprintf(spos, "Single Layer | "); - if(rs->tothalo) - spos+= sprintf(spos, "Fra:%d Ve:%d Fa:%d Ha:%d La:%d Mem:%.2fM (%.2fM) ", (G.scene->r.cfra), rs->totvert, rs->totface, rs->tothalo, rs->totlamp, megs_used_memory, mmap_used_memory); - else - spos+= sprintf(spos, "Fra:%d Ve:%d Fa:%d La:%d Mem:%.2fM (%.2fM) ", (G.scene->r.cfra), rs->totvert, rs->totface, rs->totlamp, megs_used_memory, mmap_used_memory); - + spos+= sprintf(spos, "Fra:%d Ve:%d Fa:%d ", (G.scene->r.cfra), rs->totvert, rs->totface); + if(rs->tothalo) spos+= sprintf(spos, "Ha:%d ", rs->tothalo); + if(rs->totstrand) spos+= sprintf(spos, "St:%d ", rs->totstrand); + spos+= sprintf(spos, "La:%d Mem:%.2fM (%.2fM) ", rs->totlamp, megs_used_memory, mmap_used_memory); + if(rs->curfield) spos+= sprintf(spos, "Field %d ", rs->curfield); if(rs->curblur) @@ -1241,6 +1241,21 @@ void BIF_do_render(int anim) if (G.f & G_DOSCRIPTLINKS) BPY_do_all_scripts(SCRIPT_POSTRENDER); } +void do_ogl_view3d_render(Render *re, View3D *v3d, int winx, int winy) +{ + float winmat[4][4]; + + update_for_newframe_muted(); /* here, since camera can be animated */ + + if(v3d->persp==2 && v3d->camera) { + /* in camera view, use actual render winmat */ + RE_GetCameraWindow(re, v3d->camera, CFRA, winmat); + drawview3d_render(v3d, winx, winy, winmat); + } + else + drawview3d_render(v3d, winx, winy, NULL); +} + /* set up display, render the current area view in an image */ /* the RE_Render is only used to make sure we got the picture in the result */ void BIF_do_ogl_render(View3D *v3d, int anim) @@ -1256,7 +1271,7 @@ void BIF_do_ogl_render(View3D *v3d, int anim) winy= (G.scene->r.size*G.scene->r.ysch)/100; RE_InitState(re, &G.scene->r, winx, winy, NULL); - + /* for now, result is defaulting to floats still... */ rr= RE_GetResult(re); if(rr->rect32==NULL) @@ -1282,8 +1297,10 @@ void BIF_do_ogl_render(View3D *v3d, int anim) /* user event can close window */ if(render_win==NULL) break; - drawview3d_render(v3d, winx, winy); + + do_ogl_view3d_render(re, v3d, winx, winy); glReadPixels(0, 0, winx, winy, GL_RGBA, GL_UNSIGNED_BYTE, rr->rect32); + BKE_stamp_buf((unsigned char *)rr->rect32, rr->rectf, rr->rectx, rr->recty); window_swap_buffers(render_win->win); if(BKE_imtype_is_movie(G.scene->r.imtype)) { @@ -1297,7 +1314,7 @@ void BIF_do_ogl_render(View3D *v3d, int anim) BKE_makepicstring(name, G.scene->r.pic, G.scene->r.cfra, G.scene->r.imtype); - ibuf->rect= (unsigned int *)rr->rect32; + ibuf->rect= (unsigned int *)rr->rect32; ok= BKE_write_ibuf(ibuf, name, G.scene->r.imtype, G.scene->r.subimtype, G.scene->r.quality); if(ok==0) { @@ -1321,8 +1338,9 @@ void BIF_do_ogl_render(View3D *v3d, int anim) CFRA= cfrao; } else { - drawview3d_render(v3d, winx, winy); + do_ogl_view3d_render(re, v3d, winx, winy); glReadPixels(0, 0, winx, winy, GL_RGBA, GL_UNSIGNED_BYTE, rr->rect32); + BKE_stamp_buf((unsigned char *)rr->rect32, rr->rectf, rr->rectx, rr->recty); window_swap_buffers(render_win->win); } diff --git a/source/blender/src/resources.c b/source/blender/src/resources.c index 125c80093a8..25295f4cd3c 100644 --- a/source/blender/src/resources.c +++ b/source/blender/src/resources.c @@ -274,6 +274,8 @@ char *BIF_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid) cp= ts->strip; break; case TH_STRIP_SELECT: cp= ts->strip_select; break; + case TH_CFRAME: + cp= ts->cframe; break; case TH_SYNTAX_B: cp= ts->syntaxb; break; @@ -399,6 +401,7 @@ void BIF_InitTheme(void) SETCOL(btheme->tv3d.normal, 0x22, 0xDD, 0xDD, 255); SETCOL(btheme->tv3d.face_dot, 255, 138, 48, 255); btheme->tv3d.facedot_size= 4; + SETCOL(btheme->tv3d.cframe, 0x60, 0xc0, 0x40, 255); SETCOL(btheme->tv3d.bone_solid, 200, 200, 200, 255); SETCOL(btheme->tv3d.bone_pose, 80, 200, 255, 80); // alpha 80 is not meant editable, used for wire+action draw @@ -605,6 +608,7 @@ char *BIF_ThemeColorsPup(int spacetype) str += sprintf(str, "Normal %%x%d|", TH_NORMAL); str += sprintf(str, "Bone Solid %%x%d|", TH_BONE_SOLID); str += sprintf(str, "Bone Pose %%x%d", TH_BONE_POSE); + str += sprintf(str, "Current Frame %%x%d", TH_CFRAME); break; case SPACE_IPO: str += sprintf(str, "Panel %%x%d|", TH_PANEL); @@ -615,6 +619,7 @@ char *BIF_ThemeColorsPup(int spacetype) str += sprintf(str, "Vertex %%x%d|", TH_VERTEX); str += sprintf(str, "Vertex Selected %%x%d|", TH_VERTEX_SELECT); str += sprintf(str, "Vertex Size %%x%d|", TH_VERTEX_SIZE); + str += sprintf(str, "Current Frame %%x%d", TH_CFRAME); break; case SPACE_FILE: str += sprintf(str, "Selected file %%x%d", TH_HILITE); @@ -628,6 +633,7 @@ char *BIF_ThemeColorsPup(int spacetype) str += sprintf(str, "Bars selected %%x%d|", TH_HILITE); str += sprintf(str, "Strips %%x%d|", TH_STRIP); str += sprintf(str, "Strips selected %%x%d|", TH_STRIP_SELECT); + str += sprintf(str, "Current Frame %%x%d", TH_CFRAME); break; case SPACE_ACTION: //str += sprintf(str, "Panel %%x%d|", TH_PANEL); @@ -639,6 +645,7 @@ char *BIF_ThemeColorsPup(int spacetype) str += sprintf(str, "Channels Selected %%x%d|", TH_HILITE); str += sprintf(str, "Long Key %%x%d|", TH_STRIP); str += sprintf(str, "Long Key selected %%x%d|", TH_STRIP_SELECT); + str += sprintf(str, "Current Frame %%x%d", TH_CFRAME); break; case SPACE_IMAGE: str += sprintf(str, "%%l|"); @@ -660,10 +667,12 @@ char *BIF_ThemeColorsPup(int spacetype) str += sprintf(str, "Plugin Strip %%x%d|", TH_SEQ_PLUGIN); str += sprintf(str, "Transition Strip %%x%d|", TH_SEQ_TRANSITION); str += sprintf(str, "Meta Strip %%x%d|", TH_SEQ_META); + str += sprintf(str, "Current Frame %%x%d", TH_CFRAME); break; case SPACE_SOUND: str += sprintf(str, "Grid %%x%d|", TH_GRID); str += sprintf(str, "Window Slider %%x%d|", TH_SHADE1); + str += sprintf(str, "Current Frame %%x%d", TH_CFRAME); break; case SPACE_BUTS: str += sprintf(str, "Panel %%x%d|", TH_PANEL); @@ -689,6 +698,7 @@ char *BIF_ThemeColorsPup(int spacetype) break; case SPACE_TIME: str += sprintf(str, "Grid %%x%d|", TH_GRID); + str += sprintf(str, "Current Frame %%x%d", TH_CFRAME); break; case SPACE_NODE: str += sprintf(str, "Wires %%x%d|", TH_WIRE); diff --git a/source/blender/src/retopo.c b/source/blender/src/retopo.c index 4ef07b73061..287909da470 100644 --- a/source/blender/src/retopo.c +++ b/source/blender/src/retopo.c @@ -841,7 +841,7 @@ void retopo_do_all() bp= nu->bp; for(i=0; i<nu->pntsv; ++i) { for(j=0; j<nu->pntsu; ++j, ++bp) { - if(bp->f1 & 1) + if(bp->f1 & SELECT) retopo_do_vert(G.vd,bp->vec); } } diff --git a/source/blender/src/sculptmode.c b/source/blender/src/sculptmode.c index 43b33a5c9a8..964c373771e 100644 --- a/source/blender/src/sculptmode.c +++ b/source/blender/src/sculptmode.c @@ -1361,6 +1361,7 @@ void sculptmode_propset_end(SculptSession *ss, int cancel) ss->propset= NULL; allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWBUTSEDIT, 0); + allqueue(REDRAWHEADERS, 0); } } diff --git a/source/blender/src/seqeffects.c b/source/blender/src/seqeffects.c index 5b89bd3ee44..5ed7ea29e2f 100644 --- a/source/blender/src/seqeffects.c +++ b/source/blender/src/seqeffects.c @@ -35,6 +35,7 @@ #include "MEM_guardedalloc.h" #include "PIL_dynlib.h" +#include "DNA_scene_types.h" #include "DNA_sequence_types.h" #include "BLI_blenlib.h" @@ -2494,9 +2495,10 @@ static void do_glow_effect_byte(Sequence *seq, float facf0, float facf1, unsigned char *outbuf=(unsigned char *)out; unsigned char *inbuf=(unsigned char *)rect1; GlowVars *glow = (GlowVars *)seq->effectdata; + struct RenderData *rd = &G.scene->r; RVIsolateHighlights_byte(inbuf, outbuf , x, y, glow->fMini*765, glow->fBoost, glow->fClamp); - RVBlurBitmap2_byte (outbuf, x, y, glow->dDist,glow->dQuality); + RVBlurBitmap2_byte (outbuf, x, y, glow->dDist * (rd->size / 100.0f),glow->dQuality); if (!glow->bNoComp) RVAddBitmaps_byte (inbuf , outbuf, outbuf, x, y); } @@ -2508,9 +2510,10 @@ static void do_glow_effect_float(Sequence *seq, float facf0, float facf1, float *outbuf = out; float *inbuf = rect1; GlowVars *glow = (GlowVars *)seq->effectdata; + struct RenderData *rd = &G.scene->r; RVIsolateHighlights_float(inbuf, outbuf , x, y, glow->fMini*3.0f, glow->fBoost, glow->fClamp); - RVBlurBitmap2_float (outbuf, x, y, glow->dDist,glow->dQuality); + RVBlurBitmap2_float (outbuf, x, y, glow->dDist * (rd->size / 100.0f),glow->dQuality); if (!glow->bNoComp) RVAddBitmaps_float (inbuf , outbuf, outbuf, x, y); } diff --git a/source/blender/src/space.c b/source/blender/src/space.c index b07b8aab015..84c77521841 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -1173,7 +1173,7 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if(val) { - if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0; + if( uiDoBlocks(&curarea->uiblocks, event, 1)!=UI_NOTHING ) event= 0; if(event==UI_BUT_EVENT) do_butspace(val); /* temporal, view3d deserves own queue? */ @@ -2369,7 +2369,7 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) ob= ob->parent; if(ob && (ob->flag & OB_POSEMODE)) { bArmature *arm= ob->data; - if( ELEM(arm->drawtype, ARM_B_BONE, ARM_ENVELOPE)) { + if( arm->drawtype==ARM_ENVELOPE) { initTransform(TFM_BONESIZE, CTX_NONE); Transform(); break; @@ -2761,7 +2761,7 @@ static void winqreadipospace(ScrArea *sa, void *spacedata, BWinEvent *evt) if(sa->win==0) return; if(val) { - if( uiDoBlocks(&sa->uiblocks, event)!=UI_NOTHING ) event= 0; + if( uiDoBlocks(&sa->uiblocks, event, 1)!=UI_NOTHING ) event= 0; /* swap mouse buttons based on user preference */ if (U.flag & USER_LMOUSESELECT) { @@ -3514,6 +3514,11 @@ void drawinfospace(ScrArea *sa, void *spacedata) 0, 0, 0, 0, 0, ""); } + uiDefButBitI(block, TOG, USER_SHOW_FPS, B_DRAWINFO, "Display FPS in View", + (xpos+edgsp+(3*mpref)+(4*midsp)),y2,mpref,buth, + &(U.uiflag), 0, 0, 0, 0, + "Display the number of frames per secons being drawn"); + /* illegal combo... */ if (U.flag & USER_LMOUSESELECT) U.flag &= ~USER_TWOBUTTONMOUSE; @@ -4131,7 +4136,7 @@ static void winqreadinfospace(ScrArea *sa, void *spacedata, BWinEvent *evt) short val= evt->val; if(val) { - if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0; + if( uiDoBlocks(&curarea->uiblocks, event, 1)!=UI_NOTHING ) event= 0; switch(event) { case UI_BUT_EVENT: @@ -4250,7 +4255,7 @@ static void winqreadbutspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if(val) { - if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0; + if( uiDoBlocks(&curarea->uiblocks, event, 1)!=UI_NOTHING ) event= 0; switch(event) { case UI_BUT_EVENT: @@ -4505,7 +4510,7 @@ static void winqreadseqspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if(curarea->win==0) return; if(val) { - if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0; + if( uiDoBlocks(&curarea->uiblocks, event, 1)!=UI_NOTHING ) event= 0; /* swap mouse buttons based on user preference */ if (U.flag & USER_LMOUSESELECT) { @@ -4699,7 +4704,7 @@ static void winqreadseqspace(ScrArea *sa, void *spacedata, BWinEvent *evt) break; case KKEY: if((G.qual==0)) { /* Cut at current frame */ - if(okee("Cut strips")) seq_cut(CFRA); + seq_cut(CFRA); } break; case LKEY: @@ -4964,7 +4969,7 @@ static void winqreadimagespace(ScrArea *sa, void *spacedata, BWinEvent *evt) if(val==0) return; - if(uiDoBlocks(&sa->uiblocks, event)!=UI_NOTHING ) event= 0; + if(uiDoBlocks(&sa->uiblocks, event, 1)!=UI_NOTHING ) event= 0; if (U.flag & USER_LMOUSESELECT) { if (event == LEFTMOUSE) { @@ -5349,7 +5354,7 @@ static void winqreadoopsspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if(val==0) return; - if( uiDoBlocks(&sa->uiblocks, event)!=UI_NOTHING ) event= 0; + if( uiDoBlocks(&sa->uiblocks, event, 1)!=UI_NOTHING ) event= 0; if (U.flag & USER_NONUMPAD) { event= convert_for_nonumpad(event); diff --git a/source/blender/src/toets.c b/source/blender/src/toets.c index caca9974d4e..27a39537988 100644 --- a/source/blender/src/toets.c +++ b/source/blender/src/toets.c @@ -735,6 +735,8 @@ int blenderqread(unsigned short event, short val) } else if(ob->type==OB_MESH) { if(ob==G.obedit) EM_selectmode_menu(); + else if(G.f & G_PARTICLEEDIT) + PE_selectbrush_menu(); else if(G.f & G_SCULPTMODE) sculptmode_selectbrush_menu(); else set_wpaint(); diff --git a/source/blender/src/toolbox.c b/source/blender/src/toolbox.c index f517eec055c..969b9d4657b 100644 --- a/source/blender/src/toolbox.c +++ b/source/blender/src/toolbox.c @@ -288,7 +288,7 @@ short button(short *var, short min, short max, char *str) uiBoundsBlock(block, 5); - ret= uiDoBlocks(&listb, 0); + ret= uiDoBlocks(&listb, 0, 0); if(ret==UI_RETURN_OK) return 1; return 0; @@ -322,7 +322,7 @@ short sbutton(char *var, float min, float max, char *str) uiBoundsBlock(block, 5); mainqenter_ext(BUT_ACTIVATE, 32766, 0); /* note, button id '32766' is asking for errors some day! */ - ret= uiDoBlocks(&listb, 0); + ret= uiDoBlocks(&listb, 0, 0); if(ret==UI_RETURN_OK) return 1; return 0; @@ -356,7 +356,7 @@ short fbutton(float *var, float min, float max, float a1, float a2, char *str) uiBoundsBlock(block, 2); - ret= uiDoBlocks(&listb, 0); + ret= uiDoBlocks(&listb, 0, 0); if(ret==UI_RETURN_OK) return 1; return 0; @@ -416,7 +416,7 @@ int movetolayer_buts(unsigned int *lay, char *title) uiBoundsBlock(block, 2); - ret= uiDoBlocks(&listb, 0); + ret= uiDoBlocks(&listb, 0, 0); if(ret==UI_RETURN_OK) return 1; return 0; @@ -466,7 +466,7 @@ int movetolayer_short_buts(short *lay, char *title) uiBoundsBlock(block, 2); - ret= uiDoBlocks(&listb, 0); + ret= uiDoBlocks(&listb, 0, 0); if(ret==UI_RETURN_OK) return 1; return 0; @@ -603,7 +603,7 @@ int do_clever_numbuts(char *name, int tot, int winevent) uiBoundsBlock(block, 5); - event= uiDoBlocks(&listb, 0); + event= uiDoBlocks(&listb, 0, 0); areawinset(curarea->win); @@ -2219,7 +2219,7 @@ void toolbox_n(void) } uiBoundsBlock(block, 2); - event= uiDoBlocks(&tb_listb, 0); + event= uiDoBlocks(&tb_listb, 0, 1); /* free all dynamic entries... */ BLI_freelistN(&storage); diff --git a/source/blender/src/transform.c b/source/blender/src/transform.c index 3a438f7331a..8a38c66738f 100644 --- a/source/blender/src/transform.c +++ b/source/blender/src/transform.c @@ -49,6 +49,7 @@ #include "DNA_armature_types.h" #include "DNA_action_types.h" /* for some special action-editor settings */ +#include "DNA_constraint_types.h" #include "DNA_ipo_types.h" /* some silly ipo flag */ #include "DNA_listBase.h" #include "DNA_meshdata_types.h" @@ -80,6 +81,7 @@ #include "BIF_editaction.h" #include "BKE_action.h" /* get_action_frame */ +#include "BKE_constraint.h" #include "BKE_global.h" #include "BKE_utildefines.h" #include "BKE_bad_level_calls.h"/* popmenu and error */ @@ -1251,7 +1253,7 @@ void ManipulatorTransform() } -/* ************************** TRANSFORMATIONS **************************** */ +/* ************************** TRANSFORM LOCKS **************************** */ static void protectedTransBits(short protectflag, float *vec) { @@ -1310,6 +1312,78 @@ static void protectedQuaternionBits(short protectflag, float *quat, float *oldqu } } +/* ******************* TRANSFORM LIMITS ********************** */ + +static void constraintTransLim(TransInfo *t, TransData *td) +{ + if (td->con) { + bConstraintTypeInfo *cti= get_constraint_typeinfo(CONSTRAINT_TYPE_LOCLIMIT); + bConstraintOb cob; + bConstraint *con; + + /* Make a temporary bConstraintOb for using these limit constraints + * - they only care that cob->matrix is correctly set ;-) + * - current space should be local + */ + memset(&cob, 0, sizeof(bConstraintOb)); + Mat4One(cob.matrix); + if (td->tdi) { + TransDataIpokey *tdi= td->tdi; + cob.matrix[3][0]= tdi->locx[0]; + cob.matrix[3][1]= tdi->locy[0]; + cob.matrix[3][2]= tdi->locz[0]; + } + else { + VECCOPY(cob.matrix[3], td->loc); + } + + /* Evaluate valid constraints */ + for (con= td->con; con; con= con->next) { + /* we're only interested in Limit-Location constraints */ + if (con->type == CONSTRAINT_TYPE_LOCLIMIT) { + bLocLimitConstraint *data= con->data; + float tmat[4][4]; + + /* only use it if it's tagged for this purpose */ + if ((data->flag2 & LIMIT_TRANSFORM)==0) + continue; + + /* do space conversions */ + if (con->ownspace == CONSTRAINT_SPACE_WORLD) { + /* just multiply by td->mtx (this should be ok) */ + Mat4CpyMat4(tmat, cob.matrix); + Mat4MulMat34(cob.matrix, td->mtx, tmat); // checkme + } + else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) { + /* skip... incompatable spacetype */ + continue; + } + + /* do constraint */ + cti->evaluate_constraint(con, &cob, NULL); + + /* convert spaces again */ + if (con->ownspace == CONSTRAINT_SPACE_WORLD) { + /* just multiply by td->mtx (this should be ok) */ + Mat4CpyMat4(tmat, cob.matrix); + Mat4MulMat34(cob.matrix, td->smtx, tmat); // checkme + } + } + } + + /* copy results from cob->matrix */ + if (td->tdi) { + TransDataIpokey *tdi= td->tdi; + tdi->locx[0]= cob.matrix[3][0]; + tdi->locy[0]= cob.matrix[3][1]; + tdi->locz[0]= cob.matrix[3][2]; + } + else { + VECCOPY(td->loc, cob.matrix[3]); + } + } +} + /* ************************** WARP *************************** */ void initWarp(TransInfo *t) @@ -2484,10 +2558,10 @@ static void applyTranslation(TransInfo *t, float vec[3]) { for(i = 0 ; i < t->total; i++, td++) { if (td->flag & TD_NOACTION) break; - + if (td->flag & TD_SKIP) continue; - + if (t->con.applyVec) { float pvec[3]; t->con.applyVec(t, td, vec, tvec, pvec); @@ -2495,7 +2569,7 @@ static void applyTranslation(TransInfo *t, float vec[3]) { else { VECCOPY(tvec, vec); } - + Mat3MulVecfl(td->smtx, tvec); VecMulf(tvec, td->factor); @@ -2509,6 +2583,8 @@ static void applyTranslation(TransInfo *t, float vec[3]) { add_tdi_poin(tdi->locz, tdi->oldloc+2, tvec[2]); } else VecAddf(td->loc, td->iloc, tvec); + + constraintTransLim(t, td); } } diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index d43ff885975..12acf538431 100644 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -617,6 +617,9 @@ static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tr Mat3Inv (td->smtx, td->mtx); } } + + /* store reference to first constraint */ + td->con= pchan->constraints.first; } static void bone_children_clear_transflag(ListBase *lb) @@ -639,6 +642,7 @@ static void set_pose_transflags(TransInfo *t, Object *ob) bArmature *arm= ob->data; bPoseChannel *pchan; Bone *bone; + int hastranslation; t->total= 0; @@ -664,23 +668,32 @@ static void set_pose_transflags(TransInfo *t, Object *ob) } } /* now count, and check if we have autoIK or have to switch from translate to rotate */ + hastranslation= 0; + for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { bone= pchan->bone; if(bone->flag & BONE_TRANSFORM) { + t->total++; if(t->mode==TFM_TRANSLATION) { if( has_targetless_ik(pchan)==NULL ) { if(pchan->parent && (pchan->bone->flag & BONE_CONNECTED)) { - if(!(pchan->bone->flag & BONE_HINGE_CHILD_TRANSFORM)) - t->mode= TFM_ROTATION; + if(pchan->bone->flag & BONE_HINGE_CHILD_TRANSFORM) + hastranslation= 1; } - else if((pchan->protectflag & OB_LOCK_LOC)==OB_LOCK_LOC) - t->mode= TFM_ROTATION; + else if((pchan->protectflag & OB_LOCK_LOC)!=OB_LOCK_LOC) + hastranslation= 1; } + else + hastranslation= 1; } } } + + /* if there are no translatable bones, do rotation */ + if(t->mode==TFM_TRANSLATION && !hastranslation) + t->mode= TFM_ROTATION; } /* frees temporal IKs */ @@ -690,11 +703,15 @@ static void pose_grab_with_ik_clear(Object *ob) bPoseChannel *pchan; bConstraint *con; - for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - for(con= pchan->constraints.first; con; con= con->next) { - if(con->type==CONSTRAINT_TYPE_KINEMATIC) { + for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + /* clear all temporary lock flags */ + pchan->ikflag &= ~(BONE_IK_NO_XDOF_TEMP|BONE_IK_NO_YDOF_TEMP|BONE_IK_NO_ZDOF_TEMP); + + /* remove all temporary IK-constraints added */ + for (con= pchan->constraints.first; con; con= con->next) { + if (con->type==CONSTRAINT_TYPE_KINEMATIC) { data= con->data; - if(data->flag & CONSTRAINT_IK_TEMP) { + if (data->flag & CONSTRAINT_IK_TEMP) { BLI_remlink(&pchan->constraints, con); MEM_freeN(con->data); MEM_freeN(con); @@ -717,14 +734,14 @@ static void pose_grab_with_ik_add(bPoseChannel *pchan) } /* rule: not if there's already an IK on this channel */ - for(con= pchan->constraints.first; con; con= con->next) + for (con= pchan->constraints.first; con; con= con->next) if(con->type==CONSTRAINT_TYPE_KINEMATIC) break; - if(con) { + if (con) { /* but, if this is a targetless IK, we make it auto anyway (for the children loop) */ data= has_targetless_ik(pchan); - if(data) + if (data) data->flag |= CONSTRAINT_IK_AUTO; return; } @@ -738,7 +755,13 @@ static void pose_grab_with_ik_add(bPoseChannel *pchan) data->rootbone= 1; /* we include only a connected chain */ - while(pchan && (pchan->bone->flag & BONE_CONNECTED)) { + while ((pchan) && (pchan->bone->flag & BONE_CONNECTED)) { + /* here, we set ik-settings for bone from pchan->protectflag */ + if (pchan->protectflag & OB_LOCK_ROTX) pchan->ikflag |= BONE_IK_NO_XDOF_TEMP; + if (pchan->protectflag & OB_LOCK_ROTY) pchan->ikflag |= BONE_IK_NO_YDOF_TEMP; + if (pchan->protectflag & OB_LOCK_ROTZ) pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP; + + /* now we count this pchan as being included */ data->rootbone++; pchan= pchan->parent; } @@ -1162,12 +1185,12 @@ static void createTransCurveVerts(TransInfo *t) for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) { if(bezt->hide==0) { if (G.f & G_HIDDENHANDLES) { - if(bezt->f2 & 1) countsel+=3; + if(bezt->f2 & SELECT) countsel+=3; if(propmode) count+= 3; } else { - if(bezt->f1 & 1) countsel++; - if(bezt->f2 & 1) countsel++; - if(bezt->f3 & 1) countsel++; + if(bezt->f1 & SELECT) countsel++; + if(bezt->f2 & SELECT) countsel++; + if(bezt->f3 & SELECT) countsel++; if(propmode) count+= 3; } } @@ -1177,7 +1200,7 @@ static void createTransCurveVerts(TransInfo *t) for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) { if(bp->hide==0) { if(propmode) count++; - if(bp->f1 & 1) countsel++; + if(bp->f1 & SELECT) countsel++; } } } @@ -1201,14 +1224,19 @@ static void createTransCurveVerts(TransInfo *t) if(bezt->hide==0) { if( propmode || - ((bezt->f2 & 1) && (G.f & G_HIDDENHANDLES)) || - ((bezt->f1 & 1) && (G.f & G_HIDDENHANDLES)==0) + ((bezt->f2 & SELECT) && (G.f & G_HIDDENHANDLES)) || + ((bezt->f1 & SELECT) && (G.f & G_HIDDENHANDLES)==0) ) { VECCOPY(td->iloc, bezt->vec[0]); td->loc= bezt->vec[0]; VECCOPY(td->center, bezt->vec[1]); - if(bezt->f1 & 1 || G.f & G_HIDDENHANDLES) td->flag= TD_SELECTED; - else td->flag= 0; + if (G.f & G_HIDDENHANDLES) { + if(bezt->f2 & SELECT) td->flag= TD_SELECTED; + else td->flag= 0; + } else { + if(bezt->f1 & SELECT) td->flag= TD_SELECTED; + else td->flag= 0; + } td->ext = NULL; td->tdi = NULL; td->val = NULL; @@ -1222,11 +1250,11 @@ static void createTransCurveVerts(TransInfo *t) } /* This is the Curve Point, the other two are handles */ - if(propmode || (bezt->f2 & 1)) { + if(propmode || (bezt->f2 & SELECT)) { VECCOPY(td->iloc, bezt->vec[1]); td->loc= bezt->vec[1]; VECCOPY(td->center, td->loc); - if(bezt->f2 & 1) td->flag= TD_SELECTED; + if(bezt->f2 & SELECT) td->flag= TD_SELECTED; else td->flag= 0; td->ext = NULL; td->tdi = NULL; @@ -1249,14 +1277,19 @@ static void createTransCurveVerts(TransInfo *t) tail++; } if( propmode || - ((bezt->f1 & 1) && (G.f & G_HIDDENHANDLES)) || - ((bezt->f3 & 1) && (G.f & G_HIDDENHANDLES)==0) + ((bezt->f1 & SELECT) && (G.f & G_HIDDENHANDLES)) || + ((bezt->f3 & SELECT) && (G.f & G_HIDDENHANDLES)==0) ) { VECCOPY(td->iloc, bezt->vec[2]); td->loc= bezt->vec[2]; VECCOPY(td->center, bezt->vec[1]); - if(bezt->f3 & 1 || (G.f & G_HIDDENHANDLES)) td->flag= TD_SELECTED; - else td->flag= 0; + if (G.f & G_HIDDENHANDLES) { + if(bezt->f2 & SELECT) td->flag= TD_SELECTED; + else td->flag= 0; + } else { + if(bezt->f3 & SELECT) td->flag= TD_SELECTED; + else td->flag= 0; + } td->ext = NULL; td->tdi = NULL; td->val = NULL; @@ -1282,11 +1315,11 @@ static void createTransCurveVerts(TransInfo *t) head = tail = td; for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) { if(bp->hide==0) { - if(propmode || (bp->f1 & 1)) { + if(propmode || (bp->f1 & SELECT)) { VECCOPY(td->iloc, bp->vec); td->loc= bp->vec; VECCOPY(td->center, td->loc); - if(bp->f1 & 1) td->flag= TD_SELECTED; + if(bp->f1 & SELECT) td->flag= TD_SELECTED; else td->flag= 0; td->ext = NULL; td->tdi = NULL; @@ -1333,7 +1366,7 @@ static void createTransLatticeVerts(TransInfo *t) a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw; while(a--) { if(bp->hide==0) { - if(bp->f1 & 1) countsel++; + if(bp->f1 & SELECT) countsel++; if(propmode) count++; } bp++; @@ -1353,12 +1386,12 @@ static void createTransLatticeVerts(TransInfo *t) bp= editLatt->def; a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw; while(a--) { - if(propmode || (bp->f1 & 1)) { + if(propmode || (bp->f1 & SELECT)) { if(bp->hide==0) { VECCOPY(td->iloc, bp->vec); td->loc= bp->vec; VECCOPY(td->center, td->loc); - if(bp->f1 & 1) td->flag= TD_SELECTED; + if(bp->f1 & SELECT) td->flag= TD_SELECTED; else td->flag= 0; Mat3CpyMat3(td->smtx, smtx); Mat3CpyMat3(td->mtx, mtx); @@ -2252,10 +2285,10 @@ static int count_ipo_keys(Ipo *ipo, char side, float cfra) /* only include points that occur on the right side of cfra */ for (icu= ipo->curve.first; icu; icu= icu->next) { for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) { - if (bezt->f2) { + if (bezt->f2 & SELECT) { /* fully select the other two keys */ - bezt->f1 |= 1; - bezt->f3 |= 1; + bezt->f1 |= SELECT; + bezt->f3 |= SELECT; /* increment by 3, as there are 3 points (3 * x-coordinates) that need transform */ if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) @@ -2712,6 +2745,8 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) Mat3CpyMat4(td->axismtx, ob->obmat); Mat3Ortho(td->axismtx); + td->con= ob->constraints.first; + /* hack: tempolarily disable tracking and/or constraints when getting * object matrix, if tracking is on, or if constraints don't need * inverse correction to stop it from screwing up space conversion @@ -3065,8 +3100,8 @@ void autokeyframe_pose_cb_func(Object *ob, int tmode, short targetless_ik) /* do the bone paths */ if (arm->pathflag & ARM_PATH_ACFRA) { - pose_clear_paths(ob); - pose_calculate_path(ob); + //pose_clear_paths(ob); + pose_recalculate_paths(ob); } } @@ -3307,7 +3342,7 @@ static void createTransObject(TransInfo *t) td->flag= TD_SELECTED; td->protectflag= ob->protectflag; td->ext = tx; - + /* store ipo keys? */ if(ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) { @@ -3484,7 +3519,7 @@ void createTransData(TransInfo *t) createTransPose(t, base->object); } } - else if (G.f & G_PARTICLEEDIT) { + else if (G.f & G_PARTICLEEDIT && PE_can_edit(PE_get_current(ob))) { createTransParticleVerts(t); if(t->data && t->flag & T_PROP_EDIT) { diff --git a/source/blender/src/transform_manipulator.c b/source/blender/src/transform_manipulator.c index b0bcf6da297..7a6d4c69442 100644 --- a/source/blender/src/transform_manipulator.c +++ b/source/blender/src/transform_manipulator.c @@ -340,7 +340,7 @@ int calc_manipulator_stats(ScrArea *sa) bp= nu->bp; a= nu->pntsu*nu->pntsv; while(a--) { - if(bp->f1 & 1) { + if(bp->f1 & SELECT) { calc_tw_center(bp->vec); totsel++; } @@ -388,7 +388,7 @@ int calc_manipulator_stats(ScrArea *sa) a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw; while(a--) { - if(bp->f1 & 1) { + if(bp->f1 & SELECT) { calc_tw_center(bp->vec); totsel++; } diff --git a/source/blender/src/usiblender.c b/source/blender/src/usiblender.c index 16d55202a39..2bf2d5d9ae9 100644 --- a/source/blender/src/usiblender.c +++ b/source/blender/src/usiblender.c @@ -373,6 +373,19 @@ static void init_userdef_file(void) if(U.coba_weight.tot==0) init_colorband(&U.coba_weight, 1); } + if ((G.main->versionfile < 245) || (G.main->versionfile == 245 && G.main->subversionfile < 11)) { + bTheme *btheme; + for (btheme= U.themes.first; btheme; btheme= btheme->next) { + /* these should all use the same colour */ + SETCOL(btheme->tv3d.cframe, 0x60, 0xc0, 0x40, 255); + SETCOL(btheme->tipo.cframe, 0x60, 0xc0, 0x40, 255); + SETCOL(btheme->tact.cframe, 0x60, 0xc0, 0x40, 255); + SETCOL(btheme->tnla.cframe, 0x60, 0xc0, 0x40, 255); + SETCOL(btheme->tseq.cframe, 0x60, 0xc0, 0x40, 255); + SETCOL(btheme->tsnd.cframe, 0x60, 0xc0, 0x40, 255); + SETCOL(btheme->ttime.cframe, 0x60, 0xc0, 0x40, 255); + } + } /* GL Texture Garbage Collection (variable abused above!) */ if (U.textimeout == 0) { diff --git a/source/blender/src/writeimage.c b/source/blender/src/writeimage.c index cb3d4158ec1..50d69fcdc76 100644 --- a/source/blender/src/writeimage.c +++ b/source/blender/src/writeimage.c @@ -148,6 +148,7 @@ void save_image_filesel_str(char *str) case R_RADHDR: strcpy(str, "Save Radiance HDR"); break; + case R_FFMPEG: case R_PNG: strcpy(str, "Save PNG"); break; diff --git a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp index 8f7609aed74..413b16bc300 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp @@ -54,8 +54,12 @@ #include <OpenGL/glu.h> #else #include <GL/gl.h> +#if defined(__sun__) && !defined(__sparc__) +#include <mesa/glu.h> +#else #include <GL/glu.h> #endif +#endif #include "RAS_OpenGLRasterizer/RAS_GLExtensionManager.h" #include "RAS_OpenGLRasterizer/ARB_multitexture.h" #include "BL_Material.h" // MAXTEX diff --git a/source/gameengine/GamePlayer/common/GPC_PolygonMaterial.cpp b/source/gameengine/GamePlayer/common/GPC_PolygonMaterial.cpp index 5b3c2c84edb..840230902f8 100644 --- a/source/gameengine/GamePlayer/common/GPC_PolygonMaterial.cpp +++ b/source/gameengine/GamePlayer/common/GPC_PolygonMaterial.cpp @@ -43,8 +43,12 @@ #include <OpenGL/glu.h> #else #include <GL/gl.h> +#if defined(__sun__) && !defined(__sparc__) +#include <mesa/glu.h> +#else #include <GL/glu.h> #endif +#endif diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp index 0d2aa774394..4f6c78a0fd8 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp @@ -46,8 +46,12 @@ #include <OpenGL/glu.h> #else #include <GL/gl.h> +#if defined(__sun__) && !defined(__sparc__) +#include <mesa/glu.h> +#else #include <GL/glu.h> #endif +#endif #include "GPG_Application.h" diff --git a/source/gameengine/Ketsji/BL_Shader.cpp b/source/gameengine/Ketsji/BL_Shader.cpp index ab0479eb88b..3b74b74727a 100644 --- a/source/gameengine/Ketsji/BL_Shader.cpp +++ b/source/gameengine/Ketsji/BL_Shader.cpp @@ -9,8 +9,12 @@ #include <OpenGL/glu.h> #else #include <GL/gl.h> +#if defined(__sun__) && !defined(__sparc__) +#include <mesa/glu.h> +#else #include <GL/glu.h> #endif +#endif #include <iostream> #include "BL_Shader.h" diff --git a/source/gameengine/Ketsji/BL_Texture.cpp b/source/gameengine/Ketsji/BL_Texture.cpp index d6b57f062f2..53e1af46e4e 100644 --- a/source/gameengine/Ketsji/BL_Texture.cpp +++ b/source/gameengine/Ketsji/BL_Texture.cpp @@ -8,8 +8,12 @@ #include <OpenGL/glu.h> #else #include <GL/gl.h> +#if defined(__sun__) && !defined(__sparc__) +#include <mesa/glu.h> +#else #include <GL/glu.h> #endif +#endif #include <iostream> #include <map> diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index fa1c67f251c..c3aa83bec69 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -15,8 +15,12 @@ #include <OpenGL/glu.h> #else #include <GL/gl.h> +#if defined(__sun__) && !defined(__sparc__) +#include <mesa/glu.h> +#else #include <GL/glu.h> #endif +#endif #include "KX_BlenderMaterial.h" #include "BL_Material.h" diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 1a3a0490d21..1a6aafafabf 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -44,8 +44,12 @@ #include <OpenGL/glu.h> #else #include <GL/gl.h> +#if defined(__sun__) && !defined(__sparc__) +#include <mesa/glu.h> +#else #include <GL/glu.h> #endif +#endif #ifdef WIN32 #pragma warning (disable : 4786) diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index 85250fcd552..4f9c3a1bfb3 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -46,8 +46,12 @@ #include <OpenGL/glu.h> #else #include <GL/gl.h> +#if defined(__sun__) && !defined(__sparc__) +#include <mesa/glu.h> +#else #include <GL/glu.h> #endif +#endif #include "RAS_Rect.h" #include "RAS_TexVert.h" diff --git a/source/nan_compile.mk b/source/nan_compile.mk index ae2717e3b5c..192528aa5a6 100644 --- a/source/nan_compile.mk +++ b/source/nan_compile.mk @@ -190,7 +190,7 @@ ifeq ($(OS),solaris) JAVA_HEADERS = /usr/java/include JAVA_SYSTEM_HEADERS = /usr/java/include/solaris else - OPENGL_HEADERS = /usr/local/include + OPENGL_HEADERS = /usr/X11/include endif AR = ar ARFLAGS = ruv diff --git a/source/nan_definitions.mk b/source/nan_definitions.mk index 7fa3eb98e00..39479dfccf1 100644 --- a/source/nan_definitions.mk +++ b/source/nan_definitions.mk @@ -141,8 +141,13 @@ endif NAN_OPENEXR_LIBS?=$(addprefix ${NAN_OPENEXR}/lib/lib,$(addsuffix .a,$(shell pkg-config --libs OpenEXR | sed -s "s/-l//g" ))) endif else - export NAN_OPENEXR ?= /usr/local - export NAN_OPENEXR_LIBS ?= $(NAN_OPENEXR)/lib/libIlmImf.a $(NAN_OPENEXR)/lib/libHalf.a $(NAN_OPENEXR)/lib/libIex.a + ifeq ($(OS), solaris) + export NAN_OPENEXR ?= /usr/local + export NAN_OPENEXR_LIBS ?= $(NAN_OPENEXR)/lib/libIlmImf.a $(NAN_OPENEXR)/lib/libHalf.a $(NAN_OPENEXR)/lib/libIex.a $(NAN_OPENEXR)/lib/libIlmThread.a -lrt + else + export NAN_OPENEXR ?= /usr/local + export NAN_OPENEXR_LIBS ?= $(NAN_OPENEXR)/lib/libIlmImf.a $(NAN_OPENEXR)/lib/libHalf.a $(NAN_OPENEXR)/lib/libIex.a + endif endif endif ifeq ($(WITH_OPENEXR), true) @@ -165,6 +170,7 @@ endif export NAN_PYTHON ?= $(LCGDIR)/python export NAN_PYTHON_VERSION ?= 2.3 export NAN_PYTHON_BINARY ?= $(NAN_PYTHON)/bin/python$(NAN_PYTHON_VERSION) + export NAN_PYTHON_LIB ?= $(NAN_PYTHON)/lib/python$(NAN_PYTHON_VERSION)/config/libpython$(NAN_PYTHON_VERSION).a export NAN_OPENAL ?= $(LCGDIR)/openal export NAN_FMOD ?= $(LCGDIR)/fmod export NAN_JPEG ?= $(LCGDIR)/jpeg @@ -211,10 +217,12 @@ endif export NAN_PYTHON ?= /System/Library/Frameworks/Python.framework/Versions/2.3 export NAN_PYTHON_VERSION ?= 2.3 export NAN_PYTHON_BINARY ?= $(NAN_PYTHON)/bin/python$(NAN_PYTHON_VERSION) + export NAN_PYTHON_LIB ?= -framework Python else export NAN_PYTHON ?= /sw export NAN_PYTHON_VERSION ?= 2.3 export NAN_PYTHON_BINARY ?= $(NAN_PYTHON)/bin/python$(NAN_PYTHON_VERSION) + export NAN_PYTHON_LIB ?= $(NAN_PYTHON)/lib/python$(NAN_PYTHON_VERSION)/config/libpython$(NAN_PYTHON_VERSION).a endif export NAN_OPENAL ?= $(LCGDIR)/openal @@ -229,6 +237,10 @@ endif export NAN_NSPR ?= $(LCGDIR)/nspr export NAN_FREETYPE ?= $(LCGDIR)/freetype export NAN_GETTEXT ?= $(LCGDIR)/gettext + export NAN_GETTEXT_LIB ?= $(NAN_GETTEXT)/lib/libintl.a + ifeq (($CPU), i386) + export NAN_GETTEXT_LIB += $(NAN_GETTEXT)/lib/libintl.a + endif export NAN_SDL ?= $(LCGDIR)/sdl export NAN_SDLCFLAGS ?= -I$(NAN_SDL)/include export NAN_SDLLIBS ?= $(NAN_SDL)/lib/libSDL.a -framework Cocoa -framework IOKit @@ -270,6 +282,7 @@ endif export NAN_PYTHON ?= /usr/local export NAN_PYTHON_VERSION ?= 2.3 export NAN_PYTHON_BINARY ?= $(NAN_PYTHON)/bin/python$(NAN_PYTHON_VERSION) + export NAN_PYTHON_LIB ?= $(NAN_PYTHON)/lib/python$(NAN_PYTHON_VERSION)/config/libpython$(NAN_PYTHON_VERSION).a export NAN_OPENAL ?= /usr/local export NAN_FMOD ?= $(LCGDIR)/fmod export NAN_JPEG ?= /usr/local @@ -314,6 +327,7 @@ endif export NAN_PYTHON ?= $(LCGDIR)/python export NAN_PYTHON_VERSION ?= 2.3 export NAN_PYTHON_BINARY ?= $(NAN_PYTHON)/bin/python$(NAN_PYTHON_VERSION) + export NAN_PYTHON_LIB ?= $(NAN_PYTHON)/lib/python$(NAN_PYTHON_VERSION)/config/libpython$(NAN_PYTHON_VERSION).a export NAN_OPENAL ?= $(LCGDIR)/openal export NAN_FMOD ?= $(LCGDIR)/fmod export NAN_JPEG ?= $(LCGDIR)/jpeg @@ -326,6 +340,7 @@ endif export NAN_NSPR ?= $(LCGDIR)/nspr export NAN_FREETYPE ?= /usr/freeware export NAN_GETTEXT ?= /usr/freeware + export NAN_GETTEXT_LIB ?= $(NAN_GETTEXT)/lib32/libintl.a export NAN_SDL ?= $(LCGDIR)/sdl export NAN_SDLLIBS ?= -L$(NAN_SDL)/lib -lSDL export NAN_SDLCFLAGS ?= -I$(NAN_SDL)/include/SDL @@ -358,6 +373,7 @@ endif export NAN_PYTHON ?= /usr export NAN_PYTHON_VERSION ?= 2.5 export NAN_PYTHON_BINARY ?= $(NAN_PYTHON)/bin/python$(NAN_PYTHON_VERSION) + export NAN_PYTHON_LIB ?= $(NAN_PYTHON)/lib/python$(NAN_PYTHON_VERSION)/config/libpython$(NAN_PYTHON_VERSION).a export NAN_OPENAL ?= /usr export NAN_FMOD ?= $(LCGDIR)/fmod export NAN_JPEG ?= /usr @@ -413,6 +429,7 @@ endif export NAN_PYTHON ?= $(LCGDIR)/python export NAN_PYTHON_VERSION ?= 2.3 export NAN_PYTHON_BINARY ?= $(NAN_PYTHON)/bin/python$(NAN_PYTHON_VERSION) + export NAN_PYTHON_LIB ?= $(NAN_PYTHON)/lib/python$(NAN_PYTHON_VERSION)/config/libpython$(NAN_PYTHON_VERSION).a export NAN_OPENAL ?= $(LCGDIR)/openal export NAN_FMOD ?= $(LCGDIR)/fmod export NAN_JPEG ?= $(LCGDIR)/jpeg @@ -455,21 +472,23 @@ endif export NAN_PYTHON ?= /usr/local export NAN_PYTHON_VERSION ?= 2.3 export NAN_PYTHON_BINARY ?= $(NAN_PYTHON)/bin/python$(NAN_PYTHON_VERSION) - export NAN_OPENAL ?= /usr/local + export NAN_PYTHON_LIB ?= $(NAN_PYTHON)/lib/python$(NAN_PYTHON_VERSION)/config/libpython$(NAN_PYTHON_VERSION).a + export NAN_OPENAL ?= $(LCGDIR)/openal export NAN_FMOD ?= $(LCGDIR)/fmod - export NAN_JPEG ?= /usr/local - export NAN_PNG ?= /usr/local + export NAN_JPEG ?= $(LCGDIR)/jpeg + export NAN_PNG ?= $(LCGDIR)/png export NAN_TIFF ?= /usr export NAN_ODE ?= $(LCGDIR)/ode export NAN_TERRAPLAY ?= export NAN_MESA ?= /usr/src/Mesa-3.1 - export NAN_ZLIB ?= /usr + export NAN_ZLIB ?= $(LCGDIR)/zlib export NAN_NSPR ?= $(LCGDIR)/nspr export NAN_FREETYPE ?= $(LCGDIR)/freetype export NAN_GETTEXT ?= $(LCGDIR)/gettext - export NAN_SDL ?= $(shell sdl-config --prefix) - export NAN_SDLLIBS ?= $(shell sdl-config --libs) - export NAN_SDLCFLAGS ?= $(shell sdl-config --cflags) + export NAN_GETTEXT_LIB ?= $(NAN_GETTEXT)/lib/libintl.a $(NAN_GETTEXT)/lib/libiconv.a + export NAN_SDL ?= $(LCGDIR)/sdl + export NAN_SDLCFLAGS ?= -I$(NAN_SDL)/include/SDL + export NAN_SDLLIBS ?= $(NAN_SDL)/lib/libSDL.a # Uncomment the following line to use Mozilla inplace of netscape # CPPFLAGS +=-DMOZ_NOT_NET @@ -498,20 +517,18 @@ endif export NAN_PYTHON_VERSION ?= 2.5 ifeq ($(FREE_WINDOWS), true) export NAN_PYTHON_BINARY ?= $(NAN_PYTHON)/bin/python$(NAN_PYTHON_VERSION) + export NAN_PYTHON_LIB ?= $(NAN_PYTHON)/lib/freepy.a export NAN_FREETYPE ?= $(LCGDIR)/gcc/freetype export NAN_ODE ?= $(LCGDIR)/gcc/ode - ifeq ($(NAN_SDL),) - export NAN_SDL ?= $(LCGDIR)/gcc/sdl - export NAN_SDLCFLAGS ?= -I$(NAN_SDL)/include - endif + export NAN_SDL ?= $(LCGDIR)/gcc/sdl + export NAN_SDLCFLAGS ?= -I$(NAN_SDL)/include else export NAN_PYTHON_BINARY ?= python + export NAN_PYTHON_LIB ?= $(NAN_PYTHON)/lib/python23.lib export NAN_FREETYPE ?= $(LCGDIR)/freetype export NAN_ODE ?= $(LCGDIR)/ode - ifeq ($(NAN_SDL),) - export NAN_SDL ?= $(LCGDIR)/sdl - export NAN_SDLCFLAGS ?= -I$(NAN_SDL)/include - endif + export NAN_SDL ?= $(LCGDIR)/sdl + export NAN_SDLCFLAGS ?= -I$(NAN_SDL)/include endif export NAN_OPENAL ?= $(LCGDIR)/openal export NAN_FMOD ?= $(LCGDIR)/fmod @@ -523,6 +540,11 @@ endif export NAN_ZLIB ?= $(LCGDIR)/zlib export NAN_NSPR ?= $(LCGDIR)/nspr export NAN_GETTEXT ?= $(LCGDIR)/gettext + ifeq ($(FREE_WINDOWS), true) + export NAN_GETTEXT_LIB ?= $(NAN_GETTEXT)/lib/freegettext.a $(NAN_ICONV)/lib/freeiconv.a + else + export NAN_GETTEXT_LIB ?= $(NAN_GETTEXT)/lib/gnu_gettext.lib $(NAN_ICONV)/lib/iconv.lib + endif # Uncomment the following line to use Mozilla inplace of netscape # CPPFLAGS +=-DMOZ_NOT_NET @@ -550,6 +572,8 @@ endif export NAN_PYTHON ?= $(LCGDIR)/python export NAN_PYTHON_VERSION ?= 2.3 export NAN_PYTHON_BINARY ?= python + export NAN_PYTHON_LIB ?= $(NAN_PYTHON)/lib/python$(NAN_PYTHON_VERSION)/config/libpython$(NAN_PYTHON_VERSION).a + export NAN_OPENAL ?= $(LCGDIR)/openal export NAN_FMOD ?= $(LCGDIR)/fmod export NAN_JPEG ?= $(LCGDIR)/jpeg @@ -601,3 +625,8 @@ ifeq ($(NAN_NO_KETSJI), true) export NAN_JUST_BLENDERDYNAMIC=true export NAN_NO_OPENAL=true endif + +# INTERNATIONAL implies WITH_FREETYPE2 +ifeq ($(INTERNATIONAL), true) + export WITH_FREETYPE2=true +endif diff --git a/source/nan_link.mk b/source/nan_link.mk index e6824643a04..35a0a9d0070 100644 --- a/source/nan_link.mk +++ b/source/nan_link.mk @@ -52,7 +52,6 @@ SOEXT = .so ifeq ($(OS),beos) LLIBS = -L/boot/develop/lib/x86/ -lGL -lbe -L/boot/home/config/lib/ - LLIBS += -lpython1.5 endif ifeq ($(OS),darwin) @@ -118,7 +117,10 @@ ifeq ($(OS),openbsd) endif ifeq ($(OS),solaris) - LLIBS = -lGLU -lGL -lXmu -lXext -lXi -lX11 -lc -lm -ldl -lsocket -lnsl + ifeq ($(CPU), i386) + LLIBS = -L/usr/X11/lib + endif + LLIBS += -lGLU -lGL -lXmu -lXext -lXi -lX11 -lc -lm -ldl -lsocket -lnsl DYNLDFLAGS = -shared $(LDFLAGS) endif @@ -162,3 +164,9 @@ endif ifeq ($(WITH_FFMPEG),true) LLIBS += $(NAN_FFMPEGLIBS) endif + +ifeq ($(INTERNATIONAL),true) + LLIBS += $(NAN_GETTEXT_LIB) +endif + +LLIBS += $(NAN_PYTHON_LIB) diff --git a/tools/Blender.py b/tools/Blender.py index 58f5ea7b661..77262d6eaaf 100644 --- a/tools/Blender.py +++ b/tools/Blender.py @@ -430,6 +430,8 @@ class BlenderEnvironment(SConsEnvironment): if lenv['OURPLATFORM']=='sunos5': lenv.Append(LINKFLAGS = lenv['PLATFORM_LINKFLAGS']) lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS']) + if lenv['CXX'].endswith('CC'): + lenv.Replace(LINK = '$CXX') if lenv['OURPLATFORM']=='darwin': lenv.Append(LINKFLAGS = lenv['PLATFORM_LINKFLAGS']) lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS']) |