Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt24
-rw-r--r--extern/bFTGL/include/FTGL.h6
-rw-r--r--extern/bFTGL/src/Makefile3
-rw-r--r--intern/elbeem/intern/isosurface.cpp5
-rw-r--r--intern/elbeem/intern/solver_adap.cpp3
-rw-r--r--intern/elbeem/intern/solver_main.cpp5
-rw-r--r--intern/iksolver/intern/IK_QSegment.cpp6
-rw-r--r--intern/opennl/intern/opennl.c2
-rw-r--r--po/Makefile2
-rw-r--r--projectfiles_vc7/blender/blender.sln2
-rw-r--r--projectfiles_vc7/blender/render/BRE_render.vcproj6
-rw-r--r--projectfiles_vc7/blender/src/BL_src.vcproj6
-rw-r--r--release/Makefile11
-rw-r--r--release/scripts/mesh_edges2curves.py3
-rw-r--r--release/scripts/ply_export.py15
-rw-r--r--source/Makefile71
-rw-r--r--source/blender/Makefile2
-rw-r--r--source/blender/blenkernel/BKE_blender.h2
-rw-r--r--source/blender/blenkernel/BKE_mesh.h6
-rw-r--r--source/blender/blenkernel/BKE_modifier.h4
-rw-r--r--source/blender/blenkernel/BKE_particle.h65
-rw-r--r--source/blender/blenkernel/BKE_pointcache.h10
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c124
-rw-r--r--source/blender/blenkernel/intern/action.c18
-rw-r--r--source/blender/blenkernel/intern/anim.c11
-rw-r--r--source/blender/blenkernel/intern/armature.c6
-rw-r--r--source/blender/blenkernel/intern/constraint.c9
-rw-r--r--source/blender/blenkernel/intern/curve.c48
-rw-r--r--source/blender/blenkernel/intern/customdata.c8
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c6
-rw-r--r--source/blender/blenkernel/intern/displist.c176
-rw-r--r--source/blender/blenkernel/intern/image.c8
-rw-r--r--source/blender/blenkernel/intern/ipo.c79
-rw-r--r--source/blender/blenkernel/intern/lattice.c1
-rw-r--r--source/blender/blenkernel/intern/material.c3
-rw-r--r--source/blender/blenkernel/intern/mesh.c68
-rw-r--r--source/blender/blenkernel/intern/modifier.c86
-rw-r--r--source/blender/blenkernel/intern/object.c32
-rw-r--r--source/blender/blenkernel/intern/particle.c935
-rw-r--r--source/blender/blenkernel/intern/particle_system.c819
-rw-r--r--source/blender/blenkernel/intern/pointcache.c18
-rw-r--r--source/blender/blenlib/BLI_arithb.h6
-rw-r--r--source/blender/blenlib/BLI_rand.h3
-rw-r--r--source/blender/blenlib/intern/arithb.c54
-rw-r--r--source/blender/blenlib/intern/rand.c8
-rw-r--r--source/blender/blenlib/intern/util.c13
-rw-r--r--source/blender/blenloader/intern/readfile.c125
-rw-r--r--source/blender/ftfont/intern/Makefile1
-rw-r--r--source/blender/include/BIF_editaction.h2
-rw-r--r--source/blender/include/BIF_editarmature.h6
-rw-r--r--source/blender/include/BIF_editparticle.h2
-rw-r--r--source/blender/include/BIF_gl.h4
-rw-r--r--source/blender/include/BIF_interface.h2
-rw-r--r--source/blender/include/BIF_poseobject.h3
-rw-r--r--source/blender/include/BIF_resources.h1
-rw-r--r--source/blender/include/BSE_drawview.h2
-rw-r--r--source/blender/include/BSE_editipo.h1
-rw-r--r--source/blender/include/blendef.h4
-rw-r--r--source/blender/include/butspace.h4
-rw-r--r--source/blender/include/reeb.h127
-rw-r--r--source/blender/include/transform.h2
-rw-r--r--source/blender/makesdna/DNA_action_types.h10
-rw-r--r--source/blender/makesdna/DNA_armature_types.h120
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h10
-rw-r--r--source/blender/makesdna/DNA_customdata_types.h4
-rw-r--r--source/blender/makesdna/DNA_material_types.h9
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h3
-rw-r--r--source/blender/makesdna/DNA_nla_types.h32
-rw-r--r--source/blender/makesdna/DNA_object_types.h14
-rw-r--r--source/blender/makesdna/DNA_particle_types.h13
-rw-r--r--source/blender/makesdna/DNA_scene_types.h36
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h27
-rw-r--r--source/blender/nodes/intern/CMP_nodes/CMP_normalize.c5
-rw-r--r--source/blender/nodes/intern/CMP_nodes/Makefile1
-rw-r--r--source/blender/nodes/intern/Makefile1
-rw-r--r--source/blender/nodes/intern/SHD_nodes/Makefile1
-rw-r--r--source/blender/python/BPY_interface.c36
-rw-r--r--source/blender/python/api2_2x/Armature.c4
-rw-r--r--source/blender/python/api2_2x/CurNurb.c8
-rw-r--r--source/blender/python/api2_2x/Curve.c6
-rw-r--r--source/blender/python/api2_2x/Draw.c4
-rw-r--r--source/blender/python/api2_2x/Lamp.c4
-rw-r--r--source/blender/python/api2_2x/Modifier.c4
-rw-r--r--source/blender/python/api2_2x/Object.c18
-rw-r--r--source/blender/python/api2_2x/Window.c4
-rw-r--r--source/blender/python/api2_2x/doc/Modifier.py1
-rw-r--r--source/blender/python/api2_2x/doc/Object.py2
-rw-r--r--source/blender/python/api2_2x/doc/Render.py4
-rw-r--r--source/blender/python/api2_2x/sceneRender.c2
-rw-r--r--source/blender/python/api2_2x/sceneSequence.c43
-rw-r--r--source/blender/render/extern/include/RE_pipeline.h4
-rw-r--r--source/blender/render/extern/include/RE_shader_ext.h4
-rw-r--r--source/blender/render/intern/include/render_types.h42
-rw-r--r--source/blender/render/intern/include/renderdatabase.h25
-rw-r--r--source/blender/render/intern/include/shading.h5
-rw-r--r--source/blender/render/intern/include/strand.h192
-rw-r--r--source/blender/render/intern/include/zbuf.h1
-rw-r--r--source/blender/render/intern/source/convertblender.c417
-rw-r--r--source/blender/render/intern/source/envmap.c8
-rw-r--r--source/blender/render/intern/source/imagetexture.c8
-rw-r--r--source/blender/render/intern/source/initrender.c9
-rw-r--r--source/blender/render/intern/source/pipeline.c8
-rw-r--r--source/blender/render/intern/source/rayshade.c3
-rw-r--r--source/blender/render/intern/source/rendercore.c67
-rw-r--r--source/blender/render/intern/source/renderdatabase.c254
-rw-r--r--source/blender/render/intern/source/shadbuf.c2
-rw-r--r--source/blender/render/intern/source/shadeinput.c258
-rw-r--r--source/blender/render/intern/source/shadeoutput.c90
-rw-r--r--source/blender/render/intern/source/sss.c29
-rw-r--r--source/blender/render/intern/source/strand.c1166
-rw-r--r--source/blender/render/intern/source/texture.c18
-rw-r--r--source/blender/render/intern/source/zbuf.c198
-rw-r--r--source/blender/src/buttons_editing.c161
-rw-r--r--source/blender/src/buttons_object.c93
-rw-r--r--source/blender/src/buttons_scene.c11
-rw-r--r--source/blender/src/buttons_shading.c58
-rw-r--r--source/blender/src/drawaction.c6
-rw-r--r--source/blender/src/drawarmature.c335
-rw-r--r--source/blender/src/drawimasel.c3
-rw-r--r--source/blender/src/drawipo.c30
-rw-r--r--source/blender/src/drawnla.c52
-rw-r--r--source/blender/src/drawnode.c41
-rw-r--r--source/blender/src/drawobject.c67
-rw-r--r--source/blender/src/drawsound.c5
-rw-r--r--source/blender/src/drawtext.c40
-rw-r--r--source/blender/src/drawtime.c2
-rw-r--r--source/blender/src/drawview.c132
-rw-r--r--source/blender/src/edit.c24
-rw-r--r--source/blender/src/editaction.c127
-rw-r--r--source/blender/src/editarmature.c1111
-rw-r--r--source/blender/src/editcurve.c214
-rw-r--r--source/blender/src/editimasel.c2
-rw-r--r--source/blender/src/editipo.c84
-rw-r--r--source/blender/src/editipo_lib.c8
-rw-r--r--source/blender/src/editipo_mods.c79
-rw-r--r--source/blender/src/editlattice.c10
-rw-r--r--source/blender/src/editmesh_mods.c2
-rw-r--r--source/blender/src/editnla.c65
-rw-r--r--source/blender/src/editnode.c4
-rw-r--r--source/blender/src/editobject.c80
-rw-r--r--source/blender/src/editparticle.c58
-rw-r--r--source/blender/src/editscreen.c2
-rw-r--r--source/blender/src/editseq.c590
-rw-r--r--source/blender/src/editsima.c6
-rw-r--r--source/blender/src/editsound.c2
-rw-r--r--source/blender/src/edittime.c2
-rw-r--r--source/blender/src/editview.c43
-rw-r--r--source/blender/src/filesel.c14
-rw-r--r--source/blender/src/header_action.c48
-rw-r--r--source/blender/src/header_nla.c10
-rw-r--r--source/blender/src/header_node.c2
-rw-r--r--source/blender/src/header_seq.c8
-rw-r--r--source/blender/src/header_view3d.c7
-rw-r--r--source/blender/src/interface.c45
-rw-r--r--source/blender/src/meshlaplacian.c2
-rw-r--r--source/blender/src/meshtools.c142
-rw-r--r--source/blender/src/playanim.c9
-rw-r--r--source/blender/src/poseobject.c340
-rw-r--r--source/blender/src/reeb.c1923
-rw-r--r--source/blender/src/renderwin.c36
-rw-r--r--source/blender/src/resources.c10
-rw-r--r--source/blender/src/retopo.c2
-rw-r--r--source/blender/src/sculptmode.c1
-rw-r--r--source/blender/src/seqeffects.c7
-rw-r--r--source/blender/src/space.c23
-rw-r--r--source/blender/src/toets.c2
-rw-r--r--source/blender/src/toolbox.c14
-rw-r--r--source/blender/src/transform.c84
-rw-r--r--source/blender/src/transform_conversions.c113
-rw-r--r--source/blender/src/transform_manipulator.c4
-rw-r--r--source/blender/src/usiblender.c13
-rw-r--r--source/blender/src/writeimage.c1
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderGL.cpp4
-rw-r--r--source/gameengine/GamePlayer/common/GPC_PolygonMaterial.cpp4
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_Application.cpp4
-rw-r--r--source/gameengine/Ketsji/BL_Shader.cpp4
-rw-r--r--source/gameengine/Ketsji/BL_Texture.cpp4
-rw-r--r--source/gameengine/Ketsji/KX_BlenderMaterial.cpp4
-rw-r--r--source/gameengine/Ketsji/KX_PythonInit.cpp4
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp4
-rw-r--r--source/nan_compile.mk2
-rw-r--r--source/nan_definitions.mk63
-rw-r--r--source/nan_link.mk12
-rw-r--r--tools/Blender.py2
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'])