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.txt2
-rw-r--r--extern/bullet2/CMakeLists.txt2
-rw-r--r--extern/bullet2/Makefile2
-rw-r--r--extern/bullet2/src/Makefile2
-rw-r--r--intern/elbeem/intern/isosurface.cpp56
-rw-r--r--intern/elbeem/intern/loop_tools.h20
-rw-r--r--intern/elbeem/intern/paraloopend.h7
-rw-r--r--intern/elbeem/intern/solver_init.cpp3
-rw-r--r--intern/elbeem/intern/solver_main.cpp3
-rw-r--r--intern/sph/SConscript11
-rw-r--r--intern/sph/extern/sph_extern.h51
-rw-r--r--intern/sph/intern/sph.cpp51
-rw-r--r--release/scripts/flt_defaultp.py1
-rw-r--r--release/scripts/flt_palettemanager.py388
-rw-r--r--release/scripts/flt_properties.py628
-rw-r--r--release/scripts/flt_toolbar.py809
-rw-r--r--release/scripts/weightpaint_invert.py95
-rw-r--r--release/scripts/wizard_curve2tree.py4034
-rw-r--r--source/Makefile4
-rw-r--r--source/blender/blenkernel/BKE_cloth.h21
-rw-r--r--source/blender/blenkernel/BKE_collision.h36
-rw-r--r--source/blender/blenkernel/BKE_collisions.h130
-rw-r--r--source/blender/blenkernel/BKE_effect.h1
-rw-r--r--source/blender/blenkernel/BKE_sph.h69
-rw-r--r--source/blender/blenkernel/CCGSubSurf.h152
-rw-r--r--source/blender/blenkernel/SConscript1
-rw-r--r--source/blender/blenkernel/bmesh_private.h71
-rw-r--r--source/blender/blenkernel/intern/cloth.c252
-rw-r--r--source/blender/blenkernel/intern/collision.c1477
-rw-r--r--source/blender/blenkernel/intern/kdop.c860
-rw-r--r--source/blender/blenkernel/intern/modifier.c125
-rw-r--r--source/blender/blenkernel/intern/particle_system.c46
-rw-r--r--source/blender/blenkernel/intern/sph.c490
-rw-r--r--source/blender/blenlib/BLI_kdopbvh.h63
-rw-r--r--source/blender/blenlib/intern/BLI_kdopbvh.c849
-rw-r--r--source/blender/blenloader/intern/readfile.c20
-rw-r--r--source/blender/include/butspace.h4
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h11
-rw-r--r--source/blender/makesdna/DNA_sph_types.h102
-rw-r--r--source/blender/src/buttons_editing.c8
-rw-r--r--source/blender/src/buttons_object.c136
-rw-r--r--source/blender/src/drawobject.c22
-rw-r--r--source/gameengine/Converter/KX_BlenderSceneConverter.cpp2
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h2
44 files changed, 3651 insertions, 7468 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b58fe945663..19a03c35bfc 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 LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
diff --git a/extern/bullet2/CMakeLists.txt b/extern/bullet2/CMakeLists.txt
index c5495fdf92b..b5ae20253cc 100644
--- a/extern/bullet2/CMakeLists.txt
+++ b/extern/bullet2/CMakeLists.txt
@@ -1,4 +1,4 @@
-# $Id$
+# $Id: CMakeLists.txt 14444 2008-04-16 22:40:48Z hos $
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
diff --git a/extern/bullet2/Makefile b/extern/bullet2/Makefile
index e05d441a6be..2da1a5bcf85 100644
--- a/extern/bullet2/Makefile
+++ b/extern/bullet2/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14444 2008-04-16 22:40:48Z hos $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/extern/bullet2/src/Makefile b/extern/bullet2/src/Makefile
index 24f3ca9767d..d7bb6a5e427 100644
--- a/extern/bullet2/src/Makefile
+++ b/extern/bullet2/src/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14444 2008-04-16 22:40:48Z hos $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/intern/elbeem/intern/isosurface.cpp b/intern/elbeem/intern/isosurface.cpp
index 1b0ba13c707..f90621f3b73 100644
--- a/intern/elbeem/intern/isosurface.cpp
+++ b/intern/elbeem/intern/isosurface.cpp
@@ -22,6 +22,10 @@
#define round(x) (x)
#endif
+#if PARALLEL==1
+#include <omp.h>
+#endif
+
/******************************************************************************
* Constructor
*****************************************************************************/
@@ -160,13 +164,6 @@ void IsoSurface::triangulate( void )
mpEdgeVerticesZ[i] = -1;
}
- ntlVec3Gfx pos[8];
- float value[8];
- int cubeIndex; // index entry of the cube
- int triIndices[12]; // vertex indices
- int *eVert[12];
- IsoLevelVertex ilv;
-
// edges between which points?
const int mcEdges[24] = {
0,1, 1,2, 2,3, 3,0,
@@ -193,7 +190,12 @@ void IsoSurface::triangulate( void )
px = mStart[0]-gsx*0.5;
for(int i=1;i<(mSizex-2);i++) {
px += gsx;
-
+ int cubeIndex; // index entry of the cube
+ float value[8];
+ int triIndices[12]; // vertex indices
+ int *eVert[12];
+ IsoLevelVertex ilv;
+
value[0] = *getData(i ,j ,k );
value[1] = *getData(i+1,j ,k );
value[2] = *getData(i+1,j+1,k );
@@ -239,6 +241,7 @@ void IsoSurface::triangulate( void )
eVert[11] = &mpEdgeVerticesZ[ ISOLEVEL_INDEX( i+0, j+1, edgek+0) ];
// grid positions
+ ntlVec3Gfx pos[8];
pos[0] = ntlVec3Gfx(px ,py ,pz);
pos[1] = ntlVec3Gfx(px+gsx,py ,pz);
pos[2] = ntlVec3Gfx(px+gsx,py+gsy,pz);
@@ -344,10 +347,7 @@ void IsoSurface::triangulate( void )
if(mUseFullEdgeArrays) {
errMsg("IsoSurface::triangulate","Disabling mUseFullEdgeArrays!");
}
-
- // subdiv local arrays
- gfxReal orgval[8];
- gfxReal subdAr[2][11][11]; // max 10 subdivs!
+
ParticleObject* *arppnt = new ParticleObject*[mSizez*mSizey*mSizex];
// construct pointers
@@ -408,13 +408,25 @@ void IsoSurface::triangulate( void )
debMsgStd("IsoSurface::triangulate",DM_MSG,"Starting. Parts in use:"<<pInUse<<", Subdivs:"<<mSubdivs, 9);
pz = mStart[2]-(double)(0.*gsz)-0.5*orgGsz;
+
for(int ok=1;ok<(mSizez-2)*mSubdivs;ok++) {
pz += gsz;
const int k = ok/mSubdivs;
if(k<=0) continue; // skip zero plane
+#if PARALLEL==1
+#pragma omp parallel for
+#endif
for(int j=1;j<(mSizey-2);j++) {
for(int i=1;i<(mSizex-2);i++) {
-
+ float value[8];
+ ntlVec3Gfx pos[8];
+ int cubeIndex; // index entry of the cube
+ int triIndices[12]; // vertex indices
+ int *eVert[12];
+ IsoLevelVertex ilv;
+ gfxReal orgval[8];
+ gfxReal subdAr[2][11][11]; // max 10 subdivs!
+
orgval[0] = *getData(i ,j ,k );
orgval[1] = *getData(i+1,j ,k );
orgval[2] = *getData(i+1,j+1,k ); // with subdivs
@@ -426,6 +438,7 @@ void IsoSurface::triangulate( void )
// prebuild subsampled array slice
const int sdkOffset = ok-k*mSubdivs;
+
for(int sdk=0; sdk<2; sdk++)
for(int sdj=0; sdj<mSubdivs+1; sdj++)
for(int sdi=0; sdi<mSubdivs+1; sdi++) {
@@ -580,8 +593,13 @@ void IsoSurface::triangulate( void )
// init isolevel vertex
ilv.v = p1 + (p2-p1)*mu; // with subdivs
+#if PARALLEL==1
+#pragma omp critical
+#endif
+ {
mPoints.push_back( ilv );
triIndices[e] = (mPoints.size()-1);
+ }
// store vertex
*eVert[ e ] = triIndices[e];
} else {
@@ -591,23 +609,27 @@ void IsoSurface::triangulate( void )
} // along all edges
}
// removed cutoff treatment...
-
+
// Create the triangles...
+#if PARALLEL==1
+#pragma omp critical
+#endif
+ {
for(int e=0; mcTriTable[cubeIndex][e]!=-1; e+=3) {
mIndices.push_back( triIndices[ mcTriTable[cubeIndex][e+0] ] );
mIndices.push_back( triIndices[ mcTriTable[cubeIndex][e+1] ] ); // with subdivs
mIndices.push_back( triIndices[ mcTriTable[cubeIndex][e+2] ] );
//errMsg("TTT"," i1"<<mIndices[mIndices.size()-3]<<" "<< " i2"<<mIndices[mIndices.size()-2]<<" "<< " i3"<<mIndices[mIndices.size()-1]<<" "<< mIndices.size() );
- }
-
} // triangles in edge table?
+ }
+ }
}//si
}// sj
}//i
}// j
-
+
// copy edge arrays
for(int j=0;j<(mSizey-0)*mSubdivs;j++)
for(int i=0;i<(mSizex-0)*mSubdivs;i++) {
diff --git a/intern/elbeem/intern/loop_tools.h b/intern/elbeem/intern/loop_tools.h
index 70ecb9ce3e0..163965901e8 100644
--- a/intern/elbeem/intern/loop_tools.h
+++ b/intern/elbeem/intern/loop_tools.h
@@ -34,7 +34,7 @@
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#define GRID_REGION_START() \
- { /* main_region */ \
+{ /* main_region */ \
int kstart=getForZMinBnd(), kend=getForZMaxBnd(mMaxRefine); \
if(gridLoopBound>0){ kstart=getForZMin1(), kend=getForZMax1(mMaxRefine); } \
int kdir = 1; \
@@ -49,7 +49,7 @@
kend = kstart-1; \
kstart = temp-1; \
temp = id; /* dummy remove warning */ \
- } \
+} \
@@ -74,13 +74,13 @@
// loop start
#define GRID_REGION_START() \
- { \
+{ \
\
\
if(mSizez<2) { \
mPanic = 1; \
errFatal("ParaLoop::2D","Not valid...!", SIMWORLD_GENERICERROR); \
- } \
+} \
\
\
vector<LbmPoint> calcListFull; \
@@ -113,14 +113,14 @@
int temp = kend; \
kend = kstart-1; \
kstart = temp-1; \
- } \
+} \
\
const int Nj = mLevel[mMaxRefine].lSizey; \
int jstart = 0+( id * (Nj / Nthrds) ); \
int jend = 0+( (id+1) * (Nj / Nthrds) ); \
if( ((Nj/Nthrds) *Nthrds) != Nj) { \
errMsg("LbmFsgrSolver","Invalid domain size Nj="<<Nj<<" Nthrds="<<Nthrds); \
- } \
+} \
\
if(jstart<gridLoopBound) jstart = gridLoopBound; \
if(jend>mLevel[mMaxRefine].lSizey-gridLoopBound) jend = mLevel[mMaxRefine].lSizey-gridLoopBound; \
@@ -156,16 +156,16 @@
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#define GRID_LOOPREG_END() \
\
- } /* i */ \
+} /* i */ \
int i=0; \
ADVANCE_POINTERS(2*gridLoopBound); \
- } /* j */ \
+} /* j */ \
/* COMPRESSGRIDS!=1 */ \
/* int i=0; */ \
/* ADVANCE_POINTERS(mLevel[lev].lSizex*2); */ \
- } /* all cell loop k,j,i */ \
+} /* all cell loop k,j,i */ \
if(doReduce) { } /* dummy remove warning */ \
- } /* main_region */ \
+} /* main_region */ \
\
diff --git a/intern/elbeem/intern/paraloopend.h b/intern/elbeem/intern/paraloopend.h
index 6bb224b625a..de315c5a6e1 100644
--- a/intern/elbeem/intern/paraloopend.h
+++ b/intern/elbeem/intern/paraloopend.h
@@ -1,4 +1,3 @@
-
// same as grid loop_end + barrier
} // i
@@ -22,9 +21,9 @@
{
if(doReduce) {
// synchronize global vars
- for(int j=0; j<calcListFull.size() ; j++) mListFull.push_back( calcListFull[j] );
- for(int j=0; j<calcListEmpty.size(); j++) mListEmpty.push_back( calcListEmpty[j] );
- for(int j=0; j<calcListParts.size(); j++) mpParticles->addFullParticle( calcListParts[j] );
+ for(unsigned int j=0; j<calcListFull.size() ; j++) mListFull.push_back( calcListFull[j] );
+ for(unsigned int j=0; j<calcListEmpty.size(); j++) mListEmpty.push_back( calcListEmpty[j] );
+ for(unsigned int j=0; j<calcListParts.size(); j++) mpParticles->addFullParticle( calcListParts[j] );
if(calcMaxVlen>mMaxVlen) {
mMxvx = calcMxvx;
mMxvy = calcMxvy;
diff --git a/intern/elbeem/intern/solver_init.cpp b/intern/elbeem/intern/solver_init.cpp
index c953d2f47da..105c8ff3094 100644
--- a/intern/elbeem/intern/solver_init.cpp
+++ b/intern/elbeem/intern/solver_init.cpp
@@ -706,8 +706,9 @@ bool LbmFsgrSolver::initializeSolverMemory()
if(sizeof(void *)==4 && memEstFine>maxDefaultMemChunk) {
// max memory chunk for 32bit systems 2gig
memBlockAllocProblem = true;
+
}
-
+
if(memEstFromFunc>memLimit || memBlockAllocProblem) {
sizeReduction *= 0.9;
mSizex = (int)(orgSx * sizeReduction);
diff --git a/intern/elbeem/intern/solver_main.cpp b/intern/elbeem/intern/solver_main.cpp
index 13ebf91b696..7b91724a640 100644
--- a/intern/elbeem/intern/solver_main.cpp
+++ b/intern/elbeem/intern/solver_main.cpp
@@ -368,8 +368,7 @@ LbmFsgrSolver::mainLoop(int lev)
const int cutMin = 1;
const int cutConst = mCutoff+2;
-
-
+
# if LBM_INCLUDE_TESTSOLVERS==1
// 3d region off... quit
if((mUseTestdata)&&(mpTest->mFarfMode>0)) { return; }
diff --git a/intern/sph/SConscript b/intern/sph/SConscript
new file mode 100644
index 00000000000..52243f767c3
--- /dev/null
+++ b/intern/sph/SConscript
@@ -0,0 +1,11 @@
+#!/usr/bin/python
+import sys
+import os
+Import('env')
+
+sources = env.Glob('intern/*.cpp')
+
+incs = ' . extern intern'
+defs = ''
+
+env.BlenderLib ('bf_sph', sources, Split(incs), Split(defs), libtype='blender', priority=0 )
diff --git a/intern/sph/extern/sph_extern.h b/intern/sph/extern/sph_extern.h
new file mode 100644
index 00000000000..b4964739212
--- /dev/null
+++ b/intern/sph/extern/sph_extern.h
@@ -0,0 +1,51 @@
+/**
+ * ***** 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) Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Daniel Genrich.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef PW_EXTERN_H
+#define PW_EXTERN_H
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+void sph_init_cpp(struct SphModifierData *sphmd);
+void sph_free_cpp(struct SphModifierData *sphmd);
+int sph_simulate_cpp(struct Object *ob, struct SphModifierData *sphmd, float frame, struct ListBase *effectors);
+*/
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif //PW_EXTERN_H
+
+
diff --git a/intern/sph/intern/sph.cpp b/intern/sph/intern/sph.cpp
new file mode 100644
index 00000000000..f7afa3c34eb
--- /dev/null
+++ b/intern/sph/intern/sph.cpp
@@ -0,0 +1,51 @@
+/* pw.c
+*
+*
+* ***** 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) Blender Foundation
+* All rights reserved.
+*
+* Contributor(s): Daniel Genrich
+*
+* ***** END GPL/BL DUAL LICENSE BLOCK *****
+*/
+
+#include <iostream>
+
+#include "sph_extern.h"
+/*
+extern "C" void sph_init_cpp(struct SphModifierData *sphmd)
+{
+
+}
+/*
+extern "C" void sph_free_cpp(struct SphModifierData *sphmd)
+{
+
+
+}
+
+extern "C" int sph_simulate_cpp(struct Object *ob, struct SphModifierData *sphmd, float frame, struct ListBase *effectors)
+{
+
+ return 1;
+}
+*/
diff --git a/release/scripts/flt_defaultp.py b/release/scripts/flt_defaultp.py
deleted file mode 100644
index 5c44fe29a6f..00000000000
--- a/release/scripts/flt_defaultp.py
+++ /dev/null
@@ -1 +0,0 @@
-pal = [-1,255,16711935,-16776961,-19529729,-19726337,-19922945,-20119553,-20316161,-20578305,-20840449,-21102593,-21364737,-21692417,-22020097,-22413313,-22806529,-23199745,-23658497,-24117249,-24641537,-25165825,-25755649,-26411009,-27066369,-27787265,-28573697,-29425665,-30343169,-31326209,-32374785,-33488897,-354549761,-371458049,-388366337,-405274625,-422182913,-439156737,-456130561,-473104385,-506855425,-540672001,-574488577,-608305153,-642121729,-676003841,-709885953,-760610817,-811335681,-862060545,-912850945,-980418561,-1048051713,-1115684865,-1183383553,-1267924993,-1352466433,-1453850625,-1555300353,-1656815617,-1775173633,-1893597185,-2028863489,2130771967,-1010376193,-1043996161,-1077681665,-1111367169,-1145052673,-1178738177,-1229200897,-1279663617,-1330126337,-1380654593,-1431182849,-1498488321,-1565793793,-1633164801,-1700535809,-1784684033,-1868832257,-1969823233,-2070814209,2123096575,2005262847,1887429119,1752752639,1601298943,1449779711,1281417727,1096278527,911073791,709026303,490201599,254534143,2023935,-1380857601,-1397700353,-1431320321,-1464940289,-1498560257,-1532180225,-1565865729,-1599551233,-1650013953,-1700476673,-1750939393,-1801402113,-1851864833,-1919170305,-1986475777,-2053781249,-2121086721,2089797887,2005649663,1904724223,1803798783,1686030591,1568262399,1450494207,1315883263,1164495103,1013041407,844810495,659736831,457885951,239192319,3655935,-1767919617,-1784762369,-1801605121,-1818447873,-1852067841,-1885687809,-1919307777,-1952927745,-1986547713,-2020167681,-2070564865,-2120962049,2123542527,2073079807,2022617087,1955377151,1888137215,1820897279,1736880127,1652797439,1568714751,1467854847,1366994943,1249357823,1131655167,997175295,862695423,711372799,560050175,391950335,207007743,5287935,2139657983,2122880767,2106103551,2089326335,2072549119,2055771903,2022217471,1988663039,1955108607,1921554175,1887934207,1854314239,1803917055,1753519871,1703122687,1652725503,1602328319,1535153919,1467979519,1400805119,1316853503,1232901887,1148950271,1048221439,947427071,846632703,729061119,611489535,477140735,326014719,174888703,6919935,1837268479,1820491263,1803714047,1786936831,1770159615,1753382399,1736605183,1719827967,1686273535,1652719103,1619164671,1585610239,1552055807,1518501375,1468169727,1417838079,1367506431,1317174783,1266843135,1199734271,1132625407,1065516543,998407679,914521599,830635519,729972223,629308927,528645631,411205119,293764607,159546879,8551935,-2086957569,-2103734785,-2120512001,-2137289217,2140900863,2107346431,2073791999,2040237311,2006682623,1973127935,1939573247,1906018559,1855686655,1805354751,1755022847,1704690943,1654359039,1587249919,1520140799,1453031679,1369145343,1285258751,1201372159,1100708351,1000044543,882603519,765162495,630943999,496725503,345729791,177956863,10183935,-1699437825,-1716215297,-1732992769,-1766547457,-1800102145,-1833656833,-1867211521,-1900766209,-1934320897,-1967875585,-2018207489,-2068539649,-2118871809,2125763327,2058653951,1991544575,1924435199,1857325823,1773438975,1689552127,1588888063,1488223999,1387559679,1270118143,1152676607,1018457855,884238847,733242623,565468927,397695231,213144319,11815935,-1311918593,-1345473281,-1379027969,-1412582657,-1446137345,-1479692289,-1513247233,-1546802177,-1597134337,-1647466497,-1697798657,-1748130817,-1798463233,-1865572865,-1932682497,-1999792129,-2083678977,2127401215,2043514111,1942849791,1842185215,1724743423,1607301631,1473082367,1338863103,1187866367,1020092415,852318207,667766783,466437887,248331519,13447935,-924398849,-957953793,-991508737,-1025063681,-1058618625,-1092173569,-1142505729,-1192837889,-1243170305,-1293502721,-1343835137,-1410944769,-1478054401,-1545164289,-1629051393,-1712938497,-1796825857,-1897490433,-1998155009,-2098819841,2078705407,1961263103,1827043583,1676046591,1525049599,1357275135,1172723199,971394047,753287423,518403327,283518975,15079935,-570434049,-603988993,-637543937,-671098881,-704653825,-754986241,-805318657,-855651073,-905983489,-973093377,-1040203265,-1107313153,-1174423041,-1258310401,-1342197761,-1442862593,-1543527425,-1644192257,-1761634561,-1879076865,-2013296641,2147450879,1996453631,1828678911,1660904191,1476351999,1275022335,1056915199,822030591,570368511,301928959,16711935,-503325185,-536880129,-570435073,-603990017,-637544961,-671100161,-721432577,-771764993,-822097409,-872430081,-922762753,-989872641,-1056982529,-1124092673,-1191202817,-1275090433,-1358978049,-1459642881,-1560307969,-1660973057,-1778415617,-1895858177,-2030078209,2113891583,1962894079,1795119103,1610566655,1426013951,1224683775,1006576127,771691007,520028415,-452993537,-469771265,-503326209,-536881153,-570436097,-603991297,-637546497,-671101697,-721434113,-771766785,-822099457,-872432129,-922764801,-989874945,-1056985089,-1124095489,-1191205889,-1275093505,-1358981377,-1459646465,-1560311809,-1677754369,-1795197185,-1912640257,-2046860545,2097108991,1946110975,1778335487,1593782527,1392452095,1174344191,939458815,-419439105,-436216833,-452994561,-469772289,-503327233,-536882433,-570437633,-603992833,-637548033,-671103489,-721436161,-771768833,-822101505,-872434433,-922767361,-989877761,-1056988161,-1124098561,-1207986433,-1291874305,-1375762433,-1476427777,-1577093377,-1694536449,-1811979521,-1946200065,-2080420865,2063548159,1912549631,1744773631,1560220159,1358889215,-385884673,-402662401,-419440129,-436217857,-452995585,-469773569,-503328769,-536883969,-570439169,-603994625,-637550081,-671105537,-721438209,-771771137,-822104065,-872437249,-922770433,-989880833,-1056991489,-1124102145,-1191213057,-1275101185,-1358989569,-1459655425,-1560321281,-1677764609,-1795208193,-1912652033,-2046873345,2097095167,1946096127,1778319615,-335553025,-352330753,-369108481,-385886209,-402663937,-419441921,-436219905,-452997889,-486553089,-520108545,-553664001,-587219457,-620774913,-654330625,-687886337,-738219521,-788552705,-838885889,-889219329,-939552769,-1006663681,-1073774593,-1140885761,-1224774401,-1308663041,-1392551937,-1493218305,-1593884929,-1711329025,-1828773377,-1962995201,-2097217281,-285221377,-301999105,-318776833,-335554561,-352332289,-369110273,-385888257,-402666241,-419444225,-436222465,-453000705,-469778945,-503334401,-536890113,-570445825,-604001793,-637557761,-671113729,-721447169,-771780609,-822114305,-872448001,-922781953,-989893377,-1057004801,-1124116481,-1191228417,-1275117825,-1359007489,-1459674625,-1560342017,-1677786881,-234889729,-234890241,-251667969,-268445697,-285223425,-302001409,-318779393,-335557377,-352335361,-369113601,-385891841,-402670081,-419448321,-436226817,-453005313,-469784065,-503340033,-536896001,-570452225,-604008449,-637564929,-671121409,-704678145,-755012353,-805346561,-855681025,-906015745,-973127937,-1040240385,-1107353089,-1174466049,-1258356481,-234889729,-234890241,-234890753,-234891265,-234891777,-234892545,-234893313,-234894081,-234894849,-251673089,-268451329,-285229569,-302007809,-318786305,-335564801,-352343553,-369122305,-385901057,-402680065,-419459073,-436238337,-453017601,-486574337,-520131329,-553688321,-587245569,-620803073,-654360833,-687918849,-738254337,-788590081,-838926081,-234889729,-234890241,-234890753,-234891265,-234891777,-234892545,-234893313,-234894081,-234894849,-234895873,-234896897,-234897921,-234898945,-234900225,-234901505,-234903041,-234904577,-234906113,-234907905,-234909697,-234911745,-251691009,-268470529,-285250305,-302030081,-318810113,-335590401,-352370945,-369151745,-385932801,-402714113,-419495681,-8705,-9217,-9729,-10241,-10753,-11521,-12289,-13057,-13825,-14849,-15873,-16897,-17921,-19201,-20481,-22017,-23553,-25089,-26881,-28673,-30721,-32769,-35073,-37633,-40193,-43009,-46081,-49409,-52993,-56833,-60929,-65281,-926209,-926721,-927233,-927745,-928257,-929025,-929793,-930561,-931329,-932353,-933377,-934401,-935425,-936705,-937985,-939521,-941057,-1008129,-1075457,-1142785,-1210369,-1277953,-1345793,-1413889,-1481985,-1550337,-1618945,-1687809,-1756929,-1826305,-1895937,-2031361,-926209,-926721,-927233,-927745,-928257,-929025,-929793,-996097,-1062401,-1128961,-1195521,-1262081,-1328641,-1395457,-1462273,-1529345,-1596417,-1663489,-1730817,-1798145,-1865729,-1998849,-2132225,-2265857,-2399489,-2533377,-2667521,-2867457,-3067649,-3268097,-3468801,-3669761,-926209,-992257,-1058305,-1124353,-1190401,-1256705,-1323009,-1389313,-1455617,-1522177,-1588737,-1655297,-1721857,-1788673,-1855489,-1988097,-2120705,-2253313,-2386177,-2519041,-2652161,-2785281,-2984193,-3183361,-3382529,-3581953,-3847169,-4112641,-4378369,-4644353,-4976129,-5308161,-1188353,-1254401,-1320449,-1386497,-1452545,-1518849,-1585153,-1651457,-1717761,-1784321,-1850881,-1982977,-2115073,-2247425,-2379777,-2512385,-2644993,-2777601,-2976001,-3174401,-3373057,-3571713,-3836161,-4100865,-4365569,-4630529,-4961281,-5292289,-5689089,-6086145,-6483457,-6946561,-1384961,-1451009,-1517057,-1583105,-1649153,-1715457,-1781761,-1848065,-1979905,-2112001,-2244097,-2376193,-2508289,-2640641,-2838529,-3036673,-3234817,-3432961,-3631361,-3895297,-4159489,-4423681,-4688129,-5018369,-5348609,-5744641,-6140929,-6537473,-6999809,-7462401,-7990785,-8584961,-1581569,-1647617,-1713665,-1779713,-1845761,-1977601,-2109441,-2241281,-2373121,-2505217,-2637313,-2769409,-2967041,-3164929,-3362817,-3560961,-3759105,-4022785,-4286721,-4550657,-4880385,-5210113,-5540097,-5935873,-6331649,-6793217,-7255041,-7782657,-8310529,-8904193,-9563649,-10223361,-1712641,-1778689,-1844737,-1976321,-2107905,-2239745,-2371585,-2503425,-2635265,-2767361,-2964993,-3162625,-3360257,-3558145,-3821569,-4085249,-4348929,-4612609,-4942081,-5271553,-5666817,-6062081,-6457601,-6918913,-7380225,-7907329,-8434689,-9027841,-9686785,-10345985,-11070977,-11861761,-1843713,-1975297,-2106881,-2238465,-2370049,-2501889,-2633729,-2765569,-2962945,-3160577,-3358209,-3555841,-3753473,-4016897,-4280321,-4544001,-4873217,-5202433,-5531905,-5926913,-6322177,-6782977,-7244033,-7770881,-8297729,-8890369,-9548801,-10207489,-10931969,-11722241,-12578305,-13500161,-1974785,-2106369,-2237953,-2369537,-2501121,-2632961,-2830337,-3027713,-3225089,-3422721,-3620353,-3883521,-4146689,-4410113,-4673537,-5002753,-5331969,-5726721,-6121729,-6582273,-7043073,-7503873,-8030465,-8622849,-9215233,-9873409,-10597377,-11387137,-12242689,-13164033,-14085633,-15138561,-2236929,-2368513,-2500097,-2631681,-2763265,-2960641,-3158017,-3355393,-3552769,-3815937,-4079105,-4342273,-4605441,-4934401,-5263361,-5658113,-6052865,-6447617,-6908161,-7368705,-7895041,-8421377,-9013505,-9671425,-10329345,-11053057,-11842561,-12697857,-13618945,-14605825,-15658497,-16776961] \ No newline at end of file
diff --git a/release/scripts/flt_palettemanager.py b/release/scripts/flt_palettemanager.py
deleted file mode 100644
index 6edaf2974ab..00000000000
--- a/release/scripts/flt_palettemanager.py
+++ /dev/null
@@ -1,388 +0,0 @@
-#!BPY
-
-"""
-Name: 'FLT Palette Manager'
-Blender: 240
-Group: 'Misc'
-Tooltip: 'Manage FLT colors'
-"""
-
-__author__ = "Geoffrey Bantle"
-__version__ = "1.0 11/21/2007"
-__email__ = ('scripts', 'Author, ')
-__url__ = ('blender', 'blenderartists.org')
-
-__bpydoc__ ="""\
-
-This script manages colors in OpenFlight databases. OpenFlight is a
-registered trademark of MultiGen-Paradigm, Inc.
-
-Todo:
--Figure out whats causing the PC speaker to beep when initializing...
-
-Feature overview and more availible at:
-http://wiki.blender.org/index.php/Scripts/Manual/FLTools
-"""
-
-# --------------------------------------------------------------------------
-# flt_palettemanager.py version 0.1 2005/04/08
-# --------------------------------------------------------------------------
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-# Copyright (C) 2007: Blender Foundation
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-# ***** END GPL LICENCE BLOCK *****
-# --------------------------------------------------------------------------
-
-import Blender.Draw as Draw
-from Blender.BGL import *
-import Blender
-import flt_properties
-import flt_defaultp as defaultp
-from flt_properties import *
-
-
-palette_size = 12
-palette_x = 0
-palette_y = 0
-
-colors = list()
-curint = 1.0
-curswatch = 0
-#make a default palette, not very useful.
-cinc = 1.0 / 1024.0
-cstep = 0.0
-picker = None
-ptt = ""
-for i in xrange(1024):
- colors.append([cstep,cstep,cstep])
- cstep = cstep + cinc
-def update_state():
- state = dict()
- state["activeScene"] = Blender.Scene.getCurrent()
- state["activeObject"] = state["activeScene"].getActiveObject()
- state["activeMesh"] = None
- if state["activeObject"] and state["activeObject"].type == 'Mesh':
- state["activeMesh"] = state["activeObject"].getData(mesh=True)
-
- state["activeFace"] = None
- if state["activeMesh"]:
- if state["activeMesh"].faceUV and state["activeMesh"].activeFace != None:
- state["activeFace"] = state["activeMesh"].faces[state["activeMesh"].activeFace]
-
- return state
-
-def pack_face_index(index, intensity):
- return ((127*intensity)+(128*index))
-def unpack_face_index(face_index):
- index = face_index / 128
- intensity = float(face_index - 128.0 * index) / 127.0
- return(index,intensity)
-
-def event(evt,val):
- global palette_size
- global palette_x
- global palette_y
- global colors
- global curint
- global curswatch
-
- areas = Blender.Window.GetScreenInfo()
- curarea = Blender.Window.GetAreaID()
- curRect = None
- editmode = 0
-
- for area in areas:
- if area['id'] == curarea:
- curRect = area['vertices']
- break
-
- if evt == Draw.LEFTMOUSE:
- mval = Blender.Window.GetMouseCoords()
- rastx = mval[0] - curRect[0]
- rasty = mval[1] - curRect[1]
-
- swatchx = (rastx -palette_x) / palette_size #+state["palette_x"]
- swatchy = (rasty -palette_y) / palette_size #+state["palette_y"]
- if rastx > palette_x and rastx < (palette_x + palette_size * 32) and rasty > palette_y and rasty < (palette_y+ palette_size* 32):
- if swatchx < 32 and swatchy < 32:
- curswatch = (swatchx * 32) + swatchy
- Draw.Redraw(1)
-
- elif swatchy < 34 and swatchx < 32:
- curint = 1.0 - (float(rastx-palette_x)/(palette_size*32.0))
- Draw.Redraw(1)
-
- #copy current color and intensity to selected faces.
- elif evt == Draw.CKEY:
-
- if Blender.Window.EditMode():
- Blender.Window.EditMode(0)
- editmode = 1
- state = update_state()
-
- #retrieve color from palette
- color = struct.unpack('>BBBB',struct.pack('>I',colors[curswatch]))
- actmesh = state["activeMesh"]
- if actmesh:
- if(Blender.Window.GetKeyQualifiers() != Blender.Window.Qual["CTRL"]):
- selfaces = list()
- for face in actmesh.faces:
- if face.sel:
- selfaces.append(face)
-
- if not "FLT_COL" in actmesh.faces.properties:
- actmesh.faces.addPropertyLayer("FLT_COL",Blender.Mesh.PropertyTypes["INT"])
- for face in actmesh.faces:
- face.setProperty("FLT_COL",127) #default
- try:
- actmesh.activeColorLayer = "FLT_Fcol"
- except:
- actmesh.addColorLayer("FLT_Fcol")
- actmesh.activeColorLayer = "FLT_Fcol"
-
-
- for face in selfaces:
- #First append packed index + color and store in face property
- face.setProperty("FLT_COL",int(pack_face_index(curswatch,curint)))
- #Save baked color to face vertex colors
- for col in face.col:
- col.r = int(color[0] * curint)
- col.g = int(color[1] * curint)
- col.b = int(color[2] * curint)
- col.a = int(color[3] * curint)
- else:
- if Blender.Mesh.Mode() == Blender.Mesh.SelectModes['VERTEX']:
- if not 'FLT_VCOL' in actmesh.verts.properties:
- actmesh.verts.addPropertyLayer("FLT_VCOL",Blender.Mesh.PropertyTypes["INT"])
- for vert in actmesh.verts:
- vert.setProperty("FLT_VCOL",127)
- else:
- for vert in actmesh.verts:
- if vert.sel:
- vert.setProperty("FLT_VCOL",int(pack_face_index(curswatch,curint)))
-
- if editmode:
- Blender.Window.EditMode(1)
-
- Blender.Window.RedrawAll()
-
- #grab color and intensity from active face
- elif evt == Draw.VKEY:
- if Blender.Window.EditMode():
- Blender.Window.EditMode(0)
- editmode = 1
- state = update_state()
-
- actmesh = state["activeMesh"]
- activeFace = state["activeFace"]
-
-
- if activeFace:
- if not "FLT_COL" in actmesh.faces.properties:
- actmesh.faces.addPropertyLayer("FLT_COL",Blender.Mesh.PropertyTypes["INT"])
- for face in actmesh.faces:
- face.setProperty("FLT_COL",127) #default
- try:
- actmesh.activeColorLayer = "FLT_Fcol"
- except:
- actmesh.addColorLayer("FLT_Fcol")
- actmesh.activeColorLayer = "FLT_Fcol"
- tcol = activeFace.getProperty("FLT_COL")
- (index,intensity) = unpack_face_index(tcol)
- curswatch = index
- curint = intensity
-
- if editmode:
- Blender.Window.EditMode(1)
-
- Blender.Window.RedrawAll()
-
- elif evt == Draw.ESCKEY:
- Draw.Exit()
-
- if editmode:
- Blender.Window.EditMode(1)
-
-def update_all():
- global colors
- state = update_state()
- #update the baked FLT colors for all meshes.
- for object in state["activeScene"].objects:
- if object.type == "Mesh":
- mesh = object.getData(mesh=True)
- if 'FLT_COL' in mesh.faces.properties:
- mesh.activeColorLayer = "FLT_Fcol"
- for face in mesh.faces:
- (index,intensity) = unpack_face_index(face.getProperty('FLT_COL'))
- color = struct.unpack('>BBBB',struct.pack('>I',colors[index]))
- #update the vertex colors for this face
- for col in face.col:
- col.r = int(color[0] * intensity)
- col.g = int(color[1] * intensity)
- col.b = int(color[2] * intensity)
- col.a = 255
-
-
-def but_event(evt):
- global palette_size
- global palette_x
- global palette_y
- global colors
- global curint
- global curswatch
- global picker
- state = update_state()
-
- if evt == 1:
- if picker.val:
- rval = (int(picker.val[0]*255),int(picker.val[1]*255),int(picker.val[2]*255),255)
- rval = struct.pack('>BBBB',rval[0],rval[1],rval[2],rval[3])
- rval = struct.unpack('>i',rval)
- colors[curswatch] = rval[0]
- #go cd through all meshes and update their FLT colors
- update_all()
-
- Draw.Redraw(1)
-def init_pal():
- global palette_size
- global palette_x
- global palette_y
- global colors
- global curint
- global curswatch
-
- state = update_state()
-
- if not state["activeScene"].properties.has_key('FLT'):
- state["activeScene"].properties['FLT'] = dict()
-
- try:
- colors = state["activeScene"].properties['FLT']['Color Palette']
- except:
- state["activeScene"].properties['FLT']['Color Palette'] = defaultp.pal
- colors = state["activeScene"].properties['FLT']['Color Palette']
-
-def draw_palette():
- global palette_size
- global palette_x
- global palette_y
- global colors
- global curint
- global curswatch
- global picker
-
- state = update_state()
- init_pal()
-
- ssize = palette_size
- xpos = palette_x
- cid = 0
-
- highlight = [(palette_x,palette_y),(palette_x+palette_size,palette_y),(palette_x+palette_size,palette_y+palette_size),(palette_x,palette_y+palette_size)]
- for x in xrange(32):
- ypos = palette_y
- for y in xrange(32):
- color = struct.unpack('>BBBB',struct.pack('>I',colors[cid]))
- glColor3f(color[0]/255.0,color[1]/255.0,color[2]/255.0)
- glBegin(GL_POLYGON)
- glVertex2i(xpos,ypos)
- glVertex2i(xpos+ssize,ypos)
- glVertex2i(xpos+ssize,ypos+ssize)
- glVertex2i(xpos,ypos+ssize)
- glEnd()
-
- if curswatch == cid:
- highlight[0] = (xpos,ypos)
- highlight[1] = (xpos+ssize,ypos)
- highlight[2] = (xpos+ssize,ypos+ssize)
- highlight[3] = (xpos,ypos+ssize)
-
- glColor3f(0.0,0.0,0.0)
- glBegin(GL_LINE_LOOP)
- glVertex2i(xpos,ypos)
- glVertex2i(xpos+ssize,ypos)
- glVertex2i(xpos+ssize,ypos+ssize)
- glVertex2i(xpos,ypos+ssize)
- glVertex2i(xpos,ypos)
- glEnd()
-
-
- cid = cid + 1
- ypos = ypos + ssize
-
- xpos = xpos + ssize
-
- #draw intensity gradient
- color = struct.unpack('>BBBB',struct.pack('>I',colors[curswatch]))
- color = [color[0]/255.0,color[1]/255.0,color[2]/255.0]
- colsteps = [color[0]/255.0,color[1]/255.0,color[2]/255.0]
- stripwidth = (palette_size * 32.0) / 256
- strippad = palette_size / 2.0
-
- xpos = palette_x
- grady = (palette_y + (palette_size * 32.0)) + strippad
- for x in xrange(256):
- color[0] = color[0] - colsteps[0]
- color[1] = color[1] - colsteps[1]
- color[2] = color[2] - colsteps[2]
-
- glColor3f(color[0], color[1] ,color[2])
- glBegin(GL_POLYGON)
- glVertex2f(xpos,grady)
- glVertex2f(xpos+stripwidth,grady)
- glVertex2f(xpos+stripwidth,grady+palette_size)
- glVertex2f(xpos,grady+palette_size)
- glEnd()
- xpos = xpos + stripwidth
-
- #draw intensity slider bar
- #xposition == 512 - ((curint) * 512)
- xpos = ((palette_size*32) * (1.0 - curint)) + palette_x
- glColor3f(1.0,1.0,1.0)
- glBegin(GL_LINE_LOOP)
- glVertex2i(xpos-6,grady-1)
- glVertex2i(xpos+6,grady-1)
- glVertex2i(xpos+6,grady+palette_size+1)
- glVertex2i(xpos-6,grady+palette_size+1)
- #glVertex2i(xpos-6,grady+7)
- glEnd()
-
- #draw color picker
- color = struct.unpack('>BBBB',struct.pack('>I',colors[curswatch]))
- pickcol = (color[0]/255.0,color[1]/255.0,color[2]/255.0)
- picker = Blender.Draw.ColorPicker(1,highlight[0][0]+1,highlight[0][1]+1,ssize-2,ssize-2,pickcol,ptt)
-
- #draw highlight swatch
- glColor3f(1.0,1.0,1.0)
- glBegin(GL_LINE_LOOP)
- glVertex2i(highlight[0][0],highlight[0][1])
- glVertex2i(highlight[1][0],highlight[1][1])
- glVertex2i(highlight[2][0],highlight[2][1])
- glVertex2i(highlight[3][0],highlight[3][1])
- glVertex2i(highlight[0][0],highlight[0][1])
- glEnd()
-
-def gui():
- glClearColor(0.5,0.5,0.5,1.0)
- glClear(GL_COLOR_BUFFER_BIT)
- draw_palette()
-
-
-init_pal()
-Draw.Register(gui,event,but_event)
-
diff --git a/release/scripts/flt_properties.py b/release/scripts/flt_properties.py
deleted file mode 100644
index bc7c972ca66..00000000000
--- a/release/scripts/flt_properties.py
+++ /dev/null
@@ -1,628 +0,0 @@
-#!BPY
-# flt_properties.py. For setting default OpenFLight ID property types
-# Copyright (C) 2007 Blender Foundation
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-__bpydoc__ ="""\
-Utility functions and data defintions used by OpenFlight I/O and tool scripts. OpenFlight is a
-registered trademark of MultiGen-Paradigm, Inc.
-"""
-
-
-import struct
-
-bitsLSB = [2147483648]
-for i in xrange(31):
- bitsLSB.append(bitsLSB[-1]/2)
-bitsRSB = bitsLSB[:]
-bitsRSB.reverse()
-
-def pack_color(col):
- return struct.pack('>B',col[3]) + struct.pack('>B',col[2]) + struct.pack('>B',col[1]) + struct.pack('>B',col[0])
-
-def unpack_color(col):
- string = struct.pack('>I', col)
- r = struct.unpack('>B',string[3:4])
- g = struct.unpack('>B',string[2:3])
- b = struct.unpack('>B',string[1:2])
- a = struct.unpack('>B',string[0:1])
- return [r,g,b,a]
-
-def reverse_bits(len,num):
- bitbucket = list()
- rval = 0
-
- for i in xrange(len):
- if num & bitsRSB[i]:
- bitbucket.append(1)
- else:
- bitbucket.append(0)
-
- bitbucket.reverse()
-
- for i, bit in enumerate(bitbucket):
- if bit:
- rval |= bitsLSB[i]
-
- return rval
-
-
-opcode_name = { 0: 'db',
- 1: 'head',
- 2: 'grp',
- 4: 'obj',
- 5: 'face',
- 10: 'push',
- 11: 'pop',
- 14: 'dof',
- 19: 'push sub',
- 20: 'pop sub',
- 21: 'push ext',
- 22: 'pop ext',
- 23: 'cont',
- 31: 'comment',
- 32: 'color pal',
- 33: 'long id',
- 49: 'matrix',
- 50: 'vector',
- 52: 'multi-tex',
- 53: 'uv lst',
- 55: 'bsp',
- 60: 'rep',
- 61: 'inst ref',
- 62: 'inst def',
- 63: 'ext ref',
- 64: 'tex pal',
- 67: 'vert pal',
- 68: 'vert w col',
- 69: 'vert w col & norm',
- 70: 'vert w col, norm & uv',
- 71: 'vert w col & uv',
- 72: 'vert lst',
- 73: 'lod',
- 74: 'bndin box',
- 76: 'rot edge',
- 78: 'trans',
- 79: 'scl',
- 80: 'rot pnt',
- 81: 'rot and/or scale pnt',
- 82: 'put',
- 83: 'eyepoint & trackplane pal',
- 84: 'mesh',
- 85: 'local vert pool',
- 86: 'mesh prim',
- 87: 'road seg',
- 88: 'road zone',
- 89: 'morph vert lst',
- 90: 'link pal',
- 91: 'snd',
- 92: 'rd path',
- 93: 'snd pal',
- 94: 'gen matrix',
- 95: 'txt',
- 96: 'sw',
- 97: 'line styl pal',
- 98: 'clip reg',
- 100: 'ext',
- 101: 'light src',
- 102: 'light src pal',
- 103: 'reserved',
- 104: 'reserved',
- 105: 'bndin sph',
- 106: 'bndin cyl',
- 107: 'bndin hull',
- 108: 'bndin vol cntr',
- 109: 'bndin vol orient',
- 110: 'rsrvd',
- 111: 'light pnt',
- 112: 'tex map pal',
- 113: 'mat pal',
- 114: 'name tab',
- 115: 'cat',
- 116: 'cat dat',
- 117: 'rsrvd',
- 118: 'rsrvd',
- 119: 'bounding hist',
- 120: 'rsrvd',
- 121: 'rsrvd',
- 122: 'push attrib',
- 123: 'pop attrib',
- 124: 'rsrvd',
- 125: 'rsrvd',
- 126: 'curv',
- 127: 'road const',
- 128: 'light pnt appear pal',
- 129: 'light pnt anim pal',
- 130: 'indexed lp',
- 131: 'lp sys',
- 132: 'indx str',
- 133: 'shdr pal'}
-
-
-typecodes = ['c','C','s','S','i','I','f','d','t']
-
-FLT_GRP = 2
-FLT_OBJ = 4
-FLT_LOD = 73
-FLT_XRF = 63
-FLT_DOF = 14
-FLT_ILP = 111
-FLT_DB = 1
-FLT_FCE = 5
-
-#not actual opcodes
-FLT_NUL = 0
-FLT_EXP = -1
-
-#valid childtypes for each FLT node type
-FLT_CHILDTYPES = {
- FLT_GRP : [111,2,73,4,14,63],
- FLT_OBJ : [111],
- FLT_LOD : [111,2,73,4,14,63],
- FLT_XRF : [],
- FLT_DOF : [111,2,73,4,14,63],
- FLT_ILP : []
-}
-
-#List of nodes that can have faces as children
-FLT_FACETYPES = [
- FLT_GRP,
- FLT_OBJ,
- FLT_LOD,
- FLT_DOF
-]
-
-def write_prop(fw,type,value,length):
- if type == 'c':
- fw.write_char(value)
- elif type == 'C':
- fw.write_uchar(value)
- elif type == 's':
- fw.write_short(value)
- elif type == 'S':
- fw.write_ushort(value)
- elif type == 'i':
- fw.write_int(value)
- elif type == 'I':
- fw.write_uint(value)
- elif type == 'd':
- fw.write_double(value)
- elif type == 'f':
- fw.write_float(value)
- elif type == 't':
- fw.write_string(value,length)
-
-def read_prop(fw,type,length):
- rval = None
- if type == 'c':
- rval = fw.read_char()
- elif type == 'C':
- rval = fw.read_uchar()
- elif type == 's':
- rval = fw.read_short()
- elif type == 'S':
- rval = fw.read_ushort()
- elif type == 'i':
- rval = fw.read_int()
- elif type == 'I':
- rval = fw.read_uint()
- elif type == 'd':
- rval = fw.read_double()
- elif type == 'f':
- rval = fw.read_float()
- elif type == 't':
- rval = fw.read_string(length)
- return rval
-
-
-FLTExt = {
- '3t8!id' : 'Ext',
- '4t8!sid' : '',
- '5c!reserved': 0,
- '6c!revision' : 0,
- '7S!recordcode' : 0
-}
-FLTGroup = {
- '3t8!id' : 'G',
- '4s!priority' : 0,
- '5s!reserved1' : 0,
- '6i!flags' : 0,
- '7s!special1' : 0,
- '8s!special2' : 0,
- '9s!significance' : 0,
- '10c!layer code' : 0,
- '11c!reserved2' : 0,
- '12i!reserved3' : 0,
- '13i!loop count' : 0,
- '14f!loop duration' : 0,
- '15f!last frame duration' : 0
-}
-FLTGroupDisplay = [5,11,12]
-
-FLTObject = {
- '3t8!id' : 'O',
- '4I!flags' : 0,
- '5s!priority' : 0,
- '6S!transp' : 0,
- '7s!SFX1' : 0,
- '8s!SFX2' : 0,
- '9s!significance' : 0,
- '10s!reserved' : 0
-}
-FLTObjectDisplay = [10]
-
-FLTLOD = {
- '3t8!id' : 'L',
- '4i!reserved' : 0,
- '5d!switch in' : 0,
- '6d!switch out' : 0,
- '7s!sfx ID1' : 0,
- '8s!sfx ID2' : 0,
- '9I!flags' : 0,
- '10d!X co' : 0,
- '11d!Y co' : 0,
- '12d!Z co' : 0,
- '13d!Transition' : 0,
- '14d!Sig Size' : 0
-}
-FLTLODDisplay = [4]
-
-FLTInlineLP = {
- '3t8!id' : 'Lp',
- '4s!smc' : 0,
- '5s!fid' : 0,
- '6C!back color: a' : 255,
- '7C!back color: b' : 255,
- '8C!back color: g' : 255,
- '9C!back color: r' : 255,
- '10i!display mode' : 0,
- '11f!intensity' : 1.0,
- '12f!back intensity' : 0.0,
- '13f!minimum defocus' : 0.0,
- '14f!maximum defocus' : 1.0,
- '15i!fading mode' : 0,
- '16i!fog punch mode' : 0,
- '17i!directional mode' : 1,
- '18i!range mode' : 0,
- '19f!min pixel size' : 1.0,
- '20f!max pixel size' : 1024,
- '21f!actual size' : 0.25,
- '22f!trans falloff pixel size' : 0.25,
- '23f!trans falloff exponent' : 1.0,
- '24f!trans falloff scalar' : 1.0,
- '25f!trans falloff clamp' : 1.0,
- '26f!fog scalar' : 0.25,
- '27f!fog intensity' : 1.0,
- '28f!size threshold' : 0.1,
- '29i!directionality' : 0,
- '30f!horizontal lobe angle' : 180.0,
- '31f!vertical lobe angle' : 180.0,
- '32f!lobe roll angle' : 0.0,
- '33f!dir falloff exponent' : 1.0,
- '34f!dir ambient intensity' : 0.1,
- '35f!anim period' : 2,
- '36f!anim phase' : 0,
- '37f!anim enabled' : 1.0,
- '38f!significance' : 0.0,
- '39i!draw order' : 0,
- '40I!flags' : 277004288,
- '41f!roti' : 0,
- '42f!rotj' : 0,
- '43f!rotk' : 1.0
-}
-
-FLTInlineLPDisplay = [35,36,37,41,42,43]
-
-FLTXRef = {
- '3t200!filename' : '', #we dont actually use this value on export
- '4i!reserved' : 0,
- '5I!flag' : -478150656,
- '6s!bbox' : 0,
- '7s!reserved' : 0
-}
-
-FLTXRefDisplay = [4,7,3]
-
-FLTDOF = {
- '3t8!id' : 'D',
- '4i!reserved' : 0,
- '5d!ORIGX' : 0.0,
- '6d!ORIGY' : 0.0,
- '7d!ORIGZ' : 0.0,
- '8d!XAXIS-X' : 10.0,
- '9d!XAXIS-Y' : 0.0,
- '10d!XAXIS-Z' : 0.0,
- '11d!XYPLANE-X' : 0.0,
- '12d!XYPLANE-Y' : 10.0,
- '13d!XZPLANE-Z' : 0.0,
- '14d!ZMIN' : 0.0,
- '15d!ZMAX' : 0.0,
- '16d!ZCUR' : 0.0,
- '17d!ZSTEP' : 0.0,
- '18d!YMIN' : 0.0,
- '19d!YMAX' : 0.0,
- '20d!YCUR' : 0.0,
- '21d!YSTEP' : 0.0,
- '22d!XMIN' : 0.0,
- '23d!XMAX' : 0.0,
- '24d!XCUR' : 0.0,
- '25d!XSTEP' : 0.0,
- '26d!PITCH-MIN' : 0.0,
- '27d!PITCH-MAX' : 0.0,
- '28d!PITCH-CUR' : 0.0,
- '29d!PITCH-STEP' : 0.0,
- '30d!ROLL-MIN' : 0.0,
- '31d!ROLL-MAX' : 0.0,
- '32d!ROLL-CUR' : 0.0,
- '33d!ROLL-STEP' : 0.0,
- '34d!YAW-MIN' : 0.0,
- '35d!YAW-MAX' : 0.0,
- '36d!YAW-CUR' : 0.0,
- '37d!YAW-STEP' : 0.0,
- '38d!ZSIZE-MIN' : 0.0,
- '39d!ZSIZE-MAX' : 0.0,
- '40d!ZSIZE-CUR' : 1.0,
- '41d!ZSIZE-STEP' : 0.0,
- '42d!YSIZE-MIN' : 0.0,
- '43d!YSIZE-MAX' : 0.0,
- '44d!YSIZE-CUR' : 1.0,
- '45d!YSIZE-STEP' : 0.0,
- '46d!XSIZE-MIN' : 0.0,
- '47d!XSIZE-MAX' : 0.0,
- '48d!XSIZE-CUR' : 1.0,
- '49d!XSIZE-STEP' : 0.0,
- '50I!FLAG' : 1897582,
- '51i!reserved2' : 0
-}
-
-FLTDOFDisplay = [4]
-
-FLTImage = {
- '3i!RealU Direction' : 0,
- '4i!RealV Direction' : 0,
- '5i!UpX' : 0,
- '6i!UpY' : 0,
- '7i!File Format' : 0,
- '8i!Min Filter' : 6,
- '9i!Mag Filter' : 1,
- '10i!Wrap' : 0,
- '11i!WrapU' : 0,
- '12i!WrapV' : 0,
- '13i!Modified' : 0,
- '14i!PivotX' : 0,
- '15i!PivotY' : 0,
- '16i!Enviorment' : 0,
- '17i!WhiteAlpha' : 0,
- '18i!reserved1' : 0,
- '19i!reserved2' : 0,
- '20i!reserved3' : 0,
- '21i!reserved4' : 0,
- '22i!reserved5' : 0,
- '23i!reserved6' : 0,
- '24i!reserved7' : 0,
- '25i!reserved8' : 0,
- '26i!reserved9' : 0,
- '27d!RealU Direction' : 0,
- '28d!RealV Direction' : 0,
- '29i!Origin' : 0,
- '30i!Kernel no.' : 0,
- '31i!Internal Format' : 0,
- '32i!External Format' : 0,
- '33i!MipMap Filter?' : 0,
- '34f!MMF1' : 0.0,
- '35f!MMF2' : 0.0,
- '36f!MMF3' : 0.0,
- '37f!MMF4' : 0.0,
- '38f!MMF5' : 0.0,
- '39f!MMF6' : 0.0,
- '40f!MMF7' : 0.0,
- '41f!MMF8' : 0.0,
- '42i!Tex CPs?' : 0,
- '43f!LOD0 CP' : 0.0,
- '44f!Scale0 CP' : 0.0,
- '45f!LOD1 CP' : 0.0,
- '46f!Scale1 CP' : 0.0,
- '47f!LOD2 CP' : 0.0,
- '48f!Scale2 CP' : 0.0,
- '49f!LOD3 CP' : 0.0,
- '50f!Scale3 CP' : 0.0,
- '51f!LOD4 CP' : 0.0,
- '52f!Scale4 CP' : 0.0,
- '53f!LOD5 CP' : 0.0,
- '54f!Scale5 CP' : 0.0,
- '55f!LOD6 CP' : 0.0,
- '56f!Scale6 CP' : 0.0,
- '57f!LOD7 CP' : 0.0,
- '58f!Scale7 CP' : 0.0,
- '59f!Control Clamp' : 0.0,
- '60i!Mag Alpha Filter' : 0,
- '61i!Mag Color Filter' : 0,
- '62f!reserved10' : 0,
- '63f!reserved11' : 0,
- '64f!reserved12' : 0,
- '65f!reserved13' : 0,
- '66f!reserved14' : 0,
- '67f!reserved15' : 0,
- '68f!reserved16' : 0,
- '69f!reserved17' : 0,
- '70f!reserved18' : 0,
- '71d!Lambert Central' : 0.0,
- '72d!Lambert Upper' : 0.0,
- '73d!Lambert Lower' : 0.0,
- '74d!reserved19' : 0,
- '75f!reserved20' : 0,
- '76f!reserved21' : 0,
- '77f!reserved22' : 0,
- '78f!reserved23' : 0,
- '79f!reserved24' : 0,
- '80i!Tex Detail?' : 0,
- '81i!Tex J' : 0,
- '82i!Tex K' : 0,
- '83i!Tex M' : 0,
- '84i!Tex N' : 0,
- '85i!Tex Scramble' : 0,
- '86i!Tex Tile?' : 0,
- '87f!Tex Tile LLU' : 0.0,
- '88f!Tex Tile LLV' : 0.0,
- '89f!Tex Tile URU' : 0.0,
- '90f!Tex Tile URV' : 0.0,
- '91i!Projection' : 0,
- '92i!Earth Model' : 0,
- '93i!reserved25' : 0,
- '94i!UTM Zone' : 0,
- '95i!Image Origin' : 0,
- '96i!GPU' : 0,
- '97i!reserved26' : 0,
- '98i!reserved27' : 0,
- '99i!GPU Hemi' : 0,
- '100i!reserved41' : 0,
- '101i!reserved42' : 0,
- '102i!reserved43' : 0,
- '103i!Cubemap' : 0,
- '104t588!reserved44' : '',
- '105t512!Comments' : '',
- '106i!reserved28' : 0,
- '107i!reserved29' : 0,
- '108i!reserved30' : 0,
- '109i!reserved31' : 0,
- '110i!reserved32' : 0,
- '111i!reserved33' : 0,
- '112i!reserved34' : 0,
- '113i!reserved35' : 0,
- '114i!reserved36' : 0,
- '115i!reserved37' : 0,
- '116i!reserved38' : 0,
- '117i!reserved39' : 0,
- '118i!reserved40' : 0,
- '119i!reserved45' : 0,
- '120i!Format Version' : 0,
- '121i!GPU num' : 0,
-}
-
-FLTImageDisplay = [18,19,29,21,22,23,24,25,26,62,63,64,65,66,67,68,69,70,74,75,76,77,78,79,93,97,98,102,114]
-
-FLTHeader = {
- '3t8!id' : 'db',
- '4i!version' : 1620,
- '5i!editversion' : 0,
- '6t32!date' : 0,
- '7s!NGID' : 0,
- '8s!NLID' : 0,
- '9s!NOID' : 0,
- '10s!NFID' : 0,
- '11s!UMULT' : 1,
- '12c!units' : 0,
- '13c!set white' : 0,
- '14I!flags' : 0x80000000,
- '15i!reserved1' : 0,
- '16i!reserved2' : 0,
- '17i!reserved3' : 0,
- '18i!reserved4' : 0,
- '19i!reserved5' : 0,
- '20i!reserved6' : 0,
- '21i!projection type' : 0,
- '22i!reserved7' : 0,
- '23i!reserved8' : 0,
- '24i!reserved9' : 0,
- '25i!reserved10' : 0,
- '26i!reserved11' : 0,
- '27i!reserved12' : 0,
- '28i!reserved13' : 0,
- '29s!NDID' : 0,
- '30s!vstore' : 1,
- '31i!origin' : 0,
- '32d!sw x' : 0,
- '33d!sw y' : 0,
- '34d!dx' : 0,
- '35d!dy' : 0,
- '36s!NSID' : 0,
- '37s!NPID' : 0,
- '38i!reserved14' : 0,
- '39i!reserved15' : 0,
- '40s!NCID' : 0,
- '41s!NTID' : 0,
- '42s!NBID' : 0,
- '43s!NWID' : 0,
- '44i!reserved14' : 0,
- '45d!sw lat' : 0,
- '46d!sw lon' : 0,
- '47d!ne lat' : 0,
- '48d!ne lon' : 0,
- '49d!origin lat' : 0,
- '50d!origin lon' : 0,
- '51d!lambert lat1' : 0,
- '52d!lambert lat2' : 0,
- '53s!NLSID' : 0,
- '54s!NLPID' : 0,
- '55s!NRID' : 0,
- '56s!NCATID' : 0,
- '57s!reserved15' : 0,
- '58s!reserved16' : 0,
- '59s!reserved17' : 0,
- '60s!reserved18' : 0,
- '61i!ellipsoid model' : 1,
- '62s!NAID' : 0,
- '63s!NCVID' : 0,
- '64s!utm zone' : 0,
- '65t6!reserved19' : 0,
- '66d!dz' : 0,
- '67d!radius' : 0,
- '68S!NMID' : 0,
- '69S!NLPSID' : 0,
- '70i!reserved20' : 0,
- '71d!major axis' : 0,
- '72d!minor axis' : 0,
-}
-
-FLT_Records = {
- 2 : FLTGroup,
- 4 : FLTObject,
- 73 : FLTLOD,
- 63 : FLTXRef,
- 14 : FLTDOF,
- 1 : FLTHeader,
- 111 : FLTInlineLP,
- 100 : FLTExt,
- 'Image' : FLTImage
-}
-
-def process_recordDefs():
- records = dict()
- for record in FLT_Records:
- props = dict()
- for prop in FLT_Records[record]:
- position = ''
- slice = 0
- (format,name) = prop.split('!')
- for i in format:
- if i not in typecodes:
- position = position + i
- slice = slice + 1
- else:
- break
- type = format[slice:]
- length = type[1:]
- if len(length) == 0:
- length = 1
- else:
- type = type[0]
- length = int(length)
-
- props[int(position)] = (type,length,prop)
- records[record] = props
- return records
-
-
diff --git a/release/scripts/flt_toolbar.py b/release/scripts/flt_toolbar.py
deleted file mode 100644
index a707b87f846..00000000000
--- a/release/scripts/flt_toolbar.py
+++ /dev/null
@@ -1,809 +0,0 @@
-#!BPY
-
-"""
-Name: 'FLT Toolbar'
-Blender: 240
-Group: 'Misc'
-Tooltip: 'Tools for working with FLT databases'
-"""
-
-__author__ = "Geoffrey Bantle"
-__version__ = "1.0 11/21/07"
-__email__ = ('scripts', 'Author, ')
-__url__ = ('blender', 'blenderartists.org')
-
-__bpydoc__ ="""\
-This script provides tools for working with OpenFlight databases in Blender. OpenFlight is a
-registered trademark of MultiGen-Paradigm, Inc.
-
-Feature overview and more availible at:
-http://wiki.blender.org/index.php/Scripts/Manual/FLTools
-"""
-
-# --------------------------------------------------------------------------
-# flt_palettemanager.py version 0.1 2005/04/08
-# --------------------------------------------------------------------------
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-# Copyright (C) 2007: Blender Foundation
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-# ***** END GPL LICENCE BLOCK *****
-# --------------------------------------------------------------------------
-
-import Blender.Draw as Draw
-from Blender.BGL import *
-import Blender
-import flt_properties
-reload(flt_properties)
-from flt_properties import *
-
-xrefprefix = ""
-xrefstack = list()
-vofsstack = list()
-vquatstack = list()
-prop_w = 256
-prop_h = 256
-
-
-#event codes
-evcode = {
- "XREF_MAKE" : 100,
- "XREF_EDIT" : 101,
- "XREF_FILE" : 102,
- "XREF_PICK" : 103,
- "XREF_SELECT" : 104,
- "XREF_POP" : 105,
- "XREF_PREFIX" : 106,
- "FACE_NAME" : 200,
- "FACE_MAKESUB" : 201,
- "FACE_KILLSUB" : 202,
- "FACE_SELSUB" : 203,
- "SCENE_UPDATE" : 303,
- "IDPROP_COPY" : 501,
- "IDPROP_KILL" : 502,
- "CLIGHT_MAKE" : 700,
- "DFROMACT" : 701,
- "FIXCOL" : 702
-}
-
-XREF_PREFIX = None
-XREF_MAKE = None
-XREF_EDIT = None
-XREF_SELECT = None
-XREF_POP = None
-FACE_MAKESUB = None
-FACE_SELSUB = None
-FACE_KILLSUB = None
-IDPROP_KILL = None
-IDPROP_COPY = None
-SCENE_UPDATE = None
-CLIGHT_MAKE = None
-DFROMACT = None
-FIXCOL = None
-
-
-def RGBtoHSV( r, g, b):
- cmin = min( r, g, b )
- cmax = max( r, g, b )
- v = cmax
-
- if(cmax!=0.0):
- s = (cmax-cmin)/cmax
- else:
- s = 0.0
- h = 0.0
-
- if(s == 0.0):
- h = -1.0
- else:
- cdelta = cmax-cmin
- rc = (cmax-r)/cdelta
- gc = (cmax-g)/cdelta
- bc = (cmax-b)/cdelta
- if(r==cmax):
- h = bc-gc
- else:
- if(g==cmax):
- h = 2.0+rc-bc
- else:
- h = 4.0+gc-rc
- h = h*60.0
- if(h<0.0):
- h += 360.0
-
-
- h = h/360.0
- if(h < 0.0):
- h = 0.0
- return (h,s,v)
-
-
-def update_state():
- state = dict()
- state["activeScene"] = Blender.Scene.GetCurrent()
- state["activeObject"] = state["activeScene"].objects.active
- if state["activeObject"] and not state["activeObject"].sel:
- state["activeObject"] = None
- state["activeMesh"] = None
- if state["activeObject"] and state["activeObject"].type == 'Mesh':
- state["activeMesh"] = state["activeObject"].getData(mesh=True)
-
- state["activeFace"] = None
- if state["activeMesh"]:
- if state["activeMesh"].faceUV and state["activeMesh"].activeFace != None:
- state["activeFace"] = state["activeMesh"].faces[state["activeMesh"].activeFace]
-
- #update editmode
- state["editmode"] = Blender.Window.EditMode()
-
- return state
-def pack_face_index(index, intensity):
- return ((127*intensity)+(128*index))
-def unpack_face_index(face_index):
- index = face_index / 128
- intensity = float(face_index - 128.0 * index) / 127.0
- return(index,intensity)
-
-def idprops_append(object, typecode, props):
- object.properties["FLT"] = dict()
- object.properties["FLT"]['type'] = typecode
- for prop in props:
- object.properties["FLT"][prop] = props[prop]
- object.properties["FLT"]['3t8!id'] = object.name
-
-def idprops_kill(object):
- state = update_state()
- if object and object.properties.has_key('FLT'):
- object.properties.pop('FLT')
-
-def idprops_copy(source):
- state = update_state()
- if source.properties.has_key('FLT'):
- for object in state["activeScene"].objects:
- if object.sel and object != source and (state["activeScene"].Layers & object.Layers):
- idprops_kill(object)
- object.properties['FLT'] = dict()
- for key in source.properties['FLT']:
- object.properties['FLT'][key] = source.properties['FLT'][key]
-
-def unpack_color(color):
- return struct.unpack('>BBBB',struct.pack('>I',color))
-
-
-def findColorKey(colordict, hsv):
- hdelta = 0.001
- for key in colordict:
- if not (((hsv[0] < (key[0] + hdelta)) and (hsv[0] > (key[0] - hdelta))) and ((hsv[1] < (key[1] + hdelta)) and (hsv[1] > (key[1] - hdelta)))):
- return key
- return None
-
-def hsvsort(a, b):
- (index1, mag1) = a
- (index2, mag2) = b
- if mag1 > mag2:
- return 1
- elif mag1 < mag2:
- return -1
- return 0
-
-def fix_colors():
-
- editmode = 0
- if Blender.Window.EditMode():
- Blender.Window.EditMode(0)
- editmode = 1
- state = update_state()
-
- scene = state["activeScene"]
- colors = None
- if state["activeScene"].properties.has_key('FLT'):
- try:
- colors = state["activeScene"].properties['FLT']['Color Palette']
- except:
- pass
- if not colors:
- return
-
- #first build a HSV version of our palette
- hsvpalette = list()
- for swatch in colors:
- color = unpack_color(swatch)
- hsv = RGBtoHSV(color[0] / 255.0, color[1] / 255.0, color[2] / 255.0)
- hsvpalette.append(hsv)
-
- #collect all of our meshes
- meshes = list()
- for object in scene.objects.context:
- if object.sel and object.type == 'Mesh':
- mesh = object.getData(mesh=True)
- if "FLT_COL" in mesh.faces.properties:
- meshes.append(mesh)
-
-
- #Now go through our meshes, and build a dictionary of face lists keyed according to (hue,saturation) of the baked color
- colordict = dict()
- for mesh in meshes:
- for face in mesh.faces:
- hsv = RGBtoHSV(face.col[0].r/255.0, face.col[0].g/255.0, face.col[0].b/255.0) #retrieve baked color
- if colordict.has_key((hsv[0],hsv[1])):
- colordict[(hsv[0],hsv[1])].append(face)
- else:
- colordict[(hsv[0],hsv[1])] = [face]
-
-
- #for each color key in the color dict, build a list of distances from it to the values in hsvpalette and then quicksort them for closest match
- for key in colordict:
- maglist = list()
- for i, hsv in enumerate(hsvpalette):
- norm = Blender.Mathutils.Vector(hsv[0], hsv[1]) - Blender.Mathutils.Vector(key[0],key[1])
- maglist.append((i,norm.length))
- maglist.sort(hsvsort)
- print maglist[0]
- for face in colordict[key]:
- (index, intensity) = unpack_face_index(face.getProperty("FLT_COL"))
- newfindex = pack_face_index(maglist[0][0],intensity)
- face.setProperty("FLT_COL", int(newfindex))
-
- for mesh in meshes:
- update_mesh_colors(colors,mesh)
-
- if editmode:
- Blender.Window.EditMode(1)
-
-
-def update_mesh_colors(colors, mesh):
- if 'FLT_COL' in mesh.faces.properties:
- mesh.activeColorLayer = "FLT_Fcol"
- for face in mesh.faces:
- (index,intensity) = unpack_face_index(face.getProperty('FLT_COL'))
- color = struct.unpack('>BBBB',struct.pack('>I',colors[index]))
-
- if index == 0 and intensity == 0:
- color = (255,255,255)
- intensity = 1.0
- #update the vertex colors for this face
- for col in face.col:
- col.r = int(color[0] * intensity)
- col.g = int(color[1] * intensity)
- col.b = int(color[2] * intensity)
- col.a = 255
-
-
-def update_all():
-
- editmode = 0
- if Blender.Window.EditMode():
- Blender.Window.EditMode(0)
- editmode = 1
- state = update_state()
- colors = None
- if state["activeScene"].properties.has_key('FLT'):
- try:
- colors = state["activeScene"].properties['FLT']['Color Palette']
- except:
- pass
- if colors:
- #update the baked FLT colors for all meshes.
- for object in state["activeScene"].objects:
- if object.type == "Mesh":
- mesh = object.getData(mesh=True)
- update_mesh_colors(colors,mesh)
- if editmode:
- Blender.Window.EditMode(1)
-
-#Change this to find the deep parent
-def xref_create():
- global xrefprefix
- global xrefstack
- global vofsstack
- global vquatstack
- global prop_w
- global prop_h
-
- state = update_state()
-
- def findchildren(object):
- children = list()
- for candidate in state["activeScene"].objects:
- if candidate.parent == object:
- children.append(candidate)
- retlist = list(children)
- for child in children:
- retlist = retlist + findchildren(child)
- return retlist
-
- actObject = state["activeObject"]
- if actObject and xrefprefix:
- scenenames = list()
- for scene in Blender.Scene.Get():
- scenenames.append(scene.name)
-
- if xrefprefix in scenenames:
- #build a unique name for the xref...
- suffix = 1
- found = False
- while not found:
- candidate = xrefprefix + str(suffix)
- if not candidate in scenenames:
- xrefname = candidate
- found = True
- suffix+=1
- else:
- xrefname = xrefprefix
- #create our XRef node
- xnode = state["activeScene"].objects.new('Empty')
- xnode.name = 'X:' + xrefname
- xnode.properties['FLT'] = dict()
- for prop in FLTXRef:
- xnode.properties['FLT'][prop] = FLTXRef[prop]
- xnode.properties['FLT']['3t200!filename'] = xrefname + '.flt'
- xnode.properties['FLT']['type'] = 63
- xnode.enableDupGroup = True
- xnode.DupGroup = Blender.Group.New(xrefname) #this is dangerous... be careful!
-
- #copy rot and loc of actObject
- xnode.setLocation(actObject.getLocation())
- xnode.setEuler(actObject.getEuler())
-
- #build the new scene
- xrefscene = Blender.Scene.New(xrefname)
- xrefscene.properties['FLT'] = dict()
- xrefscene.properties['FLT']['Filename'] = xrefname
- xrefscene.properties['FLT']['Main'] = 0
-
- #find the children of actObject so that we can add them to the group
- linkobjects = findchildren(actObject)
- linkobjects.append(actObject)
- for object in linkobjects:
- xrefscene.objects.link(object)
- state["activeScene"].objects.unlink(object)
- xnode.DupGroup.objects.link(object)
- #clear rotation of actObject and location
- actObject.setLocation(0.0,0.0,0.0)
- actObject.setEuler(0.0,0.0,0.0)
-
- xrefscene.update(1)
- state["activeScene"].update(1)
-
-def xref_select():
- state = update_state()
- candidates = list()
- scenelist = [scene.name for scene in Blender.Scene.Get()]
- for object in state["activeScene"].objects:
- if object.type == 'Empty' and object.enableDupGroup == True and object.DupGroup:
- candidates.append(object)
-
- for object in candidates:
- if object.DupGroup.name in scenelist:
- object.sel = 1
-
-def xref_edit():
- global xrefprefix
- global xrefstack
- global vofsstack
- global vquatstack
- global prop_w
- global prop_h
-
- state = update_state()
-
- actObject = state["activeObject"]
-
- if actObject and actObject.type == 'Empty' and actObject.DupGroup:
-# if actObject.properties.has_key('FLT') and actObject.properties['FLT']['type'] == 63:
- for FLTscene in Blender.Scene.Get():
- if FLTscene.properties.has_key('FLT') and FLTscene.name == actObject.DupGroup.name:
- actObject.sel = 0
- xrefstack.append(state["activeScene"])
- vofsstack.append(Blender.Window.GetViewOffset())
- vquatstack.append(Blender.Window.GetViewQuat())
- FLTscene.makeCurrent()
- Blender.Window.SetViewOffset(0.0,0.0,0.0)
-
-def xref_finish():
- global xrefprefix
- global xrefstack
- global vofsstack
- global vquatstack
- global prop_w
- global prop_h
-
- state = update_state()
- if xrefstack:
- scene = xrefstack.pop()
- Blender.Window.SetViewQuat(vquatstack.pop())
- Blender.Window.SetViewOffset(vofsstack.pop())
- scene.makeCurrent()
-
-
-def sortSub(a,b):
- aindex = a.getProperty("FLT_ORIGINDEX")
- bindex = b.getProperty("FLT_ORIGINDEX")
-
- if aindex > bindex:
- return 1
- elif aindex < bindex:
- return -1
- return 0
-
-def subface_make():
- global xrefprefix
- global xrefstack
- global vofsstack
- global vquatstack
- global prop_w
- global prop_h
-
- editmode = 0
- if Blender.Window.EditMode():
- Blender.Window.EditMode(0)
- editmode = 1
-
- state = update_state()
-
- actmesh = state["activeMesh"]
- activeFace = state["activeFace"]
- if actmesh:
- if not "FLT_ORIGINDEX" in actmesh.faces.properties:
- actmesh.faces.addPropertyLayer("FLT_ORIGINDEX",Blender.Mesh.PropertyTypes["INT"])
- for i, face in enumerate(actmesh.faces):
- face.setProperty("FLT_ORIGINDEX",i)
- if not "FLT_SFLEVEL" in actmesh.faces.properties:
- actmesh.faces.addPropertyLayer("FLT_SFLEVEL",Blender.Mesh.PropertyTypes["INT"])
-
- #attach the subfaces to the active face. Note, this doesnt really work 100 percent properly yet, just enough for one level!
- if activeFace:
- #steps:
- #remove actface and selected faces from the facelist
- #quicksort facelist
- #append actface and subfaces to end of facelist.
- #generate new indices
- facelist = list()
- sublist = list()
- for face in actmesh.faces:
- facelist.append(face)
- for face in facelist:
- if face == activeFace:
- face.setProperty("FLT_SFLEVEL",0)
- sublist.insert(0,face)
- elif face.sel:
- face.setProperty("FLT_SFLEVEL",1)
- sublist.append(face)
- for face in sublist:
- facelist.remove(face)
- facelist.sort(sortSub)
- for face in sublist:
- facelist.append(face)
- for i, face in enumerate(facelist):
- face.setProperty("FLT_ORIGINDEX",i)
- else:
- pass
-
- if editmode:
- Blender.Window.EditMode(1)
-
-def subface_kill():
- global xrefprefix
- global xrefstack
- global vofsstack
- global vquatstack
- global prop_w
- global prop_h
-
- editmode = 0
- if Blender.Window.EditMode():
- Blender.Window.EditMode(0)
- editmode = 1
- state = update_state()
-
- actmesh = state["activeMesh"]
- if actmesh:
- if "FLT_ORIGINDEX" in actmesh.faces.properties and "FLT_SFLEVEL" in actmesh.faces.properties:
- for i,face in enumerate(actmesh.faces):
- face.setProperty("FLT_ORIGINDEX",i)
- face.setProperty("FLT_SFLEVEL",0)
- if editmode:
- Blender.Window.EditMode(1)
-
-def subface_select():
- global xrefprefix
- global xrefstack
- global vofsstack
- global vquatstack
- global prop_w
- global prop_h
-
- editmode = 0
- if Blender.Window.EditMode():
- Blender.Window.EditMode(0)
- editmode = 1
- state = update_state()
-
- actmesh = state["activeMesh"]
- activeFace = state["activeFace"]
- if actmesh and activeFace:
- if "FLT_ORIGINDEX" in actmesh.faces.properties and "FLT_SFLEVEL" in actmesh.faces.properties:
- facelist = list()
- actIndex = None
- sublevel = None
- for face in actmesh.faces:
- facelist.append(face)
- facelist.sort(sortSub)
- for i, face in enumerate(facelist):
- if face == activeFace:
- actIndex = i
- sublevel = face.getProperty("FLT_SFLEVEL")+1
- break
- leftover = facelist[actIndex+1:]
- for face in leftover:
- if face.getProperty("FLT_SFLEVEL") == sublevel:
- face.sel = 1
- else:
- break
- if editmode:
- Blender.Window.EditMode(1)
-
-def select_by_typecode(typecode):
- global xrefprefix
- global xrefstack
- global vofsstack
- global vquatstack
- global prop_w
- global prop_h
-
- state = update_state()
-
- for object in state["activeScene"].objects:
- if object.properties.has_key('FLT') and object.properties['FLT']['type'] == typecode and state["activeScene"].Layers & object.Layers:
- object.select(1)
-def clight_make():
- state = update_state()
- actmesh = state["activeMesh"]
- actobj = state["activeObject"]
-
- if actobj and actmesh:
- actobj.properties['FLT'] = dict()
- actobj.properties['FLT']['type'] = 111
- for prop in FLTInlineLP:
- actobj.properties['FLT'][prop] = FLTInlineLP[prop]
-
- actmesh.verts.addPropertyLayer("FLT_VCOL", Blender.Mesh.PropertyTypes["INT"])
- for v in actmesh.verts:
- v.setProperty("FLT_VCOL", 83815)
-
-def dfromact():
- state = update_state()
- actobj = state["activeObject"]
- actscene = state["activeScene"]
- dof = None
-
- for object in actscene.objects.context:
- if object.sel and (object != actobj):
- if not dof:
- dof = object
- else:
- break
-
- if not dof:
- return
-
- if 'FLT' not in dof.properties:
- dof.properties['FLT'] = dict()
-
- #Warning! assumes 1 BU == 10 meters.
- #do origin
- dof.properties['FLT']['5d!ORIGX'] = actobj.getLocation('worldspace')[0]*10.0
- dof.properties['FLT']['6d!ORIGY'] = actobj.getLocation('worldspace')[1]*10.0
- dof.properties['FLT']['7d!ORIGZ'] = actobj.getLocation('worldspace')[2]*10.0
- #do X axis
- x = Blender.Mathutils.Vector(1.0,0.0,0.0)
- x = x * actobj.getMatrix('worldspace')
- x = x * 10.0
- dof.properties['FLT']['8d!XAXIS-X'] = x[0]
- dof.properties['FLT']['9d!XAXIS-Y'] = x[1]
- dof.properties['FLT']['10d!XAXIS-Z'] = x[2]
- #do X/Y plane
- x = Blender.Mathutils.Vector(1.0,1.0,0.0)
- x.normalize()
- x = x * actobj.getMatrix('worldspace')
- x = x * 10.0
- dof.properties['FLT']['11d!XYPLANE-X'] = x[0]
- dof.properties['FLT']['12d!XYPLANE-Y'] = x[1]
- dof.properties['FLT']['13d!XZPLANE-Z'] = x[2]
-
-
-
-
-
-def event(evt,val):
- if evt == Draw.ESCKEY:
- Draw.Exit()
-
-def but_event(evt):
- global xrefprefix
- global xrefstack
- global vofsstack
- global vquatstack
- global prop_w
- global prop_h
- global evcode
-
- state = update_state()
-
- #do Xref buttons
- if evt == evcode["XREF_PREFIX"]:
- xrefprefix = XREF_PREFIX.val
- if evt == evcode["XREF_EDIT"]:
- xref_edit()
- if evt == evcode["XREF_SELECT"]:
- xref_select()
- if evt == evcode["XREF_MAKE"]:
- xref_create()
- #do scene buttons
- if evt == evcode["SCENE_UPDATE"]:
- update_all()
- #do face buttons
- if evt == evcode["FACE_MAKESUB"]:
- subface_make()
- if evt== evcode["FACE_KILLSUB"]:
- subface_kill()
- if evt== evcode["FACE_SELSUB"]:
- subface_select()
- #common buttons
- if evt == evcode["IDPROP_KILL"]:
- if state["activeObject"]:
- idprops_kill(state["activeObject"])
- if evt == evcode["IDPROP_COPY"]:
- if state["activeObject"]:
- idprops_copy(state["activeObject"])
- if evt == evcode["XREF_POP"]:
- xref_finish()
- if evt == evcode["CLIGHT_MAKE"]:
- clight_make()
- if evt == evcode["DFROMACT"]:
- dfromact()
- if evt == evcode["FIXCOL"]:
- fix_colors()
- Draw.Redraw(1)
- Blender.Window.RedrawAll()
-
-
-def box(x,y,w,h,c,mode):
- glColor3f(c[0],c[1],c[2])
- if mode == "outline":
- glBegin(GL_LINE_LOOP)
- else:
- glBegin(GL_POLYGON)
- glVertex2i(x,y)
- glVertex2i(x+w,y)
- glVertex2i(x+w,y+h)
- glVertex2i(x,y+h)
- glEnd()
-
-def draw_postcommon(x,y,finaly):
- global sheetlabel
- global xrefprefix
- global xrefstack
- global vofsstack
- global vquatstack
- global prop_w
- global prop_h
- global evcode
-
- state = update_state()
-
- width = prop_w
- height = prop_h
-
- #draw the header
- glColor3f(0.15,0.15,0.15)
- glBegin(GL_POLYGON)
- glVertex2i(x-1,y)
- glVertex2i(x+width+1,y)
- glVertex2i(x+width+1,y-25)
- glVertex2i(x-1,y-25)
- glEnd()
- glColor3f(1,1,1)
- glRasterPos2i(x,y-20)
- sheetlabel = Blender.Draw.Text("FLT Tools Panel")
- #draw the box outline
- glColor3f(0,0,0)
- glBegin(GL_LINE_LOOP)
- glVertex2i(x-1,y)
- glVertex2i(x+1+width,y)
- glVertex2i(x+1+width,finaly-1)
- glVertex2i(x-1,finaly-1)
- glEnd()
- return finaly
-
-
-def draw_propsheet(x,y):
- global XREF_PREFIX
- global XREF_MAKE
- global XREF_EDIT
- global XREF_SELECT
- global XREF_POP
- global FACE_MAKESUB
- global FACE_SELSUB
- global FACE_KILLSUB
- global IDPROP_KILL
- global IDPROP_COPY
- global SCENE_UPDATE
- global DFROMACT
- global FIXCOL
-
- global CLIGHT_MAKE
- global xrefprefix
- global xrefstack
- global vofsstack
- global vquatstack
- global prop_w
- global prop_h
- global evcode
-
- state = update_state()
-
- width = prop_w
- height = prop_h
- origx = x
- origy = y
-
- #draw Xref tools
- y = y-20
- XREF_PREFIX = Blender.Draw.String("XRef Name:",evcode["XREF_PREFIX"],x,y,width,20,xrefprefix,18,"Xref prefix name, Actual name is generated from this")
- y = y-20
- XREF_MAKE = Blender.Draw.PushButton("Make XRef",evcode["XREF_MAKE"],x,y,width,20,"Make External Reference")
- y = y-20
- XREF_EDIT = Blender.Draw.PushButton("Edit XRef",evcode["XREF_EDIT"],x,y,width,20,"Edit External Reference")
- y = y-20
- XREF_SELECT = Blender.Draw.PushButton("Select XRefs",evcode["XREF_SELECT"],x,y,width,20,"Select External References")
- y = y - 20
- XREF_POP = Blender.Draw.PushButton("Return to previous scene",evcode["XREF_POP"],x,y,width,20,"Go up one level in xref hierarchy")
-
- #Draw facetools
- y = y-20
- FACE_MAKESUB = Blender.Draw.PushButton("Make Subfaces",evcode["FACE_MAKESUB"],x,y,width,20,"Make subfaces")
- y = y-20
- FACE_SELSUB = Blender.Draw.PushButton("Select Subfaces",evcode["FACE_SELSUB"],x,y,width,20,"Select subfaces")
- y = y-20
- FACE_KILLSUB = Blender.Draw.PushButton("Kill Subfaces",evcode["FACE_KILLSUB"],x,y,width,20,"Kill subfaces")
-
- #Draw ID Property tools
- y = y - 20
- IDPROP_KILL = Blender.Draw.PushButton("Delete ID props",evcode["IDPROP_KILL"],x,y,width,20,"Delete ID props")
- y = y - 20
- IDPROP_COPY = Blender.Draw.PushButton("Copy to selected",evcode["IDPROP_COPY"],x,y,width,20, "Copy from active to all selected")
-
- y= y - 20
- CLIGHT_MAKE = Blender.Draw.PushButton("Make Light Point", evcode["CLIGHT_MAKE"],x,y,width,20,"Create inline light points from current mesh")
- #General tools
- y = y-20
- SCENE_UPDATE = Blender.Draw.PushButton("Update All",evcode["SCENE_UPDATE"],x,y,width,20,"Update all vertex colors")
-
- y=y-20
- DFROMACT = Blender.Draw.PushButton("Dof from Active", evcode["DFROMACT"],x,y,width,20,"Get Dof origin from active object")
- y=y-20
- FIXCOL = Blender.Draw.PushButton("Fix Colors", evcode["FIXCOL"],x,y,width,20,"Fix baked FLT colors of selected meshes")
- draw_postcommon(origx, origy,y)
-
-def gui():
- #draw the propsheet/toolbox.
- psheety = 300
- #psheetx = psheety + 10
- draw_propsheet(0,psheety)
-Draw.Register(gui,event,but_event)
- \ No newline at end of file
diff --git a/release/scripts/weightpaint_invert.py b/release/scripts/weightpaint_invert.py
deleted file mode 100644
index cdae83a9d50..00000000000
--- a/release/scripts/weightpaint_invert.py
+++ /dev/null
@@ -1,95 +0,0 @@
-#!BPY
-"""
-Name: 'Invert Active Group'
-Blender: 245
-Group: 'WeightPaint'
-Tooltip: 'Invert the active vertex group'
-"""
-
-# --------------------------------------------------------------------------
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-# ***** END GPL LICENCE BLOCK *****
-# --------------------------------------------------------------------------
-import Blender
-from Blender import Scene, Mesh, Window, sys
-
-import BPyMessages
-import bpy
-
-def vgroup_invert(ob_orig, me):
- if not me.getVertGroupNames():
- return
- group_act = me.activeGroup
- if group_act == None:
- return
-
- group_data = me.getVertsFromGroup(group_act, 1)
-
- weights= [1.0] * len(me.verts) # 1.0 - initialize inverted
-
- group_data = me.getVertsFromGroup(group_act, 1) # (i,w) tuples.
-
- me.removeVertGroup(group_act) # messes up the active group.
- for i,w in group_data:
- weights[i] = 1.0-w
-
- me.addVertGroup(group_act)
-
- rep = Blender.Mesh.AssignModes.REPLACE
- vertList= [None]
- for i,weight in enumerate(weights):
- vertList[0] = i
- me.assignVertsToGroup(group_act, vertList, weight, rep)
-
- me.activeGroup = group_act
- me.update()
-
-def main():
-
- # Gets the current scene, there can be many scenes in 1 blend file.
- sce = bpy.data.scenes.active
-
- # Get the active object, there can only ever be 1
- # and the active object is always the editmode object.
- ob_act = sce.objects.active
-
- if not ob_act or ob_act.type != 'Mesh':
- BPyMessages.Error_NoMeshActive()
- return
-
- # Saves the editmode state and go's out of
- # editmode if its enabled, we cant make
- # changes to the mesh data while in editmode.
- is_editmode = Window.EditMode()
- Window.EditMode(0)
-
- Window.WaitCursor(1)
- me = ob_act.getData(mesh=1) # old NMesh api is default
- t = sys.time()
-
- # Run the mesh editing function
- vgroup_invert(ob_act, me)
-
- # Timing the script is a good way to be aware on any speed hits when scripting
- print 'Invert VGroup in %.2f seconds' % (sys.time()-t)
- Window.WaitCursor(0)
- if is_editmode: Window.EditMode(1)
-
-# This lets you can import the script without running it
-if __name__ == '__main__':
- main() \ No newline at end of file
diff --git a/release/scripts/wizard_curve2tree.py b/release/scripts/wizard_curve2tree.py
deleted file mode 100644
index eb27f1ca0f5..00000000000
--- a/release/scripts/wizard_curve2tree.py
+++ /dev/null
@@ -1,4034 +0,0 @@
-#!BPY
-"""
-Name: 'Tree from Curves'
-Blender: 245
-Group: 'Wizards'
-Tip: 'Generate trees from curve shapes'
-"""
-
-__author__ = "Campbell Barton"
-__url__ = ['www.blender.org', 'blenderartists.org']
-__version__ = "0.1"
-
-__bpydoc__ = """\
-
-"""
-
-# --------------------------------------------------------------------------
-# Tree from Curves v0.1 by Campbell Barton (AKA Ideasman42)
-# --------------------------------------------------------------------------
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-# ***** END GPL LICENCE BLOCK *****
-# --------------------------------------------------------------------------
-
-import bpy
-import Blender
-import BPyMesh
-from Blender.Mathutils import Vector, Matrix, CrossVecs, AngleBetweenVecs, LineIntersect, TranslationMatrix, ScaleMatrix, RotationMatrix, Rand
-from Blender.Geometry import ClosestPointOnLine
-from Blender.Noise import randuvec
-
-GLOBALS = {}
-GLOBALS['non_bez_error'] = 0
-
-'''
-def debugVec(v1,v2):
- sce = bpy.data.scenes.active
- me = bpy.data.meshes.new()
- me.verts.extend( [v1,v2] )
- me.edges.extend( [(0,1)] )
- sce.objects.new(me)
-'''
-
-def AngleBetweenVecsSafe(a1, a2):
- try:
- return AngleBetweenVecs(a1,a2)
- except:
- return 180.0
-
-# Copied from blender, we could wrap this! - BKE_curve.c
-# But probably not toooo bad in python
-def forward_diff_bezier(q0, q1, q2, q3, pointlist, steps, axis):
- f= float(steps)
- rt0= q0
- rt1= 3.0*(q1-q0)/f
- f*= f
- rt2= 3.0*(q0-2.0*q1+q2)/f
- f*= steps
- rt3= (q3-q0+3.0*(q1-q2))/f
-
- q0= rt0
- q1= rt1+rt2+rt3
- q2= 2*rt2+6*rt3
- q3= 6*rt3
- if axis == None:
- for a in xrange(steps+1):
- pointlist[a] = q0
- q0+= q1
- q1+= q2
- q2+= q3;
-
- else:
- for a in xrange(steps+1):
- pointlist[a][axis] = q0
- q0+= q1
- q1+= q2
- q2+= q3;
-
-def points_from_bezier_seg(steps, pointlist, radlist, bez1_vec, bez2_vec, radius1, radius2):
-
- # x,y,z,axis
- for ii in (0,1,2):
- forward_diff_bezier(bez1_vec[1][ii], bez1_vec[2][ii], bez2_vec[0][ii], bez2_vec[1][ii], pointlist, steps, ii)
-
- # radius - no axis, Copied from blenders BBone roll interpolation.
- forward_diff_bezier(radius1, radius1 + 0.390464*(radius2-radius1), radius2 - 0.390464*(radius2-radius1), radius2, radlist, steps, None)
-
-
-def debug_pt(co):
- Blender.Window.SetCursorPos(tuple(co))
- Blender.Window.RedrawAll()
- print 'debugging', co
-
-def freshMesh(mesh):
- '''
- Utility function to get a new mesh or clear the existing one, but dont clear everything.
- '''
- if mesh:
- materials = mesh.materials
- mesh.verts = None
- for group in mesh.getVertGroupNames():
- mesh.removeVertGroup(group)
-
- # Add materials back
- mesh.materials = materials
- else:
- mesh = bpy.data.meshes.new()
-
- return mesh
-
-def getObFromName(name):
- if name:
- try: return bpy.data.objects[name]
- except: return None
- else:
- return None
-
-def getGroupFromName(name):
- if name:
- try: return bpy.data.groups[name]
- except: return None
- else:
- return None
-
-def closestVecIndex(vec, vecls):
- best= -1
- best_dist = 100000000
- for i, vec_test in enumerate(vecls):
- # Dont use yet, we may want to tho
- if vec_test: # Seems odd, but use this so we can disable some verts in the list.
- dist = (vec-vec_test).length
- if dist < best_dist:
- best = i
- best_dist = dist
-
- return best
-
-IRATIONAL_NUM = 22.0/7.0
-def next_random_num(rnd):
- '''
- return a random number between 0.0 and 1.0
- '''
- rnd[0] += (rnd[0] * IRATIONAL_NUM) % 1
- # prevent
- if rnd[0] > 1000000:
- rnd[0]-=1000000
- return rnd[0] % 1
-
-eul = 0.00001
-
-BRANCH_TYPE_CURVE = 0
-BRANCH_TYPE_GROWN = 1
-BRANCH_TYPE_FILL = 2
-
-class tree:
- def __init__(self):
- self.branches_all = []
- self.branches_root = []
- self.branches_twigs = []
- self.mesh = None
- self.armature = None
- self.objectCurve = None
- self.objectCurveMat = None
- self.objectCurveIMat = None
-
- self.objectTwigBounds = None # use for twigs only at the moment.
- self.objectTwigBoundsIMat = None
- self.objectTwigBoundsMat = None
- self.objectTwigBoundsMesh = None
-
- self.objectLeafBounds = None
- self.objectLeafBoundsIMat = None
- self.objectLeafBoundsMesh = None
-
- self.limbScale = 1.0
-
- self.debug_objects = []
- self.steps = 6 # defalt, curve overwrites
-
- def __repr__(self):
- s = ''
- s += '[Tree]'
- s += ' limbScale: %.6f' % self.limbScale
- s += ' object: %s' % self.objectCurve
-
- for brch in self.branches_root:
- s += str(brch)
- return s
-
- def fromCurve(self, objectCurve):
- # Now calculate the normals
- self.objectCurve = objectCurve
- self.objectCurveMat = objectCurve.matrixWorld
- self.objectCurveIMat = self.objectCurveMat.copy().invert()
- curve = objectCurve.data
- self.steps = curve.resolu # curve resolution
-
- # Set the curve object scale
- if curve.bevob:
- # A bit of a hack to guess the size of the curve object if you have one.
- bb = curve.bevob.boundingBox
- # self.limbScale = (bb[0] - bb[7]).length / 2.825 # THIS IS GOOD WHEN NON SUBSURRFED
- self.limbScale = (bb[0] - bb[7]).length / 1.8
- elif curve.ext2 != 0.0:
- self.limbScale = curve.ext2 * 1.5
-
- # forward_diff_bezier will fill in the blanks
- # nice we can reuse these for every curve segment :)
- pointlist = [[None, None, None] for i in xrange(self.steps+1)]
- radlist = [ None for i in xrange(self.steps+1) ]
-
- for spline in curve:
-
- if len(spline) < 2: # Ignore single point splines
- continue
-
- if spline.type != 1: # 0 poly, 1 bez, 4 nurbs
- GLOBALS['non_bez_error'] = 1
- continue
-
-
- brch = branch()
- brch.type = BRANCH_TYPE_CURVE
-
-
-
- bez_list = list(spline)
- for i in xrange(1, len(bez_list)):
- bez1 = bez_list[i-1]
- bez2 = bez_list[i]
- vec1 = bez1.vec
- vec2 = bez2.vec
- if abs(vec1[1][0]-vec2[1][0]) > 0.000001 or\
- abs(vec1[1][1]-vec2[1][1]) > 0.000001 or\
- abs(vec1[1][2]-vec2[1][2]) > 0.000001:
-
- points_from_bezier_seg(self.steps, pointlist, radlist, vec1, vec2, bez1.radius, bez2.radius)
-
- # remove endpoint for all but the last
- len_pointlist = len(pointlist)
- if i != len(bez_list)-1:
- len_pointlist -= 1
-
- brch.bpoints.extend([ bpoint(brch, Vector(pointlist[ii]), Vector(), radlist[ii] * self.limbScale) for ii in xrange(len_pointlist) ])
-
- # Finalize once point data is there
- if brch.bpoints:
- # if all points are in the same location, this is possible
- self.branches_all.append(brch)
- if brch.bpoints[0].radius < brch.bpoints[-1].radius: # This means we dont have to worry about curve direction.
- brch.bpoints.reverse()
- brch.calcData()
-
- # Sort from big to small, so big branches get priority
- self.branches_all.sort( key = lambda brch: -brch.bpoints[0].radius )
-
-
- def closestBranchPt(self, co):
- best_brch = None
- best_pt = None
- best_dist = 10000000000
- for brch in self.branches_all:
- for pt in brch.bpoints:
- # if pt.inTwigBounds: # only find twigs, give different results for leaves
- l = (pt.co-co).length
- if l < best_dist:
- best_dist = l
- best_brch = brch
- best_pt = pt
- return best_brch, best_pt
-
- def setTwigBounds(self, objectMesh):
- self.objectTwigBounds = objectMesh
- self.objectTwigBoundsMesh = objectMesh.getData(mesh=1)
- self.objectTwigBoundsMat = objectMesh.matrixWorld.copy()
- self.objectTwigBoundsIMat = self.objectTwigBoundsMat.copy().invert()
-
- for brch in self.branches_all:
- brch.calcTwigBounds(self)
-
- def setLeafBounds(self, objectMesh):
- self.objectLeafBounds = objectMesh
- self.objectLeafBoundsMesh = objectMesh.getData(mesh=1)
- self.objectLeafBoundsIMat = objectMesh.matrixWorld.copy().invert()
-
- def isPointInTwigBounds(self, co, selected_only=False):
- return self.objectTwigBoundsMesh.pointInside(co * self.objectCurveMat * self.objectTwigBoundsIMat, selected_only)
-
- def isPointInLeafBounds(self, co, selected_only=False):
- return self.objectLeafBoundsMesh.pointInside(co * self.objectCurveMat * self.objectLeafBoundsIMat, selected_only)
-
- def resetTags(self, value):
- for brch in self.branches_all:
- brch.tag = value
-
- def buildConnections( self,\
- sloppy = 1.0,\
- connect_base_trim = 1.0,\
- do_twigs = False,\
- twig_ratio = 2.0,\
- twig_select_mode = 0,\
- twig_select_factor = 0.5,\
- twig_scale = 0.8,\
- twig_scale_width = 1.0,\
- twig_random_orientation = 180,\
- twig_random_angle = 33,\
- twig_recursive=True,\
- twig_recursive_limit=3,\
- twig_ob_bounds=None,\
- twig_ob_bounds_prune=True,\
- twig_ob_bounds_prune_taper=1.0,\
- twig_placement_maxradius=10.0,\
- twig_placement_maxtwig=0,\
- twig_follow_parent=0.0,\
- twig_follow_x=0.0,\
- twig_follow_y=0.0,\
- twig_follow_z=0.0,\
- do_variation = 0,\
- variation_seed = 1,\
- variation_orientation = 0.0,\
- variation_scale = 0.0,\
- do_twigs_fill = 0,\
- twig_fill_levels=4,\
- twig_fill_rand_scale=0.0,\
- twig_fill_fork_angle_max=180.0,\
- twig_fill_radius_min=0.1,\
- twig_fill_radius_factor=0.75,\
- twig_fill_shape_type=0,\
- twig_fill_shape_rand=0.0,\
- twig_fill_shape_power=0.3,\
- ):
- '''
- build tree data - fromCurve must run first
- '''
-
-
- # Sort the branchs by the first radius, so big branchs get joins first
- ### self.branches_all.sort( key = lambda brch: brch.bpoints[0].radius )
-
- #self.branches_all.reverse()
-
- # Connect branches
- for i in xrange(len(self.branches_all)):
- brch_i = self.branches_all[i]
-
- for j in xrange(len(self.branches_all)):
- if i != j:
- # See if any of the points match this branch
- # see if Branch 'i' is the child of branch 'j'
-
- brch_j = self.branches_all[j]
-
- if not brch_j.inParentChain(brch_i): # So we dont make cyclic tree!
-
- pt_best_j, dist = brch_j.findClosest(brch_i.bpoints[0].co)
-
- # Check its in range, allow for a bit out - hense the sloppy
- # The second check in the following IF was added incase the point is close enough to the line but the midpoint is further away
- # ...in this case the the resulting mesh will be adjusted to fit the join so its best to make it.
- if (dist < pt_best_j.radius * sloppy) or \
- ((brch_i.bpoints[0].co - pt_best_j.co).length < pt_best_j.radius * sloppy):
-
-
- brch_i.parent_pt = pt_best_j
- pt_best_j.childCount += 1 # dont remove me
-
- brch_i.baseTrim(connect_base_trim)
-
- '''
- if pt_best_j.childCount>4:
- raise "ERROR"
- '''
-
- # addas a member of best_j.children later when we have the geometry info available.
-
- #### print "Found Connection!!!", i, j
- break # go onto the next branch
-
- """
- children = [brch_child for brch_child in pt.children]
- if children:
- # This pt is one side of the segment, pt.next joins this segment.
- # calculate the median point the 2 segments would spanal
- # Once this is done we need to adjust 2 things
- # 1) move both segments up/down so they match the branches best.
- # 2) set the spacing of the segments around the point.
-
-
- # First try to get the ideal some space around each joint
- # the spacing shoule be an average of
- for brch.bpoints:
- """
-
- '''
- for brch in self.branches_all:
- brch.checkPointList()
- '''
-
- # Variations - use for making multiple versions of the same tree.
- if do_variation:
- irational_num = 22.0/7.0 # use to make the random number more odd
- rnd = [variation_seed]
-
- # Add children temporarily
- for brch in self.branches_all:
- if brch.parent_pt:
- rnd_rot = ((next_random_num(rnd) * variation_orientation) - 0.5) * 720
- mat_orientation = RotationMatrix(rnd_rot, 3, 'r', brch.parent_pt.no)
- rnd_sca = 1 + ((next_random_num(rnd)-0.5)* variation_scale )
- mat_scale = Matrix([rnd_sca,0,0],[0,rnd_sca,0],[0,0,rnd_sca])
- # mat_orientation = RotationMatrix(0, 3, 'r', brch.parent_pt.no)
- brch.transformRecursive(self, mat_scale * mat_orientation, brch.parent_pt.co)
-
- if (do_twigs or do_twigs_fill) and twig_ob_bounds: # Only spawn twigs inside this mesh
- self.setTwigBounds(twig_ob_bounds)
-
- # Important we so this with existing parent/child but before connecting and calculating verts.
- if do_twigs:
-
- # scale values down
- twig_random_orientation= twig_random_orientation/360.0
- twig_random_angle= twig_random_angle/360.0
-
- irational_num = 22.0/7.0 # use to make the random number more odd
-
- if not twig_recursive:
- twig_recursive_limit = 0
-
- self.buildTwigs(twig_ratio, twig_select_mode, twig_select_factor)
-
- branches_twig_attached = []
-
- # This wont add all! :/
- brch_twig_index = 0
- brch_twig_index_LAST = -1 # use this to prevent in inf loop, since its possible we cant place every branch
- while brch_twig_index < len(self.branches_twigs) and brch_twig_index_LAST != brch_twig_index:
- ###print "While"
- ### print brch_twig_index, len(self.branches_twigs) # if this dosnt change, quit the while
-
- brch_twig_index_LAST = brch_twig_index
-
- # new twigs have been added, recalculate
- branches_twig_sort = [brch.bestTwigSegment() for brch in self.branches_all]
- branches_twig_sort.sort() # this will sort the branches with best braches for adding twigs to at the start of the list
-
- for tmp_sortval, twig_pt_index, brch_parent in branches_twig_sort: # tmp_sortval is not used.
- if twig_pt_index != -1 and \
- (twig_recursive_limit == 0 or brch_parent.generation < twig_recursive_limit) and \
- (twig_placement_maxtwig == 0 or brch_parent.twig_count < twig_placement_maxtwig) and \
- brch_parent.bpoints[twig_pt_index].radius < twig_placement_maxradius:
-
- if brch_twig_index >= len(self.branches_twigs):
- break
-
- brch_twig = self.branches_twigs[brch_twig_index]
- parent_pt = brch_parent.bpoints[twig_pt_index]
-
- brch_twig.parent_pt = parent_pt
- parent_pt.childCount += 1
-
- # Scale this twig using this way...
- # The size of the parent, scaled by the parent point's radius,
- # ...compared to the parent branch;s root point radius.
- # Also take into account the length of the parent branch
- # Use this for pretend random numbers too.
- scale = twig_scale * (parent_pt.branch.bpoints[0].radius / brch_twig.bpoints[0].radius) * (parent_pt.radius / parent_pt.branch.bpoints[0].radius)
-
- # Random orientation
- # THIS IS NOT RANDOM - Dont be real random so we can always get re-produceale results.
- if twig_random_orientation: rnd1 = (((irational_num * scale * 10000000) % 360) - 180) * twig_random_orientation
- else: rnd1 = 0.0
- if twig_random_angle: rnd2 = (((irational_num * scale * 66666666) % 360) - 180) * twig_random_angle
- else: rnd2 = 0.0
-
- # Align this with the existing branch
- angle = AngleBetweenVecsSafe(zup, parent_pt.no)
- cross = CrossVecs(zup, parent_pt.no)
- mat_align = RotationMatrix(angle, 3, 'r', cross)
-
- # Use the bend on the point to work out which way to make the branch point!
- if parent_pt.prev: cross = CrossVecs(parent_pt.no, parent_pt.prev.no - parent_pt.no)
- else: cross = CrossVecs(parent_pt.no, parent_pt.next.no - parent_pt.no)
-
- if parent_pt.branch.parent_pt:
- angle = AngleBetweenVecsSafe(parent_pt.branch.parent_pt.no, parent_pt.no)
- else:
- # Should add a UI for this... only happens when twigs come off a root branch
- angle = 66
-
- mat_branch_angle = RotationMatrix(angle+rnd1, 3, 'r', cross)
- mat_scale = Matrix([scale,0,0],[0,scale,0],[0,0,scale])
-
- mat_orientation = RotationMatrix(rnd2, 3, 'r', parent_pt.no)
-
- if twig_scale_width != 1.0:
- # adjust length - no radius adjusting
- for pt in brch_twig.bpoints:
- pt.radius *= twig_scale_width
-
- brch_twig.transform(mat_scale * mat_branch_angle * mat_align * mat_orientation, parent_pt.co)
-
- # Follow the parent normal
- if twig_follow_parent or twig_follow_x or twig_follow_y or twig_follow_z:
-
- vecs = []
- brch_twig_len = float(len(brch_twig.bpoints))
-
- if twig_follow_parent:
- no = parent_pt.no.copy() * twig_follow_parent
- else:
- no = Vector()
-
- no.x += twig_follow_x
- no.y += twig_follow_y
- no.z += twig_follow_z
-
- for i, pt in enumerate(brch_twig.bpoints):
- if pt.prev:
- fac = i / brch_twig_len
-
- # Scale this value
- fac_inv = 1-fac
-
- no_orig = pt.co - pt.prev.co
- len_orig = no_orig.length
-
- no_new = (fac_inv * no_orig) + (fac * no)
- no_new.length = len_orig
-
- # Mix the 2 normals
- vecs.append(no_new)
-
- # Apply the coords
- for i, pt in enumerate(brch_twig.bpoints):
- if pt.prev:
- pt.co = pt.prev.co + vecs[i-1]
-
- brch_twig.calcPointExtras()
-
-
- # When using a bounding mesh, clip and calculate points in bounds.
- #print "Attempting to trim base"
- brch_twig.baseTrim(connect_base_trim)
-
- if twig_ob_bounds and (twig_ob_bounds_prune or twig_recursive):
- brch_twig.calcTwigBounds(self)
-
- # we would not have been but here if the bounds were outside
- if twig_ob_bounds_prune:
- brch_twig.boundsTrim()
- if twig_ob_bounds_prune_taper != 1.0:
- # taper to a point. we could use some nice taper algo here - just linear atm.
-
- brch_twig.taper(twig_ob_bounds_prune_taper)
-
- # Make sure this dosnt mess up anything else
-
- brch_twig_index += 1
-
- # Add to the branches
- #self.branches_all.append(brch_twig)
- if len(brch_twig.bpoints) > 2:
- branches_twig_attached.append(brch_twig)
- brch_twig.generation = brch_parent.generation + 1
- brch_parent.twig_count += 1
- else:
- # Dont add the branch
- parent_pt.childCount -= 1
-
- # Watch This! - move 1 tab down for no recursive twigs
- if twig_recursive:
- self.branches_all.extend(branches_twig_attached)
- branches_twig_attached = []
-
- if not twig_recursive:
- self.branches_all.extend(branches_twig_attached)
- branches_twig_attached = []
-
-
- if do_twigs_fill and twig_ob_bounds:
- self.twigFill(\
- twig_fill_levels,\
- twig_fill_rand_scale,\
- twig_fill_fork_angle_max,\
- twig_fill_radius_min,\
- twig_fill_radius_factor,\
- twig_fill_shape_type,\
- twig_fill_shape_rand,\
- twig_fill_shape_power,\
- )
-
- ### self.branches_all.sort( key = lambda brch: brch.parent_pt != None )
-
- # Calc points with dependancies
- # detect circular loops!!! - TODO
- #### self.resetTags(False) # NOT NEEDED NOW
- done_nothing = False
- while done_nothing == False:
- done_nothing = True
-
- for brch in self.branches_all:
-
- if brch.tag == False and (brch.parent_pt == None or brch.parent_pt.branch.tag == True):
- # Assign this to a spesific side of the parents point
- # we know this is a child but not which side it should be attached to.
- if brch.parent_pt:
-
- child_locs = [\
- brch.parent_pt.childPointUnused(0),\
- brch.parent_pt.childPointUnused(1),\
- brch.parent_pt.childPointUnused(2),\
- brch.parent_pt.childPointUnused(3)]
-
- best_idx = closestVecIndex(brch.bpoints[0].co, child_locs)
-
- # best_idx could be -1 if all childPoint's are used however we check for this and dont allow it to happen.
- #if best_idx==-1:
- # raise "Error"z
- brch.parent_pt.children[best_idx] = brch
-
- for pt in brch.bpoints:
- pt.calcVerts()
-
- done_nothing = False
- brch.tag = True
-
- '''
- for i in xrange(len(self.branches_all)):
- brch_i = self.branches_all[i]
- print brch_i.myindex,
- print 'tag', brch_i.tag,
- print 'parent is',
- if brch_i.parent_pt:
- print brch_i.parent_pt.branch.myindex
- else:
- print None
- '''
-
- def optimizeSpacing(self, seg_density=0.5, seg_density_angle=20.0, seg_density_radius=0.3, joint_compression=1.0, joint_smooth=1.0):
- '''
- Optimize spacing, taking branch hierarchy children into account,
- can add or subdivide segments so branch joins dont look horrible.
- '''
- for brch in self.branches_all:
- brch.evenJointDistrobution(joint_compression)
-
- # Correct points that were messed up from sliding
- # This happens when one point is pushed past another and the branch gets an overlaping line
-
- for brch in self.branches_all:
- brch.fixOverlapError(joint_smooth)
-
-
- # Collapsing
- for brch in self.branches_all:
- brch.collapsePoints(seg_density, seg_density_angle, seg_density_radius, joint_smooth)
-
- '''
- for brch in self.branches_all:
- brch.branchReJoin()
- '''
-
- def twigFill(self_tree,\
- twig_fill_levels,\
- twig_fill_rand_scale,\
- twig_fill_fork_angle_max,\
- twig_fill_radius_min,\
- twig_fill_radius_factor,\
- twig_fill_shape_type,\
- twig_fill_shape_rand,\
- twig_fill_shape_power,\
- ):
- '''
- Fill with twigs, this function uses its own class 'segment'
-
- twig_fill_shape_type;
- 0 - no child smoothing
- 1 - smooth one child
- 2 - smooth both children
-
- '''
-
- rnd = [1]
-
- segments_all = []
- segments_level = []
-
- # Only for testing
- def preview_curve():
- TWIG_WIDTH_MAX = 1.0
- TWIG_WIDTH_MIN = 0.1
- cu = bpy.data.curves["cu"]
- # remove all curves
- while len(cu):
- del cu[0]
- # return
-
- cu.setFlag(1)
- cu.ext2 = 0.01
-
- WIDTH_STEP = (TWIG_WIDTH_MAX-TWIG_WIDTH_MIN) / twig_fill_levels
-
- for i, seg in enumerate(segments_all):
-
- # 1 is the base and 2 is the tail
-
- p1_h2 = seg.getHeadHandle() # isnt used
- p1_co = seg.headCo
- p1_h1 = seg.getHeadHandle()
-
- p2_h1 = seg.getTailHandle()
-
- p2_co = seg.tailCo
- p2_h2 = seg.tailCo # isnt used
-
- bez1 = Blender.BezTriple.New([ p1_h1[0], p1_h1[1], p1_h1[2], p1_co[0], p1_co[1], p1_co[2], p1_h2[0], p1_h2[1], p1_h2[2] ])
- bez2 = Blender.BezTriple.New([ p2_h1[0], p2_h1[1], p2_h1[2], p2_co[0], p2_co[1], p2_co[2], p2_h2[0], p2_h2[1], p2_h2[2] ])
- bez1.handleTypes = bez2.handleTypes = [Blender.BezTriple.HandleTypes.FREE, Blender.BezTriple.HandleTypes.FREE]
-
- bez1.radius = TWIG_WIDTH_MIN + (WIDTH_STEP * (seg.levelFromLeaf+1))
- bez2.radius = TWIG_WIDTH_MIN + (WIDTH_STEP * seg.levelFromLeaf)
-
- cunurb = cu.appendNurb(bez1)
- cunurb.append(bez2)
-
- # This sucks
- for bez in cunurb:
- bez.handleTypes = [Blender.BezTriple.HandleTypes.FREE, Blender.BezTriple.HandleTypes.FREE]
-
- ### cc = sce.objects.new( cu )
- cu.update()
-
-
- def mergeCo(parentCo, ch1Co, ch2Co, twig_fill_shape_rand):
- if twig_fill_shape_rand==0.0:
- return (parentCo + ch1Co + ch2Co) / 3.0
- else:
-
- w1 = (next_random_num(rnd)*twig_fill_shape_rand) + (1-twig_fill_shape_rand)
- w2 = (next_random_num(rnd)*twig_fill_shape_rand) + (1-twig_fill_shape_rand)
- w3 = (next_random_num(rnd)*twig_fill_shape_rand) + (1-twig_fill_shape_rand)
- wtot = w1+w2+w3
- w1=w1/wtot
- w2=w2/wtot
- w3=w3/wtot
-
- # return (parentCo*w1 + ch1Co*w2 + ch2Co*w2)
- co1 = (parentCo * w1) + (ch1Co * (1.0-w1))
- co2 = (ch1Co * w2) + (ch2Co * (1.0-w2))
- co3 = (ch2Co * w3) + (parentCo * (1.0-w3))
-
- return (co1 + co2 + co3) / 3.0
-
-
-
- class segment:
- def __init__(self, level):
- self.headCo = Vector()
- self.tailCo = Vector()
- self.parent = None
- self.mergeCount = 0
- self.levelFromLeaf = level # how far we are from the leaf in levels
- self.levelFromRoot = -1 # set later, assume root bone
- self.children = []
- segments_all.append(self)
-
- if level >= len(segments_level): segments_level.append([self])
- else: segments_level[level].append(self)
-
- self.brothers = []
- self.no = Vector() # only endpoints have these
- # self.id = len(segments_all)
-
- # First value is the bpoint,
- # Second value is what to do -
- # 0 - dont join
- # 1 - Join to parent (tree point)
- # 2 - join to parent, point from another fill-twig branch we just created.
-
- self.bpt = (None, False) # branch point for root segs only
- self.new_bpt = None
-
- self.used = False # use this to tell if we are apart of a branch
-
- def sibling(self):
- i = self.parent.children.index(self)
-
- if i == 0:
- return self.parent.children[ 1 ]
- elif i == 1:
- return self.parent.children[ 0 ]
- else:
- raise "error"
-
-
- def getHeadHandle(self):
- """
- For Bezier only
- """
-
- if not self.parent:
- return self.headCo
-
- if twig_fill_shape_type == 0: # no smoothing
- return self.headCo
- elif twig_fill_shape_type == 1:
- if self.parent.children[1] == self:
- return self.headCo
- # 2 - always do both
-
-
- # Y shape with curve? optional
-
- # we have a parent but it has no handle direction, easier
- if not self.parent.parent: no = self.parent.headCo - self.parent.tailCo
- else: no = self.parent.parent.headCo-self.parent.tailCo
-
- no.length = self.getLength() * twig_fill_shape_power
- # Ok we have to account for the parents handle
- return self.headCo - no
- # return self.headCo - Vector(1, 0,0)
-
- def getTailHandle(self):
- """
- For Bezier only
- """
- if self.parent:
- no = self.parent.headCo-self.tailCo
- no.length = self.getLength() * twig_fill_shape_power
- return self.tailCo + no
- else:
- return self.tailCo # isnt used
-
- def getRootSeg(self):
- seg = self
- while seg.parent:
- seg = seg.parent
-
- return seg
-
- def calcBrothers(self):
- # Run on children first
- self.brothers.extend( \
- [seg_child_sibling.parent \
- for seg_child in self.children \
- for seg_child_sibling in seg_child.brothers \
- if seg_child_sibling.parent not in (self, None)]\
- )
- #print self.brothers
-
- def calcLevelFromRoot(self):
- if self.parent:
- self.levelFromRoot = self.parent.levelFromRoot + 1
-
- for seg_child in self.children:
- seg_child.calcLevelFromRoot()
-
- # Dont use for now, but scale worked, transform was never tested.
- """
- def transform(self, matrix):
- self.headCo = self.headCo * matrix
- self.tailCo = self.tailCo * matrix
-
- if self.children:
- ch1 = self.children[0]
- ch2 = self.children[1]
-
- ch1.transform(matrix)
- ch2.transform(matrix)
-
- def scale(self, scale, cent=None):
- # scale = 0.9
- #matrix = Matrix([scale,0,0],[0,scale,0],[0,0,scale]).resize4x4()
- #self.transform(matrix)
- if cent == None: # first iter
- cent = self.headCo
- self.tailCo = ((self.tailCo-cent) * scale) + cent
- else:
- self.headCo = ((self.headCo-cent) * scale) + cent
- self.tailCo = ((self.tailCo-cent) * scale) + cent
-
- if self.children:
- self.children[0].scale(scale, cent)
- self.children[1].scale(scale, cent)
- """
- def recalcChildLoc(self):
- if not self.children:
- return
- ch1 = self.children[0]
- ch2 = self.children[1]
- new_mid = mergeCo(self.headCo, ch1.tailCo, ch2.tailCo, twig_fill_shape_rand)
-
- self.tailCo[:] = ch1.headCo[:] = ch2.headCo[:] = new_mid
-
- ch1.recalcChildLoc()
- ch2.recalcChildLoc()
-
- def merge(self, other):
- """
- Merge other into self and make a new segment
- """
- """
- seg_child = segment(self.levelFromLeaf)
- self.levelFromLeaf += 1
-
- seg_child.parent = other.parent = self
-
- # No need, recalcChildLoc sets the other coords
- #self.parent.tailCo = (self.headCo + self.tailCo + other.tailCo) / 3.0
- #self.parent.headCo[:] = self.headCo
-
- seg_child.headCo[:] = self.headCo
-
- # isect = LineIntersect(self.headCo, self.tailCo, other.headCo, other.tailCo)
- # new_head = (isect[0]+isect[1]) * 0.5
-
- seg_child.mergeCount += 1
- other.mergeCount += 1
-
- self.children.extend([ seg_child, other ])
-
- self.recalcChildLoc()
-
- # print 'merging', self.id, other.id
- """
-
- #new_head = (self.headCo + self.tailCo + other.headCo + other.tailCo) * 0.25
-
- self.parent = other.parent = segment(self.levelFromLeaf + 1)
-
- # No need, recalcChildLoc sets the self.parent.tailCo
- # self.parent.tailCo = (self.headCo + self.tailCo + other.tailCo) / 3.0
-
- self.parent.headCo[:] = self.headCo
- self.parent.bpt = self.bpt
- self.bpt = (None, False)
-
- # isect = LineIntersect(self.headCo, self.tailCo, other.headCo, other.tailCo)
- # new_head = (isect[0]+isect[1]) * 0.5
-
- self.mergeCount += 1
- other.mergeCount += 1
-
- self.parent.children.extend([ self, other ])
-
- self.parent.recalcChildLoc()
- # print 'merging', self.id, other.id
-
-
- def findBestMerge(self, twig_fill_fork_angle_max):
- # print "findBestMerge"
- if self.parent != None:
- return
-
- best_dist = 1000000
- best_seg = None
- for seg_list in (self.brothers, segments_level[self.levelFromLeaf]):
- #for seg_list in (segments_level[self.levelFromLeaf],):
-
- # only use all other segments if we cant find any from our brothers
- if seg_list == segments_level[self.levelFromLeaf] and best_seg != None:
- break
-
- for seg in seg_list:
- # 2 ppoint join
- if seg != self and seg.mergeCount == 0 and seg.parent == None:
-
- # find the point they would join
- test_dist = (self.tailCo - seg.tailCo).length
- if test_dist < best_dist:
- if twig_fill_fork_angle_max > 179:
- best_dist = test_dist
- best_seg = seg
- else:
- # Work out if the desired angle range is ok.
- mco = mergeCo( self.headCo, self.tailCo, seg.tailCo, 0.0 ) # we dont want the random value for this test
- ang = AngleBetweenVecsSafe(self.tailCo-mco, seg.tailCo-mco)
- if ang < twig_fill_fork_angle_max:
- best_dist = test_dist
- best_seg = seg
- return best_seg
-
- def getNormal(self):
- return (self.headCo - self.tailCo).normalize()
-
- def getLength(self):
- return (self.headCo - self.tailCo).length
- """
- def toMatrix(self, LEAF_SCALE, LEAF_RANDSCALE, LEAF_RANDVEC):
- if LEAF_RANDSCALE: scale = LEAF_SCALE * Rand(1.0-LEAF_RANDSCALE, 1.0+LEAF_RANDSCALE)
- else: scale = LEAF_SCALE * 1.0
-
- if LEAF_RANDVEC: rand_vec = Vector( Rand(-1, 1), Rand(-1, 1), Rand(-1, 1) ).normalize() * LEAF_RANDVEC
- else: rand_vec = Vector( )
-
- return Matrix([scale,0,0],[0,scale,0],[0,0,scale]).resize4x4() * (self.no + rand_vec).toTrackQuat('x', 'z').toMatrix().resize4x4() * TranslationMatrix(self.tailCo)
- """
- def distripute_seg_on_mesh(me__, face_group):
- """
- add segment endpoints
- """
-
- vert_segment_mapping = {}
- for f in face_group:
- for v in f:
- i = v.index
- if i not in vert_segment_mapping:
- vert_segment_mapping[i] = len(segments_all)
- v.sel = True
- seg = segment(0)
- # seg.tailCo = v.co.copy() # headCo undefined atm.
- seg.tailCo = v.co.copy() * self_tree.objectTwigBoundsMat * self_tree.objectCurveIMat
-
- # self_tree.objectCurveMat
-
- seg.no = v.no
-
- # Build connectivity
- for ed in me__.edges:
- if ed.v1.sel and ed.v2.sel:
- i1,i2 = ed.key
- i1 = vert_segment_mapping[i1]
- i2 = vert_segment_mapping[i2]
-
- segments_all[i1].brothers.append( segments_all[i2] )
- segments_all[i2].brothers.append( segments_all[i1] )
-
- # Dont need to return anything, added when created.
-
- def set_seg_attach_point(seg, interior_points, twig_fill_rand_scale):
- """
- Can only run on end nodes that have normals set
- """
- best_dist = 1000000000.0
- best_point = None
-
- co = seg.tailCo
-
- for pt in interior_points:
- # line from the point to the seg endpoint
-
- line_normal = seg.tailCo - pt.nextMidCo
- l = line_normal.length
-
-
- cross1 = CrossVecs( seg.no, line_normal )
- cross2 = CrossVecs( pt.no, line_normal )
-
- angle_line = min(AngleBetweenVecsSafe(cross1, cross2), AngleBetweenVecsSafe(cross1, -cross2))
- angle_leaf_no_diff = min(AngleBetweenVecsSafe(line_normal, seg.no), AngleBetweenVecsSafe(line_normal, -seg.no))
-
- # BEST_ANG=66.0
- # angle = 66.0 # min(AngleBetweenVecs(v2_co-v1_co, leaf.co-cc), AngleBetweenVecs(v1_co-v2_co, leaf.co-cc))
- # print angle, angle2
- # l = (l * ((1+abs(angle-BEST_ANG))**2 )) / (1+angle_line)
- l = (1+(angle_leaf_no_diff/180)) * (1+(angle_line/180)) * l
-
- if l < best_dist:
- best_pt = pt
- best_co = pt.nextMidCo
-
- best_dist = l
-
- # twig_fill_rand_scale
- seg.headCo = best_co.copy()
-
- if twig_fill_rand_scale:
- seg_dir = seg.tailCo - seg.headCo
-
- seg_dir.length = seg_dir.length * ( 1.0 - (next_random_num(rnd)*twig_fill_rand_scale) )
- seg.tailCo = seg.headCo + seg_dir
-
-
- if best_pt.childCount < 4:
- # Watch this!!! adding a user before its attached and the branch is created!
- # make sure if its not added later on, this isnt left added
- best_pt.childCount += 1
-
- # True/False denotes weather we try to connect to our parent branch
- seg.bpt = (best_pt, True)
- else:
- seg.bpt = (best_pt, False)
-
- return True
-
-
- # END Twig code, next add them
-
-
- """
- Uses a reversed approch, fill in twigs from a bounding mesh
- """
- # print "twig_fill_fork_angle_max"
- # twig_fill_fork_angle_max = 60.0 #
- # forward_diff_bezier will fill in the blanks
- # nice we can reuse these for every curve segment :)
- pointlist = [[None, None, None] for i in xrange(self_tree.steps+1)]
- radlist = [ None for i in xrange(self_tree.steps+1) ]
-
- orig_branch_count = len(self_tree.branches_all)
-
- for face_group in BPyMesh.mesh2linkedFaces(self_tree.objectTwigBoundsMesh):
- # Set the selection to do point inside.
- self_tree.objectTwigBoundsMesh.sel = False
- for f in face_group: f.sel = True
-
- interior_points = []
- interior_normal = Vector()
- for i, brch in enumerate(self_tree.branches_all):
-
- if i == orig_branch_count:
- break # no need to check new branches are inside us
-
- for pt in brch.bpoints:
- if pt.next and pt.childCount < 4: # cannot attach to the last points
- if self_tree.isPointInTwigBounds(pt.co, True): # selected_only
- interior_points.append(pt)
- interior_normal += pt.no * pt.radius
-
- segments_all[:] = []
- segments_level[:] = []
-
- if interior_points:
- # Ok, we can add twigs now
- distripute_seg_on_mesh( self_tree.objectTwigBoundsMesh, face_group )
-
- for seg in segments_level[0]: # only be zero segments
- # Warning, increments the child count for bpoints we attach to!!
- set_seg_attach_point(seg, interior_points, twig_fill_rand_scale)
-
- # Try sorting by other properties! this is ok for now
- for segments_level_current in segments_level:
- segments_level_current.sort( key = lambda seg: -(seg.headCo-seg.tailCo).length )
-
- for level in xrange(twig_fill_levels):
- if len(segments_level) > level:
- for seg in segments_level[level]:
- # print level, seg.brothers
- if seg.mergeCount == 0:
- seg_merge = seg.findBestMerge(twig_fill_fork_angle_max)
- if seg_merge:
- seg.merge( seg_merge )
-
- if len(segments_level) > level+1:
- for seg in segments_level[level+1]:
- seg.calcBrothers()
-
- for seg in segments_all:
- if seg.parent == None:
- seg.levelFromRoot = 0
- seg.calcLevelFromRoot()
-
- '''
- for i, seg in enumerate(segments_all):
- # Make a branch from this data!
-
- brch = branch()
- brch.type = BRANCH_TYPE_FILL
- self_tree.branches_all.append(brch)
-
- # ============================= do this per bez pair
- # 1 is the base and 2 is the tail
-
- #p1_h1 = seg.getHeadHandle()
- p1_co = seg.headCo.copy()
- p1_h2 = seg.getHeadHandle() # isnt used
-
- p2_h1 = seg.getTailHandle()
- p2_co = seg.tailCo.copy()
- #p2_h2 = seg.getTailHandle() # isnt used
-
-
- bez1_vec = (None, p1_co, p1_h2)
- bez2_vec = (p2_h1, p2_co, None)
-
- seg_root = seg.getRootSeg()
-
- radius_root = seg_root.bpt.radius * twig_fill_radius_factor
- # Clamp so the head is never smaller then the tail
- if radius_root < twig_fill_radius_min: radius_root = twig_fill_radius_min
-
- if seg_root.levelFromLeaf:
- # print seg_root.levelFromLeaf, seg.levelFromRoot
- WIDTH_STEP = (radius_root - twig_fill_radius_min) / (seg_root.levelFromLeaf+1)
-
- radius1 = twig_fill_radius_min + (WIDTH_STEP * (seg.levelFromLeaf+1))
- if seg.levelFromLeaf: radius2 = twig_fill_radius_min + (WIDTH_STEP * seg.levelFromLeaf)
- else: radius2 = twig_fill_radius_min
- else:
- radius1 = radius_root
- radius2 = twig_fill_radius_min
-
-
- points_from_bezier_seg(self_tree.steps, pointlist, radlist, bez1_vec, bez2_vec, radius1, radius2)
-
- # dont apply self_tree.limbScale here! - its alredy done
- bpoints = [ bpoint(brch, Vector(pointlist[ii]), Vector(), radlist[ii]) for ii in xrange(len(pointlist)) ]
-
- # remove endpoint for all but the last
- #if i != len(bez_list)-1:
- # bpoints.pop()
-
- brch.bpoints.extend(bpoints)
- # =============================
-
- # Finalize once point data is there
- brch.calcData()
- #
- #preview_curve()
- '''
-
- for segments_level_current in reversed(segments_level):
- for seg in segments_level_current:
- if seg.used == False and (seg.parent == None or seg.parent.used == True):
-
- # The root segment for this set of links.
- # seg_root_linked = seg
-
- brch = branch()
- brch.type = BRANCH_TYPE_FILL
- self_tree.branches_all.append(brch)
-
- # Can we attach to a real branch?
- if seg.parent == None:
- if seg.bpt[1]: # we can do a real join into the attach point
- brch.parent_pt = seg.bpt[0]
- # brch.parent_pt.childCount # this has alredy changed from
-
- '''
- if seg.parent:
- if seg.bpt[1] == 2:
- #if seg.bpt[1]:
- # print "Making Connection"
- if seg.bpt[0] == None:
- raise "Error"
- if seg.bpt[1] != 2:
- print seg.bpt[1]
- raise "Error"
-
- brch.parent_pt = seg.bpt[1]
- brch.parent_pt.childCount += 1
- if brch.parent_pt.childCount > 4:
- raise "Aeeae"
- print "\n\nM<aking Joint!!"
- '''
-
- if seg.parent:
- sibling = seg.sibling()
- if sibling.new_bpt:
- if sibling.new_bpt.childCount < 4:
- brch.parent_pt = sibling.new_bpt
- brch.parent_pt.childCount +=1
-
- # Go down the hierarhy
- is_first = True
- while seg != None:
- seg.used = True
-
- # ==============================================
-
- #p1_h1 = seg.getHeadHandle()
- p1_co = seg.headCo.copy()
- p1_h2 = seg.getHeadHandle() # isnt used
-
- p2_h1 = seg.getTailHandle()
- p2_co = seg.tailCo.copy()
- #p2_h2 = seg.getTailHandle() # isnt used
-
-
- bez1_vec = (None, p1_co, p1_h2)
- bez2_vec = (p2_h1, p2_co, None)
-
- seg_root = seg.getRootSeg()
-
- radius_root = seg_root.bpt[0].radius * twig_fill_radius_factor
- # Clamp so the head is never smaller then the tail
- if radius_root < twig_fill_radius_min: radius_root = twig_fill_radius_min
-
- if seg_root.levelFromLeaf:
- # print seg_root.levelFromLeaf, seg.levelFromRoot
- widthStep = (radius_root - twig_fill_radius_min) / (seg_root.levelFromLeaf+1)
-
- radius1 = twig_fill_radius_min + (widthStep * (seg.levelFromLeaf+1))
- if seg.levelFromLeaf: radius2 = twig_fill_radius_min + (widthStep * seg.levelFromLeaf)
- else: radius2 = twig_fill_radius_min
- else:
- radius1 = radius_root
- radius2 = twig_fill_radius_min
-
- points_from_bezier_seg(self_tree.steps, pointlist, radlist, bez1_vec, bez2_vec, radius1, radius2)
-
-
- start_pointlist = 0
-
- # This is like baseTrim, (remove the base points to make nice joins, accounting for radius of parent point)
- # except we do it before the branch is made
-
- if brch.parent_pt:
- while len(pointlist) - start_pointlist > 2 and (Vector(pointlist[start_pointlist]) - brch.parent_pt.co).length < (brch.parent_pt.radius*2):
- start_pointlist +=1
-
- if is_first and brch.parent_pt:
- # We need to move the base point to a place where it looks good on the parent branch
- # to do this. move the first point, then remove the following points that look horrible (double back on themself)
-
- no = Vector(pointlist[0]) - Vector(pointlist[-1])
- no.length = brch.parent_pt.radius*2
- pointlist[0] = list(Vector(pointlist[0]) - no)
-
- """
- pointlist[1][0] = (pointlist[0][0] + pointlist[2][0])/2.0
- pointlist[1][1] = (pointlist[0][1] + pointlist[2][1])/2.0
- pointlist[1][2] = (pointlist[0][2] + pointlist[2][2])/2.0
-
- pointlist[2][0] = (pointlist[1][0] + pointlist[3][0])/2.0
- pointlist[2][1] = (pointlist[1][1] + pointlist[3][1])/2.0
- pointlist[2][2] = (pointlist[1][2] + pointlist[3][2])/2.0
- """
-
-
- # Done setting the start point
-
-
- len_pointlist = len(pointlist)
- if seg.children:
- len_pointlist -= 1
-
- # dont apply self_tree.limbScale here! - its alredy done
- bpoints = [ bpoint(brch, Vector(pointlist[ii]), Vector(), radlist[ii]) for ii in xrange(start_pointlist, len_pointlist) ]
- brch.bpoints.extend( bpoints )
- # ==============================================
-
- seg.new_bpt = bpoints[0]
-
- if seg.children:
- seg = seg.children[0]
- else:
- seg = None
-
- is_first = False
-
- # done adding points
- brch.calcData()
-
-
-
-
- def buildTwigs(self, twig_ratio, twig_select_mode, twig_select_factor):
-
- ratio_int = int(len(self.branches_all) * twig_ratio)
- if ratio_int == 0:
- return
-
- # So we only mix branches of similar lengths
- branches_sorted = self.branches_all[:]
-
- # Get the branches based on our selection method!
- if twig_select_mode==0:
- branches_sorted.sort( key = lambda brch: brch.getLength())
- elif twig_select_mode==1:
- branches_sorted.sort( key = lambda brch:-brch.getLength())
- elif twig_select_mode==2:
- branches_sorted.sort( key = lambda brch:brch.getStraightness())
- elif twig_select_mode==3:
- branches_sorted.sort( key = lambda brch:-brch.getStraightness())
-
- factor_int = int(len(self.branches_all) * twig_select_factor)
- branches_sorted[factor_int:] = [] # remove the last part of the list
-
- branches_sorted.sort( key = lambda brch: len(brch.bpoints))
-
- branches_new = []
- #for i in xrange(ratio_int):
- tot_twigs = 0
-
- step = 1
- while tot_twigs < ratio_int and step < len(branches_sorted):
- # Make branches from the existing
- for j in xrange(step, len(branches_sorted)):
- brch = branches_sorted[j-step].mixToNew(branches_sorted[j], None)
- branches_new.append( brch )
- tot_twigs +=1
-
- if tot_twigs > ratio_int:
- break
-
- ### print "TwigCount", len(branches_new), ratio_int
-
- self.branches_twigs = branches_new
-
- def toDebugDisplay(self):
- '''
- Should be able to call this at any time to see whats going on, dosnt work so nice ATM.
- '''
- sce = bpy.data.scenes.active
-
- for ob in self.debug_objects:
- for ob in sce.objects:
- sce.objects.unlink(ob)
-
- for branch_index, brch in enumerate(self.branches_all):
- pt_index = 0
- for pt_index, pt in enumerate(brch.bpoints):
- name = '%.3d_%.3d' % (branch_index, pt_index)
- if pt.next==None:
- name += '_end'
- if pt.prev==None:
- name += '_start'
-
- ob = sce.objects.new('Empty', name)
- self.debug_objects.append(ob)
- mat = ScaleMatrix(pt.radius, 4) * TranslationMatrix(pt.co)
- ob.setMatrix(mat)
- ob.setDrawMode(8) # drawname
- Blender.Window.RedrawAll()
-
-
-
- def toMesh(self, mesh=None,\
- do_uv=True,\
- do_uv_keep_vproportion=True,\
- do_uv_vnormalize=False,\
- do_uv_uscale=False,\
- uv_image = None,\
- uv_x_scale=1.0,\
- uv_y_scale=4.0,\
- do_uv_blend_layer= False,\
- do_cap_ends=False,\
- ):
-
- self.mesh = freshMesh(mesh)
- totverts = 0
-
- for brch in self.branches_all:
- totverts += len(brch.bpoints)
-
- self.mesh.verts.extend( [ (0.0,0.0,0.0) ] * ((totverts * 4)+1) ) # +1 is a dummy vert
- verts = self.mesh.verts
-
- # Assign verts to points, 4 verts for each point.
- i = 1 # dummy vert, should be 0
- for brch in self.branches_all:
- for pt in brch.bpoints:
- pt.verts[0] = verts[i]
- pt.verts[1] = verts[i+1]
- pt.verts[2] = verts[i+2]
- pt.verts[3] = verts[i+3]
- i+=4
-
- # Do this again because of collapsing
- # pt.calcVerts(brch)
-
- # roll the tube so quads best meet up to their branches.
- for brch in self.branches_all:
- #for pt in brch.bpoints:
- if brch.parent_pt:
-
- # Use temp lists for gathering an average
- if brch.parent_pt.roll_angle == None:
- brch.parent_pt.roll_angle = [brch.getParentQuadAngle()]
- # More then 2 branches use this point, add to the list
- else:
- brch.parent_pt.roll_angle.append( brch.getParentQuadAngle() )
-
- # average the temp lists into floats
- for brch in self.branches_all:
- #for pt in brch.bpoints:
- if brch.parent_pt and type(brch.parent_pt.roll_angle) == list:
- # print brch.parent_pt.roll_angle
- f = 0.0
- for val in brch.parent_pt.roll_angle:
- f += val
- brch.parent_pt.roll_angle = f/len(brch.parent_pt.roll_angle)
-
- # set the roll of all the first segments that have parents,
- # this is because their roll is set from their parent quad and we dont want them to roll away from that.
- for brch in self.branches_all:
- if brch.parent_pt:
- # if the first joint has a child then apply half the roll
- # theres no correct solition here, but this seems ok
- if brch.bpoints[0].roll_angle != None:
- #brch.bpoints[0].roll_angle *= 0.5
- #brch.bpoints[0].roll_angle = 0.0
- #brch.bpoints[1].roll_angle = 0.0
- brch.bpoints[0].roll_angle = 0.0
- pass
- else:
- # our roll was set from the branches parent and needs no changing
- # set it to zero so the following functions know to interpolate.
- brch.bpoints[0].roll_angle = 0.0
- #brch.bpoints[1].roll_angle = 0.0
-
- '''
- Now interpolate the roll!
- The method used here is a little odd.
-
- * first loop up the branch and set each points value to the "last defined" value and record the steps
- since the last defined value
- * Do the same again but backwards
-
- now for each undefined value we have 1 or 2 values, if its 1 its simple we just use that value
- ( no interpolation ), if there are 2 then we use the offsets from each end to work out the interpolation.
-
- one up, one back, and another to set the values, so 3 loops all up.
- '''
- #### print "scan up the branch..."
- for brch in self.branches_all:
- last_value = None
- last_index = -1
- for i in xrange(len(brch.bpoints)):
- pt = brch.bpoints[i]
- if type(pt.roll_angle) in (float, int):
- last_value = pt.roll_angle
- last_index = i
- else:
- if type(last_value) in (float, int):
- # Assign a list, because there may be a connecting roll value from another joint
- pt.roll_angle = [(last_value, i-last_index)]
-
- #### print "scan down the branch..."
- last_value = None
- last_index = -1
- for i in xrange(len(brch.bpoints)-1, -1, -1): # same as above but reverse
- pt = brch.bpoints[i]
- if type(pt.roll_angle) in (float, int):
- last_value = pt.roll_angle
- last_index = i
- else:
- if last_value != None:
- if type(pt.roll_angle) == list:
- pt.roll_angle.append((last_value, last_index-i))
- else:
- #pt.roll_angle = [(last_value, last_index-i)]
-
- # Dont bother assigning a list because we wont need to add to it later
- pt.roll_angle = last_value
-
- # print "looping ,...."
- ### print "assigning/interpolating roll values"
- for pt in brch.bpoints:
-
- # print "this roll IS", pt.roll_angle
-
- if pt.roll_angle == None:
- continue
- elif type(pt.roll_angle) in (float, int):
- pass
- elif len(pt.roll_angle) == 1:
- pt.roll_angle = pt.roll_angle[0][0]
- else:
- # interpolate
- tot = pt.roll_angle[0][1] + pt.roll_angle[1][1]
- pt.roll_angle = \
- (pt.roll_angle[0][0] * (tot - pt.roll_angle[0][1]) +\
- pt.roll_angle[1][0] * (tot - pt.roll_angle[1][1])) / tot
-
- #### print pt.roll_angle, 'interpolated roll'
-
- pt.roll(pt.roll_angle)
-
- # Done with temp average list. now we know the best roll for each branch.
-
- # mesh the data
- for brch in self.branches_all:
- for pt in brch.bpoints:
- pt.toMesh(self.mesh)
-
- #faces_extend = [ face for brch in self.branches_all for pt in brch.bpoints for face in pt.faces if face ]
-
-
-
- faces_extend = []
- for brch in self.branches_all:
- if brch.parent_pt:
- faces_extend.extend(brch.faces)
- for pt in brch.bpoints:
- for face in pt.faces:
- if face:
- faces_extend.append(face)
-
- if do_cap_ends:
- # TODO - UV map and image?
- faces_extend.extend([ brch.bpoints[-1].verts for brch in self.branches_all ])
-
- faces = self.mesh.faces
-
- faces.extend(faces_extend, smooth=True)
-
- if do_uv:
- # Assign the faces back
- face_index = 0
- for brch in self.branches_all:
- if brch.parent_pt:
- for i in (0,1,2,3):
- face = brch.faces[i] = faces[face_index+i]
- face_index +=4
-
- for pt in brch.bpoints:
- for i in (0,1,2,3):
- if pt.faces[i]:
- pt.faces[i] = faces[face_index]
- face_index +=1
-
- #if self.mesh.faces:
- # self.mesh.faceUV = True
- mesh.addUVLayer( 'base' )
-
- # rename the uv layer
- #mesh.renameUVLayer(mesh.getUVLayerNames()[0], 'base')
-
- for brch in self.branches_all:
-
- uv_x_scale_branch = 1.0
- if do_uv_uscale:
- uv_x_scale_branch = 0.0
- for pt in brch.bpoints:
- uv_x_scale_branch += pt.radius
-
- uv_x_scale_branch = uv_x_scale_branch / len(brch.bpoints)
- # uv_x_scale_branch = brch.bpoints[0].radius
-
- if do_uv_vnormalize:
- uv_normalize = []
-
- def uvmap_faces(my_faces, y_val, y_size):
- '''
- Accept a branch or pt faces
- '''
- uv_ls = [None, None, None, None]
- for i in (0,1,2,3):
- if my_faces[i]:
- if uv_image:
- my_faces[i].image = uv_image
- uvs = my_faces[i].uv
- else:
- # Use these for calculating blending values
- uvs = [Vector(0,0), Vector(0,0), Vector(0,0), Vector(0,0)]
-
- uv_ls[i] = uvs
-
- x1 = i*0.25 * uv_x_scale * uv_x_scale_branch
- x2 = (i+1)*0.25 * uv_x_scale * uv_x_scale_branch
-
- uvs[3].x = x1;
- uvs[3].y = y_val+y_size
-
- uvs[0].x = x1
- uvs[0].y = y_val
-
- uvs[1].x = x2
- uvs[1].y = y_val
-
- uvs[2].x = x2
- uvs[2].y = y_val+y_size
-
- if do_uv_vnormalize:
- uv_normalize.extend(uvs)
-
- return uv_ls
-
- # Done uvmap_faces
-
- y_val = 0.0
-
- if brch.parent_pt:
- y_size = (brch.getParentFaceCent() - brch.bpoints[0].co).length
-
- if do_uv_keep_vproportion:
- y_size = y_size / ((brch.bpoints[0].radius + brch.parent_pt.radius)/2) * uv_y_scale
-
- brch.uv = uvmap_faces(brch.faces, 0.0, y_size)
-
- y_val += y_size
-
- for pt in brch.bpoints:
- if pt.next:
- y_size = (pt.co-pt.next.co).length
- # scale the uvs by the radius, avoids stritching.
- if do_uv_keep_vproportion:
- y_size = y_size / pt.radius * uv_y_scale
- pt.uv = uvmap_faces(pt.faces, y_val, y_size)
- y_val += y_size
-
-
- if do_uv_vnormalize and uv_normalize:
- # Use yscale here so you can choose to have half the normalized value say.
- vscale = (1/uv_normalize[-1].y) * uv_y_scale
- for uv in uv_normalize:
- uv.y *= vscale
-
-
- # Done with UV mapping the first layer! now map the blend layers
- if do_uv_blend_layer:
- # Set up the blend UV layer - this is simply the blending for branch joints
- mesh.addUVLayer( 'blend' )
- mesh.activeUVLayer = 'blend'
-
- # Set all faces to be on full blend
- for f in mesh.faces:
- for uv in f.uv:
- uv.y = uv.x = 0.0
-
- for brch in self.branches_all:
- if brch.parent_pt:
- for f in brch.faces:
- if f:
- uvs = f.uv
- uvs[0].x = uvs[1].x = uvs[2].x = uvs[3].x = 0.0
- uvs[0].y = uvs[1].y = 1.0 # swap these? - same as inverting the blend
- uvs[2].y = uvs[3].y = 0.0
-
- # Set up the join UV layer, this overlays nice blended
- mesh.addUVLayer( 'join' )
- mesh.activeUVLayer = 'join'
-
- # Set all faces to be on full blend
- for f in mesh.faces:
- for uv in f.uv:
- uv.y = uv.x = 0.0
-
- for brch in self.branches_all:
- if brch.parent_pt:
- # The UV's that this branch would cover if it was a face,
- uvs_base = brch.parent_pt.uv[brch.getParentQuadIndex()]
-
- uvs_base_mid = Vector(0,0)
- for uv in uvs_base:
- uvs_base_mid += uv
-
- uvs_base_mid *= 0.25
-
- # TODO - Factor scale and distance in here
- ## uvs_base_small = [(uv+uvs_base_mid)*0.5 for uv in uvs_base]
- uvs_base_small = [uvs_base_mid, uvs_base_mid, uvs_base_mid, uvs_base_mid]
-
- if brch.faces[0]:
- f = brch.faces[0]
- uvs = f.uv
- uvs[0][:] = uvs_base[0]
- uvs[1][:] = uvs_base[1]
-
- uvs[2][:] = uvs_base_small[1]
- uvs[3][:] = uvs_base_small[0]
-
- if brch.faces[1]:
- f = brch.faces[1]
- uvs = f.uv
- uvs[0][:] = uvs_base[1]
- uvs[1][:] = uvs_base[2]
-
- uvs[2][:] = uvs_base_small[2]
- uvs[3][:] = uvs_base_small[1]
-
- if brch.faces[2]:
- f = brch.faces[2]
- uvs = f.uv
- uvs[0][:] = uvs_base[2]
- uvs[1][:] = uvs_base[3]
-
- uvs[2][:] = uvs_base_small[3]
- uvs[3][:] = uvs_base_small[2]
-
- if brch.faces[3]:
- f = brch.faces[3]
- uvs = f.uv
- uvs[0][:] = uvs_base[3]
- uvs[1][:] = uvs_base[0]
-
- uvs[2][:] = uvs_base_small[0]
- uvs[3][:] = uvs_base_small[3]
-
- mesh.activeUVLayer = 'base' # just so people dont get worried the texture is not there - dosnt effect rendering.
- else:
- # no UV's
- pass
-
- if do_cap_ends:
- # de-select end points for
- i = len(faces)-1
-
- cap_end_face_start = len(faces) - len(self.branches_all)
-
- j = 0
- for i in xrange(cap_end_face_start, len(faces)):
- self.branches_all[j].face_cap = faces[i]
- faces[i].sel = 0
-
- # default UV's are ok for now :/
- if do_uv and uv_image:
- faces[i].image = uv_image
-
- j +=1
-
- # set edge crease for capped ends.
- for ed in self.mesh.edges:
- if ed.v1.sel==False and ed.v2.sel==False:
- ed.crease = 255
- ed.sel = True # so its all selected still
-
- del faces_extend
-
- return self.mesh
-
- def toLeafMesh(self, mesh_leaf,\
- leaf_branch_limit = 0.5,\
- leaf_branch_limit_rand = 0.8,\
- leaf_branch_limit_type_curve = False,\
- leaf_branch_limit_type_grow = False,\
- leaf_branch_limit_type_fill = False,\
- leaf_size = 0.5,\
- leaf_size_rand = 0.5,\
- leaf_branch_density = 0.2,\
- leaf_branch_pitch_angle = 0.0,\
- leaf_branch_pitch_rand = 0.2,\
- leaf_branch_roll_rand = 0.2,\
- leaf_branch_angle = 75.0,\
- leaf_rand_seed = 1.0,\
- leaf_object=None,\
- ):
-
- '''
- return a mesh with leaves seperate from the tree
-
- Add to the existing mesh.
- '''
-
- #radius = [(pt.radius for pt in self.branches_all for pt in brch.bpoints for pt in brch.bpoints]
- mesh_leaf = freshMesh(mesh_leaf)
- self.mesh_leaf = mesh_leaf
-
- # if not leaf_object: return # make the dupli anyway :/ - they can do it later or the script could complain
-
- if leaf_branch_limit == 1.0:
- max_radius = 1000000.0
- else:
- # We wont place leaves on all branches so...
- # first collect stats, we want to know the average radius and total segments
- totpoints = 0
- radius = 0.0
- max_radius = 0.0
- for brch in self.branches_all:
- for pt in brch.bpoints:
- radius += pt.radius
- if pt.radius > max_radius:
- max_radius = pt.radius
-
- #totpoints += len(brch.bpoints)
-
- radius_max = max_radius * leaf_branch_limit
-
- verts_extend = []
- faces_extend = []
-
- co1 = Vector(0.0, -0.5, -0.5)
- co2 = Vector(0.0, -0.5, 0.5)
- co3 = Vector(0.0, 0.5, 0.5)
- co4 = Vector(0.0, 0.5, -0.5)
-
- rnd_seed = [leaf_rand_seed] # could have seed as an input setting
-
- for brch in self.branches_all:
-
- # quick test, do we need leaves on this branch?
- if leaf_branch_limit != 1.0 and brch.bpoints[-1].radius > radius_max:
- continue
-
-
- for pt in brch.bpoints:
-
- # For each point we can add 2 leaves
- for odd_even in (0,1):
-
-
- if (pt == brch.bpoints[-1] and odd_even==1) or \
- (leaf_branch_density != 1.0 and leaf_branch_density < next_random_num(rnd_seed)):
- pass
- else:
- if leaf_branch_limit_rand:
- # (-1 : +1) * leaf_branch_limit_rand
- rnd = 1 + (((next_random_num(rnd_seed) - 0.5) * 2 ) * leaf_branch_limit_rand)
- else:
- rnd = 1.0
-
- if pt.childCount == 0 and (leaf_branch_limit == 1.0 or (pt.radius * rnd) < radius_max):
- leaf_size_tmp = leaf_size * (1.0-(next_random_num(rnd_seed)*leaf_size_rand))
-
- # endpoints dont rotate
- if pt.next != None:
- cross1 = CrossVecs(zup, pt.no) # use this to offset the leaf later
- cross2 = CrossVecs(cross1, pt.no)
- if odd_even ==0:
- mat_yaw = RotationMatrix(leaf_branch_angle, 3, 'r', cross2)
- else:
- mat_yaw = RotationMatrix(-leaf_branch_angle, 3, 'r', cross2)
-
- leaf_no = (pt.no * mat_yaw)
-
- # Correct upwards pointing from changing the yaw
- #my_up = zup * mat
-
- # correct leaf location for branch width
- cross1.length = pt.radius/2
- leaf_co = pt.co + cross1
- else:
- # no correction needed, we are at the end of the branch
- leaf_no = pt.no
- leaf_co = pt.co
-
- mat = Matrix([leaf_size_tmp,0,0],[0,leaf_size_tmp,0],[0,0,leaf_size_tmp]) * leaf_no.toTrackQuat('x', 'z').toMatrix()
-
- # Randomize pitch and roll for the leaf
-
- # work out the axis to pitch and roll
- cross1 = CrossVecs(zup, leaf_no) # use this to offset the leaf later
- if leaf_branch_pitch_rand or leaf_branch_pitch_angle:
-
- angle = -leaf_branch_pitch_angle
- if leaf_branch_pitch_rand:
- angle += leaf_branch_pitch_rand * ((next_random_num(rnd_seed)-0.5)*360)
-
- mat_pitch = RotationMatrix( angle, 3, 'r', cross1)
- mat = mat * mat_pitch
- if leaf_branch_roll_rand:
- mat_roll = RotationMatrix( leaf_branch_roll_rand * ((next_random_num(rnd_seed)-0.5)*360), 3, 'r', leaf_no)
- mat = mat * mat_roll
-
- mat = mat.resize4x4() * TranslationMatrix(leaf_co)
-
- i = len(verts_extend)
- faces_extend.append( (i,i+1,i+2,i+3) )
- verts_extend.extend([tuple(co4*mat), tuple(co3*mat), tuple(co2*mat), tuple(co1*mat)])
- #count += 1
-
-
- # setup dupli's
-
- self.mesh_leaf.verts.extend(verts_extend)
- self.mesh_leaf.faces.extend(faces_extend)
-
- return self.mesh_leaf
-
-
- def toArmature(self, ob_arm, armature):
-
- armature.drawType = Blender.Armature.STICK
- armature.makeEditable() # enter editmode
-
- # Assume toMesh has run
- self.armature = armature
- for bonename in armature.bones.keys():
- del armature.bones[bonename]
-
-
- group_names = []
-
- for i, brch in enumerate(self.branches_all):
-
- # get a list of parent points to make into bones. use parents and endpoints
- bpoints_parent = [pt for pt in brch.bpoints if pt.childCount or pt.prev == None or pt.next == None]
- bpbone_last = None
- for j in xrange(len(bpoints_parent)-1):
-
- # bone container class
- bpoints_parent[j].bpbone = bpbone = bpoint_bone()
- bpbone.name = '%i_%i' % (i,j) # must be unique
- group_names.append(bpbone.name)
-
- bpbone.editbone = Blender.Armature.Editbone() # automatically added to the armature
- self.armature.bones[bpbone.name] = bpbone.editbone
-
- bpbone.editbone.head = bpoints_parent[j].co
- bpbone.editbone.head = bpoints_parent[j].co
- bpbone.editbone.tail = bpoints_parent[j+1].co
-
- # parent the chain.
- if bpbone_last:
- bpbone.editbone.parent = bpbone_last.editbone
- bpbone.editbone.options = [Blender.Armature.CONNECTED]
-
- bpbone_last = bpbone
-
- for brch in self.branches_all:
- if brch.parent_pt: # We must have a parent
-
- # find the bone in the parent chain to use for the parent of this
- parent_pt = brch.parent_pt
- bpbone_parent = None
- while parent_pt:
- bpbone_parent = parent_pt.bpbone
- if bpbone_parent:
- break
-
- parent_pt = parent_pt.prev
-
-
- if bpbone_parent:
- brch.bpoints[0].bpbone.editbone.parent = bpbone_parent.editbone
- else: # in rare cases this may not work. should be verry rare but check anyway.
- print 'this is really odd... look into the bug.'
-
- self.armature.update() # exit editmode
-
- # Skin the mesh
- if self.mesh:
- for group in group_names:
- self.mesh.addVertGroup(group)
-
- for brch in self.branches_all:
- vertList = []
- group = '' # dummy
-
- for pt in brch.bpoints:
- if pt.bpbone:
- if vertList:
- self.mesh.assignVertsToGroup(group, vertList, 1.0, Blender.Mesh.AssignModes.ADD)
-
- vertList = []
- group = pt.bpbone.name
-
- vertList.extend( [v.index for v in pt.verts] )
-
- if vertList:
- self.mesh.assignVertsToGroup(group, vertList, 1.0, Blender.Mesh.AssignModes.ADD)
-
- return self.armature
-
- def toAction(self, ob_arm, texture, anim_speed=1.0, anim_magnitude=1.0, anim_speed_size_scale=True, anim_offset_scale=1.0):
- # Assume armature
- action = ob_arm.action
- if not action:
- action = bpy.data.actions.new()
- action.fakeUser = False # so we dont get masses of bad data
- ob_arm.action = action
-
- # Blender.Armature.NLA.ob_arm.
- pose = ob_arm.getPose()
-
- for pose_bone in pose.bones.values():
- pose_bone.insertKey(ob_arm, 0, [Blender.Object.Pose.ROT], True)
-
- # Now get all the IPO's
-
- ipo_dict = action.getAllChannelIpos()
- # print ipo_dict
-
- # Sicne its per frame, it increases very fast. scale it down a bit
- anim_speed = anim_speed/100
-
- # When we have the same trees next to eachother, they will animate the same way unless we give each its own texture or offset settings.
- # We can use the object's location as a factor - this also will have the advantage? of seeing the animation move across the tree's
- # allow a scale so the difference between tree textures can be adjusted.
- anim_offset = self.objectCurve.matrixWorld.translationPart() * anim_offset_scale
-
- anim_speed_final = anim_speed
- # Assign drivers to them all
- for name, ipo in ipo_dict.iteritems():
- tex_str = 'b.Texture.Get("%s")' % texture.name
-
- if anim_speed_size_scale:
- # Adjust the speed by the bone size.
- # get the point from the name. a bit ugly but works fine ;) - Just dont mess the index up!
- lookup = [int(val) for val in name.split('_')]
- pt = self.branches_all[ lookup[0] ].bpoints[ lookup[1] ]
- anim_speed_final = anim_speed / (1+pt.radius)
-
- cu = ipo[Blender.Ipo.PO_QUATX]
- try: cu.delBezier(0)
- except: pass
- cu.driver = 2 # Python expression
- cu.driverExpression = '%.3f*(%s.evaluate(((b.Get("curframe")*%.3f)+%.3f,%.3f,%.3f)).w-0.5)' % (anim_magnitude, tex_str, anim_speed_final, anim_offset.x, anim_offset.y, anim_offset.z)
-
- cu = ipo[Blender.Ipo.PO_QUATY]
- try: cu.delBezier(0)
- except: pass
- cu.driver = 2 # Python expression
- cu.driverExpression = '%.3f*(%s.evaluate((%.3f,(b.Get("curframe")*%.3f)+%.3f,%.3f)).w-0.5)' % (anim_magnitude, tex_str, anim_offset.x, anim_speed_final, anim_offset.y, anim_offset.z)
-
- cu = ipo[Blender.Ipo.PO_QUATZ]
- try: cu.delBezier(0)
- except: pass
- cu.driver = 2 # Python expression
- cu.driverExpression = '%.3f*(%s.evaluate((%.3f,%.3f,(b.Get("curframe")*%.3f)+%.3f)).w-0.5)' % (anim_magnitude, tex_str, anim_offset.x, anim_offset.y, anim_speed_final, anim_offset.z)
-
-xyzup = Vector(1,1,1).normalize()
-xup = Vector(1,0,0)
-yup = Vector(0,1,0)
-zup = Vector(0,0,1)
-
-class bpoint_bone:
- def __init__(self):
- self.name = None
- self.editbone = None
- self.blenbone = None
- self.posebone = None
-
-class bpoint(object):
- ''' The point in the middle of the branch, not the mesh points
- '''
- __slots__ = 'branch', 'co', 'no', 'radius', 'vecs', 'verts', 'children', 'faces', 'uv', 'next', 'prev', 'childCount', 'bpbone', 'roll_angle', 'nextMidCo', 'childrenMidCo', 'childrenMidRadius', 'targetCos', 'inTwigBounds'
- def __init__(self, brch, co, no, radius):
- self.branch = brch
- self.co = co
- self.no = no
- self.radius = radius
- self.vecs = [None, None, None, None] # 4 for now
- self.verts = [None, None, None, None]
- self.children = [None, None, None, None] # child branches, dont fill in faces here
- self.faces = [None, None, None, None]
- self.uv = None # matching faces, except - UV's are calculated even if there is no face, this is so we can calculate the blending UV's
- self.next = None
- self.prev = None
- self.childCount = 0
- self.bpbone = None # bpoint_bone instance
-
- # when set, This is the angle we need to roll to best face our branches
- # the roll that is set may be interpolated if we are between 2 branches that need to roll.
- # Set to None means that the roll will be left default (from parent)
- self.roll_angle = None
-
-
- # The location between this and the next point,
- # if we want to be tricky we can try make this not just a simple
- # inbetween and use the normals to have some curvature
- self.nextMidCo = None
-
- # Similar to above, median point of all children
- self.childrenMidCo = None
-
- # Similar as above, but for radius
- self.childrenMidRadius = None
-
- # Target locations are used when you want to move the point to a new location but there are
- # more then 1 influence, build up a list and then apply
- self.targetCos = []
-
- # When we use twig bounding mesh, store if this point is in the bounding mesh. Assume true unless we set to false and do the test
- self.inTwigBounds = True
-
- def __repr__(self):
- s = ''
- s += '\t\tco:', self.co
- s += '\t\tno:', self.no
- s += '\t\tradius:', self.radius
- s += '\t\tchildren:', [(child != False) for child in self.children]
- return s
-
- def makeLast(self):
- self.next = None
- self.nextMidCo = None
- self.childrenMidCo = None
-
- def setCo(self, co):
- self.co[:] = co
- self.calcNextMidCo()
- self.calcNormal()
-
- if self.prev:
- self.prev.calcNextMidCo()
- self.prev.calcNormal()
- self.prev.calcChildrenMidData()
-
- if self.next:
- self.prev.calcNormal()
-
- self.calcChildrenMidData()
-
-
- def nextLength(self):
- return (self.co-self.next.co).length
- def prevLength(self):
- return (self.co-self.prev.co).length
-
- def hasOverlapError(self):
- if self.prev == None:
- return False
- if self.next == None:
- return False
- '''
- # see if this point sits on the line between its siblings.
- co, fac = ClosestPointOnLine(self.co, self.prev.co, self.next.co)
-
- if fac >= 0.0 and fac <= 1.0:
- return False # no overlap, we are good
- else:
- return True # error, some overlap
- '''
-
-
- # Alternate method, maybe better
- ln = self.nextLength()
- lp = self.prevLength()
- ls = (self.prev.co-self.next.co).length
-
- # Are we overlapping? the length from our next or prev is longer then the next-TO-previous?
- if ln>ls or lp>ls:
- return True
- else:
- return False
-
-
- def applyTargetLocation(self):
- if not self.targetCos:
- return False
- elif len(self.targetCos) == 1:
- co_all = self.targetCos[0]
- else:
- co_all = Vector()
- for co in self.targetCos:
- co_all += co
- co_all = co_all / len(self.targetCos)
-
- self.targetCos[:] = []
-
- length = (self.co-co_all).length
- # work out if we are moving up or down
- if AngleBetweenVecsSafe(self.no, self.co - co_all) < 90:
-
- # Up
- while length > (self.co-self.prev.co).length:
- if not self.collapseUp():
- break
-
- else:
- # Down
- while length*2 > (self.co-self.next.co).length:
- if not self.collapseDown():
- break
-
- self.setCo(co_all)
-
- return True
-
- def calcNextMidCo(self):
- if not self.next:
- return None
-
- # be tricky later.
- self.nextMidCo = (self.co + self.next.co) * 0.5
-
- def calcNormal(self):
- if self.prev == None:
- self.no = (self.next.co - self.co).normalize()
- elif self.next == None:
- self.no = (self.co - self.prev.co).normalize()
- else:
- self.no = (self.next.co - self.prev.co).normalize()
-
- def calcChildrenMidData(self):
- '''
- Calculate childrenMidCo & childrenMidRadius
- This is a bit tricky, we need to find a point between this and the next,
- the medium of all children, this point will be on the line between this and the next.
- '''
- if not self.next:
- return None
-
- # factor between this and the next point
- radius = factor = factor_i = 0.0
-
- count = 0
- for brch in self.children:
- if brch: # we dont need the co at teh moment.
- co, fac = ClosestPointOnLine(brch.bpoints[0].co, self.co, self.next.co)
- factor_i += fac
- count += 1
-
- radius += brch.bpoints[0].radius
-
- if not count:
- return
-
- # interpolate points
- factor_i = factor_i/count
- factor = 1-factor_i
-
- self.childrenMidCo = (self.co * factor) + (self.next.co * factor_i)
- self.childrenMidRadius = radius
-
- #debug_pt(self.childrenMidCo)
-
- def getAbsVec(self, index):
- # print self.vecs, index
- return self.co + self.vecs[index]
-
- def slide(self, factor):
- '''
- Slides the segment up and down using the prev and next points
- '''
- self.setCo(self.slideCo(factor))
-
- def slideCo(self, factor):
- if self.prev == None or self.next == None or factor==0.0:
- return
-
- if factor < 0.0:
- prev_co = self.prev.co
- co = self.co
-
- ofs = co-prev_co
- ofs.length = abs(factor)
- self.co - ofs
-
- return self.co - ofs
- else:
- next_co = self.next.co
- co = self.co
-
- ofs = co-next_co
- ofs.length = abs(factor)
-
- return self.co - ofs
-
-
- def collapseDown(self):
- '''
- Collapse the next point into this one
- '''
-
- # self.next.next == None check is so we dont shorten the final length of branches.
- if self.next == None or self.next.next == None or self.childCount or self.next.childCount:
- return False
-
- self.branch.bpoints.remove(self.next)
- self.next = self.next.next # skip
- self.next.prev = self
-
- # Watch this place - must update all data thats needed. roll is not calculaetd yet.
- self.calcNextMidCo()
- return True
-
- def collapseUp(self):
- '''
- Collapse the previous point into this one
- '''
-
- # self.next.next == None check is so we dont shorten the final length of branches.
- if self.prev == None or self.prev.prev == None or self.prev.childCount or self.prev.prev.childCount:
- return False
-
- self.branch.bpoints.remove(self.prev)
- self.prev = self.prev.prev # skip
- self.prev.next = self
-
- # Watch this place - must update all data thats needed. roll is not calculaetd yet.
- self.prev.calcNextMidCo()
- return True
-
-
- def smooth(self, factor, factor_joint):
- '''
- Blend this point into the other 2 points
- '''
- if self.next == None or self.prev == None:
- return False
-
- if self.childCount or self.prev.childCount:
- factor = factor_joint;
-
- if factor==0.0:
- return False;
-
- radius = (self.next.radius + self.prev.radius)/2.0
- no = (self.next.no + self.prev.no).normalize()
-
- # do a line intersect to work out the best location
- '''
- cos = LineIntersect( self.next.co, self.next.co+self.next.no,\
- self.prev.co, self.prev.co+self.prev.no)
- if cos == None:
- co = (self.prev.co + self.next.co)/2.0
- else:
- co = (cos[0]+cos[1])/2.0
- '''
- # Above can give odd results every now and then
- co = (self.prev.co + self.next.co)/2.0
-
- # Now apply
- factor_i = 1.0-factor
- self.setCo(self.co*factor_i + co*factor)
- self.radius = self.radius*factor_i + radius*factor
-
- return True
-
- def childPoint(self, index):
- '''
- Returns the middle point for any children between this and the next edge
- '''
- if self.next == None:
- raise 'Error'
-
- if index == 0: return (self.getAbsVec(0) + self.next.getAbsVec(1)) / 2
- if index == 1: return (self.getAbsVec(1) + self.next.getAbsVec(2)) / 2
- if index == 2: return (self.getAbsVec(2) + self.next.getAbsVec(3)) / 2
- if index == 3: return (self.getAbsVec(3) + self.next.getAbsVec(0)) / 2
-
- def childPointUnused(self, index):
- '''
- Same as above but return None when the point is alredy used.
- '''
- if self.children[index]:
- return None
- return self.childPoint(index)
-
-
- def roll(self, angle):
- '''
- Roll the quad about its normal
- use for aurienting the sides of a quad to meet a branch that stems from here...
- '''
- # debugVec(self.co, self.co + self.no)
-
- mat = RotationMatrix(angle, 3, 'r', self.no)
- for i in xrange(4):
- self.vecs[i] = self.vecs[i] * mat
-
-
- def toMesh(self, mesh):
- self.verts[0].co = self.getAbsVec(0)
- self.verts[1].co = self.getAbsVec(1)
- self.verts[2].co = self.getAbsVec(2)
- self.verts[3].co = self.getAbsVec(3)
-
- if not self.next:
- return
-
- if self.prev == None and self.branch.parent_pt:
- # join from parent branch
-
- # which side are we of the parents quad
- index = self.branch.parent_pt.children.index(self.branch)
-
- # collect the points we are to merge into between the parent its next point
- if index==0: verts = [self.branch.parent_pt.verts[0], self.branch.parent_pt.verts[1], self.branch.parent_pt.next.verts[1], self.branch.parent_pt.next.verts[0]]
- if index==1: verts = [self.branch.parent_pt.verts[1], self.branch.parent_pt.verts[2], self.branch.parent_pt.next.verts[2], self.branch.parent_pt.next.verts[1]]
- if index==2: verts = [self.branch.parent_pt.verts[2], self.branch.parent_pt.verts[3], self.branch.parent_pt.next.verts[3], self.branch.parent_pt.next.verts[2]]
- if index==3: verts = [self.branch.parent_pt.verts[3], self.branch.parent_pt.verts[0], self.branch.parent_pt.next.verts[0], self.branch.parent_pt.next.verts[3]]
-
-
- # Watchout for overlapping faces!
- self.branch.faces[:] =\
- [verts[0], verts[1], self.verts[1], self.verts[0]],\
- [verts[1], verts[2], self.verts[2], self.verts[1]],\
- [verts[2], verts[3], self.verts[3], self.verts[2]],\
- [verts[3], verts[0], self.verts[0], self.verts[3]]
-
- # normal join, parents or no parents
- if not self.children[0]: self.faces[0] = [self.verts[0], self.verts[1], self.next.verts[1], self.next.verts[0]]
- if not self.children[1]: self.faces[1] = [self.verts[1], self.verts[2], self.next.verts[2], self.next.verts[1]]
- if not self.children[2]: self.faces[2] = [self.verts[2], self.verts[3], self.next.verts[3], self.next.verts[2]]
- if not self.children[3]: self.faces[3] = [self.verts[3], self.verts[0], self.next.verts[0], self.next.verts[3]]
-
- def calcVerts(self):
- if self.prev == None:
- if self.branch.parent_pt:
- cross = CrossVecs(self.no, self.branch.parent_pt.no) * RotationMatrix(-45, 3, 'r', self.no)
- else:
- # parentless branch - for best results get a cross thats not the same as the normal, in rare cases this happens.
-
- # Was just doing
- # cross = zup
- # which works most of the time, but no verticle lines
-
- if AngleBetweenVecsSafe(self.no, zup) > 1.0: cross = zup
- elif AngleBetweenVecsSafe(self.no, yup) > 1.0: cross = yup
- else: cross = xup
-
- else:
- cross = CrossVecs(self.prev.vecs[0], self.no)
-
- self.vecs[0] = Blender.Mathutils.CrossVecs(self.no, cross)
- self.vecs[0].length = abs(self.radius)
- mat = RotationMatrix(90, 3, 'r', self.no)
- self.vecs[1] = self.vecs[0] * mat
- self.vecs[2] = self.vecs[1] * mat
- self.vecs[3] = self.vecs[2] * mat
-
- def hasChildren(self):
- '''
- Use .childCount where possible, this does the real check
- '''
- if self.children.count(None) == 4:
- return False
- else:
- return True
-
-class branch:
- def __init__(self):
- self.bpoints = []
- self.parent_pt = None
- self.tag = False # have we calculated our points
- self.face_cap = None
- self.length = -1
- # self.totchildren = 0
- # Bones per branch
- self.faces = [None, None, None, None]
- self.uv = None # face uvs can be fake, always 4
- self.bones = []
- self.generation = 0 # use to limit twig reproduction
- self.twig_count = 0 # count the number of twigs - so as to limit how many twigs a branch gets
- # self.myindex = -1
- ### self.segment_spacing_scale = 1.0 # use this to scale up the spacing - so small twigs dont get WAY too many polys
- self.type = None
-
- def __repr__(self):
- s = ''
- s += '\tbranch'
- s += '\tbpoints:', len(self.bpoints)
- for pt in brch.bpoints:
- s += str(self.pt)
-
- def getNormal(self):
- return (self.bpoints[-1].co - self.bpoints[0].co).normalize()
-
- def getParentAngle(self):
- if self.parent_pt:
- return AngleBetweenVecsSafe(self.parent_pt.no, self.bpoints[0].no )
- else:
- return 45.0
-
- def getParentRadiusRatio(self):
- if self.parent_pt:
- return self.bpoints[0].radius / self.parent_pt.radius
- else:
- return 0.8
-
- def getLength(self):
- return (self.bpoints[0].co - self.bpoints[-1].co).length
-
- def getStraightness(self):
- straight = 0.0
- pt = self.bpoints[0]
- while pt.next:
- straight += AngleBetweenVecsSafe(pt.no, pt.next.no)
- pt = pt.next
- return straight
-
-
- '''
- def calcTotChildren(self):
- for pt in self.bpoints:
- self.totchildren += pt.childCount
- '''
- def calcData(self):
- '''
- Finalize once point data is there
- '''
- self.calcPointLinkedList()
- self.calcPointExtras()
-
- def calcPointLinkedList(self):
- for i in xrange(1, len(self.bpoints)-1):
- self.bpoints[i].next = self.bpoints[i+1]
- self.bpoints[i].prev = self.bpoints[i-1]
-
- self.bpoints[0].next = self.bpoints[1]
- self.bpoints[-1].prev = self.bpoints[-2]
-
- def calcPointExtras(self):
- '''
- Run on a new branch or after transforming an existing one.
- '''
- for pt in self.bpoints:
- pt.calcNormal()
- pt.calcNextMidCo()
-
- def calcTwigBounds(self, tree):
- '''
- Check if out points are
- '''
- for pt in self.bpoints:
- pt.inTwigBounds = tree.isPointInTwigBounds(pt.co)
- #if pt.inTwigBounds:
- # debug_pt(pt.co)
-
- def baseTrim(self, connect_base_trim):
- # if 1) dont remove the whole branch, maybe an option but later
- # if 2) we are alredy a parent, cant remove me now.... darn :/ not nice...
- # could do this properly but it would be slower and its a corner case.
- #
- # if 3) this point is within the branch, remove it.
- # Scale this value by the difference in radius, a low trim looks better when the parent is a lot bigger..
- #
-
- while len(self.bpoints)>2 and\
- self.bpoints[0].childCount == 0 and\
- (self.parent_pt.nextMidCo - self.bpoints[0].co).length < ((self.parent_pt.radius + self.parent_pt.next.radius)/4) + (self.bpoints[0].radius * connect_base_trim):
- # Note /4 - is a bit odd, since /2 is correct, but /4 lets us have more tight joints by default
-
-
- del self.bpoints[0]
- self.bpoints[0].prev = None
-
- def boundsTrim(self):
- '''
- depends on calcTwigBounds running first. - also assumes no children assigned yet! make sure this is always the case.
- '''
- trim = False
- for i, pt in enumerate(self.bpoints):
- if not pt.inTwigBounds:
- trim = True
- break
-
- # We must have at least 2 points to be a valid branch. this will be a stump :/
- if not trim or i < 3:
- self.bpoints = [] #
- return
-
- # Shorten the point list
- self.bpoints = self.bpoints[:i]
- self.bpoints[-1].makeLast()
-
- def taper(self, twig_ob_bounds_prune_taper = 0.0):
- l = float(len( self.bpoints ))
- for i, pt in enumerate(self.bpoints):
- pt.radius *= (((l-i)/l) + (twig_ob_bounds_prune_taper*(i/l)) )
-
- def getParentBranch(self):
- if not self.parent_pt:
- return None
- return self.parent_pt.branch
-
- def getParentQuadAngle(self):
- '''
- The angle off we are from our parent quad,
- '''
- # used to roll the parent so its faces us better
-
- # Warning this can be zero sometimes, see the try below for the error
- parent_normal = self.getParentFaceCent() - self.parent_pt.nextMidCo
-
-
- self_normal = self.bpoints[1].co - self.parent_pt.co
- # We only want the angle in relation to the parent points normal
- # modify self_normal to make this so
- cross = CrossVecs(self_normal, self.parent_pt.no)
- self_normal = CrossVecs(self.parent_pt.no, cross) # CHECK
-
- #try: angle = AngleBetweenVecs(parent_normal, self_normal)
- #except: return 0.0
- angle = AngleBetweenVecsSafe(parent_normal, self_normal)
-
-
- # see if we need to rotate positive or negative
- # USE DOT PRODUCT!
- cross = CrossVecs(parent_normal, self_normal)
- if AngleBetweenVecsSafe(cross, self.parent_pt.no) > 90:
- angle = -angle
-
- return angle
-
- def getParentQuadIndex(self):
- return self.parent_pt.children.index(self)
- def getParentFaceCent(self):
- return self.parent_pt.childPoint( self.getParentQuadIndex() )
-
- def findClosest(self, co):
- '''
- Find the closest point that can bare a child
- '''
-
-
- ''' # this dosnt work, but could.
- best = None
- best_dist = 100000000
- for pt in self.bpoints:
- if pt.next:
- co_on_line, fac = ClosestPointOnLine(co, pt.co, pt.next.co)
- print fac
- if fac >= 0.0 and fac <= 1.0:
-
- return pt, (co-co_on_line).length
-
- return best, best_dist
- '''
- best = None
- best_dist = 100000000
- for pt in self.bpoints:
- if pt.nextMidCo and pt.childCount < 4:
- dist = (pt.nextMidCo-co).length
- if dist < best_dist:
- best = pt
- best_dist = dist
-
- return best, best_dist
-
- def inParentChain(self, brch):
- '''
- See if this branch is a parent of self or in the chain
- '''
-
- self_parent_lookup = self.getParentBranch()
- while self_parent_lookup:
- if self_parent_lookup == brch:
- return True
- self_parent_lookup = self_parent_lookup.getParentBranch()
-
- return False
-
- def transform(self, mat, loc=None, scale=None):
- if scale==None:
- scale = (xyzup * mat).length
-
- for pt in self.bpoints:
- if loc:
- pt.co = (pt.co * mat) + loc
- else:
- pt.co = pt.co * mat
- pt.radius *= scale
-
- for pt in self.bpoints:
- self.calcPointExtras()
-
- def translate(self, co):
- '''
- Simply move the twig on the branch
- '''
- ofs = self.bpoints[0].co-co
- for pt in self.bpoints:
- pt.co -= ofs
-
- def transformRecursive(self, tree, mat3x3, cent, scale=None):
-
- if scale==None:
- # incase this is a translation matrix
- scale = ((xyzup * mat3x3) - (Vector(0,0,0) * mat3x3)).length
-
- for pt in self.bpoints: pt.co = ((pt.co-cent) * mat3x3) + cent
- #for pt in self.bpoints: pt.co = (pt.co * mat3x3)
- for pt in self.bpoints: self.calcPointExtras()
-
-
- for brch in tree.branches_all:
- if brch.parent_pt:
- if brch.parent_pt.branch == self:
-
- brch.transformRecursive(tree, mat3x3, cent, scale)
-
- '''
- for pt in self.bpoints:
- for brch in pt.children:
- if brch:
- brch.transformRecursive(mat3x3, cent, scale)
- '''
- def bestTwigSegment(self):
- '''
- Return the most free part on the branch to place a new twig
- return (sort_value, best_index, self)
- '''
-
- # loop up and down the branch - counding how far from the last parent segment we are
- spacing1 = [0] * (len(self.bpoints)-1)
- spacing2 = spacing1[:]
-
- step_from_parent = 0
- for i in xrange(len(spacing1)): # -1 because the last pt cant have kits
-
- if self.bpoints[i].childCount or self.bpoints[i].inTwigBounds==False:
- step_from_parent = 0
- else:
- step_from_parent += 1
-
- spacing1[i] += step_from_parent # -1 because the last pt cant have kits
-
- best_index = -1
- best_val = -1
- step_from_parent = 0
- for i in xrange(len(spacing1)-1, -1, -1):
-
- if self.bpoints[i].childCount or self.bpoints[i].inTwigBounds==False:
- step_from_parent = 0
- else:
- step_from_parent += 1
-
- spacing2[i] += step_from_parent
-
- # inTwigBounds is true by default, when twigBounds are used it can be false
- if self.bpoints[i].childCount < 4 and self.bpoints[i].inTwigBounds:
- # Dont allow to assign more verts then 4
- val = spacing1[i] * spacing2[i]
- if val > best_val:
- best_val = val
- best_index = i
-
- #if best_index == -1:
- # raise "Error"
-
- # This value is only used for sorting, so the lower the value - the sooner it gets a twig.
- #sort_val = -best_val + (1/self.getLength())
- sort_val=self.getLength()
-
- return sort_val, best_index, self
-
- def evenPointDistrobution(self, factor=1.0, factor_joint=1.0):
- '''
- Redistribute points that are not evenly distributed
- factor is between 0.0 and 1.0
- '''
-
- for pt in self.bpoints:
- if pt.next and pt.prev and pt.childCount == 0 and pt.prev.childCount == 0:
- w1 = pt.nextLength()
- w2 = pt.prevLength()
- wtot = w1+w2
- if wtot > 0.0:
- w1=w1/wtot
- #w2=w2/wtot
- w1 = abs(w1-0.5)*2 # make this from 0.0 to 1.0, where 0 is the middle and 1.0 is as far out of the middle as possible.
- # print "%.6f" % w1
- pt.smooth(w1*factor, w1*factor_joint)
-
- def fixOverlapError(self, joint_smooth=1.0):
- # Keep fixing until no hasOverlapError left to fix.
-
- error = True
- while error:
- error = False
- for pt in self.bpoints:
- if pt.prev and pt.next:
- if pt.hasOverlapError():
- if pt.smooth(1.0, joint_smooth): # if we cant fix then dont bother trying again.
- error = True
-
- def evenJointDistrobution(self, joint_compression = 1.0):
- # See if we need to evaluate this branch at all
- if len(self.bpoints) <= 2: # Rare but in this case we cant do anything
- return
- has_children = False
- for pt in self.bpoints:
- if pt.childCount:
- has_children = True
- break
-
- if not has_children:
- return
-
- # OK, we have children, so we have some work to do...
- # center each segment
-
- # work out the median location of all points children.
- for pt in self.bpoints:
- pt.calcChildrenMidData()
- pt.targetCos[:] = []
-
- for pt in self.bpoints:
-
- if pt.childrenMidCo:
- # Move this and the next segment to be around the child point.
- # TODO - factor in the branch angle, be careful with this - close angles can have extreme values.
- slide_dist = (pt.childrenMidCo - pt.co).length - (pt.childrenMidRadius * joint_compression)
- co = pt.slideCo( slide_dist )
- if co:
- pt.targetCos.append( co )
-
- slide_dist = (pt.childrenMidRadius * joint_compression) - (pt.childrenMidCo - pt.next.co).length
- co = pt.next.slideCo( slide_dist )
- if co:
- pt.next.targetCos.append( co )
-
- for pt in reversed(self.bpoints):
- pt.applyTargetLocation()
-
- def collapsePoints(self, seg_density=0.5, seg_density_angle=20.0, seg_density_radius=0.3, smooth_joint=1.0):
-
- collapse = True
- while collapse:
- collapse = False
- pt = self.bpoints[0]
- while pt:
- # Collapse angles greater then 90. they are useually artifacts
-
- if pt.prev and pt.next and pt.prev.childCount == 0:
- if (pt.radius + pt.prev.radius) != 0.0 and abs(pt.radius - pt.prev.radius) / (pt.radius + pt.prev.radius) < seg_density_radius:
- ang = AngleBetweenVecsSafe(pt.no, pt.prev.no)
- if seg_density_angle == 180 or ang > 90 or ang < seg_density_angle:
- ## if (pt.prev.nextMidCo-pt.co).length < ((pt.radius + pt.prev.radius)/2) * seg_density:
- if (pt.prev.nextMidCo-pt.co).length < seg_density or ang > 90:
- pt_save = pt.prev
- if pt.next.collapseUp(): # collapse this point
- collapse = True
- pt = pt_save # so we never reference a removed point
-
- if pt.childCount == 0 and pt.next: #if pt.childrenMidCo == None:
- if (pt.radius + pt.next.radius) != 0.0 and abs(pt.radius - pt.next.radius) / (pt.radius + pt.next.radius) < seg_density_radius:
- ang = AngleBetweenVecsSafe(pt.no, pt.next.no)
- if seg_density_angle == 180 or ang > 90 or ang < seg_density_angle:
- # do here because we only want to run this on points with no children,
- # Are we closer theto eachother then the radius?
- ## if (pt.nextMidCo-pt.co).length < ((pt.radius + pt.next.radius)/2) * seg_density:
- if (pt.nextMidCo-pt.co).length < seg_density or ang > 90:
- if pt.collapseDown():
- collapse = True
-
- pt = pt.next
- ## self.checkPointList()
- self.evenPointDistrobution(1.0, smooth_joint)
-
- for pt in self.bpoints:
- pt.calcNormal()
- pt.calcNextMidCo()
-
- # This is a bit dodgy - moving the branches around after placing can cause problems
- """
- def branchReJoin(self):
- '''
- Not needed but nice to run after collapsing incase segments moved a lot
- '''
- if not self.parent_pt:
- return # nothing to do
-
- # see if the next segment is closer now (after collapsing)
- parent_pt = self.parent_pt
- root_pt = self.bpoints[0]
-
- #try:
- index = parent_pt.children.index(self)
- #except:
- #print "This is bad!, but not being able to re-join isnt that big a deal"
-
- current_dist = (parent_pt.nextMidCo - root_pt.co).length
-
- # TODO - Check size of new area is ok to move into
-
- if parent_pt.next and parent_pt.next.next and parent_pt.next.children[index] == None:
- # We can go here if we want, see if its better
- if current_dist > (parent_pt.next.nextMidCo - root_pt.co).length:
- self.parent_pt.children[index] = None
- self.parent_pt.childCount -= 1
-
- self.parent_pt = parent_pt.next
- self.parent_pt.children[index] = self
- self.parent_pt.childCount += 1
- return
-
- if parent_pt.prev and parent_pt.prev.children[index] == None:
- # We can go here if we want, see if its better
- if current_dist > (parent_pt.prev.nextMidCo - root_pt.co).length:
- self.parent_pt.children[index] = None
- self.parent_pt.childCount -= 1
-
- self.parent_pt = parent_pt.prev
- self.parent_pt.children[index] = self
- self.parent_pt.childCount += 1
- return
- """
-
- def checkPointList(self):
- '''
- Error checking. use to check if collapsing worked.
- '''
- p_link = self.bpoints[0]
- i = 0
- while p_link:
- if self.bpoints[i] != p_link:
- raise "Error"
-
- if p_link.prev and p_link.prev != self.bpoints[i-1]:
- raise "Error Prev"
-
- if p_link.next and p_link.next != self.bpoints[i+1]:
- raise "Error Next"
-
- p_link = p_link.next
- i+=1
-
- def mixToNew(self, other, BLEND_MODE):
- '''
- Generate a new branch based on 2 existing ones
- These branches will point 'zup' - aurient 'xup' and have a tip length of 1.0
- '''
-
- # Lets be lazy! - if the branches are different sizes- use the shortest.
- # brch1 is always smaller
-
- brch1 = self
- brch2 = other
- if len(brch1.bpoints) > len(brch2.bpoints):
- brch1, brch2 = brch2, brch1
-
- if len(brch1.bpoints) == 1:
- return None
-
- co_start = brch1.bpoints[0].co
- cos1 = [ pt.co - co_start for pt in brch1.bpoints ]
-
- co_start = brch2.bpoints[0].co
- if len(brch1.bpoints) == len(brch2.bpoints):
- cos2 = [ pt.co - co_start for pt in brch2.bpoints ]
- else: # truncate the points
- cos2 = [ brch2.bpoints[i].co - co_start for i in xrange(len(brch1.bpoints)) ]
-
- scales = []
- for cos_ls in (cos1, cos2):
- cross = CrossVecs(cos_ls[-1], zup)
- mat = RotationMatrix(AngleBetweenVecsSafe(cos_ls[-1], zup), 3, 'r', cross)
- cos_ls[:] = [co*mat for co in cos_ls]
-
- # point z-up
-
- # Now they are both pointing the same way aurient the curves to be rotated the same way
- xy_nor = Vector(0,0,0)
- for co in cos_ls:
- xy_nor.x += co.x
- xy_nor.y += co.y
- cross = CrossVecs(xy_nor, xup)
-
- # Also scale them here so they are 1.0 tall always
- scale = 1.0/(cos_ls[0]-cos_ls[-1]).length
- mat = RotationMatrix(AngleBetweenVecsSafe(xy_nor, xup), 3, 'r', cross) * Matrix([scale,0,0],[0,scale,0],[0,0,scale])
- cos_ls[:] = [co*mat for co in cos_ls]
-
- scales.append(scale)
-
- # Make the new branch
- new_brch = branch()
- new_brch.type = BRANCH_TYPE_GROWN
- for i in xrange(len(cos1)):
- new_brch.bpoints.append( bpoint(new_brch, (cos1[i]+cos2[i])*0.5, Vector(), (brch1.bpoints[i].radius*scales[0] + brch2.bpoints[i].radius*scales[1])/2) )
-
- new_brch.calcData()
- return new_brch
-
- '''
- def toMesh(self):
- pass
- '''
-
-
-
-
-# No GUI code above this! ------------------------------------------------------
-
-# PREFS - These can be saved on the object's id property. use 'tree2curve' slot
-from Blender import Draw
-import BPyWindow
-ID_SLOT_NAME = 'Curve2Tree'
-
-EVENT_NONE = 0
-EVENT_EXIT = 1
-EVENT_UPDATE = 2
-EVENT_UPDATE_AND_UI = 2
-EVENT_REDRAW = 3
-
-
-# Prefs for each tree
-PREFS = {}
-PREFS['connect_sloppy'] = Draw.Create(1.5)
-PREFS['connect_base_trim'] = Draw.Create(1.0)
-PREFS['seg_density'] = Draw.Create(0.5)
-PREFS['seg_density_angle'] = Draw.Create(20.0)
-PREFS['seg_density_radius'] = Draw.Create(0.3)
-PREFS['seg_joint_compression'] = Draw.Create(1.0)
-PREFS['seg_joint_smooth'] = Draw.Create(2.0)
-PREFS['image_main'] = Draw.Create('')
-PREFS['do_uv'] = Draw.Create(0)
-PREFS['uv_x_scale'] = Draw.Create(4.0)
-PREFS['uv_y_scale'] = Draw.Create(1.0)
-PREFS['do_material'] = Draw.Create(0)
-PREFS['material_use_existing'] = Draw.Create(1)
-PREFS['material_texture'] = Draw.Create(1)
-PREFS['material_stencil'] = Draw.Create(1)
-PREFS['do_subsurf'] = Draw.Create(1)
-PREFS['do_cap_ends'] = Draw.Create(0)
-PREFS['do_uv_keep_vproportion'] = Draw.Create(1)
-PREFS['do_uv_vnormalize'] = Draw.Create(0)
-PREFS['do_uv_uscale'] = Draw.Create(0)
-PREFS['do_armature'] = Draw.Create(0)
-PREFS['do_anim'] = Draw.Create(1)
-try: PREFS['anim_tex'] = Draw.Create([tex for tex in bpy.data.textures][0].name)
-except: PREFS['anim_tex'] = Draw.Create('')
-
-PREFS['anim_speed'] = Draw.Create(0.2)
-PREFS['anim_magnitude'] = Draw.Create(0.2)
-PREFS['anim_speed_size_scale'] = Draw.Create(1)
-PREFS['anim_offset_scale'] = Draw.Create(1.0)
-
-PREFS['do_twigs_fill'] = Draw.Create(0)
-PREFS['twig_fill_levels'] = Draw.Create(4)
-
-PREFS['twig_fill_rand_scale'] = Draw.Create(0.1)
-PREFS['twig_fill_fork_angle_max'] = Draw.Create(180.0)
-PREFS['twig_fill_radius_min'] = Draw.Create(0.001)
-PREFS['twig_fill_radius_factor'] = Draw.Create(0.75)
-PREFS['twig_fill_shape_type'] = Draw.Create(1)
-PREFS['twig_fill_shape_rand'] = Draw.Create(0.5)
-PREFS['twig_fill_shape_power'] = Draw.Create(0.5)
-
-PREFS['do_twigs'] = Draw.Create(0)
-PREFS['twig_ratio'] = Draw.Create(2.0)
-PREFS['twig_select_mode'] = Draw.Create(0)
-PREFS['twig_select_factor'] = Draw.Create(0.5)
-PREFS['twig_scale'] = Draw.Create(0.8)
-PREFS['twig_scale_width'] = Draw.Create(1.0)
-PREFS['twig_random_orientation'] = Draw.Create(180)
-PREFS['twig_random_angle'] = Draw.Create(33)
-PREFS['twig_recursive'] = Draw.Create(1)
-PREFS['twig_recursive_limit'] = Draw.Create(3)
-PREFS['twig_ob_bounds'] = Draw.Create('') # WATCH out, used for do_twigs_fill AND do_twigs
-PREFS['twig_ob_bounds_prune'] = Draw.Create(1)
-PREFS['twig_ob_bounds_prune_taper'] = Draw.Create(1.0)
-PREFS['twig_placement_maxradius'] = Draw.Create(10.0)
-PREFS['twig_placement_maxtwig'] = Draw.Create(4)
-PREFS['twig_follow_parent'] = Draw.Create(0.0)
-PREFS['twig_follow_x'] = Draw.Create(0.0)
-PREFS['twig_follow_y'] = Draw.Create(0.0)
-PREFS['twig_follow_z'] = Draw.Create(0.0)
-
-PREFS['do_leaf'] = Draw.Create(0)
-
-PREFS['leaf_branch_limit'] = Draw.Create(0.25)
-PREFS['leaf_branch_limit_rand'] = Draw.Create(0.1)
-PREFS['leaf_branch_density'] = Draw.Create(0.1)
-PREFS['leaf_branch_pitch_angle'] = Draw.Create(0.0)
-PREFS['leaf_branch_pitch_rand'] = Draw.Create(0.2)
-PREFS['leaf_branch_roll_rand'] = Draw.Create(0.2)
-PREFS['leaf_branch_angle'] = Draw.Create(75.0)
-PREFS['leaf_rand_seed'] = Draw.Create(1.0)
-PREFS['leaf_size'] = Draw.Create(0.5)
-PREFS['leaf_size_rand'] = Draw.Create(0.5)
-
-PREFS['leaf_object'] = Draw.Create('')
-
-PREFS['do_variation'] = Draw.Create(0)
-PREFS['variation_seed'] = Draw.Create(1)
-PREFS['variation_orientation'] = Draw.Create(0.0)
-PREFS['variation_scale'] = Draw.Create(0.0)
-
-GLOBAL_PREFS = {}
-GLOBAL_PREFS['realtime_update'] = Draw.Create(0)
-
-
-def getContextCurveObjects():
- sce = bpy.data.scenes.active
- objects = []
- ob_act = sce.objects.active
- for ob in sce.objects.context:
- if ob == ob_act: ob_act = None
-
- if ob.type != 'Curve':
- ob = ob.parent
- if not ob or ob.type != 'Curve':
- continue
- objects.append(ob)
-
- # Alredy delt with
-
-
- # Add the active, important when using localview or local layers
- if ob_act:
- ob = ob_act
- if ob.type != 'Curve':
- ob = ob.parent
- if not ob or ob.type != 'Curve':
- pass
- else:
- objects.append(ob)
-
- return objects
-
-
-def Prefs2Dict(prefs, new_prefs):
- '''
- Make a copy with no button settings
- '''
- new_prefs.clear()
- for key, val in prefs.items():
- try: new_prefs[key] = val.val
- except: new_prefs[key] = val
- return new_prefs
-
-def Dict2Prefs(prefs, new_prefs):
- '''
- Make a copy with button settings
- '''
- for key in prefs: # items would be nice for id groups
- val = prefs[key]
- ok = True
-
- try:
- # If we have this setting allredy but its a different type, use the old setting (converting int's to floats for instance)
- new_val = new_prefs[key] # this may fail, thats ok
- if (type(new_val)==Blender.Types.ButtonType) and (type(new_val.val) != type(val)):
- ok = False
- except:
- pass
-
- if ok:
- try:
- new_prefs[key] = Blender.Draw.Create( val )
- except:
- new_prefs[key] = val
-
- return new_prefs
-
-def Prefs2IDProp(idprop, prefs):
- new_prefs = {}
- Prefs2Dict(prefs, new_prefs)
- try: del idprop[ID_SLOT_NAME]
- except: pass
-
- idprop[ID_SLOT_NAME] = new_prefs
-
-def IDProp2Prefs(idprop, prefs):
- try:
- prefs = idprop[ID_SLOT_NAME]
- except:
- return False
- Dict2Prefs(prefs, PREFS)
- return True
-
-def buildTree(ob_curve, single=False):
- '''
- Must be a curve object, write to a child mesh
- Must check this is a curve object!
- '''
- print 'Curve2Tree, starting...'
- # if were only doing 1 object, just use the current prefs
- prefs = {}
-
- if single or not (IDProp2Prefs(ob_curve.properties, prefs)):
- prefs = PREFS
-
-
- # Check prefs are ok.
-
-
- sce = bpy.data.scenes.active
-
- def getObChild(parent, obtype):
- try:
- return [ _ob for _ob in sce.objects if _ob.type == obtype if _ob.parent == parent ][0]
- except:
- return None
-
- def newObChild(parent, obdata):
-
- ob_new = bpy.data.scenes.active.objects.new(obdata)
- # ob_new.Layers = parent.Layers
-
- # new object settings
- parent.makeParent([ob_new])
- ob_new.setMatrix(Matrix())
- ob_new.sel = 0
- return ob_new
-
- def hasModifier(modtype):
- return len([mod for mod in ob_mesh.modifiers if mod.type == modtype]) > 0
-
-
- sce = bpy.data.scenes.active
-
- if PREFS['image_main'].val:
- try: image = bpy.data.images[PREFS['image_main'].val]
- except: image = None
- else: image = None
-
- # Get the mesh child
-
- print '\treading blenders curves...',
- time1 = Blender.sys.time()
-
- t = tree()
- t.fromCurve(ob_curve)
- if not t.branches_all:
- return # Empty curve? - may as well not throw an error
-
- time2 = Blender.sys.time() # time print
- """
- print '%.4f sec' % (time2-time1)
- if PREFS['do_twigs'].val:
- print '\tbuilding twigs...',
- t.buildTwigs(ratio=PREFS['twig_ratio'].val)
- time3 = Blender.sys.time() # time print
- print '%.4f sec' % (time3 - time2)
- """
- if 0: pass
- else:
- time3 = Blender.sys.time() # time print
-
- print '\tconnecting branches...',
-
- twig_ob_bounds = getObFromName(PREFS['twig_ob_bounds'].val)
-
- t.buildConnections(\
- sloppy = PREFS['connect_sloppy'].val,\
- connect_base_trim = PREFS['connect_base_trim'].val,\
- do_twigs = PREFS['do_twigs'].val,\
- twig_ratio = PREFS['twig_ratio'].val,\
- twig_select_mode = PREFS['twig_select_mode'].val,\
- twig_select_factor = PREFS['twig_select_factor'].val,\
- twig_scale = PREFS['twig_scale'].val,\
- twig_scale_width = PREFS['twig_scale_width'].val,\
- twig_random_orientation = PREFS['twig_random_orientation'].val,\
- twig_random_angle = PREFS['twig_random_angle'].val,\
- twig_recursive = PREFS['twig_recursive'].val,\
- twig_recursive_limit = PREFS['twig_recursive_limit'].val,\
- twig_ob_bounds = twig_ob_bounds,\
- twig_ob_bounds_prune = PREFS['twig_ob_bounds_prune'].val,\
- twig_ob_bounds_prune_taper = PREFS['twig_ob_bounds_prune_taper'].val,\
- twig_placement_maxradius = PREFS['twig_placement_maxradius'].val,\
- twig_placement_maxtwig = PREFS['twig_placement_maxtwig'].val,\
- twig_follow_parent = PREFS['twig_follow_parent'].val,\
- twig_follow_x = PREFS['twig_follow_x'].val,\
- twig_follow_y = PREFS['twig_follow_y'].val,\
- twig_follow_z = PREFS['twig_follow_z'].val,\
- do_variation = PREFS['do_variation'].val,\
- variation_seed = PREFS['variation_seed'].val,\
- variation_orientation = PREFS['variation_orientation'].val,\
- variation_scale = PREFS['variation_scale'].val,\
- do_twigs_fill = PREFS['do_twigs_fill'].val,\
- twig_fill_levels = PREFS['twig_fill_levels'].val,\
- twig_fill_rand_scale = PREFS['twig_fill_rand_scale'].val,\
- twig_fill_fork_angle_max = PREFS['twig_fill_fork_angle_max'].val,\
- twig_fill_radius_min = PREFS['twig_fill_radius_min'].val,\
- twig_fill_radius_factor = PREFS['twig_fill_radius_factor'].val,\
- twig_fill_shape_type = PREFS['twig_fill_shape_type'].val,\
- twig_fill_shape_rand = PREFS['twig_fill_shape_rand'].val,\
- twig_fill_shape_power = PREFS['twig_fill_shape_power'].val,\
- )
-
- time4 = Blender.sys.time() # time print
- print '%.4f sec' % (time4-time3)
- print '\toptimizing point spacing...',
-
- t.optimizeSpacing(\
- seg_density=PREFS['seg_density'].val,\
- seg_density_angle=PREFS['seg_density_angle'].val,\
- seg_density_radius=PREFS['seg_density_radius'].val,\
- joint_compression = PREFS['seg_joint_compression'].val,\
- joint_smooth = PREFS['seg_joint_smooth'].val\
- )
-
- time5 = Blender.sys.time() # time print
- print '%.4f sec' % (time5-time4)
- print '\tbuilding mesh...',
-
- ob_mesh = getObChild(ob_curve, 'Mesh')
- if not ob_mesh:
- # New object
- mesh = bpy.data.meshes.new('tree_' + ob_curve.name)
- ob_mesh = newObChild(ob_curve, mesh)
- # do subsurf later
-
- else:
- # Existing object
- mesh = ob_mesh.getData(mesh=1)
- ob_mesh.setMatrix(Matrix())
-
- # Do we need a do_uv_blend_layer?
- if PREFS['do_material'].val and PREFS['material_stencil'].val and PREFS['material_texture'].val:
- do_uv_blend_layer = True
- else:
- do_uv_blend_layer = False
-
- mesh = t.toMesh(mesh,\
- do_uv = PREFS['do_uv'].val,\
- uv_image = image,\
- do_uv_keep_vproportion = PREFS['do_uv_keep_vproportion'].val,\
- do_uv_vnormalize = PREFS['do_uv_vnormalize'].val,\
- do_uv_uscale = PREFS['do_uv_uscale'].val,\
- uv_x_scale = PREFS['uv_x_scale'].val,\
- uv_y_scale = PREFS['uv_y_scale'].val,\
- do_uv_blend_layer = do_uv_blend_layer,\
- do_cap_ends = PREFS['do_cap_ends'].val
- )
-
- if PREFS['do_leaf'].val:
- ob_leaf_dupliface = getObChild(ob_mesh, 'Mesh')
- if not ob_leaf_dupliface: # New object
- mesh_leaf = bpy.data.meshes.new('leaf_' + ob_curve.name)
- ob_leaf_dupliface = newObChild(ob_mesh, mesh_leaf)
- else:
- mesh_leaf = ob_leaf_dupliface.getData(mesh=1)
- ob_leaf_dupliface.setMatrix(Matrix())
-
- leaf_object = getObFromName(PREFS['leaf_object'].val)
-
- mesh_leaf = t.toLeafMesh(mesh_leaf,\
- leaf_branch_limit = PREFS['leaf_branch_limit'].val,\
- leaf_branch_limit_rand = PREFS['leaf_branch_limit_rand'].val,\
- leaf_size = PREFS['leaf_size'].val,\
- leaf_size_rand = PREFS['leaf_size_rand'].val,\
- leaf_branch_density = PREFS['leaf_branch_density'].val,\
- leaf_branch_pitch_angle = PREFS['leaf_branch_pitch_angle'].val,\
- leaf_branch_pitch_rand = PREFS['leaf_branch_pitch_rand'].val,\
- leaf_branch_roll_rand = PREFS['leaf_branch_roll_rand'].val,\
- leaf_branch_angle = PREFS['leaf_branch_angle'].val,\
- leaf_rand_seed = PREFS['leaf_rand_seed'].val,\
- leaf_object = leaf_object,\
- )
-
- if leaf_object:
- ob_leaf_dupliface.enableDupFaces = True
- ob_leaf_dupliface.enableDupFacesScale = True
- ob_leaf_dupliface.makeParent([leaf_object], 1)
- else:
- ob_leaf_dupliface.enableDupFaces = False
-
- mesh.calcNormals()
-
- if PREFS['do_material'].val:
-
- materials = mesh.materials
- if PREFS['material_use_existing'].val and materials:
- t.material = materials[0]
- else:
- t.material = bpy.data.materials.new(ob_curve.name)
- mesh.materials = [t.material]
-
- if PREFS['material_texture'].val:
-
- # Set up the base image texture
- t.texBase = bpy.data.textures.new('base_' + ob_curve.name)
- t.material.setTexture(0, t.texBase, Blender.Texture.TexCo.UV, Blender.Texture.MapTo.COL)
- t.texBase.type = Blender.Texture.Types.IMAGE
- if image:
- t.texBase.image = image
- t.texBaseMTex = t.material.getTextures()[0]
- t.texBaseMTex.uvlayer = 'base'
-
- if PREFS['material_stencil'].val:
- # Set up the blend texture
- t.texBlend = bpy.data.textures.new('blend_' + ob_curve.name)
- t.material.setTexture(1, t.texBlend, Blender.Texture.TexCo.UV, 0) # map to None
- t.texBlend.type = Blender.Texture.Types.BLEND
- t.texBlend.flags |= Blender.Texture.Flags.FLIPBLEND
- t.texBlendMTex = t.material.getTextures()[1]
- t.texBlendMTex.stencil = True
- t.texBlendMTex.uvlayer = 'blend'
-
-
- # Now make the texture for the stencil to blend, can reuse texBase here, jus tdifferent settings for the mtex
- t.material.setTexture(2, t.texBase, Blender.Texture.TexCo.UV, Blender.Texture.MapTo.COL)
- t.texJoinMTex = t.material.getTextures()[2]
- t.texJoinMTex.uvlayer = 'join'
-
- # Add a UV layer for blending
-
-
-
-
- time6 = Blender.sys.time() # time print
- print '%.4f sec' % (time6-time5)
-
- # Do armature stuff....
- if PREFS['do_armature'].val:
-
- print '\tbuilding armature & animation...',
-
- ob_arm = getObChild(ob_curve, 'Armature')
- if ob_arm:
- armature = ob_arm.data
- ob_arm.setMatrix(Matrix())
- else:
- armature = bpy.data.armatures.new()
- ob_arm = newObChild(ob_curve, armature)
-
- t.toArmature(ob_arm, armature)
-
- # Add the modifier.
- if not hasModifier(Blender.Modifier.Types.ARMATURE):
- mod = ob_mesh.modifiers.append(Blender.Modifier.Types.ARMATURE)
-
- # TODO - assigne object anyway, even if an existing modifier exists.
- mod[Blender.Modifier.Settings.OBJECT] = ob_arm
-
- if PREFS['do_anim'].val:
- try:
- tex = bpy.data.textures[PREFS['anim_tex'].val]
- except:
- tex = None
- Blender.Draw.PupMenu('error no texture, cannot animate bones')
-
- if tex:
- t.toAction(ob_arm, tex,\
- anim_speed = PREFS['anim_speed'].val,\
- anim_magnitude = PREFS['anim_magnitude'].val,\
- anim_speed_size_scale= PREFS['anim_speed_size_scale'].val,\
- anim_offset_scale=PREFS['anim_offset_scale'].val
- )
-
- time7 = Blender.sys.time() # time print
- print '%.4f sec\n' % (time7-time6)
- else:
- time7 = Blender.sys.time() # time print
-
- print 'done in %.4f sec' % (time7 - time1)
-
- # Add subsurf last it needed. so armature skinning is done first.
- # Do subsurf?
- if PREFS['do_subsurf'].val:
- if not hasModifier(Blender.Modifier.Types.SUBSURF):
- mod = ob_mesh.modifiers.append(Blender.Modifier.Types.SUBSURF)
-
- #ob_mesh.makeDisplayList()
- #mesh.update()
- bpy.data.scenes.active.update()
-
-def do_pref_read(e=0,v=0, quiet=False):
- '''
- We dont care about e and v values, only there because its a callback
- '''
- sce = bpy.data.scenes.active
- ob = sce.objects.active
-
- if not ob:
- if not quiet:
- Blender.Draw.PupMenu('No active curve object')
- return
-
- if ob.type != 'Curve':
- ob = ob.parent
-
- if ob == None or ob.type != 'Curve':
- if not quiet:
- Blender.Draw.PupMenu('No active curve object')
- return
-
- if not IDProp2Prefs(ob.properties, PREFS):
- if not quiet:
- Blender.Draw.PupMenu('Curve object has no settings stored on it')
- return
-
- Blender.Draw.Redraw()
-
-def do_pref_write(e,v):
-
- objects = getContextCurveObjects()
- if not objects:
- Blender.Draw.PupMenu('No curve objects selected')
- return
-
- for ob in objects:
- Prefs2IDProp(ob.properties, PREFS)
-
-def do_pref_clear(e,v):
- objects = getContextCurveObjects()
- if not objects:
- Blender.Draw.PupMenu('No curve objects selected')
- return
-
- for ob in objects:
- try: del ob.properties[ID_SLOT_NAME]
- except: pass
-
-def do_tex_check(e,v):
- if not v: return
- try:
- bpy.data.textures[v]
- except:
- PREFS['anim_tex'].val = ''
- Draw.PupMenu('Texture dosnt exist!')
- Draw.Redraw()
-
-def do_ob_check(e,v):
- if not v: return
- try:
- bpy.data.objects[v]
- except:
- # PREFS['twig_ob_bounds'].val = ''
- Draw.PupMenu('Object dosnt exist!')
- Draw.Redraw()
-
-def do_group_check(e,v):
- if not v: return
- try:
- bpy.data.groups[v]
- except:
- # PREFS['leaf_object'].val = ''
- Draw.PupMenu('dosnt exist!')
- Draw.Redraw()
-
-# Button callbacks
-def do_active_image(e,v):
- img = bpy.data.images.active
- if img:
- PREFS['image_main'].val = img.name
- else:
- PREFS['image_main'].val = ''
-
-# Button callbacks
-def do_tree_generate__real():
- sce = bpy.data.scenes.active
- objects = getContextCurveObjects()
-
- if not objects:
- Draw.PupMenu('Select one or more curve objects or a mesh/armature types with curve parents')
-
- is_editmode = Blender.Window.EditMode()
- if is_editmode:
- Blender.Window.EditMode(0, '', 0)
- Blender.Window.WaitCursor(1)
-
- for ob in objects:
- buildTree(ob, len(objects)==1)
-
- if is_editmode:
- Blender.Window.EditMode(1, '', 0)
-
- Blender.Window.RedrawAll()
-
- Blender.Window.WaitCursor(0)
-
-
-# Profile
-# Had to do this to get it to work in ubuntu "sudo aptitude install python-profiler"
-'''
-import hotshot
-import profile
-from hotshot import stats
-'''
-def do_tree_generate(e,v):
-
- do_tree_generate__real()
- '''
- prof = hotshot.Profile("hotshot_edi_stats")
- prof.runcall(do_tree_generate__real)
- prof.close()
- s = stats.load("hotshot_edi_stats")
- s.sort_stats("time").print_stats()
- '''
- if GLOBALS['non_bez_error']:
- Blender.Draw.PupMenu('Error%t|Nurbs and Poly curve types cant be used!')
- GLOBALS['non_bez_error'] = 0
-
-def do_tree_help(e,v):
- url = 'http://wiki.blender.org/index.php/Scripts/Manual/Wizards/TreeFromCurves'
- print 'Trying to open web browser with documentation at this address...'
- print '\t' + url
-
- try:
- import webbrowser
- webbrowser.open(url)
- except:
- print '...could not open a browser window.'
-
-
-def evt(e,val):
- pass
-
-def bevt(e):
-
- if e==EVENT_NONE:
- return
-
- if e == EVENT_UPDATE or e == EVENT_UPDATE_AND_UI:
- if GLOBAL_PREFS['realtime_update'].val:
- do_tree_generate(0,0) # values dont matter
-
- if e == EVENT_REDRAW or e == EVENT_UPDATE_AND_UI:
- Draw.Redraw()
- if e == EVENT_EXIT:
- Draw.Exit()
- pass
-
-def gui():
- MARGIN = 4
- rect = BPyWindow.spaceRect()
- but_width = int((rect[2]-MARGIN*2)/4.0) # 72
- # Clamp
- if but_width>100: but_width = 100
- but_height = 17
-
- x=MARGIN
- y=rect[3]-but_height-MARGIN
- xtmp = x
-
- Blender.Draw.BeginAlign()
- PREFS['do_twigs_fill'] = Draw.Toggle('Fill Twigs',EVENT_UPDATE_AND_UI, xtmp, y, but_width*2, but_height, PREFS['do_twigs_fill'].val, 'Generate child branches based existing branches'); xtmp += but_width*2;
- if PREFS['do_twigs_fill'].val:
-
- PREFS['twig_fill_levels'] = Draw.Number('Generations', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_fill_levels'].val, 1, 32, 'How many generations to make for filled twigs'); xtmp += but_width*2;
- y-=but_height
- xtmp = x
-
- # ---------- ---------- ---------- ----------
- # WARNING USED IN 2 PLACES!! - see below
- PREFS['twig_ob_bounds'] = Draw.String('OB Bound: ', EVENT_UPDATE_AND_UI, xtmp, y, but_width*2, but_height, PREFS['twig_ob_bounds'].val, 64, 'Only grow twigs inside this mesh object', do_ob_check); xtmp += but_width*2;
- PREFS['twig_fill_rand_scale'] = Draw.Number('Randomize Scale', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_fill_rand_scale'].val, 0.0, 1.0, 'Randomize twig scale from the bounding mesh'); xtmp += but_width*2;
-
- y-=but_height
- xtmp = x
-
- PREFS['twig_fill_radius_min'] = Draw.Number('Min Radius', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_fill_radius_min'].val, 0.0, 1.0, 'Radius at endpoints of all twigs'); xtmp += but_width*2;
- PREFS['twig_fill_radius_factor'] = Draw.Number('Inherit Scale', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_fill_radius_factor'].val, 0.0, 1.0, 'What attaching to branches, scale the radius by this value for filled twigs, 0.0 for fixed width twigs.'); xtmp += but_width*2;
-
- y-=but_height
- xtmp = x
-
- #PREFS['twig_fill_shape_type'] = Draw.Number('Shape Type', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_fill_shape_type'].val, 0.0, 1.0, 'Shape used for the fork'); xtmp += but_width*2;
- PREFS['twig_fill_shape_type'] = Draw.Menu('Join Type%t|Even%x0|Smooth One Child%x1|Smooth Both Children%x2',EVENT_UPDATE_AND_UI, xtmp, y, but_width*2, but_height, PREFS['twig_fill_shape_type'].val, 'Select the wat twigs '); xtmp += but_width*2;
- PREFS['twig_fill_fork_angle_max'] = Draw.Number('Shape Max Ang', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_fill_fork_angle_max'].val, 0.0, 180.0, 'Maximum fork angle'); xtmp += but_width*2;
-
- y-=but_height
- xtmp = x
-
- PREFS['twig_fill_shape_rand'] = Draw.Number('Shape Rand', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_fill_shape_rand'].val, 0.0, 1.0, 'Randomize the shape of forks'); xtmp += but_width*2;
- PREFS['twig_fill_shape_power'] = Draw.Number('Shape Strength', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_fill_shape_power'].val, 0.0, 1.0, 'Strength of curves'); xtmp += but_width*2;
-
- Blender.Draw.EndAlign()
-
- y-=but_height+MARGIN
- xtmp = x
- # ---------- ---------- ---------- ----------
-
-
-
- # ---------- ---------- ---------- ----------
- Blender.Draw.BeginAlign()
- PREFS['do_twigs'] = Draw.Toggle('Grow Twigs',EVENT_UPDATE_AND_UI, xtmp, y, but_width*2, but_height, PREFS['do_twigs'].val, 'Generate child branches based existing branches'); xtmp += but_width*2;
- if PREFS['do_twigs'].val:
-
- PREFS['twig_ratio'] = Draw.Number('Twig Multiply', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_ratio'].val, 0.01, 500.0, 'How many twigs to generate per branch'); xtmp += but_width*2;
- y-=but_height
- xtmp = x
-
- # ---------- ---------- ---------- ----------
- PREFS['twig_select_mode'] = Draw.Menu('Branch Selection Method%t|From Short%x0|From Long%x1|From Straight%x2|From Bent%x3|',EVENT_UPDATE_AND_UI, xtmp, y, but_width*2, but_height, PREFS['twig_select_mode'].val, 'Select branches to use as twigs based on this attribute'); xtmp += but_width*2;
- PREFS['twig_select_factor'] = Draw.Number('From Factor', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_select_factor'].val, 0.0, 16, 'Select branches, lower value is more strict and will give you less variation'); xtmp += but_width*2;
- y-=but_height
- xtmp = x
-
- # ---------- ---------- ---------- ----------
- PREFS['twig_recursive'] = Draw.Toggle('Recursive Twigs',EVENT_UPDATE_AND_UI, xtmp, y, but_width*2, but_height, PREFS['twig_recursive'].val, 'Recursively add twigs into eachother'); xtmp += but_width*2;
- PREFS['twig_recursive_limit'] = Draw.Number('Generations', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_recursive_limit'].val, 0.0, 16, 'Number of generations allowed, 0 is inf'); xtmp += but_width*2;
- y-=but_height
- xtmp = x
-
- # ---------- ---------- ---------- ----------
-
- PREFS['twig_scale'] = Draw.Number('Twig Scale', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_scale'].val, 0.01, 10.0, 'Scale down twigs in relation to their parents each generation'); xtmp += but_width*2;
- PREFS['twig_scale_width'] = Draw.Number('Twig Scale Width', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_scale_width'].val, 0.01, 20.0, 'Scale the twig length only (not thickness)'); xtmp += but_width*2;
- y-=but_height
- xtmp = x
-
- # ---------- ---------- ---------- ----------
-
- PREFS['twig_random_orientation'] = Draw.Number('Rand Orientation', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_random_orientation'].val, 0.0, 360.0, 'Random rotation around the parent'); xtmp += but_width*2;
- PREFS['twig_random_angle'] = Draw.Number('Rand Angle', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_random_angle'].val, 0.0, 360.0, 'Random rotation to the parent joint'); xtmp += but_width*2;
- y-=but_height
- xtmp = x
-
- # ---------- ---------- ---------- ----------
-
- PREFS['twig_placement_maxradius'] = Draw.Number('Place Max Radius', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_placement_maxradius'].val, 0.0, 50.0, 'Only place twigs on branches below this radius'); xtmp += but_width*2;
- PREFS['twig_placement_maxtwig'] = Draw.Number('Place Max Count', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_placement_maxtwig'].val, 0.0, 50.0, 'Limit twig placement to this many per branch'); xtmp += but_width*2;
-
- y-=but_height
- xtmp = x
- # ---------- ---------- ---------- ----------
-
- PREFS['twig_follow_parent'] = Draw.Number('ParFollow', EVENT_UPDATE, xtmp, y, but_width, but_height, PREFS['twig_follow_parent'].val, 0.0, 10.0, 'Follow the parent branch'); xtmp += but_width;
- PREFS['twig_follow_x'] = Draw.Number('Grav X', EVENT_UPDATE, xtmp, y, but_width, but_height, PREFS['twig_follow_x'].val, -10.0, 10.0, 'Twigs gravitate on the X axis'); xtmp += but_width;
- PREFS['twig_follow_y'] = Draw.Number('Grav Y', EVENT_UPDATE, xtmp, y, but_width, but_height, PREFS['twig_follow_y'].val, -10.0, 10.0, 'Twigs gravitate on the Y axis'); xtmp += but_width;
- PREFS['twig_follow_z'] = Draw.Number('Grav Z', EVENT_UPDATE, xtmp, y, but_width, but_height, PREFS['twig_follow_z'].val, -10.0, 10.0, 'Twigs gravitate on the Z axis'); xtmp += but_width;
-
- y-=but_height
- xtmp = x
-
- # ---------- ---------- ---------- ----------
- # WARNING USED IN 2 PLACES!!
- PREFS['twig_ob_bounds'] = Draw.String('OB Bound: ', EVENT_UPDATE_AND_UI, xtmp, y, but_width*2, but_height, PREFS['twig_ob_bounds'].val, 64, 'Only grow twigs inside this mesh object', do_ob_check); xtmp += but_width*2;
-
- if PREFS['twig_ob_bounds_prune'].val:
- but_width_tmp = but_width
- else:
- but_width_tmp = but_width*2
-
- PREFS['twig_ob_bounds_prune'] = Draw.Toggle('Prune',EVENT_UPDATE_AND_UI, xtmp, y, but_width_tmp, but_height, PREFS['twig_ob_bounds_prune'].val, 'Prune twigs to the mesh object bounds'); xtmp += but_width_tmp;
- if PREFS['twig_ob_bounds_prune'].val:
- PREFS['twig_ob_bounds_prune_taper'] = Draw.Number('Taper', EVENT_UPDATE_AND_UI, xtmp, y, but_width, but_height, PREFS['twig_ob_bounds_prune_taper'].val, 0.0, 1.0, 'Taper pruned branches to a point'); xtmp += but_width;
-
- #PREFS['image_main'] = Draw.String('IM: ', EVENT_UPDATE, xtmp, y, but_width*3, but_height, PREFS['image_main'].val, 64, 'Image to apply to faces'); xtmp += but_width*3;
- #Draw.PushButton('Use Active', EVENT_UPDATE, xtmp, y, but_width, but_height, 'Get the image from the active image window', do_active_image); xtmp += but_width;
- Blender.Draw.EndAlign()
-
- y-=but_height+MARGIN
- xtmp = x
- # ---------- ---------- ---------- ----------
-
-
-
- Blender.Draw.BeginAlign()
- PREFS['do_leaf'] = Draw.Toggle('Generate Leaves',EVENT_UPDATE_AND_UI, xtmp, y, but_width*2, but_height, PREFS['do_leaf'].val, 'Generate leaves using duplifaces'); xtmp += but_width*2;
-
- if PREFS['do_leaf'].val:
-
- PREFS['leaf_object'] = Draw.String('OB: ', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['leaf_object'].val, 64, 'Use this object as a leaf', do_ob_check); xtmp += but_width*2;
- # ---------- ---------- ---------- ----------
- y-=but_height
- xtmp = x
-
- PREFS['leaf_size'] = Draw.Number('Size', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['leaf_size'].val, 0.001, 10.0, 'size of the leaf'); xtmp += but_width*2;
- PREFS['leaf_size_rand'] = Draw.Number('Randsize', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['leaf_size_rand'].val, 0.0, 1.0, 'randomize the leaf size'); xtmp += but_width*2;
-
- # ---------- ---------- ---------- ----------
- y-=but_height
- xtmp = x
-
- # Dont use yet
- PREFS['leaf_branch_limit'] = Draw.Number('Branch Limit', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['leaf_branch_limit'].val, 0.0, 1.0, 'Maximum thichness where a branch can bare leaves, higher value to place leaves on bigger branches'); xtmp += but_width*2;
- PREFS['leaf_branch_limit_rand'] = Draw.Number('Limit Random', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['leaf_branch_limit_rand'].val, 0.0, 1.0, 'Randomize the allowed minimum branch width to place leaves'); xtmp += but_width*2;
-
- # ---------- ---------- ---------- ----------
- y-=but_height
- xtmp = x
-
- PREFS['leaf_branch_density'] = Draw.Number('Density', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['leaf_branch_density'].val, 0.0, 1.0, 'Chance each segment has of baring a leaf, use a high value for more leaves'); xtmp += but_width*2;
- PREFS['leaf_branch_angle'] = Draw.Number('Angle From Branch', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['leaf_branch_angle'].val, 0.0, 90.0, 'angle the leaf is from the branch direction'); xtmp += but_width*2;
-
- # ---------- ---------- ---------- ----------
- y-=but_height
- xtmp = x
-
- PREFS['leaf_rand_seed'] = Draw.Number('Random Seed', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['leaf_rand_seed'].val, 0.0, 10000.0, 'Set the seed for leaf random values'); xtmp += but_width*2;
- PREFS['leaf_branch_pitch_angle'] = Draw.Number('Pitch Angle', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['leaf_branch_pitch_angle'].val, -180, 180.0, 'Change the pitch rotation of leaves, negative angle to point down'); xtmp += but_width*2;
-
- # ---------- ---------- ---------- ----------
- y-=but_height
- xtmp = x
-
- PREFS['leaf_branch_pitch_rand'] = Draw.Number('Random Pitch', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['leaf_branch_pitch_rand'].val, 0.0, 1.0, 'Randomize the leaf rotation (up-down/pitch)'); xtmp += but_width*2;
- PREFS['leaf_branch_roll_rand'] = Draw.Number('Random Roll', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['leaf_branch_roll_rand'].val, 0.0, 1.0, 'Randomize the leaf rotation (roll/tilt/yaw)'); xtmp += but_width*2;
-
-
- Blender.Draw.EndAlign()
-
- y-=but_height+MARGIN
- xtmp = x
- # ---------- ---------- ---------- ----------
-
-
- Blender.Draw.BeginAlign()
- if PREFS['do_uv'].val == 0: but_width_tmp = but_width*2
- else: but_width_tmp = but_width*4
- PREFS['do_uv'] = Draw.Toggle('Generate UVs',EVENT_UPDATE_AND_UI, xtmp, y, but_width_tmp, but_height, PREFS['do_uv'].val, 'Calculate UVs coords'); xtmp += but_width_tmp;
-
- if PREFS['do_uv'].val:
- # ---------- ---------- ---------- ----------
- y-=but_height
- xtmp = x
-
- PREFS['do_uv_uscale'] = Draw.Toggle('U-Scale', EVENT_UPDATE, xtmp, y, but_width, but_height, PREFS['do_uv_uscale'].val, 'Scale the width according to the face size (will NOT tile)'); xtmp += but_width;
- PREFS['do_uv_keep_vproportion'] = Draw.Toggle('V-Aspect', EVENT_UPDATE, xtmp, y, but_width, but_height, PREFS['do_uv_keep_vproportion'].val, 'Correct the UV aspect with the branch width'); xtmp += but_width;
- PREFS['do_uv_vnormalize'] = Draw.Toggle('V-Normaize', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['do_uv_vnormalize'].val, 'Scale the UVs to fit onto the image verticaly'); xtmp += but_width*2;
-
- y-=but_height
- xtmp = x
- # ---------- ---------- ---------- ----------
-
- PREFS['uv_x_scale'] = Draw.Number('Scale U', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['uv_x_scale'].val, 0.01, 10.0, 'Edge loop spacing around branch join, lower value for less webed joins'); xtmp += but_width*2;
- PREFS['uv_y_scale'] = Draw.Number('Scale V', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['uv_y_scale'].val, 0.01, 10.0, 'Edge loop spacing around branch join, lower value for less webed joins'); xtmp += but_width*2;
-
- y-=but_height
- xtmp = x
- # ---------- ---------- ---------- ----------
-
- PREFS['image_main'] = Draw.String('IM: ', EVENT_UPDATE, xtmp, y, but_width*3, but_height, PREFS['image_main'].val, 64, 'Image to apply to faces'); xtmp += but_width*3;
- Draw.PushButton('Use Active', EVENT_UPDATE, xtmp, y, but_width, but_height, 'Get the image from the active image window', do_active_image); xtmp += but_width;
- Blender.Draw.EndAlign()
-
- y-=but_height+MARGIN
- xtmp = x
- # ---------- ---------- ---------- ----------
-
- Blender.Draw.BeginAlign()
- PREFS['do_material'] = Draw.Toggle('Generate Material',EVENT_UPDATE_AND_UI, xtmp, y, but_width*2, but_height, PREFS['do_material'].val, 'Create material and textures (for seamless joints)'); xtmp += but_width*2;
-
- if PREFS['do_material'].val:
- PREFS['material_use_existing'] = Draw.Toggle('ReUse Existing',EVENT_UPDATE_AND_UI, xtmp, y, but_width*2, but_height, PREFS['material_use_existing'].val, 'Modify the textures of the existing material'); xtmp += but_width*2;
-
- # ---------- ---------- ---------- ----------
- y-=but_height
- xtmp = x
-
- PREFS['material_texture'] = Draw.Toggle('Texture', EVENT_UPDATE_AND_UI, xtmp, y, but_width*2, but_height, PREFS['material_texture'].val, 'Create an image texture for this material to use'); xtmp += but_width*2;
- PREFS['material_stencil'] = Draw.Toggle('Blend Joints', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['material_stencil'].val, 'Use a 2 more texture and UV layers to blend the seams between joints'); xtmp += but_width*2;
- Blender.Draw.EndAlign()
-
- y-=but_height+MARGIN
- xtmp = x
- # ---------- ---------- ---------- ----------
-
- Blender.Draw.BeginAlign()
- if PREFS['do_armature'].val == 0:
- but_width_tmp = but_width*2
- else:
- but_width_tmp = but_width*4
-
- Blender.Draw.BeginAlign()
- PREFS['do_armature'] = Draw.Toggle('Generate Motion', EVENT_UPDATE_AND_UI, xtmp, y, but_width_tmp, but_height, PREFS['do_armature'].val, 'Generate Armatuer animation and apply to branches'); xtmp += but_width_tmp;
-
- # ---------- ---------- ---------- ----------
- if PREFS['do_armature'].val:
- y-=but_height
- xtmp = x
-
- PREFS['do_anim'] = Draw.Toggle('Texture Anim', EVENT_UPDATE_AND_UI, xtmp, y, but_width*2, but_height, PREFS['do_anim'].val, 'Use a texture to animate the bones'); xtmp += but_width*2;
-
- if PREFS['do_anim'].val:
-
- PREFS['anim_tex'] = Draw.String('TEX: ', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['anim_tex'].val, 64, 'Texture to use for the IPO Driver animation', do_tex_check); xtmp += but_width*2;
- y-=but_height
- xtmp = x
- # ---------- ---------- ---------- ----------
-
- PREFS['anim_speed'] = Draw.Number('Speed', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['anim_speed'].val, 0.001, 10.0, 'Animate the movement faster with a higher value'); xtmp += but_width*2;
- PREFS['anim_magnitude'] = Draw.Number('Magnitude', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['anim_magnitude'].val, 0.001, 10.0, 'Animate with more motion with a higher value'); xtmp += but_width*2;
- y-=but_height
- xtmp = x
- # ---------- ---------- ---------- ----------
-
- PREFS['anim_offset_scale'] = Draw.Number('Unique Offset Scale', EVENT_UPDATE, xtmp, y, but_width*4, but_height, PREFS['anim_offset_scale'].val, 0.001, 10.0, 'Use the curve object location as input into the texture so trees have more unique motion, a low value is less unique'); xtmp += but_width*4;
- y-=but_height
- xtmp = x
-
- # ---------- ---------- ---------- ----------
-
- PREFS['anim_speed_size_scale'] = Draw.Toggle('Branch Size Scales Speed', EVENT_UPDATE, xtmp, y, but_width*4, but_height, PREFS['anim_speed_size_scale'].val, 'Use the branch size as a factor when calculating speed'); xtmp += but_width*4;
-
- Blender.Draw.EndAlign()
-
- y-=but_height+MARGIN
- xtmp = x
-
-
-
-
- # ---------- ---------- ---------- ----------
-
- Blender.Draw.BeginAlign()
- PREFS['do_variation'] = Draw.Toggle('Generate Variation', EVENT_UPDATE_AND_UI, xtmp, y, but_width*2, but_height, PREFS['do_variation'].val, 'Create a variant by moving the branches'); xtmp += but_width*2;
-
- # ---------- ---------- ---------- ----------
- if PREFS['do_variation'].val:
- PREFS['variation_seed'] = Draw.Number('Rand Seed', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['variation_seed'].val, 1, 100000, 'Change this to get a different variation'); xtmp += but_width*2;
- y-=but_height
- xtmp = x
-
-
- PREFS['variation_orientation'] = Draw.Number('Orientation', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['variation_orientation'].val, 0, 1.0, 'Randomize rotation of the branch around its parent'); xtmp += but_width*2;
- PREFS['variation_scale'] = Draw.Number('Scale', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['variation_scale'].val, 0.0, 1.0, 'Randomize the scale of branches'); xtmp += but_width*2;
-
- Blender.Draw.EndAlign()
-
- y-=but_height+(MARGIN*2)
- xtmp = x
-
-
-
- # ---------- ---------- ---------- ----------
- Blender.Draw.BeginAlign()
- PREFS['seg_density'] = Draw.Number('Segment Spacing',EVENT_UPDATE, xtmp, y, but_width*4, but_height, PREFS['seg_density'].val, 0.05, 10.0, 'Scale the limit points collapse, that are closer then the branch width'); xtmp += but_width*4;
-
- y-=but_height
- xtmp = x
-
- # ---------- ---------- ---------- ----------
- PREFS['seg_density_angle'] = Draw.Number('Angle Spacing', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['seg_density_angle'].val, 0.0, 180.0, 'Segments above this angle will not collapse (lower value for more detail)'); xtmp += but_width*2;
- PREFS['seg_density_radius'] = Draw.Number('Radius Spacing', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['seg_density_radius'].val, 0.0, 1.0, 'Segments above this difference in radius will not collapse (lower value for more detail)'); xtmp += but_width*2;
-
- y-=but_height
- xtmp = x
- # ---------- ---------- ---------- ----------
-
- PREFS['seg_joint_compression'] = Draw.Number('Joint Width', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['seg_joint_compression'].val, 0.1, 2.0, 'Edge loop spacing around branch join, lower value for less webed joins'); xtmp += but_width*2;
- PREFS['seg_joint_smooth'] = Draw.Number('Joint Smooth', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['seg_joint_smooth'].val, 0.0, 1.0, 'Edge loop spacing around branch join, lower value for less webed joins'); xtmp += but_width*2;
-
- y-=but_height
- xtmp = x
- # ---------- ---------- ---------- ----------
-
- PREFS['connect_sloppy'] = Draw.Number('Connect Limit',EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['connect_sloppy'].val, 0.1, 3.0, 'Strictness when connecting branches'); xtmp += but_width*2;
- PREFS['connect_base_trim'] = Draw.Number('Joint Bevel', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['connect_base_trim'].val, 0.0, 2.0, 'low value for a tight join, hi for a smoother bevel'); xtmp += but_width*2;
- Blender.Draw.EndAlign()
- y-=but_height+MARGIN
- xtmp = x
-
- # ---------- ---------- ---------- ----------
- Blender.Draw.BeginAlign()
- PREFS['do_cap_ends'] = Draw.Toggle('Cap Ends',EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['do_cap_ends'].val, 'Add faces onto branch endpoints'); xtmp += but_width*2;
- PREFS['do_subsurf'] = Draw.Toggle('SubSurf',EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['do_subsurf'].val, 'Enable subsurf for newly generated objects'); xtmp += but_width*2;
- Blender.Draw.EndAlign()
- y-=but_height+MARGIN
- xtmp = x
-
-
- # ---------- ---------- ---------- ----------
- Blender.Draw.BeginAlign()
- Draw.PushButton('Read Active Prefs', EVENT_REDRAW, xtmp, y, but_width*2, but_height, 'Read the ID Property settings from the active curve object', do_pref_read); xtmp += but_width*2;
- Draw.PushButton('Write Prefs to Sel', EVENT_NONE, xtmp, y, but_width*2, but_height, 'Save these settings in the ID Properties of all selected curve objects', do_pref_write); xtmp += but_width*2;
-
- y-=but_height
- xtmp = x
-
- # ---------- ---------- ---------- ----------
- Draw.PushButton('Clear Prefs from Sel', EVENT_NONE, xtmp, y, but_width*4, but_height, 'Remove settings from the selected curve aaobjects', do_pref_clear); xtmp += but_width*4;
- Blender.Draw.EndAlign()
-
- y-=but_height+MARGIN
- xtmp = x
- # ---------- ---------- ---------- ----------
-
- Blender.Draw.BeginAlign()
- Draw.PushButton('Exit', EVENT_EXIT, xtmp, y, but_width, but_height, ''); xtmp += but_width;
- Draw.PushButton('Help', EVENT_NONE, xtmp, y, but_width, but_height, '', do_tree_help); xtmp += but_width;
- Draw.PushButton('Generate from selection', EVENT_REDRAW, xtmp, y, but_width*2, but_height, 'Generate mesh', do_tree_generate); xtmp += but_width*3;
- Blender.Draw.EndAlign()
- y-=but_height+MARGIN
- xtmp = x
- # ---------- ---------- ---------- ----------
-
- GLOBAL_PREFS['realtime_update'] = Draw.Toggle('Automatic Update', EVENT_UPDATE, xtmp, y, but_width*4, but_height, GLOBAL_PREFS['realtime_update'].val, 'Update automatically when settings change'); xtmp += but_width*4;
-
-
-
-if __name__ == '__main__':
- # Read the active objects prefs on load. if they exist
- do_pref_read(quiet=True)
-
- Draw.Register(gui, evt, bevt)
diff --git a/source/Makefile b/source/Makefile
index 5ebff3bbbf5..cd8bf0e7cb4 100644
--- a/source/Makefile
+++ b/source/Makefile
@@ -148,9 +148,11 @@ ifneq ($(NAN_NO_KETSJI),true)
COMLIB += $(OCGDIR)/gameengine/ketsji/KXNetwork/$(DEBUG_DIR)libKXNetwork.a
COMLIB += $(OCGDIR)/gameengine/Network/$(DEBUG_DIR)libNetwork.a
COMLIB += $(OCGDIR)/gameengine/Network/LoopBackNetwork/$(DEBUG_DIR)libLoopBackNetwork.a
- COMLIB += $(NAN_BULLET2)/lib/libbullet2.a
endif
+# Required by cloth, not gameengine only anymore
+COMLIB += $(NAN_BULLET2)/lib/$(DEBUG_DIR)libbullet2.a
+
COMLIB += $(NAN_GUARDEDALLOC)/lib/libguardedalloc.a
COMLIB += $(NAN_MEMUTIL)/lib/libmemutil.a
COMLIB += $(NAN_BMFONT)/lib/$(DEBUG_DIR)libbmfont.a
diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h
index af920e9762d..6575b8b873b 100644
--- a/source/blender/blenkernel/BKE_cloth.h
+++ b/source/blender/blenkernel/BKE_cloth.h
@@ -24,14 +24,14 @@
*
* The Original Code is: all of this file.
*
- * Contributor(s): none yet.
+ * Contributor(s): Daniel Genrich.
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef BKE_CLOTH_H
#define BKE_CLOTH_H
-#include "float.h"
+#include <float.h>
#include "BLI_linklist.h"
#include "BKE_customdata.h"
@@ -49,6 +49,9 @@
#include "BKE_collision.h"
+#include "RE_raytrace.h"
+
+
struct Object;
struct MFace;
@@ -102,7 +105,8 @@ typedef struct Cloth
unsigned char old_solver_type; /* unused, only 1 solver here */
unsigned char pad2;
short pad3;
- struct BVH *tree; /* collision tree for this cloth object */
+ struct BVHTree *bvhtree; /* collision tree for this cloth object */
+ struct BVHTree *bvhselftree; /* collision tree for this cloth object */
struct MFace *mfaces;
struct Implicit_Data *implicit; /* our implicit solver connects to this pointer */
struct Implicit_Data *implicitEM; /* our implicit solver connects to this pointer */
@@ -171,17 +175,10 @@ ClothSpring;
/* These are the bits used in SimSettings.flags. */
typedef enum
{
- //CLOTH_SIMSETTINGS_FLAG_RESET = ( 1 << 1 ), // The CM object requires a reinitializaiton.
CLOTH_SIMSETTINGS_FLAG_COLLOBJ = ( 1 << 2 ),// object is only collision object, no cloth simulation is done
CLOTH_SIMSETTINGS_FLAG_GOAL = ( 1 << 3 ), // we have goals enabled
CLOTH_SIMSETTINGS_FLAG_TEARING = ( 1 << 4 ),// true if tearing is enabled
- //CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT = ( 1 << 5 ), // true if tearing is enabled
- //CLOTH_SIMSETTINGS_FLAG_EDITMODE = ( 1 << 6 ), // are we in editmode? -several things disabled
- //CLOTH_SIMSETTINGS_FLAG_CCACHE_FFREE = ( 1 << 7 ), /* force cache freeing */
CLOTH_SIMSETTINGS_FLAG_SCALING = ( 1 << 8 ), /* is advanced scaling active? */
- //CLOTH_SIMSETTINGS_FLAG_LOADED = ( 1 << 9 ), /* did we just got load? */
- //CLOTH_SIMSETTINGS_FLAG_AUTOPROTECT = ( 1 << 10 ), /* is autoprotect enabled? */
- //CLOTH_SIMSETTINGS_FLAG_CCACHE_OUTDATED = (1 << 11), /* while protected, did cache get outdated? */
CLOTH_SIMSETTINGS_FLAG_CCACHE_EDIT = (1 << 12) /* edit cache in editmode */
} CLOTH_SIMSETTINGS_FLAGS;
@@ -208,6 +205,7 @@ typedef enum
CLOTH_SPRING_FLAG_NEEDED = ( 1 << 2 ), // springs has values to be applied
} CLOTH_SPRINGS_FLAGS;
+
/////////////////////////////////////////////////
// collision.c
////////////////////////////////////////////////
@@ -246,7 +244,8 @@ DerivedMesh *clothModifier_do ( ClothModifierData *clmd,Object *ob, DerivedMesh
void cloth_update_normals ( ClothVertex *verts, int nVerts, MFace *face, int totface );
// needed for collision.c
-void bvh_update_from_cloth ( ClothModifierData *clmd, int moving );
+void bvhtree_update_from_cloth ( ClothModifierData *clmd, int moving );
+void bvhselftree_update_from_cloth ( ClothModifierData *clmd, int moving );
// needed for editmesh.c
void cloth_write_cache ( Object *ob, ClothModifierData *clmd, float framenr );
diff --git a/source/blender/blenkernel/BKE_collision.h b/source/blender/blenkernel/BKE_collision.h
index 7328f9108e3..f0298950f8b 100644
--- a/source/blender/blenkernel/BKE_collision.h
+++ b/source/blender/blenkernel/BKE_collision.h
@@ -32,7 +32,7 @@
#define BKE_COLLISIONS_H
#include <math.h>
-#include "float.h"
+#include <float.h>
#include <stdlib.h>
#include <string.h>
@@ -47,6 +47,8 @@
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
+#include "BLI_kdopbvh.h"
+
struct Object;
struct Cloth;
struct MFace;
@@ -102,10 +104,16 @@ BVH;
typedef void ( *CM_COLLISION_RESPONSE ) ( ModifierData *md1, ModifierData *md2, CollisionTree *tree1, CollisionTree *tree2 );
// needed for collision.c
-int bvh_traverse ( ModifierData * md1, ModifierData * md2, CollisionTree * tree1, CollisionTree * tree2, float step, CM_COLLISION_RESPONSE collision_response, int selfcollision);
+int bvh_traverse ( ModifierData * md1, ModifierData * md2, CollisionTree * tree1, CollisionTree * tree2, float step, CM_COLLISION_RESPONSE collision_response, int selfcollision );
////////////////////////////////////////
+/* COLLISION FLAGS */
+typedef enum
+{
+ COLLISION_IN_FUTURE = ( 1 << 1 ),
+} COLLISION_FLAGS;
+
////////////////////////////////////////
// used for collisions in kdop.c and also collision.c
@@ -119,10 +127,10 @@ typedef struct CollPair
float normal[3];
float vector[3]; // unnormalized collision vector: p2-p1
float pa[3], pb[3]; // collision point p1 on face1, p2 on face2
- int lastsign; // indicates if the distance sign has changed, unused itm
+ int flag;
float time; // collision time, from 0 up to 1
- unsigned int ap1, ap2, ap3, bp1, bp2, bp3;
- unsigned int pointsb[4];
+ int ap1, ap2, ap3, bp1, bp2, bp3;
+ int pointsb[4];
}
CollPair;
@@ -160,8 +168,9 @@ FaceCollPair;
// NOTICE: mvert-routines for building + update the BVH are the most native ones
// builds bounding volume hierarchy
-void bvh_build (BVH *bvh);
-BVH *bvh_build_from_mvert (MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon);
+void bvh_build ( BVH *bvh );
+BVH *bvh_build_from_mvert ( MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon );
+BVHTree *bvhtree_build_from_mvert ( MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon );
// frees the same
void bvh_free ( BVH * bvh );
@@ -169,20 +178,21 @@ void bvh_free ( BVH * bvh );
// checks two bounding volume hierarchies for potential collisions and returns some list with those
-// update bounding volumes, needs updated positions in bvh->current_xold (static)
+// update bounding volumes, needs updated positions in bvh->current_xold (static)
// and also bvh->current_x if moving==1
-void bvh_update_from_mvert(BVH * bvh, MVert *x, unsigned int numverts, MVert *xnew, int moving);
-void bvh_update(BVH * bvh, int moving);
+void bvh_update_from_mvert ( BVH * bvh, MVert *x, unsigned int numverts, MVert *xnew, int moving );
+void bvh_update ( BVH * bvh, int moving );
+void bvhtree_update_from_mvert ( BVHTree * bvhtree, MFace *faces, int numfaces, MVert *x, MVert *xnew, int numverts, int moving );
LinkNode *BLI_linklist_append_fast ( LinkNode **listp, void *ptr );
// move Collision modifier object inter-frame with step = [0,1]
// defined in collisions.c
-void collision_move_object(CollisionModifierData *collmd, float step, float prevstep);
+void collision_move_object ( CollisionModifierData *collmd, float step, float prevstep );
// interface for collision functions
-void collisions_compute_barycentric (float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3);
-void interpolateOnTriangle(float to[3], float v1[3], float v2[3], float v3[3], double w1, double w2, double w3);
+void collisions_compute_barycentric ( float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3 );
+void interpolateOnTriangle ( float to[3], float v1[3], float v2[3], float v3[3], double w1, double w2, double w3 );
/////////////////////////////////////////////////
diff --git a/source/blender/blenkernel/BKE_collisions.h b/source/blender/blenkernel/BKE_collisions.h
new file mode 100644
index 00000000000..f0f6212d3f5
--- /dev/null
+++ b/source/blender/blenkernel/BKE_collisions.h
@@ -0,0 +1,130 @@
+/**
+ * BKE_cloth.h
+ *
+ * $Id: BKE_cloth.h,v 1.1 2007/08/01 02:07:27 daniel Exp $
+ *
+ * ***** 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) Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_COLLISIONS_H
+#define BKE_COLLISIONS_H
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* types */
+#include "BLI_linklist.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_object.h"
+
+#include "DNA_modifier_types.h"
+
+// used in kdop.c and collision.c
+typedef struct CollisionTree
+{
+ struct CollisionTree *nodes[4]; // 4 children --> quad-tree
+ struct CollisionTree *parent;
+ struct CollisionTree *nextLeaf;
+ struct CollisionTree *prevLeaf;
+ float bv[26]; // Bounding volume of all nodes / we have 7 axes on a 14-DOP
+ int point_index[4]; // supports up to 4 points in a leaf
+ int count_nodes; // how many nodes are used
+ int traversed; // how many nodes already traversed until this level?
+ int isleaf;
+}
+CollisionTree;
+
+typedef struct CollisionTree TreeNode;
+
+typedef struct BVH
+{
+ unsigned int numfaces;
+ unsigned int numverts;
+ MVert *xnew; // position of verts at time n
+ MVert *x; // position of verts at time n-1
+ MFace *mfaces; // just a pointer to the original datastructure
+ struct LinkNode *tree;
+ CollisionTree *root; // TODO: saving the root --> is this really needed? YES!
+ CollisionTree *leaf_tree; /* Tail of the leaf linked list. */
+ CollisionTree *leaf_root; /* Head of the leaf linked list. */
+ float epsilon; /* epslion is used for inflation of the k-dop */
+ int flags; /* bvhFlags */
+
+}
+BVH;
+
+
+/* used for collisions in kdop.c and also collision.c*/
+typedef struct CollisionPair
+{
+ int point_indexA[4], point_indexB[4];
+ float vector[3];
+ float normal[3]; // has to be calculated from vector
+ float distance;
+ float pa[3], pb[3];
+}
+CollisionPair;
+
+
+/////////////////////////////////////////////////
+// forward declarations
+/////////////////////////////////////////////////
+
+// NOTICE: mvert-routines for building + update the BVH are the most native ones
+
+// builds bounding volume hierarchy
+BVH *bvh_build_from_mvert (MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon);
+BVH *bvh_build_from_float3 (MFace *mfaces, unsigned int numfaces, float (*x)[3], unsigned int numverts, float epsilon);
+BVH *bvh_build_from_float4 (MFace *mfaces, unsigned int numfaces, float (*x)[4], unsigned int numverts, float epsilon);
+
+// frees the same
+void bvh_free ( BVH *bvh );
+
+// checks two bounding volume hierarchies for potential collisions and returns some list with those
+int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode **collision_list);
+
+// update bounding volumes, needs updated positions in bvh->x
+void bvh_update_from_mvert(BVH * bvh, MVert *x, unsigned int numverts, MVert *xnew, int moving);
+void bvh_update_from_float3(BVH * bvh, float (*x)[3], unsigned int numverts, float (*xnew)[3], int moving);
+void bvh_update_from_float4(BVH * bvh, float (*x)[4], unsigned int numverts, float (*xnew)[4], int moving);
+
+LinkNode *BLI_linklist_append_fast (LinkNode **listp, void *ptr);
+
+// move Collision modifier object inter-frame with step = [0,1]
+// defined in collisions.c
+void collision_move_object(CollisionModifierData *collmd, float step, float prevstep);
+
+// interface for collision functions
+void collisions_compute_barycentric (float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3);
+void interpolateOnTriangle(float to[3], float v1[3], float v2[3], float v3[3], double w1, double w2, double w3);
+
+/////////////////////////////////////////////////
+
+#endif
+
diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h
index 3763a659f2f..15816699285 100644
--- a/source/blender/blenkernel/BKE_effect.h
+++ b/source/blender/blenkernel/BKE_effect.h
@@ -31,6 +31,7 @@
#ifndef BKE_EFFECT_H
#define BKE_EFFECT_H
+#include "DNA_effect_types.h"
#include "DNA_object_types.h"
struct Effect;
diff --git a/source/blender/blenkernel/BKE_sph.h b/source/blender/blenkernel/BKE_sph.h
new file mode 100644
index 00000000000..9fa42f5acb2
--- /dev/null
+++ b/source/blender/blenkernel/BKE_sph.h
@@ -0,0 +1,69 @@
+/**
+ * ***** 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) Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Daniel Genrich.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_SPH_H
+#define BKE_SPH_H
+
+
+#include "BKE_DerivedMesh.h"
+#include "BKE_utildefines.h"
+
+#include "BLI_linklist.h"
+
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+
+void sph_init(SphModifierData *sphmd);
+void sph_free_modifier (SphModifierData *sphmd);
+DerivedMesh *sphModifier_do(SphModifierData *sphmd,Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc);
+int sph_init_all (SphModifierData *sphmd, DerivedMesh *dm, Object *ob);
+
+
+/* SIMULATION FLAGS: goal flags,.. */
+/* These are the bits used in SimSettings.flags. */
+// first 16 (short) flags are used for fluid type identification
+typedef enum
+{
+ SPH_SIMSETTINGS_FLAG_FLUID = ( 1 << 0 ), // Fluid object?
+ SPH_SIMSETTINGS_FLAG_OBSTACLE = ( 1 << 1 ), // Obstacle?
+ SPH_SIMSETTINGS_FLAG_DOMAIN = ( 1 << 2 ), // Fluid domain
+
+ SPH_SIMSETTINGS_FLAG_GHOSTS = ( 1 << 16 ), // use ghost particles?
+ SPH_SIMSETTINGS_FLAG_OFFLINE = ( 1 << 17 ), // do offline simulation?
+ SPH_SIMSETTINGS_FLAG_MULTIRES = ( 1 << 18 ), // use multires?
+ SPH_SIMSETTINGS_FLAG_VORTICITY = ( 1 << 19 ), // use vorticity enhancement?
+ SPH_SIMSETTINGS_FLAG_BAKING = ( 1 << 20 ), // is domain baking?
+ SPH_SIMSETTINGS_FLAG_INIT = ( 1 << 21 ), // inited?
+} SPH_SIMSETTINGS_FLAGS;
+
+
+#endif //BKE_SPH_H
+
+
+
diff --git a/source/blender/blenkernel/CCGSubSurf.h b/source/blender/blenkernel/CCGSubSurf.h
new file mode 100644
index 00000000000..a8269b7ada0
--- /dev/null
+++ b/source/blender/blenkernel/CCGSubSurf.h
@@ -0,0 +1,152 @@
+/* $Id: CCGSubSurf.h 12931 2007-12-17 18:20:48Z theeth $ */
+
+typedef void* CCGMeshHDL;
+typedef void* CCGVertHDL;
+typedef void* CCGEdgeHDL;
+typedef void* CCGFaceHDL;
+
+typedef struct _CCGVert CCGVert;
+typedef struct _CCGEdge CCGEdge;
+typedef struct _CCGFace CCGFace;
+
+typedef struct _CCGMeshIFC CCGMeshIFC;
+struct _CCGMeshIFC {
+ int vertUserSize, edgeUserSize, faceUserSize;
+
+ int vertDataSize;
+};
+
+/***/
+
+typedef void* CCGAllocatorHDL;
+
+typedef struct _CCGAllocatorIFC CCGAllocatorIFC;
+struct _CCGAllocatorIFC {
+ void* (*alloc) (CCGAllocatorHDL a, int numBytes);
+ void* (*realloc) (CCGAllocatorHDL a, void *ptr, int newSize, int oldSize);
+ void (*free) (CCGAllocatorHDL a, void *ptr);
+ void (*release) (CCGAllocatorHDL a);
+};
+
+/***/
+
+typedef enum {
+ eCCGError_None = 0,
+
+ eCCGError_InvalidSyncState,
+ eCCGError_InvalidValue,
+} CCGError;
+
+/***/
+
+typedef struct _CCGSubSurf CCGSubSurf;
+
+CCGSubSurf* ccgSubSurf_new (CCGMeshIFC *ifc, int subdivisionLevels, CCGAllocatorIFC *allocatorIFC, CCGAllocatorHDL allocator);
+void ccgSubSurf_free (CCGSubSurf *ss);
+
+CCGError ccgSubSurf_sync (CCGSubSurf *ss);
+
+CCGError ccgSubSurf_initFullSync (CCGSubSurf *ss);
+CCGError ccgSubSurf_initPartialSync (CCGSubSurf *ss);
+
+CCGError ccgSubSurf_syncVert (CCGSubSurf *ss, CCGVertHDL vHDL, void *vertData, int seam, CCGVert **v_r);
+CCGError ccgSubSurf_syncEdge (CCGSubSurf *ss, CCGEdgeHDL eHDL, CCGVertHDL e_vHDL0, CCGVertHDL e_vHDL1, float crease, CCGEdge **e_r);
+CCGError ccgSubSurf_syncFace (CCGSubSurf *ss, CCGFaceHDL fHDL, int numVerts, CCGVertHDL *vHDLs, CCGFace **f_r);
+
+CCGError ccgSubSurf_syncVertDel (CCGSubSurf *ss, CCGVertHDL vHDL);
+CCGError ccgSubSurf_syncEdgeDel (CCGSubSurf *ss, CCGEdgeHDL eHDL);
+CCGError ccgSubSurf_syncFaceDel (CCGSubSurf *ss, CCGFaceHDL fHDL);
+
+CCGError ccgSubSurf_processSync (CCGSubSurf *ss);
+
+CCGError ccgSubSurf_setSubdivisionLevels (CCGSubSurf *ss, int subdivisionLevels);
+
+CCGError ccgSubSurf_setAllowEdgeCreation (CCGSubSurf *ss, int allowEdgeCreation, float defaultCreaseValue, void *defaultUserData);
+void ccgSubSurf_getAllowEdgeCreation (CCGSubSurf *ss, int *allowEdgeCreation_r, float *defaultCreaseValue_r, void *defaultUserData_r);
+
+void ccgSubSurf_getUseAgeCounts (CCGSubSurf *ss, int *useAgeCounts_r, int *vertUserOffset_r, int *edgeUserOffset_r, int *faceUserOffset_r);
+CCGError ccgSubSurf_setUseAgeCounts (CCGSubSurf *ss, int useAgeCounts, int vertUserOffset, int edgeUserOffset, int faceUserOffset);
+
+CCGError ccgSubSurf_setCalcVertexNormals (CCGSubSurf *ss, int useVertNormals, int normalDataOffset);
+
+/***/
+
+int ccgSubSurf_getNumVerts (CCGSubSurf *ss);
+int ccgSubSurf_getNumEdges (CCGSubSurf *ss);
+int ccgSubSurf_getNumFaces (CCGSubSurf *ss);
+
+int ccgSubSurf_getSubdivisionLevels (CCGSubSurf *ss);
+int ccgSubSurf_getEdgeSize (CCGSubSurf *ss);
+int ccgSubSurf_getEdgeLevelSize (CCGSubSurf *ss, int level);
+int ccgSubSurf_getGridSize (CCGSubSurf *ss);
+int ccgSubSurf_getGridLevelSize (CCGSubSurf *ss, int level);
+
+CCGVert* ccgSubSurf_getVert (CCGSubSurf *ss, CCGVertHDL v);
+CCGVertHDL ccgSubSurf_getVertVertHandle (CCGSubSurf *ss, CCGVert *v);
+int ccgSubSurf_getVertNumFaces (CCGSubSurf *ss, CCGVert *v);
+CCGFace* ccgSubSurf_getVertFace (CCGSubSurf *ss, CCGVert *v, int index);
+int ccgSubSurf_getVertNumEdges (CCGSubSurf *ss, CCGVert *v);
+CCGEdge* ccgSubSurf_getVertEdge (CCGSubSurf *ss, CCGVert *v, int index);
+
+int ccgSubSurf_getVertAge (CCGSubSurf *ss, CCGVert *v);
+void* ccgSubSurf_getVertUserData (CCGSubSurf *ss, CCGVert *v);
+void* ccgSubSurf_getVertData (CCGSubSurf *ss, CCGVert *v);
+void* ccgSubSurf_getVertLevelData (CCGSubSurf *ss, CCGVert *v, int level);
+
+CCGEdge* ccgSubSurf_getEdge (CCGSubSurf *ss, CCGEdgeHDL e);
+CCGEdgeHDL ccgSubSurf_getEdgeEdgeHandle (CCGSubSurf *ss, CCGEdge *e);
+int ccgSubSurf_getEdgeNumFaces (CCGSubSurf *ss, CCGEdge *e);
+CCGFace* ccgSubSurf_getEdgeFace (CCGSubSurf *ss, CCGEdge *e, int index);
+CCGVert* ccgSubSurf_getEdgeVert0 (CCGSubSurf *ss, CCGEdge *e);
+CCGVert* ccgSubSurf_getEdgeVert1 (CCGSubSurf *ss, CCGEdge *e);
+float ccgSubSurf_getEdgeCrease (CCGSubSurf *ss, CCGEdge *e);
+
+int ccgSubSurf_getEdgeAge (CCGSubSurf *ss, CCGEdge *e);
+void* ccgSubSurf_getEdgeUserData (CCGSubSurf *ss, CCGEdge *e);
+void* ccgSubSurf_getEdgeDataArray (CCGSubSurf *ss, CCGEdge *e);
+void* ccgSubSurf_getEdgeData (CCGSubSurf *ss, CCGEdge *e, int x);
+void* ccgSubSurf_getEdgeLevelData (CCGSubSurf *ss, CCGEdge *e, int x, int level);
+
+CCGFace* ccgSubSurf_getFace (CCGSubSurf *ss, CCGFaceHDL f);
+CCGFaceHDL ccgSubSurf_getFaceFaceHandle (CCGSubSurf *ss, CCGFace *f);
+int ccgSubSurf_getFaceNumVerts (CCGSubSurf *ss, CCGFace *f);
+CCGVert* ccgSubSurf_getFaceVert (CCGSubSurf *ss, CCGFace *f, int index);
+CCGEdge* ccgSubSurf_getFaceEdge (CCGSubSurf *ss, CCGFace *f, int index);
+int ccgSubSurf_getFaceEdgeIndex (CCGSubSurf *ss, CCGFace *f, CCGEdge *e);
+
+int ccgSubSurf_getFaceAge (CCGSubSurf *ss, CCGFace *f);
+void* ccgSubSurf_getFaceUserData (CCGSubSurf *ss, CCGFace *f);
+void* ccgSubSurf_getFaceCenterData (CCGSubSurf *ss, CCGFace *f);
+void* ccgSubSurf_getFaceGridEdgeDataArray (CCGSubSurf *ss, CCGFace *f, int gridIndex);
+void* ccgSubSurf_getFaceGridEdgeData (CCGSubSurf *ss, CCGFace *f, int gridIndex, int x);
+void* ccgSubSurf_getFaceGridDataArray (CCGSubSurf *ss, CCGFace *f, int gridIndex);
+void* ccgSubSurf_getFaceGridData (CCGSubSurf *ss, CCGFace *f, int gridIndex, int x, int y);
+
+int ccgSubSurf_getNumFinalVerts (CCGSubSurf *ss);
+int ccgSubSurf_getNumFinalEdges (CCGSubSurf *ss);
+int ccgSubSurf_getNumFinalFaces (CCGSubSurf *ss);
+
+/***/
+
+typedef struct _CCGVertIterator CCGVertIterator;
+typedef struct _CCGEdgeIterator CCGEdgeIterator;
+typedef struct _CCGFaceIterator CCGFaceIterator;
+
+CCGVertIterator* ccgSubSurf_getVertIterator (CCGSubSurf *ss);
+CCGEdgeIterator* ccgSubSurf_getEdgeIterator (CCGSubSurf *ss);
+CCGFaceIterator* ccgSubSurf_getFaceIterator (CCGSubSurf *ss);
+
+CCGVert* ccgVertIterator_getCurrent (CCGVertIterator *vi);
+int ccgVertIterator_isStopped (CCGVertIterator *vi);
+void ccgVertIterator_next (CCGVertIterator *vi);
+void ccgVertIterator_free (CCGVertIterator *vi);
+
+CCGEdge* ccgEdgeIterator_getCurrent (CCGEdgeIterator *ei);
+int ccgEdgeIterator_isStopped (CCGEdgeIterator *ei);
+void ccgEdgeIterator_next (CCGEdgeIterator *ei);
+void ccgEdgeIterator_free (CCGEdgeIterator *ei);
+
+CCGFace* ccgFaceIterator_getCurrent (CCGFaceIterator *fi);
+int ccgFaceIterator_isStopped (CCGFaceIterator *fi);
+void ccgFaceIterator_next (CCGFaceIterator *fi);
+void ccgFaceIterator_free (CCGFaceIterator *fi);
diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript
index 1bb98239a68..4f77e4f42a7 100644
--- a/source/blender/blenkernel/SConscript
+++ b/source/blender/blenkernel/SConscript
@@ -10,6 +10,7 @@ incs += ' #/intern/iksolver/extern ../blenloader ../quicktime'
incs += ' #/extern/bullet2/src'
incs += ' #/intern/bmfont'
incs += ' #/intern/opennl/extern'
+incs += ' #/intern/sph/extern'
incs += ' ' + env['BF_PYTHON_INC']
incs += ' ' + env['BF_OPENGL_INC']
diff --git a/source/blender/blenkernel/bmesh_private.h b/source/blender/blenkernel/bmesh_private.h
new file mode 100644
index 00000000000..ad90398bf66
--- /dev/null
+++ b/source/blender/blenkernel/bmesh_private.h
@@ -0,0 +1,71 @@
+/**
+ * BME_private.h jan 2007
+ *
+ * low level, 'private' function prototypes for bmesh kernel.
+ *
+ * $Id: BKE_bmesh.h,v 1.00 2007/01/17 17:42:01 Briggs Exp $
+ *
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2004 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Geoffrey Bantle.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BMESH_PRIVATE
+#define BMESH_PRIVATE
+
+#include "BKE_bmesh.h"
+
+/*ALLOCATION/DEALLOCATION*/
+struct BME_Vert *BME_addvertlist(struct BME_Mesh *bm, struct BME_Vert *example);
+struct BME_Edge *BME_addedgelist(struct BME_Mesh *bm, struct BME_Vert *v1, struct BME_Vert *v2, struct BME_Edge *example);
+struct BME_Poly *BME_addpolylist(struct BME_Mesh *bm, struct BME_Poly *example);
+struct BME_Loop *BME_create_loop(struct BME_Mesh *bm, struct BME_Vert *v, struct BME_Edge *e, struct BME_Poly *f, struct BME_Loop *example);
+
+void BME_free_vert(struct BME_Mesh *bm, struct BME_Vert *v);
+void BME_free_edge(struct BME_Mesh *bm, struct BME_Edge *e);
+void BME_free_poly(struct BME_Mesh *bm, struct BME_Poly *f);
+void BME_free_loop(struct BME_Mesh *bm, struct BME_Loop *l);
+void BME_delete_loop(struct BME_Mesh *bm, struct BME_Loop *l);
+
+/*DOUBLE CIRCULAR LINKED LIST FUNCTIONS*/
+void BME_cycle_append(void *h, void *nt);
+int BME_cycle_remove(void *h, void *remn);
+int BME_cycle_validate(int len, void *h);
+/*DISK CYCLE MANAGMENT*/
+int BME_disk_append_edge(struct BME_Edge *e, struct BME_Vert *v);
+void BME_disk_remove_edge(struct BME_Edge *e, struct BME_Vert *v);
+/*RADIAL CYCLE MANAGMENT*/
+void BME_radial_append(struct BME_Edge *e, struct BME_Loop *l);
+void BME_radial_remove_loop(struct BME_Loop *l, struct BME_Edge *e);
+
+/*MISC FUNCTIONS*/
+int BME_edge_swapverts(struct BME_Edge *e, struct BME_Vert *orig, struct BME_Vert *new); /*relink edge*/
+int BME_disk_hasedge(struct BME_Vert *v, struct BME_Edge *e);
+
+/*Error reporting. Shouldnt be called by tools ever.*/
+void BME_error(void);
+#endif
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index 09a51bb37a4..4fb8eeda78d 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -45,6 +45,10 @@
#include "BKE_pointcache.h"
+#include "BLI_kdopbvh.h"
+
+#include <time.h>
+
#ifdef _WIN32
void tstart ( void )
{}
@@ -76,6 +80,40 @@ double tval()
}
#endif
+
+/* Util macros */
+#define TO_STR(a) #a
+#define JOIN(a,b) a##b
+
+/* Benchmark macros */
+#if 1
+
+#define BENCH(a) \
+ do { \
+ clock_t _clock_init = clock(); \
+ (a); \
+ printf("%s: %fms\n", #a, (float)(clock()-_clock_init)*1000/CLOCKS_PER_SEC); \
+} while(0)
+
+#define BENCH_VAR(name) clock_t JOIN(_bench_step,name) = 0, JOIN(_bench_total,name) = 0
+#define BENCH_BEGIN(name) JOIN(_bench_step, name) = clock()
+#define BENCH_END(name) JOIN(_bench_total,name) += clock() - JOIN(_bench_step,name)
+#define BENCH_RESET(name) JOIN(_bench_total, name) = 0
+#define BENCH_REPORT(name) printf("%s: %fms\n", TO_STR(name), JOIN(_bench_total,name)*1000.0f/CLOCKS_PER_SEC)
+
+#else
+
+#define BENCH(a) (a)
+#define BENCH_VAR(name)
+#define BENCH_BEGIN(name)
+#define BENCH_END(name)
+#define BENCH_RESET(name)
+#define BENCH_REPORT(name)
+
+#endif
+
+
+
/* Our available solvers. */
// 255 is the magic reserved number, so NEVER try to put 255 solvers in here!
// 254 = MAX!
@@ -151,13 +189,14 @@ void cloth_init ( ClothModifierData *clmd )
clmd->sim_parms->goalfrict = 0.0f;
}
-
-BVH *bvh_build_from_cloth (ClothModifierData *clmd, float epsilon)
+BVHTree *bvhselftree_build_from_cloth (ClothModifierData *clmd, float epsilon)
{
- unsigned int i = 0;
- BVH *bvh=NULL;
+ int i;
+ BVHTree *bvhtree;
Cloth *cloth = clmd->clothObject;
- ClothVertex *verts = NULL;
+ ClothVertex *verts;
+ MFace *mfaces;
+ float co[12];
if(!clmd)
return NULL;
@@ -168,69 +207,171 @@ BVH *bvh_build_from_cloth (ClothModifierData *clmd, float epsilon)
return NULL;
verts = cloth->verts;
+ mfaces = cloth->mfaces;
// in the moment, return zero if no faces there
- if(!cloth->numfaces)
+ if(!cloth->numverts)
return NULL;
- bvh = MEM_callocN(sizeof(BVH), "BVH");
- if (bvh == NULL)
+ // create quadtree with k=26
+ bvhtree = BLI_bvhtree_new(cloth->numverts, epsilon, 4, 6);
+
+ // fill tree
+ for(i = 0; i < cloth->numverts; i++, verts++)
{
- printf("bvh: Out of memory.\n");
- return NULL;
+ VECCOPY(&co[0*3], verts->xold);
+
+ BLI_bvhtree_insert(bvhtree, i, co, 1);
}
- // springs = cloth->springs;
- // numsprings = cloth->numsprings;
+ // balance tree
+ BLI_bvhtree_balance(bvhtree);
+
+ return bvhtree;
+}
+
+BVHTree *bvhtree_build_from_cloth (ClothModifierData *clmd, float epsilon)
+{
+ int i;
+ BVHTree *bvhtree;
+ Cloth *cloth = clmd->clothObject;
+ ClothVertex *verts;
+ MFace *mfaces;
+ float co[12];
- bvh->epsilon = epsilon;
- bvh->numfaces = cloth->numfaces;
- bvh->mfaces = cloth->mfaces;
+ if(!clmd)
+ return NULL;
- bvh->numverts = cloth->numverts;
+ cloth = clmd->clothObject;
+
+ if(!cloth)
+ return NULL;
- bvh->current_x = MEM_callocN ( sizeof ( MVert ) * bvh->numverts, "bvh->current_x" );
+ verts = cloth->verts;
+ mfaces = cloth->mfaces;
- if (bvh->current_x == NULL)
- {
- printf("bvh: Out of memory.\n");
- MEM_freeN(bvh);
+ // in the moment, return zero if no faces there
+ if(!cloth->numfaces)
return NULL;
- }
- for(i = 0; i < bvh->numverts; i++)
+ // create quadtree with k=26
+ bvhtree = BLI_bvhtree_new(cloth->numfaces, epsilon, 4, 26);
+
+ // fill tree
+ for(i = 0; i < cloth->numfaces; i++, mfaces++)
{
- VECCOPY(bvh->current_x[i].co, verts[i].tx);
+ VECCOPY(&co[0*3], verts[mfaces->v1].xold);
+ VECCOPY(&co[1*3], verts[mfaces->v2].xold);
+ VECCOPY(&co[2*3], verts[mfaces->v3].xold);
+
+ if(mfaces->v4)
+ VECCOPY(&co[3*3], verts[mfaces->v4].xold);
+
+ BLI_bvhtree_insert(bvhtree, i, co, (mfaces->v4 ? 4 : 3));
}
- bvh_build (bvh);
+ // balance tree
+ BLI_bvhtree_balance(bvhtree);
- return bvh;
+ return bvhtree;
}
-void bvh_update_from_cloth(ClothModifierData *clmd, int moving)
-{
+void bvhtree_update_from_cloth(ClothModifierData *clmd, int moving)
+{
unsigned int i = 0;
Cloth *cloth = clmd->clothObject;
- BVH *bvh = cloth->tree;
+ BVHTree *bvhtree = cloth->bvhtree;
ClothVertex *verts = cloth->verts;
+ MFace *mfaces;
+ float co[12], co_moving[12];
+ int ret = 0;
- if(!bvh)
+ if(!bvhtree)
return;
- if(cloth->numverts!=bvh->numverts)
- return;
+ mfaces = cloth->mfaces;
- if(cloth->verts)
+ // update vertex position in bvh tree
+ if(verts && mfaces)
{
- for(i = 0; i < bvh->numverts; i++)
+ for(i = 0; i < cloth->numfaces; i++, mfaces++)
{
- VECCOPY(bvh->current_x[i].co, verts[i].tx);
- VECCOPY(bvh->current_xold[i].co, verts[i].txold);
+ VECCOPY(&co[0*3], verts[mfaces->v1].txold);
+ VECCOPY(&co[1*3], verts[mfaces->v2].txold);
+ VECCOPY(&co[2*3], verts[mfaces->v3].txold);
+
+ if(mfaces->v4)
+ VECCOPY(&co[3*3], verts[mfaces->v4].txold);
+
+ // copy new locations into array
+ if(moving)
+ {
+ // update moving positions
+ VECCOPY(&co_moving[0*3], verts[mfaces->v1].tx);
+ VECCOPY(&co_moving[1*3], verts[mfaces->v2].tx);
+ VECCOPY(&co_moving[2*3], verts[mfaces->v3].tx);
+
+ if(mfaces->v4)
+ VECCOPY(&co_moving[3*3], verts[mfaces->v4].tx);
+
+ ret = BLI_bvhtree_update_node(bvhtree, i, co, co_moving, (mfaces->v4 ? 4 : 3));
+ }
+ else
+ {
+ ret = BLI_bvhtree_update_node(bvhtree, i, co, NULL, (mfaces->v4 ? 4 : 3));
+ }
+
+ // check if tree is already full
+ if(!ret)
+ break;
}
+
+ BLI_bvhtree_update_tree(bvhtree);
}
+}
+
+void bvhselftree_update_from_cloth(ClothModifierData *clmd, int moving)
+{
+ unsigned int i = 0;
+ Cloth *cloth = clmd->clothObject;
+ BVHTree *bvhtree = cloth->bvhselftree;
+ ClothVertex *verts = cloth->verts;
+ MFace *mfaces;
+ float co[12], co_moving[12];
+ int ret = 0;
- bvh_update(bvh, moving);
+ if(!bvhtree)
+ return;
+
+ mfaces = cloth->mfaces;
+
+ // update vertex position in bvh tree
+ if(verts && mfaces)
+ {
+ for(i = 0; i < cloth->numverts; i++, verts++)
+ {
+ VECCOPY(&co[0*3], verts->txold);
+
+ // copy new locations into array
+ if(moving)
+ {
+ // update moving positions
+ VECCOPY(&co_moving[0*3], verts->tx);
+
+ ret = BLI_bvhtree_update_node(bvhtree, i, co, co_moving, 1);
+ }
+ else
+ {
+ ret = BLI_bvhtree_update_node(bvhtree, i, co, NULL, 1);
+ }
+
+ // check if tree is already full
+ if(!ret)
+ break;
+ }
+
+ BLI_bvhtree_update_tree(bvhtree);
+ }
}
int modifiers_indexInObject(Object *ob, ModifierData *md_seek);
@@ -358,15 +499,15 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul
Mat4MulVecfl(ob->obmat, verts->xconst);
}
- tstart();
+ // tstart();
/* call the solver. */
if(solvers [clmd->sim_parms->solver_type].solver)
- ret = solvers[clmd->sim_parms->solver_type].solver(ob, framenr, clmd, effectors);
+ BENCH(ret = solvers[clmd->sim_parms->solver_type].solver(ob, framenr, clmd, effectors));
- tend();
+ // tend();
- /* printf ( "Cloth simulation time: %f\n", ( float ) tval() ); */
+ // printf ( "Cloth simulation time: %f\n", ( float ) tval() );
return ret;
}
@@ -541,8 +682,11 @@ void cloth_free_modifier ( Object *ob, ClothModifierData *clmd )
cloth->numsprings = 0;
// free BVH collision tree
- if ( cloth->tree )
- bvh_free ( ( BVH * ) cloth->tree );
+ if ( cloth->bvhtree )
+ BLI_bvhtree_free ( cloth->bvhtree );
+
+ if ( cloth->bvhselftree )
+ BLI_bvhtree_free ( cloth->bvhselftree );
// we save our faces for collision objects
if ( cloth->mfaces )
@@ -611,8 +755,11 @@ void cloth_free_modifier_extern ( ClothModifierData *clmd )
cloth->numsprings = 0;
// free BVH collision tree
- if ( cloth->tree )
- bvh_free ( ( BVH * ) cloth->tree );
+ if ( cloth->bvhtree )
+ BLI_bvhtree_free ( cloth->bvhtree );
+
+ if ( cloth->bvhselftree )
+ BLI_bvhtree_free ( cloth->bvhselftree );
// we save our faces for collision objects
if ( cloth->mfaces )
@@ -751,6 +898,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d
ClothVertex *verts = NULL;
float tnull[3] = {0,0,0};
Cloth *cloth = NULL;
+ float maxdist = 0;
// If we have a clothObject, free it.
if ( clmd->clothObject != NULL )
@@ -810,6 +958,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d
VECCOPY ( verts->xold, verts->x );
VECCOPY ( verts->xconst, verts->x );
VECCOPY ( verts->txold, verts->x );
+ VECCOPY ( verts->tx, verts->x );
VecMulf ( verts->v, 0.0f );
verts->impulse_count = 0;
@@ -819,8 +968,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d
// apply / set vertex groups
// has to be happen before springs are build!
cloth_apply_vgroup (clmd, dm);
-
-
+
if ( !cloth_build_springs ( clmd, dm ) )
{
cloth_free_modifier ( ob, clmd );
@@ -845,12 +993,18 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d
if(!first)
implicit_set_positions(clmd);
- clmd->clothObject->tree = bvh_build_from_cloth ( clmd, clmd->coll_parms->epsilon );
+ clmd->clothObject->bvhtree = bvhtree_build_from_cloth ( clmd, clmd->coll_parms->epsilon );
+
+ for(i = 0; i < dm->getNumVerts(dm); i++)
+ {
+ maxdist = MAX2(maxdist, clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len*2.0));
+ }
+
+ clmd->clothObject->bvhselftree = bvhselftree_build_from_cloth ( clmd, maxdist );
return 1;
}
-
static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm )
{
unsigned int numverts = dm->getNumVerts ( dm );
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
index e244ccca306..37784b43cf9 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -41,7 +41,6 @@
#include "BKE_global.h"
#include "BKE_mesh.h"
#include "BKE_object.h"
-#include "BKE_cloth.h"
#include "BKE_modifier.h"
#include "BKE_utildefines.h"
#include "BKE_DerivedMesh.h"
@@ -49,6 +48,38 @@
#include "Bullet-C-Api.h"
+#include "BLI_kdopbvh.h"
+#include "BKE_collision.h"
+
+#ifdef _WIN32
+static void start ( void )
+{}
+static void end ( void )
+{
+}
+static double val()
+{
+ return 0;
+}
+#else
+#include <sys/time.h>
+static void mystart ( struct timeval *start, struct timezone *z )
+{
+ gettimeofday ( start, z );
+}
+static void myend ( struct timeval *end, struct timezone *z )
+{
+ gettimeofday ( end,z );
+}
+static double myval ( struct timeval *start, struct timeval *end )
+{
+ double t1, t2;
+ t1 = ( double ) start->tv_sec + ( double ) start->tv_usec/ ( 1000*1000 );
+ t2 = ( double ) end->tv_sec + ( double ) end->tv_usec/ ( 1000*1000 );
+ return t2-t1;
+}
+#endif
+
/***********************************
Collision modifier code start
***********************************/
@@ -66,58 +97,80 @@ void collision_move_object ( CollisionModifierData *collmd, float step, float pr
VECADDS ( collmd->current_xnew[i].co, collmd->x[i].co, tv, step );
VECSUB ( collmd->current_v[i].co, collmd->current_xnew[i].co, collmd->current_x[i].co );
}
- bvh_update_from_mvert ( collmd->bvh, collmd->current_x, collmd->numverts, collmd->current_xnew, 1 );
+ bvhtree_update_from_mvert ( collmd->bvhtree, collmd->mfaces, collmd->numfaces, collmd->current_x, collmd->current_xnew, collmd->numverts, 1 );
}
-/* build bounding volume hierarchy from mverts (see kdop.c for whole BVH code) */
-BVH *bvh_build_from_mvert ( MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon )
+BVHTree *bvhtree_build_from_mvert ( MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon )
{
- BVH *bvh=NULL;
-
- bvh = MEM_callocN ( sizeof ( BVH ), "BVH" );
- if ( bvh == NULL )
- {
- printf ( "bvh: Out of memory.\n" );
- return NULL;
- }
-
- // in the moment, return zero if no faces there
- if ( !numfaces )
- return NULL;
+ BVHTree *tree;
+ float co[12];
+ int i;
+ MFace *tface = mfaces;
- bvh->epsilon = epsilon;
- bvh->numfaces = numfaces;
- bvh->mfaces = mfaces;
+ tree = BLI_bvhtree_new ( numfaces*2, epsilon, 4, 26 );
- // we have no faces, we save seperate points
- if ( !mfaces )
+ // fill tree
+ for ( i = 0; i < numfaces; i++, tface++ )
{
- bvh->numfaces = numverts;
- }
+ VECCOPY ( &co[0*3], x[tface->v1].co );
+ VECCOPY ( &co[1*3], x[tface->v2].co );
+ VECCOPY ( &co[2*3], x[tface->v3].co );
+ if ( tface->v4 )
+ VECCOPY ( &co[3*3], x[tface->v4].co );
- bvh->numverts = numverts;
- bvh->current_x = MEM_dupallocN ( x );
+ BLI_bvhtree_insert ( tree, i, co, ( mfaces->v4 ? 4 : 3 ) );
+ }
- bvh_build ( bvh );
+ // balance tree
+ BLI_bvhtree_balance ( tree );
- return bvh;
+ return tree;
}
-void bvh_update_from_mvert ( BVH * bvh, MVert *x, unsigned int numverts, MVert *xnew, int moving )
+void bvhtree_update_from_mvert ( BVHTree * bvhtree, MFace *faces, int numfaces, MVert *x, MVert *xnew, int numverts, int moving )
{
- if ( !bvh )
- return;
+ int i;
+ MFace *mfaces = faces;
+ float co[12], co_moving[12];
+ int ret = 0;
- if ( numverts!=bvh->numverts )
+ if ( !bvhtree )
return;
if ( x )
- memcpy ( bvh->current_xold, x, sizeof ( MVert ) * numverts );
+ {
+ for ( i = 0; i < numfaces; i++, mfaces++ )
+ {
+ VECCOPY ( &co[0*3], x[mfaces->v1].co );
+ VECCOPY ( &co[1*3], x[mfaces->v2].co );
+ VECCOPY ( &co[2*3], x[mfaces->v3].co );
+ if ( mfaces->v4 )
+ VECCOPY ( &co[3*3], x[mfaces->v4].co );
+
+ // copy new locations into array
+ if ( moving && xnew )
+ {
+ // update moving positions
+ VECCOPY ( &co_moving[0*3], xnew[mfaces->v1].co );
+ VECCOPY ( &co_moving[1*3], xnew[mfaces->v2].co );
+ VECCOPY ( &co_moving[2*3], xnew[mfaces->v3].co );
+ if ( mfaces->v4 )
+ VECCOPY ( &co_moving[3*3], xnew[mfaces->v4].co );
+
+ ret = BLI_bvhtree_update_node ( bvhtree, i, co, co_moving, ( mfaces->v4 ? 4 : 3 ) );
+ }
+ else
+ {
+ ret = BLI_bvhtree_update_node ( bvhtree, i, co, NULL, ( mfaces->v4 ? 4 : 3 ) );
+ }
- if ( xnew )
- memcpy ( bvh->current_x, xnew, sizeof ( MVert ) * numverts );
+ // check if tree is already full
+ if ( !ret )
+ break;
+ }
- bvh_update ( bvh, moving );
+ BLI_bvhtree_update_tree ( bvhtree );
+ }
}
/***********************************
@@ -125,47 +178,48 @@ Collision modifier code end
***********************************/
/**
- * gsl_poly_solve_cubic -
- *
- * copied from SOLVE_CUBIC.C --> GSL
- */
+* gsl_poly_solve_cubic -
+*
+* copied from SOLVE_CUBIC.C --> GSL
+*/
-/* DG: debug hint! don't forget that all functions were "fabs", "sinf", etc before */
-#define mySWAP(a,b) { float tmp = b ; b = a ; a = tmp ; }
+#define mySWAP(a,b) do { double tmp = b ; b = a ; a = tmp ; } while(0)
-int gsl_poly_solve_cubic ( float a, float b, float c, float *x0, float *x1, float *x2 )
+int
+gsl_poly_solve_cubic (double a, double b, double c,
+ double *x0, double *x1, double *x2)
{
- float q = ( a * a - 3 * b );
- float r = ( 2 * a * a * a - 9 * a * b + 27 * c );
+ double q = (a * a - 3 * b);
+ double r = (2 * a * a * a - 9 * a * b + 27 * c);
- float Q = q / 9;
- float R = r / 54;
+ double Q = q / 9;
+ double R = r / 54;
- float Q3 = Q * Q * Q;
- float R2 = R * R;
+ double Q3 = Q * Q * Q;
+ double R2 = R * R;
- float CR2 = 729 * r * r;
- float CQ3 = 2916 * q * q * q;
+ double CR2 = 729 * r * r;
+ double CQ3 = 2916 * q * q * q;
- if ( R == 0 && Q == 0 )
+ if (R == 0 && Q == 0)
{
*x0 = - a / 3 ;
*x1 = - a / 3 ;
*x2 = - a / 3 ;
return 3 ;
}
- else if ( CR2 == CQ3 )
+ else if (CR2 == CQ3)
{
/* this test is actually R2 == Q3, written in a form suitable
- for exact computation with integers */
+ for exact computation with integers */
- /* Due to finite precision some float roots may be missed, and
- considered to be a pair of complex roots z = x +/- epsilon i
- close to the real axis. */
+ /* Due to finite precision some double roots may be missed, and
+ considered to be a pair of complex roots z = x +/- epsilon i
+ close to the real axis. */
- float sqrtQ = sqrt ( Q );
+ double sqrtQ = sqrt (Q);
- if ( R > 0 )
+ if (R > 0)
{
*x0 = -2 * sqrtQ - a / 3;
*x1 = sqrtQ - a / 3;
@@ -179,72 +233,88 @@ int gsl_poly_solve_cubic ( float a, float b, float c, float *x0, float *x1, floa
}
return 3 ;
}
- else if ( CR2 < CQ3 ) /* equivalent to R2 < Q3 */
+ else if (CR2 < CQ3) /* equivalent to R2 < Q3 */
{
- float sqrtQ = sqrt ( Q );
- float sqrtQ3 = sqrtQ * sqrtQ * sqrtQ;
- float theta = acos ( R / sqrtQ3 );
- float norm = -2 * sqrtQ;
- *x0 = norm * cos ( theta / 3 ) - a / 3;
- *x1 = norm * cos ( ( theta + 2.0 * M_PI ) / 3 ) - a / 3;
- *x2 = norm * cos ( ( theta - 2.0 * M_PI ) / 3 ) - a / 3;
+ double sqrtQ = sqrt (Q);
+ double sqrtQ3 = sqrtQ * sqrtQ * sqrtQ;
+ double theta = acos (R / sqrtQ3);
+ double norm = -2 * sqrtQ;
+ *x0 = norm * cos (theta / 3) - a / 3;
+ *x1 = norm * cos ((theta + 2.0 * M_PI) / 3) - a / 3;
+ *x2 = norm * cos ((theta - 2.0 * M_PI) / 3) - a / 3;
/* Sort *x0, *x1, *x2 into increasing order */
- if ( *x0 > *x1 )
- mySWAP ( *x0, *x1 ) ;
+ if (*x0 > *x1)
+ mySWAP(*x0, *x1) ;
- if ( *x1 > *x2 )
+ if (*x1 > *x2)
{
- mySWAP ( *x1, *x2 ) ;
+ mySWAP(*x1, *x2) ;
- if ( *x0 > *x1 )
- mySWAP ( *x0, *x1 ) ;
+ if (*x0 > *x1)
+ mySWAP(*x0, *x1) ;
}
return 3;
}
else
{
- float sgnR = ( R >= 0 ? 1 : -1 );
- float A = -sgnR * pow ( ABS ( R ) + sqrt ( R2 - Q3 ), 1.0/3.0 );
- float B = Q / A ;
+ double sgnR = (R >= 0 ? 1 : -1);
+ double A = -sgnR * pow (fabs (R) + sqrt (R2 - Q3), 1.0/3.0);
+ double B = Q / A ;
*x0 = A + B - a / 3;
return 1;
}
}
+
/**
- * gsl_poly_solve_quadratic
- *
- * copied from GSL
- */
-int gsl_poly_solve_quadratic ( float a, float b, float c, float *x0, float *x1 )
+* gsl_poly_solve_quadratic
+*
+* copied from GSL
+*/
+int
+gsl_poly_solve_quadratic (double a, double b, double c,
+ double *x0, double *x1)
{
- float disc = b * b - 4 * a * c;
+ double disc = b * b - 4 * a * c;
- if ( disc > 0 )
+ if (a == 0) /* Handle linear case */
{
- if ( b == 0 )
+ if (b == 0)
{
- float r = ABS ( 0.5 * sqrt ( disc ) / a );
+ return 0;
+ }
+ else
+ {
+ *x0 = -c / b;
+ return 1;
+ };
+ }
+
+ if (disc > 0)
+ {
+ if (b == 0)
+ {
+ double r = fabs (0.5 * sqrt (disc) / a);
*x0 = -r;
*x1 = r;
}
else
{
- float sgnb = ( b > 0 ? 1 : -1 );
- float temp = -0.5 * ( b + sgnb * sqrt ( disc ) );
- float r1 = temp / a ;
- float r2 = c / temp ;
+ double sgnb = (b > 0 ? 1 : -1);
+ double temp = -0.5 * (b + sgnb * sqrt (disc));
+ double r1 = temp / a ;
+ double r2 = c / temp ;
- if ( r1 < r2 )
+ if (r1 < r2)
{
*x0 = r1 ;
*x1 = r2 ;
- }
- else
+ }
+ else
{
*x0 = r2 ;
*x1 = r1 ;
@@ -252,7 +322,7 @@ int gsl_poly_solve_quadratic ( float a, float b, float c, float *x0, float *x1
}
return 2;
}
- else if ( disc == 0 )
+ else if (disc == 0)
{
*x0 = -0.5 * b / a ;
*x1 = -0.5 * b / a ;
@@ -266,79 +336,88 @@ int gsl_poly_solve_quadratic ( float a, float b, float c, float *x0, float *x1
-/*
- * See Bridson et al. "Robust Treatment of Collision, Contact and Friction for Cloth Animation"
- * page 4, left column
- */
-int cloth_get_collision_time ( float a[3], float b[3], float c[3], float d[3], float e[3], float f[3], float solution[3] )
+/*
+* See Bridson et al. "Robust Treatment of Collision, Contact and Friction for Cloth Animation"
+* page 4, left column
+*/
+int cloth_get_collision_time ( double a[3], double b[3], double c[3], double d[3], double e[3], double f[3], double solution[3] )
{
int num_sols = 0;
- float g = -a[2] * c[1] * e[0] + a[1] * c[2] * e[0] +
- a[2] * c[0] * e[1] - a[0] * c[2] * e[1] -
- a[1] * c[0] * e[2] + a[0] * c[1] * e[2];
-
- float h = -b[2] * c[1] * e[0] + b[1] * c[2] * e[0] - a[2] * d[1] * e[0] +
- a[1] * d[2] * e[0] + b[2] * c[0] * e[1] - b[0] * c[2] * e[1] +
- a[2] * d[0] * e[1] - a[0] * d[2] * e[1] - b[1] * c[0] * e[2] +
- b[0] * c[1] * e[2] - a[1] * d[0] * e[2] + a[0] * d[1] * e[2] -
- a[2] * c[1] * f[0] + a[1] * c[2] * f[0] + a[2] * c[0] * f[1] -
- a[0] * c[2] * f[1] - a[1] * c[0] * f[2] + a[0] * c[1] * f[2];
-
- float i = -b[2] * d[1] * e[0] + b[1] * d[2] * e[0] +
- b[2] * d[0] * e[1] - b[0] * d[2] * e[1] -
- b[1] * d[0] * e[2] + b[0] * d[1] * e[2] -
- b[2] * c[1] * f[0] + b[1] * c[2] * f[0] -
- a[2] * d[1] * f[0] + a[1] * d[2] * f[0] +
- b[2] * c[0] * f[1] - b[0] * c[2] * f[1] +
- a[2] * d[0] * f[1] - a[0] * d[2] * f[1] -
- b[1] * c[0] * f[2] + b[0] * c[1] * f[2] -
- a[1] * d[0] * f[2] + a[0] * d[1] * f[2];
-
- float j = -b[2] * d[1] * f[0] + b[1] * d[2] * f[0] +
- b[2] * d[0] * f[1] - b[0] * d[2] * f[1] -
- b[1] * d[0] * f[2] + b[0] * d[1] * f[2];
+ // x^0 - checked
+ double g = a[0] * c[1] * e[2] - a[0] * c[2] * e[1] +
+ a[1] * c[2] * e[0] - a[1] * c[0] * e[2] +
+ a[2] * c[0] * e[1] - a[2] * c[1] * e[0];
+
+ // x^1
+ double h = -b[2] * c[1] * e[0] + b[1] * c[2] * e[0] - a[2] * d[1] * e[0] +
+ a[1] * d[2] * e[0] + b[2] * c[0] * e[1] - b[0] * c[2] * e[1] +
+ a[2] * d[0] * e[1] - a[0] * d[2] * e[1] - b[1] * c[0] * e[2] +
+ b[0] * c[1] * e[2] - a[1] * d[0] * e[2] + a[0] * d[1] * e[2] -
+ a[2] * c[1] * f[0] + a[1] * c[2] * f[0] + a[2] * c[0] * f[1] -
+ a[0] * c[2] * f[1] - a[1] * c[0] * f[2] + a[0] * c[1] * f[2];
+
+ // x^2
+ double i = -b[2] * d[1] * e[0] + b[1] * d[2] * e[0] +
+ b[2] * d[0] * e[1] - b[0] * d[2] * e[1] -
+ b[1] * d[0] * e[2] + b[0] * d[1] * e[2] -
+ b[2] * c[1] * f[0] + b[1] * c[2] * f[0] -
+ a[2] * d[1] * f[0] + a[1] * d[2] * f[0] +
+ b[2] * c[0] * f[1] - b[0] * c[2] * f[1] +
+ a[2] * d[0] * f[1] - a[0] * d[2] * f[1] -
+ b[1] * c[0] * f[2] + b[0] * c[1] * f[2] -
+ a[1] * d[0] * f[2] + a[0] * d[1] * f[2];
+
+ // x^3 - checked
+ double j = -b[2] * d[1] * f[0] + b[1] * d[2] * f[0] +
+ b[2] * d[0] * f[1] - b[0] * d[2] * f[1] -
+ b[1] * d[0] * f[2] + b[0] * d[1] * f[2];
+
+ /*
+ printf("r1: %lf\n", a[0] * c[1] * e[2] - a[0] * c[2] * e[1]);
+ printf("r2: %lf\n", a[1] * c[2] * e[0] - a[1] * c[0] * e[2]);
+ printf("r3: %lf\n", a[2] * c[0] * e[1] - a[2] * c[1] * e[0]);
+
+ printf("x1 x: %f, y: %f, z: %f\n", a[0], a[1], a[2]);
+ printf("x2 x: %f, y: %f, z: %f\n", c[0], c[1], c[2]);
+ printf("x3 x: %f, y: %f, z: %f\n", e[0], e[1], e[2]);
+
+ printf("v1 x: %f, y: %f, z: %f\n", b[0], b[1], b[2]);
+ printf("v2 x: %f, y: %f, z: %f\n", d[0], d[1], d[2]);
+ printf("v3 x: %f, y: %f, z: %f\n", f[0], f[1], f[2]);
+
+ printf("t^3: %lf, t^2: %lf, t^1: %lf, t^0: %lf\n", j, i, h, g);
+ */
// Solve cubic equation to determine times t1, t2, t3, when the collision will occur.
- if ( ABS ( j ) > ALMOST_ZERO )
+ if ( ABS ( j ) > DBL_EPSILON )
{
i /= j;
h /= j;
g /= j;
-
num_sols = gsl_poly_solve_cubic ( i, h, g, &solution[0], &solution[1], &solution[2] );
}
- else if ( ABS ( i ) > ALMOST_ZERO )
+ else
{
num_sols = gsl_poly_solve_quadratic ( i, h, g, &solution[0], &solution[1] );
solution[2] = -1.0;
}
- else if ( ABS ( h ) > ALMOST_ZERO )
- {
- solution[0] = -g / h;
- solution[1] = solution[2] = -1.0;
- num_sols = 1;
- }
- else if ( ABS ( g ) > ALMOST_ZERO )
- {
- solution[0] = 0;
- solution[1] = solution[2] = -1.0;
- num_sols = 1;
- }
+
+ // printf("num_sols: %d, sol1: %lf, sol2: %lf, sol3: %lf\n", num_sols, solution[0], solution[1], solution[2]);
// Discard negative solutions
- if ( ( num_sols >= 1 ) && ( solution[0] < 0 ) )
+ if ( ( num_sols >= 1 ) && ( solution[0] < DBL_EPSILON ) )
{
--num_sols;
solution[0] = solution[num_sols];
}
- if ( ( num_sols >= 2 ) && ( solution[1] < 0 ) )
+ if ( ( num_sols >= 2 ) && ( solution[1] < DBL_EPSILON ) )
{
--num_sols;
solution[1] = solution[num_sols];
}
- if ( ( num_sols == 3 ) && ( solution[2] < 0 ) )
+ if ( ( num_sols == 3 ) && ( solution[2] < DBL_EPSILON ) )
{
--num_sols;
}
@@ -419,38 +498,37 @@ DO_INLINE void collision_interpolateOnTriangle ( float to[3], float v1[3], float
VECADDMUL ( to, v3, w3 );
}
-int cloth_collision_response_static ( ClothModifierData *clmd, CollisionModifierData *collmd )
+
+int cloth_collision_response_static ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end )
{
int result = 0;
- LinkNode *search = NULL;
- CollPair *collpair = NULL;
Cloth *cloth1;
float w1, w2, w3, u1, u2, u3;
float v1[3], v2[3], relativeVelocity[3];
float magrelVel;
- float epsilon2 = collmd->bvh->epsilon;
+ float epsilon2 = BLI_bvhtree_getepsilon ( collmd->bvhtree );
cloth1 = clmd->clothObject;
- search = clmd->coll_parms->collision_list;
-
- while ( search )
+ for ( ; collpair != collision_end; collpair++ )
{
- collpair = search->link;
+ // only handle static collisions here
+ if ( collpair->flag & COLLISION_IN_FUTURE )
+ continue;
// compute barycentric coordinates for both collision points
collision_compute_barycentric ( collpair->pa,
- cloth1->verts[collpair->ap1].txold,
- cloth1->verts[collpair->ap2].txold,
- cloth1->verts[collpair->ap3].txold,
- &w1, &w2, &w3 );
+ cloth1->verts[collpair->ap1].txold,
+ cloth1->verts[collpair->ap2].txold,
+ cloth1->verts[collpair->ap3].txold,
+ &w1, &w2, &w3 );
// was: txold
collision_compute_barycentric ( collpair->pb,
- collmd->current_x[collpair->bp1].co,
- collmd->current_x[collpair->bp2].co,
- collmd->current_x[collpair->bp3].co,
- &u1, &u2, &u3 );
+ collmd->current_x[collpair->bp1].co,
+ collmd->current_x[collpair->bp2].co,
+ collmd->current_x[collpair->bp3].co,
+ &u1, &u2, &u3 );
// Calculate relative "velocity".
collision_interpolateOnTriangle ( v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, cloth1->verts[collpair->ap3].tv, w1, w2, w3 );
@@ -530,70 +608,50 @@ int cloth_collision_response_static ( ClothModifierData *clmd, CollisionModifier
result = 1;
}
-
- search = search->next;
}
-
-
return result;
}
-int cloth_collision_response_moving_tris ( ClothModifierData *clmd, ClothModifierData *coll_clmd )
-{
- return 1;
-}
-
-
-int cloth_collision_response_moving_edges ( ClothModifierData *clmd, ClothModifierData *coll_clmd )
-{
- return 1;
-}
-
-void cloth_collision_static ( ModifierData *md1, ModifierData *md2, CollisionTree *tree1, CollisionTree *tree2 )
+//Determines collisions on overlap, collisions are writen to collpair[i] and collision+number_collision_found is returned
+CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, BVHTreeOverlap *overlap, CollPair *collpair )
{
ClothModifierData *clmd = ( ClothModifierData * ) md1;
CollisionModifierData *collmd = ( CollisionModifierData * ) md2;
- CollPair *collpair = NULL;
- Cloth *cloth1=NULL;
- MFace *face1=NULL, *face2=NULL;
- ClothVertex *verts1=NULL;
+ MFace *face1=NULL, *face2 = NULL;
+ ClothVertex *verts1 = clmd->clothObject->verts;
double distance = 0;
- float epsilon = clmd->coll_parms->epsilon;
- float epsilon2 = ( ( CollisionModifierData * ) md2 )->bvh->epsilon;
- unsigned int i = 0;
+ float epsilon1 = clmd->coll_parms->epsilon;
+ float epsilon2 = BLI_bvhtree_getepsilon ( collmd->bvhtree );
+ int i;
+
+ face1 = & ( clmd->clothObject->mfaces[overlap->indexA] );
+ face2 = & ( collmd->mfaces[overlap->indexB] );
+ // check all 4 possible collisions
for ( i = 0; i < 4; i++ )
{
- collpair = ( CollPair * ) MEM_callocN ( sizeof ( CollPair ), "cloth coll pair" );
-
- cloth1 = clmd->clothObject;
-
- verts1 = cloth1->verts;
-
- face1 = & ( cloth1->mfaces[tree1->tri_index] );
- face2 = & ( collmd->mfaces[tree2->tri_index] );
-
- // check all possible pairs of triangles
if ( i == 0 )
{
+ // fill faceA
collpair->ap1 = face1->v1;
collpair->ap2 = face1->v2;
collpair->ap3 = face1->v3;
+ // fill faceB
collpair->bp1 = face2->v1;
collpair->bp2 = face2->v2;
collpair->bp3 = face2->v3;
-
}
-
- if ( i == 1 )
+ else if ( i == 1 )
{
if ( face1->v4 )
{
- collpair->ap1 = face1->v3;
+ // fill faceA
+ collpair->ap1 = face1->v1;
collpair->ap2 = face1->v4;
- collpair->ap3 = face1->v1;
+ collpair->ap3 = face1->v3;
+ // fill faceB
collpair->bp1 = face2->v1;
collpair->bp2 = face2->v2;
collpair->bp3 = face2->v3;
@@ -601,386 +659,743 @@ void cloth_collision_static ( ModifierData *md1, ModifierData *md2, CollisionTre
else
i++;
}
-
if ( i == 2 )
{
if ( face2->v4 )
{
+ // fill faceA
collpair->ap1 = face1->v1;
collpair->ap2 = face1->v2;
collpair->ap3 = face1->v3;
- collpair->bp1 = face2->v3;
+ // fill faceB
+ collpair->bp1 = face2->v1;
collpair->bp2 = face2->v4;
- collpair->bp3 = face2->v1;
+ collpair->bp3 = face2->v3;
}
else
- i+=2;
+ break;
}
-
- if ( i == 3 )
+ else if ( i == 3 )
{
- if ( ( face1->v4 ) && ( face2->v4 ) )
+ if ( face1->v4 && face2->v4 )
{
- collpair->ap1 = face1->v3;
+ // fill faceA
+ collpair->ap1 = face1->v1;
collpair->ap2 = face1->v4;
- collpair->ap3 = face1->v1;
+ collpair->ap3 = face1->v3;
- collpair->bp1 = face2->v3;
+ // fill faceB
+ collpair->bp1 = face2->v1;
collpair->bp2 = face2->v4;
- collpair->bp3 = face2->v1;
+ collpair->bp3 = face2->v3;
}
else
- i++;
+ break;
}
- // calc SIPcode (?)
-
- if ( i < 4 )
- {
- // calc distance + normal
#ifdef WITH_BULLET
- distance = plNearestPoints (
- verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, collmd->current_x[collpair->bp1].co, collmd->current_x[collpair->bp2].co, collmd->current_x[collpair->bp3].co, collpair->pa,collpair->pb,collpair->vector );
+ // calc distance + normal
+ distance = plNearestPoints (
+ verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, collmd->current_x[collpair->bp1].co, collmd->current_x[collpair->bp2].co, collmd->current_x[collpair->bp3].co, collpair->pa,collpair->pb,collpair->vector );
#else
- // just be sure that we don't add anything
- distance = 2.0 * ( epsilon + epsilon2 + ALMOST_ZERO );
+ // just be sure that we don't add anything
+ distance = 2.0 * ( epsilon1 + epsilon2 + ALMOST_ZERO );
#endif
- if ( distance <= ( epsilon + epsilon2 + ALMOST_ZERO ) )
- {
- // printf("dist: %f\n", (float)distance);
-
- // collpair->face1 = tree1->tri_index;
- // collpair->face2 = tree2->tri_index;
- VECCOPY ( collpair->normal, collpair->vector );
- Normalize ( collpair->normal );
-
- collpair->distance = distance;
- BLI_linklist_prepend ( &clmd->coll_parms->collision_list, collpair );
+ if ( distance <= ( epsilon1 + epsilon2 + ALMOST_ZERO ) )
+ {
+ VECCOPY ( collpair->normal, collpair->vector );
+ Normalize ( collpair->normal );
- }
- else
- {
- MEM_freeN ( collpair );
- }
+ collpair->distance = distance;
+ collpair->flag = 0;
}
else
{
- MEM_freeN ( collpair );
+ // check for collision in the future
+ collpair->flag |= COLLISION_IN_FUTURE;
}
+ collpair++;
}
+ return collpair;
}
-int cloth_are_edges_adjacent ( ClothModifierData *clmd, ClothModifierData *coll_clmd, EdgeCollPair *edgecollpair )
+int cloth_are_edges_adjacent ( ClothModifierData *clmd, CollisionModifierData *collmd, EdgeCollPair *edgecollpair )
{
- Cloth *cloth1 = NULL, *cloth2 = NULL;
- ClothVertex *verts1 = NULL, *verts2 = NULL;
+ Cloth *cloth1 = NULL;
+ ClothVertex *verts1 = NULL;
float temp[3];
+ MVert *verts2 = collmd->current_x; // old x
cloth1 = clmd->clothObject;
- cloth2 = coll_clmd->clothObject;
-
verts1 = cloth1->verts;
- verts2 = cloth2->verts;
- VECSUB ( temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p21].xold );
+ VECSUB ( temp, verts1[edgecollpair->p11].txold, verts2[edgecollpair->p21].co );
+ if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO )
+ return 1;
+
+ VECSUB ( temp, verts1[edgecollpair->p11].txold, verts2[edgecollpair->p22].co );
if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO )
return 1;
- VECSUB ( temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p22].xold );
+ VECSUB ( temp, verts1[edgecollpair->p12].txold, verts2[edgecollpair->p21].co );
if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO )
return 1;
- VECSUB ( temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p21].xold );
+ VECSUB ( temp, verts1[edgecollpair->p12].txold, verts2[edgecollpair->p22].co );
if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO )
return 1;
- VECSUB ( temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p22].xold );
+ VECSUB ( temp, verts1[edgecollpair->p11].txold, verts1[edgecollpair->p12].txold );
if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO )
return 1;
+ VECSUB ( temp, verts2[edgecollpair->p21].co, verts2[edgecollpair->p22].co );
+ if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO )
+ return 1;
+
+
return 0;
}
-void cloth_collision_moving_edges ( ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2 )
+int cloth_collision_response_moving( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end )
{
- EdgeCollPair edgecollpair;
- Cloth *cloth1=NULL, *cloth2=NULL;
- MFace *face1=NULL, *face2=NULL;
- ClothVertex *verts1=NULL, *verts2=NULL;
- unsigned int i = 0, j = 0, k = 0;
- int numsolutions = 0;
- float a[3], b[3], c[3], d[3], e[3], f[3], solution[3];
+ int result = 0;
+ Cloth *cloth1;
+ float w1, w2, w3, u1, u2, u3;
+ float v1[3], v2[3], relativeVelocity[3];
+ float magrelVel;
+ float epsilon2 = BLI_bvhtree_getepsilon ( collmd->bvhtree );
cloth1 = clmd->clothObject;
- cloth2 = coll_clmd->clothObject;
- verts1 = cloth1->verts;
- verts2 = cloth2->verts;
+ for ( ; collpair != collision_end; collpair++ )
+ {
+ // compute barycentric coordinates for both collision points
+ collision_compute_barycentric ( collpair->pa,
+ cloth1->verts[collpair->ap1].txold,
+ cloth1->verts[collpair->ap2].txold,
+ cloth1->verts[collpair->ap3].txold,
+ &w1, &w2, &w3 );
- face1 = & ( cloth1->mfaces[tree1->tri_index] );
- face2 = & ( cloth2->mfaces[tree2->tri_index] );
+ // was: txold
+ collision_compute_barycentric ( collpair->pb,
+ collmd->current_x[collpair->bp1].co,
+ collmd->current_x[collpair->bp2].co,
+ collmd->current_x[collpair->bp3].co,
+ &u1, &u2, &u3 );
- for ( i = 0; i < 5; i++ )
- {
- if ( i == 0 )
- {
- edgecollpair.p11 = face1->v1;
- edgecollpair.p12 = face1->v2;
- }
- else if ( i == 1 )
- {
- edgecollpair.p11 = face1->v2;
- edgecollpair.p12 = face1->v3;
- }
- else if ( i == 2 )
+ // Calculate relative "velocity".
+ collision_interpolateOnTriangle ( v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, cloth1->verts[collpair->ap3].tv, w1, w2, w3 );
+
+ collision_interpolateOnTriangle ( v2, collmd->current_v[collpair->bp1].co, collmd->current_v[collpair->bp2].co, collmd->current_v[collpair->bp3].co, u1, u2, u3 );
+
+ VECSUB ( relativeVelocity, v2, v1 );
+
+ // Calculate the normal component of the relative velocity (actually only the magnitude - the direction is stored in 'normal').
+ magrelVel = INPR ( relativeVelocity, collpair->normal );
+
+ // printf("magrelVel: %f\n", magrelVel);
+
+ // Calculate masses of points.
+ // TODO
+
+ // If v_n_mag < 0 the edges are approaching each other.
+ if ( magrelVel > ALMOST_ZERO )
{
- if ( face1->v4 )
+ // Calculate Impulse magnitude to stop all motion in normal direction.
+ float magtangent = 0, repulse = 0, d = 0;
+ double impulse = 0.0;
+ float vrel_t_pre[3];
+ float temp[3];
+
+ // calculate tangential velocity
+ VECCOPY ( temp, collpair->normal );
+ VecMulf ( temp, magrelVel );
+ VECSUB ( vrel_t_pre, relativeVelocity, temp );
+
+ // Decrease in magnitude of relative tangential velocity due to coulomb friction
+ // in original formula "magrelVel" should be the "change of relative velocity in normal direction"
+ magtangent = MIN2 ( clmd->coll_parms->friction * 0.01 * magrelVel,sqrt ( INPR ( vrel_t_pre,vrel_t_pre ) ) );
+
+ // Apply friction impulse.
+ if ( magtangent > ALMOST_ZERO )
{
- edgecollpair.p11 = face1->v3;
- edgecollpair.p12 = face1->v4;
+ Normalize ( vrel_t_pre );
+
+ impulse = 2.0 * magtangent / ( 1.0 + w1*w1 + w2*w2 + w3*w3 );
+ VECADDMUL ( cloth1->verts[collpair->ap1].impulse, vrel_t_pre, w1 * impulse );
+ VECADDMUL ( cloth1->verts[collpair->ap2].impulse, vrel_t_pre, w2 * impulse );
+ VECADDMUL ( cloth1->verts[collpair->ap3].impulse, vrel_t_pre, w3 * impulse );
}
- else
+
+ // Apply velocity stopping impulse
+ // I_c = m * v_N / 2.0
+ // no 2.0 * magrelVel normally, but looks nicer DG
+ impulse = magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3 );
+
+ VECADDMUL ( cloth1->verts[collpair->ap1].impulse, collpair->normal, w1 * impulse );
+ cloth1->verts[collpair->ap1].impulse_count++;
+
+ VECADDMUL ( cloth1->verts[collpair->ap2].impulse, collpair->normal, w2 * impulse );
+ cloth1->verts[collpair->ap2].impulse_count++;
+
+ VECADDMUL ( cloth1->verts[collpair->ap3].impulse, collpair->normal, w3 * impulse );
+ cloth1->verts[collpair->ap3].impulse_count++;
+
+ // Apply repulse impulse if distance too short
+ // I_r = -min(dt*kd, m(0,1d/dt - v_n))
+ /*
+ d = clmd->coll_parms->epsilon*8.0/9.0 + epsilon2*8.0/9.0 - collpair->distance;
+ if ( ( magrelVel < 0.1*d*clmd->sim_parms->stepsPerFrame ) && ( d > ALMOST_ZERO ) )
{
- edgecollpair.p11 = face1->v3;
- edgecollpair.p12 = face1->v1;
- i+=5; // get out of here after this edge pair is handled
+ repulse = MIN2 ( d*1.0/clmd->sim_parms->stepsPerFrame, 0.1*d*clmd->sim_parms->stepsPerFrame - magrelVel );
+
+ // stay on the safe side and clamp repulse
+ if ( impulse > ALMOST_ZERO )
+ repulse = MIN2 ( repulse, 5.0*impulse );
+ repulse = MAX2 ( impulse, repulse );
+
+ impulse = repulse / ( 1.0 + w1*w1 + w2*w2 + w3*w3 ); // original 2.0 / 0.25
+ VECADDMUL ( cloth1->verts[collpair->ap1].impulse, collpair->normal, impulse );
+ VECADDMUL ( cloth1->verts[collpair->ap2].impulse, collpair->normal, impulse );
+ VECADDMUL ( cloth1->verts[collpair->ap3].impulse, collpair->normal, impulse );
}
+ */
+ result = 1;
}
- else if ( i == 3 )
+ }
+ return result;
+}
+
+static float projectPointOntoLine(float *p, float *a, float *b)
+{
+ float ba[3], pa[3];
+ VECSUB(ba, b, a);
+ VECSUB(pa, p, a);
+ return INPR(pa, ba) / INPR(ba, ba);
+}
+
+static void calculateEENormal(float *np1, float *np2, float *np3, float *np4,float *out_normal)
+{
+ float line1[33], line2[3];
+ float length;
+
+ VECSUB(line1, np2, np1);
+ VECSUB(line2, np3, np1);
+
+ Crossf(out_normal, line1, line2);
+ length = Normalize(out_normal);
+ if (length <= FLT_EPSILON)
+ { // lines are collinear
+ VECSUB(out_normal, np2, np1);
+ Normalize(out_normal);
+ }
+}
+
+static void findClosestPointsEE(float *x1, float *x2, float *x3, float *x4, float *w1, float *w2)
+{
+ float temp[3], temp2[3];
+
+ double a, b, c, e, f;
+
+ VECSUB(temp, x2, x1);
+ a = INPR(temp, temp);
+
+ VECSUB(temp2, x4, x3);
+ b = -INPR(temp, temp2);
+
+ c = INPR(temp2, temp2);
+
+ VECSUB(temp2, x3, x1);
+ e = INPR(temp, temp2);
+
+ VECSUB(temp, x4, x3);
+ f = -INPR(temp, temp2);
+
+ *w1 = (e * c - b * f) / (a * c - b * b);
+ *w2 = (f - b * *w1) / c;
+
+}
+
+// calculates the distance of 2 edges
+float edgedge_distance(float np11[3], float np12[3], float np21[3], float np22[3], float *out_a1, float *out_a2, float *out_normal)
+{
+ float line1[3], line2[3], cross[3];
+ float length;
+ float temp[3], temp2[3];
+ float dist_a1, dist_a2;
+
+ VECSUB(line1, np12, np11);
+ VECSUB(line2, np22, np21);
+
+ Crossf(cross, line1, line2);
+ length = INPR(cross, cross);
+
+ if (length < FLT_EPSILON)
+ {
+ *out_a2 = projectPointOntoLine(np11, np21, np22);
+ if ((*out_a2 >= -FLT_EPSILON) && (*out_a2 <= 1.0 + FLT_EPSILON))
{
- if ( face1->v4 )
+ *out_a1 = 0;
+ calculateEENormal(np11, np12, np21, np22, out_normal);
+ VECSUB(temp, np22, np21);
+ VecMulf(temp, *out_a2);
+ VECADD(temp2, temp, np21);
+ VECADD(temp2, temp2, np11);
+ return INPR(temp2, temp2);
+ }
+
+ CLAMP(*out_a2, 0.0, 1.0);
+ if (*out_a2 > .5)
+ { // == 1.0
+ *out_a1 = projectPointOntoLine(np22, np11, np12);
+ if ((*out_a1 >= -FLT_EPSILON) && (*out_a1 <= 1.0 + FLT_EPSILON))
{
- edgecollpair.p11 = face1->v4;
- edgecollpair.p12 = face1->v1;
+ calculateEENormal(np11, np12, np21, np22, out_normal);
+
+ // return (np22 - (np11 + (np12 - np11) * out_a1)).lengthSquared();
+ VECSUB(temp, np12, np11);
+ VecMulf(temp, *out_a1);
+ VECADD(temp2, temp, np11);
+ VECSUB(temp2, np22, temp2);
+ return INPR(temp2, temp2);
+ }
+ }
+ else
+ { // == 0.0
+ *out_a1 = projectPointOntoLine(np21, np11, np12);
+ if ((*out_a1 >= -FLT_EPSILON) && (*out_a1 <= 1.0 + FLT_EPSILON))
+ {
+ calculateEENormal(np11, np11, np21, np22, out_normal);
+
+ // return (np21 - (np11 + (np12 - np11) * out_a1)).lengthSquared();
+ VECSUB(temp, np12, np11);
+ VecMulf(temp, *out_a1);
+ VECADD(temp2, temp, np11);
+ VECSUB(temp2, np21, temp2);
+ return INPR(temp2, temp2);
}
- else
- continue;
- }
- else
- {
- edgecollpair.p11 = face1->v3;
- edgecollpair.p12 = face1->v1;
}
-
- for ( j = 0; j < 5; j++ )
+ CLAMP(*out_a1, 0.0, 1.0);
+ calculateEENormal(np11, np12, np21, np22, out_normal);
+ if(*out_a1 > .5)
{
- if ( j == 0 )
+ if(*out_a2 > .5)
{
- edgecollpair.p21 = face2->v1;
- edgecollpair.p22 = face2->v2;
+ VECSUB(temp, np12, np22);
}
- else if ( j == 1 )
+ else
{
- edgecollpair.p21 = face2->v2;
- edgecollpair.p22 = face2->v3;
+ VECSUB(temp, np12, np21);
}
- else if ( j == 2 )
+ }
+ else
+ {
+ if(*out_a2 > .5)
{
- if ( face2->v4 )
- {
- edgecollpair.p21 = face2->v3;
- edgecollpair.p22 = face2->v4;
- }
- else
- {
- edgecollpair.p21 = face2->v3;
- edgecollpair.p22 = face2->v1;
- }
- }
- else if ( j == 3 )
- {
- if ( face2->v4 )
- {
- edgecollpair.p21 = face2->v4;
- edgecollpair.p22 = face2->v1;
- }
- else
- continue;
+ VECSUB(temp, np11, np22);
}
else
{
- edgecollpair.p21 = face2->v3;
- edgecollpair.p22 = face2->v1;
+ VECSUB(temp, np11, np21);
}
+ }
+ return INPR(temp, temp);
+ }
+ else
+ {
+
+ // If the lines aren't parallel (but coplanar) they have to intersect
- if ( !cloth_are_edges_adjacent ( clmd, coll_clmd, &edgecollpair ) )
- {
- VECSUB ( a, verts1[edgecollpair.p12].xold, verts1[edgecollpair.p11].xold );
- VECSUB ( b, verts1[edgecollpair.p12].v, verts1[edgecollpair.p11].v );
- VECSUB ( c, verts1[edgecollpair.p21].xold, verts1[edgecollpair.p11].xold );
- VECSUB ( d, verts1[edgecollpair.p21].v, verts1[edgecollpair.p11].v );
- VECSUB ( e, verts2[edgecollpair.p22].xold, verts1[edgecollpair.p11].xold );
- VECSUB ( f, verts2[edgecollpair.p22].v, verts1[edgecollpair.p11].v );
-
- numsolutions = cloth_get_collision_time ( a, b, c, d, e, f, solution );
-
- for ( k = 0; k < numsolutions; k++ )
- {
- if ( ( solution[k] >= 0.0 ) && ( solution[k] <= 1.0 ) )
- {
- //float out_collisionTime = solution[k];
-
- // TODO: check for collisions
+ findClosestPointsEE(np11, np12, np21, np22, out_a1, out_a2);
- // TODO: put into (edge) collision list
+ // If both points are on the finite edges, we're done.
+ if (*out_a1 >= 0.0 && *out_a1 <= 1.0 && *out_a2 >= 0.0 && *out_a2 <= 1.0)
+ {
+ float p1[3], p2[3];
+
+ // p1= np11 + (np12 - np11) * out_a1;
+ VECSUB(temp, np12, np11);
+ VecMulf(temp, *out_a1);
+ VECADD(p1, np11, temp);
+
+ // p2 = np21 + (np22 - np21) * out_a2;
+ VECSUB(temp, np22, np21);
+ VecMulf(temp, *out_a2);
+ VECADD(p2, np21, temp);
+
+ calculateEENormal(np11, np12, np21, np22, out_normal);
+ VECSUB(temp, p1, p2);
+ return INPR(temp, temp);
+ }
- // printf("Moving edge found!\n");
- }
- }
- }
+
+ /*
+ * Clamp both points to the finite edges.
+ * The one that moves most during clamping is one part of the solution.
+ */
+ dist_a1 = *out_a1;
+ CLAMP(dist_a1, 0.0, 1.0);
+ dist_a2 = *out_a2;
+ CLAMP(dist_a2, 0.0, 1.0);
+
+ // Now project the "most clamped" point on the other line.
+ if (dist_a1 > dist_a2)
+ {
+ /* keep out_a1 */
+ float p1[3];
+
+ // p1 = np11 + (np12 - np11) * out_a1;
+ VECSUB(temp, np12, np11);
+ VecMulf(temp, *out_a1);
+ VECADD(p1, np11, temp);
+
+ *out_a2 = projectPointOntoLine(p1, np21, np22);
+ CLAMP(*out_a2, 0.0, 1.0);
+
+ calculateEENormal(np11, np12, np21, np22, out_normal);
+
+ // return (p1 - (np21 + (np22 - np21) * out_a2)).lengthSquared();
+ VECSUB(temp, np22, np21);
+ VecMulf(temp, *out_a2);
+ VECADD(temp, temp, np21);
+ VECSUB(temp, p1, temp);
+ return INPR(temp, temp);
+ }
+ else
+ {
+ /* keep out_a2 */
+ float p2[3];
+
+ // p2 = np21 + (np22 - np21) * out_a2;
+ VECSUB(temp, np22, np21);
+ VecMulf(temp, *out_a2);
+ VECADD(p2, np21, temp);
+
+ *out_a1 = projectPointOntoLine(p2, np11, np12);
+ CLAMP(*out_a1, 0.0, 1.0);
+
+ calculateEENormal(np11, np12, np21, np22, out_normal);
+
+ // return ((np11 + (np12 - np11) * out_a1) - p2).lengthSquared();
+ VECSUB(temp, np12, np11);
+ VecMulf(temp, *out_a1);
+ VECADD(temp, temp, np11);
+ VECSUB(temp, temp, p2);
+ return INPR(temp, temp);
}
}
+
+ printf("Error in edgedge_distance: end of function\n");
+ return 0;
}
-void cloth_collision_moving_tris ( ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2 )
+int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair )
{
- CollPair collpair;
- Cloth *cloth1=NULL, *cloth2=NULL;
- MFace *face1=NULL, *face2=NULL;
- ClothVertex *verts1=NULL, *verts2=NULL;
+ EdgeCollPair edgecollpair;
+ Cloth *cloth1=NULL;
+ ClothVertex *verts1=NULL;
unsigned int i = 0, j = 0, k = 0;
int numsolutions = 0;
- float a[3], b[3], c[3], d[3], e[3], f[3], solution[3];
+ double x1[3], v1[3], x2[3], v2[3], x3[3], v3[3];
+ double solution[3];
+ MVert *verts2 = collmd->current_x; // old x
+ MVert *velocity2 = collmd->current_v; // velocity
+ float mintime = FLT_MAX;
+ float distance;
+ float triA[3][3], triB[3][3];
+ int result = 0;
- for ( i = 0; i < 2; i++ )
+ cloth1 = clmd->clothObject;
+ verts1 = cloth1->verts;
+
+ for(i = 0; i < 9; i++)
{
- cloth1 = clmd->clothObject;
- cloth2 = coll_clmd->clothObject;
+ // 9 edge - edge possibilities
- verts1 = cloth1->verts;
- verts2 = cloth2->verts;
+ if(i == 0) // cloth edge: 1-2; coll edge: 1-2
+ {
+ edgecollpair.p11 = collpair->ap1;
+ edgecollpair.p12 = collpair->ap2;
- face1 = & ( cloth1->mfaces[tree1->tri_index] );
- face2 = & ( cloth2->mfaces[tree2->tri_index] );
+ edgecollpair.p21 = collpair->bp1;
+ edgecollpair.p22 = collpair->bp2;
+ }
+ else if(i == 1) // cloth edge: 1-2; coll edge: 2-3
+ {
+ edgecollpair.p11 = collpair->ap1;
+ edgecollpair.p12 = collpair->ap2;
- // check all possible pairs of triangles
- if ( i == 0 )
+ edgecollpair.p21 = collpair->bp2;
+ edgecollpair.p22 = collpair->bp3;
+ }
+ else if(i == 2) // cloth edge: 1-2; coll edge: 1-3
{
- collpair.ap1 = face1->v1;
- collpair.ap2 = face1->v2;
- collpair.ap3 = face1->v3;
-
- collpair.pointsb[0] = face2->v1;
- collpair.pointsb[1] = face2->v2;
- collpair.pointsb[2] = face2->v3;
- collpair.pointsb[3] = face2->v4;
+ edgecollpair.p11 = collpair->ap1;
+ edgecollpair.p12 = collpair->ap2;
+
+ edgecollpair.p21 = collpair->bp1;
+ edgecollpair.p22 = collpair->bp3;
}
+ else if(i == 3) // cloth edge: 2-3; coll edge: 1-2
+ {
+ edgecollpair.p11 = collpair->ap2;
+ edgecollpair.p12 = collpair->ap3;
- if ( i == 1 )
+ edgecollpair.p21 = collpair->bp1;
+ edgecollpair.p22 = collpair->bp2;
+ }
+ else if(i == 4) // cloth edge: 2-3; coll edge: 2-3
{
- if ( face1->v4 )
- {
- collpair.ap1 = face1->v3;
- collpair.ap2 = face1->v4;
- collpair.ap3 = face1->v1;
-
- collpair.pointsb[0] = face2->v1;
- collpair.pointsb[1] = face2->v2;
- collpair.pointsb[2] = face2->v3;
- collpair.pointsb[3] = face2->v4;
- }
- else
- i++;
+ edgecollpair.p11 = collpair->ap2;
+ edgecollpair.p12 = collpair->ap3;
+
+ edgecollpair.p21 = collpair->bp2;
+ edgecollpair.p22 = collpair->bp3;
}
+ else if(i == 5) // cloth edge: 2-3; coll edge: 1-3
+ {
+ edgecollpair.p11 = collpair->ap2;
+ edgecollpair.p12 = collpair->ap3;
- // calc SIPcode (?)
+ edgecollpair.p21 = collpair->bp1;
+ edgecollpair.p22 = collpair->bp3;
+ }
+ else if(i ==6) // cloth edge: 1-3; coll edge: 1-2
+ {
+ edgecollpair.p11 = collpair->ap1;
+ edgecollpair.p12 = collpair->ap3;
- if ( i < 2 )
+ edgecollpair.p21 = collpair->bp1;
+ edgecollpair.p22 = collpair->bp2;
+ }
+ else if(i ==7) // cloth edge: 1-3; coll edge: 2-3
{
- VECSUB ( a, verts1[collpair.ap2].xold, verts1[collpair.ap1].xold );
- VECSUB ( b, verts1[collpair.ap2].v, verts1[collpair.ap1].v );
- VECSUB ( c, verts1[collpair.ap3].xold, verts1[collpair.ap1].xold );
- VECSUB ( d, verts1[collpair.ap3].v, verts1[collpair.ap1].v );
+ edgecollpair.p11 = collpair->ap1;
+ edgecollpair.p12 = collpair->ap3;
- for ( j = 0; j < 4; j++ )
- {
- if ( ( j==3 ) && ! ( face2->v4 ) )
- break;
+ edgecollpair.p21 = collpair->bp2;
+ edgecollpair.p22 = collpair->bp3;
+ }
+ else if(i == 8) // cloth edge: 1-3; coll edge: 1-3
+ {
+ edgecollpair.p11 = collpair->ap1;
+ edgecollpair.p12 = collpair->ap3;
- VECSUB ( e, verts2[collpair.pointsb[j]].xold, verts1[collpair.ap1].xold );
- VECSUB ( f, verts2[collpair.pointsb[j]].v, verts1[collpair.ap1].v );
+ edgecollpair.p21 = collpair->bp1;
+ edgecollpair.p22 = collpair->bp3;
+ }
- numsolutions = cloth_get_collision_time ( a, b, c, d, e, f, solution );
+ if((edgecollpair.p11 == 3) && (edgecollpair.p12 == 6))
+ printf("Ahier!\n");
+ if((edgecollpair.p11 == 6) && (edgecollpair.p12 == 3))
+ printf("Ahier!\n");
- for ( k = 0; k < numsolutions; k++ )
+ if ( !cloth_are_edges_adjacent ( clmd, collmd, &edgecollpair ) )
+ {
+ // printf("Collision between:\n");
+ // printf("p11: %d, p12: %d, p21: %d, p22: %d\n", edgecollpair.p11, edgecollpair.p12, edgecollpair.p21, edgecollpair.p22);
+
+ // always put coll points in p21/p22
+ VECSUB ( x1, verts1[edgecollpair.p12].txold, verts1[edgecollpair.p11].txold );
+ VECSUB ( v1, verts1[edgecollpair.p12].tv, verts1[edgecollpair.p11].tv );
+
+ VECSUB ( x2, verts2[edgecollpair.p21].co, verts1[edgecollpair.p11].txold );
+ VECSUB ( v2, velocity2[edgecollpair.p21].co, verts1[edgecollpair.p11].tv );
+
+ VECSUB ( x3, verts2[edgecollpair.p22].co, verts1[edgecollpair.p11].txold );
+ VECSUB ( v3, velocity2[edgecollpair.p22].co, verts1[edgecollpair.p11].tv );
+
+ numsolutions = cloth_get_collision_time ( x1, v1, x2, v2, x3, v3, solution );
+
+ for ( k = 0; k < numsolutions; k++ )
+ {
+ // printf("sol %d: %lf\n", k, solution[k]);
+ if ( ( solution[k] >= ALMOST_ZERO ) && ( solution[k] <= 1.0 ) && ( solution[k] > ALMOST_ZERO))
{
- if ( ( solution[k] >= 0.0 ) && ( solution[k] <= 1.0 ) )
+ float a,b;
+ float out_normal[3];
+ float distance;
+ float impulse = 0;
+ float I_mag;
+ float m1, m2;
+
+ // move verts
+ VECADDS(triA[0], verts1[edgecollpair.p11].txold, verts1[edgecollpair.p11].tv, mintime);
+ VECADDS(triA[1], verts1[edgecollpair.p12].txold, verts1[edgecollpair.p12].tv, mintime);
+
+ VECADDS(triB[0], collmd->current_x[edgecollpair.p21].co, collmd->current_v[edgecollpair.p21].co, mintime);
+ VECADDS(triB[1], collmd->current_x[edgecollpair.p22].co, collmd->current_v[edgecollpair.p22].co, mintime);
+
+ // TODO: check for collisions
+ distance = edgedge_distance(triA[0], triA[1], triB[0], triB[1], &a, &b, out_normal);
+
+ if ((distance <= clmd->coll_parms->epsilon + BLI_bvhtree_getepsilon ( collmd->bvhtree ) + ALMOST_ZERO) && (INPR(out_normal, out_normal) > 0))
{
- //float out_collisionTime = solution[k];
+ float vrel_1_to_2[3], temp[3], temp2[3], out_normalVelocity;
+ float desiredVn;
- // TODO: check for collisions
+ VECCOPY(vrel_1_to_2, verts1[edgecollpair.p11].tv);
+ VecMulf(vrel_1_to_2, 1.0 - a);
+ VECCOPY(temp, verts1[edgecollpair.p12].tv);
+ VecMulf(temp, a);
- // TODO: put into (point-face) collision list
+ VECADD(vrel_1_to_2, vrel_1_to_2, temp);
+
+ VECCOPY(temp, verts1[edgecollpair.p21].tv);
+ VecMulf(temp, 1.0 - b);
+ VECCOPY(temp2, verts1[edgecollpair.p22].tv);
+ VecMulf(temp2, b);
+ VECADD(temp, temp, temp2);
+
+ VECSUB(vrel_1_to_2, vrel_1_to_2, temp);
+
+ out_normalVelocity = INPR(vrel_1_to_2, out_normal);
+
+ if(out_normalVelocity < 0.0)
+ {
+ out_normalVelocity*= -1.0;
+ VecMulf(out_normal, -1.0);
+ }
- // printf("Moving found!\n");
+ /* Inelastic repulsion impulse. */
+ // Calculate which normal velocity we need.
+ desiredVn = (out_normalVelocity * (float)solution[k] - (.1 * (clmd->coll_parms->epsilon + BLI_bvhtree_getepsilon ( collmd->bvhtree )) - sqrt(distance)) - ALMOST_ZERO);
+
+ // Now calculate what impulse we need to reach that velocity.
+ I_mag = (out_normalVelocity - desiredVn) / 2.0; // / (1/m1 + 1/m2);
+
+ // Finally apply that impulse.
+ impulse = (2.0 * -I_mag) / (a*a + (1.0-a)*(1.0-a) + b*b + (1.0-b)*(1.0-b));
+
+ VECADDMUL ( verts1[edgecollpair.p11].impulse, out_normal, (1.0-a) * impulse );
+ verts1[edgecollpair.p11].impulse_count++;
+
+ VECADDMUL ( verts1[edgecollpair.p12].impulse, out_normal, a * impulse );
+ verts1[edgecollpair.p12].impulse_count++;
+
+ // return true;
+ result = 1;
+ break;
}
- }
+ else
+ {
+ // missing from collision.hpp
+ }
+ mintime = MIN2(mintime, (float)solution[k]);
- // TODO: check borders for collisions
+ break;
+ }
}
-
}
}
+ return result;
}
-void cloth_collision_moving ( ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2 )
+int cloth_collision_moving_tris ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair )
{
- // TODO: check for adjacent
- cloth_collision_moving_edges ( clmd, coll_clmd, tree1, tree2 );
+ EdgeCollPair edgecollpair;
+ Cloth *cloth1=NULL;
+ ClothVertex *verts1=NULL;
+ unsigned int i = 0, j = 0, k = 0;
+ int numsolutions = 0;
+ double x1[3], v1[3], x2[3], v2[3], x3[3], v3[3];
+ double solution[3];
+ MVert *verts2 = collmd->current_x; // old x
+ MVert *velocity2 = collmd->current_v; // velocity
+ float mintime = FLT_MAX;
+ float distance;
+ float triA[3][3], triB[3][3];
+ int result = 0;
- cloth_collision_moving_tris ( clmd, coll_clmd, tree1, tree2 );
- cloth_collision_moving_tris ( coll_clmd, clmd, tree2, tree1 );
-}
+ cloth1 = clmd->clothObject;
+ verts1 = cloth1->verts;
-void cloth_free_collision_list ( ClothModifierData *clmd )
-{
- // free collision list
- if ( clmd->coll_parms->collision_list )
+ for(i = 0; i < 9; i++)
{
- LinkNode *search = clmd->coll_parms->collision_list;
- while ( search )
+ // 9 edge - edge possibilities
+
+ if(i == 0)
{
- CollPair *coll_pair = search->link;
+ edgecollpair.p11 = collpair->ap1;
+ edgecollpair.p12 = collpair->ap2;
- MEM_freeN ( coll_pair );
- search = search->next;
+ edgecollpair.p21 = collpair->bp1;
+ edgecollpair.p22 = collpair->bp2;
}
- BLI_linklist_free ( clmd->coll_parms->collision_list,NULL );
+ }
+
+ return result;
+}
+
+int cloth_collision_moving ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end )
+{
+ int result = 0;
+ Cloth *cloth1;
+ float w1, w2, w3, u1, u2, u3;
+ float v1[3], v2[3], relativeVelocity[3];
+ float magrelVel;
+ float epsilon2 = BLI_bvhtree_getepsilon ( collmd->bvhtree );
+
+ cloth1 = clmd->clothObject;
+
+ for ( ; collpair != collision_end; collpair++ )
+ {
+ // only handle moving collisions here
+ if (!( collpair->flag & COLLISION_IN_FUTURE ))
+ continue;
- clmd->coll_parms->collision_list = NULL;
+ cloth_collision_moving_edges ( clmd, collmd, collpair);
+ // cloth_collision_moving_tris ( clmd, collmd, collpair);
}
+
+ return 1;
}
int cloth_bvh_objcollisions_do ( ClothModifierData * clmd, CollisionModifierData *collmd, float step, float dt )
{
Cloth *cloth = clmd->clothObject;
- BVH *cloth_bvh= ( BVH * ) cloth->tree;
+ BVHTree *cloth_bvh= ( BVHTree * ) cloth->bvhtree;
long i=0, j = 0, numfaces = 0, numverts = 0;
ClothVertex *verts = NULL;
+ CollPair *collisions = NULL, *collisions_index = NULL;
int ret = 0;
- unsigned int result = 0;
+ int result = 0;
float tnull[3] = {0,0,0};
+ BVHTreeOverlap *overlap = NULL;
+
numfaces = clmd->clothObject->numfaces;
numverts = clmd->clothObject->numverts;
verts = cloth->verts;
- if ( collmd->bvh )
+ if ( collmd->bvhtree )
{
/* get pointer to bounding volume hierarchy */
- BVH *coll_bvh = collmd->bvh;
+ BVHTree *coll_bvh = collmd->bvhtree;
/* move object to position (step) in time */
collision_move_object ( collmd, step + dt, step );
/* search for overlapping collision pairs */
- bvh_traverse ( ( ModifierData * ) clmd, ( ModifierData * ) collmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_static, 0 );
+ overlap = BLI_bvhtree_overlap ( cloth_bvh, coll_bvh, &result );
+
+ collisions = ( CollPair* ) MEM_mallocN ( sizeof ( CollPair ) * result*4, "collision array" ); //*4 since cloth_collision_static can return more than 1 collision
+ collisions_index = collisions;
+
+ for ( i = 0; i < result; i++ )
+ {
+ collisions_index = cloth_collision ( ( ModifierData * ) clmd, ( ModifierData * ) collmd, overlap+i, collisions_index );
+ }
+
+ if ( overlap )
+ MEM_freeN ( overlap );
}
else
{
@@ -994,29 +1409,50 @@ int cloth_bvh_objcollisions_do ( ClothModifierData * clmd, CollisionModifierData
{
result = 0;
- if ( collmd->bvh )
- result += cloth_collision_response_static ( clmd, collmd );
+ if ( collmd->bvhtree )
+ {
+ result += cloth_collision_response_static ( clmd, collmd, collisions, collisions_index );
+
+ // apply impulses in parallel
+ if ( result )
+ {
+ for ( i = 0; i < numverts; i++ )
+ {
+ // calculate "velocities" (just xnew = xold + v; no dt in v)
+ if ( verts[i].impulse_count )
+ {
+ VECADDMUL ( verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count );
+ VECCOPY ( verts[i].impulse, tnull );
+ verts[i].impulse_count = 0;
+
+ ret++;
+ }
+ }
+ }
+
+ result += cloth_collision_moving ( clmd, collmd, collisions, collisions_index );
- // apply impulses in parallel
- if ( result )
- for ( i = 0; i < numverts; i++ )
+ // apply impulses in parallel
+ if ( result )
{
- // calculate "velocities" (just xnew = xold + v; no dt in v)
- if ( verts[i].impulse_count )
+ for ( i = 0; i < numverts; i++ )
{
- VECADDMUL ( verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count );
- VECCOPY ( verts[i].impulse, tnull );
- verts[i].impulse_count = 0;
+ // calculate "velocities" (just xnew = xold + v; no dt in v)
+ if ( verts[i].impulse_count )
+ {
+ VECADDMUL ( verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count );
+ VECCOPY ( verts[i].impulse, tnull );
+ verts[i].impulse_count = 0;
- ret++;
+ ret++;
+ }
}
}
- if ( !result )
- break;
+ }
}
- cloth_free_collision_list ( clmd );
+ if ( collisions ) MEM_freeN ( collisions );
return ret;
}
@@ -1028,22 +1464,22 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt )
CollisionModifierData *collmd=NULL;
Cloth *cloth=NULL;
Object *coll_ob=NULL;
- BVH *cloth_bvh=NULL;
- long i=0, j = 0, numfaces = 0, numverts = 0;
+ BVHTree *cloth_bvh=NULL;
+ long i=0, j = 0, k = 0, numfaces = 0, numverts = 0;
unsigned int result = 0, rounds = 0; // result counts applied collisions; ic is for debug output;
ClothVertex *verts = NULL;
- int ret = 0;
+ int ret = 0, ret2 = 0;
ClothModifierData *tclmd;
int collisions = 0, count = 0;
- if ( ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) || ! ( ( ( Cloth * ) clmd->clothObject )->tree ) )
+ if ( ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) || ! ( ( ( Cloth * ) clmd->clothObject )->bvhtree ) )
{
return 0;
}
cloth = clmd->clothObject;
verts = cloth->verts;
- cloth_bvh = ( BVH * ) cloth->tree;
+ cloth_bvh = ( BVHTree * ) cloth->bvhtree;
numfaces = clmd->clothObject->numfaces;
numverts = clmd->clothObject->numverts;
@@ -1052,12 +1488,13 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt )
////////////////////////////////////////////////////////////
// update cloth bvh
- bvh_update_from_cloth ( clmd, 0 ); // 0 means STATIC, 1 means MOVING (see later in this function)
+ bvhtree_update_from_cloth ( clmd, 1 ); // 0 means STATIC, 1 means MOVING (see later in this function)
+ bvhselftree_update_from_cloth ( clmd, 0 ); // 0 means STATIC, 1 means MOVING (see later in this function)
do
{
result = 0;
- clmd->coll_parms->collision_list = NULL;
+ ret2 = 0;
// check all collision objects
for ( base = G.scene->base.first; base; base = base->next )
@@ -1086,6 +1523,7 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt )
continue;
ret += cloth_bvh_objcollisions_do ( clmd, collmd, step, dt );
+ ret2 += ret;
}
}
}
@@ -1096,6 +1534,7 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt )
continue;
ret += cloth_bvh_objcollisions_do ( clmd, collmd, step, dt );
+ ret2 += ret;
}
}
rounds++;
@@ -1126,97 +1565,121 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt )
////////////////////////////////////////////////////////////
if ( clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF )
{
+
+ MFace *mface = cloth->mfaces;
+ BVHTreeOverlap *overlap = NULL;
+
collisions = 1;
verts = cloth->verts; // needed for openMP
- for ( count = 0; count < clmd->coll_parms->self_loop_count; count++ )
+ numfaces = clmd->clothObject->numfaces;
+ numverts = clmd->clothObject->numverts;
+
+ verts = cloth->verts;
+
+ if ( cloth->bvhselftree )
{
- if ( collisions )
+ // search for overlapping collision pairs
+ overlap = BLI_bvhtree_overlap ( cloth->bvhselftree, cloth->bvhselftree, &result );
+
+// #pragma omp parallel for private(k, i, j) schedule(static)
+ for ( k = 0; k < result; k++ )
{
- collisions = 0;
-#pragma omp parallel for private(i,j, collisions) shared(verts, ret)
- for ( i = 0; i < cloth->numverts; i++ )
+ float temp[3];
+ float length = 0;
+ float mindistance;
+
+ i = overlap[k].indexA;
+ j = overlap[k].indexB;
+
+ mindistance = clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len + cloth->verts[j].avg_spring_len );
+
+ if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL )
+ {
+ if ( ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED )
+ && ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) )
+ {
+ continue;
+ }
+ }
+
+ VECSUB ( temp, verts[i].tx, verts[j].tx );
+
+ if ( ( ABS ( temp[0] ) > mindistance ) || ( ABS ( temp[1] ) > mindistance ) || ( ABS ( temp[2] ) > mindistance ) ) continue;
+
+ // check for adjacent points (i must be smaller j)
+ if ( BLI_edgehash_haskey ( cloth->edgehash, MIN2(i, j), MAX2(i, j) ) )
+ {
+ continue;
+ }
+
+ length = Normalize ( temp );
+
+ if ( length < mindistance )
{
- for ( j = i + 1; j < cloth->numverts; j++ )
+ float correction = mindistance - length;
+
+ if ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED )
+ {
+ VecMulf ( temp, -correction );
+ VECADD ( verts[j].tx, verts[j].tx, temp );
+ }
+ else if ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED )
{
- float temp[3];
- float length = 0;
- float mindistance = clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len + cloth->verts[j].avg_spring_len );
-
- if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL )
- {
- if ( ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED )
- && ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) )
- {
- continue;
- }
- }
-
- VECSUB ( temp, verts[i].tx, verts[j].tx );
-
- if ( ( ABS ( temp[0] ) > mindistance ) || ( ABS ( temp[1] ) > mindistance ) || ( ABS ( temp[2] ) > mindistance ) ) continue;
-
- // check for adjacent points (i must be smaller j)
- if ( BLI_edgehash_haskey ( cloth->edgehash, i, j ) )
- {
- continue;
- }
-
- length = Normalize ( temp );
-
- if ( length < mindistance )
- {
- float correction = mindistance - length;
-
- if ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED )
- {
- VecMulf ( temp, -correction );
- VECADD ( verts[j].tx, verts[j].tx, temp );
- }
- else if ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED )
- {
- VecMulf ( temp, correction );
- VECADD ( verts[i].tx, verts[i].tx, temp );
- }
- else
- {
- VecMulf ( temp, -correction*0.5 );
- VECADD ( verts[j].tx, verts[j].tx, temp );
-
- VECSUB ( verts[i].tx, verts[i].tx, temp );
- }
-
- collisions = 1;
-
- if ( !ret )
- {
-#pragma omp critical
- {
- ret = 1;
- }
- }
- }
+ VecMulf ( temp, correction );
+ VECADD ( verts[i].tx, verts[i].tx, temp );
+ }
+ else
+ {
+ VecMulf ( temp, -correction*0.5 );
+ VECADD ( verts[j].tx, verts[j].tx, temp );
+
+ VECSUB ( verts[i].tx, verts[i].tx, temp );
}
+ ret = 1;
+ ret2 += ret;
+ }
+ else
+ {
+ // check for approximated time collisions
}
}
+
+ if ( overlap )
+ MEM_freeN ( overlap );
+
}
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// SELFCOLLISIONS: update velocities
////////////////////////////////////////////////////////////
- if ( ret )
+ if ( ret2 )
{
for ( i = 0; i < cloth->numverts; i++ )
{
- if ( ! ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) )
+ if ( ! ( verts [i].flags & CLOTH_VERT_FLAG_PINNED ) )
+ {
VECSUB ( verts[i].tv, verts[i].tx, verts[i].txold );
+ }
}
}
////////////////////////////////////////////////////////////
}
}
- while ( result && ( clmd->coll_parms->loop_count>rounds ) );
+ while ( ret2 && ( clmd->coll_parms->loop_count>rounds ) );
return MIN2 ( ret, 1 );
}
+
+
+/*
+if ( verts[i].impulse_count )
+{
+ VECADDMUL ( verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count );
+ VECCOPY ( verts[i].impulse, tnull );
+ verts[i].impulse_count = 0;
+
+ ret++;
+}
+*/ \ No newline at end of file
diff --git a/source/blender/blenkernel/intern/kdop.c b/source/blender/blenkernel/intern/kdop.c
deleted file mode 100644
index 3189fe960ad..00000000000
--- a/source/blender/blenkernel/intern/kdop.c
+++ /dev/null
@@ -1,860 +0,0 @@
-/* kdop.c
-*
-*
-* ***** 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) Blender Foundation
-* All rights reserved.
-*
-* The Original Code is: all of this file.
-*
-* Contributor(s): none yet.
-*
-* ***** END GPL LICENSE BLOCK *****
-*/
-
-#include "MEM_guardedalloc.h"
-
-#include "BKE_cloth.h"
-
-#include "DNA_cloth_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_scene_types.h"
-
-#include "BKE_deform.h"
-#include "BKE_DerivedMesh.h"
-#include "BKE_cdderivedmesh.h"
-#include "BKE_effect.h"
-#include "BKE_global.h"
-#include "BKE_object.h"
-#include "BKE_modifier.h"
-#include "BKE_utildefines.h"
-
-#ifdef _OPENMP
-#include <omp.h>
-#endif
-
-
-////////////////////////////////////////////////////////////////////////
-// Additional fastened appending function
-// It uses the link to the last inserted node as start value
-// for searching the end of the list
-// NEW: in compare to the original function, this one returns
-// the reference to the last inserted node
-////////////////////////////////////////////////////////////////////////
-LinkNode *BLI_linklist_append_fast(LinkNode **listp, void *ptr) {
- LinkNode *nlink= MEM_mallocN(sizeof(*nlink), "nlink");
- LinkNode *node = *listp;
-
- nlink->link = ptr;
- nlink->next = NULL;
-
- if(node == NULL){
- *listp = nlink;
- } else {
- while(node->next != NULL){
- node = node->next;
- }
- node->next = nlink;
- }
- return nlink;
-}
-
-
-
-////////////////////////////////////////////////////////////////////////
-// Bounding Volume Hierarchy Definition
-//
-// Notes: From OBB until 26-DOP --> all bounding volumes possible, just choose type below
-// Notes: You have to choose the type at compile time ITM
-// Notes: You can choose the tree type --> binary, quad, octree, choose below
-////////////////////////////////////////////////////////////////////////
-
-static float KDOP_AXES[13][3] =
-{ {1.0, 0, 0}, {0, 1.0, 0}, {0, 0, 1.0}, {1.0, 1.0, 1.0}, {1.0, -1.0, 1.0}, {1.0, 1.0, -1.0},
-{1.0, -1.0, -1.0}, {1.0, 1.0, 0}, {1.0, 0, 1.0}, {0, 1.0, 1.0}, {1.0, -1.0, 0}, {1.0, 0, -1.0},
-{0, 1.0, -1.0}
-};
-
-///////////// choose bounding volume here! /////////////
-
-#define KDOP_26
-
-
-
-#ifdef KDOP_26
-#define KDOP_END 13
-#define KDOP_START 0
-#endif
-
-#ifdef KDOP_18
-#define KDOP_END 13
-#define KDOP_START 7
-#endif
-
-#ifdef KDOP_14
-#define KDOP_END 7
-#define KDOP_START 0
-#endif
-
-// this is basicly some AABB
-#ifdef KDOP_8
-#define KDOP_END 4
-#define KDOP_START 0
-#endif
-
-// this is basicly some OBB
-#ifdef KDOP_6
-#define KDOP_END 3
-#define KDOP_START 0
-#endif
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////
-// Introsort
-// with permission deriven from the following Java code:
-// http://ralphunden.net/content/tutorials/a-guide-to-introsort/
-// and he derived it from the SUN STL
-//////////////////////////////////////////////////////////////////////////////////////////////////////
-static int size_threshold = 16;
-/*
-* Common methods for all algorithms
-*/
-DO_INLINE void bvh_exchange(CollisionTree **a, int i, int j)
-{
- CollisionTree *t=a[i];
- a[i]=a[j];
- a[j]=t;
-}
-DO_INLINE int floor_lg(int a)
-{
- return (int)(floor(log(a)/log(2)));
-}
-
-/*
-* Insertion sort algorithm
-*/
-void bvh_insertionsort(CollisionTree **a, int lo, int hi, int axis)
-{
- int i,j;
- CollisionTree *t;
- for (i=lo; i < hi; i++)
- {
- j=i;
- t = a[i];
- while((j!=lo) && (t->bv[axis] < (a[j-1])->bv[axis]))
- {
- a[j] = a[j-1];
- j--;
- }
- a[j] = t;
- }
-}
-
-static int bvh_partition(CollisionTree **a, int lo, int hi, CollisionTree * x, int axis)
-{
- int i=lo, j=hi;
- while (1)
- {
- while ((a[i])->bv[axis] < x->bv[axis]) i++;
- j=j-1;
- while (x->bv[axis] < (a[j])->bv[axis]) j=j-1;
- if(!(i < j))
- return i;
- bvh_exchange(a, i,j);
- i++;
- }
-}
-
-/*
-* Heapsort algorithm
-*/
-static void bvh_downheap(CollisionTree **a, int i, int n, int lo, int axis)
-{
- CollisionTree * d = a[lo+i-1];
- int child;
- while (i<=n/2)
- {
- child = 2*i;
- if ((child < n) && ((a[lo+child-1])->bv[axis] < (a[lo+child])->bv[axis]))
- {
- child++;
- }
- if (!(d->bv[axis] < (a[lo+child-1])->bv[axis])) break;
- a[lo+i-1] = a[lo+child-1];
- i = child;
- }
- a[lo+i-1] = d;
-}
-
-static void bvh_heapsort(CollisionTree **a, int lo, int hi, int axis)
-{
- int n = hi-lo, i;
- for (i=n/2; i>=1; i=i-1)
- {
- bvh_downheap(a, i,n,lo, axis);
- }
- for (i=n; i>1; i=i-1)
- {
- bvh_exchange(a, lo,lo+i-1);
- bvh_downheap(a, 1,i-1,lo, axis);
- }
-}
-
-static CollisionTree *bvh_medianof3(CollisionTree **a, int lo, int mid, int hi, int axis) // returns Sortable
-{
- if ((a[mid])->bv[axis] < (a[lo])->bv[axis])
- {
- if ((a[hi])->bv[axis] < (a[mid])->bv[axis])
- return a[mid];
- else
- {
- if ((a[hi])->bv[axis] < (a[lo])->bv[axis])
- return a[hi];
- else
- return a[lo];
- }
- }
- else
- {
- if ((a[hi])->bv[axis] < (a[mid])->bv[axis])
- {
- if ((a[hi])->bv[axis] < (a[lo])->bv[axis])
- return a[lo];
- else
- return a[hi];
- }
- else
- return a[mid];
- }
-}
-/*
-* Quicksort algorithm modified for Introsort
-*/
-void bvh_introsort_loop (CollisionTree **a, int lo, int hi, int depth_limit, int axis)
-{
- int p;
-
- while (hi-lo > size_threshold)
- {
- if (depth_limit == 0)
- {
- bvh_heapsort(a, lo, hi, axis);
- return;
- }
- depth_limit=depth_limit-1;
- p=bvh_partition(a, lo, hi, bvh_medianof3(a, lo, lo+((hi-lo)/2)+1, hi-1, axis), axis);
- bvh_introsort_loop(a, p, hi, depth_limit, axis);
- hi=p;
- }
-}
-
-DO_INLINE void bvh_sort(CollisionTree **a0, int begin, int end, int axis)
-{
- if (begin < end)
- {
- CollisionTree **a=a0;
- bvh_introsort_loop(a, begin, end, 2*floor_lg(end-begin), axis);
- bvh_insertionsort(a, begin, end, axis);
- }
-}
-DO_INLINE void bvh_sort_along_axis(CollisionTree **face_list, int start, int end, int axis)
-{
- bvh_sort(face_list, start, end, axis);
-}
-////////////////////////////////////////////////////////////////////////////////////////////////
-void bvh_free(BVH * bvh)
-{
- LinkNode *search = NULL;
- CollisionTree *tree = NULL;
-
- if (bvh)
- {
-
- search = bvh->tree;
-
- while(search)
- {
- LinkNode *next= search->next;
- tree = search->link;
-
- MEM_freeN(tree);
-
- search = next;
- }
-
- BLI_linklist_free(bvh->tree,NULL);
- bvh->tree = NULL;
-
- if(bvh->current_x)
- MEM_freeN(bvh->current_x);
- if(bvh->current_xold)
- MEM_freeN(bvh->current_xold);
-
- MEM_freeN(bvh);
- bvh = NULL;
- }
-}
-
-// only supports x,y,z axis in the moment
-// but we should use a plain and simple function here for speed sake
-DO_INLINE int bvh_largest_axis(float *bv)
-{
- float middle_point[3];
-
- middle_point[0] = (bv[1]) - (bv[0]); // x axis
- middle_point[1] = (bv[3]) - (bv[2]); // y axis
- middle_point[2] = (bv[5]) - (bv[4]); // z axis
- if (middle_point[0] > middle_point[1])
- {
- if (middle_point[0] > middle_point[2])
- return 1; // max x axis
- else
- return 5; // max z axis
- }
- else
- {
- if (middle_point[1] > middle_point[2])
- return 3; // max y axis
- else
- return 5; // max z axis
- }
-}
-
-// depends on the fact that the BVH's for each face is already build
-DO_INLINE void bvh_calc_DOP_hull_from_faces(BVH * bvh, CollisionTree **tri, int numfaces, float *bv)
-{
- float newmin,newmax;
- int i, j;
-
- if(numfaces >0)
- {
- // for all Axes.
- for (i = KDOP_START; i < KDOP_END; i++)
- {
- bv[(2 * i)] = (tri [0])->bv[(2 * i)];
- bv[(2 * i) + 1] = (tri [0])->bv[(2 * i) + 1];
- }
- }
-
- for (j = 0; j < numfaces; j++)
- {
- // for all Axes.
- for (i = KDOP_START; i < KDOP_END; i++)
- {
- newmin = (tri [j])->bv[(2 * i)];
- if ((newmin < bv[(2 * i)]))
- {
- bv[(2 * i)] = newmin;
- }
-
- newmax = (tri [j])->bv[(2 * i) + 1];
- if ((newmax > bv[(2 * i) + 1]))
- {
- bv[(2 * i) + 1] = newmax;
- }
- }
- }
-}
-
-DO_INLINE void bvh_calc_DOP_hull_static(BVH * bvh, CollisionTree **tri, int numfaces, float *bv, CollisionTree *tree)
-{
- MFace *tempMFace = bvh->mfaces;
- float *tempBV = bv;
- float newminmax;
- int i, j, k;
-
- for (j = 0; j < numfaces; j++)
- {
- tempMFace = bvh->mfaces + (tri [j])->tri_index;
- // 3 or 4 vertices per face.
- for (k = 0; k < 4; k++)
- {
- int temp = 0;
- // If this is a triangle.
- if (k == 3 && !tempMFace->v4)
- continue;
- // TODO: other name for "temp" this gets all vertices of a face
- if (k == 0)
- temp = tempMFace->v1;
- else if (k == 1)
- temp = tempMFace->v2;
- else if (k == 2)
- temp = tempMFace->v3;
- else if (k == 3)
- temp = tempMFace->v4;
- // for all Axes.
- for (i = KDOP_START; i < KDOP_END; i++)
- {
- newminmax = INPR(bvh->current_xold[temp].co, KDOP_AXES[i]);
- if ((newminmax < tempBV[(2 * i)]) || (k == 0 && j == 0))
- tempBV[(2 * i)] = newminmax;
- if ((newminmax > tempBV[(2 * i) + 1])|| (k == 0 && j == 0))
- tempBV[(2 * i) + 1] = newminmax;
- }
- }
-
- /* calculate normal of this face */
- /* (code copied from cdderivedmesh.c) */
- /*
- if(tempMFace->v4)
- CalcNormFloat4(bvh->current_xold[tempMFace->v1].co, bvh->current_xold[tempMFace->v2].co,
- bvh->current_xold[tempMFace->v3].co, bvh->current_xold[tempMFace->v4].co, tree->normal);
- else
- CalcNormFloat(bvh->current_xold[tempMFace->v1].co, bvh->current_xold[tempMFace->v2].co,
- bvh->current_xold[tempMFace->v3].co, tree->normal);
-
- tree->alpha = 0;
- */
- }
-}
-
-DO_INLINE void bvh_calc_DOP_hull_moving(BVH * bvh, CollisionTree **tri, int numfaces, float *bv, CollisionTree *tree)
-{
- MFace *tempMFace = bvh->mfaces;
- float *tempBV = bv;
- float newminmax;
- int i, j, k;
-
- /* TODO: calculate normals */
-
- for (j = 0; j < numfaces; j++)
- {
- tempMFace = bvh->mfaces + (tri [j])->tri_index;
- // 3 or 4 vertices per face.
- for (k = 0; k < 4; k++)
- {
- int temp = 0;
- // If this is a triangle.
- if (k == 3 && !tempMFace->v4)
- continue;
- // TODO: other name for "temp" this gets all vertices of a face
- if (k == 0)
- temp = tempMFace->v1;
- else if (k == 1)
- temp = tempMFace->v2;
- else if (k == 2)
- temp = tempMFace->v3;
- else if (k == 3)
- temp = tempMFace->v4;
- // for all Axes.
- for (i = KDOP_START; i < KDOP_END; i++)
- {
- newminmax = INPR(bvh->current_xold[temp].co, KDOP_AXES[i]);
- if ((newminmax < tempBV[(2 * i)]) || (k == 0 && j == 0))
- tempBV[(2 * i)] = newminmax;
- if ((newminmax > tempBV[(2 * i) + 1])|| (k == 0 && j == 0))
- tempBV[(2 * i) + 1] = newminmax;
-
- newminmax = INPR(bvh->current_x[temp].co, KDOP_AXES[i]);
- if ((newminmax < tempBV[(2 * i)]) || (k == 0 && j == 0))
- tempBV[(2 * i)] = newminmax;
- if ((newminmax > tempBV[(2 * i) + 1])|| (k == 0 && j == 0))
- tempBV[(2 * i) + 1] = newminmax;
- }
- }
- }
-}
-
-static void bvh_div_env_node(BVH *bvh, CollisionTree *tree, CollisionTree **face_list, unsigned int start, unsigned int end, int lastaxis, LinkNode *nlink)
-{
- int i = 0;
- CollisionTree *newtree = NULL;
- int laxis = 0, max_nodes=4;
- unsigned int tstart, tend;
- LinkNode *nlink1 = nlink;
- LinkNode *tnlink;
- tree->traversed = 0;
- // Determine which axis to split along
- laxis = bvh_largest_axis(tree->bv);
-
- // Sort along longest axis
- if(laxis!=lastaxis)
- bvh_sort_along_axis(face_list, start, end, laxis);
-
- // maximum is 4 since we have a quad tree
- max_nodes = MIN2((end-start + 1 ),4);
-
- for (i = 0; i < max_nodes; i++)
- {
- tree->count_nodes++;
-
- if(end-start+1 > 4)
- {
- int quarter = ((float)((float)(end - start + 1) / 4.0f));
- tstart = start + i * quarter;
- tend = tstart + quarter - 1;
-
- // be sure that we get all faces
- if(i==3)
- {
- tend = end;
- }
- }
- else
- {
- tend = tstart = start + i;
- }
-
- // Build tree until 4 node left.
- if ((tend-tstart + 1 ) > 1)
- {
- newtree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree");
- tnlink = BLI_linklist_append_fast(&nlink1->next, newtree);
-
- newtree->nodes[0] = newtree->nodes[1] = newtree->nodes[2] = newtree->nodes[3] = NULL;
- newtree->count_nodes = 0;
- newtree->parent = tree;
- newtree->isleaf = 0;
-
- tree->nodes[i] = newtree;
-
- nlink1 = tnlink;
-
- bvh_calc_DOP_hull_from_faces(bvh, &face_list[tstart], tend-tstart + 1, tree->nodes[i]->bv);
-
- bvh_div_env_node(bvh, tree->nodes[i], face_list, tstart, tend, laxis, nlink1);
- }
- else // ok, we have 1 left for this node
- {
- CollisionTree *tnode = face_list[tstart];
- tree->nodes[i] = tnode;
- tree->nodes[i]->parent = tree;
- }
- }
- return;
-}
-
-/* function cannot be directly called - needs alloced bvh */
-void bvh_build (BVH *bvh)
-{
- unsigned int i = 0, j = 0, k = 0;
- CollisionTree **face_list=NULL;
- CollisionTree *tree=NULL;
- LinkNode *nlink = NULL;
-
- bvh->flags = 0;
- bvh->leaf_tree = NULL;
- bvh->leaf_root = NULL;
- bvh->tree = NULL;
-
- if(!bvh->current_x)
- {
- bvh_free(bvh);
- return;
- }
-
- bvh->current_xold = MEM_dupallocN(bvh->current_x);
-
- tree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree");
-
- if (tree == NULL)
- {
- printf("bvh_build: Out of memory for nodes.\n");
- bvh_free(bvh);
- return;
- }
-
- BLI_linklist_append(&bvh->tree, tree);
-
- nlink = bvh->tree;
-
- bvh->root = bvh->tree->link;
- bvh->root->isleaf = 0;
- bvh->root->parent = NULL;
- bvh->root->nodes[0] = bvh->root->nodes[1] = bvh->root->nodes[1] = bvh->root->nodes[3] = NULL;
-
- if(bvh->numfaces<=1)
- {
- bvh->root->tri_index = 0; // Why that? --> only one face there
- bvh->root->isleaf = 1;
- bvh->root->traversed = 0;
- bvh->root->count_nodes = 0;
- bvh->leaf_root = bvh->root;
- bvh->leaf_tree = bvh->root;
- bvh->root->nextLeaf = NULL;
- bvh->root->prevLeaf = NULL;
- }
- else
- {
- // create face boxes
- face_list = MEM_callocN (bvh->numfaces * sizeof (CollisionTree *), "CollisionTree");
- if (face_list == NULL)
- {
- printf("bvh_build: Out of memory for face_list.\n");
- bvh_free(bvh);
- return;
- }
-
- // create face boxes
- for(i = 0, k = 0; i < bvh->numfaces; i++)
- {
- LinkNode *tnlink;
-
- tree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree");
- // TODO: check succesfull alloc
-
- tnlink = BLI_linklist_append_fast(&nlink->next, tree);
-
- face_list[i] = tree;
- tree->tri_index = i;
- tree->isleaf = 1;
- tree->nextLeaf = NULL;
- tree->prevLeaf = bvh->leaf_tree;
- tree->parent = NULL;
- tree->count_nodes = 0;
-
- if(i==0)
- {
- bvh->leaf_tree = bvh->leaf_root = tree;
- }
- else
- {
- bvh->leaf_tree->nextLeaf = tree;
- bvh->leaf_tree = bvh->leaf_tree->nextLeaf;
- }
-
- tree->nodes[0] = tree->nodes[1] = tree->nodes[2] = tree->nodes[3] = NULL;
-
- bvh_calc_DOP_hull_static(bvh, &face_list[i], 1, tree->bv, tree);
-
- // inflate the bv with some epsilon
- for (j = KDOP_START; j < KDOP_END; j++)
- {
- tree->bv[(2 * j)] -= bvh->epsilon; // minimum
- tree->bv[(2 * j) + 1] += bvh->epsilon; // maximum
- }
-
- nlink = tnlink;
- }
-
- // build root bvh
- bvh_calc_DOP_hull_from_faces(bvh, face_list, bvh->numfaces, bvh->root->bv);
-
- // This is the traversal function.
- bvh_div_env_node(bvh, bvh->root, face_list, 0, bvh->numfaces-1, 0, nlink);
- if (face_list)
- MEM_freeN(face_list);
-
- }
-
-}
-
-// bvh_overlap - is it possbile for 2 bv's to collide ?
-DO_INLINE int bvh_overlap(float *bv1, float *bv2)
-{
- int i = 0;
- for (i = KDOP_START; i < KDOP_END; i++)
- {
- // Minimum test.
- if (bv1[(2 * i)] > bv2[(2 * i) + 1])
- {
- return 0;
- }
- // Maxiumum test.
- if (bv2[(2 * i)] > bv1[(2 * i) + 1])
- {
- return 0;
- }
- }
-
- return 1;
-}
-
-// bvh_overlap_self - is it possbile for 2 bv's to selfcollide ?
-DO_INLINE int bvh_overlap_self(CollisionTree * tree1, CollisionTree * tree2)
-{
- // printf("overlap: %f, q: %f\n", (saacos(INPR(tree1->normal, tree2->normal)) / 2.0)+MAX2(tree1->alpha, tree2->alpha), saacos(INPR(tree1->normal, tree2->normal)));
-
- if((saacos(INPR(tree1->normal, tree2->normal)) / 2.0)+MAX2(tree1->alpha, tree2->alpha) > M_PI)
- {
- return 1;
- }
- else
- return 0;
-}
-
-/**
- * bvh_traverse - traverse two bvh trees looking for potential collisions.
- *
- * max collisions are n*n collisions --> every triangle collide with
- * every other triangle that doesn't require any realloc, but uses
- * much memory
- */
-int bvh_traverse ( ModifierData * md1, ModifierData * md2, CollisionTree * tree1, CollisionTree * tree2, float step, CM_COLLISION_RESPONSE collision_response, int selfcollision)
-{
- int i = 0, ret=0, overlap = 0;
-
- /*
- // Shouldn't be possible
- if(!tree1 || !tree2)
- {
- printf("Error: no tree there\n");
- return 0;
-}
- */
-
- if(selfcollision)
- overlap = bvh_overlap_self(tree1, tree2);
- else
- overlap = bvh_overlap(tree1->bv, tree2->bv);
-
- if (overlap)
- {
- // Check if this node in the first tree is a leaf
- if (tree1->isleaf)
- {
- // Check if this node in the second tree a leaf
- if (tree2->isleaf)
- {
- // Provide the collision response.
-
- if(collision_response)
- collision_response (md1, md2, tree1, tree2);
- return 1;
- }
- else
- {
- // Process the quad tree.
- for (i = 0; i < 4; i++)
- {
- // Only traverse nodes that exist.
- if (tree2->nodes[i] && bvh_traverse (md1, md2, tree1, tree2->nodes[i], step, collision_response, selfcollision))
- ret = 1;
- }
- }
- }
- else
- {
- // Process the quad tree.
- for (i = 0; i < 4; i++)
- {
- // Only traverse nodes that exist.
- if (tree1->nodes [i] && bvh_traverse (md1, md2, tree1->nodes[i], tree2, step, collision_response, selfcollision))
- ret = 1;
- }
- }
- }
-
- return ret;
-}
-// bottom up update of bvh tree:
-// join the 4 children here
-void bvh_join(CollisionTree *tree)
-{
- int i = 0, j = 0;
- float max = 0;
-
- if (!tree)
- return;
-
- for (i = 0; i < 4; i++)
- {
- if (tree->nodes[i])
- {
- for (j = KDOP_START; j < KDOP_END; j++)
- {
- // update minimum
- if ((tree->nodes[i]->bv[(2 * j)] < tree->bv[(2 * j)]) || (i == 0))
- {
- tree->bv[(2 * j)] = tree->nodes[i]->bv[(2 * j)];
- }
- // update maximum
- if ((tree->nodes[i]->bv[(2 * j) + 1] > tree->bv[(2 * j) + 1])|| (i == 0))
- {
- tree->bv[(2 * j) + 1] = tree->nodes[i]->bv[(2 * j) + 1];
- }
- }
-
- /* for selfcollisions */
- /*
- if(!i)
- {
- tree->alpha = tree->nodes[i]->alpha;
- VECCOPY(tree->normal, tree->nodes[i]->normal);
- }
- else
- {
- tree->alpha += saacos(INPR(tree->normal, tree->nodes[i]->normal)) / 2.0;
- VECADD(tree->normal, tree->normal, tree->nodes[i]->normal);
- VecMulf(tree->normal, 0.5);
- max = MAX2(max, tree->nodes[i]->alpha);
- }
- */
-
- }
- else
- break;
- }
-
- tree->alpha += max;
-}
-
-// update static bvh
-/* you have to update the bvh position before calling this function */
-void bvh_update(BVH * bvh, int moving)
-{
- CollisionTree *leaf, *parent;
- int traversecheck = 1; // if this is zero we don't go further
- unsigned int j = 0;
-
- for (leaf = bvh->leaf_root; leaf; leaf = leaf->nextLeaf)
- {
- traversecheck = 1;
- if ((leaf->parent) && (leaf->parent->traversed == leaf->parent->count_nodes))
- {
- leaf->parent->traversed = 0;
- }
- if(!moving)
- bvh_calc_DOP_hull_static(bvh, &leaf, 1, leaf->bv, leaf);
- else
- bvh_calc_DOP_hull_moving(bvh, &leaf, 1, leaf->bv, leaf);
-
- // inflate the bv with some epsilon
- for (j = KDOP_START; j < KDOP_END; j++)
- {
- leaf->bv[(2 * j)] -= bvh->epsilon; // minimum
- leaf->bv[(2 * j) + 1] += bvh->epsilon; // maximum
- }
-
- for (parent = leaf->parent; parent; parent = parent->parent)
- {
- if (traversecheck)
- {
- parent->traversed++; // we tried to go up in hierarchy
- if (parent->traversed < parent->count_nodes)
- {
- traversecheck = 0;
-
- if (parent->parent)
- {
- if (parent->parent->traversed == parent->parent->count_nodes)
- {
- parent->parent->traversed = 0;
- }
- }
- break; // we do not need to check further
- }
- else
- {
- bvh_join(parent);
- }
- }
-
- }
- }
-}
-
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index f9f17e7762d..067108ac8cb 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -58,6 +58,7 @@
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
+#include "DNA_sph_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "DNA_object_force.h"
@@ -90,6 +91,7 @@
#include "BKE_object.h"
#include "BKE_mesh.h"
#include "BKE_softbody.h"
+#include "BKE_sph.h"
#include "BKE_cloth.h"
#include "BKE_material.h"
#include "BKE_particle.h"
@@ -5180,6 +5182,89 @@ static void clothModifier_freeData(ModifierData *md)
}
}
+/* Smooth Particly Hydrodynamics */
+
+static void sphModifier_initData(ModifierData *md)
+{
+ SphModifierData *sphmd = (SphModifierData*) md;
+
+ sphmd->sim_parms = MEM_callocN(sizeof(SphSimSettings), "SPH sim parms");
+ sphmd->coll_parms = MEM_callocN(sizeof(SphCollSettings), "SPH coll parms");
+
+ /* check for alloc failing */
+ if(!sphmd->sim_parms || !sphmd->coll_parms)
+ return;
+
+ sph_init(sphmd);
+}
+
+static DerivedMesh *sphModifier_applyModifier(ModifierData *md, Object *ob,
+ DerivedMesh *derivedData, int useRenderParams, int isFinalCalc)
+{
+ SphModifierData *sphmd = (SphModifierData*) md;
+ DerivedMesh *result=NULL;
+
+ /* check for alloc failing */
+ if(!sphmd->sim_parms || !sphmd->coll_parms)
+ return derivedData;
+
+ result = sphModifier_do(sphmd, ob, derivedData, useRenderParams, isFinalCalc);
+
+ if(result)
+ {
+ CDDM_calc_normals(result);
+ return result;
+ }
+
+ return derivedData;
+}
+
+static void sphModifier_updateDepgraph(
+ ModifierData *md, DagForest *forest, Object *ob,
+ DagNode *obNode)
+{
+ SphModifierData *sphmd = (SphModifierData*) md;
+
+ Base *base;
+
+}
+
+CustomDataMask sphModifier_requiredDataMask(ModifierData *md)
+{
+ CustomDataMask dataMask = 0;
+
+ /* ask for vertexgroups if we need them */
+ dataMask |= (1 << CD_MDEFORMVERT);
+
+ return dataMask;
+}
+
+static void sphModifier_copyData(ModifierData *md, ModifierData *target)
+{
+
+}
+
+
+static int sphModifier_dependsOnTime(ModifierData *md)
+{
+ return 1;
+}
+
+static void sphModifier_freeData(ModifierData *md)
+{
+ SphModifierData *sphmd = (SphModifierData*) md;
+
+ if (sphmd)
+ {
+ sph_free_modifier(sphmd);
+
+ if(sphmd->sim_parms)
+ MEM_freeN(sphmd->sim_parms);
+ if(sphmd->coll_parms)
+ MEM_freeN(sphmd->coll_parms);
+ }
+}
+
/* Collision */
static void collisionModifier_initData(ModifierData *md)
@@ -5193,7 +5278,7 @@ static void collisionModifier_initData(ModifierData *md)
collmd->current_v = NULL;
collmd->time = -1;
collmd->numverts = 0;
- collmd->bvh = NULL;
+ collmd->bvhtree = NULL;
}
static void collisionModifier_freeData(ModifierData *md)
@@ -5202,8 +5287,8 @@ static void collisionModifier_freeData(ModifierData *md)
if (collmd)
{
- if(collmd->bvh)
- bvh_free(collmd->bvh);
+ if(collmd->bvhtree)
+ BLI_bvhtree_free(collmd->bvhtree);
if(collmd->x)
MEM_freeN(collmd->x);
if(collmd->xnew)
@@ -5214,7 +5299,6 @@ static void collisionModifier_freeData(ModifierData *md)
MEM_freeN(collmd->current_xnew);
if(collmd->current_v)
MEM_freeN(collmd->current_v);
-
if(collmd->mfaces)
MEM_freeN(collmd->mfaces);
@@ -5225,7 +5309,7 @@ static void collisionModifier_freeData(ModifierData *md)
collmd->current_v = NULL;
collmd->time = -1;
collmd->numverts = 0;
- collmd->bvh = NULL;
+ collmd->bvhtree = NULL;
collmd->mfaces = NULL;
}
}
@@ -5293,9 +5377,8 @@ static void collisionModifier_deformVerts(
collmd->mfaces = dm->dupFaceArray(dm);
collmd->numfaces = dm->getNumFaces(dm);
- // TODO: epsilon
// create bounding box hierarchy
- collmd->bvh = bvh_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->x, numverts, ob->pd->pdef_sboft);
+ collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->x, numverts, ob->pd->pdef_sboft);
collmd->time = current_time;
}
@@ -5318,25 +5401,25 @@ static void collisionModifier_deformVerts(
memcpy(collmd->current_x, collmd->x, numverts*sizeof(MVert));
/* check if GUI setting has changed for bvh */
- if(collmd->bvh)
+ if(collmd->bvhtree)
{
- if(ob->pd->pdef_sboft != collmd->bvh->epsilon)
+ if(ob->pd->pdef_sboft != BLI_bvhtree_getepsilon(collmd->bvhtree))
{
- bvh_free(collmd->bvh);
- collmd->bvh = bvh_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft);
+ BLI_bvhtree_free(collmd->bvhtree);
+ collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft);
}
}
- /* happens on file load (ONLY when i decomment changes in readfile.c */
- if(!collmd->bvh)
+ /* happens on file load (ONLY when i decomment changes in readfile.c) */
+ if(!collmd->bvhtree)
{
- collmd->bvh = bvh_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft);
+ collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft);
}
else
{
// recalc static bounding boxes
- bvh_update_from_mvert(collmd->bvh, collmd->current_x, numverts, NULL, 0);
+ bvhtree_update_from_mvert ( collmd->bvhtree, collmd->mfaces, collmd->numfaces, collmd->current_x, collmd->current_xnew, collmd->numverts, 1 );
}
collmd->time = current_time;
@@ -7137,6 +7220,18 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
mti->requiredDataMask = bevelModifier_requiredDataMask;
mti->applyModifier = bevelModifier_applyModifier;
mti->applyModifierEM = bevelModifier_applyModifierEM;
+
+ mti = INIT_TYPE(Sph);
+ mti->type = eModifierTypeType_Nonconstructive;
+ mti->flags = eModifierTypeFlag_AcceptsMesh
+ | eModifierTypeFlag_UsesPointCache;
+ mti->initData = sphModifier_initData;
+ mti->copyData = sphModifier_copyData;
+ mti->requiredDataMask = sphModifier_requiredDataMask;
+ mti->applyModifier = sphModifier_applyModifier;
+ mti->dependsOnTime = sphModifier_dependsOnTime;
+ mti->freeData = sphModifier_freeData;
+ mti->updateDepgraph = sphModifier_updateDepgraph;
mti = INIT_TYPE(Displace);
mti->type = eModifierTypeType_OnlyDeform;
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 5112fb08fe6..257e3317215 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -46,6 +46,7 @@
#include "DNA_curve_types.h"
#include "DNA_group_types.h"
#include "DNA_scene_types.h"
+#include "DNA_sph_types.h"
#include "DNA_texture_types.h"
#include "BLI_rand.h"
@@ -74,6 +75,7 @@
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_scene.h"
+#include "BKE_sph.h"
#include "BSE_headerbuttons.h"
@@ -4636,6 +4638,50 @@ static void particles_fluid_step(Object *ob, ParticleSystem *psys, int cfra)
snprintf(debugStrBuffer,256,"readFsPartData::done - particles:%d, active:%d, file:%d, mask:%d \n", psys->totpart,activeParts,fileParts,readMask);
elbeemDebugOut(debugStrBuffer);
} // fluid sim particles done
+ else
+ {
+ // check for sph modifier
+ SphModifierData *sphmd = (SphModifierData *)modifiers_findByType(ob, eModifierType_Sph);
+
+ // check for an sph object
+ if(sphmd)
+ {
+ // check for existing coordinates
+ if(sphmd->sim_parms->co)
+ {
+ int i = 0;
+ ParticleSettings *part = psys->part;
+ ParticleData *pa=0;
+ float null[3] = {0,0,0};
+
+ if(ob==G.obedit) // off...
+ return;
+
+ part->totpart= sphmd->sim_parms->numpart;
+ part->sta=part->end = 1.0f;
+ part->lifetime = G.scene->r.efra + 1;
+
+ /* initialize particles */
+ realloc_particles(ob, psys, part->totpart);
+ initialize_all_particles(ob, psys, 0);
+
+ printf("sphmd->sim_parms->numpart: %ld\n", sphmd->sim_parms->numpart);
+
+ for(i = 0, pa=psys->particles; i < sphmd->sim_parms->numpart; i++, pa++)
+ {
+ pa->size = 0.01f;
+ VECCOPY(pa->state.co, sphmd->sim_parms->co + i*3);
+ VECCOPY(pa->state.vel, null);
+
+ pa->state.ave[0] = pa->state.ave[1] = pa->state.ave[2] = 0.0f;
+ pa->state.rot[0] = 1.0;
+ pa->state.rot[1] = pa->state.rot[2] = pa->state.rot[3] = 0.0;
+
+ pa->alive = PARS_ALIVE;
+ }
+ }
+ }
+ }
#endif // DISABLE_ELBEEM
}
diff --git a/source/blender/blenkernel/intern/sph.c b/source/blender/blenkernel/intern/sph.c
new file mode 100644
index 00000000000..3db1a361d5c
--- /dev/null
+++ b/source/blender/blenkernel/intern/sph.c
@@ -0,0 +1,490 @@
+/* pw.c
+*
+*
+* ***** 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) Blender Foundation
+* All rights reserved.
+*
+* Contributor(s): Daniel Genrich
+*
+* ***** END GPL/BL DUAL LICENSE BLOCK *****
+*/
+
+#include <malloc.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BKE_sph.h"
+
+#include "DNA_sph_types.h"
+
+#include "sph_extern.h"
+
+#include "DNA_effect_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_particle_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_cdderivedmesh.h"
+#include "BKE_effect.h"
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_particle.h"
+
+
+// necessary
+#include "float.h"
+#include "math.h"
+#include "BLI_kdtree.h"
+#include "BLI_arithb.h"
+
+// #include "omp.h"
+
+#ifdef _WIN32
+void ststart ( void )
+{}
+void stend ( void )
+{
+}
+double stval()
+{
+ return 0;
+}
+#else
+#include <sys/time.h>
+
+static struct timeval _ststart, _stend;
+static struct timezone stz;
+
+void ststart(void)
+{
+ gettimeofday(&_ststart, &stz);
+}
+void stend(void)
+{
+ gettimeofday(&_stend,&stz);
+}
+double stval()
+{
+ double t1, t2;
+ t1 = (double)_ststart.tv_sec + (double)_ststart.tv_usec/(1000*1000);
+ t2 = (double)_stend.tv_sec + (double)_stend.tv_usec/(1000*1000);
+ return t2-t1;
+}
+#endif
+
+void sph_init (SphModifierData *sphmd)
+{
+ /* fill modifier with standard settings */
+ sphmd->sim_parms->timestep = 0.001; // 0.001
+ sphmd->sim_parms->viscosity = 80000.0;
+ sphmd->sim_parms->incompressibility = 8000000.0;
+ sphmd->sim_parms->surfacetension = 8000.0;
+ sphmd->sim_parms->density = 1000.0;
+ sphmd->sim_parms->gravity[2] = -9.81;
+ sphmd->sim_parms->gravity[1] = 0.0;
+ sphmd->sim_parms->gravity[0] = 0.0;
+ sphmd->sim_parms->samplingdistance = 0.02; // length of one cell? 0.01
+ sphmd->sim_parms->smoothinglength = 2.5;
+ sphmd->sim_parms->flags = SPH_SIMSETTINGS_FLAG_GHOSTS | SPH_SIMSETTINGS_FLAG_OFFLINE | SPH_SIMSETTINGS_FLAG_MULTIRES | SPH_SIMSETTINGS_FLAG_DOMAIN;
+ sphmd->sim_parms->computesurfaceevery = 5; // 30000000
+ sphmd->sim_parms->fastmarchingevery = 5;
+ sphmd->sim_parms->dumppovrayevery = 300000;
+ sphmd->sim_parms->dumpimageevery = 30;
+ sphmd->sim_parms->totaltime = 0.01; // 40.0
+ sphmd->sim_parms->tangentialfriction = 0.1;
+ sphmd->sim_parms->normalfriction = 0.95;
+ sphmd->sim_parms->initiallevel = 1;
+ sphmd->sim_parms->rotation_angle = 0.0;
+
+ sphmd->sim_parms->rotation_axis[0] = 1.0;
+ sphmd->sim_parms->rotation_axis[1] = 1.0;
+ sphmd->sim_parms->rotation_axis[2] = 1.0;
+
+ sphmd->sim_parms->rotation_center[0] = 0.0;
+ sphmd->sim_parms->rotation_center[1] = 0.0;
+ sphmd->sim_parms->rotation_center[2] = 0.0;
+
+ sphmd->sim_parms->scenelowerbound[0] = -1.0;
+ sphmd->sim_parms->scenelowerbound[1] = -1.0;
+ sphmd->sim_parms->scenelowerbound[2] = -1.0;
+
+ sphmd->sim_parms->sceneupperbound[0] = 1.0;
+ sphmd->sim_parms->sceneupperbound[1] = 1.0;
+ sphmd->sim_parms->sceneupperbound[2] = 1.0;
+
+ sphmd->sim_parms->alpha = 2.0;
+ sphmd->sim_parms->beta = 3.0;
+ sphmd->sim_parms->gamma = 1.5;
+
+ sphmd->sim_parms->numverts = 0;
+ sphmd->sim_parms->numtris = 0;
+ sphmd->sim_parms->verts = NULL;
+ sphmd->sim_parms->tris = NULL;
+ sphmd->sim_parms->normals = NULL;
+
+ sphmd->sim_parms->resolution = 70;
+
+ sphmd->sim_parms->co = NULL;
+ sphmd->sim_parms->r = NULL;
+ sphmd->sim_parms->numpart = 0;
+}
+
+void sph_free_modifier (SphModifierData *sphmd)
+{
+
+ // sph_free_cpp(sphmd);
+
+ if(sphmd->sim_parms->verts)
+ free(sphmd->sim_parms->verts);
+ if(sphmd->sim_parms->tris)
+ free(sphmd->sim_parms->tris);
+ if(sphmd->sim_parms->normals)
+ free(sphmd->sim_parms->normals);
+ if(sphmd->sim_parms->co)
+ MEM_freeN(sphmd->sim_parms->co);
+ if(sphmd->sim_parms->r)
+ free(sphmd->sim_parms->r);
+
+}
+
+
+DerivedMesh *sphModifier_do(SphModifierData *sphmd,Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc)
+{
+ SphSimSettings *sim_parms = sphmd->sim_parms;
+ DerivedMesh *result = NULL;
+ MVert *mvert = NULL;
+ MFace *mface = NULL;
+ int a = 0;
+ float mat[4][4], imat[4][4];
+ Mat4CpyMat4(mat, ob->obmat);
+ Mat4Invert(imat, mat);
+
+ // only domain is simulated
+ if(!(sim_parms->flags & SPH_SIMSETTINGS_FLAG_DOMAIN) && !(sim_parms->flags & SPH_SIMSETTINGS_FLAG_BAKING))
+ {
+ return dm;
+ }
+
+ ststart();
+
+ if(!(sim_parms->flags & SPH_SIMSETTINGS_FLAG_INIT))
+ {
+ if(!sph_init_all (sphmd, dm, ob))
+ {
+ sphmd->sim_parms->flags &= ~SPH_SIMSETTINGS_FLAG_INIT;
+ return dm;
+ }
+ }
+
+
+
+ // sph_simulate_cpp(ob, sphmd, 1.0, NULL);
+
+ stend();
+
+ printf ( "SPH simulation time: %f\n", ( float ) stval() );
+
+ if(sim_parms->numverts && sim_parms->numtris)
+ {
+
+
+ result = CDDM_new ( sim_parms->numverts, 0, sim_parms->numtris);
+
+ // copy verts
+ mvert = CDDM_get_verts(result);
+ for(a=0; a<sim_parms->numverts; a++) {
+ MVert *mv = &mvert[a];
+ float *vbCo = &sim_parms->verts[a*3];
+ VECCOPY(mv->co, vbCo);
+ Mat4MulVecfl(imat, mv->co);
+ }
+
+ mface = CDDM_get_faces(result);
+ for(a=0; a<sim_parms->numtris; a++) {
+ MFace *mf = &mface[a];
+ int *tri = &sim_parms->tris[a*3];
+ mf->v1 = tri[0];
+ mf->v2 = tri[1];
+ mf->v3 = tri[2];
+ test_index_face(mf, NULL, 0, 3);
+ }
+
+ CDDM_calc_edges ( result );
+ CDDM_calc_normals ( result );
+
+ return result;
+ }
+ else
+ return dm;
+}
+
+static void set_min_max(float *min, float *max, float *co)
+{
+ // also calc min + max of bounding box for 3d grid
+ min[0] = MIN2(min[0], co[0]);
+ min[1] = MIN2(min[1], co[1]);
+ min[2] = MIN2(min[2], co[2]);
+
+ max[0] = MAX2(max[0], co[0]);
+ max[1] = MAX2(max[1], co[1]);
+ max[2] = MAX2(max[2], co[2]);
+}
+
+long calc_distance_field(Object *ob, DerivedMesh *dm, SphModifierData *sphmd, float mat[4][4])
+{
+ int numverts = dm->getNumVerts(dm);
+ int numfaces = dm->getNumFaces(dm);
+ MVert *mvert = dm->getVertArray(dm);
+ MFace *mface = dm->getFaceArray(dm);
+ int i, j, k;
+ KDTree *tree;
+ float co[3], co1[3], co2[3], co3[3], co4[3];
+ int index;
+ float min[3] = {FLT_MAX, FLT_MAX, FLT_MAX}, max[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX}, slice, maxdir;
+ int resx, resy, resz;
+ int maxres = 20;
+ float *dist;
+ float *normals;
+ int totpart = 0;
+ float *cos = NULL;
+ int maxpart = 0;
+
+ printf("calc_distance_field\n");
+
+ dist = MEM_callocN(maxres*maxres*maxres*sizeof(float), "distance_field");
+ normals = MEM_callocN(numfaces*3*sizeof(float), "triangle_normals");
+
+ /////////////////////////////////////////////////
+ // create + fill + balance kdtree
+ /////////////////////////////////////////////////
+ tree = BLI_kdtree_new(numverts);
+ for(i = 0; i < numfaces; i++)
+ {
+ VECCOPY(co1, mvert[mface[i].v1].co);
+ Mat4MulVecfl(mat, co1);
+ set_min_max(min, max, co1);
+ VECCOPY(co2, mvert[mface[i].v2].co);
+ Mat4MulVecfl(mat, co2);
+ set_min_max(min, max, co2);
+ VECCOPY(co3, mvert[mface[i].v3].co);
+ Mat4MulVecfl(mat, co3);
+ set_min_max(min, max, co3);
+
+ // calc triangle center
+ VECCOPY(co, co1);
+ VECADD(co, co, co2);
+ VECADD(co, co, co3);
+ if(mface[i].v4)
+ {
+ VECCOPY(co4, mvert[mface[i].v4].co);
+ Mat4MulVecfl(mat, co4);
+ set_min_max(min, max, co4);
+ VECADD(co, co, co4);
+ VecMulf(co, 0.25);
+ }
+ else
+ VecMulf(co, 1.0 / 3.0);
+
+ if(mface[i].v4)
+ CalcNormFloat4(mvert[mface[i].v1].co, mvert[mface[i].v2].co, mvert[mface[i].v3].co, mvert[mface[i].v4].co, &normals[i*3]);
+ else
+ CalcNormFloat(mvert[mface[i].v1].co, mvert[mface[i].v2].co, mvert[mface[i].v3].co, &normals[i*3]);
+
+ BLI_kdtree_insert(tree, i, co, NULL);
+ }
+ BLI_kdtree_balance(tree);
+ /////////////////////////////////////////////////
+
+ // calculate slice height + width
+ maxdir = max[0] - min[0];
+ maxdir = MAX2(max[1]-min[1], maxdir);
+ maxdir = MAX2(max[2]-min[2], maxdir);
+ slice = maxdir / (float)maxres;
+ resx = MIN2(maxres, ceil((max[0] - min[0]) / slice));
+ resy = MIN2(maxres, ceil((max[1] - min[1]) / slice));
+ resz = MIN2(maxres, ceil((max[2] - min[2]) / slice));
+
+ // adjust max
+ max[0] = min[0] + slice * resx;
+ max[1] = min[1] + slice * resy;
+ max[2] = min[2] + slice * resz;
+
+ if(sphmd->sim_parms->co)
+ MEM_freeN(sphmd->sim_parms->co);
+
+ cos = sphmd->sim_parms->co = MEM_callocN(sizeof(float)*3*resx*resy*resz, "sph_cos");
+ // r = calloc(1, sizeof(float)*resx*resy*resz);
+ maxpart = sizeof(float)*3*resx*resy*resz;
+
+// #pragma omp parallel for private(i,j,k) schedule(static)
+ for(i = 0; i < resx; i ++)
+ {
+ for(j = 0; j < resy; j++)
+ {
+ for(k = 0; k < resz; k++)
+ {
+ KDTreeNearest nearest;
+ float tco[3];
+ tco[0] = min[0] + slice * i + slice * 0.5;
+ tco[1] = min[1] + slice * j + slice * 0.5;
+ tco[2] = min[2] + slice * k + slice * 0.5;
+
+ index = BLI_kdtree_find_nearest(tree, tco, NULL, &nearest);
+
+ if(index != -1)
+ {
+ float t[3];
+ float sgn;
+
+ VECSUB(t, tco, nearest.co);
+ sgn = INPR(t, &normals[nearest.index*3]);
+
+ if(sgn < 0.0)
+ sgn = -1.0;
+ else
+ sgn = 1.0;
+
+ dist[(i*resy*resz)+(j*resz)+k] = sgn * nearest.dist;
+
+ if((int)sgn < 0)
+ {
+ // create particle if inside object
+ VECCOPY(&cos[totpart*3], tco);
+
+ totpart++;
+ }
+
+ }
+ else
+ {
+ printf("Error: no nearest point!\n");
+ }
+ }
+ }
+ }
+ printf("maxpart: %d, totpart: %d\n", maxpart, totpart);
+
+ sphmd->sim_parms->numpart = totpart;
+ MEM_freeN(dist);
+ MEM_freeN(normals);
+ BLI_kdtree_free(tree);
+ return totpart;
+}
+
+/* add constraints, inflows, fluid, ... */
+int sph_init_all (SphModifierData *sphmd, DerivedMesh *dm, Object *ob)
+{
+ Base *base=NULL;
+ Object *fobject = NULL;
+ SphModifierData *fsphmd = NULL;
+ int fluids = 0; // only one fluid object possible
+ DerivedMesh *fdm = NULL;
+
+ sphmd->sim_parms->flags |= SPH_SIMSETTINGS_FLAG_INIT;
+ CDDM_calc_normals ( dm );
+
+ /* create C++ object */
+ // sph_init_cpp(sphmd);
+ sphmd->sim_parms->numpart = calc_distance_field(ob, dm, sphmd, ob->obmat);
+ return 1;
+
+ /* create fluid domain */
+ // sph_set_domain(sphmd, dm, ob->obmat);
+
+ // check for constraints, fluid, etc. but ignore domains
+ for ( base = G.scene->base.first; base; base = base->next )
+ {
+ fobject = base->object;
+ fsphmd = ( SphModifierData * ) modifiers_findByType ( fobject, eModifierType_Sph );
+
+ // TODO I could check for linked groups, too
+ if ( !fsphmd )
+ {
+ // TODO
+ }
+ else
+ {
+ if(fsphmd == sphmd)
+ continue;
+
+ if(fsphmd->sim_parms)
+ {
+ // check for fluid
+ if(((short)fsphmd->sim_parms->flags == SPH_SIMSETTINGS_FLAG_FLUID) && (!fluids))
+ {
+ // create fluids
+ // particles have to be created AFTER constraints
+ // TODO: no particles = crash
+
+ // get derivedmesh from object
+ fdm = mesh_get_derived_final(fobject, CD_MASK_BAREMESH);
+
+ // create fluid object
+ /*
+ if(!sph_add_particles(sphmd, fdm, fobject->obmat, fsphmd->sim_parms->resolution))
+ {
+ fluids--;
+ }
+ */
+ if(fdm)
+ fdm->release(fdm);
+
+ fluids++;
+ }
+ else if((short)fsphmd->sim_parms->flags & SPH_SIMSETTINGS_FLAG_OBSTACLE)
+ {
+
+ }
+ }
+ }
+ }
+
+ if(!fluids)
+ return 0;
+
+ return 1;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h
new file mode 100644
index 00000000000..c1240da6c3a
--- /dev/null
+++ b/source/blender/blenlib/BLI_kdopbvh.h
@@ -0,0 +1,63 @@
+/**
+ *
+ * ***** 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) 2006 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Daniel Genrich, Andre Pinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+
+#ifndef BLI_KDOPBVH_H
+#define BLI_KDOPBVH_H
+
+#include <float.h>
+
+struct BVHTree;
+typedef struct BVHTree BVHTree;
+
+typedef struct BVHTreeOverlap {
+ int indexA;
+ int indexB;
+} BVHTreeOverlap;
+
+BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis);
+void BLI_bvhtree_free(BVHTree *tree);
+
+/* construct: first insert points, then call balance */
+int BLI_bvhtree_insert(BVHTree *tree, int index, float *co, int numpoints);
+void BLI_bvhtree_balance(BVHTree *tree);
+
+/* update: first update points/nodes, then call update_tree to refit the bounding volumes */
+int BLI_bvhtree_update_node(BVHTree *tree, int index, float *co, float *co_moving, int numpoints);
+void BLI_bvhtree_update_tree(BVHTree *tree);
+
+/* collision/overlap: check two trees if they overlap, alloc's *overlap with length of the int return value */
+BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result);
+
+float BLI_bvhtree_getepsilon(BVHTree *tree);
+
+#endif // BLI_KDOPBVH_H
+
+
+
+
diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c
new file mode 100644
index 00000000000..c884b97b182
--- /dev/null
+++ b/source/blender/blenlib/intern/BLI_kdopbvh.c
@@ -0,0 +1,849 @@
+/* kdop.c
+*
+*
+* ***** 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) Blender Foundation
+* All rights reserved.
+*
+* The Original Code is: all of this file.
+*
+* Contributor(s): Daniel Genrich, Andre Pinto
+*
+* ***** END GPL/BL DUAL LICENSE BLOCK *****
+*/
+
+#include "math.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BKE_utildefines.h"
+
+#include "BLI_kdopbvh.h"
+#include "BLI_arithb.h"
+
+#ifdef _OPENMP
+#include <omp.h>
+#endif
+
+#include <time.h>
+
+/* Util macros */
+#define TO_STR(a) #a
+#define JOIN(a,b) a##b
+
+/* Benchmark macros */
+#if 1
+
+#define BENCH(a) \
+ do { \
+ clock_t _clock_init = clock(); \
+ (a); \
+ printf("%s: %fms\n", #a, (float)(clock()-_clock_init)*1000/CLOCKS_PER_SEC); \
+} while(0)
+
+#define BENCH_VAR(name) clock_t JOIN(_bench_step,name) = 0, JOIN(_bench_total,name) = 0
+#define BENCH_BEGIN(name) JOIN(_bench_step, name) = clock()
+#define BENCH_END(name) JOIN(_bench_total,name) += clock() - JOIN(_bench_step,name)
+#define BENCH_RESET(name) JOIN(_bench_total, name) = 0
+#define BENCH_REPORT(name) printf("%s: %fms\n", TO_STR(name), JOIN(_bench_total,name)*1000.0f/CLOCKS_PER_SEC)
+
+#else
+
+#define BENCH(a) (a)
+#define BENCH_VAR(name)
+#define BENCH_BEGIN(name)
+#define BENCH_END(name)
+#define BENCH_RESET(name)
+#define BENCH_REPORT(name)
+
+#endif
+
+
+typedef struct BVHNode
+{
+ struct BVHNode **children; // max 8 children
+ struct BVHNode *parent; // needed for bottom - top update
+ float *bv; // Bounding volume of all nodes, max 13 axis
+ int index; /* face, edge, vertex index */
+ char totnode; // how many nodes are used, used for speedup
+ char traversed; // how many nodes already traversed until this level?
+ char main_axis;
+} BVHNode;
+
+struct BVHTree
+{
+ BVHNode **nodes;
+ BVHNode *nodearray; /* pre-alloc branch nodes */
+ BVHNode **nodechild; // pre-alloc childs for nodes
+ float *nodebv; // pre-alloc bounding-volumes for nodes
+ float epsilon; /* epslion is used for inflation of the k-dop */
+ int totleaf; // leafs
+ int totbranch;
+ char tree_type; // type of tree (4 => quadtree)
+ char axis; // kdop type (6 => OBB, 7 => AABB, ...)
+ char start_axis, stop_axis; // KDOP_AXES array indices according to axis
+};
+
+typedef struct BVHOverlapData
+{
+ BVHTree *tree1, *tree2;
+ BVHTreeOverlap *overlap;
+ int i, max_overlap; /* i is number of overlaps */
+} BVHOverlapData;
+////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////
+// Bounding Volume Hierarchy Definition
+//
+// Notes: From OBB until 26-DOP --> all bounding volumes possible, just choose type below
+// Notes: You have to choose the type at compile time ITM
+// Notes: You can choose the tree type --> binary, quad, octree, choose below
+////////////////////////////////////////////////////////////////////////
+
+static float KDOP_AXES[13][3] =
+{ {1.0, 0, 0}, {0, 1.0, 0}, {0, 0, 1.0}, {1.0, 1.0, 1.0}, {1.0, -1.0, 1.0}, {1.0, 1.0, -1.0},
+{1.0, -1.0, -1.0}, {1.0, 1.0, 0}, {1.0, 0, 1.0}, {0, 1.0, 1.0}, {1.0, -1.0, 0}, {1.0, 0, -1.0},
+{0, 1.0, -1.0}
+};
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+// Introsort
+// with permission deriven from the following Java code:
+// http://ralphunden.net/content/tutorials/a-guide-to-introsort/
+// and he derived it from the SUN STL
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+static int size_threshold = 16;
+/*
+* Common methods for all algorithms
+*/
+static int floor_lg(int a)
+{
+ return (int)(floor(log(a)/log(2)));
+}
+
+/*
+* Insertion sort algorithm
+*/
+static void bvh_insertionsort(BVHNode **a, int lo, int hi, int axis)
+{
+ int i,j;
+ BVHNode *t;
+ for (i=lo; i < hi; i++)
+ {
+ j=i;
+ t = a[i];
+ while((j!=lo) && (t->bv[axis] < (a[j-1])->bv[axis]))
+ {
+ a[j] = a[j-1];
+ j--;
+ }
+ a[j] = t;
+ }
+}
+
+static int bvh_partition(BVHNode **a, int lo, int hi, BVHNode * x, int axis)
+{
+ int i=lo, j=hi;
+ while (1)
+ {
+ while ((a[i])->bv[axis] < x->bv[axis]) i++;
+ j--;
+ while (x->bv[axis] < (a[j])->bv[axis]) j--;
+ if(!(i < j))
+ return i;
+ SWAP( BVHNode* , a[i], a[j]);
+ i++;
+ }
+}
+
+/*
+* Heapsort algorithm
+*/
+static void bvh_downheap(BVHNode **a, int i, int n, int lo, int axis)
+{
+ BVHNode * d = a[lo+i-1];
+ int child;
+ while (i<=n/2)
+ {
+ child = 2*i;
+ if ((child < n) && ((a[lo+child-1])->bv[axis] < (a[lo+child])->bv[axis]))
+ {
+ child++;
+ }
+ if (!(d->bv[axis] < (a[lo+child-1])->bv[axis])) break;
+ a[lo+i-1] = a[lo+child-1];
+ i = child;
+ }
+ a[lo+i-1] = d;
+}
+
+static void bvh_heapsort(BVHNode **a, int lo, int hi, int axis)
+{
+ int n = hi-lo, i;
+ for (i=n/2; i>=1; i=i-1)
+ {
+ bvh_downheap(a, i,n,lo, axis);
+ }
+ for (i=n; i>1; i=i-1)
+ {
+ SWAP(BVHNode*, a[lo],a[lo+i-1]);
+ bvh_downheap(a, 1,i-1,lo, axis);
+ }
+}
+
+static BVHNode *bvh_medianof3(BVHNode **a, int lo, int mid, int hi, int axis) // returns Sortable
+{
+ if ((a[mid])->bv[axis] < (a[lo])->bv[axis])
+ {
+ if ((a[hi])->bv[axis] < (a[mid])->bv[axis])
+ return a[mid];
+ else
+ {
+ if ((a[hi])->bv[axis] < (a[lo])->bv[axis])
+ return a[hi];
+ else
+ return a[lo];
+ }
+ }
+ else
+ {
+ if ((a[hi])->bv[axis] < (a[mid])->bv[axis])
+ {
+ if ((a[hi])->bv[axis] < (a[lo])->bv[axis])
+ return a[lo];
+ else
+ return a[hi];
+ }
+ else
+ return a[mid];
+ }
+}
+/*
+* Quicksort algorithm modified for Introsort
+*/
+static void bvh_introsort_loop (BVHNode **a, int lo, int hi, int depth_limit, int axis)
+{
+ int p;
+
+ while (hi-lo > size_threshold)
+ {
+ if (depth_limit == 0)
+ {
+ bvh_heapsort(a, lo, hi, axis);
+ return;
+ }
+ depth_limit=depth_limit-1;
+ p=bvh_partition(a, lo, hi, bvh_medianof3(a, lo, lo+((hi-lo)/2)+1, hi-1, axis), axis);
+ bvh_introsort_loop(a, p, hi, depth_limit, axis);
+ hi=p;
+ }
+}
+
+static void sort(BVHNode **a0, int begin, int end, int axis)
+{
+ if (begin < end)
+ {
+ BVHNode **a=a0;
+ bvh_introsort_loop(a, begin, end, 2*floor_lg(end-begin), axis);
+ bvh_insertionsort(a, begin, end, axis);
+ }
+}
+void sort_along_axis(BVHTree *tree, int start, int end, int axis)
+{
+ sort(tree->nodes, start, end, axis);
+}
+
+//after a call to this function you can expect one of:
+// every node to left of a[n] are smaller or equal to it
+// every node to the right of a[n] are greater or equal to it
+int partition_nth_element(BVHNode **a, int _begin, int _end, int n, int axis){
+ int begin = _begin, end = _end, cut;
+ int i;
+ while(end-begin > 3)
+ {
+ cut = bvh_partition(a, begin, end, bvh_medianof3(a, begin, (begin+end)/2, end-1, axis), axis );
+ if(cut <= n)
+ begin = cut;
+ else
+ end = cut;
+ }
+ bvh_insertionsort(a, begin, end, axis);
+
+ return n;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void BLI_bvhtree_free(BVHTree *tree)
+{
+ if(tree)
+ {
+ MEM_freeN(tree->nodes);
+ MEM_freeN(tree->nodearray);
+ MEM_freeN(tree->nodebv);
+ MEM_freeN(tree->nodechild);
+ MEM_freeN(tree);
+ }
+}
+
+BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis)
+{
+ BVHTree *tree;
+ int numbranches=0, i;
+
+ // only support up to octree
+ if(tree_type > 8)
+ return NULL;
+
+ tree = (BVHTree *)MEM_callocN(sizeof(BVHTree), "BVHTree");
+
+ if(tree)
+ {
+ tree->epsilon = epsilon;
+ tree->tree_type = tree_type;
+ tree->axis = axis;
+
+ if(axis == 26)
+ {
+ tree->start_axis = 0;
+ tree->stop_axis = 13;
+ }
+ else if(axis == 18)
+ {
+ tree->start_axis = 7;
+ tree->stop_axis = 13;
+ }
+ else if(axis == 14)
+ {
+ tree->start_axis = 0;
+ tree->stop_axis = 7;
+ }
+ else if(axis == 8) // AABB
+ {
+ tree->start_axis = 0;
+ tree->stop_axis = 4;
+ }
+ else if(axis == 6) // OBB
+ {
+ tree->start_axis = 0;
+ tree->stop_axis = 3;
+ }
+ else
+ {
+ MEM_freeN(tree);
+ return NULL;
+ }
+
+
+ // calculate max number of branches, our bvh kdop is "almost perfect"
+ for(i = 1; i <= (int)ceil((float)((float)log(maxsize)/(float)log(tree_type))); i++)
+ numbranches += (pow(tree_type, i) / tree_type);
+
+ tree->nodes = (BVHNode **)MEM_callocN(sizeof(BVHNode *)*(numbranches+maxsize + tree_type), "BVHNodes");
+
+ if(!tree->nodes)
+ {
+ MEM_freeN(tree);
+ return NULL;
+ }
+
+ tree->nodebv = (float*)MEM_callocN(sizeof(float)* axis * (numbranches+maxsize + tree_type), "BVHNodeBV");
+ if(!tree->nodebv)
+ {
+ MEM_freeN(tree->nodes);
+ MEM_freeN(tree);
+ }
+
+ tree->nodechild = (BVHNode**)MEM_callocN(sizeof(BVHNode*) * tree_type * (numbranches+maxsize + tree_type), "BVHNodeBV");
+ if(!tree->nodechild)
+ {
+ MEM_freeN(tree->nodebv);
+ MEM_freeN(tree->nodes);
+ MEM_freeN(tree);
+ }
+
+ tree->nodearray = (BVHNode *)MEM_callocN(sizeof(BVHNode)*(numbranches+maxsize + tree_type), "BVHNodeArray");
+
+ if(!tree->nodearray)
+ {
+ MEM_freeN(tree->nodechild);
+ MEM_freeN(tree->nodebv);
+ MEM_freeN(tree->nodes);
+ MEM_freeN(tree);
+ return NULL;
+ }
+
+ //link the dynamic bv and child links
+ for(i=0; i< numbranches+maxsize + tree_type; i++)
+ {
+ tree->nodearray[i].bv = tree->nodebv + i * axis;
+ tree->nodearray[i].children = tree->nodechild + i * tree_type;
+ }
+
+ }
+
+ return tree;
+}
+
+
+static void create_kdop_hull(BVHTree *tree, BVHNode *node, float *co, int numpoints, int moving)
+{
+ float newminmax;
+ int i, k;
+
+ // don't init boudings for the moving case
+ if(!moving)
+ {
+ for (i = tree->start_axis; i < tree->stop_axis; i++)
+ {
+ node->bv[2*i] = FLT_MAX;
+ node->bv[2*i + 1] = -FLT_MAX;
+ }
+ }
+
+ for(k = 0; k < numpoints; k++)
+ {
+ // for all Axes.
+ for (i = tree->start_axis; i < tree->stop_axis; i++)
+ {
+ newminmax = INPR(&co[k * 3], KDOP_AXES[i]);
+ if (newminmax < node->bv[2 * i])
+ node->bv[2 * i] = newminmax;
+ if (newminmax > node->bv[(2 * i) + 1])
+ node->bv[(2 * i) + 1] = newminmax;
+ }
+ }
+}
+
+// depends on the fact that the BVH's for each face is already build
+static void refit_kdop_hull(BVHTree *tree, BVHNode *node, int start, int end)
+{
+ float newmin,newmax;
+ int i, j;
+ float *bv = node->bv;
+
+ for (i = tree->start_axis; i < tree->stop_axis; i++)
+ {
+ bv[2*i] = FLT_MAX;
+ bv[2*i + 1] = -FLT_MAX;
+ }
+
+ for (j = start; j < end; j++)
+ {
+ // for all Axes.
+ for (i = tree->start_axis; i < tree->stop_axis; i++)
+ {
+ newmin = tree->nodes[j]->bv[(2 * i)];
+ if ((newmin < bv[(2 * i)]))
+ bv[(2 * i)] = newmin;
+
+ newmax = tree->nodes[j]->bv[(2 * i) + 1];
+ if ((newmax > bv[(2 * i) + 1]))
+ bv[(2 * i) + 1] = newmax;
+ }
+ }
+}
+
+int BLI_bvhtree_insert(BVHTree *tree, int index, float *co, int numpoints)
+{
+ BVHNode *node= NULL;
+ int i;
+
+ // insert should only possible as long as tree->totbranch is 0
+ if(tree->totbranch > 0)
+ return 0;
+
+ if(tree->totleaf+1 >= MEM_allocN_len(tree->nodes))
+ return 0;
+
+ // TODO check if have enough nodes in array
+
+ node = tree->nodes[tree->totleaf] = &(tree->nodearray[tree->totleaf]);
+ tree->totleaf++;
+
+ create_kdop_hull(tree, node, co, numpoints, 0);
+
+ // inflate the bv with some epsilon
+ for (i = tree->start_axis; i < tree->stop_axis; i++)
+ {
+ node->bv[(2 * i)] -= tree->epsilon; // minimum
+ node->bv[(2 * i) + 1] += tree->epsilon; // maximum
+ }
+
+ node->index= index;
+
+ return 1;
+}
+
+// only supports x,y,z axis in the moment
+// but we should use a plain and simple function here for speed sake
+static char get_largest_axis(float *bv)
+{
+ float middle_point[3];
+
+ middle_point[0] = (bv[1]) - (bv[0]); // x axis
+ middle_point[1] = (bv[3]) - (bv[2]); // y axis
+ middle_point[2] = (bv[5]) - (bv[4]); // z axis
+ if (middle_point[0] > middle_point[1])
+ {
+ if (middle_point[0] > middle_point[2])
+ return 1; // max x axis
+ else
+ return 5; // max z axis
+ }
+ else
+ {
+ if (middle_point[1] > middle_point[2])
+ return 3; // max y axis
+ else
+ return 5; // max z axis
+ }
+}
+
+static void bvh_div_nodes(BVHTree *tree, BVHNode *node, int start, int end, char lastaxis)
+{
+ char laxis;
+ int i, tend;
+ BVHNode *tnode;
+ int slice = (end-start+tree->tree_type-1)/tree->tree_type; //division rounded up
+
+ // Determine which axis to split along
+ laxis = get_largest_axis(node->bv);
+
+ // split nodes along longest axis
+ for (i=0; start < end; start += slice, i++) //i counts the current child
+ {
+ tend = start + slice;
+
+ if(tend > end) tend = end;
+
+ if(tend-start == 1) // ok, we have 1 left for this node
+ {
+ node->children[i] = tree->nodes[start];
+ node->children[i]->parent = node;
+ }
+ else
+ {
+ tnode = node->children[i] = tree->nodes[tree->totleaf + tree->totbranch] = &(tree->nodearray[tree->totbranch + tree->totleaf]);
+ tree->totbranch++;
+ tnode->parent = node;
+
+ if(tend != end)
+ partition_nth_element(tree->nodes, start, end, tend, laxis);
+ refit_kdop_hull(tree, tnode, start, tend);
+ bvh_div_nodes(tree, tnode, start, tend, laxis);
+ }
+ node->totnode++;
+ }
+
+ return;
+}
+
+static void verify_tree(BVHTree *tree)
+{
+ int i, j, check = 0;
+
+ // check the pointer list
+ for(i = 0; i < tree->totleaf; i++)
+ {
+ if(tree->nodes[i]->parent == NULL)
+ printf("Leaf has no parent: %d\n", i);
+ else
+ {
+ for(j = 0; j < tree->tree_type; j++)
+ {
+ if(tree->nodes[i]->parent->children[j] == tree->nodes[i])
+ check = 1;
+ }
+ if(!check)
+ {
+ printf("Parent child relationship doesn't match: %d\n", i);
+ }
+ check = 0;
+ }
+ }
+
+ // check the leaf list
+ for(i = 0; i < tree->totleaf; i++)
+ {
+ if(tree->nodearray[i].parent == NULL)
+ printf("Leaf has no parent: %d\n", i);
+ else
+ {
+ for(j = 0; j < tree->tree_type; j++)
+ {
+ if(tree->nodearray[i].parent->children[j] == &tree->nodearray[i])
+ check = 1;
+ }
+ if(!check)
+ {
+ printf("Parent child relationship doesn't match: %d\n", i);
+ }
+ check = 0;
+ }
+ }
+
+ printf("branches: %d, leafs: %d, total: %d\n", tree->totbranch, tree->totleaf, tree->totbranch + tree->totleaf);
+}
+
+void BLI_bvhtree_balance(BVHTree *tree)
+{
+ BVHNode *node;
+
+ if(tree->totleaf == 0)
+ return;
+
+ // create root node
+ node = tree->nodes[tree->totleaf] = &(tree->nodearray[tree->totleaf]);
+ tree->totbranch++;
+
+ // refit root bvh node
+ refit_kdop_hull(tree, tree->nodes[tree->totleaf], 0, tree->totleaf);
+ // create + balance tree
+ bvh_div_nodes(tree, tree->nodes[tree->totleaf], 0, tree->totleaf, 0);
+
+ // verify_tree(tree);
+}
+
+// overlap - is it possbile for 2 bv's to collide ?
+static int tree_overlap(float *bv1, float *bv2, int start_axis, int stop_axis)
+{
+ float *bv1_end = bv1 + (stop_axis<<1);
+
+ bv1 += start_axis<<1;
+ bv2 += start_axis<<1;
+
+ // test all axis if min + max overlap
+ for (; bv1 != bv1_end; bv1+=2, bv2+=2)
+ {
+ if ((*(bv1) > *(bv2 + 1)) || (*(bv2) > *(bv1 + 1)))
+ return 0;
+ }
+
+ return 1;
+}
+
+static void traverse(BVHOverlapData *data, BVHNode *node1, BVHNode *node2)
+{
+ int j;
+
+ if(tree_overlap(node1->bv, node2->bv, MIN2(data->tree1->start_axis, data->tree2->start_axis), MIN2(data->tree1->stop_axis, data->tree2->stop_axis)))
+ {
+ // check if node1 is a leaf
+ if(!node1->totnode)
+ {
+ // check if node2 is a leaf
+ if(!node2->totnode)
+ {
+
+ if(node1 == node2)
+ {
+ return;
+ }
+
+ if(data->i >= data->max_overlap)
+ {
+ // try to make alloc'ed memory bigger
+ data->overlap = realloc(data->overlap, sizeof(BVHTreeOverlap)*data->max_overlap*2);
+
+ if(!data->overlap)
+ {
+ printf("Out of Memory in traverse\n");
+ return;
+ }
+ data->max_overlap *= 2;
+ }
+
+ // both leafs, insert overlap!
+ data->overlap[data->i].indexA = node1->index;
+ data->overlap[data->i].indexB = node2->index;
+
+ data->i++;
+ }
+ else
+ {
+ for(j = 0; j < data->tree2->tree_type; j++)
+ {
+ if(node2->children[j])
+ traverse(data, node1, node2->children[j]);
+ }
+ }
+ }
+ else
+ {
+
+ for(j = 0; j < data->tree2->tree_type; j++)
+ {
+ if(node1->children[j])
+ traverse(data, node1->children[j], node2);
+ }
+ }
+ }
+ return;
+}
+
+BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result)
+{
+ int j, total = 0;
+ BVHTreeOverlap *overlap = NULL, *to = NULL;
+ BVHOverlapData **data;
+
+ // check for compatibility of both trees (can't compare 14-DOP with 18-DOP)
+ if((tree1->axis != tree2->axis) && ((tree1->axis == 14) || tree2->axis == 14))
+ return 0;
+
+ // fast check root nodes for collision before doing big splitting + traversal
+ if(!tree_overlap(tree1->nodes[tree1->totleaf]->bv, tree2->nodes[tree2->totleaf]->bv, MIN2(tree1->start_axis, tree2->start_axis), MIN2(tree1->stop_axis, tree2->stop_axis)))
+ return 0;
+
+ data = MEM_callocN(sizeof(BVHOverlapData *)* tree1->tree_type, "BVHOverlapData_star");
+
+ for(j = 0; j < tree1->tree_type; j++)
+ {
+ data[j] = (BVHOverlapData *)MEM_callocN(sizeof(BVHOverlapData), "BVHOverlapData");
+
+ // init BVHOverlapData
+ data[j]->overlap = (BVHTreeOverlap *)malloc(sizeof(BVHTreeOverlap)*MAX2(tree1->totleaf, tree2->totleaf));
+ data[j]->tree1 = tree1;
+ data[j]->tree2 = tree2;
+ data[j]->max_overlap = MAX2(tree1->totleaf, tree2->totleaf);
+ data[j]->i = 0;
+ }
+
+#pragma omp parallel for private(j) schedule(static)
+ for(j = 0; j < tree1->tree_type; j++)
+ {
+ traverse(data[j], tree1->nodes[tree1->totleaf]->children[j], tree2->nodes[tree2->totleaf]);
+ }
+
+ for(j = 0; j < tree1->tree_type; j++)
+ total += data[j]->i;
+
+ to = overlap = (BVHTreeOverlap *)MEM_callocN(sizeof(BVHTreeOverlap)*total, "BVHTreeOverlap");
+
+ for(j = 0; j < tree1->tree_type; j++)
+ {
+ memcpy(to, data[j]->overlap, data[j]->i*sizeof(BVHTreeOverlap));
+ to+=data[j]->i;
+ }
+
+ for(j = 0; j < tree1->tree_type; j++)
+ {
+ free(data[j]->overlap);
+ MEM_freeN(data[j]);
+ }
+ MEM_freeN(data);
+
+ (*result) = total;
+ return overlap;
+}
+
+
+// bottom up update of bvh tree:
+// join the 4 children here
+static void node_join(BVHTree *tree, BVHNode *node)
+{
+ int i, j;
+
+ for (i = tree->start_axis; i < tree->stop_axis; i++)
+ {
+ node->bv[2*i] = FLT_MAX;
+ node->bv[2*i + 1] = -FLT_MAX;
+ }
+
+ for (i = 0; i < tree->tree_type; i++)
+ {
+ if (node->children[i])
+ {
+ for (j = tree->start_axis; j < tree->stop_axis; j++)
+ {
+ // update minimum
+ if (node->children[i]->bv[(2 * j)] < node->bv[(2 * j)])
+ node->bv[(2 * j)] = node->children[i]->bv[(2 * j)];
+
+ // update maximum
+ if (node->children[i]->bv[(2 * j) + 1] > node->bv[(2 * j) + 1])
+ node->bv[(2 * j) + 1] = node->children[i]->bv[(2 * j) + 1];
+ }
+ }
+ else
+ break;
+ }
+}
+
+// call before BLI_bvhtree_update_tree()
+int BLI_bvhtree_update_node(BVHTree *tree, int index, float *co, float *co_moving, int numpoints)
+{
+ BVHNode *node= NULL;
+ int i = 0;
+
+ // check if index exists
+ if(index > tree->totleaf)
+ return 0;
+
+ node = tree->nodearray + index;
+
+ create_kdop_hull(tree, node, co, numpoints, 0);
+
+ if(co_moving)
+ create_kdop_hull(tree, node, co_moving, numpoints, 1);
+
+ // inflate the bv with some epsilon
+ for (i = tree->start_axis; i < tree->stop_axis; i++)
+ {
+ node->bv[(2 * i)] -= tree->epsilon; // minimum
+ node->bv[(2 * i) + 1] += tree->epsilon; // maximum
+ }
+
+ return 1;
+}
+
+// call BLI_bvhtree_update_node() first for every node/point/triangle
+void BLI_bvhtree_update_tree(BVHTree *tree)
+{
+ BVHNode *leaf, *parent;
+
+ // reset tree traversing flag
+ for (leaf = tree->nodearray + tree->totleaf; leaf != tree->nodearray + tree->totleaf + tree->totbranch; leaf++)
+ leaf->traversed = 0;
+
+ for (leaf = tree->nodearray; leaf != tree->nodearray + tree->totleaf; leaf++)
+ {
+ for (parent = leaf->parent; parent; parent = parent->parent)
+ {
+ parent->traversed++; // we tried to go up in hierarchy
+ if (parent->traversed < parent->totnode)
+ break; // we do not need to check further
+ else
+ node_join(tree, parent);
+ }
+ }
+}
+
+float BLI_bvhtree_getepsilon(BVHTree *tree)
+{
+ return tree->epsilon;
+}
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 1cb8b10b087..629de595345 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -3075,6 +3075,7 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
clmd->sim_parms= newdataadr(fd, clmd->sim_parms);
clmd->coll_parms= newdataadr(fd, clmd->coll_parms);
+
clmd->point_cache= newdataadr(fd, clmd->point_cache);
if(clmd->point_cache)
@@ -3084,22 +3085,16 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
if(clmd->sim_parms->presets > 10)
clmd->sim_parms->presets = 0;
}
+ else
+ {
+ /* Collision modifier without parameters?? */
+
+ }
}
else if (md->type==eModifierType_Collision) {
CollisionModifierData *collmd = (CollisionModifierData*) md;
- /*
- // TODO: CollisionModifier should use pointcache
- // + have proper reset events before enabling this
- collmd->x = newdataadr(fd, collmd->x);
- collmd->xnew = newdataadr(fd, collmd->xnew);
- collmd->mfaces = newdataadr(fd, collmd->mfaces);
-
- collmd->current_x = MEM_callocN(sizeof(MVert)*collmd->numverts,"current_x");
- collmd->current_xnew = MEM_callocN(sizeof(MVert)*collmd->numverts,"current_xnew");
- collmd->current_v = MEM_callocN(sizeof(MVert)*collmd->numverts,"current_v");
- */
collmd->x = NULL;
collmd->xnew = NULL;
@@ -3108,9 +3103,8 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
collmd->current_v = NULL;
collmd->time = -1;
collmd->numverts = 0;
- collmd->bvh = NULL;
+ collmd->bvhtree = NULL;
collmd->mfaces = NULL;
-
}
else if (md->type==eModifierType_Hook) {
HookModifierData *hmd = (HookModifierData*) md;
diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h
index 7571d64be91..058e4243b96 100644
--- a/source/blender/include/butspace.h
+++ b/source/blender/include/butspace.h
@@ -297,6 +297,10 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la
/* Cloth sim button defines */
#define B_CLOTH_CHANGEPREROLL 1480
+/* SPH sim button defines */
+#define B_SPH_BAKE 1490
+
+
/* *********************** */
#define B_WORLDBUTS 1600
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index b7b43817474..b2d6e8e5756 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -35,6 +35,7 @@ typedef enum ModifierType {
eModifierType_Cloth,
eModifierType_Collision,
eModifierType_Bevel,
+ eModifierType_Sph,
NUM_MODIFIER_TYPES
} ModifierType;
@@ -374,6 +375,14 @@ typedef struct ClothModifierData {
struct PointCache *point_cache; /* definition is in DNA_object_force.h */
} ClothModifierData;
+typedef struct SphModifierData {
+ ModifierData modifier;
+
+ struct SPH *sph; /* pointer to cpp sph sim */
+ struct SphSimSettings *sim_parms; /* definition is in DNA_sph_types.h */
+ struct SphCollSettings *coll_parms; /* definition is in DNA_sph_types.h */
+} SphModifierData;
+
typedef struct CollisionModifierData {
ModifierData modifier;
@@ -390,7 +399,7 @@ typedef struct CollisionModifierData {
unsigned int numfaces;
int pad;
float time; /* cfra time of modifier */
- struct BVH *bvh; /* bounding volume hierarchy for this cloth object */
+ struct BVHTree *bvhtree; /* bounding volume hierarchy for this cloth object */
} CollisionModifierData;
typedef enum {
diff --git a/source/blender/makesdna/DNA_sph_types.h b/source/blender/makesdna/DNA_sph_types.h
new file mode 100644
index 00000000000..add3053f612
--- /dev/null
+++ b/source/blender/makesdna/DNA_sph_types.h
@@ -0,0 +1,102 @@
+/**
+ * $Id: DNA_cloth_types.h,v 1.1 2007/08/01 02:28:34 daniel Exp $
+ *
+ * ***** 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) 2006 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Daniel (Genscher)
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef DNA_SPH_TYPES_H
+#define DNA_SPH_TYPES_H
+
+// string scene, constraint, backup: missing
+// string _file;
+// string pov;
+// string rendered;
+typedef struct SphSimSettings
+{
+ int flags; // see pw_extern.h
+ float timestep;
+ float viscosity;
+ float incompressibility; /* how incompressible is the fluid? */
+ float surfacetension;
+ float density;
+ float gravity[3]; /* gravity on the domain */
+ float samplingdistance;
+ float smoothinglength;
+
+ float controlviscosity;
+ int dumpimageevery;
+ int computesurfaceevery;
+ int fastmarchingevery;
+ int dumppovrayevery;
+
+ float totaltime;
+
+ float tangentialfriction; /* constraint tangential friction */
+ float normalfriction; /* constraint normal friction */
+
+ float rotation_angle;
+ float rotation_axis[3];
+ float rotation_center[3];
+ float scenelowerbound[3];
+ float sceneupperbound[3];
+
+ int initiallevel;
+
+ float alpha;
+ float beta;
+ float gamma;
+
+ /* needed for better direct resolution input for constraints, fluids,... */
+ int resolution; /* can also be calculated by (Max-Min) / samplingdistance */
+ int pad;
+ float *verts;
+ float *normals;
+ int *tris;
+ unsigned int numverts;
+ unsigned int numtris;
+ float *co; /* particle positions */
+ float *r; /* particle radius */
+ long numpart;
+ int pad2;
+}
+SphSimSettings;
+
+typedef struct SphCollSettings
+{
+ float epsilon; /* min distance for collisions. */
+ float self_friction; /* Fiction/damping with self contact. */
+ float friction; /* Friction/damping applied on contact with other object.*/
+ short self_loop_count; /* How many iterations for the selfcollision loop */
+ short loop_count; /* How many iterations for the collision loop. */
+ struct LinkNode *collision_list; /* e.g. pointer to temp memory for collisions */
+ int flags; /* collision flags defined in BKE_cloth.h */
+ float selfepsilon; /* for selfcollision */
+}
+SphCollSettings;
+
+#endif // DNA_SPH_TYPES_H
diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c
index 1365baf075a..d2f798d0b6e 100644
--- a/source/blender/src/buttons_editing.c
+++ b/source/blender/src/buttons_editing.c
@@ -985,7 +985,7 @@ static uiBlock *modifiers_add_menu(void *ob_v)
/* Only allow adding through appropriate other interfaces */
if(ELEM3(i, eModifierType_Softbody, eModifierType_Hook, eModifierType_ParticleSystem)) continue;
- if(ELEM(i, eModifierType_Cloth, eModifierType_Collision)) continue;
+ if(ELEM3(i, eModifierType_Cloth, eModifierType_Collision, eModifierType_Sph)) continue;
if((mti->flags&eModifierTypeFlag_AcceptsCVs) ||
(ob->type==OB_MESH && (mti->flags&eModifierTypeFlag_AcceptsMesh))) {
@@ -1813,6 +1813,8 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
height = 31;
} else if (md->type==eModifierType_Collision) {
height = 31;
+ } else if (md->type==eModifierType_Sph) {
+ height = 31;
} else if (md->type==eModifierType_Boolean) {
height = 48;
} else if (md->type==eModifierType_Array) {
@@ -1843,7 +1845,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
uiButSetFunc(but, modifiers_applyModifier, ob, md);
}
- if (md->type!=eModifierType_Softbody && md->type!=eModifierType_ParticleSystem && (md->type!=eModifierType_Cloth)) {
+ if (md->type!=eModifierType_Softbody && md->type!=eModifierType_ParticleSystem && (md->type!=eModifierType_Cloth) && (md->type!=eModifierType_Sph)) {
but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Copy", lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Duplicate the current modifier at the same position in the stack");
uiButSetFunc(but, modifiers_copyModifier, ob, md);
}
@@ -2235,6 +2237,8 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
uiDefBut(block, LABEL, 1, "See Soft Body panel.", lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
} else if (md->type==eModifierType_Cloth) {
uiDefBut(block, LABEL, 1, "See Cloth panel.", lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
+ } else if (md->type==eModifierType_Sph) {
+ uiDefBut(block, LABEL, 1, "See Sph panel.", lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
} else if (md->type==eModifierType_Collision) {
uiDefBut(block, LABEL, 1, "See Collision panel.", lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
} else if (md->type==eModifierType_Boolean) {
diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c
index fb36d103656..93e5603e97a 100644
--- a/source/blender/src/buttons_object.c
+++ b/source/blender/src/buttons_object.c
@@ -52,6 +52,8 @@
#include "BKE_utildefines.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
+#include "BKE_sph.h"
+
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
@@ -107,6 +109,7 @@
#include "DNA_particle_types.h"
#include "DNA_radio_types.h"
#include "DNA_screen_types.h"
+#include "DNA_sph_types.h"
#include "DNA_sound_types.h"
#include "DNA_texture_types.h"
#include "DNA_userdef_types.h"
@@ -135,6 +138,7 @@
#include "BKE_object.h"
#include "BKE_particle.h"
#include "BKE_sound.h"
+#include "BKE_sph.h"
#include "BKE_texture.h"
#include "BKE_utildefines.h"
#include "BKE_DerivedMesh.h"
@@ -2476,6 +2480,27 @@ void do_object_panels(unsigned short event)
allqueue(REDRAWVIEW3D, 0);
}
break;
+ case B_SPH_BAKE:
+ {
+ SphModifierData *sphmd = (SphModifierData *)modifiers_findByType(ob, eModifierType_Sph);
+ int i = 0;
+
+ if(sphmd && sphmd->sim_parms)
+ {
+ sphmd->sim_parms->flags |= SPH_SIMSETTINGS_FLAG_BAKING;
+
+ // call baking function
+ for(i = 0; i < 1; i++)
+ {
+ CFRA++;
+ update_for_newframe();
+ }
+
+ sphmd->sim_parms->flags &= ~SPH_SIMSETTINGS_FLAG_BAKING;
+
+ }
+ }
+ break;
}
}
@@ -5677,6 +5702,116 @@ static void object_panel_cloth_III(Object *ob)
}
+static void object_sph__enabletoggle(void *ob_v, void *arg2)
+{
+ Object *ob = ob_v;
+ ModifierData *md = modifiers_findByType(ob, eModifierType_Sph);
+
+ if (!md) {
+ // create particle modifier
+ ParticleSettings *part = psys_new_settings("PSys", G.main);
+ ParticleSystem *psys = MEM_callocN(sizeof(ParticleSystem), "particle_system");
+ ParticleSystemModifierData *psmd;
+
+ md = modifier_new(eModifierType_Sph);
+ BLI_addtail(&ob->modifiers, md);
+
+ part->type = PART_FLUID;
+ psys->part = part;
+ psys->pointcache = BKE_ptcache_add();
+ psys->flag |= PSYS_ENABLED;
+ BLI_addtail(&ob->particlesystem,psys);
+ md= modifier_new(eModifierType_ParticleSystem);
+ sprintf(md->name, "SphParticleSystem" );
+ psmd= (ParticleSystemModifierData*) md;
+ psmd->psys=psys;
+ BLI_addtail(&ob->modifiers, md);
+
+ DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
+ allqueue(REDRAWBUTSEDIT, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ else {
+ Object *ob = ob_v;
+ ModifierData *md = modifiers_findByType(ob, eModifierType_Sph);
+
+ if (!md)
+ return;
+
+ BLI_remlink(&ob->modifiers, md);
+
+ modifier_free(md);
+
+ BIF_undo_push("Del modifier");
+
+ // ob->softflag |= OB_SB_RESET;
+ allqueue(REDRAWBUTSEDIT, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWIMAGE, 0);
+ allqueue(REDRAWOOPS, 0);
+ DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
+ object_handle_update(ob);
+ countall();
+ }
+}
+
+static void object_panel_sph(Object *ob)
+{
+ uiBlock *block=NULL;
+ uiBut *but=NULL;
+ static int val;
+ SphModifierData *sphmd = (SphModifierData *)modifiers_findByType(ob, eModifierType_Sph);
+
+ block= uiNewBlock(&curarea->uiblocks, "object_sph", UI_EMBOSS, UI_HELV, curarea->win);
+ if(uiNewPanel(curarea, block, "Sph ", "Physics", 640, 0, 318, 204)==0) return;
+ uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
+
+ val = (sphmd ? 1:0);
+
+
+ but = uiDefButI(block, TOG, REDRAWBUTSOBJECT, "Sph", 10,200,130,20, &val, 0, 0, 0, 0, "Sets object to become Sph");
+ uiButSetFunc(but, object_sph__enabletoggle, ob, NULL);
+
+
+ uiDefBut(block, LABEL, 0, "",10,10,300,0, NULL, 0.0, 0, 0, 0, ""); /* tell UI we go to 10,10*/
+
+ if(sphmd)
+ {
+ if(sphmd->sim_parms && (sphmd->sim_parms->flags & SPH_SIMSETTINGS_FLAG_DOMAIN))
+ {
+ uiDefBut(block, BUT, B_SPH_BAKE, "BAKE",10, 180,300,20, NULL, 0.0, 0.0, 10, 0, "Perform simulation and output and surface&preview meshes for each frame.");
+ }
+
+ uiDefButS(block, ROW, REDRAWBUTSOBJECT ,"Domain", 10, 160, 100, 20, (short *)&sphmd->sim_parms->flags, 15.0, SPH_SIMSETTINGS_FLAG_DOMAIN, 0.0, 0.0, " ");
+ uiDefButS(block, ROW, REDRAWBUTSOBJECT ,"Fluid", 110, 160, 100, 20, (short *)&sphmd->sim_parms->flags, 15.0, SPH_SIMSETTINGS_FLAG_FLUID, 0.0, 0.0, " ");
+ uiDefButS(block, ROW, REDRAWBUTSOBJECT ,"Obstacle", 210, 160, 100, 20, (short *)&sphmd->sim_parms->flags, 15.0, SPH_SIMSETTINGS_FLAG_OBSTACLE, 0.0, 0.0, " ");
+
+ if(sphmd->sim_parms && (sphmd->sim_parms->flags & SPH_SIMSETTINGS_FLAG_DOMAIN))
+ {
+ uiDefButBitI(block, TOG, SPH_SIMSETTINGS_FLAG_GHOSTS, REDRAWBUTSOBJECT, "Ghosts",10,140,100,20, &sphmd->sim_parms->flags, 0, 0, 0, 0, " ");
+ uiDefButBitI(block, TOG, SPH_SIMSETTINGS_FLAG_MULTIRES, REDRAWBUTSOBJECT, "Multires",110,140,100,20, &sphmd->sim_parms->flags, 0, 0, 0, 0, " ");
+ uiDefButBitI(block, TOG, SPH_SIMSETTINGS_FLAG_VORTICITY, REDRAWBUTSOBJECT, "Vorticity",210,140,100,20, &sphmd->sim_parms->flags, 0, 0, 0, 0, " ");
+
+ // timestep
+ uiDefButF(block, NUM, REDRAWBUTSOBJECT, "Timestep:",10,120,100,20, &sphmd->sim_parms->timestep, 0.0, 1.0, 0.0001f, 0, " ");
+ // totaltime
+ uiDefButF(block, NUM, REDRAWBUTSOBJECT, "Totaltime:",110,120,100,20, &sphmd->sim_parms->totaltime, 0.0, 10000.0, 0.001f, 0, " ");
+ uiDefButF(block, NUM, REDRAWBUTSOBJECT, "Sampling distance:",210,120,100,20, &sphmd->sim_parms->samplingdistance, 0.0, 1.0, 0.0001f, 0, " ");
+ uiDefButF(block, NUM, REDRAWBUTSOBJECT, "Smoothing Length:",10,100,100,20, &sphmd->sim_parms->smoothinglength, 0.0, 10.0, 0.1f, 0, " ");
+
+ uiDefButI(block, NUM, REDRAWBUTSOBJECT, "Surface:",110,100,100,20, &sphmd->sim_parms->computesurfaceevery, 0.0, 1000.0, 1.0, 0, " ");
+ uiDefButI(block, NUM, REDRAWBUTSOBJECT, "Fast Marching:",210,100,100,20, &sphmd->sim_parms->fastmarchingevery, 0.0, 1000.0, 1.0, 0, " ");
+ }
+ else if(sphmd->sim_parms && (sphmd->sim_parms->flags & SPH_SIMSETTINGS_FLAG_FLUID))
+ {
+ uiDefButI(block, NUM, REDRAWBUTSOBJECT, "Resolution:",10,120,100,20, &sphmd->sim_parms->resolution, 1.0, 1000.0, 1.0f, 0, " ");
+ }
+ }
+
+
+ uiBlockEndAlign(block);
+}
+
void object_panels()
{
Object *ob;
@@ -5709,6 +5844,7 @@ void physics_panels()
object_panel_cloth(ob);
object_panel_cloth_II(ob);
object_panel_cloth_III(ob);
+ object_panel_sph(ob);
object_panel_fluidsim(ob);
}
}
diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c
index 3ef14574bc8..0b042fc542f 100644
--- a/source/blender/src/drawobject.c
+++ b/source/blender/src/drawobject.c
@@ -1883,11 +1883,13 @@ static void draw_em_measure_stats(Object *ob, EditMesh *em)
{
EditEdge *eed;
EditFace *efa;
+ EditVert *eve;
float v1[3], v2[3], v3[3], v4[3];
float fvec[3];
char val[32]; /* Stores the measurement display text here */
char conv_float[5]; /* Use a float conversion matching the grid size */
float area, col[3]; /* area of the face, color of the text to draw */
+ int i = 0;
/* make the precission of the pronted value proportionate to the gridsize */
if ((G.vd->grid) < 0.01)
@@ -1941,7 +1943,7 @@ static void draw_em_measure_stats(Object *ob, EditMesh *em)
if(col[1]> 0.5) {col[0]*=0.7; col[2]*= 0.7;}
else col[1]= col[1]*0.7 + 0.3;
glColor3fv(col);
-
+ /*
for(efa= em->faces.first; efa; efa= efa->next) {
if((efa->f & SELECT) || (G.moving && faceselectedOR(efa, SELECT)) ) {
VECCOPY(v1, efa->v1->co);
@@ -1966,6 +1968,24 @@ static void draw_em_measure_stats(Object *ob, EditMesh *em)
glRasterPos3fv(efa->cent);
BMF_DrawString( G.fonts, val);
}
+ }*/
+
+ /* draw IDs of mesh vertexes */
+ for(eve = em->verts.first; eve; eve = eve->next) {
+ char val[32];
+ float fvec[3];
+ VecLerpf(fvec, ob->loc, eve->co, 1.1);
+ glRasterPos3f(fvec[0], fvec[1], fvec[2]);
+
+ sprintf(val, "%d", eve->keyindex);
+ BMF_DrawString(G.fonts, val);
+ }
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ char val[32];
+ sprintf(val, "%d", i);
+ glRasterPos3fv(efa->cent);
+ BMF_DrawString( G.fonts, val);
+ i++;
}
}
diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
index 8640e69102b..757e9a39a83 100644
--- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
+++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
@@ -307,7 +307,7 @@ void KX_BlenderSceneConverter::ConvertScene(const STR_String& scenename,
case UseBullet:
{
CcdPhysicsEnvironment* ccdPhysEnv = new CcdPhysicsEnvironment();
- ccdPhysEnv->setDebugDrawer(new BlenderDebugDraw());
+ // ccdPhysEnv->setDebugDrawer(new BlenderDebugDraw());
ccdPhysEnv->setDeactivationLinearTreshold(0.8f); // default, can be overridden by Python
ccdPhysEnv->setDeactivationAngularTreshold(1.0f); // default, can be overridden by Python
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
index 9f14cf6cbef..c89e0b43456 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
@@ -71,7 +71,7 @@ protected:
public:
- CcdPhysicsEnvironment(btDispatcher* dispatcher=0, btOverlappingPairCache* pairCache=0);
+ CcdPhysicsEnvironment(btDispatcher* dispatcher=0, btBroadphaseInterface* broadphase=0);
virtual ~CcdPhysicsEnvironment();