1
1

* Merge with 2.5 branch revision 21915 to 22079

* SoundActuator update
This commit is contained in:
2009-07-31 12:29:28 +00:00
351 changed files with 31861 additions and 12403 deletions

View File

@@ -10,8 +10,6 @@ import commands
# IMPORTANT NOTE : OFFICIAL BUILDS SHOULD BE DONE WITH SDKs
USE_SDK=True
BF_PYTHON_VERSION = '2.3'
cmd = 'uname -p'
MAC_PROC=commands.getoutput(cmd)
cmd = 'uname -r'
@@ -32,9 +30,12 @@ LIBDIR = '${LCGDIR}'
if MAC_PROC== 'powerpc' and BF_PYTHON_VERSION == '2.3':
MAC_MIN_VERS = '10.3'
MACOSX_SDK='/Developer/SDKs/MacOSX10.3.9.sdk'
else:
elif MAC_CUR_VER=='10.4':
MAC_MIN_VERS = '10.4'
MACOSX_SDK='/Developer/SDKs/MacOSX10.4u.sdk'
else:
MAC_MIN_VERS = '10.5'
MACOSX_SDK='/Developer/SDKs/MacOSX10.5.sdk'
# enable ffmpeg support
@@ -46,24 +47,35 @@ if USE_SDK==True:
#BF_FFMPEG_LIBPATH='${BF_FFMPEG}/lib'
#BF_FFMPEG_LIB = 'avformat.a avcodec.a avutil.a'
# python.org libs install in /library we want to use that for 2.5
#
# if you want py2.5 on leopard without installing
# change value to BF_PYTHON = '/Library/Frameworks/Python.framework/Versions/'
# BEWARE: in that case it will work only on leopard
BF_PYTHON_VERSION = '3.1'
if BF_PYTHON_VERSION=='2.3':
BF_PYTHON = '/System/Library/Frameworks/Python.framework/Versions/'
if BF_PYTHON_VERSION=='3.1':
# python 3.1 uses precompiled libraries in bf svn /lib by default
BF_PYTHON = LIBDIR + '/python'
BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}'
# BF_PYTHON_BINARY = '${BF_PYTHON}/bin/python${BF_PYTHON_VERSION}'
BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}'
BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib/python${BF_PYTHON_VERSION}'
# BF_PYTHON_LINKFLAGS = '-u _PyMac_Error -framework System'
else:
BF_PYTHON = '/Library/Frameworks/Python.framework/Versions/'
# python 2.5 etc. uses built-in framework
BF_PYTHON_INC = '${BF_PYTHON}${BF_PYTHON_VERSION}/include/python${BF_PYTHON_VERSION}'
BF_PYTHON_BINARY = '${BF_PYTHON}${BF_PYTHON_VERSION}/bin/python${BF_PYTHON_VERSION}'
BF_PYTHON_LIB = ''
BF_PYTHON_LIBPATH = '${BF_PYTHON}${BF_PYTHON_VERSION}/lib/python${BF_PYTHON_VERSION}/config'
BF_PYTHON_LINKFLAGS = '-u _PyMac_Error -framework System -framework Python'
if MAC_CUR_VER=='10.3' or MAC_CUR_VER=='10.4':
BF_PYTHON_LINKFLAGS ='-u __dummy '+BF_PYTHON_LINKFLAGS
# python.org libs install in /library we want to use that for 2.5
#
# if you want py2.5 on leopard without installing
# change value to BF_PYTHON = '/Library/Frameworks/Python.framework/Versions/'
# BEWARE: in that case it will work only on leopard
BF_PYTHON = '/System/Library/Frameworks/Python.framework/Versions/'
BF_PYTHON_INC = '${BF_PYTHON}${BF_PYTHON_VERSION}/include/python${BF_PYTHON_VERSION}'
BF_PYTHON_BINARY = '${BF_PYTHON}${BF_PYTHON_VERSION}/bin/python${BF_PYTHON_VERSION}'
BF_PYTHON_LIB = ''
BF_PYTHON_LIBPATH = '${BF_PYTHON}${BF_PYTHON_VERSION}/lib/python${BF_PYTHON_VERSION}/config'
BF_PYTHON_LINKFLAGS = '-u _PyMac_Error -framework System -framework Python'
if MAC_CUR_VER=='10.3' or MAC_CUR_VER=='10.4':
BF_PYTHON_LINKFLAGS ='-u __dummy '+BF_PYTHON_LINKFLAGS
BF_QUIET = '1'
WITH_BF_OPENMP = '0'
@@ -144,7 +156,7 @@ BF_GETTEXT_LIB = 'intl'
BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
WITH_BF_GAMEENGINE=True
WITH_BF_PLAYER=False
WITH_BF_PLAYER = False
WITH_BF_BULLET = True
BF_BULLET = '#extern/bullet2/src'

View File

@@ -78,6 +78,7 @@ BF_GETTEXT_LIB = 'gettextpo intl'
BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
WITH_BF_GAMEENGINE='false'
WITH_BF_PLAYER = 'false'
WITH_BF_BULLET = 'true'
BF_BULLET = '#extern/bullet2/src'

View File

@@ -78,6 +78,7 @@ BF_GETTEXT_LIB = 'gnu_gettext'
BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
WITH_BF_GAMEENGINE = False
WITH_BF_PLAYER = False
WITH_BF_BULLET = True
BF_BULLET = '#extern/bullet2/src'

View File

@@ -65,6 +65,7 @@ BF_GETTEXT_LIB = 'intl iconv'
BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
WITH_BF_GAMEENGINE=False
WITH_BF_PLAYER = False
WITH_BF_BULLET = True
BF_BULLET = '#extern/bullet2/src'

View File

@@ -73,6 +73,7 @@ BF_GETTEXT_LIB = 'gettextlib'
BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
WITH_BF_GAMEENGINE=False
WITH_BF_PLAYER = False
WITH_BF_BULLET = True
BF_BULLET = '#extern/bullet2/src'

View File

@@ -36,6 +36,7 @@ ADD_SUBDIRECTORY(decimation)
ADD_SUBDIRECTORY(iksolver)
ADD_SUBDIRECTORY(boolop)
ADD_SUBDIRECTORY(opennl)
ADD_SUBDIRECTORY(smoke)
IF(WITH_ELBEEM)
ADD_SUBDIRECTORY(elbeem)

View File

@@ -32,7 +32,7 @@ SOURCEDIR = intern
# include nan_subdirs.mk
ALLDIRS = string ghost guardedalloc moto container memutil
ALLDIRS += decimation iksolver bsp SoundSystem opennl elbeem boolop audaspace
ALLDIRS += decimation iksolver bsp SoundSystem opennl elbeem boolop smoke audaspace
all::
@for i in $(ALLDIRS); do \

View File

@@ -12,7 +12,8 @@ SConscript(['audaspace/SConscript',
'decimation/SConscript',
'iksolver/SConscript',
'boolop/SConscript',
'opennl/SConscript'])
'opennl/SConscript',
'smoke/SConscript'])
# NEW_CSG was intended for intern/csg, but
# getting it to compile is difficult

View File

@@ -556,6 +556,7 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep)
// play sound
m_playingSounds->push_back(sound);
alSourcei(sound->source, AL_SOURCE_RELATIVE, 1);
start();
alcProcessContext(m_context);
@@ -664,6 +665,7 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep)
// play sound
m_playingSounds->push_back(sound);
alSourcei(sound->source, AL_SOURCE_RELATIVE, 1);
start();
@@ -1142,7 +1144,10 @@ bool AUD_OpenALDevice::getCapability(int capability, void *value)
AUD_Handle* AUD_OpenALDevice::play3D(AUD_IFactory* factory, bool keep)
{
return play(factory, keep);
AUD_OpenALHandle* handle = (AUD_OpenALHandle*)play(factory, keep);
if(handle)
alSourcei(handle->source, AL_SOURCE_RELATIVE, 0);
return handle;
}
bool AUD_OpenALDevice::updateListener(AUD_3DData &data)
@@ -1261,7 +1266,7 @@ bool AUD_OpenALDevice::setSourceSetting(AUD_Handle* handle,
result = true;
break;
case AUD_3DSS_IS_RELATIVE:
alSourcei(source, AL_SOURCE_RELATIVE, value > 1.0);
alSourcei(source, AL_SOURCE_RELATIVE, value > 0.0);
result = true;
break;
case AUD_3DSS_MAX_DISTANCE:

View File

@@ -1464,7 +1464,7 @@ void LbmFsgrSolver::initMovingObstacles(bool staticInit) {
obj->applyTransformation(targetTime, &mMOIVertices,NULL /* no old normals needed */, 0, mMOIVertices.size(), false );
} else {
// only do transform update
obj->getMovingPoints(mMOIVertices,pNormals);
obj->getMovingPoints(mMOIVertices,pNormals); // mMOIVertices = mCachedMovPoints
mMOIVerticesOld = mMOIVertices;
// WARNING - assumes mSimulationTime is global!?
obj->applyTransformation(targetTime, &mMOIVertices,pNormals, 0, mMOIVertices.size(), false );

View File

@@ -534,11 +534,28 @@ GHOST_SystemX11::processEvent(XEvent *xe)
window, data);
}
} else if (((Atom)xcme.data.l[0]) == m_wm_take_focus) {
XWindowAttributes attr;
Window fwin;
int revert_to;
/* as ICCCM say, we need reply this event
* with a SetInputFocus, the data[1] have
* the valid timestamp (send by the wm).
*
* Some WM send this event before the
* window is really mapped (for example
* change from virtual desktop), so we need
* to be sure that our windows is mapped
* or this call fail and close blender.
*/
XSetInputFocus(m_display, xcme.window, RevertToParent, xcme.data.l[1]);
if (XGetWindowAttributes(m_display, xcme.window, &attr) == True) {
if (XGetInputFocus(m_display, &fwin, &revert_to) == True) {
if (attr.map_state == IsViewable) {
if (fwin != xcme.window)
XSetInputFocus(m_display, xcme.window, RevertToParent, xcme.data.l[1]);
}
}
}
} else {
/* Unknown client message, ignore */
}

View File

@@ -0,0 +1,38 @@
# $Id$
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# The Original Code is Copyright (C) 2006, Blender Foundation
# All rights reserved.
#
# The Original Code is: all of this file.
#
# Contributor(s): Daniel Genrich
#
# ***** END GPL LICENSE BLOCK *****
SET(INC ${PNG_INC} ${ZLIB_INC} intern ../../extern/bullet2/src ../memutil ../guardealloc)
# ${FFTW3_INC}
FILE(GLOB SRC intern/*.cpp)
IF(WITH_OPENMP)
ADD_DEFINITIONS(-DPARALLEL=1)
ENDIF(WITH_OPENMP)
BLENDERLIB(bf_smoke "${SRC}" "${INC}")
#, libtype='blender', priority = 0 )

54
intern/smoke/Makefile Normal file
View File

@@ -0,0 +1,54 @@
# -*- mode: gnumakefile; tab-width: 8; indent-tabs-mode: t; -*-
# vim: tabstop=8
#
# $Id$
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
# All rights reserved.
#
# The Original Code is: all of this file.
#
# Contributor(s): Hans Lambermont, GSR
#
# ***** END GPL LICENSE BLOCK *****
# smoke main makefile.
#
include nan_definitions.mk
unexport NAN_QUIET
LIBNAME = smoke
SOURCEDIR = intern/$(LIBNAME)
DIR = $(OCGDIR)/$(SOURCEDIR)
DIRS = intern
#not ready yet TESTDIRS = test
include nan_subdirs.mk
install: $(ALL_OR_DEBUG)
@[ -d $(NAN_SMOKE) ] || mkdir $(NAN_SMOKE)
@[ -d $(NAN_SMOKE)/include ] || mkdir $(NAN_SMOKE)/include
@[ -d $(NAN_SMOKE)/lib/$(DEBUG_DIR) ] || mkdir $(NAN_SMOKE)/lib/$(DEBUG_DIR)
@../tools/cpifdiff.sh $(DIR)/$(DEBUG_DIR)lib$(LIBNAME).a $(NAN_SMOKE)/lib/$(DEBUG_DIR)
ifeq ($(OS),darwin)
ranlib $(NAN_SMOKE)/lib/$(DEBUG_DIR)lib$(LIBNAME).a
endif
@../tools/cpifdiff.sh extern/*.h $(NAN_SMOKE)/include/

15
intern/smoke/SConscript Normal file
View File

@@ -0,0 +1,15 @@
#!/usr/bin/python
Import ('env')
sources = env.Glob('intern/*.cpp')
defs = ''
if env['WITH_BF_OPENMP']:
defs += ' PARALLEL=1'
incs = env['BF_PNG_INC'] + ' ' + env['BF_ZLIB_INC']
incs += ' intern ../../extern/bullet2/src ../memutil ../guardealloc '
# incs += env['BF_FFTW3_INC']
env.BlenderLib ('bf_smoke', sources, Split(incs), Split(defs), libtype=['intern'], priority=[40] )

62
intern/smoke/extern/smoke_API.h vendored Normal file
View File

@@ -0,0 +1,62 @@
/**
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2009 by Daniel Genrich
* All rights reserved.
*
* Contributor(s): None
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef SMOKE_API_H_
#define SMOKE_API_H_
#ifdef __cplusplus
extern "C" {
#endif
struct FLUID_3D *smoke_init(int *res, int amplify, float *p0, float *p1, float dt);
void smoke_free(struct FLUID_3D *fluid);
void smoke_initBlenderRNA(struct FLUID_3D *fluid, float *alpha, float *beta);
void smoke_step(struct FLUID_3D *fluid);
float *smoke_get_density(struct FLUID_3D *fluid);
float *smoke_get_bigdensity(struct FLUID_3D *fluid);
float *smoke_get_heat(struct FLUID_3D *fluid);
float *smoke_get_velocity_x(struct FLUID_3D *fluid);
float *smoke_get_velocity_y(struct FLUID_3D *fluid);
float *smoke_get_velocity_z(struct FLUID_3D *fluid);
unsigned char *smoke_get_obstacle(struct FLUID_3D *fluid);
size_t smoke_get_index(int x, int max_x, int y, int max_y, int z);
size_t smoke_get_index2d(int x, int max_x, int y);
void smoke_set_noise(struct FLUID_3D *fluid, int type);
void smoke_get_bigres(struct FLUID_3D *fluid, int *res);
#ifdef __cplusplus
}
#endif
#endif /* SMOKE_API_H_ */

View File

@@ -0,0 +1,47 @@
//////////////////////////////////////////////////////////////////////
// This file is part of Wavelet Turbulence.
//
// Wavelet Turbulence 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 3 of the License, or
// (at your option) any later version.
//
// Wavelet Turbulence 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 Wavelet Turbulence. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright 2008 Theodore Kim and Nils Thuerey
//
//////////////////////////////////////////////////////////////////////
// Helper function, compute eigenvalues of 3x3 matrix
//////////////////////////////////////////////////////////////////////
#include "tnt/jama_eig.h"
//////////////////////////////////////////////////////////////////////
// eigenvalues of 3x3 non-symmetric matrix
//////////////////////////////////////////////////////////////////////
int inline computeEigenvalues3x3(
float dout[3],
float a[3][3])
{
TNT::Array2D<float> A = TNT::Array2D<float>(3,3, &a[0][0]);
TNT::Array1D<float> eig = TNT::Array1D<float>(3);
TNT::Array1D<float> eigImag = TNT::Array1D<float>(3);
JAMA::Eigenvalue<float> jeig = JAMA::Eigenvalue<float>(A);
jeig.getRealEigenvalues(eig);
// complex ones
jeig.getImagEigenvalues(eigImag);
dout[0] = sqrt(eig[0]*eig[0] + eigImag[0]*eigImag[0]);
dout[1] = sqrt(eig[1]*eig[1] + eigImag[1]*eigImag[1]);
dout[2] = sqrt(eig[2]*eig[2] + eigImag[2]*eigImag[2]);
return 0;
}
#undef rfabs
#undef ROT

View File

@@ -0,0 +1,178 @@
//////////////////////////////////////////////////////////////////////
// This file is part of Wavelet Turbulence.
//
// Wavelet Turbulence 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 3 of the License, or
// (at your option) any later version.
//
// Wavelet Turbulence 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 Wavelet Turbulence. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright 2008 Theodore Kim and Nils Thuerey
//
/////////////////////////////////////////////////////////////////////////
//
#ifndef FFT_NOISE_H_
#define FFT_NOISE_H_
#if 0
#include <iostream>
#include <fftw3.h>
#include <MERSENNETWISTER.h>
#include "WAVELET_NOISE.h"
#ifndef M_PI
#define M_PI 3.14159265
#endif
/////////////////////////////////////////////////////////////////////////
// shift spectrum to the format that FFTW expects
/////////////////////////////////////////////////////////////////////////
static void shift3D(float*& field, int xRes, int yRes, int zRes)
{
int xHalf = xRes / 2;
int yHalf = yRes / 2;
int zHalf = zRes / 2;
int slabSize = xRes * yRes;
for (int z = 0; z < zHalf; z++)
for (int y = 0; y < yHalf; y++)
for (int x = 0; x < xHalf; x++)
{
int index = x + y * xRes + z * xRes * yRes;
float temp;
int xSwap = xHalf;
int ySwap = yHalf * xRes;
int zSwap = zHalf * xRes * yRes;
// [0,0,0] to [1,1,1]
temp = field[index];
field[index] = field[index + xSwap + ySwap + zSwap];
field[index + xSwap + ySwap + zSwap] = temp;
// [1,0,0] to [0,1,1]
temp = field[index + xSwap];
field[index + xSwap] = field[index + ySwap + zSwap];
field[index + ySwap + zSwap] = temp;
// [0,1,0] to [1,0,1]
temp = field[index + ySwap];
field[index + ySwap] = field[index + xSwap + zSwap];
field[index + xSwap + zSwap] = temp;
// [0,0,1] to [1,1,0]
temp = field[index + zSwap];
field[index + zSwap] = field[index + xSwap + ySwap];
field[index + xSwap + ySwap] = temp;
}
}
static void generatTile_FFT(float* const noiseTileData, std::string filename)
{
if (loadTile(noiseTileData, filename)) return;
int res = NOISE_TILE_SIZE;
int xRes = res;
int yRes = res;
int zRes = res;
int totalCells = xRes * yRes * zRes;
// create and shift the filter
float* filter = new float[totalCells];
for (int z = 0; z < zRes; z++)
for (int y = 0; y < yRes; y++)
for (int x = 0; x < xRes; x++)
{
int index = x + y * xRes + z * xRes * yRes;
float diff[] = {abs(x - xRes/2),
abs(y - yRes/2),
abs(z - zRes/2)};
float radius = sqrtf(diff[0] * diff[0] +
diff[1] * diff[1] +
diff[2] * diff[2]) / (xRes / 2);
radius *= M_PI;
float H = cos((M_PI / 2.0f) * log(4.0f * radius / M_PI) / log(2.0f));
H = H * H;
float filtered = H;
// clamp everything outside the wanted band
if (radius >= M_PI / 2.0f)
filtered = 0.0f;
// make sure to capture all low frequencies
if (radius <= M_PI / 4.0f)
filtered = 1.0f;
filter[index] = filtered;
}
shift3D(filter, xRes, yRes, zRes);
// create the noise
float* noise = new float[totalCells];
int index = 0;
MTRand twister;
for (int z = 0; z < zRes; z++)
for (int y = 0; y < yRes; y++)
for (int x = 0; x < xRes; x++, index++)
noise[index] = twister.randNorm();
// create padded field
fftw_complex* forward = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * totalCells);
// init padded field
index = 0;
for (int z = 0; z < zRes; z++)
for (int y = 0; y < yRes; y++)
for (int x = 0; x < xRes; x++, index++)
{
forward[index][0] = noise[index];
forward[index][1] = 0.0f;
}
// forward FFT
fftw_complex* backward = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * totalCells);
fftw_plan forwardPlan = fftw_plan_dft_3d(xRes, yRes, zRes, forward, backward, FFTW_FORWARD, FFTW_ESTIMATE);
fftw_execute(forwardPlan);
fftw_destroy_plan(forwardPlan);
// apply filter
index = 0;
for (int z = 0; z < zRes; z++)
for (int y = 0; y < yRes; y++)
for (int x = 0; x < xRes; x++, index++)
{
backward[index][0] *= filter[index];
backward[index][1] *= filter[index];
}
// backward FFT
fftw_plan backwardPlan = fftw_plan_dft_3d(xRes, yRes, zRes, backward, forward, FFTW_BACKWARD, FFTW_ESTIMATE);
fftw_execute(backwardPlan);
fftw_destroy_plan(backwardPlan);
// subtract out the low frequency components
index = 0;
for (int z = 0; z < zRes; z++)
for (int y = 0; y < yRes; y++)
for (int x = 0; x < xRes; x++, index++)
noise[index] -= forward[index][0] / totalCells;
// save out the noise tile
saveTile(noise, filename);
fftw_free(forward);
fftw_free(backward);
delete[] filter;
delete[] noise;
}
#endif
#endif /* FFT_NOISE_H_ */

View File

@@ -0,0 +1,672 @@
//////////////////////////////////////////////////////////////////////
// This file is part of Wavelet Turbulence.
//
// Wavelet Turbulence 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 3 of the License, or
// (at your option) any later version.
//
// Wavelet Turbulence 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 Wavelet Turbulence. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright 2008 Theodore Kim and Nils Thuerey
//
// FLUID_3D.cpp: implementation of the FLUID_3D class.
//
//////////////////////////////////////////////////////////////////////
#include "FLUID_3D.h"
#include "IMAGE.h"
#include <INTERPOLATE.h>
#include "SPHERE.h"
#include <zlib.h>
// boundary conditions of the fluid domain
#define DOMAIN_BC_FRONT 1
#define DOMAIN_BC_TOP 0
#define DOMAIN_BC_LEFT 1
#define DOMAIN_BC_BACK DOMAIN_BC_FRONT
#define DOMAIN_BC_BOTTOM DOMAIN_BC_TOP
#define DOMAIN_BC_RIGHT DOMAIN_BC_LEFT
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
FLUID_3D::FLUID_3D(int *res, int amplify, float *p0, float dt) :
_xRes(res[0]), _yRes(res[1]), _zRes(res[2]), _res(0.0f), _dt(dt)
{
// set simulation consts
// _dt = dt; // 0.10
// start point of array
_p0[0] = p0[0];
_p0[1] = p0[1];
_p0[2] = p0[2];
_iterations = 100;
_tempAmb = 0;
_heatDiffusion = 1e-3;
_vorticityEps = 2.0;
_totalTime = 0.0f;
_totalSteps = 0;
_res = Vec3Int(_xRes,_yRes,_zRes);
_maxRes = MAX3(_xRes, _yRes, _zRes);
// initialize wavelet turbulence
_wTurbulence = new WTURBULENCE(_res[0],_res[1],_res[2], amplify);
// scale the constants according to the refinement of the grid
_dx = 1.0f / (float)_maxRes;
float scaling = 64.0f / _maxRes;
scaling = (scaling < 1.0f) ? 1.0f : scaling;
_vorticityEps /= scaling;
// allocate arrays
_totalCells = _xRes * _yRes * _zRes;
_slabSize = _xRes * _yRes;
_divergence = new float[_totalCells];
_pressure = new float[_totalCells];
_xVelocity = new float[_totalCells];
_yVelocity = new float[_totalCells];
_zVelocity = new float[_totalCells];
_xVelocityOld = new float[_totalCells];
_yVelocityOld = new float[_totalCells];
_zVelocityOld = new float[_totalCells];
_xForce = new float[_totalCells];
_yForce = new float[_totalCells];
_zForce = new float[_totalCells];
_vorticity = new float[_totalCells];
_density = new float[_totalCells];
_densityOld = new float[_totalCells];
_heat = new float[_totalCells];
_heatOld = new float[_totalCells];
_residual = new float[_totalCells];
_direction = new float[_totalCells];
_q = new float[_totalCells];
_obstacles = new unsigned char[_totalCells];
_xVorticity = new float[_totalCells];
_yVorticity = new float[_totalCells];
_zVorticity = new float[_totalCells];
for (int x = 0; x < _totalCells; x++)
{
_density[x] = 0.0f;
_densityOld[x] = 0.0f;
_heat[x] = 0.0f;
_heatOld[x] = 0.0f;
_divergence[x] = 0.0f;
_pressure[x] = 0.0f;
_xVelocity[x] = 0.0f;
_yVelocity[x] = 0.0f;
_zVelocity[x] = 0.0f;
_xVelocityOld[x] = 0.0f;
_yVelocityOld[x] = 0.0f;
_zVelocityOld[x] = 0.0f;
_xForce[x] = 0.0f;
_yForce[x] = 0.0f;
_zForce[x] = 0.0f;
_xVorticity[x] = 0.0f;
_yVorticity[x] = 0.0f;
_zVorticity[x] = 0.0f;
_residual[x] = 0.0f;
_obstacles[x] = false;
}
// set side obstacles
int index;
for (int y = 0; y < _yRes; y++)
for (int x = 0; x < _xRes; x++)
{
// front slab
index = x + y * _xRes;
if(DOMAIN_BC_FRONT==1) _obstacles[index] = 1;
// back slab
index += _totalCells - _slabSize;
if(DOMAIN_BC_BACK==1) _obstacles[index] = 1;
}
for (int z = 0; z < _zRes; z++)
for (int x = 0; x < _xRes; x++)
{
// bottom slab
index = x + z * _slabSize;
if(DOMAIN_BC_BOTTOM==1) _obstacles[index] = 1;
// top slab
index += _slabSize - _xRes;
if(DOMAIN_BC_TOP==1) _obstacles[index] = 1;
}
for (int z = 0; z < _zRes; z++)
for (int y = 0; y < _yRes; y++)
{
// left slab
index = y * _xRes + z * _slabSize;
if(DOMAIN_BC_LEFT==1) _obstacles[index] = 1;
// right slab
index += _xRes - 1;
if(DOMAIN_BC_RIGHT==1) _obstacles[index] = 1;
}
/*
SPHERE *obsSphere = NULL;
obsSphere = new SPHERE(0.375,0.5,0.375, 0.1); // for 4 to 3 domain
addObstacle(obsSphere);
delete obsSphere;
*/
}
FLUID_3D::~FLUID_3D()
{
if (_divergence) delete[] _divergence;
if (_pressure) delete[] _pressure;
if (_xVelocity) delete[] _xVelocity;
if (_yVelocity) delete[] _yVelocity;
if (_zVelocity) delete[] _zVelocity;
if (_xVelocityOld) delete[] _xVelocityOld;
if (_yVelocityOld) delete[] _yVelocityOld;
if (_zVelocityOld) delete[] _zVelocityOld;
if (_xForce) delete[] _xForce;
if (_yForce) delete[] _yForce;
if (_zForce) delete[] _zForce;
if (_residual) delete[] _residual;
if (_direction) delete[] _direction;
if (_q) delete[] _q;
if (_density) delete[] _density;
if (_densityOld) delete[] _densityOld;
if (_heat) delete[] _heat;
if (_heatOld) delete[] _heatOld;
if (_xVorticity) delete[] _xVorticity;
if (_yVorticity) delete[] _yVorticity;
if (_zVorticity) delete[] _zVorticity;
if (_vorticity) delete[] _vorticity;
if (_obstacles) delete[] _obstacles;
if (_wTurbulence) delete _wTurbulence;
printf("deleted fluid\n");
}
// init direct access functions from blender
void FLUID_3D::initBlenderRNA(float *alpha, float *beta)
{
_alpha = alpha;
_beta = beta;
// XXX TODO DEBUG
// *_alpha = 0;
// *_beta = 0;
}
//////////////////////////////////////////////////////////////////////
// step simulation once
//////////////////////////////////////////////////////////////////////
void FLUID_3D::step()
{
// wipe forces
for (int i = 0; i < _totalCells; i++)
_xForce[i] = _yForce[i] = _zForce[i] = 0.0f;
wipeBoundaries();
// run the solvers
addVorticity();
addBuoyancy(_heat, _density);
addForce();
project();
diffuseHeat();
// advect everything
advectMacCormack();
if(_wTurbulence) {
_wTurbulence->stepTurbulenceFull(_dt/_dx,
_xVelocity, _yVelocity, _zVelocity, _obstacles);
// _wTurbulence->stepTurbulenceReadable(_dt/_dx,
// _xVelocity, _yVelocity, _zVelocity, _obstacles);
}
/*
// no file output
float *src = _density;
string prefix = string("./original.preview/density_fullxy_");
writeImageSliceXY(src,_res, _res[2]/2, prefix, _totalSteps);
*/
// artificial damping -- this is necessary because we use a
// collated grid, and at very coarse grid resolutions, banding
// artifacts can occur
artificialDamping(_xVelocity);
artificialDamping(_yVelocity);
artificialDamping(_zVelocity);
/*
// no file output
string pbrtPrefix = string("./pbrt/density_small_");
IMAGE::dumpPBRT(_totalSteps, pbrtPrefix, _density, _res[0],_res[1],_res[2]);
*/
_totalTime += _dt;
_totalSteps++;
}
//////////////////////////////////////////////////////////////////////
// helper function to dampen co-located grid artifacts of given arrays in intervals
// (only needed for velocity, strength (w) depends on testcase...
//////////////////////////////////////////////////////////////////////
void FLUID_3D::artificialDamping(float* field) {
const float w = 0.9;
if(_totalSteps % 4 == 1) {
for (int z = 1; z < _res[2]-1; z++)
for (int y = 1; y < _res[1]-1; y++)
for (int x = 1+(y+z)%2; x < _res[0]-1; x+=2) {
const int index = x + y*_res[0] + z * _slabSize;
field[index] = (1-w)*field[index] + 1./6. * w*(
field[index+1] + field[index-1] +
field[index+_res[0]] + field[index-_res[0]] +
field[index+_slabSize] + field[index-_slabSize] );
}
}
if(_totalSteps % 4 == 3) {
for (int z = 1; z < _res[2]-1; z++)
for (int y = 1; y < _res[1]-1; y++)
for (int x = 1+(y+z+1)%2; x < _res[0]-1; x+=2) {
const int index = x + y*_res[0] + z * _slabSize;
field[index] = (1-w)*field[index] + 1./6. * w*(
field[index+1] + field[index-1] +
field[index+_res[0]] + field[index-_res[0]] +
field[index+_slabSize] + field[index-_slabSize] );
}
}
}
//////////////////////////////////////////////////////////////////////
// copy out the boundary in all directions
//////////////////////////////////////////////////////////////////////
void FLUID_3D::copyBorderAll(float* field)
{
int index;
for (int y = 0; y < _yRes; y++)
for (int x = 0; x < _xRes; x++)
{
// front slab
index = x + y * _xRes;
field[index] = field[index + _slabSize];
// back slab
index += _totalCells - _slabSize;
field[index] = field[index - _slabSize];
}
for (int z = 0; z < _zRes; z++)
for (int x = 0; x < _xRes; x++)
{
// bottom slab
index = x + z * _slabSize;
field[index] = field[index + _xRes];
// top slab
index += _slabSize - _xRes;
field[index] = field[index - _xRes];
}
for (int z = 0; z < _zRes; z++)
for (int y = 0; y < _yRes; y++)
{
// left slab
index = y * _xRes + z * _slabSize;
field[index] = field[index + 1];
// right slab
index += _xRes - 1;
field[index] = field[index - 1];
}
}
//////////////////////////////////////////////////////////////////////
// wipe boundaries of velocity and density
//////////////////////////////////////////////////////////////////////
void FLUID_3D::wipeBoundaries()
{
setZeroBorder(_xVelocity, _res);
setZeroBorder(_yVelocity, _res);
setZeroBorder(_zVelocity, _res);
setZeroBorder(_density, _res);
}
//////////////////////////////////////////////////////////////////////
// add forces to velocity field
//////////////////////////////////////////////////////////////////////
void FLUID_3D::addForce()
{
for (int i = 0; i < _totalCells; i++)
{
_xVelocity[i] += _dt * _xForce[i];
_yVelocity[i] += _dt * _yForce[i];
_zVelocity[i] += _dt * _zForce[i];
}
}
//////////////////////////////////////////////////////////////////////
// project into divergence free field
//////////////////////////////////////////////////////////////////////
void FLUID_3D::project()
{
int index, x, y, z;
setObstacleBoundaries();
// copy out the boundaries
if(DOMAIN_BC_LEFT == 0) setNeumannX(_xVelocity, _res);
else setZeroX(_xVelocity, _res);
if(DOMAIN_BC_TOP == 0) setNeumannY(_yVelocity, _res);
else setZeroY(_yVelocity, _res);
if(DOMAIN_BC_FRONT == 0) setNeumannZ(_zVelocity, _res);
else setZeroZ(_zVelocity, _res);
// calculate divergence
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
{
float xright = _xVelocity[index + 1];
float xleft = _xVelocity[index - 1];
float yup = _yVelocity[index + _xRes];
float ydown = _yVelocity[index - _xRes];
float ztop = _zVelocity[index + _slabSize];
float zbottom = _zVelocity[index - _slabSize];
if(_obstacles[index+1]) xright = - _xVelocity[index];
if(_obstacles[index-1]) xleft = - _xVelocity[index];
if(_obstacles[index+_xRes]) yup = - _yVelocity[index];
if(_obstacles[index-_xRes]) ydown = - _yVelocity[index];
if(_obstacles[index+_slabSize]) ztop = - _zVelocity[index];
if(_obstacles[index-_slabSize]) zbottom = - _zVelocity[index];
_divergence[index] = -_dx * 0.5f * (
xright - xleft +
yup - ydown +
ztop - zbottom );
_pressure[index] = 0.0f;
}
copyBorderAll(_pressure);
// solve Poisson equation
solvePressure(_pressure, _divergence, _obstacles);
// project out solution
float invDx = 1.0f / _dx;
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
{
_xVelocity[index] -= 0.5f * (_pressure[index + 1] - _pressure[index - 1]) * invDx;
_yVelocity[index] -= 0.5f * (_pressure[index + _xRes] - _pressure[index - _xRes]) * invDx;
_zVelocity[index] -= 0.5f * (_pressure[index + _slabSize] - _pressure[index - _slabSize]) * invDx;
}
}
//////////////////////////////////////////////////////////////////////
// diffuse heat
//////////////////////////////////////////////////////////////////////
void FLUID_3D::diffuseHeat()
{
SWAP_POINTERS(_heat, _heatOld);
copyBorderAll(_heatOld);
solveHeat(_heat, _heatOld, _obstacles);
// zero out inside obstacles
for (int x = 0; x < _totalCells; x++)
if (_obstacles[x])
_heat[x] = 0.0f;
}
//////////////////////////////////////////////////////////////////////
// stamp an obstacle in the _obstacles field
//////////////////////////////////////////////////////////////////////
void FLUID_3D::addObstacle(OBSTACLE* obstacle)
{
int index = 0;
for (int z = 0; z < _zRes; z++)
for (int y = 0; y < _yRes; y++)
for (int x = 0; x < _xRes; x++, index++)
if (obstacle->inside(x * _dx, y * _dx, z * _dx)) {
_obstacles[index] = true;
}
}
//////////////////////////////////////////////////////////////////////
// calculate the obstacle directional types
//////////////////////////////////////////////////////////////////////
void FLUID_3D::setObstacleBoundaries()
{
// cull degenerate obstacles , move to addObstacle?
for (int z = 1, index = _slabSize + _xRes + 1;
z < _zRes - 1; z++, index += 2 * _xRes)
for (int y = 1; y < _yRes - 1; y++, index += 2)
for (int x = 1; x < _xRes - 1; x++, index++)
if (_obstacles[index] != EMPTY)
{
const int top = _obstacles[index + _slabSize];
const int bottom= _obstacles[index - _slabSize];
const int up = _obstacles[index + _xRes];
const int down = _obstacles[index - _xRes];
const int left = _obstacles[index - 1];
const int right = _obstacles[index + 1];
int counter = 0;
if (up) counter++;
if (down) counter++;
if (left) counter++;
if (right) counter++;
if (top) counter++;
if (bottom) counter++;
if (counter < 3)
_obstacles[index] = EMPTY;
}
// tag remaining obstacle blocks
for (int z = 1, index = _slabSize + _xRes + 1;
z < _zRes - 1; z++, index += 2 * _xRes)
for (int y = 1; y < _yRes - 1; y++, index += 2)
for (int x = 1; x < _xRes - 1; x++, index++)
{
// could do cascade of ifs, but they are a pain
if (_obstacles[index] != EMPTY)
{
const int top = _obstacles[index + _slabSize];
const int bottom= _obstacles[index - _slabSize];
const int up = _obstacles[index + _xRes];
const int down = _obstacles[index - _xRes];
const int left = _obstacles[index - 1];
const int right = _obstacles[index + 1];
// unused
// const bool fullz = (top && bottom);
// const bool fully = (up && down);
//const bool fullx = (left && right);
_xVelocity[index] =
_yVelocity[index] =
_zVelocity[index] = 0.0f;
_pressure[index] = 0.0f;
// average pressure neighbors
float pcnt = 0.;
if (left && !right) {
_pressure[index] += _pressure[index + 1];
pcnt += 1.;
}
if (!left && right) {
_pressure[index] += _pressure[index - 1];
pcnt += 1.;
}
if (up && !down) {
_pressure[index] += _pressure[index - _xRes];
pcnt += 1.;
}
if (!up && down) {
_pressure[index] += _pressure[index + _xRes];
pcnt += 1.;
}
if (top && !bottom) {
_pressure[index] += _pressure[index - _xRes];
pcnt += 1.;
}
if (!top && bottom) {
_pressure[index] += _pressure[index + _xRes];
pcnt += 1.;
}
_pressure[index] /= pcnt;
// TODO? set correct velocity bc's
// velocities are only set to zero right now
// this means it's not a full no-slip boundary condition
// but a "half-slip" - still looks ok right now
}
}
}
//////////////////////////////////////////////////////////////////////
// add buoyancy forces
//////////////////////////////////////////////////////////////////////
void FLUID_3D::addBuoyancy(float *heat, float *density)
{
int index = 0;
for (int z = 0; z < _zRes; z++)
for (int y = 0; y < _yRes; y++)
for (int x = 0; x < _xRes; x++, index++)
{
_zForce[index] += *_alpha * density[index] + (*_beta * (heat[index] - _tempAmb)); // DG: was _yForce, changed for Blender
}
}
//////////////////////////////////////////////////////////////////////
// add vorticity to the force field
//////////////////////////////////////////////////////////////////////
void FLUID_3D::addVorticity()
{
int x,y,z,index;
if(_vorticityEps<=0.) return;
// calculate vorticity
float gridSize = 0.5f / _dx;
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
{
int up = _obstacles[index + _xRes] ? index : index + _xRes;
int down = _obstacles[index - _xRes] ? index : index - _xRes;
float dy = (up == index || down == index) ? 1.0f / _dx : gridSize;
int out = _obstacles[index + _slabSize] ? index : index + _slabSize;
int in = _obstacles[index - _slabSize] ? index : index - _slabSize;
float dz = (out == index || in == index) ? 1.0f / _dx : gridSize;
int right = _obstacles[index + 1] ? index : index + 1;
int left = _obstacles[index - 1] ? index : index - 1;
float dx = (right == index || right == index) ? 1.0f / _dx : gridSize;
_xVorticity[index] = (_zVelocity[up] - _zVelocity[down]) * dy + (-_yVelocity[out] + _yVelocity[in]) * dz;
_yVorticity[index] = (_xVelocity[out] - _xVelocity[in]) * dz + (-_zVelocity[right] + _zVelocity[left]) * dx;
_zVorticity[index] = (_yVelocity[right] - _yVelocity[left]) * dx + (-_xVelocity[up] + _xVelocity[down])* dy;
_vorticity[index] = sqrtf(_xVorticity[index] * _xVorticity[index] +
_yVorticity[index] * _yVorticity[index] +
_zVorticity[index] * _zVorticity[index]);
}
// calculate normalized vorticity vectors
float eps = _vorticityEps;
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
if (!_obstacles[index])
{
float N[3];
int up = _obstacles[index + _xRes] ? index : index + _xRes;
int down = _obstacles[index - _xRes] ? index : index - _xRes;
float dy = (up == index || down == index) ? 1.0f / _dx : gridSize;
int out = _obstacles[index + _slabSize] ? index : index + _slabSize;
int in = _obstacles[index - _slabSize] ? index : index - _slabSize;
float dz = (out == index || in == index) ? 1.0f / _dx : gridSize;
int right = _obstacles[index + 1] ? index : index + 1;
int left = _obstacles[index - 1] ? index : index - 1;
float dx = (right == index || right == index) ? 1.0f / _dx : gridSize;
N[0] = (_vorticity[right] - _vorticity[left]) * dx;
N[1] = (_vorticity[up] - _vorticity[down]) * dy;
N[2] = (_vorticity[out] - _vorticity[in]) * dz;
float magnitude = sqrtf(N[0] * N[0] + N[1] * N[1] + N[2] * N[2]);
if (magnitude > 0.0f)
{
magnitude = 1.0f / magnitude;
N[0] *= magnitude;
N[1] *= magnitude;
N[2] *= magnitude;
_xForce[index] += (N[1] * _zVorticity[index] - N[2] * _yVorticity[index]) * _dx * eps;
_yForce[index] -= (N[0] * _zVorticity[index] - N[2] * _xVorticity[index]) * _dx * eps;
_zForce[index] += (N[0] * _yVorticity[index] - N[1] * _xVorticity[index]) * _dx * eps;
}
}
}
//////////////////////////////////////////////////////////////////////
// Advect using the MacCormack method from the Selle paper
//////////////////////////////////////////////////////////////////////
void FLUID_3D::advectMacCormack()
{
Vec3Int res = Vec3Int(_xRes,_yRes,_zRes);
if(DOMAIN_BC_LEFT == 0) copyBorderX(_xVelocity, res);
else setZeroX(_xVelocity, res);
if(DOMAIN_BC_TOP == 0) copyBorderY(_yVelocity, res);
else setZeroY(_yVelocity, res);
if(DOMAIN_BC_FRONT == 0) copyBorderZ(_zVelocity, res);
else setZeroZ(_zVelocity, res);
SWAP_POINTERS(_xVelocity, _xVelocityOld);
SWAP_POINTERS(_yVelocity, _yVelocityOld);
SWAP_POINTERS(_zVelocity, _zVelocityOld);
SWAP_POINTERS(_density, _densityOld);
SWAP_POINTERS(_heat, _heatOld);
const float dt0 = _dt / _dx;
// use force arrays as temp arrays
for (int x = 0; x < _totalCells; x++)
_xForce[x] = _yForce[x] = 0.0;
float* t1 = _xForce;
float* t2 = _yForce;
advectFieldMacCormack(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _densityOld, _density, t1,t2, res, NULL);
advectFieldMacCormack(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _heatOld, _heat, t1,t2, res, NULL);
advectFieldMacCormack(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _xVelocityOld, _xVelocity, t1,t2, res, NULL);
advectFieldMacCormack(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _yVelocityOld, _yVelocity, t1,t2, res, NULL);
advectFieldMacCormack(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _zVelocityOld, _zVelocity, t1,t2, res, NULL);
if(DOMAIN_BC_LEFT == 0) copyBorderX(_xVelocity, res);
else setZeroX(_xVelocity, res);
if(DOMAIN_BC_TOP == 0) copyBorderY(_yVelocity, res);
else setZeroY(_yVelocity, res);
if(DOMAIN_BC_FRONT == 0) copyBorderZ(_zVelocity, res);
else setZeroZ(_zVelocity, res);
setZeroBorder(_density, res);
setZeroBorder(_heat, res);
for (int x = 0; x < _totalCells; x++)
t1[x] = t2[x] = 0.0;
}

View File

@@ -0,0 +1,175 @@
//////////////////////////////////////////////////////////////////////
// This file is part of Wavelet Turbulence.
//
// Wavelet Turbulence 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 3 of the License, or
// (at your option) any later version.
//
// Wavelet Turbulence 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 Wavelet Turbulence. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright 2008 Theodore Kim and Nils Thuerey
//
// FLUID_3D.h: interface for the FLUID_3D class.
//
//////////////////////////////////////////////////////////////////////
#ifndef FLUID_3D_H
#define FLUID_3D_H
#include <cstdlib>
#include <cmath>
#include <iostream>
#include "OBSTACLE.h"
#include "WTURBULENCE.h"
#include "VEC3.h"
using namespace std;
using namespace BasicVector;
class WTURBULENCE;
class FLUID_3D
{
public:
FLUID_3D(int *res, int amplify, float *p0, float dt);
FLUID_3D() {};
virtual ~FLUID_3D();
void initBlenderRNA(float *alpha, float *beta);
// create & allocate vector noise advection
void initVectorNoise(int amplify);
void addSmokeColumn();
static void addSmokeTestCase(float* field, Vec3Int res, float value);
void step();
void addObstacle(OBSTACLE* obstacle);
const float* xVelocity() { return _xVelocity; };
const float* yVelocity() { return _yVelocity; };
const float* zVelocity() { return _zVelocity; };
int xRes() const { return _xRes; };
int yRes() const { return _yRes; };
int zRes() const { return _zRes; };
public:
// dimensions
int _xRes, _yRes, _zRes, _maxRes;
Vec3Int _res;
int _totalCells;
int _slabSize;
float _dx;
float _p0[3];
float _p1[3];
float _totalTime;
int _totalSteps;
int _totalImgDumps;
int _totalVelDumps;
void artificialDamping(float* field);
// fields
float* _density;
float* _densityOld;
float* _heat;
float* _heatOld;
float* _pressure;
float* _xVelocity;
float* _yVelocity;
float* _zVelocity;
float* _xVelocityOld;
float* _yVelocityOld;
float* _zVelocityOld;
float* _xForce;
float* _yForce;
float* _zForce;
float* _divergence;
float* _xVorticity;
float* _yVorticity;
float* _zVorticity;
float* _vorticity;
unsigned char* _obstacles;
// CG fields
float* _residual;
float* _direction;
float* _q;
int _iterations;
// simulation constants
float _dt;
float _vorticityEps;
float _heatDiffusion;
float *_alpha; // for the buoyancy density term <-- as pointer to get blender RNA in here
float *_beta; // was _buoyancy <-- as pointer to get blender RNA in here
float _tempAmb; /* ambient temperature */
// WTURBULENCE object, if active
WTURBULENCE* _wTurbulence;
// boundary setting functions
void copyBorderAll(float* field);
// timestepping functions
void wipeBoundaries();
void addForce();
void addVorticity();
void addBuoyancy(float *heat, float *density);
// solver stuff
void project();
void diffuseHeat();
void solvePressure(float* field, float* b, unsigned char* skip);
void solveHeat(float* field, float* b, unsigned char* skip);
// handle obstacle boundaries
void setObstacleBoundaries();
public:
// advection, accessed e.g. by WTURBULENCE class
void advectMacCormack();
// boundary setting functions
static void copyBorderX(float* field, Vec3Int res);
static void copyBorderY(float* field, Vec3Int res);
static void copyBorderZ(float* field, Vec3Int res);
static void setNeumannX(float* field, Vec3Int res);
static void setNeumannY(float* field, Vec3Int res);
static void setNeumannZ(float* field, Vec3Int res);
static void setZeroX(float* field, Vec3Int res);
static void setZeroY(float* field, Vec3Int res);
static void setZeroZ(float* field, Vec3Int res);
static void setZeroBorder(float* field, Vec3Int res) {
setZeroX(field, res);
setZeroY(field, res);
setZeroZ(field, res);
};
// static advection functions, also used by WTURBULENCE
static void advectFieldSemiLagrange(const float dt, const float* velx, const float* vely, const float* velz,
float* oldField, float* newField, Vec3Int res);
static void advectFieldMacCormack(const float dt, const float* xVelocity, const float* yVelocity, const float* zVelocity,
float* oldField, float* newField, float* temp1, float* temp2, Vec3Int res, const float* obstacles);
// maccormack helper functions
static void clampExtrema(const float dt, const float* xVelocity, const float* yVelocity, const float* zVelocity,
float* oldField, float* newField, Vec3Int res);
static void clampOutsideRays(const float dt, const float* xVelocity, const float* yVelocity, const float* zVelocity,
float* oldField, float* newField, Vec3Int res, const float* obstacles, const float *oldAdvection);
// output helper functions
// static void writeImageSliceXY(const float *field, Vec3Int res, int slice, string prefix, int picCnt, float scale=1.);
// static void writeImageSliceYZ(const float *field, Vec3Int res, int slice, string prefix, int picCnt, float scale=1.);
// static void writeImageSliceXZ(const float *field, Vec3Int res, int slice, string prefix, int picCnt, float scale=1.);
// static void writeProjectedIntern(const float *field, Vec3Int res, int dir1, int dir2, string prefix, int picCnt, float scale=1.);
};
#endif

View File

@@ -0,0 +1,319 @@
//////////////////////////////////////////////////////////////////////
// This file is part of Wavelet Turbulence.
//
// Wavelet Turbulence 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 3 of the License, or
// (at your option) any later version.
//
// Wavelet Turbulence 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 Wavelet Turbulence. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright 2008 Theodore Kim and Nils Thuerey
//
// FLUID_3D.cpp: implementation of the FLUID_3D class.
//
//////////////////////////////////////////////////////////////////////
#include "FLUID_3D.h"
#define SOLVER_ACCURACY 1e-06
//////////////////////////////////////////////////////////////////////
// solve the poisson equation with CG
//////////////////////////////////////////////////////////////////////
void FLUID_3D::solvePressure(float* field, float* b, unsigned char* skip)
{
int x, y, z, index;
// i = 0
int i = 0;
// r = b - Ax
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
{
// if the cell is a variable
float Acenter = 0.0f;
if (!skip[index])
{
// set the matrix to the Poisson stencil in order
if (!skip[index + 1]) Acenter += 1.;
if (!skip[index - 1]) Acenter += 1.;
if (!skip[index + _xRes]) Acenter += 1.;
if (!skip[index - _xRes]) Acenter += 1.;
if (!skip[index + _slabSize]) Acenter += 1.;
if (!skip[index - _slabSize]) Acenter += 1.;
}
_residual[index] = b[index] - (Acenter * field[index] +
field[index - 1] * (skip[index - 1] ? 0.0 : -1.0f)+
field[index + 1] * (skip[index + 1] ? 0.0 : -1.0f)+
field[index - _xRes] * (skip[index - _xRes] ? 0.0 : -1.0f)+
field[index + _xRes] * (skip[index + _xRes] ? 0.0 : -1.0f)+
field[index - _slabSize] * (skip[index - _slabSize] ? 0.0 : -1.0f)+
field[index + _slabSize] * (skip[index + _slabSize] ? 0.0 : -1.0f) );
_residual[index] = (skip[index]) ? 0.0f : _residual[index];
}
// d = r
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
_direction[index] = _residual[index];
// deltaNew = transpose(r) * r
float deltaNew = 0.0f;
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
deltaNew += _residual[index] * _residual[index];
// delta0 = deltaNew
// float delta0 = deltaNew;
// While deltaNew > (eps^2) * delta0
const float eps = SOLVER_ACCURACY;
float maxR = 2.0f * eps;
while ((i < _iterations) && (maxR > eps))
{
// q = Ad
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
{
// if the cell is a variable
float Acenter = 0.0f;
if (!skip[index])
{
// set the matrix to the Poisson stencil in order
if (!skip[index + 1]) Acenter += 1.;
if (!skip[index - 1]) Acenter += 1.;
if (!skip[index + _xRes]) Acenter += 1.;
if (!skip[index - _xRes]) Acenter += 1.;
if (!skip[index + _slabSize]) Acenter += 1.;
if (!skip[index - _slabSize]) Acenter += 1.;
}
_q[index] = Acenter * _direction[index] +
_direction[index - 1] * (skip[index - 1] ? 0.0 : -1.0f) +
_direction[index + 1] * (skip[index + 1] ? 0.0 : -1.0f) +
_direction[index - _xRes] * (skip[index - _xRes] ? 0.0 : -1.0f) +
_direction[index + _xRes] * (skip[index + _xRes] ? 0.0 : -1.0f)+
_direction[index - _slabSize] * (skip[index - _slabSize] ? 0.0 : -1.0f) +
_direction[index + _slabSize] * (skip[index + _slabSize] ? 0.0 : -1.0f);
_q[index] = (skip[index]) ? 0.0f : _q[index];
}
// alpha = deltaNew / (transpose(d) * q)
float alpha = 0.0f;
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
alpha += _direction[index] * _q[index];
if (fabs(alpha) > 0.0f)
alpha = deltaNew / alpha;
// x = x + alpha * d
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
field[index] += alpha * _direction[index];
// r = r - alpha * q
maxR = 0.0f;
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
{
_residual[index] -= alpha * _q[index];
maxR = (_residual[index] > maxR) ? _residual[index] : maxR;
}
// deltaOld = deltaNew
float deltaOld = deltaNew;
// deltaNew = transpose(r) * r
deltaNew = 0.0f;
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
deltaNew += _residual[index] * _residual[index];
// beta = deltaNew / deltaOld
float beta = deltaNew / deltaOld;
// d = r + beta * d
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
_direction[index] = _residual[index] + beta * _direction[index];
// i = i + 1
i++;
}
cout << i << " iterations converged to " << maxR << endl;
}
//////////////////////////////////////////////////////////////////////
// solve the heat equation with CG
//////////////////////////////////////////////////////////////////////
void FLUID_3D::solveHeat(float* field, float* b, unsigned char* skip)
{
int x, y, z, index;
const float heatConst = _dt * _heatDiffusion / (_dx * _dx);
// i = 0
int i = 0;
// r = b - Ax
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
{
// if the cell is a variable
float Acenter = 1.0f;
if (!skip[index])
{
// set the matrix to the Poisson stencil in order
if (!skip[index + 1]) Acenter += heatConst;
if (!skip[index - 1]) Acenter += heatConst;
if (!skip[index + _xRes]) Acenter += heatConst;
if (!skip[index - _xRes]) Acenter += heatConst;
if (!skip[index + _slabSize]) Acenter += heatConst;
if (!skip[index - _slabSize]) Acenter += heatConst;
}
_residual[index] = b[index] - (Acenter * field[index] +
field[index - 1] * (skip[index - 1] ? 0.0 : -heatConst) +
field[index + 1] * (skip[index + 1] ? 0.0 : -heatConst) +
field[index - _xRes] * (skip[index - _xRes] ? 0.0 : -heatConst) +
field[index + _xRes] * (skip[index + _xRes] ? 0.0 : -heatConst) +
field[index - _slabSize] * (skip[index - _slabSize] ? 0.0 : -heatConst) +
field[index + _slabSize] * (skip[index + _slabSize] ? 0.0 : -heatConst));
_residual[index] = (skip[index]) ? 0.0f : _residual[index];
}
// d = r
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
_direction[index] = _residual[index];
// deltaNew = transpose(r) * r
float deltaNew = 0.0f;
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
deltaNew += _residual[index] * _residual[index];
// delta0 = deltaNew
// float delta0 = deltaNew;
// While deltaNew > (eps^2) * delta0
const float eps = SOLVER_ACCURACY;
float maxR = 2.0f * eps;
while ((i < _iterations) && (maxR > eps))
{
// q = Ad
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
{
// if the cell is a variable
float Acenter = 1.0f;
if (!skip[index])
{
// set the matrix to the Poisson stencil in order
if (!skip[index + 1]) Acenter += heatConst;
if (!skip[index - 1]) Acenter += heatConst;
if (!skip[index + _xRes]) Acenter += heatConst;
if (!skip[index - _xRes]) Acenter += heatConst;
if (!skip[index + _slabSize]) Acenter += heatConst;
if (!skip[index - _slabSize]) Acenter += heatConst;
}
_q[index] = (Acenter * _direction[index] +
_direction[index - 1] * (skip[index - 1] ? 0.0 : -heatConst) +
_direction[index + 1] * (skip[index + 1] ? 0.0 : -heatConst) +
_direction[index - _xRes] * (skip[index - _xRes] ? 0.0 : -heatConst) +
_direction[index + _xRes] * (skip[index + _xRes] ? 0.0 : -heatConst) +
_direction[index - _slabSize] * (skip[index - _slabSize] ? 0.0 : -heatConst) +
_direction[index + _slabSize] * (skip[index + _slabSize] ? 0.0 : -heatConst));
_q[index] = (skip[index]) ? 0.0f : _q[index];
}
// alpha = deltaNew / (transpose(d) * q)
float alpha = 0.0f;
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
alpha += _direction[index] * _q[index];
if (fabs(alpha) > 0.0f)
alpha = deltaNew / alpha;
// x = x + alpha * d
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
field[index] += alpha * _direction[index];
// r = r - alpha * q
maxR = 0.0f;
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
{
_residual[index] -= alpha * _q[index];
maxR = (_residual[index] > maxR) ? _residual[index] : maxR;
}
// deltaOld = deltaNew
float deltaOld = deltaNew;
// deltaNew = transpose(r) * r
deltaNew = 0.0f;
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
deltaNew += _residual[index] * _residual[index];
// beta = deltaNew / deltaOld
float beta = deltaNew / deltaOld;
// d = r + beta * d
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
_direction[index] = _residual[index] + beta * _direction[index];
// i = i + 1
i++;
}
cout << i << " iterations converged to " << maxR << endl;
}

View File

@@ -0,0 +1,657 @@
//////////////////////////////////////////////////////////////////////
// This file is part of Wavelet Turbulence.
//
// Wavelet Turbulence 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 3 of the License, or
// (at your option) any later version.
//
// Wavelet Turbulence 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 Wavelet Turbulence. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright 2008 Theodore Kim and Nils Thuerey
//
// FLUID_3D.cpp: implementation of the static functions of the FLUID_3D class.
//
//////////////////////////////////////////////////////////////////////
#include <zlib.h>
#include "FLUID_3D.h"
#include "IMAGE.h"
#include "WTURBULENCE.h"
#include "INTERPOLATE.h"
//////////////////////////////////////////////////////////////////////
// add a test cube of density to the center
//////////////////////////////////////////////////////////////////////
/*
void FLUID_3D::addSmokeColumn() {
addSmokeTestCase(_density, _res, 1.0);
// addSmokeTestCase(_zVelocity, _res, 1.0);
addSmokeTestCase(_heat, _res, 1.0);
if (_wTurbulence) {
addSmokeTestCase(_wTurbulence->getDensityBig(), _wTurbulence->getResBig(), 1.0);
}
}
*/
//////////////////////////////////////////////////////////////////////
// generic static version, so that it can be applied to the
// WTURBULENCE grid as well
//////////////////////////////////////////////////////////////////////
/*
void FLUID_3D::addSmokeTestCase(float* field, Vec3Int res, float value)
{
const int slabSize = res[0]*res[1]; int maxRes = (int)MAX3V(res);
float dx = 1.0f / (float)maxRes;
float xTotal = dx * res[0];
float yTotal = dx * res[1];
float zTotal = dx * res[2];
float heighMin = 0.05;
float heighMax = 0.10;
for (int y = 0; y < res[1]; y++)
for (int z = (int)(heighMin*res[2]); z <= (int)(heighMax * res[1]); z++)
for (int x = 0; x < res[0]; x++)
{
float xLength = x * dx - xTotal * 0.4f;
float yLength = y * dx - zTotal * 0.5f;
float radius = sqrtf(xLength * xLength + yLength * yLength);
if (radius < 0.075f * xTotal)
{
int index = x + y * res[0] + z * slabSize;
field[index] = value;
}
}
}
*/
//////////////////////////////////////////////////////////////////////
// set x direction to Neumann boundary conditions
//////////////////////////////////////////////////////////////////////
void FLUID_3D::setNeumannX(float* field, Vec3Int res)
{
const int slabSize = res[0] * res[1];
int index;
for (int z = 0; z < res[2]; z++)
for (int y = 0; y < res[1]; y++)
{
// left slab
index = y * res[0] + z * slabSize;
field[index] = field[index + 2];
// right slab
index += res[0] - 1;
field[index] = field[index - 2];
}
}
//////////////////////////////////////////////////////////////////////
// set y direction to Neumann boundary conditions
//////////////////////////////////////////////////////////////////////
void FLUID_3D::setNeumannY(float* field, Vec3Int res)
{
const int slabSize = res[0] * res[1];
int index;
for (int z = 0; z < res[2]; z++)
for (int x = 0; x < res[0]; x++)
{
// bottom slab
index = x + z * slabSize;
field[index] = field[index + 2 * res[0]];
// top slab
index += slabSize - res[0];
field[index] = field[index - 2 * res[0]];
}
// fix, force top slab to only allow outwards flux
for (int z = 0; z < res[2]; z++)
for (int x = 0; x < res[0]; x++)
{
// top slab
index = x + z * slabSize;
index += slabSize - res[0];
if(field[index]<0.) field[index] = 0.;
index -= res[0];
if(field[index]<0.) field[index] = 0.;
}
}
//////////////////////////////////////////////////////////////////////
// set z direction to Neumann boundary conditions
//////////////////////////////////////////////////////////////////////
void FLUID_3D::setNeumannZ(float* field, Vec3Int res)
{
const int slabSize = res[0] * res[1];
const int totalCells = res[0] * res[1] * res[2];
int index;
for (int y = 0; y < res[1]; y++)
for (int x = 0; x < res[0]; x++)
{
// front slab
index = x + y * res[0];
field[index] = field[index + 2 * slabSize];
// back slab
index += totalCells - slabSize;
field[index] = field[index - 2 * slabSize];
}
}
//////////////////////////////////////////////////////////////////////
// set x direction to zero
//////////////////////////////////////////////////////////////////////
void FLUID_3D::setZeroX(float* field, Vec3Int res)
{
const int slabSize = res[0] * res[1];
int index;
for (int z = 0; z < res[2]; z++)
for (int y = 0; y < res[1]; y++)
{
// left slab
index = y * res[0] + z * slabSize;
field[index] = 0.0f;
// right slab
index += res[0] - 1;
field[index] = 0.0f;
}
}
//////////////////////////////////////////////////////////////////////
// set y direction to zero
//////////////////////////////////////////////////////////////////////
void FLUID_3D::setZeroY(float* field, Vec3Int res)
{
const int slabSize = res[0] * res[1];
int index;
for (int z = 0; z < res[2]; z++)
for (int x = 0; x < res[0]; x++)
{
// bottom slab
index = x + z * slabSize;
field[index] = 0.0f;
// top slab
index += slabSize - res[0];
field[index] = 0.0f;
}
}
//////////////////////////////////////////////////////////////////////
// set z direction to zero
//////////////////////////////////////////////////////////////////////
void FLUID_3D::setZeroZ(float* field, Vec3Int res)
{
const int slabSize = res[0] * res[1];
const int totalCells = res[0] * res[1] * res[2];
int index;
for (int y = 0; y < res[1]; y++)
for (int x = 0; x < res[0]; x++)
{
// front slab
index = x + y * res[0];
field[index] = 0.0f;
// back slab
index += totalCells - slabSize;
field[index] = 0.0f;
}
}
//////////////////////////////////////////////////////////////////////
// copy grid boundary
//////////////////////////////////////////////////////////////////////
void FLUID_3D::copyBorderX(float* field, Vec3Int res)
{
const int slabSize = res[0] * res[1];
int index;
for (int z = 0; z < res[2]; z++)
for (int y = 0; y < res[1]; y++)
{
// left slab
index = y * res[0] + z * slabSize;
field[index] = field[index + 1];
// right slab
index += res[0] - 1;
field[index] = field[index - 1];
}
}
void FLUID_3D::copyBorderY(float* field, Vec3Int res)
{
const int slabSize = res[0] * res[1];
int index;
for (int z = 0; z < res[2]; z++)
for (int x = 0; x < res[0]; x++)
{
// bottom slab
index = x + z * slabSize;
field[index] = field[index + res[0]];
// top slab
index += slabSize - res[0];
field[index] = field[index - res[0]];
}
}
void FLUID_3D::copyBorderZ(float* field, Vec3Int res)
{
const int slabSize = res[0] * res[1];
const int totalCells = res[0] * res[1] * res[2];
int index;
for (int y = 0; y < res[1]; y++)
for (int x = 0; x < res[0]; x++)
{
// front slab
index = x + y * res[0];
field[index] = field[index + slabSize];
// back slab
index += totalCells - slabSize;
field[index] = field[index - slabSize];
}
}
/////////////////////////////////////////////////////////////////////
// advect field with the semi lagrangian method
//////////////////////////////////////////////////////////////////////
void FLUID_3D::advectFieldSemiLagrange(const float dt, const float* velx, const float* vely, const float* velz,
float* oldField, float* newField, Vec3Int res)
{
const int xres = res[0];
const int yres = res[1];
const int zres = res[2];
const int slabSize = res[0] * res[1];
// scale dt up to grid resolution
#if PARALLEL==1
#pragma omp parallel for schedule(static)
#endif
for (int z = 0; z < zres; z++)
for (int y = 0; y < yres; y++)
for (int x = 0; x < xres; x++)
{
const int index = x + y * xres + z * xres*yres;
// backtrace
float xTrace = x - dt * velx[index];
float yTrace = y - dt * vely[index];
float zTrace = z - dt * velz[index];
// clamp backtrace to grid boundaries
if (xTrace < 0.5) xTrace = 0.5;
if (xTrace > xres - 1.5) xTrace = xres - 1.5;
if (yTrace < 0.5) yTrace = 0.5;
if (yTrace > yres - 1.5) yTrace = yres - 1.5;
if (zTrace < 0.5) zTrace = 0.5;
if (zTrace > zres - 1.5) zTrace = zres - 1.5;
// locate neighbors to interpolate
const int x0 = (int)xTrace;
const int x1 = x0 + 1;
const int y0 = (int)yTrace;
const int y1 = y0 + 1;
const int z0 = (int)zTrace;
const int z1 = z0 + 1;
// get interpolation weights
const float s1 = xTrace - x0;
const float s0 = 1.0f - s1;
const float t1 = yTrace - y0;
const float t0 = 1.0f - t1;
const float u1 = zTrace - z0;
const float u0 = 1.0f - u1;
const int i000 = x0 + y0 * xres + z0 * slabSize;
const int i010 = x0 + y1 * xres + z0 * slabSize;
const int i100 = x1 + y0 * xres + z0 * slabSize;
const int i110 = x1 + y1 * xres + z0 * slabSize;
const int i001 = x0 + y0 * xres + z1 * slabSize;
const int i011 = x0 + y1 * xres + z1 * slabSize;
const int i101 = x1 + y0 * xres + z1 * slabSize;
const int i111 = x1 + y1 * xres + z1 * slabSize;
// interpolate
// (indices could be computed once)
newField[index] = u0 * (s0 * (t0 * oldField[i000] +
t1 * oldField[i010]) +
s1 * (t0 * oldField[i100] +
t1 * oldField[i110])) +
u1 * (s0 * (t0 * oldField[i001] +
t1 * oldField[i011]) +
s1 * (t0 * oldField[i101] +
t1 * oldField[i111]));
}
}
/////////////////////////////////////////////////////////////////////
// advect field with the maccormack method
//
// comments are the pseudocode from selle's paper
//////////////////////////////////////////////////////////////////////
void FLUID_3D::advectFieldMacCormack(const float dt, const float* xVelocity, const float* yVelocity, const float* zVelocity,
float* oldField, float* newField, float* temp1, float* temp2, Vec3Int res, const float* obstacles)
{
float* phiHatN = temp1;
float* phiHatN1 = temp2;
const int sx= res[0];
const int sy= res[1];
const int sz= res[2];
for (int x = 0; x < sx * sy * sz; x++)
phiHatN[x] = phiHatN1[x] = oldField[x];
float*& phiN = oldField;
float*& phiN1 = newField;
// phiHatN1 = A(phiN)
advectFieldSemiLagrange( dt, xVelocity, yVelocity, zVelocity, phiN, phiHatN1, res);
// phiHatN = A^R(phiHatN1)
advectFieldSemiLagrange( -1.0*dt, xVelocity, yVelocity, zVelocity, phiHatN1, phiHatN, res);
// phiN1 = phiHatN1 + (phiN - phiHatN) / 2
const int border = 0;
for (int z = border; z < sz-border; z++)
for (int y = border; y < sy-border; y++)
for (int x = border; x < sx-border; x++) {
int index = x + y * sx + z * sx*sy;
phiN1[index] = phiHatN1[index] + (phiN[index] - phiHatN[index]) * 0.50f;
//phiN1[index] = phiHatN1[index]; // debug, correction off
}
copyBorderX(phiN1, res);
copyBorderY(phiN1, res);
copyBorderZ(phiN1, res);
// clamp any newly created extrema
clampExtrema(dt, xVelocity, yVelocity, zVelocity, oldField, newField, res);
// if the error estimate was bad, revert to first order
clampOutsideRays(dt, xVelocity, yVelocity, zVelocity, oldField, newField, res, obstacles, phiHatN1);
}
//////////////////////////////////////////////////////////////////////
// Clamp the extrema generated by the BFECC error correction
//////////////////////////////////////////////////////////////////////
void FLUID_3D::clampExtrema(const float dt, const float* velx, const float* vely, const float* velz,
float* oldField, float* newField, Vec3Int res)
{
const int xres= res[0];
const int yres= res[1];
const int zres= res[2];
const int slabSize = res[0] * res[1];
for (int z = 1; z < zres-1; z++)
for (int y = 1; y < yres-1; y++)
for (int x = 1; x < xres-1; x++)
{
const int index = x + y * xres+ z * xres*yres;
// backtrace
float xTrace = x - dt * velx[index];
float yTrace = y - dt * vely[index];
float zTrace = z - dt * velz[index];
// clamp backtrace to grid boundaries
if (xTrace < 0.5) xTrace = 0.5;
if (xTrace > xres - 1.5) xTrace = xres - 1.5;
if (yTrace < 0.5) yTrace = 0.5;
if (yTrace > yres - 1.5) yTrace = yres - 1.5;
if (zTrace < 0.5) zTrace = 0.5;
if (zTrace > zres - 1.5) zTrace = zres - 1.5;
// locate neighbors to interpolate
const int x0 = (int)xTrace;
const int x1 = x0 + 1;
const int y0 = (int)yTrace;
const int y1 = y0 + 1;
const int z0 = (int)zTrace;
const int z1 = z0 + 1;
const int i000 = x0 + y0 * xres + z0 * slabSize;
const int i010 = x0 + y1 * xres + z0 * slabSize;
const int i100 = x1 + y0 * xres + z0 * slabSize;
const int i110 = x1 + y1 * xres + z0 * slabSize;
const int i001 = x0 + y0 * xres + z1 * slabSize;
const int i011 = x0 + y1 * xres + z1 * slabSize;
const int i101 = x1 + y0 * xres + z1 * slabSize;
const int i111 = x1 + y1 * xres + z1 * slabSize;
float minField = oldField[i000];
float maxField = oldField[i000];
minField = (oldField[i010] < minField) ? oldField[i010] : minField;
maxField = (oldField[i010] > maxField) ? oldField[i010] : maxField;
minField = (oldField[i100] < minField) ? oldField[i100] : minField;
maxField = (oldField[i100] > maxField) ? oldField[i100] : maxField;
minField = (oldField[i110] < minField) ? oldField[i110] : minField;
maxField = (oldField[i110] > maxField) ? oldField[i110] : maxField;
minField = (oldField[i001] < minField) ? oldField[i001] : minField;
maxField = (oldField[i001] > maxField) ? oldField[i001] : maxField;
minField = (oldField[i011] < minField) ? oldField[i011] : minField;
maxField = (oldField[i011] > maxField) ? oldField[i011] : maxField;
minField = (oldField[i101] < minField) ? oldField[i101] : minField;
maxField = (oldField[i101] > maxField) ? oldField[i101] : maxField;
minField = (oldField[i111] < minField) ? oldField[i111] : minField;
maxField = (oldField[i111] > maxField) ? oldField[i111] : maxField;
newField[index] = (newField[index] > maxField) ? maxField : newField[index];
newField[index] = (newField[index] < minField) ? minField : newField[index];
}
}
//////////////////////////////////////////////////////////////////////
// Reverts any backtraces that go into boundaries back to first
// order -- in this case the error correction term was totally
// incorrect
//////////////////////////////////////////////////////////////////////
void FLUID_3D::clampOutsideRays(const float dt, const float* velx, const float* vely, const float* velz,
float* oldField, float* newField, Vec3Int res, const float* obstacles, const float *oldAdvection)
{
const int sx= res[0];
const int sy= res[1];
const int sz= res[2];
const int slabSize = res[0] * res[1];
for (int z = 1; z < sz-1; z++)
for (int y = 1; y < sy-1; y++)
for (int x = 1; x < sx-1; x++)
{
const int index = x + y * sx+ z * slabSize;
// backtrace
float xBackward = x + dt * velx[index];
float yBackward = y + dt * vely[index];
float zBackward = z + dt * velz[index];
float xTrace = x - dt * velx[index];
float yTrace = y - dt * vely[index];
float zTrace = z - dt * velz[index];
// see if it goes outside the boundaries
bool hasObstacle =
(zTrace < 1.0f) || (zTrace > sz - 2.0f) ||
(yTrace < 1.0f) || (yTrace > sy - 2.0f) ||
(xTrace < 1.0f) || (xTrace > sx - 2.0f) ||
(zBackward < 1.0f) || (zBackward > sz - 2.0f) ||
(yBackward < 1.0f) || (yBackward > sy - 2.0f) ||
(xBackward < 1.0f) || (xBackward > sx - 2.0f);
// reuse old advection instead of doing another one...
if(hasObstacle) { newField[index] = oldAdvection[index]; continue; }
// clamp to prevent an out of bounds access when looking into
// the _obstacles array
zTrace = (zTrace < 0.5f) ? 0.5f : zTrace;
zTrace = (zTrace > sz - 1.5f) ? sz - 1.5f : zTrace;
yTrace = (yTrace < 0.5f) ? 0.5f : yTrace;
yTrace = (yTrace > sy - 1.5f) ? sy - 1.5f : yTrace;
xTrace = (xTrace < 0.5f) ? 0.5f : xTrace;
xTrace = (xTrace > sx - 1.5f) ? sx - 1.5f : xTrace;
// locate neighbors to interpolate,
// do backward first since we will use the forward indices if a
// reversion is actually necessary
zBackward = (zBackward < 0.5f) ? 0.5f : zBackward;
zBackward = (zBackward > sz - 1.5f) ? sz - 1.5f : zBackward;
yBackward = (yBackward < 0.5f) ? 0.5f : yBackward;
yBackward = (yBackward > sy - 1.5f) ? sy - 1.5f : yBackward;
xBackward = (xBackward < 0.5f) ? 0.5f : xBackward;
xBackward = (xBackward > sx - 1.5f) ? sx - 1.5f : xBackward;
int x0 = (int)xBackward;
int x1 = x0 + 1;
int y0 = (int)yBackward;
int y1 = y0 + 1;
int z0 = (int)zBackward;
int z1 = z0 + 1;
if(obstacles && !hasObstacle) {
hasObstacle = hasObstacle ||
obstacles[x0 + y0 * sx + z0*slabSize] ||
obstacles[x0 + y1 * sx + z0*slabSize] ||
obstacles[x1 + y0 * sx + z0*slabSize] ||
obstacles[x1 + y1 * sx + z0*slabSize] ||
obstacles[x0 + y0 * sx + z1*slabSize] ||
obstacles[x0 + y1 * sx + z1*slabSize] ||
obstacles[x1 + y0 * sx + z1*slabSize] ||
obstacles[x1 + y1 * sx + z1*slabSize] ;
}
// reuse old advection instead of doing another one...
if(hasObstacle) { newField[index] = oldAdvection[index]; continue; }
x0 = (int)xTrace;
x1 = x0 + 1;
y0 = (int)yTrace;
y1 = y0 + 1;
z0 = (int)zTrace;
z1 = z0 + 1;
if(obstacles && !hasObstacle) {
hasObstacle = hasObstacle ||
obstacles[x0 + y0 * sx + z0*slabSize] ||
obstacles[x0 + y1 * sx + z0*slabSize] ||
obstacles[x1 + y0 * sx + z0*slabSize] ||
obstacles[x1 + y1 * sx + z0*slabSize] ||
obstacles[x0 + y0 * sx + z1*slabSize] ||
obstacles[x0 + y1 * sx + z1*slabSize] ||
obstacles[x1 + y0 * sx + z1*slabSize] ||
obstacles[x1 + y1 * sx + z1*slabSize] ;
} // obstacle array
// reuse old advection instead of doing another one...
if(hasObstacle) { newField[index] = oldAdvection[index]; continue; }
// see if either the forward or backward ray went into
// a boundary
if (hasObstacle) {
// get interpolation weights
float s1 = xTrace - x0;
float s0 = 1.0f - s1;
float t1 = yTrace - y0;
float t0 = 1.0f - t1;
float u1 = zTrace - z0;
float u0 = 1.0f - u1;
const int i000 = x0 + y0 * sx + z0 * slabSize;
const int i010 = x0 + y1 * sx + z0 * slabSize;
const int i100 = x1 + y0 * sx + z0 * slabSize;
const int i110 = x1 + y1 * sx + z0 * slabSize;
const int i001 = x0 + y0 * sx + z1 * slabSize;
const int i011 = x0 + y1 * sx + z1 * slabSize;
const int i101 = x1 + y0 * sx + z1 * slabSize;
const int i111 = x1 + y1 * sx + z1 * slabSize;
// interpolate, (indices could be computed once)
newField[index] = u0 * (s0 * (
t0 * oldField[i000] +
t1 * oldField[i010]) +
s1 * (t0 * oldField[i100] +
t1 * oldField[i110])) +
u1 * (s0 * (t0 * oldField[i001] +
t1 * oldField[i011]) +
s1 * (t0 * oldField[i101] +
t1 * oldField[i111]));
}
} // xyz
}
//////////////////////////////////////////////////////////////////////
// image output
//////////////////////////////////////////////////////////////////////
/*
void FLUID_3D::writeImageSliceXY(const float *field, Vec3Int res, int slice, string prefix, int picCnt, float scale) {
writeProjectedIntern(field, res, 0,1, prefix, picCnt, scale);
}
void FLUID_3D::writeImageSliceYZ(const float *field, Vec3Int res, int slice, string prefix, int picCnt, float scale) {
writeProjectedIntern(field, res, 1,2, prefix, picCnt, scale);
}
void FLUID_3D::writeImageSliceXZ(const float *field, Vec3Int res, int slice, string prefix, int picCnt, float scale) {
writeProjectedIntern(field, res, 0,2, prefix, picCnt, scale);
}
*/
//////////////////////////////////////////////////////////////////////
// Helper function for projecting densities along a dimension
//////////////////////////////////////////////////////////////////////
static int getOtherDir(int dir1, int dir2) {
switch(dir1) {
case 0:
switch(dir2) {
case 1: return 2;
case 2: return 1; }
break;
case 1:
switch(dir2) {
case 0: return 2;
case 2: return 0; }
break;
case 2:
switch(dir2) {
case 0: return 1;
case 1: return 0; }
break;
default:
return 0;
}
return 0;
}
//////////////////////////////////////////////////////////////////////
// average densities along third spatial direction
//////////////////////////////////////////////////////////////////////
/*
void FLUID_3D::writeProjectedIntern(const float *field, Vec3Int res,
int dir1, int dir2, string prefix, int picCnt, float scale) {
const int nitems = res[dir1]*res[dir2];
const int otherDir = getOtherDir(dir1,dir2);
float *buf = new float[nitems];
Vec3Int min = Vec3Int(0);
Vec3Int max = res;
min[otherDir] = 0;
max[otherDir] = res[otherDir];
float div = 1./(float)MIN3V(res); // normalize for shorter sides, old: res[otherDir];
div *= 4.; //slightly increase contrast
for(int i=0; i<nitems; i++) buf[i] = 0.;
Vec3Int cnt = 0;
for (cnt[2] = min[2]; cnt[2] < max[2]; cnt[2]++) {
for (cnt[1] = min[1]; cnt[1] < max[1]; cnt[1]++)
for (cnt[0] = min[0]; cnt[0] < max[0]; cnt[0]++)
{
const int index = cnt[0] + cnt[1] * res[0] + cnt[2] * res[0]*res[1];
const int bufindex = cnt[dir1] + cnt[dir2] * res[dir1];
buf[bufindex] += field[index] * scale *div;
}
}
// IMAGE::dumpNumberedPNG(picCnt, prefix, buf, res[dir1], res[dir2]);
delete[] buf;
}
*/

277
intern/smoke/intern/IMAGE.h Normal file
View File

@@ -0,0 +1,277 @@
//////////////////////////////////////////////////////////////////////
// This file is part of Wavelet Turbulence.
//
// Wavelet Turbulence 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 3 of the License, or
// (at your option) any later version.
//
// Wavelet Turbulence 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 Wavelet Turbulence. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright 2008 Theodore Kim and Nils Thuerey
//
//////////////////////////////////////////////////////////////////////
//
#ifndef IMAGE_H
#define IMAGE_H
#include <stdlib.h>
#include <string>
#include <fstream>
#include <sstream>
#include <zlib.h>
//////////////////////////////////////////////////////////////////////
// NT helper functions
//////////////////////////////////////////////////////////////////////
template < class T > inline T ABS( T a ) {
return (0 < a) ? a : -a ;
}
template < class T > inline void SWAP_POINTERS( T &a, T &b ) {
T temp = a;
a = b;
b = temp;
}
template < class T > inline void CLAMP( T &a, T b=0., T c=1.) {
if(a<b) { a=b; return; }
if(a>c) { a=c; return; }
}
template < class T > inline T MIN( T a, T b) {
return (a < b) ? a : b;
}
template < class T > inline T MAX( T a, T b) {
return (a > b) ? a : b;
}
template < class T > inline T MAX3( T a, T b, T c) {
T max = (a > b) ? a : b;
max = (max > c) ? max : c;
return max;
}
template < class T > inline float MAX3V( T vec) {
float max = (vec[0] > vec[1]) ? vec[0] : vec[1];
max = (max > vec[2]) ? max : vec[2];
return max;
}
template < class T > inline float MIN3V( T vec) {
float min = (vec[0] < vec[1]) ? vec[0] : vec[1];
min = (min < vec[2]) ? min : vec[2];
return min;
}
//////////////////////////////////////////////////////////////////////
// PNG, POV-Ray, and PBRT output functions
//////////////////////////////////////////////////////////////////////
#include <png.h>
namespace IMAGE {
/*
static int writePng(const char *fileName, unsigned char **rowsp, int w, int h)
{
// defaults
const int colortype = PNG_COLOR_TYPE_RGBA;
const int bitdepth = 8;
png_structp png_ptr = NULL;
png_infop info_ptr = NULL;
png_bytep *rows = rowsp;
FILE *fp = NULL;
std::string doing = "open for writing";
if (!(fp = fopen(fileName, "wb"))) goto fail;
if(!png_ptr) {
doing = "create png write struct";
if (!(png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL))) goto fail;
}
if(!info_ptr) {
doing = "create png info struct";
if (!(info_ptr = png_create_info_struct(png_ptr))) goto fail;
}
if (setjmp(png_jmpbuf(png_ptr))) goto fail;
doing = "init IO";
png_init_io(png_ptr, fp);
doing = "write header";
png_set_IHDR(png_ptr, info_ptr, w, h, bitdepth, colortype, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
doing = "write info";
png_write_info(png_ptr, info_ptr);
doing = "write image";
png_write_image(png_ptr, rows);
doing = "write end";
png_write_end(png_ptr, NULL);
doing = "write destroy structs";
png_destroy_write_struct(&png_ptr, &info_ptr);
fclose( fp );
return 0;
fail:
std::cerr << "writePng: could not "<<doing<<" !\n";
if(fp) fclose( fp );
if(png_ptr || info_ptr) png_destroy_write_struct(&png_ptr, &info_ptr);
return -1;
}
*/
/////////////////////////////////////////////////////////////////////////////////
// write a numbered PNG file out, padded with zeros up to three zeros
/////////////////////////////////////////////////////////////////////////////////
/*
static void dumpNumberedPNG(int counter, std::string prefix, float* field, int xRes, int yRes)
{
char buffer[256];
sprintf(buffer,"%04i", counter);
std::string number = std::string(buffer);
unsigned char pngbuf[xRes*yRes*4];
unsigned char *rows[yRes];
float *pfield = field;
for (int j=0; j<yRes; j++) {
for (int i=0; i<xRes; i++) {
float val = *pfield;
if(val>1.) val=1.;
if(val<0.) val=0.;
pngbuf[(j*xRes+i)*4+0] = (unsigned char)(val*255.);
pngbuf[(j*xRes+i)*4+1] = (unsigned char)(val*255.);
pngbuf[(j*xRes+i)*4+2] = (unsigned char)(val*255.);
pfield++;
pngbuf[(j*xRes+i)*4+3] = 255;
}
rows[j] = &pngbuf[(yRes-j-1)*xRes*4];
}
std::string filenamePNG = prefix + number + std::string(".png");
writePng(filenamePNG.c_str(), rows, xRes, yRes, false);
printf("Writing %s\n", filenamePNG.c_str());
}
*/
/////////////////////////////////////////////////////////////////////////////////
// export pbrt volumegrid geometry object
/////////////////////////////////////////////////////////////////////////////////
/*
static void dumpPBRT(int counter, std::string prefix, float* fieldOrg, int xRes, int yRes, int zRes)
{
char buffer[256];
sprintf(buffer,"%04i", counter);
std::string number = std::string(buffer);
std::string filenamePbrt = prefix + number + std::string(".pbrt.gz");
printf("Writing PBRT %s\n", filenamePbrt.c_str());
float *field = new float[xRes*yRes*zRes];
// normalize values
float maxDensVal = ABS(fieldOrg[0]);
float targetNorm = 0.5;
for (int i = 0; i < xRes * yRes * zRes; i++) {
if(ABS(fieldOrg[i])>maxDensVal) maxDensVal = ABS(fieldOrg[i]);
field[i] = 0.;
}
if(maxDensVal>0.) {
for (int i = 0; i < xRes * yRes * zRes; i++) {
field[i] = ABS(fieldOrg[i]) / maxDensVal * targetNorm;
}
}
std::fstream fout;
fout.open(filenamePbrt.c_str(), std::ios::out);
int maxRes = (xRes > yRes) ? xRes : yRes;
maxRes = (maxRes > zRes) ? maxRes : zRes;
const float xSize = 1.0 / (float)maxRes * (float)xRes;
const float ySize = 1.0 / (float)maxRes * (float)yRes;
const float zSize = 1.0 / (float)maxRes * (float)zRes;
gzFile file;
file = gzopen(filenamePbrt.c_str(), "wb1");
if (file == NULL) {
std::cerr << " Couldn't write file " << filenamePbrt << "!!!" << std::endl;
return;
}
// dimensions
gzprintf(file, "Volume \"volumegrid\" \n");
gzprintf(file, " \"integer nx\" %i\n", xRes);
gzprintf(file, " \"integer ny\" %i\n", yRes);
gzprintf(file, " \"integer nz\" %i\n", zRes);
gzprintf(file, " \"point p0\" [ 0.0 0.0 0.0 ] \"point p1\" [%f %f %f ] \n", xSize, ySize, zSize);
gzprintf(file, " \"float density\" [ \n");
for (int i = 0; i < xRes * yRes * zRes; i++)
gzprintf(file, "%f ", field[i]);
gzprintf(file, "] \n \n");
gzclose(file);
delete[] field;
}
*/
/////////////////////////////////////////////////////////////////////////////////
// 3D df3 export
/////////////////////////////////////////////////////////////////////////////////
/*
static void dumpDF3(int counter, std::string prefix, float* fieldOrg, int xRes, int yRes, int zRes)
{
char buffer[256];
// do deferred copying to final directory, better for network directories
sprintf(buffer,"%04i", counter);
std::string number = std::string(buffer);
std::string filenameDf3 = prefix + number + std::string(".df3.gz");
printf("Writing DF3 %s\n", filenameDf3.c_str());
gzFile file;
file = gzopen(filenameDf3.c_str(), "wb1");
if (file == NULL) {
std::cerr << " Couldn't write file " << filenameDf3 << "!!!" << std::endl;
return;
}
// dimensions
const int byteSize = 2;
const unsigned short int onx=xRes,ony=yRes,onz=zRes;
unsigned short int nx,ny,nz;
nx = onx >> 8;
ny = ony >> 8;
nz = onz >> 8;
nx += (onx << 8);
ny += (ony << 8);
nz += (onz << 8);
gzwrite(file, (void*)&nx, sizeof(short));
gzwrite(file, (void*)&ny, sizeof(short));
gzwrite(file, (void*)&nz, sizeof(short));
const int nitems = onx*ony*onz;
const float mul = (float)( (1<<(8*byteSize))-1);
unsigned short int *buf = new unsigned short int[nitems];
for (int k = 0; k < onz; k++)
for (int j = 0; j < ony; j++)
for (int i = 0; i < onx; i++) {
float val = fieldOrg[k*(onx*ony)+j*onx+i] ;
CLAMP(val);
buf[k*(onx*ony)+j*onx+i] = (short int)(val*mul);
}
gzwrite(file, (void*)buf, sizeof(unsigned short int)* nitems);
gzclose(file);
delete[] buf;
}
*/
};
#endif

View File

@@ -0,0 +1,227 @@
//////////////////////////////////////////////////////////////////////
// This file is part of Wavelet Turbulence.
//
// Wavelet Turbulence 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 3 of the License, or
// (at your option) any later version.
//
// Wavelet Turbulence 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 Wavelet Turbulence. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright 2008 Theodore Kim and Nils Thuerey
//
//////////////////////////////////////////////////////////////////////
#ifndef INTERPOLATE_H
#define INTERPOLATE_H
#include <iostream>
#include <VEC3.h>
namespace INTERPOLATE {
//////////////////////////////////////////////////////////////////////
// linear interpolators
//////////////////////////////////////////////////////////////////////
static inline float lerp(float t, float a, float b) {
return ( a + t * (b - a) );
}
static inline float lerp(float* field, float x, float y, int res) {
// clamp backtrace to grid boundaries
if (x < 0.5f) x = 0.5f;
if (x > res - 1.5f) x = res - 1.5f;
if (y < 0.5f) y = 0.5f;
if (y > res - 1.5f) y = res - 1.5f;
const int x0 = (int)x;
const int y0 = (int)y;
x -= x0;
y -= y0;
float d00, d10, d01, d11;
// lerp the velocities
d00 = field[x0 + y0 * res];
d10 = field[(x0 + 1) + y0 * res];
d01 = field[x0 + (y0 + 1) * res];
d11 = field[(x0 + 1) + (y0 + 1) * res];
return lerp(y, lerp(x, d00, d10),
lerp(x, d01, d11));
}
//////////////////////////////////////////////////////////////////////////////////////////
// 3d linear interpolation
//////////////////////////////////////////////////////////////////////////////////////////
static inline float lerp3d(float* field, float x, float y, float z, int xres, int yres, int zres) {
// clamp pos to grid boundaries
if (x < 0.5) x = 0.5;
if (x > xres - 1.5) x = xres - 1.5;
if (y < 0.5) y = 0.5;
if (y > yres - 1.5) y = yres - 1.5;
if (z < 0.5) z = 0.5;
if (z > zres - 1.5) z = zres - 1.5;
// locate neighbors to interpolate
const int x0 = (int)x;
const int x1 = x0 + 1;
const int y0 = (int)y;
const int y1 = y0 + 1;
const int z0 = (int)z;
const int z1 = z0 + 1;
// get interpolation weights
const float s1 = x - (float)x0;
const float s0 = 1.0f - s1;
const float t1 = y - (float)y0;
const float t0 = 1.0f - t1;
const float u1 = z - (float)z0;
const float u0 = 1.0f - u1;
const int slabSize = xres*yres;
const int i000 = x0 + y0 * xres + z0 * slabSize;
const int i010 = x0 + y1 * xres + z0 * slabSize;
const int i100 = x1 + y0 * xres + z0 * slabSize;
const int i110 = x1 + y1 * xres + z0 * slabSize;
const int i001 = x0 + y0 * xres + z1 * slabSize;
const int i011 = x0 + y1 * xres + z1 * slabSize;
const int i101 = x1 + y0 * xres + z1 * slabSize;
const int i111 = x1 + y1 * xres + z1 * slabSize;
// interpolate (indices could be computed once)
return ( u0 * (s0 * (t0 * field[i000] +
t1 * field[i010]) +
s1 * (t0 * field[i100] +
t1 * field[i110])) +
u1 * (s0 * (t0 * field[i001] +
t1 * field[i011]) +
s1 * (t0 * field[i101] +
t1 * field[i111])) );
}
//////////////////////////////////////////////////////////////////////////////////////////
// convert field entries of type T to floats, then interpolate
//////////////////////////////////////////////////////////////////////////////////////////
template <class T>
static inline float lerp3dToFloat(T* field1,
float x, float y, float z, int xres, int yres, int zres) {
// clamp pos to grid boundaries
if (x < 0.5) x = 0.5;
if (x > xres - 1.5) x = xres - 1.5;
if (y < 0.5) y = 0.5;
if (y > yres - 1.5) y = yres - 1.5;
if (z < 0.5) z = 0.5;
if (z > zres - 1.5) z = zres - 1.5;
// locate neighbors to interpolate
const int x0 = (int)x;
const int x1 = x0 + 1;
const int y0 = (int)y;
const int y1 = y0 + 1;
const int z0 = (int)z;
const int z1 = z0 + 1;
// get interpolation weights
const float s1 = x - (float)x0;
const float s0 = 1.0f - s1;
const float t1 = y - (float)y0;
const float t0 = 1.0f - t1;
const float u1 = z - (float)z0;
const float u0 = 1.0f - u1;
const int slabSize = xres*yres;
const int i000 = x0 + y0 * xres + z0 * slabSize;
const int i010 = x0 + y1 * xres + z0 * slabSize;
const int i100 = x1 + y0 * xres + z0 * slabSize;
const int i110 = x1 + y1 * xres + z0 * slabSize;
const int i001 = x0 + y0 * xres + z1 * slabSize;
const int i011 = x0 + y1 * xres + z1 * slabSize;
const int i101 = x1 + y0 * xres + z1 * slabSize;
const int i111 = x1 + y1 * xres + z1 * slabSize;
// interpolate (indices could be computed once)
return (float)(
( u0 * (s0 * (t0 * (float)field1[i000] +
t1 * (float)field1[i010]) +
s1 * (t0 * (float)field1[i100] +
t1 * (float)field1[i110])) +
u1 * (s0 * (t0 * (float)field1[i001] +
t1 * (float)field1[i011]) +
s1 * (t0 * (float)field1[i101] +
t1 * (float)field1[i111])) ) );
}
//////////////////////////////////////////////////////////////////////////////////////////
// interpolate a vector from 3 fields
//////////////////////////////////////////////////////////////////////////////////////////
static inline Vec3 lerp3dVec(float* field1, float* field2, float* field3,
float x, float y, float z, int xres, int yres, int zres) {
// clamp pos to grid boundaries
if (x < 0.5) x = 0.5;
if (x > xres - 1.5) x = xres - 1.5;
if (y < 0.5) y = 0.5;
if (y > yres - 1.5) y = yres - 1.5;
if (z < 0.5) z = 0.5;
if (z > zres - 1.5) z = zres - 1.5;
// locate neighbors to interpolate
const int x0 = (int)x;
const int x1 = x0 + 1;
const int y0 = (int)y;
const int y1 = y0 + 1;
const int z0 = (int)z;
const int z1 = z0 + 1;
// get interpolation weights
const float s1 = x - (float)x0;
const float s0 = 1.0f - s1;
const float t1 = y - (float)y0;
const float t0 = 1.0f - t1;
const float u1 = z - (float)z0;
const float u0 = 1.0f - u1;
const int slabSize = xres*yres;
const int i000 = x0 + y0 * xres + z0 * slabSize;
const int i010 = x0 + y1 * xres + z0 * slabSize;
const int i100 = x1 + y0 * xres + z0 * slabSize;
const int i110 = x1 + y1 * xres + z0 * slabSize;
const int i001 = x0 + y0 * xres + z1 * slabSize;
const int i011 = x0 + y1 * xres + z1 * slabSize;
const int i101 = x1 + y0 * xres + z1 * slabSize;
const int i111 = x1 + y1 * xres + z1 * slabSize;
// interpolate (indices could be computed once)
return Vec3(
( u0 * (s0 * (t0 * field1[i000] +
t1 * field1[i010]) +
s1 * (t0 * field1[i100] +
t1 * field1[i110])) +
u1 * (s0 * (t0 * field1[i001] +
t1 * field1[i011]) +
s1 * (t0 * field1[i101] +
t1 * field1[i111])) ) ,
( u0 * (s0 * (t0 * field2[i000] +
t1 * field2[i010]) +
s1 * (t0 * field2[i100] +
t1 * field2[i110])) +
u1 * (s0 * (t0 * field2[i001] +
t1 * field2[i011]) +
s1 * (t0 * field2[i101] +
t1 * field2[i111])) ) ,
( u0 * (s0 * (t0 * field3[i000] +
t1 * field3[i010]) +
s1 * (t0 * field3[i100] +
t1 * field3[i110])) +
u1 * (s0 * (t0 * field3[i001] +
t1 * field3[i011]) +
s1 * (t0 * field3[i101] +
t1 * field3[i111])) )
);
}
};
#endif

View File

@@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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 3 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, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

View File

@@ -0,0 +1,56 @@
//////////////////////////////////////////////////////////////////////
// This file is part of Wavelet Turbulence.
//
// Wavelet Turbulence 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 3 of the License, or
// (at your option) any later version.
//
// Wavelet Turbulence 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 Wavelet Turbulence. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright 2008 Theodore Kim and Nils Thuerey
//
//////////////////////////////////////////////////////////////////////
#ifndef LU_HELPER_H
#define LU_HELPER_H
//////////////////////////////////////////////////////////////////////
// Helper function, compute eigenvalues of 3x3 matrix
//////////////////////////////////////////////////////////////////////
#include "tnt/jama_lu.h"
//////////////////////////////////////////////////////////////////////
// LU decomposition of 3x3 non-symmetric matrix
//////////////////////////////////////////////////////////////////////
JAMA::LU<float> inline computeLU3x3(
float a[3][3])
{
TNT::Array2D<float> A = TNT::Array2D<float>(3,3, &a[0][0]);
JAMA::LU<float> jLU= JAMA::LU<float>(A);
return jLU;
}
//////////////////////////////////////////////////////////////////////
// LU decomposition of 3x3 non-symmetric matrix
//////////////////////////////////////////////////////////////////////
void inline solveLU3x3(
JAMA::LU<float>& A,
float x[3],
float b[3])
{
TNT::Array1D<float> jamaB = TNT::Array1D<float>(3, &b[0]);
TNT::Array1D<float> jamaX = A.solve(jamaB);
x[0] = jamaX[0];
x[1] = jamaX[1];
x[2] = jamaX[2];
}
#endif

View File

@@ -0,0 +1,429 @@
// MersenneTwister.h
// Mersenne Twister random number generator -- a C++ class MTRand
// Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
// Richard J. Wagner v1.0 15 May 2003 rjwagner@writeme.com
// The Mersenne Twister is an algorithm for generating random numbers. It
// was designed with consideration of the flaws in various other generators.
// The period, 2^19937-1, and the order of equidistribution, 623 dimensions,
// are far greater. The generator is also fast; it avoids multiplication and
// division, and it benefits from caches and pipelines. For more information
// see the inventors' web page at http://www.math.keio.ac.jp/~matumoto/emt.html
// Reference
// M. Matsumoto and T. Nishimura, "Mersenne Twister: A 623-Dimensionally
// Equidistributed Uniform Pseudo-Random Number Generator", ACM Transactions on
// Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3-30.
// Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
// Copyright (C) 2000 - 2003, Richard J. Wagner
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. The names of its contributors may not be used to endorse or promote
// products derived from this software without specific prior written
// permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// The original code included the following notice:
//
// When you use this, send an email to: matumoto@math.keio.ac.jp
// with an appropriate reference to your work.
//
// It would be nice to CC: rjwagner@writeme.com and Cokus@math.washington.edu
// when you write.
#ifndef MERSENNETWISTER_H
#define MERSENNETWISTER_H
// Not thread safe (unless auto-initialization is avoided and each thread has
// its own MTRand object)
#include <iostream>
#include <limits.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
class MTRand {
// Data
public:
typedef unsigned long uint32; // unsigned integer type, at least 32 bits
enum { N = 624 }; // length of state vector
enum { SAVE = N + 1 }; // length of array for save()
protected:
enum { M = 397 }; // period parameter
uint32 state[N]; // internal state
uint32 *pNext; // next value to get from state
int left; // number of values left before reload needed
//Methods
public:
MTRand( const uint32& oneSeed ); // initialize with a simple uint32
MTRand( uint32 *const bigSeed, uint32 const seedLength = N ); // or an array
MTRand(); // auto-initialize with /dev/urandom or time() and clock()
// Do NOT use for CRYPTOGRAPHY without securely hashing several returned
// values together, otherwise the generator state can be learned after
// reading 624 consecutive values.
// Access to 32-bit random numbers
double rand(); // real number in [0,1]
double rand( const double& n ); // real number in [0,n]
double randExc(); // real number in [0,1)
double randExc( const double& n ); // real number in [0,n)
double randDblExc(); // real number in (0,1)
double randDblExc( const double& n ); // real number in (0,n)
uint32 randInt(); // integer in [0,2^32-1]
uint32 randInt( const uint32& n ); // integer in [0,n] for n < 2^32
double operator()() { return rand(); } // same as rand()
// Access to 53-bit random numbers (capacity of IEEE double precision)
double rand53(); // real number in [0,1)
// Access to nonuniform random number distributions
double randNorm( const double& mean = 0.0, const double& variance = 1.0 );
// Re-seeding functions with same behavior as initializers
void seed( const uint32 oneSeed );
void seed( uint32 *const bigSeed, const uint32 seedLength = N );
void seed();
// Saving and loading generator state
void save( uint32* saveArray ) const; // to array of size SAVE
void load( uint32 *const loadArray ); // from such array
friend std::ostream& operator<<( std::ostream& os, const MTRand& mtrand );
friend std::istream& operator>>( std::istream& is, MTRand& mtrand );
protected:
void initialize( const uint32 oneSeed );
void reload();
uint32 hiBit( const uint32& u ) const { return u & 0x80000000UL; }
uint32 loBit( const uint32& u ) const { return u & 0x00000001UL; }
uint32 loBits( const uint32& u ) const { return u & 0x7fffffffUL; }
uint32 mixBits( const uint32& u, const uint32& v ) const
{ return hiBit(u) | loBits(v); }
uint32 twist( const uint32& m, const uint32& s0, const uint32& s1 ) const
{ return m ^ (mixBits(s0,s1)>>1) ^ (-loBit(s1) & 0x9908b0dfUL); }
static uint32 hash( time_t t, clock_t c );
};
inline MTRand::MTRand( const uint32& oneSeed )
{ seed(oneSeed); }
inline MTRand::MTRand( uint32 *const bigSeed, const uint32 seedLength )
{ seed(bigSeed,seedLength); }
inline MTRand::MTRand()
{ seed(); }
inline double MTRand::rand()
{ return double(randInt()) * (1.0/4294967295.0); }
inline double MTRand::rand( const double& n )
{ return rand() * n; }
inline double MTRand::randExc()
{ return double(randInt()) * (1.0/4294967296.0); }
inline double MTRand::randExc( const double& n )
{ return randExc() * n; }
inline double MTRand::randDblExc()
{ return ( double(randInt()) + 0.5 ) * (1.0/4294967296.0); }
inline double MTRand::randDblExc( const double& n )
{ return randDblExc() * n; }
inline double MTRand::rand53()
{
uint32 a = randInt() >> 5, b = randInt() >> 6;
return ( a * 67108864.0 + b ) * (1.0/9007199254740992.0); // by Isaku Wada
}
inline double MTRand::randNorm( const double& mean, const double& variance )
{
// Return a real number from a normal (Gaussian) distribution with given
// mean and variance by Box-Muller method
double r = sqrt( -2.0 * log( 1.0-randDblExc()) ) * variance;
double phi = 2.0 * 3.14159265358979323846264338328 * randExc();
return mean + r * cos(phi);
}
inline MTRand::uint32 MTRand::randInt()
{
// Pull a 32-bit integer from the generator state
// Every other access function simply transforms the numbers extracted here
if( left == 0 ) reload();
--left;
register uint32 s1;
s1 = *pNext++;
s1 ^= (s1 >> 11);
s1 ^= (s1 << 7) & 0x9d2c5680UL;
s1 ^= (s1 << 15) & 0xefc60000UL;
return ( s1 ^ (s1 >> 18) );
}
inline MTRand::uint32 MTRand::randInt( const uint32& n )
{
// Find which bits are used in n
// Optimized by Magnus Jonsson (magnus@smartelectronix.com)
uint32 used = n;
used |= used >> 1;
used |= used >> 2;
used |= used >> 4;
used |= used >> 8;
used |= used >> 16;
// Draw numbers until one is found in [0,n]
uint32 i;
do
i = randInt() & used; // toss unused bits to shorten search
while( i > n );
return i;
}
inline void MTRand::seed( const uint32 oneSeed )
{
// Seed the generator with a simple uint32
initialize(oneSeed);
reload();
}
inline void MTRand::seed( uint32 *const bigSeed, const uint32 seedLength )
{
// Seed the generator with an array of uint32's
// There are 2^19937-1 possible initial states. This function allows
// all of those to be accessed by providing at least 19937 bits (with a
// default seed length of N = 624 uint32's). Any bits above the lower 32
// in each element are discarded.
// Just call seed() if you want to get array from /dev/urandom
initialize(19650218UL);
register int i = 1;
register uint32 j = 0;
register int k = ( N > seedLength ? N : seedLength );
for( ; k; --k )
{
state[i] =
state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1664525UL );
state[i] += ( bigSeed[j] & 0xffffffffUL ) + j;
state[i] &= 0xffffffffUL;
++i; ++j;
if( i >= N ) { state[0] = state[N-1]; i = 1; }
if( j >= seedLength ) j = 0;
}
for( k = N - 1; k; --k )
{
state[i] =
state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL );
state[i] -= i;
state[i] &= 0xffffffffUL;
++i;
if( i >= N ) { state[0] = state[N-1]; i = 1; }
}
state[0] = 0x80000000UL; // MSB is 1, assuring non-zero initial array
reload();
}
inline void MTRand::seed()
{
// seed deterministically to produce reproducible runs
seed(123456);
/*
// Seed the generator with an array from /dev/urandom if available
// Otherwise use a hash of time() and clock() values
// First try getting an array from /dev/urandom
FILE* urandom = fopen( "/dev/urandom", "rb" );
if( urandom )
{
uint32 bigSeed[N];
register uint32 *s = bigSeed;
register int i = N;
register bool success = true;
while( success && i-- )
success = fread( s++, sizeof(uint32), 1, urandom );
fclose(urandom);
if( success ) { seed( bigSeed, N ); return; }
}
// Was not successful, so use time() and clock() instead
seed( hash( time(NULL), clock() ) );
*/
}
inline void MTRand::initialize( const uint32 seed )
{
// Initialize generator state with seed
// See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
// In previous versions, most significant bits (MSBs) of the seed affect
// only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto.
register uint32 *s = state;
register uint32 *r = state;
register int i = 1;
*s++ = seed & 0xffffffffUL;
for( ; i < N; ++i )
{
*s++ = ( 1812433253UL * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffUL;
r++;
}
}
inline void MTRand::reload()
{
// Generate N new values in state
// Made clearer and faster by Matthew Bellew (matthew.bellew@home.com)
register uint32 *p = state;
register int i;
for( i = N - M; i--; ++p )
*p = twist( p[M], p[0], p[1] );
for( i = M; --i; ++p )
*p = twist( p[M-N], p[0], p[1] );
*p = twist( p[M-N], p[0], state[0] );
left = N, pNext = state;
}
inline MTRand::uint32 MTRand::hash( time_t t, clock_t c )
{
// Get a uint32 from t and c
// Better than uint32(x) in case x is floating point in [0,1]
// Based on code by Lawrence Kirby (fred@genesis.demon.co.uk)
static uint32 differ = 0; // guarantee time-based seeds will change
uint32 h1 = 0;
unsigned char *p = (unsigned char *) &t;
for( size_t i = 0; i < sizeof(t); ++i )
{
h1 *= UCHAR_MAX + 2U;
h1 += p[i];
}
uint32 h2 = 0;
p = (unsigned char *) &c;
for( size_t j = 0; j < sizeof(c); ++j )
{
h2 *= UCHAR_MAX + 2U;
h2 += p[j];
}
return ( h1 + differ++ ) ^ h2;
}
inline void MTRand::save( uint32* saveArray ) const
{
register uint32 *sa = saveArray;
register const uint32 *s = state;
register int i = N;
for( ; i--; *sa++ = *s++ ) {}
*sa = left;
}
inline void MTRand::load( uint32 *const loadArray )
{
register uint32 *s = state;
register uint32 *la = loadArray;
register int i = N;
for( ; i--; *s++ = *la++ ) {}
left = *la;
pNext = &state[N-left];
}
inline std::ostream& operator<<( std::ostream& os, const MTRand& mtrand )
{
register const MTRand::uint32 *s = mtrand.state;
register int i = mtrand.N;
for( ; i--; os << *s++ << "\t" ) {}
return os << mtrand.left;
}
inline std::istream& operator>>( std::istream& is, MTRand& mtrand )
{
register MTRand::uint32 *s = mtrand.state;
register int i = mtrand.N;
for( ; i--; is >> *s++ ) {}
is >> mtrand.left;
mtrand.pNext = &mtrand.state[mtrand.N-mtrand.left];
return is;
}
#endif // MERSENNETWISTER_H
// Change log:
//
// v0.1 - First release on 15 May 2000
// - Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
// - Translated from C to C++
// - Made completely ANSI compliant
// - Designed convenient interface for initialization, seeding, and
// obtaining numbers in default or user-defined ranges
// - Added automatic seeding from /dev/urandom or time() and clock()
// - Provided functions for saving and loading generator state
//
// v0.2 - Fixed bug which reloaded generator one step too late
//
// v0.3 - Switched to clearer, faster reload() code from Matthew Bellew
//
// v0.4 - Removed trailing newline in saved generator format to be consistent
// with output format of built-in types
//
// v0.5 - Improved portability by replacing static const int's with enum's and
// clarifying return values in seed(); suggested by Eric Heimburg
// - Removed MAXINT constant; use 0xffffffffUL instead
//
// v0.6 - Eliminated seed overflow when uint32 is larger than 32 bits
// - Changed integer [0,n] generator to give better uniformity
//
// v0.7 - Fixed operator precedence ambiguity in reload()
// - Added access for real numbers in (0,1) and (0,n)
//
// v0.8 - Included time.h header to properly support time_t and clock_t
//
// v1.0 - Revised seeding to match 26 Jan 2002 update of Nishimura and Matsumoto
// - Allowed for seeding with arrays of any length
// - Added access for real numbers in [0,1) with 53-bit resolution
// - Added access for real numbers from normal (Gaussian) distributions
// - Increased overall speed by optimizing twist()
// - Doubled speed of integer [0,n] generation
// - Fixed out-of-range number generation on 64-bit machines
// - Improved portability by substituting literal constants for long enum's
// - Changed license from GNU LGPL to BSD

View File

@@ -0,0 +1,52 @@
#
# $Id$
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
# All rights reserved.
#
# The Original Code is: all of this file.
#
# Contributor(s): none yet.
#
# ***** END GPL LICENSE BLOCK *****
# smoke intern Makefile
#
LIBNAME = smoke
DIR = $(OCGDIR)/intern/$(LIBNAME)
include nan_compile.mk
unexport NAN_QUIET
CCFLAGS += $(LEVEL_2_CPP_WARNINGS)
ifeq ($(WITH_BF_OPENMP),true)
CPPFLAGS += -DPARALLEL
endif
CPPFLAGS += -I.
CPPFLAGS += -I../extern
CPPFLAGS += -I$(NAN_PNG)/include
CPPFLAGS += -I$(NAN_PNG)/include/libpng
# zlib
ifeq ($(OS),$(findstring $(OS), "solaris windows"))
CPPFLAGS += -I$(NAN_ZLIB)/include
endif

View File

@@ -0,0 +1,22 @@
# common stuff
LDFLAGS_COMMON = -lfftw3 #-lglut -lglu32 -lopengl32 -lz -lpng
CFLAGS_COMMON = -c -Wall -I./ #-I/cygdrive/c/lib/glvu/include -D_WIN32
CC = g++
CFLAGS = ${CFLAGS_COMMON} -O3 -Wno-unused
LDFLAGS = ${LDFLAGS_COMMON}
EXECUTABLE = noiseFFT
SOURCES = noiseFFT.cpp
OBJECTS = $(SOURCES:.cpp=.o)
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(OBJECTS) $(LDFLAGS) -o $@
.cpp.o:
$(CC) $(CFLAGS) $< -o $@
clean:
rm -f *.o $(EXECUTABLE_LOADER) $(EXECUTABLE)

View File

@@ -0,0 +1,23 @@
CC = g++
LDFLAGS = -lz -lpng
CFLAGS = -O3 -Wno-unused -c -Wall -I./ -D_WIN32
EXECUTABLE = FLUID_3D
SOURCES = main.cpp FLUID_3D.cpp FLUID_3D_SOLVERS.cpp FLUID_3D_STATIC.cpp SPHERE.cpp WTURBULENCE.cpp
OBJECTS = $(SOURCES:.cpp=.o)
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(OBJECTS) $(LDFLAGS) -o $@
.cpp.o:
$(CC) $(CFLAGS) $< -o $@
SPHERE.o: SPHERE.h
FLUID_3D.o: FLUID_3D.h FLUID_3D.cpp
FLUID_3D_SOLVERS.o: FLUID_3D.h FLUID_3D_SOLVERS.cpp
main.o: FLUID_3D.h FLUID_3D.cpp FLUID_3D_SOLVERS.cpp
clean:
rm -f *.o $(EXECUTABLE_LOADER) $(EXECUTABLE)

View File

@@ -0,0 +1,23 @@
CC = g++
LDFLAGS = -lz -lpng -fopenmp -lgomp
CFLAGS = -c -Wall -I./ -fopenmp -DPARALLEL=1 -O3 -Wno-unused
EXECUTABLE = FLUID_3D
SOURCES = main.cpp FLUID_3D.cpp FLUID_3D_SOLVERS.cpp FLUID_3D_STATIC.cpp SPHERE.cpp WTURBULENCE.cpp
OBJECTS = $(SOURCES:.cpp=.o)
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(OBJECTS) $(LDFLAGS) -o $@
.cpp.o:
$(CC) $(CFLAGS) $< -o $@
SPHERE.o: SPHERE.h
FLUID_3D.o: FLUID_3D.h FLUID_3D.cpp
FLUID_3D_SOLVERS.o: FLUID_3D.h FLUID_3D_SOLVERS.cpp
main.o: FLUID_3D.h FLUID_3D.cpp FLUID_3D_SOLVERS.cpp
clean:
rm -f *.o $(EXECUTABLE_LOADER) $(EXECUTABLE)

View File

@@ -0,0 +1,35 @@
CC = g++
# uncomment the other two OPENMP_... lines, if your gcc supports OpenMP
#OPENMP_FLAGS = -fopenmp -DPARALLEL=1 -I/opt/gcc-4.3/usr/local/include
#OPENMPLD_FLAGS = -fopenmp -lgomp -I/opt/gcc-4.3/usr/local/lib
OPENMP_FLAGS =
OPENMPLD_FLAGS =
# assumes MacPorts libpng installation
PNG_INCLUDE = -I/opt/local/include
PNG_LIBS = -I/opt/local/lib
LDFLAGS = $(PNG_LIBS)-lz -lpng $(OPENMPLD_FLAGS)
CFLAGS = -c -Wall -I./ $(PNG_INCLUDE) $(OPENMP_FLAGS) -O3 -Wno-unused
EXECUTABLE = FLUID_3D
SOURCES = main.cpp FLUID_3D.cpp FLUID_3D_SOLVERS.cpp FLUID_3D_STATIC.cpp SPHERE.cpp WTURBULENCE.cpp
OBJECTS = $(SOURCES:.cpp=.o)
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(OBJECTS) $(LDFLAGS) -o $@
.cpp.o:
$(CC) $(CFLAGS) $< -o $@
SPHERE.o: SPHERE.h
FLUID_3D.o: FLUID_3D.h FLUID_3D.cpp
FLUID_3D_SOLVERS.o: FLUID_3D.h FLUID_3D_SOLVERS.cpp
main.o: FLUID_3D.h FLUID_3D.cpp FLUID_3D_SOLVERS.cpp
clean:
rm -f *.o $(EXECUTABLE_LOADER) $(EXECUTABLE)

View File

@@ -0,0 +1,41 @@
//////////////////////////////////////////////////////////////////////
// This file is part of Wavelet Turbulence.
//
// Wavelet Turbulence 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 3 of the License, or
// (at your option) any later version.
//
// Wavelet Turbulence 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 Wavelet Turbulence. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright 2008 Theodore Kim and Nils Thuerey
//
// OBSTACLE.h: interface for the OBSTACLE class.
//
//////////////////////////////////////////////////////////////////////
#ifndef OBSTACLE_H
#define OBSTACLE_H
enum OBSTACLE_FLAGS {
EMPTY = 0,
MARCHED = 2,
RETIRED = 4
};
class OBSTACLE
{
public:
OBSTACLE() {};
virtual ~OBSTACLE() {};
virtual bool inside(float x, float y, float z) = 0;
};
#endif

View File

@@ -0,0 +1,50 @@
//////////////////////////////////////////////////////////////////////
// This file is part of Wavelet Turbulence.
//
// Wavelet Turbulence 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 3 of the License, or
// (at your option) any later version.
//
// Wavelet Turbulence 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 Wavelet Turbulence. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright 2008 Theodore Kim and Nils Thuerey
//
// SPHERE.cpp: implementation of the SPHERE class.
//
//////////////////////////////////////////////////////////////////////
#include "SPHERE.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
SPHERE::SPHERE(float x, float y, float z, float radius) :
_radius(radius)
{
_center[0] = x;
_center[1] = y;
_center[2] = z;
}
SPHERE::~SPHERE()
{
}
bool SPHERE::inside(float x, float y, float z)
{
float translate[] = {x - _center[0], y - _center[1], z - _center[2]};
float magnitude = translate[0] * translate[0] +
translate[1] * translate[1] +
translate[2] * translate[2];
return (magnitude < _radius * _radius) ? true : false;
}

View File

@@ -0,0 +1,41 @@
//////////////////////////////////////////////////////////////////////
// This file is part of Wavelet Turbulence.
//
// Wavelet Turbulence 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 3 of the License, or
// (at your option) any later version.
//
// Wavelet Turbulence 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 Wavelet Turbulence. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright 2008 Theodore Kim and Nils Thuerey
//
// SPHERE.h: interface for the SPHERE class.
//
//////////////////////////////////////////////////////////////////////
#ifndef SPHERE_H
#define SPHERE_H
#include "OBSTACLE.h"
class SPHERE : public OBSTACLE
{
public:
SPHERE(float x, float y, float z, float radius);
virtual ~SPHERE();
bool inside(float x, float y, float z);
private:
float _center[3];
float _radius;
};
#endif

984
intern/smoke/intern/VEC3.h Normal file
View File

@@ -0,0 +1,984 @@
/******************************************************************************
* Copyright 2007 Nils Thuerey
* Basic vector class
*****************************************************************************/
#ifndef BASICVECTOR_H
#define BASICVECTOR_H
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <sstream>
// use which fp-precision? 1=float, 2=double
#ifndef FLOATINGPOINT_PRECISION
#if DDF_DEBUG==1
#define FLOATINGPOINT_PRECISION 2
#else // DDF_DEBUG==1
#define FLOATINGPOINT_PRECISION 1
#endif // DDF_DEBUG==1
#endif
// VECTOR_EPSILON is the minimal vector length
// In order to be able to discriminate floating point values near zero, and
// to be sure not to fail a comparison because of roundoff errors, use this
// value as a threshold.
#if FLOATINGPOINT_PRECISION==1
typedef float Real;
#define FP_REAL_MAX __FLT_MAX__
#define VECTOR_EPSILON (1e-5f)
#else
typedef double Real;
#define FP_REAL_MAX __DBL_MAX__
#define VECTOR_EPSILON (1e-10)
#endif
// hardcoded limits for now...
// for e.g. MSVC compiler...
// some of these defines can be needed
// for linux systems as well (e.g. FLT_MAX)
#ifndef __FLT_MAX__
# ifdef FLT_MAX // try to use it instead
# define __FLT_MAX__ FLT_MAX
# else // FLT_MAX
# define __FLT_MAX__ 3.402823466e+38f
# endif // FLT_MAX
#endif // __FLT_MAX__
#ifndef __DBL_MAX__
# ifdef DBL_MAX // try to use it instead
# define __DBL_MAX__ DBL_MAX
# else // DBL_MAX
# define __DBL_MAX__ 1.7976931348623158e+308
# endif // DBL_MAX
#endif // __DBL_MAX__
#ifndef FLT_MAX
#define FLT_MAX __FLT_MAX__
#endif
#ifndef DBL_MAX
#define DBL_MAX __DBL_MAX__
#endif
#ifndef M_PI
# define M_PI 3.1415926536
# define M_E 2.7182818284
#endif
namespace BasicVector {
// basic inlined vector class
template<class Scalar>
class Vector3Dim
{
public:
// Constructor
inline Vector3Dim();
// Copy-Constructor
inline Vector3Dim(const Vector3Dim<Scalar> &v );
inline Vector3Dim(const float *);
inline Vector3Dim(const double *);
// construct a vector from one Scalar
inline Vector3Dim(Scalar);
// construct a vector from three Scalars
inline Vector3Dim(Scalar, Scalar, Scalar);
// get address of array for OpenGL
Scalar *getAddress() { return value; }
// Assignment operator
inline const Vector3Dim<Scalar>& operator= (const Vector3Dim<Scalar>& v);
// Assignment operator
inline const Vector3Dim<Scalar>& operator= (Scalar s);
// Assign and add operator
inline const Vector3Dim<Scalar>& operator+= (const Vector3Dim<Scalar>& v);
// Assign and add operator
inline const Vector3Dim<Scalar>& operator+= (Scalar s);
// Assign and sub operator
inline const Vector3Dim<Scalar>& operator-= (const Vector3Dim<Scalar>& v);
// Assign and sub operator
inline const Vector3Dim<Scalar>& operator-= (Scalar s);
// Assign and mult operator
inline const Vector3Dim<Scalar>& operator*= (const Vector3Dim<Scalar>& v);
// Assign and mult operator
inline const Vector3Dim<Scalar>& operator*= (Scalar s);
// Assign and div operator
inline const Vector3Dim<Scalar>& operator/= (const Vector3Dim<Scalar>& v);
// Assign and div operator
inline const Vector3Dim<Scalar>& operator/= (Scalar s);
// unary operator
inline Vector3Dim<Scalar> operator- () const;
// binary operator add
inline Vector3Dim<Scalar> operator+ (const Vector3Dim<Scalar>&) const;
// binary operator add
inline Vector3Dim<Scalar> operator+ (Scalar) const;
// binary operator sub
inline Vector3Dim<Scalar> operator- (const Vector3Dim<Scalar>&) const;
// binary operator sub
inline Vector3Dim<Scalar> operator- (Scalar) const;
// binary operator mult
inline Vector3Dim<Scalar> operator* (const Vector3Dim<Scalar>&) const;
// binary operator mult
inline Vector3Dim<Scalar> operator* (Scalar) const;
// binary operator div
inline Vector3Dim<Scalar> operator/ (const Vector3Dim<Scalar>&) const;
// binary operator div
inline Vector3Dim<Scalar> operator/ (Scalar) const;
// Projection normal to a vector
inline Vector3Dim<Scalar> getOrthogonalntlVector3Dim() const;
// Project into a plane
inline const Vector3Dim<Scalar>& projectNormalTo(const Vector3Dim<Scalar> &v);
// minimize
inline const Vector3Dim<Scalar> &minimize(const Vector3Dim<Scalar> &);
// maximize
inline const Vector3Dim<Scalar> &maximize(const Vector3Dim<Scalar> &);
// access operator
inline Scalar& operator[](unsigned int i);
// access operator
inline const Scalar& operator[](unsigned int i) const;
//! actual values
union {
struct {
Scalar value[3];
};
struct {
Scalar x;
Scalar y;
Scalar z;
};
struct {
Scalar X;
Scalar Y;
Scalar Z;
};
};
protected:
};
//------------------------------------------------------------------------------
// VECTOR inline FUNCTIONS
//------------------------------------------------------------------------------
/*************************************************************************
Constructor.
*/
template<class Scalar>
inline Vector3Dim<Scalar>::Vector3Dim( void )
{
value[0] = value[1] = value[2] = 0;
}
/*************************************************************************
Copy-Constructor.
*/
template<class Scalar>
inline Vector3Dim<Scalar>::Vector3Dim( const Vector3Dim<Scalar> &v )
{
value[0] = v.value[0];
value[1] = v.value[1];
value[2] = v.value[2];
}
template<class Scalar>
inline Vector3Dim<Scalar>::Vector3Dim( const float *fvalue)
{
value[0] = (Scalar)fvalue[0];
value[1] = (Scalar)fvalue[1];
value[2] = (Scalar)fvalue[2];
}
template<class Scalar>
inline Vector3Dim<Scalar>::Vector3Dim( const double *fvalue)
{
value[0] = (Scalar)fvalue[0];
value[1] = (Scalar)fvalue[1];
value[2] = (Scalar)fvalue[2];
}
/*************************************************************************
Constructor for a vector from a single Scalar. All components of
the vector get the same value.
\param s The value to set
\return The new vector
*/
template<class Scalar>
inline Vector3Dim<Scalar>::Vector3Dim(Scalar s )
{
value[0]= s;
value[1]= s;
value[2]= s;
}
/*************************************************************************
Constructor for a vector from three Scalars.
\param s1 The value for the first vector component
\param s2 The value for the second vector component
\param s3 The value for the third vector component
\return The new vector
*/
template<class Scalar>
inline Vector3Dim<Scalar>::Vector3Dim(Scalar s1, Scalar s2, Scalar s3)
{
value[0]= s1;
value[1]= s2;
value[2]= s3;
}
/*************************************************************************
Copy a Vector3Dim componentwise.
\param v vector with values to be copied
\return Reference to self
*/
template<class Scalar>
inline const Vector3Dim<Scalar>&
Vector3Dim<Scalar>::operator=( const Vector3Dim<Scalar> &v )
{
value[0] = v.value[0];
value[1] = v.value[1];
value[2] = v.value[2];
return *this;
}
/*************************************************************************
Copy a Scalar to each component.
\param s The value to copy
\return Reference to self
*/
template<class Scalar>
inline const Vector3Dim<Scalar>&
Vector3Dim<Scalar>::operator=(Scalar s)
{
value[0] = s;
value[1] = s;
value[2] = s;
return *this;
}
/*************************************************************************
Add another Vector3Dim componentwise.
\param v vector with values to be added
\return Reference to self
*/
template<class Scalar>
inline const Vector3Dim<Scalar>&
Vector3Dim<Scalar>::operator+=( const Vector3Dim<Scalar> &v )
{
value[0] += v.value[0];
value[1] += v.value[1];
value[2] += v.value[2];
return *this;
}
/*************************************************************************
Add a Scalar value to each component.
\param s Value to add
\return Reference to self
*/
template<class Scalar>
inline const Vector3Dim<Scalar>&
Vector3Dim<Scalar>::operator+=(Scalar s)
{
value[0] += s;
value[1] += s;
value[2] += s;
return *this;
}
/*************************************************************************
Subtract another vector componentwise.
\param v vector of values to subtract
\return Reference to self
*/
template<class Scalar>
inline const Vector3Dim<Scalar>&
Vector3Dim<Scalar>::operator-=( const Vector3Dim<Scalar> &v )
{
value[0] -= v.value[0];
value[1] -= v.value[1];
value[2] -= v.value[2];
return *this;
}
/*************************************************************************
Subtract a Scalar value from each component.
\param s Value to subtract
\return Reference to self
*/
template<class Scalar>
inline const Vector3Dim<Scalar>&
Vector3Dim<Scalar>::operator-=(Scalar s)
{
value[0]-= s;
value[1]-= s;
value[2]-= s;
return *this;
}
/*************************************************************************
Multiply with another vector componentwise.
\param v vector of values to multiply with
\return Reference to self
*/
template<class Scalar>
inline const Vector3Dim<Scalar>&
Vector3Dim<Scalar>::operator*=( const Vector3Dim<Scalar> &v )
{
value[0] *= v.value[0];
value[1] *= v.value[1];
value[2] *= v.value[2];
return *this;
}
/*************************************************************************
Multiply each component with a Scalar value.
\param s Value to multiply with
\return Reference to self
*/
template<class Scalar>
inline const Vector3Dim<Scalar>&
Vector3Dim<Scalar>::operator*=(Scalar s)
{
value[0] *= s;
value[1] *= s;
value[2] *= s;
return *this;
}
/*************************************************************************
Divide by another Vector3Dim componentwise.
\param v vector of values to divide by
\return Reference to self
*/
template<class Scalar>
inline const Vector3Dim<Scalar>&
Vector3Dim<Scalar>::operator/=( const Vector3Dim<Scalar> &v )
{
value[0] /= v.value[0];
value[1] /= v.value[1];
value[2] /= v.value[2];
return *this;
}
/*************************************************************************
Divide each component by a Scalar value.
\param s Value to divide by
\return Reference to self
*/
template<class Scalar>
inline const Vector3Dim<Scalar>&
Vector3Dim<Scalar>::operator/=(Scalar s)
{
value[0] /= s;
value[1] /= s;
value[2] /= s;
return *this;
}
//------------------------------------------------------------------------------
// unary operators
//------------------------------------------------------------------------------
/*************************************************************************
Build componentwise the negative this vector.
\return The new (negative) vector
*/
template<class Scalar>
inline Vector3Dim<Scalar>
Vector3Dim<Scalar>::operator-() const
{
return Vector3Dim<Scalar>(-value[0], -value[1], -value[2]);
}
//------------------------------------------------------------------------------
// binary operators
//------------------------------------------------------------------------------
/*************************************************************************
Build a vector with another vector added componentwise.
\param v The second vector to add
\return The sum vector
*/
template<class Scalar>
inline Vector3Dim<Scalar>
Vector3Dim<Scalar>::operator+( const Vector3Dim<Scalar> &v ) const
{
return Vector3Dim<Scalar>(value[0]+v.value[0],
value[1]+v.value[1],
value[2]+v.value[2]);
}
/*************************************************************************
Build a vector with a Scalar value added to each component.
\param s The Scalar value to add
\return The sum vector
*/
template<class Scalar>
inline Vector3Dim<Scalar>
Vector3Dim<Scalar>::operator+(Scalar s) const
{
return Vector3Dim<Scalar>(value[0]+s,
value[1]+s,
value[2]+s);
}
/*************************************************************************
Build a vector with another vector subtracted componentwise.
\param v The second vector to subtract
\return The difference vector
*/
template<class Scalar>
inline Vector3Dim<Scalar>
Vector3Dim<Scalar>::operator-( const Vector3Dim<Scalar> &v ) const
{
return Vector3Dim<Scalar>(value[0]-v.value[0],
value[1]-v.value[1],
value[2]-v.value[2]);
}
/*************************************************************************
Build a vector with a Scalar value subtracted componentwise.
\param s The Scalar value to subtract
\return The difference vector
*/
template<class Scalar>
inline Vector3Dim<Scalar>
Vector3Dim<Scalar>::operator-(Scalar s ) const
{
return Vector3Dim<Scalar>(value[0]-s,
value[1]-s,
value[2]-s);
}
/*************************************************************************
Build a vector with another vector multiplied by componentwise.
\param v The second vector to muliply with
\return The product vector
*/
template<class Scalar>
inline Vector3Dim<Scalar>
Vector3Dim<Scalar>::operator*( const Vector3Dim<Scalar>& v) const
{
return Vector3Dim<Scalar>(value[0]*v.value[0],
value[1]*v.value[1],
value[2]*v.value[2]);
}
/*************************************************************************
Build a Vector3Dim with a Scalar value multiplied to each component.
\param s The Scalar value to multiply with
\return The product vector
*/
template<class Scalar>
inline Vector3Dim<Scalar>
Vector3Dim<Scalar>::operator*(Scalar s) const
{
return Vector3Dim<Scalar>(value[0]*s, value[1]*s, value[2]*s);
}
/*************************************************************************
Build a vector divided componentwise by another vector.
\param v The second vector to divide by
\return The ratio vector
*/
template<class Scalar>
inline Vector3Dim<Scalar>
Vector3Dim<Scalar>::operator/(const Vector3Dim<Scalar>& v) const
{
return Vector3Dim<Scalar>(value[0]/v.value[0],
value[1]/v.value[1],
value[2]/v.value[2]);
}
/*************************************************************************
Build a vector divided componentwise by a Scalar value.
\param s The Scalar value to divide by
\return The ratio vector
*/
template<class Scalar>
inline Vector3Dim<Scalar>
Vector3Dim<Scalar>::operator/(Scalar s) const
{
return Vector3Dim<Scalar>(value[0]/s,
value[1]/s,
value[2]/s);
}
/*************************************************************************
Get a particular component of the vector.
\param i Number of Scalar to get
\return Reference to the component
*/
template<class Scalar>
inline Scalar&
Vector3Dim<Scalar>::operator[]( unsigned int i )
{
return value[i];
}
/*************************************************************************
Get a particular component of a constant vector.
\param i Number of Scalar to get
\return Reference to the component
*/
template<class Scalar>
inline const Scalar&
Vector3Dim<Scalar>::operator[]( unsigned int i ) const
{
return value[i];
}
//------------------------------------------------------------------------------
// BLITZ compatibility functions
//------------------------------------------------------------------------------
/*************************************************************************
Compute the scalar product with another vector.
\param v The second vector to work with
\return The value of the scalar product
*/
template<class Scalar>
inline Scalar dot(const Vector3Dim<Scalar> &t, const Vector3Dim<Scalar> &v )
{
//return t.value[0]*v.value[0] + t.value[1]*v.value[1] + t.value[2]*v.value[2];
return ((t[0]*v[0]) + (t[1]*v[1]) + (t[2]*v[2]));
}
/*************************************************************************
Calculate the cross product of this and another vector
*/
template<class Scalar>
inline Vector3Dim<Scalar> cross(const Vector3Dim<Scalar> &t, const Vector3Dim<Scalar> &v)
{
Vector3Dim<Scalar> cp(
((t[1]*v[2]) - (t[2]*v[1])),
((t[2]*v[0]) - (t[0]*v[2])),
((t[0]*v[1]) - (t[1]*v[0])) );
return cp;
}
/*************************************************************************
Compute a vector that is orthonormal to self. Nothing else can be assumed
for the direction of the new vector.
\return The orthonormal vector
*/
template<class Scalar>
Vector3Dim<Scalar>
Vector3Dim<Scalar>::getOrthogonalntlVector3Dim() const
{
// Determine the component with max. absolute value
int max= (fabs(value[0]) > fabs(value[1])) ? 0 : 1;
max= (fabs(value[max]) > fabs(value[2])) ? max : 2;
/*************************************************************************
Choose another axis than the one with max. component and project
orthogonal to self
*/
Vector3Dim<Scalar> vec(0.0);
vec[(max+1)%3]= 1;
vec.normalize();
vec.projectNormalTo(this->getNormalized());
return vec;
}
/*************************************************************************
Projects the vector into a plane normal to the given vector, which must
have unit length. Self is modified.
\param v The plane normal
\return The projected vector
*/
template<class Scalar>
inline const Vector3Dim<Scalar>&
Vector3Dim<Scalar>::projectNormalTo(const Vector3Dim<Scalar> &v)
{
Scalar sprod = dot(*this,v);
value[0]= value[0] - v.value[0] * sprod;
value[1]= value[1] - v.value[1] * sprod;
value[2]= value[2] - v.value[2] * sprod;
return *this;
}
//------------------------------------------------------------------------------
// Other helper functions
//------------------------------------------------------------------------------
/*************************************************************************
Minimize the vector, i.e. set each entry of the vector to the minimum
of both values.
\param pnt The second vector to compare with
\return Reference to the modified self
*/
template<class Scalar>
inline const Vector3Dim<Scalar> &
Vector3Dim<Scalar>::minimize(const Vector3Dim<Scalar> &pnt)
{
for (unsigned int i = 0; i < 3; i++)
value[i] = MIN(value[i],pnt[i]);
return *this;
}
/*************************************************************************
Maximize the vector, i.e. set each entry of the vector to the maximum
of both values.
\param pnt The second vector to compare with
\return Reference to the modified self
*/
template<class Scalar>
inline const Vector3Dim<Scalar> &
Vector3Dim<Scalar>::maximize(const Vector3Dim<Scalar> &pnt)
{
for (unsigned int i = 0; i < 3; i++)
value[i] = MAX(value[i],pnt[i]);
return *this;
}
/************************************************************************/
// HELPER FUNCTIONS, independent of implementation
/************************************************************************/
#define VECTOR_TYPE Vector3Dim<Scalar>
/*************************************************************************
Compute the length (norm) of the vector.
\return The value of the norm
*/
template<class Scalar>
inline Scalar norm( const VECTOR_TYPE &v)
{
Scalar l = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
return (fabs(l-1.) < VECTOR_EPSILON*VECTOR_EPSILON) ? 1. : sqrt(l);
}
// for e.g. min max operator
inline Real normHelper(const Vector3Dim<Real> &v) {
return norm(v);
}
inline Real normHelper(const Real &v) {
return (0. < v) ? v : -v ;
}
inline Real normHelper(const int &v) {
return (0 < v) ? (Real)(v) : (Real)(-v) ;
}
/*************************************************************************
Same as getNorm but doesnt sqrt
*/
template<class Scalar>
inline Scalar normNoSqrt( const VECTOR_TYPE &v)
{
return v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
}
/*************************************************************************
Compute a normalized vector based on this vector.
\return The new normalized vector
*/
template<class Scalar>
inline VECTOR_TYPE getNormalized( const VECTOR_TYPE &v)
{
Scalar l = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
if (fabs(l-1.) < VECTOR_EPSILON*VECTOR_EPSILON)
return v; /* normalized "enough"... */
else if (l > VECTOR_EPSILON*VECTOR_EPSILON)
{
Scalar fac = 1./sqrt(l);
return VECTOR_TYPE(v[0]*fac, v[1]*fac, v[2]*fac);
}
else
return VECTOR_TYPE((Scalar)0);
}
/*************************************************************************
Compute the norm of the vector and normalize it.
\return The value of the norm
*/
template<class Scalar>
inline Scalar normalize( VECTOR_TYPE &v)
{
Scalar norm;
Scalar l = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
if (fabs(l-1.) < VECTOR_EPSILON*VECTOR_EPSILON) {
norm = 1.;
} else if (l > VECTOR_EPSILON*VECTOR_EPSILON) {
norm = sqrt(l);
Scalar fac = 1./norm;
v[0] *= fac;
v[1] *= fac;
v[2] *= fac;
} else {
v[0]= v[1]= v[2]= 0;
norm = 0.;
}
return (Scalar)norm;
}
/*************************************************************************
Compute a vector, that is self (as an incoming
vector) reflected at a surface with a distinct normal vector. Note
that the normal is reversed, if the scalar product with it is positive.
\param n The surface normal
\return The new reflected vector
*/
template<class Scalar>
inline VECTOR_TYPE reflectVector(const VECTOR_TYPE &t, const VECTOR_TYPE &n)
{
VECTOR_TYPE nn= (dot(t, n) > 0.0) ? (n*-1.0) : n;
return ( t - nn * (2.0 * dot(nn, t)) );
}
/*************************************************************************
* My own refraction calculation
* Taken from Glassner's book, section 5.2 (Heckberts method)
*/
template<class Scalar>
inline VECTOR_TYPE refractVector(const VECTOR_TYPE &t, const VECTOR_TYPE &normal, Scalar nt, Scalar nair, int &refRefl)
{
Scalar eta = nair / nt;
Scalar n = -dot(t, normal);
Scalar tt = 1.0 + eta*eta* (n*n-1.0);
if(tt<0.0) {
// we have total reflection!
refRefl = 1;
} else {
// normal reflection
tt = eta*n - sqrt(tt);
return( t*eta + normal*tt );
}
return t;
}
/*************************************************************************
Test two ntlVector3Dims for equality based on the equality of their
values within a small threshold.
\param c The second vector to compare
\return TRUE if both are equal
\sa getEpsilon()
*/
template<class Scalar>
inline bool equal(const VECTOR_TYPE &v, const VECTOR_TYPE &c)
{
return (ABS(v[0]-c[0]) +
ABS(v[1]-c[1]) +
ABS(v[2]-c[2]) < VECTOR_EPSILON);
}
/*************************************************************************
* Assume this vector is an RGB color, and convert it to HSV
*/
template<class Scalar>
inline void rgbToHsv( VECTOR_TYPE &V )
{
Scalar h=0,s=0,v=0;
Scalar maxrgb, minrgb, delta;
// convert to hsv...
maxrgb = V[0];
int maxindex = 1;
if(V[2] > maxrgb){ maxrgb = V[2]; maxindex = 2; }
if(V[1] > maxrgb){ maxrgb = V[1]; maxindex = 3; }
minrgb = V[0];
if(V[2] < minrgb) minrgb = V[2];
if(V[1] < minrgb) minrgb = V[1];
v = maxrgb;
delta = maxrgb-minrgb;
if(maxrgb > 0) s = delta/maxrgb;
else s = 0;
h = 0;
if(s > 0) {
if(maxindex == 1) {
h = ((V[1]-V[2])/delta) + 0.0; }
if(maxindex == 2) {
h = ((V[2]-V[0])/delta) + 2.0; }
if(maxindex == 3) {
h = ((V[0]-V[1])/delta) + 4.0; }
h *= 60.0;
if(h < 0.0) h += 360.0;
}
V[0] = h;
V[1] = s;
V[2] = v;
}
/*************************************************************************
* Assume this vector is HSV and convert to RGB
*/
template<class Scalar>
inline void hsvToRgb( VECTOR_TYPE &V )
{
Scalar h = V[0], s = V[1], v = V[2];
Scalar r=0,g=0,b=0;
Scalar p,q,t, fracth;
int floorh;
// ...and back to rgb
if(s == 0) {
r = g = b = v; }
else {
h /= 60.0;
floorh = (int)h;
fracth = h - floorh;
p = v * (1.0 - s);
q = v * (1.0 - (s * fracth));
t = v * (1.0 - (s * (1.0 - fracth)));
switch (floorh) {
case 0: r = v; g = t; b = p; break;
case 1: r = q; g = v; b = p; break;
case 2: r = p; g = v; b = t; break;
case 3: r = p; g = q; b = v; break;
case 4: r = t; g = p; b = v; break;
case 5: r = v; g = p; b = q; break;
}
}
V[0] = r;
V[1] = g;
V[2] = b;
}
//------------------------------------------------------------------------------
// STREAM FUNCTIONS
//------------------------------------------------------------------------------
//! global string for formatting vector output in utilities.cpp
//extern const char *globVecFormatStr;
static const char *globVecFormatStr = "[%6.4f,%6.4f,%6.4f]";
/*************************************************************************
Outputs the object in human readable form using the format
[x,y,z]
*/
template<class Scalar>
std::ostream&
operator<<( std::ostream& os, const BasicVector::Vector3Dim<Scalar>& i )
{
char buf[256];
#if 0
#if _WIN32
sprintf(buf,globVecFormatStr, (double)i[0],(double)i[1],(double)i[2]);
#else
snprintf(buf,256,globVecFormatStr, (double)i[0],(double)i[1],(double)i[2]);
#endif
os << std::string(buf);
#endif
return os;
}
/*************************************************************************
Reads the contents of the object from a stream using the same format
as the output operator.
*/
template<class Scalar>
std::istream&
operator>>( std::istream& is, BasicVector::Vector3Dim<Scalar>& i )
{
char c;
char dummy[3];
is >> c >> i[0] >> dummy >> i[1] >> dummy >> i[2] >> c;
return is;
}
/**************************************************************************/
// typedefs!
/**************************************************************************/
/* get minimal vector length value that can be discriminated. */
inline Real getVecEpsilon() { return (Real)VECTOR_EPSILON; }
// a 3D integer vector
typedef Vector3Dim<int> Vec3Int;
// a 3D vector
typedef Vector3Dim<Real> Vec3;
}; // namespace
#endif /* BASICVECTOR_H */

View File

@@ -0,0 +1,457 @@
//////////////////////////////////////////////////////////////////////
// This file is part of Wavelet Turbulence.
//
// Wavelet Turbulence 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 3 of the License, or
// (at your option) any later version.
//
// Wavelet Turbulence 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 Wavelet Turbulence. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright 2008 Theodore Kim and Nils Thuerey
//
//////////////////////////////////////////////////////////////////////////////////////////
// Wavelet noise functions
//
// This code is based on the C code provided in the appendices of:
//
// @article{1073264,
// author = {Robert L. Cook and Tony DeRose},
// title = {Wavelet noise},
// journal = {ACM Trans. Graph.},
// volume = {24},
// number = {3},
// year = {2005},
// issn = {0730-0301},
// pages = {803--811},
// doi = {http://doi.acm.org/10.1145/1073204.1073264},
// publisher = {ACM},
// address = {New York, NY, USA},
// }
//
//////////////////////////////////////////////////////////////////////////////////////////
#ifndef WAVELET_NOISE_H
#define WAVELET_NOISE_H
#include <MERSENNETWISTER.h>
#define NOISE_TILE_SIZE 128
static const int noiseTileSize = NOISE_TILE_SIZE;
// warning - noiseTileSize has to be 128^3!
#define modFast128(x) ((x) & 127)
#define modFast64(x) ((x) & 63)
#define DOWNCOEFFS 0.000334f,-0.001528f, 0.000410f, 0.003545f,-0.000938f,-0.008233f, 0.002172f, 0.019120f, \
-0.005040f,-0.044412f, 0.011655f, 0.103311f,-0.025936f,-0.243780f, 0.033979f, 0.655340f, \
0.655340f, 0.033979f,-0.243780f,-0.025936f, 0.103311f, 0.011655f,-0.044412f,-0.005040f, \
0.019120f, 0.002172f,-0.008233f,-0.000938f, 0.003546f, 0.000410f,-0.001528f, 0.000334f
//////////////////////////////////////////////////////////////////////////////////////////
// Wavelet downsampling -- periodic boundary conditions
//////////////////////////////////////////////////////////////////////////////////////////
static void downsampleX(float *from, float *to, int n){
// if these values are not local incorrect results are generated
float downCoeffs[32] = { DOWNCOEFFS };
const float *a = &downCoeffs[16];
for (int i = 0; i < n / 2; i++) {
to[i] = 0;
for (int k = 2 * i - 16; k <= 2 * i + 16; k++)
to[i] += a[k - 2 * i] * from[modFast128(k)];
}
}
static void downsampleY(float *from, float *to, int n){
// if these values are not local incorrect results are generated
float downCoeffs[32] = { DOWNCOEFFS };
const float *a = &downCoeffs[16];
for (int i = 0; i < n / 2; i++) {
to[i * n] = 0;
for (int k = 2 * i - 16; k <= 2 * i + 16; k++)
to[i * n] += a[k - 2 * i] * from[modFast128(k) * n];
}
}
static void downsampleZ(float *from, float *to, int n){
// if these values are not local incorrect results are generated
float downCoeffs[32] = { DOWNCOEFFS };
const float *a = &downCoeffs[16];
for (int i = 0; i < n / 2; i++) {
to[i * n * n] = 0;
for (int k = 2 * i - 16; k <= 2 * i + 16; k++)
to[i * n * n] += a[k - 2 * i] * from[modFast128(k) * n * n];
}
}
//////////////////////////////////////////////////////////////////////////////////////////
// Wavelet downsampling -- Neumann boundary conditions
//////////////////////////////////////////////////////////////////////////////////////////
static void downsampleNeumann(const float *from, float *to, int n, int stride)
{
// if these values are not local incorrect results are generated
float downCoeffs[32] = { DOWNCOEFFS };
static const float *const aCoCenter= &downCoeffs[16];
for (int i = 0; i < n / 2; i++) {
to[i * stride] = 0;
for (int k = 2 * i - 16; k < 2 * i + 16; k++) {
// handle boundary
float fromval;
if (k < 0) {
fromval = from[0];
} else if(k > n - 1) {
fromval = from[(n - 1) * stride];
} else {
fromval = from[k * stride];
}
to[i * stride] += aCoCenter[k - 2 * i] * fromval;
}
}
}
static void downsampleXNeumann(float* to, const float* from, int sx,int sy, int sz) {
for (int iy = 0; iy < sy; iy++)
for (int iz = 0; iz < sz; iz++) {
const int i = iy * sx + iz*sx*sy;
downsampleNeumann(&from[i], &to[i], sx, 1);
}
}
static void downsampleYNeumann(float* to, const float* from, int sx,int sy, int sz) {
for (int ix = 0; ix < sx; ix++)
for (int iz = 0; iz < sz; iz++) {
const int i = ix + iz*sx*sy;
downsampleNeumann(&from[i], &to[i], sy, sx);
}
}
static void downsampleZNeumann(float* to, const float* from, int sx,int sy, int sz) {
for (int ix = 0; ix < sx; ix++)
for (int iy = 0; iy < sy; iy++) {
const int i = ix + iy*sx;
downsampleNeumann(&from[i], &to[i], sz, sx*sy);
}
}
//////////////////////////////////////////////////////////////////////////////////////////
// Wavelet upsampling - periodic boundary conditions
//////////////////////////////////////////////////////////////////////////////////////////
static float _upCoeffs[4] = {0.25f, 0.75f, 0.75f, 0.25f};
static void upsampleX(float *from, float *to, int n) {
const float *p = &_upCoeffs[2];
for (int i = 0; i < n; i++) {
to[i] = 0;
for (int k = i / 2; k <= i / 2 + 1; k++)
to[i] += p[i - 2 * k] * from[modFast64(k)];
}
}
static void upsampleY(float *from, float *to, int n) {
const float *p = &_upCoeffs[2];
for (int i = 0; i < n; i++) {
to[i * n] = 0;
for (int k = i / 2; k <= i / 2 + 1; k++)
to[i * n] += p[i - 2 * k] * from[modFast64(k) * n];
}
}
static void upsampleZ(float *from, float *to, int n) {
const float *p = &_upCoeffs[2];
for (int i = 0; i < n; i++) {
to[i * n * n] = 0;
for (int k = i / 2; k <= i / 2 + 1; k++)
to[i * n * n] += p[i - 2 * k] * from[modFast64(k) * n * n];
}
}
//////////////////////////////////////////////////////////////////////////////////////////
// Wavelet upsampling - Neumann boundary conditions
//////////////////////////////////////////////////////////////////////////////////////////
static void upsampleNeumann(const float *from, float *to, int n, int stride) {
static const float *const pCoCenter = &_upCoeffs[2];
for (int i = 0; i < n; i++) {
to[i * stride] = 0;
for (int k = i / 2; k <= i / 2 + 1; k++) {
float fromval;
if(k>n/2) {
fromval = from[(n/2) * stride];
} else {
fromval = from[k * stride];
}
to[i * stride] += pCoCenter[i - 2 * k] * fromval;
}
}
}
static void upsampleXNeumann(float* to, const float* from, int sx, int sy, int sz) {
for (int iy = 0; iy < sy; iy++)
for (int iz = 0; iz < sz; iz++) {
const int i = iy * sx + iz*sx*sy;
upsampleNeumann(&from[i], &to[i], sx, 1);
}
}
static void upsampleYNeumann(float* to, const float* from, int sx, int sy, int sz) {
for (int ix = 0; ix < sx; ix++)
for (int iz = 0; iz < sz; iz++) {
const int i = ix + iz*sx*sy;
upsampleNeumann(&from[i], &to[i], sy, sx);
}
}
static void upsampleZNeumann(float* to, const float* from, int sx, int sy, int sz) {
for (int ix = 0; ix < sx; ix++)
for (int iy = 0; iy < sy; iy++) {
const int i = ix + iy*sx;
upsampleNeumann(&from[i], &to[i], sz, sx*sy);
}
}
//////////////////////////////////////////////////////////////////////////////////////////
// load in an existing noise tile
//////////////////////////////////////////////////////////////////////////////////////////
static bool loadTile(float* const noiseTileData, std::string filename)
{
FILE* file;
file = fopen(filename.c_str(), "rb");
if (file == NULL) {
printf("loadTile: No noise tile '%s' found.\n", filename.c_str());
return false;
}
// dimensions
int gridSize = noiseTileSize * noiseTileSize * noiseTileSize;
// noiseTileData memory is managed by caller
size_t bread = fread((void*)noiseTileData, sizeof(float), gridSize, file);
fclose(file);
printf("Noise tile file '%s' loaded.\n", filename.c_str());
if (bread != gridSize) {
printf("loadTile: Noise tile '%s' is wrong size %d.\n", filename.c_str(), bread);
return false;
}
return true;
}
//////////////////////////////////////////////////////////////////////////////////////////
// write out an existing noise tile
//////////////////////////////////////////////////////////////////////////////////////////
static void saveTile(float* const noiseTileData, std::string filename)
{
FILE* file;
file = fopen(filename.c_str(), "wb");
if (file == NULL) {
printf("saveTile: Noise tile '%s' could not be saved.\n", filename.c_str());
return;
}
fwrite((void*)noiseTileData, sizeof(float), noiseTileSize * noiseTileSize * noiseTileSize, file);
fclose(file);
printf("saveTile: Noise tile file '%s' saved.\n", filename.c_str());
}
//////////////////////////////////////////////////////////////////////////////////////////
// create a new noise tile if necessary
//////////////////////////////////////////////////////////////////////////////////////////
static void generateTile_WAVELET(float* const noiseTileData, std::string filename) {
// if a tile already exists, just use that
if (loadTile(noiseTileData, filename)) return;
const int n = noiseTileSize;
const int n3 = n*n*n;
std::cout <<"Generating new 3d noise tile size="<<n<<"^3 \n";
MTRand twister;
float *temp13 = new float[n3];
float *temp23 = new float[n3];
float *noise3 = new float[n3];
// initialize
for (int i = 0; i < n3; i++) {
temp13[i] = temp23[i] = noise3[i] = 0.;
}
// Step 1. Fill the tile with random numbers in the range -1 to 1.
for (int i = 0; i < n3; i++)
noise3[i] = twister.randNorm();
// Steps 2 and 3. Downsample and upsample the tile
for (int iy = 0; iy < n; iy++)
for (int iz = 0; iz < n; iz++) {
const int i = iy * n + iz*n*n;
downsampleX(&noise3[i], &temp13[i], n);
upsampleX (&temp13[i], &temp23[i], n);
}
for (int ix = 0; ix < n; ix++)
for (int iz = 0; iz < n; iz++) {
const int i = ix + iz*n*n;
downsampleY(&temp23[i], &temp13[i], n);
upsampleY (&temp13[i], &temp23[i], n);
}
for (int ix = 0; ix < n; ix++)
for (int iy = 0; iy < n; iy++) {
const int i = ix + iy*n;
downsampleZ(&temp23[i], &temp13[i], n);
upsampleZ (&temp13[i], &temp23[i], n);
}
// Step 4. Subtract out the coarse-scale contribution
for (int i = 0; i < n3; i++)
noise3[i] -= temp23[i];
// Avoid even/odd variance difference by adding odd-offset version of noise to itself.
int offset = n / 2;
if (offset % 2 == 0) offset++;
int icnt=0;
for (int ix = 0; ix < n; ix++)
for (int iy = 0; iy < n; iy++)
for (int iz = 0; iz < n; iz++) {
temp13[icnt] = noise3[modFast128(ix+offset) + modFast128(iy+offset)*n + modFast128(iz+offset)*n*n];
icnt++;
}
for (int i = 0; i < n3; i++)
noise3[i] += temp13[i];
for (int i = 0; i < n3; i++)
noiseTileData[i] = noise3[i];
saveTile(noise3, filename);
delete[] temp13;
delete[] temp23;
std::cout <<"Generating new 3d noise done\n";
}
//////////////////////////////////////////////////////////////////////////////////////////
// x derivative of noise
//////////////////////////////////////////////////////////////////////////////////////////
static inline float WNoiseDx(Vec3 p, float* data) {
int c[3], mid[3], n = noiseTileSize;
float w[3][3], t, result = 0;
mid[0] = (int)ceil(p[0] - 0.5);
t = mid[0] - (p[0] - 0.5);
w[0][0] = -t;
w[0][2] = (1.f - t);
w[0][1] = 2.0f * t - 1.0f;
mid[1] = (int)ceil(p[1] - 0.5);
t = mid[1] - (p[1] - 0.5);
w[1][0] = t * t / 2;
w[1][2] = (1 - t) * (1 - t) / 2;
w[1][1] = 1 - w[1][0] - w[1][2];
mid[2] = (int)ceil(p[2] - 0.5);
t = mid[2] - (p[2] - 0.5);
w[2][0] = t * t / 2;
w[2][2] = (1 - t) * (1 - t)/2;
w[2][1] = 1 - w[2][0] - w[2][2];
// to optimize, explicitly unroll this loop
for (int z = -1; z <=1; z++)
for (int y = -1; y <=1; y++)
for (int x = -1; x <=1; x++)
{
float weight = 1.0f;
c[0] = modFast128(mid[0] + x);
weight *= w[0][x+1];
c[1] = modFast128(mid[1] + y);
weight *= w[1][y+1];
c[2] = modFast128(mid[2] + z);
weight *= w[2][z+1];
result += weight * data[c[2]*n*n+c[1]*n+c[0]];
}
return result;
}
//////////////////////////////////////////////////////////////////////////////////////////
// y derivative of noise
//////////////////////////////////////////////////////////////////////////////////////////
static inline float WNoiseDy(Vec3 p, float* data) {
int c[3], mid[3], n=noiseTileSize;
float w[3][3], t, result =0;
mid[0] = (int)ceil(p[0] - 0.5);
t = mid[0]-(p[0] - 0.5);
w[0][0] = t * t / 2;
w[0][2] = (1 - t) * (1 - t) / 2;
w[0][1] = 1 - w[0][0] - w[0][2];
mid[1] = (int)ceil(p[1] - 0.5);
t = mid[1]-(p[1] - 0.5);
w[1][0] = -t;
w[1][2] = (1.f - t);
w[1][1] = 2.0f * t - 1.0f;
mid[2] = (int)ceil(p[2] - 0.5);
t = mid[2] - (p[2] - 0.5);
w[2][0] = t * t / 2;
w[2][2] = (1 - t) * (1 - t)/2;
w[2][1] = 1 - w[2][0] - w[2][2];
// to optimize, explicitly unroll this loop
for (int z = -1; z <=1; z++)
for (int y = -1; y <=1; y++)
for (int x = -1; x <=1; x++)
{
float weight = 1.0f;
c[0] = modFast128(mid[0] + x);
weight *= w[0][x+1];
c[1] = modFast128(mid[1] + y);
weight *= w[1][y+1];
c[2] = modFast128(mid[2] + z);
weight *= w[2][z+1];
result += weight * data[c[2]*n*n+c[1]*n+c[0]];
}
return result;
}
//////////////////////////////////////////////////////////////////////////////////////////
// z derivative of noise
//////////////////////////////////////////////////////////////////////////////////////////
static inline float WNoiseDz(Vec3 p, float* data) {
int c[3], mid[3], n=noiseTileSize;
float w[3][3], t, result =0;
mid[0] = (int)ceil(p[0] - 0.5);
t = mid[0]-(p[0] - 0.5);
w[0][0] = t * t / 2;
w[0][2] = (1 - t) * (1 - t) / 2;
w[0][1] = 1 - w[0][0] - w[0][2];
mid[1] = (int)ceil(p[1] - 0.5);
t = mid[1]-(p[1] - 0.5);
w[1][0] = t * t / 2;
w[1][2] = (1 - t) * (1 - t) / 2;
w[1][1] = 1 - w[1][0] - w[1][2];
mid[2] = (int)ceil(p[2] - 0.5);
t = mid[2] - (p[2] - 0.5);
w[2][0] = -t;
w[2][2] = (1.f - t);
w[2][1] = 2.0f * t - 1.0f;
// to optimize, explicitly unroll this loop
for (int z = -1; z <=1; z++)
for (int y = -1; y <=1; y++)
for (int x = -1; x <=1; x++)
{
float weight = 1.0f;
c[0] = modFast128(mid[0] + x);
weight *= w[0][x+1];
c[1] = modFast128(mid[1] + y);
weight *= w[1][y+1];
c[2] = modFast128(mid[2] + z);
weight *= w[2][z+1];
result += weight * data[c[2]*n*n+c[1]*n+c[0]];
}
return result;
}
#endif

View File

@@ -0,0 +1,965 @@
//////////////////////////////////////////////////////////////////////
// This file is part of Wavelet Turbulence.
//
// Wavelet Turbulence 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 3 of the License, or
// (at your option) any later version.
//
// Wavelet Turbulence 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 Wavelet Turbulence. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright 2008 Theodore Kim and Nils Thuerey
//
// WTURBULENCE handling
///////////////////////////////////////////////////////////////////////////////////
#include "WTURBULENCE.h"
#include "INTERPOLATE.h"
#include "IMAGE.h"
#include <MERSENNETWISTER.h>
#include "WAVELET_NOISE.h"
#include "FFT_NOISE.h"
#include "EIGENVALUE_HELPER.h"
#include "LU_HELPER.h"
#include "SPHERE.h"
#include <zlib.h>
// needed to access static advection functions
#include "FLUID_3D.h"
#if PARALLEL==1
#include <omp.h>
#endif // PARALLEL
// 2^ {-5/6}
static const float persistence = 0.56123f;
//////////////////////////////////////////////////////////////////////
// constructor
//////////////////////////////////////////////////////////////////////
WTURBULENCE::WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify)
{
// if noise magnitude is below this threshold, its contribution
// is negilgible, so stop evaluating new octaves
_cullingThreshold = 1e-3;
// factor by which to increase the simulation resolution
_amplify = amplify;
// manually adjust the overall amount of turbulence
_strength = 2.;
// add the corresponding octaves of noise
_octaves = (int)log((float)_amplify) / log(2.0f); // XXX DEBUG/ TODO: int casting correct? - dg
// noise resolution
_xResBig = _amplify * xResSm;
_yResBig = _amplify * yResSm;
_zResBig = _amplify * zResSm;
_resBig = Vec3Int(_xResBig, _yResBig, _zResBig);
_invResBig = Vec3(1./(float)_resBig[0], 1./(float)_resBig[1], 1./(float)_resBig[2]);
_slabSizeBig = _xResBig*_yResBig;
_totalCellsBig = _slabSizeBig * _zResBig;
// original / small resolution
_xResSm = xResSm;
_yResSm = yResSm;
_zResSm = zResSm;
_resSm = Vec3Int(xResSm, yResSm, zResSm);
_invResSm = Vec3(1./(float)_resSm[0], 1./(float)_resSm[1], 1./(float)_resSm[2] );
_slabSizeSm = _xResSm*_yResSm;
_totalCellsSm = _slabSizeSm * _zResSm;
// allocate high resolution density field
_totalStepsBig = 0;
_densityBig = new float[_totalCellsBig];
_densityBigOld = new float[_totalCellsBig];
// allocate high resolution velocity field. Note that this is only
// necessary because we use MacCormack advection. For semi-Lagrangian
// advection, these arrays are not necessary.
_tempBig1 = _tempBig2 =
_bigUx = _bigUy = _bigUz = NULL;
_tempBig1 = new float[_totalCellsBig];
_tempBig2 = new float[_totalCellsBig];
_bigUx = new float[_totalCellsBig];
_bigUy = new float[_totalCellsBig];
_bigUz = new float[_totalCellsBig];
for(int i = 0; i < _totalCellsBig; i++) {
_densityBig[i] =
_densityBigOld[i] =
_bigUx[i] =
_bigUy[i] =
_bigUz[i] =
_tempBig1[i] =
_tempBig2[i] = 0.;
}
// allocate & init texture coordinates
_tcU = new float[_totalCellsSm];
_tcV = new float[_totalCellsSm];
_tcW = new float[_totalCellsSm];
_tcTemp = new float[_totalCellsSm];
// allocate & init energy terms
_energy = new float[_totalCellsSm];
_highFreqEnergy = new float[_totalCellsSm];
// map all
const float dx = 1./(float)(_resSm[0]);
const float dy = 1./(float)(_resSm[1]);
const float dz = 1./(float)(_resSm[2]);
int index = 0;
for (int z = 0; z < _zResSm; z++)
for (int y = 0; y < _yResSm; y++)
for (int x = 0; x < _xResSm; x++, index++)
{
_tcU[index] = x*dx;
_tcV[index] = y*dy;
_tcW[index] = z*dz;
_tcTemp[index] = 0.;
_energy[index] = 0.;
}
// allocate eigenvalue arrays
_eigMin = new float[_totalCellsSm];
_eigMax = new float[_totalCellsSm];
for(int i=0; i < _totalCellsSm; i++)
_eigMin[i] = _eigMax[i] = 0.;
// noise tiles
_noiseTile = new float[noiseTileSize * noiseTileSize * noiseTileSize];
std::string noiseTileFilename = std::string("noise.wavelets");
generateTile_WAVELET(_noiseTile, noiseTileFilename);
/*
std::string noiseTileFilename = std::string("noise.fft");
generatTile_FFT(_noiseTile, noiseTileFilename);
*/
}
//////////////////////////////////////////////////////////////////////
// destructor
//////////////////////////////////////////////////////////////////////
WTURBULENCE::~WTURBULENCE() {
delete[] _densityBig;
delete[] _densityBigOld;
delete[] _bigUx;
delete[] _bigUy;
delete[] _bigUz;
delete[] _tempBig1;
delete[] _tempBig2;
delete[] _tcU;
delete[] _tcV;
delete[] _tcW;
delete[] _tcTemp;
delete[] _eigMin;
delete[] _eigMax;
delete[] _noiseTile;
delete[] _energy;
delete[] _highFreqEnergy;
}
//////////////////////////////////////////////////////////////////////
// Change noise type
//
// type (1<<1) = wavelet / 2
// type (1<<2) = FFT / 4
// type (1<<3) = curl / 8
//////////////////////////////////////////////////////////////////////
void WTURBULENCE::setNoise(int type)
{
if(type == 4) // FFT
{
// needs fft
// std::string noiseTileFilename = std::string("noise.fft");
// generatTile_FFT(_noiseTile, noiseTileFilename);
}
else if(type == 8) // curl
{
// TODO: not supported yet
}
else // standard - wavelet
{
std::string noiseTileFilename = std::string("noise.wavelets");
generateTile_WAVELET(_noiseTile, noiseTileFilename);
}
}
//////////////////////////////////////////////////////////////////////
// Get the smallest valid x derivative
//
// Takes the one-sided finite difference in both directions and
// selects the smaller of the two
//////////////////////////////////////////////////////////////////////
static float minDx(int x, int y, int z, float* input, Vec3Int res)
{
const int index = x + y * res[0] + z * res[0] * res[1];
const int maxx = res[0]-2;
// get grid values
float center = input[index];
float left = (x <= 1) ? FLT_MAX : input[index - 1];
float right = (x >= maxx) ? FLT_MAX : input[index + 1];
const float dx = res[0];
// get all the derivative estimates
float dLeft = (x <= 1) ? FLT_MAX : (center - left) * dx;
float dRight = (x >= maxx) ? FLT_MAX : (right - center) * dx;
float dCenter = (x <= 1 || x >= maxx) ? FLT_MAX : (right - left) * dx * 0.5f;
// if it's on a boundary, only one estimate is valid
if (x <= 1) return dRight;
if (x >= maxx) return dLeft;
// if it's not on a boundary, get the smallest one
float finalD;
finalD = (fabs(dCenter) < fabs(dRight)) ? dCenter : dRight;
finalD = (fabs(finalD) < fabs(dLeft)) ? finalD : dLeft;
return finalD;
}
//////////////////////////////////////////////////////////////////////
// get the smallest valid y derivative
//
// Takes the one-sided finite difference in both directions and
// selects the smaller of the two
//////////////////////////////////////////////////////////////////////
static float minDy(int x, int y, int z, float* input, Vec3Int res)
{
const int index = x + y * res[0] + z * res[0] * res[1];
const int maxy = res[1]-2;
// get grid values
float center = input[index];
float down = (y <= 1) ? FLT_MAX : input[index - res[0]];
float up = (y >= maxy) ? FLT_MAX : input[index + res[0]];
const float dx = res[1]; // only for square domains
// get all the derivative estimates
float dDown = (y <= 1) ? FLT_MAX : (center - down) * dx;
float dUp = (y >= maxy) ? FLT_MAX : (up - center) * dx;
float dCenter = (y <= 1 || y >= maxy) ? FLT_MAX : (up - down) * dx * 0.5f;
// if it's on a boundary, only one estimate is valid
if (y <= 1) return dUp;
if (y >= maxy) return dDown;
// if it's not on a boundary, get the smallest one
float finalD = (fabs(dCenter) < fabs(dUp)) ? dCenter : dUp;
finalD = (fabs(finalD) < fabs(dDown)) ? finalD : dDown;
return finalD;
}
//////////////////////////////////////////////////////////////////////
// get the smallest valid z derivative
//
// Takes the one-sided finite difference in both directions and
// selects the smaller of the two
//////////////////////////////////////////////////////////////////////
static float minDz(int x, int y, int z, float* input, Vec3Int res)
{
const int slab = res[0]*res[1];
const int index = x + y * res[0] + z * slab;
const int maxz = res[2]-2;
// get grid values
float center = input[index];
float front = (z <= 1) ? FLT_MAX : input[index - slab];
float back = (z >= maxz) ? FLT_MAX : input[index + slab];
const float dx = res[2]; // only for square domains
// get all the derivative estimates
float dfront = (z <= 1) ? FLT_MAX : (center - front) * dx;
float dback = (z >= maxz) ? FLT_MAX : (back - center) * dx;
float dCenter = (z <= 1 || z >= maxz) ? FLT_MAX : (back - front) * dx * 0.5f;
// if it's on a boundary, only one estimate is valid
if (z <= 1) return dback;
if (z >= maxz) return dfront;
// if it's not on a boundary, get the smallest one
float finalD = (fabs(dCenter) < fabs(dback)) ? dCenter : dback;
finalD = (fabs(finalD) < fabs(dfront)) ? finalD : dfront;
return finalD;
}
//////////////////////////////////////////////////////////////////////
// handle texture coordinates (advection, reset, eigenvalues),
// Beware -- uses big density maccormack as temporary arrays
//////////////////////////////////////////////////////////////////////
void WTURBULENCE::advectTextureCoordinates (float dtOrg, float* xvel, float* yvel, float* zvel) {
// advection
SWAP_POINTERS(_tcTemp, _tcU);
FLUID_3D::copyBorderX(_tcTemp, _resSm);
FLUID_3D::copyBorderY(_tcTemp, _resSm);
FLUID_3D::copyBorderZ(_tcTemp, _resSm);
FLUID_3D::advectFieldMacCormack(dtOrg, xvel, yvel, zvel,
_tcTemp, _tcU, _tempBig1, _tempBig2, _resSm, NULL);
SWAP_POINTERS(_tcTemp, _tcV);
FLUID_3D::copyBorderX(_tcTemp, _resSm);
FLUID_3D::copyBorderY(_tcTemp, _resSm);
FLUID_3D::copyBorderZ(_tcTemp, _resSm);
FLUID_3D::advectFieldMacCormack(dtOrg, xvel, yvel, zvel,
_tcTemp, _tcV, _tempBig1, _tempBig2, _resSm, NULL);
SWAP_POINTERS(_tcTemp, _tcW);
FLUID_3D::copyBorderX(_tcTemp, _resSm);
FLUID_3D::copyBorderY(_tcTemp, _resSm);
FLUID_3D::copyBorderZ(_tcTemp, _resSm);
FLUID_3D::advectFieldMacCormack(dtOrg, xvel, yvel, zvel,
_tcTemp, _tcW, _tempBig1, _tempBig2, _resSm, NULL);
}
//////////////////////////////////////////////////////////////////////
// Compute the eigenvalues of the advected texture
//////////////////////////////////////////////////////////////////////
void WTURBULENCE::computeEigenvalues() {
// stats
float maxeig = -1.;
float mineig = 10.;
// texture coordinate eigenvalues
for (int z = 1; z < _zResSm-1; z++) {
for (int y = 1; y < _yResSm-1; y++)
for (int x = 1; x < _xResSm-1; x++)
{
const int index = x+ y *_resSm[0] + z*_slabSizeSm;
// compute jacobian
float jacobian[3][3] = {
{ minDx(x, y, z, _tcU, _resSm), minDx(x, y, z, _tcV, _resSm), minDx(x, y, z, _tcW, _resSm) } ,
{ minDy(x, y, z, _tcU, _resSm), minDy(x, y, z, _tcV, _resSm), minDy(x, y, z, _tcW, _resSm) } ,
{ minDz(x, y, z, _tcU, _resSm), minDz(x, y, z, _tcV, _resSm), minDz(x, y, z, _tcW, _resSm) }
};
// ONLY compute the eigenvalues after checking that the matrix
// is nonsingular
JAMA::LU<float> LU = computeLU3x3(jacobian);
if (LU.isNonsingular())
{
// get the analytic eigenvalues, quite slow right now...
Vec3 eigenvalues = Vec3(1.);
computeEigenvalues3x3( &eigenvalues[0], jacobian);
_eigMax[index] = MAX3V(eigenvalues);
_eigMin[index] = MIN3V(eigenvalues);
maxeig = MAX(_eigMax[index],maxeig);
mineig = MIN(_eigMin[index],mineig);
}
else
{
_eigMax[index] = 10.0f;
_eigMin[index] = 0.1;
}
}
}
}
//////////////////////////////////////////////////////////////////////
// advect & reset texture coordinates based on eigenvalues
//////////////////////////////////////////////////////////////////////
void WTURBULENCE::resetTextureCoordinates()
{
// allowed deformation of the textures
const float limit = 2.f;
const float limitInv = 1./limit;
// standard reset
int resets = 0;
const float dx = 1./(float)(_resSm[0]);
const float dy = 1./(float)(_resSm[1]);
const float dz = 1./(float)(_resSm[2]);
for (int z = 1; z < _zResSm-1; z++)
for (int y = 1; y < _yResSm-1; y++)
for (int x = 1; x < _xResSm-1; x++)
{
const int index = x+ y *_resSm[0] + z*_slabSizeSm;
if (_eigMax[index] > limit || _eigMin[index] < limitInv)
{
_tcU[index] = (float)x * dx;
_tcV[index] = (float)y * dy;
_tcW[index] = (float)z * dz;
resets++;
}
}
}
//////////////////////////////////////////////////////////////////////
// Compute the highest frequency component of the wavelet
// decomposition
//////////////////////////////////////////////////////////////////////
void WTURBULENCE::decomposeEnergy()
{
// do the decomposition -- the goal here is to have
// the energy with the high frequency component stomped out
// stored in _tcTemp when it is done. _highFreqEnergy is only used
// as an additional temp array
// downsample input
downsampleXNeumann(_highFreqEnergy, _energy, _xResSm, _yResSm, _zResSm);
downsampleYNeumann(_tcTemp, _highFreqEnergy, _xResSm, _yResSm, _zResSm);
downsampleZNeumann(_highFreqEnergy, _tcTemp, _xResSm, _yResSm, _zResSm);
// upsample input
upsampleZNeumann(_tcTemp, _highFreqEnergy, _xResSm, _yResSm, _zResSm);
upsampleYNeumann(_highFreqEnergy, _tcTemp, _xResSm, _yResSm, _zResSm);
upsampleXNeumann(_tcTemp, _highFreqEnergy, _xResSm, _yResSm, _zResSm);
// subtract the down and upsampled field from the original field --
// what should be left over is solely the high frequency component
int index = 0;
for (int z = 0; z < _zResSm; z++)
for (int y = 0; y < _yResSm; y++) {
for (int x = 0; x < _xResSm; x++, index++) {
// brute force reset of boundaries
if(z >= _zResSm - 1 || x >= _xResSm - 1 || y >= _yResSm - 1 || z <= 0 || y <= 0 || x <= 0)
_highFreqEnergy[index] = 0.;
else
_highFreqEnergy[index] = _energy[index] - _tcTemp[index];
}
}
}
//////////////////////////////////////////////////////////////////////
// compute velocity from energies and march into obstacles
// for wavelet decomposition
//////////////////////////////////////////////////////////////////////
void WTURBULENCE::computeEnergy(float* xvel, float* yvel, float* zvel, unsigned char *obstacles)
{
// compute everywhere
for (int x = 0; x < _totalCellsSm; x++)
_energy[x] = 0.5f * (xvel[x] * xvel[x] + yvel[x] * yvel[x] + zvel[x] * zvel[x]);
FLUID_3D::copyBorderX(_energy, _resSm);
FLUID_3D::copyBorderY(_energy, _resSm);
FLUID_3D::copyBorderZ(_energy, _resSm);
// pseudo-march the values into the obstacles
// the wavelet upsampler only uses a 3x3 support neighborhood, so
// propagating the values in by 4 should be sufficient
int index;
// iterate
for (int iter = 0; iter < 4; iter++)
{
index = _slabSizeSm + _xResSm + 1;
for (int z = 1; z < _zResSm - 1; z++, index += 2 * _xResSm)
for (int y = 1; y < _yResSm - 1; y++, index += 2)
for (int x = 1; x < _xResSm - 1; x++, index++)
if (obstacles[index] && obstacles[index] != RETIRED)
{
float sum = 0.0f;
int valid = 0;
if (!obstacles[index + 1] || obstacles[index + 1] == RETIRED)
{
sum += _energy[index + 1];
valid++;
}
if (!obstacles[index - 1] || obstacles[index - 1] == RETIRED)
{
sum += _energy[index - 1];
valid++;
}
if (!obstacles[index + _xResSm] || obstacles[index + _xResSm] == RETIRED)
{
sum += _energy[index + _xResSm];
valid++;
}
if (!obstacles[index - _xResSm] || obstacles[index - _xResSm] == RETIRED)
{
sum += _energy[index - _xResSm];
valid++;
}
if (!obstacles[index + _slabSizeSm] || obstacles[index + _slabSizeSm] == RETIRED)
{
sum += _energy[index + _slabSizeSm];
valid++;
}
if (!obstacles[index - _slabSizeSm] || obstacles[index - _slabSizeSm] == RETIRED)
{
sum += _energy[index - _slabSizeSm];
valid++;
}
if (valid > 0)
{
_energy[index] = sum / valid;
obstacles[index] = MARCHED;
}
}
index = _slabSizeSm + _xResSm + 1;
for (int z = 1; z < _zResSm - 1; z++, index += 2 * _xResSm)
for (int y = 1; y < _yResSm - 1; y++, index += 2)
for (int x = 1; x < _xResSm - 1; x++, index++)
if (obstacles[index] == MARCHED)
obstacles[index] = RETIRED;
}
index = _slabSizeSm + _xResSm + 1;
for (int z = 1; z < _zResSm - 1; z++, index += 2 * _xResSm)
for (int y = 1; y < _yResSm - 1; y++, index += 2)
for (int x = 1; x < _xResSm - 1; x++, index++)
if (obstacles[index])
obstacles[index] = 1;
}
//////////////////////////////////////////////////////////////////////////////////////////
// Evaluate derivatives
//////////////////////////////////////////////////////////////////////////////////////////
Vec3 WTURBULENCE::WVelocity(Vec3 orgPos)
{
// arbitrarily offset evaluation points
const Vec3 p1 = orgPos + Vec3(NOISE_TILE_SIZE/2,0,0);
const Vec3 p2 = orgPos + Vec3(0,NOISE_TILE_SIZE/2,0);
const Vec3 p3 = orgPos + Vec3(0,0,NOISE_TILE_SIZE/2);
const float f1y = WNoiseDy(p1, _noiseTile);
const float f1z = WNoiseDz(p1, _noiseTile);
const float f2x = WNoiseDx(p2, _noiseTile);
const float f2z = WNoiseDz(p2, _noiseTile);
const float f3x = WNoiseDx(p3, _noiseTile);
const float f3y = WNoiseDy(p3, _noiseTile);
Vec3 ret = Vec3(
f3y - f2z,
f1z - f3x,
f2x - f1y );
return ret;
}
//////////////////////////////////////////////////////////////////////////////////////////
// Evaluate derivatives with Jacobian
//////////////////////////////////////////////////////////////////////////////////////////
Vec3 WTURBULENCE::WVelocityWithJacobian(Vec3 orgPos, float* xUnwarped, float* yUnwarped, float* zUnwarped)
{
// arbitrarily offset evaluation points
const Vec3 p1 = orgPos + Vec3(NOISE_TILE_SIZE/2,0,0);
const Vec3 p2 = orgPos + Vec3(0,NOISE_TILE_SIZE/2,0);
const Vec3 p3 = orgPos + Vec3(0,0,NOISE_TILE_SIZE/2);
Vec3 final;
final[0] = WNoiseDx(p1, _noiseTile);
final[1] = WNoiseDy(p1, _noiseTile);
final[2] = WNoiseDz(p1, _noiseTile);
// UNUSED const float f1x = xUnwarped[0] * final[0] + xUnwarped[1] * final[1] + xUnwarped[2] * final[2];
const float f1y = yUnwarped[0] * final[0] + yUnwarped[1] * final[1] + yUnwarped[2] * final[2];
const float f1z = zUnwarped[0] * final[0] + zUnwarped[1] * final[1] + zUnwarped[2] * final[2];
final[0] = WNoiseDx(p2, _noiseTile);
final[1] = WNoiseDy(p2, _noiseTile);
final[2] = WNoiseDz(p2, _noiseTile);
const float f2x = xUnwarped[0] * final[0] + xUnwarped[1] * final[1] + xUnwarped[2] * final[2];
// UNUSED const float f2y = yUnwarped[0] * final[0] + yUnwarped[1] * final[1] + yUnwarped[2] * final[2];
const float f2z = zUnwarped[0] * final[0] + zUnwarped[1] * final[1] + zUnwarped[2] * final[2];
final[0] = WNoiseDx(p3, _noiseTile);
final[1] = WNoiseDy(p3, _noiseTile);
final[2] = WNoiseDz(p3, _noiseTile);
const float f3x = xUnwarped[0] * final[0] + xUnwarped[1] * final[1] + xUnwarped[2] * final[2];
const float f3y = yUnwarped[0] * final[0] + yUnwarped[1] * final[1] + yUnwarped[2] * final[2];
// UNUSED const float f3z = zUnwarped[0] * final[0] + zUnwarped[1] * final[1] + zUnwarped[2] * final[2];
Vec3 ret = Vec3(
f3y - f2z,
f1z - f3x,
f2x - f1y );
return ret;
}
//////////////////////////////////////////////////////////////////////
// perform an actual noise advection step
//////////////////////////////////////////////////////////////////////
void WTURBULENCE::stepTurbulenceReadable(float dtOrg, float* xvel, float* yvel, float* zvel, unsigned char *obstacles)
{
// enlarge timestep to match grid
const float dt = dtOrg * _amplify;
const float invAmp = 1.0f / _amplify;
// prepare textures
advectTextureCoordinates(dtOrg, xvel,yvel,zvel);
// compute eigenvalues of the texture coordinates
computeEigenvalues();
// do wavelet decomposition of energy
computeEnergy(xvel, yvel, zvel, obstacles);
decomposeEnergy();
// zero out coefficients inside of the obstacle
for (int x = 0; x < _totalCellsSm; x++)
if (obstacles[x]) _energy[x] = 0.f;
float maxVelocity = 0.;
for (int z = 1; z < _zResBig - 1; z++)
for (int y = 1; y < _yResBig - 1; y++)
for (int x = 1; x < _xResBig - 1; x++)
{
// get unit position for both fine and coarse grid
const Vec3 pos = Vec3(x,y,z);
const Vec3 posSm = pos * invAmp;
// get grid index for both fine and coarse grid
const int index = x + y *_xResBig + z *_slabSizeBig;
const int indexSmall = (int)posSm[0] + (int)posSm[1] * _xResSm + (int)posSm[2] * _slabSizeSm;
// get a linearly interpolated velocity and texcoords
// from the coarse grid
Vec3 vel = INTERPOLATE::lerp3dVec( xvel,yvel,zvel,
posSm[0], posSm[1], posSm[2], _xResSm,_yResSm,_zResSm);
Vec3 uvw = INTERPOLATE::lerp3dVec( _tcU,_tcV,_tcW,
posSm[0], posSm[1], posSm[2], _xResSm,_yResSm,_zResSm);
// multiply the texture coordinate by _resSm so that turbulence
// synthesis begins at the first octave that the coarse grid
// cannot capture
Vec3 texCoord = Vec3(uvw[0] * _resSm[0],
uvw[1] * _resSm[1],
uvw[2] * _resSm[2]);
// retrieve wavelet energy at highest frequency
float energy = INTERPOLATE::lerp3d(
_highFreqEnergy, posSm[0],posSm[1],posSm[2], _xResSm, _yResSm, _zResSm);
// base amplitude for octave 0
float coefficient = sqrtf(2.0f * fabs(energy));
const float amplitude = _strength * fabs(0.5 * coefficient) * persistence;
// add noise to velocity, but only if the turbulence is
// sufficiently undeformed, and the energy is large enough
// to make a difference
const bool addNoise = _eigMax[indexSmall] < 2. &&
_eigMin[indexSmall] > 0.5;
if (addNoise && amplitude > _cullingThreshold) {
// base amplitude for octave 0
float amplitudeScaled = amplitude;
for (int octave = 0; octave < _octaves; octave++)
{
// multiply the vector noise times the maximum allowed
// noise amplitude at this octave, and add it to the total
vel += WVelocity(texCoord) * amplitudeScaled;
// scale coefficient for next octave
amplitudeScaled *= persistence;
texCoord *= 2.0f;
}
}
// Store velocity + turbulence in big grid for maccormack step
//
// If you wanted to save memory, you would instead perform a
// semi-Lagrangian backtrace for the current grid cell here. Then
// you could just throw the velocity away.
_bigUx[index] = vel[0];
_bigUy[index] = vel[1];
_bigUz[index] = vel[2];
// compute the velocity magnitude for substepping later
const float velMag = _bigUx[index] * _bigUx[index] +
_bigUy[index] * _bigUy[index] +
_bigUz[index] * _bigUz[index];
if (velMag > maxVelocity) maxVelocity = velMag;
// zero out velocity inside obstacles
float obsCheck = INTERPOLATE::lerp3dToFloat(
obstacles, posSm[0], posSm[1], posSm[2], _xResSm, _yResSm, _zResSm);
if (obsCheck > 0.95)
_bigUx[index] = _bigUy[index] = _bigUz[index] = 0.;
}
// prepare density for an advection
SWAP_POINTERS(_densityBig, _densityBigOld);
// based on the maximum velocity present, see if we need to substep,
// but cap the maximum number of substeps to 5
const int maxSubSteps = 25;
const int maxVel = 5;
maxVelocity = sqrt(maxVelocity) * dt;
int totalSubsteps = (int)(maxVelocity / (float)maxVel);
totalSubsteps = (totalSubsteps < 1) ? 1 : totalSubsteps;
totalSubsteps = (totalSubsteps > maxSubSteps) ? maxSubSteps : totalSubsteps;
const float dtSubdiv = dt / (float)totalSubsteps;
// set boundaries of big velocity grid
FLUID_3D::setZeroX(_bigUx, _resBig);
FLUID_3D::setZeroY(_bigUy, _resBig);
FLUID_3D::setZeroZ(_bigUz, _resBig);
// do the MacCormack advection, with substepping if necessary
for(int substep = 0; substep < totalSubsteps; substep++)
{
FLUID_3D::advectFieldMacCormack(dtSubdiv, _bigUx, _bigUy, _bigUz,
_densityBigOld, _densityBig, _tempBig1, _tempBig2, _resBig, NULL);
if (substep < totalSubsteps - 1)
SWAP_POINTERS(_densityBig, _densityBigOld);
} // substep
// wipe the density borders
FLUID_3D::setZeroBorder(_densityBig, _resBig);
// reset texture coordinates now in preparation for next timestep
// Shouldn't do this before generating the noise because then the
// eigenvalues stored do not reflect the underlying texture coordinates
resetTextureCoordinates();
// output files
/*
string prefix = string("./amplified.preview/density_bigxy_");
FLUID_3D::writeImageSliceXY(_densityBig, _resBig, _resBig[2]/2, prefix, _totalStepsBig, 1.0f);
//string df3Prefix = string("./df3/density_big_");
//IMAGE::dumpDF3(_totalStepsBig, df3Prefix, _densityBig, _resBig[0],_resBig[1],_resBig[2]);
string pbrtPrefix = string("./pbrt/density_big_");
IMAGE::dumpPBRT(_totalStepsBig, pbrtPrefix, _densityBig, _resBig[0],_resBig[1],_resBig[2]);
*/
_totalStepsBig++;
}
//////////////////////////////////////////////////////////////////////
// perform the full turbulence algorithm, including OpenMP
// if available
//////////////////////////////////////////////////////////////////////
void WTURBULENCE::stepTurbulenceFull(float dtOrg, float* xvel, float* yvel, float* zvel, unsigned char *obstacles)
{
// enlarge timestep to match grid
const float dt = dtOrg * _amplify;
const float invAmp = 1.0f / _amplify;
// prepare textures
advectTextureCoordinates(dtOrg, xvel,yvel,zvel);
// do wavelet decomposition of energy
computeEnergy(xvel, yvel, zvel, obstacles);
decomposeEnergy();
// zero out coefficients inside of the obstacle
for (int x = 0; x < _totalCellsSm; x++)
if (obstacles[x]) _energy[x] = 0.f;
// parallel region setup
float maxVelMagThreads[8] = { -1., -1., -1., -1., -1., -1., -1., -1. };
#if PARALLEL==1
#pragma omp parallel
#endif
{ float maxVelMag1 = 0.;
#if PARALLEL==1
const int id = omp_get_thread_num(), num = omp_get_num_threads();
#endif
// vector noise main loop
#if PARALLEL==1
#pragma omp for schedule(static)
#endif
for (int zSmall = 0; zSmall < _zResSm; zSmall++)
for (int ySmall = 0; ySmall < _yResSm; ySmall++)
for (int xSmall = 0; xSmall < _xResSm; xSmall++)
{
const int indexSmall = xSmall + ySmall * _xResSm + zSmall * _slabSizeSm;
// compute jacobian
float jacobian[3][3] = {
{ minDx(xSmall, ySmall, zSmall, _tcU, _resSm), minDx(xSmall, ySmall, zSmall, _tcV, _resSm), minDx(xSmall, ySmall, zSmall, _tcW, _resSm) } ,
{ minDy(xSmall, ySmall, zSmall, _tcU, _resSm), minDy(xSmall, ySmall, zSmall, _tcV, _resSm), minDy(xSmall, ySmall, zSmall, _tcW, _resSm) } ,
{ minDz(xSmall, ySmall, zSmall, _tcU, _resSm), minDz(xSmall, ySmall, zSmall, _tcV, _resSm), minDz(xSmall, ySmall, zSmall, _tcW, _resSm) }
};
// get LU factorization of texture jacobian and apply
// it to unit vectors
JAMA::LU<float> LU = computeLU3x3(jacobian);
float xUnwarped[] = {1.0f, 0.0f, 0.0f};
float yUnwarped[] = {0.0f, 1.0f, 0.0f};
float zUnwarped[] = {0.0f, 0.0f, 1.0f};
float xWarped[] = {1.0f, 0.0f, 0.0f};
float yWarped[] = {0.0f, 1.0f, 0.0f};
float zWarped[] = {0.0f, 0.0f, 1.0f};
bool nonSingular = LU.isNonsingular();
#if 0
// UNUSED
float eigMax = 10.0f;
float eigMin = 0.1f;
#endif
if (nonSingular)
{
solveLU3x3(LU, xUnwarped, xWarped);
solveLU3x3(LU, yUnwarped, yWarped);
solveLU3x3(LU, zUnwarped, zWarped);
// compute the eigenvalues while we have the Jacobian available
Vec3 eigenvalues = Vec3(1.);
computeEigenvalues3x3( &eigenvalues[0], jacobian);
_eigMax[indexSmall] = MAX3V(eigenvalues);
_eigMin[indexSmall] = MIN3V(eigenvalues);
}
// make sure to skip one on the beginning and end
int xStart = (xSmall == 0) ? 1 : 0;
int xEnd = (xSmall == _xResSm - 1) ? _amplify - 1 : _amplify;
int yStart = (ySmall == 0) ? 1 : 0;
int yEnd = (ySmall == _yResSm - 1) ? _amplify - 1 : _amplify;
int zStart = (zSmall == 0) ? 1 : 0;
int zEnd = (zSmall == _zResSm - 1) ? _amplify - 1 : _amplify;
for (int zBig = zStart; zBig < zEnd; zBig++)
for (int yBig = yStart; yBig < yEnd; yBig++)
for (int xBig = xStart; xBig < xEnd; xBig++)
{
const int x = xSmall * _amplify + xBig;
const int y = ySmall * _amplify + yBig;
const int z = zSmall * _amplify + zBig;
// get unit position for both fine and coarse grid
const Vec3 pos = Vec3(x,y,z);
const Vec3 posSm = pos * invAmp;
// get grid index for both fine and coarse grid
const int index = x + y *_xResBig + z *_slabSizeBig;
// get a linearly interpolated velocity and texcoords
// from the coarse grid
Vec3 vel = INTERPOLATE::lerp3dVec( xvel,yvel,zvel,
posSm[0], posSm[1], posSm[2], _xResSm,_yResSm,_zResSm);
Vec3 uvw = INTERPOLATE::lerp3dVec( _tcU,_tcV,_tcW,
posSm[0], posSm[1], posSm[2], _xResSm,_yResSm,_zResSm);
// multiply the texture coordinate by _resSm so that turbulence
// synthesis begins at the first octave that the coarse grid
// cannot capture
Vec3 texCoord = Vec3(uvw[0] * _resSm[0],
uvw[1] * _resSm[1],
uvw[2] * _resSm[2]);
// retrieve wavelet energy at highest frequency
float energy = INTERPOLATE::lerp3d(
_highFreqEnergy, posSm[0],posSm[1],posSm[2], _xResSm, _yResSm, _zResSm);
// base amplitude for octave 0
float coefficient = sqrtf(2.0f * fabs(energy));
const float amplitude = _strength * fabs(0.5 * coefficient) * persistence;
// add noise to velocity, but only if the turbulence is
// sufficiently undeformed, and the energy is large enough
// to make a difference
const bool addNoise = _eigMax[indexSmall] < 2. &&
_eigMin[indexSmall] > 0.5;
if (addNoise && amplitude > _cullingThreshold) {
// base amplitude for octave 0
float amplitudeScaled = amplitude;
for (int octave = 0; octave < _octaves; octave++)
{
// multiply the vector noise times the maximum allowed
// noise amplitude at this octave, and add it to the total
vel += WVelocityWithJacobian(texCoord, &xUnwarped[0], &yUnwarped[0], &zUnwarped[0]) * amplitudeScaled;
// scale coefficient for next octave
amplitudeScaled *= persistence;
texCoord *= 2.0f;
}
}
// Store velocity + turbulence in big grid for maccormack step
//
// If you wanted to save memory, you would instead perform a
// semi-Lagrangian backtrace for the current grid cell here. Then
// you could just throw the velocity away.
_bigUx[index] = vel[0];
_bigUy[index] = vel[1];
_bigUz[index] = vel[2];
// compute the velocity magnitude for substepping later
const float velMag = _bigUx[index] * _bigUx[index] +
_bigUy[index] * _bigUy[index] +
_bigUz[index] * _bigUz[index];
if (velMag > maxVelMag1) maxVelMag1 = velMag;
// zero out velocity inside obstacles
float obsCheck = INTERPOLATE::lerp3dToFloat(
obstacles, posSm[0], posSm[1], posSm[2], _xResSm, _yResSm, _zResSm);
if (obsCheck > 0.95)
_bigUx[index] = _bigUy[index] = _bigUz[index] = 0.;
} // xyz
#if PARALLEL==1
maxVelMagThreads[id] = maxVelMag1;
#else
maxVelMagThreads[0] = maxVelMag1;
#endif
}
} // omp
// compute maximum over threads
float maxVelMag = maxVelMagThreads[0];
#if PARALLEL==1
for (int i = 1; i < 8; i++)
if (maxVelMag < maxVelMagThreads[i])
maxVelMag = maxVelMagThreads[i];
#endif
// prepare density for an advection
SWAP_POINTERS(_densityBig, _densityBigOld);
// based on the maximum velocity present, see if we need to substep,
// but cap the maximum number of substeps to 5
const int maxSubSteps = 25;
const int maxVel = 5;
maxVelMag = sqrt(maxVelMag) * dt;
int totalSubsteps = (int)(maxVelMag / (float)maxVel);
totalSubsteps = (totalSubsteps < 1) ? 1 : totalSubsteps;
totalSubsteps = (totalSubsteps > maxSubSteps) ? maxSubSteps : totalSubsteps;
const float dtSubdiv = dt / (float)totalSubsteps;
// set boundaries of big velocity grid
FLUID_3D::setZeroX(_bigUx, _resBig);
FLUID_3D::setZeroY(_bigUy, _resBig);
FLUID_3D::setZeroZ(_bigUz, _resBig);
// do the MacCormack advection, with substepping if necessary
for(int substep = 0; substep < totalSubsteps; substep++)
{
FLUID_3D::advectFieldMacCormack(dtSubdiv, _bigUx, _bigUy, _bigUz,
_densityBigOld, _densityBig, _tempBig1, _tempBig2, _resBig, NULL);
if (substep < totalSubsteps - 1)
SWAP_POINTERS(_densityBig, _densityBigOld);
} // substep
// wipe the density borders
FLUID_3D::setZeroBorder(_densityBig, _resBig);
// reset texture coordinates now in preparation for next timestep
// Shouldn't do this before generating the noise because then the
// eigenvalues stored do not reflect the underlying texture coordinates
resetTextureCoordinates();
// output files
// string prefix = string("./amplified.preview/density_bigxy_");
// FLUID_3D::writeImageSliceXY(_densityBig, _resBig, _resBig[2]/2, prefix, _totalStepsBig, 1.0f);
//string df3prefix = string("./df3/density_big_");
//IMAGE::dumpDF3(_totalStepsBig, df3prefix, _densityBig, _resBig[0],_resBig[1],_resBig[2]);
// string pbrtPrefix = string("./pbrt/density_big_");
// IMAGE::dumpPBRT(_totalStepsBig, pbrtPrefix, _densityBig, _resBig[0],_resBig[1],_resBig[2]);
_totalStepsBig++;
}

View File

@@ -0,0 +1,147 @@
//////////////////////////////////////////////////////////////////////
// This file is part of Wavelet Turbulence.
//
// Wavelet Turbulence 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 3 of the License, or
// (at your option) any later version.
//
// Wavelet Turbulence 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 Wavelet Turbulence. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright 2008 Theodore Kim and Nils Thuerey
//
// WTURBULENCE handling
///////////////////////////////////////////////////////////////////////////////////
#ifndef WTURBULENCE_H
#define WTURBULENCE_H
#include "VEC3.h"
using namespace BasicVector;
class SIMPLE_PARSER;
///////////////////////////////////////////////////////////////////////////////
/// Main WTURBULENCE class, stores large density array etc.
///////////////////////////////////////////////////////////////////////////////
class WTURBULENCE
{
public:
// both config files can be NULL, altCfg might override values from noiseCfg
WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify);
/// destructor
virtual ~WTURBULENCE();
void setNoise(int type);
// step more readable version -- no rotation correction
void stepTurbulenceReadable(float dt, float* xvel, float* yvel, float* zvel, unsigned char *obstacles);
// step more complete version -- include rotation correction
// and use OpenMP if available
void stepTurbulenceFull(float dt, float* xvel, float* yvel, float* zvel, unsigned char *obstacles);
// texcoord functions
void advectTextureCoordinates(float dtOrg, float* xvel, float* yvel, float* zvel);
void resetTextureCoordinates();
void computeEnergy(float* xvel, float* yvel, float* zvel, unsigned char *obstacles);
// evaluate wavelet noise function
Vec3 WVelocity(Vec3 p);
Vec3 WVelocityWithJacobian(Vec3 p, float* xUnwarped, float* yUnwarped, float* zUnwarped);
// access functions
inline float* getDensityBig() { return _densityBig; }
inline float* getArrayTcU() { return _tcU; }
inline float* getArrayTcV() { return _tcV; }
inline float* getArrayTcW() { return _tcW; }
inline float* getArrayEigMin() { return _eigMin; }
inline float* getArrayEigMax() { return _eigMax; }
inline Vec3Int getResSm() { return _resSm; } // small resolution
inline Vec3Int getResBig() { return _resBig; }
inline int getOctaves() { return _octaves; }
protected:
// enlargement factor from original velocity field / simulation
// _Big = _amplify * _Sm
int _amplify;
int _octaves;
float _strength;
// noise settings
float _cullingThreshold;
float _noiseStrength;
float _noiseSizeScale;
bool _uvwAdvection;
bool _uvwReset;
float _noiseTimeanimSpeed;
int _dumpInterval;
int _noiseControlType;
// debug, scale density for projections output images
float _outputScale;
// noise resolution
int _xResBig;
int _yResBig;
int _zResBig;
Vec3Int _resBig;
Vec3 _invResBig;
int _totalCellsBig;
int _slabSizeBig;
// original / small resolution
int _xResSm;
int _yResSm;
int _zResSm;
Vec3Int _resSm;
Vec3 _invResSm;
int _totalCellsSm;
int _slabSizeSm;
float* _densityBig;
float* _densityBigOld;
// big velocity macCormack fields
float* _bigUx;
float* _bigUy;
float* _bigUz;
// temp arrays for BFECC and MacCormack - they have more convenient
// names in the actual implementations
float* _tempBig1;
float* _tempBig2;
// texture coordinates for noise
float* _tcU;
float* _tcV;
float* _tcW;
float* _tcTemp;
float* _eigMin;
float* _eigMax;
// wavelet decomposition of velocity energies
float* _energy;
// noise data
float* _noiseTile;
//float* _noiseTileExt;
// step counter
int _totalStepsBig;
// highest frequency component of wavelet decomposition
float* _highFreqEnergy;
void computeEigenvalues();
void decomposeEnergy();
};
#endif // WTURBULENCE_H

View File

@@ -0,0 +1,121 @@
/**
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2009 by Daniel Genrich
* All rights reserved.
*
* Contributor(s): None
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "FLUID_3D.h"
#include <stdio.h>
#include <stdlib.h>
// y in smoke is z in blender
extern "C" FLUID_3D *smoke_init(int *res, int amplify, float *p0, float *p1, float dt)
{
// smoke lib uses y as top-bottom/vertical axis where blender uses z
FLUID_3D *fluid = new FLUID_3D(res, amplify, p0, dt);
// printf("xres: %d, yres: %d, zres: %d\n", res[0], res[1], res[2]);
return fluid;
}
extern "C" void smoke_free(FLUID_3D *fluid)
{
delete fluid;
fluid = NULL;
}
extern "C" void smoke_step(FLUID_3D *fluid)
{
fluid->step();
}
extern "C" void smoke_initBlenderRNA(FLUID_3D *fluid, float *alpha, float *beta)
{
fluid->initBlenderRNA(alpha, beta);
}
template < class T > inline T ABS( T a ) {
return (0 < a) ? a : -a ;
}
extern "C" float *smoke_get_density(FLUID_3D *fluid)
{
return fluid->_density;
}
extern "C" float *smoke_get_heat(FLUID_3D *fluid)
{
return fluid->_heat;
}
extern "C" float *smoke_get_velocity_x(FLUID_3D *fluid)
{
return fluid->_xVorticity;
}
extern "C" float *smoke_get_velocity_y(FLUID_3D *fluid)
{
return fluid->_yVorticity;
}
extern "C" float *smoke_get_velocity_z(FLUID_3D *fluid)
{
return fluid->_zVorticity;
}
extern "C" float *smoke_get_bigdensity(FLUID_3D *fluid)
{
return fluid->_wTurbulence->getDensityBig();
}
extern "C" void smoke_get_bigres(FLUID_3D *fluid, int *res)
{
Vec3Int r = fluid->_wTurbulence->getResBig();
res[0] = r[0];
res[1] = r[1];
res[2] = r[2];
}
extern "C" unsigned char *smoke_get_obstacle(FLUID_3D *fluid)
{
return fluid->_obstacles;
}
extern "C" size_t smoke_get_index(int x, int max_x, int y, int max_y, int z /*, int max_z */)
{
// // const int index = x + y * smd->res[0] + z * smd->res[0]*smd->res[1];
return x + y * max_x + z * max_x*max_y;
}
extern "C" size_t smoke_get_index2d(int x, int max_x, int y /*, int max_y, int z, int max_z */)
{
return x + y * max_x;
}
extern "C" void smoke_set_noise(FLUID_3D *fluid, int type)
{
fluid->_wTurbulence->setNoise(type);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,319 @@
#ifndef JAMA_LU_H
#define JAMA_LU_H
#include "tnt.h"
#include <algorithm>
//for min(), max() below
using namespace TNT;
using namespace std;
namespace JAMA
{
/** LU Decomposition.
<P>
For an m-by-n matrix A with m >= n, the LU decomposition is an m-by-n
unit lower triangular matrix L, an n-by-n upper triangular matrix U,
and a permutation vector piv of length m so that A(piv,:) = L*U.
If m < n, then L is m-by-m and U is m-by-n.
<P>
The LU decompostion with pivoting always exists, even if the matrix is
singular, so the constructor will never fail. The primary use of the
LU decomposition is in the solution of square systems of simultaneous
linear equations. This will fail if isNonsingular() returns false.
*/
template <class Real>
class LU
{
/* Array for internal storage of decomposition. */
Array2D<Real> LU_;
int m, n, pivsign;
Array1D<int> piv;
Array2D<Real> permute_copy(const Array2D<Real> &A,
const Array1D<int> &piv, int j0, int j1)
{
int piv_length = piv.dim();
Array2D<Real> X(piv_length, j1-j0+1);
for (int i = 0; i < piv_length; i++)
for (int j = j0; j <= j1; j++)
X[i][j-j0] = A[piv[i]][j];
return X;
}
Array1D<Real> permute_copy(const Array1D<Real> &A,
const Array1D<int> &piv)
{
int piv_length = piv.dim();
if (piv_length != A.dim())
return Array1D<Real>();
Array1D<Real> x(piv_length);
for (int i = 0; i < piv_length; i++)
x[i] = A[piv[i]];
return x;
}
public :
/** LU Decomposition
@param A Rectangular matrix
@return LU Decomposition object to access L, U and piv.
*/
LU (const Array2D<Real> &A) : LU_(A.copy()), m(A.dim1()), n(A.dim2()),
piv(A.dim1())
{
// Use a "left-looking", dot-product, Crout/Doolittle algorithm.
for (int i = 0; i < m; i++) {
piv[i] = i;
}
pivsign = 1;
Real *LUrowi = 0;;
Array1D<Real> LUcolj(m);
// Outer loop.
for (int j = 0; j < n; j++) {
// Make a copy of the j-th column to localize references.
for (int i = 0; i < m; i++) {
LUcolj[i] = LU_[i][j];
}
// Apply previous transformations.
for (int i = 0; i < m; i++) {
LUrowi = LU_[i];
// Most of the time is spent in the following dot product.
int kmax = min(i,j);
double s = 0.0;
for (int k = 0; k < kmax; k++) {
s += LUrowi[k]*LUcolj[k];
}
LUrowi[j] = LUcolj[i] -= s;
}
// Find pivot and exchange if necessary.
int p = j;
for (int i = j+1; i < m; i++) {
if (abs(LUcolj[i]) > abs(LUcolj[p])) {
p = i;
}
}
if (p != j) {
int k=0;
for (k = 0; k < n; k++) {
double t = LU_[p][k];
LU_[p][k] = LU_[j][k];
LU_[j][k] = t;
}
k = piv[p];
piv[p] = piv[j];
piv[j] = k;
pivsign = -pivsign;
}
// Compute multipliers.
if ((j < m) && (LU_[j][j] != 0.0)) {
for (int i = j+1; i < m; i++) {
LU_[i][j] /= LU_[j][j];
}
}
}
}
/** Is the matrix nonsingular?
@return 1 (true) if upper triangular factor U (and hence A)
is nonsingular, 0 otherwise.
*/
int isNonsingular () {
for (int j = 0; j < n; j++) {
if (LU_[j][j] == 0)
return 0;
}
return 1;
}
/** Return lower triangular factor
@return L
*/
Array2D<Real> getL () {
Array2D<Real> L_(m,n);
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (i > j) {
L_[i][j] = LU_[i][j];
} else if (i == j) {
L_[i][j] = 1.0;
} else {
L_[i][j] = 0.0;
}
}
}
return L_;
}
/** Return upper triangular factor
@return U portion of LU factorization.
*/
Array2D<Real> getU () {
Array2D<Real> U_(n,n);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i <= j) {
U_[i][j] = LU_[i][j];
} else {
U_[i][j] = 0.0;
}
}
}
return U_;
}
/** Return pivot permutation vector
@return piv
*/
Array1D<int> getPivot () {
return piv;
}
/** Compute determinant using LU factors.
@return determinant of A, or 0 if A is not square.
*/
Real det () {
if (m != n) {
return Real(0);
}
Real d = Real(pivsign);
for (int j = 0; j < n; j++) {
d *= LU_[j][j];
}
return d;
}
/** Solve A*X = B
@param B A Matrix with as many rows as A and any number of columns.
@return X so that L*U*X = B(piv,:), if B is nonconformant, returns
0x0 (null) array.
*/
Array2D<Real> solve (const Array2D<Real> &B)
{
/* Dimensions: A is mxn, X is nxk, B is mxk */
if (B.dim1() != m) {
return Array2D<Real>(0,0);
}
if (!isNonsingular()) {
return Array2D<Real>(0,0);
}
// Copy right hand side with pivoting
int nx = B.dim2();
Array2D<Real> X = permute_copy(B, piv, 0, nx-1);
// Solve L*Y = B(piv,:)
for (int k = 0; k < n; k++) {
for (int i = k+1; i < n; i++) {
for (int j = 0; j < nx; j++) {
X[i][j] -= X[k][j]*LU_[i][k];
}
}
}
// Solve U*X = Y;
for (int k = n-1; k >= 0; k--) {
for (int j = 0; j < nx; j++) {
X[k][j] /= LU_[k][k];
}
for (int i = 0; i < k; i++) {
for (int j = 0; j < nx; j++) {
X[i][j] -= X[k][j]*LU_[i][k];
}
}
}
return X;
}
/** Solve A*x = b, where x and b are vectors of length equal
to the number of rows in A.
@param b a vector (Array1D> of length equal to the first dimension
of A.
@return x a vector (Array1D> so that L*U*x = b(piv), if B is nonconformant,
returns 0x0 (null) array.
*/
Array1D<Real> solve (const Array1D<Real> &b)
{
/* Dimensions: A is mxn, X is nxk, B is mxk */
if (b.dim1() != m) {
return Array1D<Real>();
}
if (!isNonsingular()) {
return Array1D<Real>();
}
Array1D<Real> x = permute_copy(b, piv);
// Solve L*Y = B(piv)
for (int k = 0; k < n; k++) {
for (int i = k+1; i < n; i++) {
x[i] -= x[k]*LU_[i][k];
}
}
// Solve U*X = Y;
for (int k = n-1; k >= 0; k--) {
x[k] /= LU_[k][k];
for (int i = 0; i < k; i++)
x[i] -= x[k]*LU_[i][k];
}
return x;
}
}; /* class LU */
} /* namespace JAMA */
#endif
/* JAMA_LU_H */

View File

@@ -0,0 +1,64 @@
/*
*
* Template Numerical Toolkit (TNT): Linear Algebra Module
*
* Mathematical and Computational Sciences Division
* National Institute of Technology,
* Gaithersburg, MD USA
*
*
* This software was developed at the National Institute of Standards and
* Technology (NIST) by employees of the Federal Government in the course
* of their official duties. Pursuant to title 17 Section 105 of the
* United States Code, this software is not subject to copyright protection
* and is in the public domain. NIST assumes no responsibility whatsoever for
* its use by other parties, and makes no guarantees, expressed or implied,
* about its quality, reliability, or any other characteristic.
*
*/
#ifndef TNT_H
#define TNT_H
//---------------------------------------------------------------------
// Define this macro if you want TNT to track some of the out-of-bounds
// indexing. This can encur a small run-time overhead, but is recommended
// while developing code. It can be turned off for production runs.
//
// #define TNT_BOUNDS_CHECK
//---------------------------------------------------------------------
//
//#define TNT_BOUNDS_CHECK
#include "tnt_version.h"
#include "tnt_math_utils.h"
#include "tnt_array1d.h"
#include "tnt_array2d.h"
#include "tnt_array3d.h"
#include "tnt_array1d_utils.h"
#include "tnt_array2d_utils.h"
#include "tnt_array3d_utils.h"
#include "tnt_fortran_array1d.h"
#include "tnt_fortran_array2d.h"
#include "tnt_fortran_array3d.h"
#include "tnt_fortran_array1d_utils.h"
#include "tnt_fortran_array2d_utils.h"
#include "tnt_fortran_array3d_utils.h"
#include "tnt_sparse_matrix_csr.h"
#include "tnt_stopwatch.h"
#include "tnt_subscript.h"
#include "tnt_vec.h"
#include "tnt_cmat.h"
#endif
// TNT_H

View File

@@ -0,0 +1,278 @@
/*
*
* Template Numerical Toolkit (TNT)
*
* Mathematical and Computational Sciences Division
* National Institute of Technology,
* Gaithersburg, MD USA
*
*
* This software was developed at the National Institute of Standards and
* Technology (NIST) by employees of the Federal Government in the course
* of their official duties. Pursuant to title 17 Section 105 of the
* United States Code, this software is not subject to copyright protection
* and is in the public domain. NIST assumes no responsibility whatsoever for
* its use by other parties, and makes no guarantees, expressed or implied,
* about its quality, reliability, or any other characteristic.
*
*/
#ifndef TNT_ARRAY1D_H
#define TNT_ARRAY1D_H
//#include <cstdlib>
#include <iostream>
#ifdef TNT_BOUNDS_CHECK
#include <assert.h>
#endif
#include "tnt_i_refvec.h"
namespace TNT
{
template <class T>
class Array1D
{
private:
/* ... */
i_refvec<T> v_;
int n_;
T* data_; /* this normally points to v_.begin(), but
* could also point to a portion (subvector)
* of v_.
*/
void copy_(T* p, const T* q, int len) const;
void set_(T* begin, T* end, const T& val);
public:
typedef T value_type;
Array1D();
explicit Array1D(int n);
Array1D(int n, const T &a);
Array1D(int n, T *a);
inline Array1D(const Array1D &A);
inline operator T*();
inline operator const T*();
inline Array1D & operator=(const T &a);
inline Array1D & operator=(const Array1D &A);
inline Array1D & ref(const Array1D &A);
Array1D copy() const;
Array1D & inject(const Array1D & A);
inline T& operator[](int i);
inline const T& operator[](int i) const;
inline int dim1() const;
inline int dim() const;
~Array1D();
/* ... extended interface ... */
inline int ref_count() const;
inline Array1D<T> subarray(int i0, int i1);
};
template <class T>
Array1D<T>::Array1D() : v_(), n_(0), data_(0) {}
template <class T>
Array1D<T>::Array1D(const Array1D<T> &A) : v_(A.v_), n_(A.n_),
data_(A.data_)
{
#ifdef TNT_DEBUG
std::cout << "Created Array1D(const Array1D<T> &A) \n";
#endif
}
template <class T>
Array1D<T>::Array1D(int n) : v_(n), n_(n), data_(v_.begin())
{
#ifdef TNT_DEBUG
std::cout << "Created Array1D(int n) \n";
#endif
}
template <class T>
Array1D<T>::Array1D(int n, const T &val) : v_(n), n_(n), data_(v_.begin())
{
#ifdef TNT_DEBUG
std::cout << "Created Array1D(int n, const T& val) \n";
#endif
set_(data_, data_+ n, val);
}
template <class T>
Array1D<T>::Array1D(int n, T *a) : v_(a), n_(n) , data_(v_.begin())
{
#ifdef TNT_DEBUG
std::cout << "Created Array1D(int n, T* a) \n";
#endif
}
template <class T>
inline Array1D<T>::operator T*()
{
return &(v_[0]);
}
template <class T>
inline Array1D<T>::operator const T*()
{
return &(v_[0]);
}
template <class T>
inline T& Array1D<T>::operator[](int i)
{
#ifdef TNT_BOUNDS_CHECK
assert(i>= 0);
assert(i < n_);
#endif
return data_[i];
}
template <class T>
inline const T& Array1D<T>::operator[](int i) const
{
#ifdef TNT_BOUNDS_CHECK
assert(i>= 0);
assert(i < n_);
#endif
return data_[i];
}
template <class T>
Array1D<T> & Array1D<T>::operator=(const T &a)
{
set_(data_, data_+n_, a);
return *this;
}
template <class T>
Array1D<T> Array1D<T>::copy() const
{
Array1D A( n_);
copy_(A.data_, data_, n_);
return A;
}
template <class T>
Array1D<T> & Array1D<T>::inject(const Array1D &A)
{
if (A.n_ == n_)
copy_(data_, A.data_, n_);
return *this;
}
template <class T>
Array1D<T> & Array1D<T>::ref(const Array1D<T> &A)
{
if (this != &A)
{
v_ = A.v_; /* operator= handles the reference counting. */
n_ = A.n_;
data_ = A.data_;
}
return *this;
}
template <class T>
Array1D<T> & Array1D<T>::operator=(const Array1D<T> &A)
{
return ref(A);
}
template <class T>
inline int Array1D<T>::dim1() const { return n_; }
template <class T>
inline int Array1D<T>::dim() const { return n_; }
template <class T>
Array1D<T>::~Array1D() {}
/* ............................ exented interface ......................*/
template <class T>
inline int Array1D<T>::ref_count() const
{
return v_.ref_count();
}
template <class T>
inline Array1D<T> Array1D<T>::subarray(int i0, int i1)
{
if ((i0 > 0) && (i1 < n_) || (i0 <= i1))
{
Array1D<T> X(*this); /* create a new instance of this array. */
X.n_ = i1-i0+1;
X.data_ += i0;
return X;
}
else
{
return Array1D<T>();
}
}
/* private internal functions */
template <class T>
void Array1D<T>::set_(T* begin, T* end, const T& a)
{
for (T* p=begin; p<end; p++)
*p = a;
}
template <class T>
void Array1D<T>::copy_(T* p, const T* q, int len) const
{
T *end = p + len;
while (p<end )
*p++ = *q++;
}
} /* namespace TNT */
#endif
/* TNT_ARRAY1D_H */

View File

@@ -0,0 +1,230 @@
/*
*
* Template Numerical Toolkit (TNT)
*
* Mathematical and Computational Sciences Division
* National Institute of Technology,
* Gaithersburg, MD USA
*
*
* This software was developed at the National Institute of Standards and
* Technology (NIST) by employees of the Federal Government in the course
* of their official duties. Pursuant to title 17 Section 105 of the
* United States Code, this software is not subject to copyright protection
* and is in the public domain. NIST assumes no responsibility whatsoever for
* its use by other parties, and makes no guarantees, expressed or implied,
* about its quality, reliability, or any other characteristic.
*
*/
#ifndef TNT_ARRAY1D_UTILS_H
#define TNT_ARRAY1D_UTILS_H
#include <cstdlib>
#include <cassert>
namespace TNT
{
template <class T>
std::ostream& operator<<(std::ostream &s, const Array1D<T> &A)
{
int N=A.dim1();
#ifdef TNT_DEBUG
s << "addr: " << (void *) &A[0] << "\n";
#endif
s << N << "\n";
for (int j=0; j<N; j++)
{
s << A[j] << "\n";
}
s << "\n";
return s;
}
template <class T>
std::istream& operator>>(std::istream &s, Array1D<T> &A)
{
int N;
s >> N;
Array1D<T> B(N);
for (int i=0; i<N; i++)
s >> B[i];
A = B;
return s;
}
template <class T>
Array1D<T> operator+(const Array1D<T> &A, const Array1D<T> &B)
{
int n = A.dim1();
if (B.dim1() != n )
return Array1D<T>();
else
{
Array1D<T> C(n);
for (int i=0; i<n; i++)
{
C[i] = A[i] + B[i];
}
return C;
}
}
template <class T>
Array1D<T> operator-(const Array1D<T> &A, const Array1D<T> &B)
{
int n = A.dim1();
if (B.dim1() != n )
return Array1D<T>();
else
{
Array1D<T> C(n);
for (int i=0; i<n; i++)
{
C[i] = A[i] - B[i];
}
return C;
}
}
template <class T>
Array1D<T> operator*(const Array1D<T> &A, const Array1D<T> &B)
{
int n = A.dim1();
if (B.dim1() != n )
return Array1D<T>();
else
{
Array1D<T> C(n);
for (int i=0; i<n; i++)
{
C[i] = A[i] * B[i];
}
return C;
}
}
template <class T>
Array1D<T> operator/(const Array1D<T> &A, const Array1D<T> &B)
{
int n = A.dim1();
if (B.dim1() != n )
return Array1D<T>();
else
{
Array1D<T> C(n);
for (int i=0; i<n; i++)
{
C[i] = A[i] / B[i];
}
return C;
}
}
template <class T>
Array1D<T>& operator+=(Array1D<T> &A, const Array1D<T> &B)
{
int n = A.dim1();
if (B.dim1() == n)
{
for (int i=0; i<n; i++)
{
A[i] += B[i];
}
}
return A;
}
template <class T>
Array1D<T>& operator-=(Array1D<T> &A, const Array1D<T> &B)
{
int n = A.dim1();
if (B.dim1() == n)
{
for (int i=0; i<n; i++)
{
A[i] -= B[i];
}
}
return A;
}
template <class T>
Array1D<T>& operator*=(Array1D<T> &A, const Array1D<T> &B)
{
int n = A.dim1();
if (B.dim1() == n)
{
for (int i=0; i<n; i++)
{
A[i] *= B[i];
}
}
return A;
}
template <class T>
Array1D<T>& operator/=(Array1D<T> &A, const Array1D<T> &B)
{
int n = A.dim1();
if (B.dim1() == n)
{
for (int i=0; i<n; i++)
{
A[i] /= B[i];
}
}
return A;
}
} // namespace TNT
#endif

View File

@@ -0,0 +1,315 @@
/*
*
* Template Numerical Toolkit (TNT)
*
* Mathematical and Computational Sciences Division
* National Institute of Technology,
* Gaithersburg, MD USA
*
*
* This software was developed at the National Institute of Standards and
* Technology (NIST) by employees of the Federal Government in the course
* of their official duties. Pursuant to title 17 Section 105 of the
* United States Code, this software is not subject to copyright protection
* and is in the public domain. NIST assumes no responsibility whatsoever for
* its use by other parties, and makes no guarantees, expressed or implied,
* about its quality, reliability, or any other characteristic.
*
*/
#ifndef TNT_ARRAY2D_H
#define TNT_ARRAY2D_H
#include <cstdlib>
#include <iostream>
#ifdef TNT_BOUNDS_CHECK
#include <assert.h>
#endif
#include "tnt_array1d.h"
namespace TNT
{
template <class T>
class Array2D
{
private:
Array1D<T> data_;
Array1D<T*> v_;
int m_;
int n_;
public:
typedef T value_type;
Array2D();
Array2D(int m, int n);
Array2D(int m, int n, T *a);
Array2D(int m, int n, const T &a);
inline Array2D(const Array2D &A);
inline operator T**();
inline operator const T**();
inline Array2D & operator=(const T &a);
inline Array2D & operator=(const Array2D &A);
inline Array2D & ref(const Array2D &A);
Array2D copy() const;
Array2D & inject(const Array2D & A);
inline T* operator[](int i);
inline const T* operator[](int i) const;
inline int dim1() const;
inline int dim2() const;
~Array2D();
/* extended interface (not part of the standard) */
inline int ref_count();
inline int ref_count_data();
inline int ref_count_dim1();
Array2D subarray(int i0, int i1, int j0, int j1);
};
template <class T>
Array2D<T>::Array2D() : data_(), v_(), m_(0), n_(0) {}
template <class T>
Array2D<T>::Array2D(const Array2D<T> &A) : data_(A.data_), v_(A.v_),
m_(A.m_), n_(A.n_) {}
template <class T>
Array2D<T>::Array2D(int m, int n) : data_(m*n), v_(m), m_(m), n_(n)
{
if (m>0 && n>0)
{
T* p = &(data_[0]);
for (int i=0; i<m; i++)
{
v_[i] = p;
p += n;
}
}
}
template <class T>
Array2D<T>::Array2D(int m, int n, const T &val) : data_(m*n), v_(m),
m_(m), n_(n)
{
if (m>0 && n>0)
{
data_ = val;
T* p = &(data_[0]);
for (int i=0; i<m; i++)
{
v_[i] = p;
p += n;
}
}
}
template <class T>
Array2D<T>::Array2D(int m, int n, T *a) : data_(m*n, a), v_(m), m_(m), n_(n)
{
if (m>0 && n>0)
{
T* p = &(data_[0]);
for (int i=0; i<m; i++)
{
v_[i] = p;
p += n;
}
}
}
template <class T>
inline T* Array2D<T>::operator[](int i)
{
#ifdef TNT_BOUNDS_CHECK
assert(i >= 0);
assert(i < m_);
#endif
return v_[i];
}
template <class T>
inline const T* Array2D<T>::operator[](int i) const
{
#ifdef TNT_BOUNDS_CHECK
assert(i >= 0);
assert(i < m_);
#endif
return v_[i];
}
template <class T>
Array2D<T> & Array2D<T>::operator=(const T &a)
{
/* non-optimzied, but will work with subarrays in future verions */
for (int i=0; i<m_; i++)
for (int j=0; j<n_; j++)
v_[i][j] = a;
return *this;
}
template <class T>
Array2D<T> Array2D<T>::copy() const
{
Array2D A(m_, n_);
for (int i=0; i<m_; i++)
for (int j=0; j<n_; j++)
A[i][j] = v_[i][j];
return A;
}
template <class T>
Array2D<T> & Array2D<T>::inject(const Array2D &A)
{
if (A.m_ == m_ && A.n_ == n_)
{
for (int i=0; i<m_; i++)
for (int j=0; j<n_; j++)
v_[i][j] = A[i][j];
}
return *this;
}
template <class T>
Array2D<T> & Array2D<T>::ref(const Array2D<T> &A)
{
if (this != &A)
{
v_ = A.v_;
data_ = A.data_;
m_ = A.m_;
n_ = A.n_;
}
return *this;
}
template <class T>
Array2D<T> & Array2D<T>::operator=(const Array2D<T> &A)
{
return ref(A);
}
template <class T>
inline int Array2D<T>::dim1() const { return m_; }
template <class T>
inline int Array2D<T>::dim2() const { return n_; }
template <class T>
Array2D<T>::~Array2D() {}
template <class T>
inline Array2D<T>::operator T**()
{
return &(v_[0]);
}
template <class T>
inline Array2D<T>::operator const T**()
{
return &(v_[0]);
}
/* ............... extended interface ............... */
/**
Create a new view to a subarray defined by the boundaries
[i0][i0] and [i1][j1]. The size of the subarray is
(i1-i0) by (j1-j0). If either of these lengths are zero
or negative, the subarray view is null.
*/
template <class T>
Array2D<T> Array2D<T>::subarray(int i0, int i1, int j0, int j1)
{
Array2D<T> A;
int m = i1-i0+1;
int n = j1-j0+1;
/* if either length is zero or negative, this is an invalide
subarray. return a null view.
*/
if (m<1 || n<1)
return A;
A.data_ = data_;
A.m_ = m;
A.n_ = n;
A.v_ = Array1D<T*>(m);
T* p = &(data_[0]) + i0 * n_ + j0;
for (int i=0; i<m; i++)
{
A.v_[i] = p + i*n_;
}
return A;
}
template <class T>
inline int Array2D<T>::ref_count()
{
return ref_count_data();
}
template <class T>
inline int Array2D<T>::ref_count_data()
{
return data_.ref_count();
}
template <class T>
inline int Array2D<T>::ref_count_dim1()
{
return v_.ref_count();
}
} /* namespace TNT */
#endif
/* TNT_ARRAY2D_H */

View File

@@ -0,0 +1,287 @@
/*
*
* Template Numerical Toolkit (TNT)
*
* Mathematical and Computational Sciences Division
* National Institute of Technology,
* Gaithersburg, MD USA
*
*
* This software was developed at the National Institute of Standards and
* Technology (NIST) by employees of the Federal Government in the course
* of their official duties. Pursuant to title 17 Section 105 of the
* United States Code, this software is not subject to copyright protection
* and is in the public domain. NIST assumes no responsibility whatsoever for
* its use by other parties, and makes no guarantees, expressed or implied,
* about its quality, reliability, or any other characteristic.
*
*/
#ifndef TNT_ARRAY2D_UTILS_H
#define TNT_ARRAY2D_UTILS_H
#include <cstdlib>
#include <cassert>
namespace TNT
{
template <class T>
std::ostream& operator<<(std::ostream &s, const Array2D<T> &A)
{
int M=A.dim1();
int N=A.dim2();
s << M << " " << N << "\n";
for (int i=0; i<M; i++)
{
for (int j=0; j<N; j++)
{
s << A[i][j] << " ";
}
s << "\n";
}
return s;
}
template <class T>
std::istream& operator>>(std::istream &s, Array2D<T> &A)
{
int M, N;
s >> M >> N;
Array2D<T> B(M,N);
for (int i=0; i<M; i++)
for (int j=0; j<N; j++)
{
s >> B[i][j];
}
A = B;
return s;
}
template <class T>
Array2D<T> operator+(const Array2D<T> &A, const Array2D<T> &B)
{
int m = A.dim1();
int n = A.dim2();
if (B.dim1() != m || B.dim2() != n )
return Array2D<T>();
else
{
Array2D<T> C(m,n);
for (int i=0; i<m; i++)
{
for (int j=0; j<n; j++)
C[i][j] = A[i][j] + B[i][j];
}
return C;
}
}
template <class T>
Array2D<T> operator-(const Array2D<T> &A, const Array2D<T> &B)
{
int m = A.dim1();
int n = A.dim2();
if (B.dim1() != m || B.dim2() != n )
return Array2D<T>();
else
{
Array2D<T> C(m,n);
for (int i=0; i<m; i++)
{
for (int j=0; j<n; j++)
C[i][j] = A[i][j] - B[i][j];
}
return C;
}
}
template <class T>
Array2D<T> operator*(const Array2D<T> &A, const Array2D<T> &B)
{
int m = A.dim1();
int n = A.dim2();
if (B.dim1() != m || B.dim2() != n )
return Array2D<T>();
else
{
Array2D<T> C(m,n);
for (int i=0; i<m; i++)
{
for (int j=0; j<n; j++)
C[i][j] = A[i][j] * B[i][j];
}
return C;
}
}
template <class T>
Array2D<T> operator/(const Array2D<T> &A, const Array2D<T> &B)
{
int m = A.dim1();
int n = A.dim2();
if (B.dim1() != m || B.dim2() != n )
return Array2D<T>();
else
{
Array2D<T> C(m,n);
for (int i=0; i<m; i++)
{
for (int j=0; j<n; j++)
C[i][j] = A[i][j] / B[i][j];
}
return C;
}
}
template <class T>
Array2D<T>& operator+=(Array2D<T> &A, const Array2D<T> &B)
{
int m = A.dim1();
int n = A.dim2();
if (B.dim1() == m || B.dim2() == n )
{
for (int i=0; i<m; i++)
{
for (int j=0; j<n; j++)
A[i][j] += B[i][j];
}
}
return A;
}
template <class T>
Array2D<T>& operator-=(Array2D<T> &A, const Array2D<T> &B)
{
int m = A.dim1();
int n = A.dim2();
if (B.dim1() == m || B.dim2() == n )
{
for (int i=0; i<m; i++)
{
for (int j=0; j<n; j++)
A[i][j] -= B[i][j];
}
}
return A;
}
template <class T>
Array2D<T>& operator*=(Array2D<T> &A, const Array2D<T> &B)
{
int m = A.dim1();
int n = A.dim2();
if (B.dim1() == m || B.dim2() == n )
{
for (int i=0; i<m; i++)
{
for (int j=0; j<n; j++)
A[i][j] *= B[i][j];
}
}
return A;
}
template <class T>
Array2D<T>& operator/=(Array2D<T> &A, const Array2D<T> &B)
{
int m = A.dim1();
int n = A.dim2();
if (B.dim1() == m || B.dim2() == n )
{
for (int i=0; i<m; i++)
{
for (int j=0; j<n; j++)
A[i][j] /= B[i][j];
}
}
return A;
}
/**
Matrix Multiply: compute C = A*B, where C[i][j]
is the dot-product of row i of A and column j of B.
@param A an (m x n) array
@param B an (n x k) array
@return the (m x k) array A*B, or a null array (0x0)
if the matrices are non-conformant (i.e. the number
of columns of A are different than the number of rows of B.)
*/
template <class T>
Array2D<T> matmult(const Array2D<T> &A, const Array2D<T> &B)
{
if (A.dim2() != B.dim1())
return Array2D<T>();
int M = A.dim1();
int N = A.dim2();
int K = B.dim2();
Array2D<T> C(M,K);
for (int i=0; i<M; i++)
for (int j=0; j<K; j++)
{
T sum = 0;
for (int k=0; k<N; k++)
sum += A[i][k] * B [k][j];
C[i][j] = sum;
}
return C;
}
} // namespace TNT
#endif

View File

@@ -0,0 +1,296 @@
/*
*
* Template Numerical Toolkit (TNT)
*
* Mathematical and Computational Sciences Division
* National Institute of Technology,
* Gaithersburg, MD USA
*
*
* This software was developed at the National Institute of Standards and
* Technology (NIST) by employees of the Federal Government in the course
* of their official duties. Pursuant to title 17 Section 105 of the
* United States Code, this software is not subject to copyright protection
* and is in the public domain. NIST assumes no responsibility whatsoever for
* its use by other parties, and makes no guarantees, expressed or implied,
* about its quality, reliability, or any other characteristic.
*
*/
#ifndef TNT_ARRAY3D_H
#define TNT_ARRAY3D_H
#include <cstdlib>
#include <iostream>
#ifdef TNT_BOUNDS_CHECK
#include <assert.h>
#endif
#include "tnt_array1d.h"
#include "tnt_array2d.h"
namespace TNT
{
template <class T>
class Array3D
{
private:
Array1D<T> data_;
Array2D<T*> v_;
int m_;
int n_;
int g_;
public:
typedef T value_type;
Array3D();
Array3D(int m, int n, int g);
Array3D(int m, int n, int g, T val);
Array3D(int m, int n, int g, T *a);
inline operator T***();
inline operator const T***();
inline Array3D(const Array3D &A);
inline Array3D & operator=(const T &a);
inline Array3D & operator=(const Array3D &A);
inline Array3D & ref(const Array3D &A);
Array3D copy() const;
Array3D & inject(const Array3D & A);
inline T** operator[](int i);
inline const T* const * operator[](int i) const;
inline int dim1() const;
inline int dim2() const;
inline int dim3() const;
~Array3D();
/* extended interface */
inline int ref_count(){ return data_.ref_count(); }
Array3D subarray(int i0, int i1, int j0, int j1,
int k0, int k1);
};
template <class T>
Array3D<T>::Array3D() : data_(), v_(), m_(0), n_(0) {}
template <class T>
Array3D<T>::Array3D(const Array3D<T> &A) : data_(A.data_),
v_(A.v_), m_(A.m_), n_(A.n_), g_(A.g_)
{
}
template <class T>
Array3D<T>::Array3D(int m, int n, int g) : data_(m*n*g), v_(m,n),
m_(m), n_(n), g_(g)
{
if (m>0 && n>0 && g>0)
{
T* p = & (data_[0]);
int ng = n_*g_;
for (int i=0; i<m_; i++)
{
T* ping = p+ i*ng;
for (int j=0; j<n; j++)
v_[i][j] = ping + j*g_;
}
}
}
template <class T>
Array3D<T>::Array3D(int m, int n, int g, T val) : data_(m*n*g, val),
v_(m,n), m_(m), n_(n), g_(g)
{
if (m>0 && n>0 && g>0)
{
T* p = & (data_[0]);
int ng = n_*g_;
for (int i=0; i<m_; i++)
{
T* ping = p+ i*ng;
for (int j=0; j<n; j++)
v_[i][j] = ping + j*g_;
}
}
}
template <class T>
Array3D<T>::Array3D(int m, int n, int g, T* a) :
data_(m*n*g, a), v_(m,n), m_(m), n_(n), g_(g)
{
if (m>0 && n>0 && g>0)
{
T* p = & (data_[0]);
int ng = n_*g_;
for (int i=0; i<m_; i++)
{
T* ping = p+ i*ng;
for (int j=0; j<n; j++)
v_[i][j] = ping + j*g_;
}
}
}
template <class T>
inline T** Array3D<T>::operator[](int i)
{
#ifdef TNT_BOUNDS_CHECK
assert(i >= 0);
assert(i < m_);
#endif
return v_[i];
}
template <class T>
inline const T* const * Array3D<T>::operator[](int i) const
{ return v_[i]; }
template <class T>
Array3D<T> & Array3D<T>::operator=(const T &a)
{
for (int i=0; i<m_; i++)
for (int j=0; j<n_; j++)
for (int k=0; k<g_; k++)
v_[i][j][k] = a;
return *this;
}
template <class T>
Array3D<T> Array3D<T>::copy() const
{
Array3D A(m_, n_, g_);
for (int i=0; i<m_; i++)
for (int j=0; j<n_; j++)
for (int k=0; k<g_; k++)
A.v_[i][j][k] = v_[i][j][k];
return A;
}
template <class T>
Array3D<T> & Array3D<T>::inject(const Array3D &A)
{
if (A.m_ == m_ && A.n_ == n_ && A.g_ == g_)
for (int i=0; i<m_; i++)
for (int j=0; j<n_; j++)
for (int k=0; k<g_; k++)
v_[i][j][k] = A.v_[i][j][k];
return *this;
}
template <class T>
Array3D<T> & Array3D<T>::ref(const Array3D<T> &A)
{
if (this != &A)
{
m_ = A.m_;
n_ = A.n_;
g_ = A.g_;
v_ = A.v_;
data_ = A.data_;
}
return *this;
}
template <class T>
Array3D<T> & Array3D<T>::operator=(const Array3D<T> &A)
{
return ref(A);
}
template <class T>
inline int Array3D<T>::dim1() const { return m_; }
template <class T>
inline int Array3D<T>::dim2() const { return n_; }
template <class T>
inline int Array3D<T>::dim3() const { return g_; }
template <class T>
Array3D<T>::~Array3D() {}
template <class T>
inline Array3D<T>::operator T***()
{
return v_;
}
template <class T>
inline Array3D<T>::operator const T***()
{
return v_;
}
/* extended interface */
template <class T>
Array3D<T> Array3D<T>::subarray(int i0, int i1, int j0,
int j1, int k0, int k1)
{
/* check that ranges are valid. */
if (!( 0 <= i0 && i0 <= i1 && i1 < m_ &&
0 <= j0 && j0 <= j1 && j1 < n_ &&
0 <= k0 && k0 <= k1 && k1 < g_))
return Array3D<T>(); /* null array */
Array3D<T> A;
A.data_ = data_;
A.m_ = i1-i0+1;
A.n_ = j1-j0+1;
A.g_ = k1-k0+1;
A.v_ = Array2D<T*>(A.m_,A.n_);
T* p = &(data_[0]) + i0*n_*g_ + j0*g_ + k0;
for (int i=0; i<A.m_; i++)
{
T* ping = p + i*n_*g_;
for (int j=0; j<A.n_; j++)
A.v_[i][j] = ping + j*g_ ;
}
return A;
}
} /* namespace TNT */
#endif
/* TNT_ARRAY3D_H */

View File

@@ -0,0 +1,236 @@
#ifndef TNT_ARRAY3D_UTILS_H
#define TNT_ARRAY3D_UTILS_H
#include <cstdlib>
#include <cassert>
namespace TNT
{
template <class T>
std::ostream& operator<<(std::ostream &s, const Array3D<T> &A)
{
int M=A.dim1();
int N=A.dim2();
int K=A.dim3();
s << M << " " << N << " " << K << "\n";
for (int i=0; i<M; i++)
{
for (int j=0; j<N; j++)
{
for (int k=0; k<K; k++)
s << A[i][j][k] << " ";
s << "\n";
}
s << "\n";
}
return s;
}
template <class T>
std::istream& operator>>(std::istream &s, Array3D<T> &A)
{
int M, N, K;
s >> M >> N >> K;
Array3D<T> B(M,N,K);
for (int i=0; i<M; i++)
for (int j=0; j<N; j++)
for (int k=0; k<K; k++)
s >> B[i][j][k];
A = B;
return s;
}
template <class T>
Array3D<T> operator+(const Array3D<T> &A, const Array3D<T> &B)
{
int m = A.dim1();
int n = A.dim2();
int p = A.dim3();
if (B.dim1() != m || B.dim2() != n || B.dim3() != p )
return Array3D<T>();
else
{
Array3D<T> C(m,n,p);
for (int i=0; i<m; i++)
for (int j=0; j<n; j++)
for (int k=0; k<p; k++)
C[i][j][k] = A[i][j][k] + B[i][j][k];
return C;
}
}
template <class T>
Array3D<T> operator-(const Array3D<T> &A, const Array3D<T> &B)
{
int m = A.dim1();
int n = A.dim2();
int p = A.dim3();
if (B.dim1() != m || B.dim2() != n || B.dim3() != p )
return Array3D<T>();
else
{
Array3D<T> C(m,n,p);
for (int i=0; i<m; i++)
for (int j=0; j<n; j++)
for (int k=0; k<p; k++)
C[i][j][k] = A[i][j][k] - B[i][j][k];
return C;
}
}
template <class T>
Array3D<T> operator*(const Array3D<T> &A, const Array3D<T> &B)
{
int m = A.dim1();
int n = A.dim2();
int p = A.dim3();
if (B.dim1() != m || B.dim2() != n || B.dim3() != p )
return Array3D<T>();
else
{
Array3D<T> C(m,n,p);
for (int i=0; i<m; i++)
for (int j=0; j<n; j++)
for (int k=0; k<p; k++)
C[i][j][k] = A[i][j][k] * B[i][j][k];
return C;
}
}
template <class T>
Array3D<T> operator/(const Array3D<T> &A, const Array3D<T> &B)
{
int m = A.dim1();
int n = A.dim2();
int p = A.dim3();
if (B.dim1() != m || B.dim2() != n || B.dim3() != p )
return Array3D<T>();
else
{
Array3D<T> C(m,n,p);
for (int i=0; i<m; i++)
for (int j=0; j<n; j++)
for (int k=0; k<p; k++)
C[i][j][k] = A[i][j][k] / B[i][j][k];
return C;
}
}
template <class T>
Array3D<T>& operator+=(Array3D<T> &A, const Array3D<T> &B)
{
int m = A.dim1();
int n = A.dim2();
int p = A.dim3();
if (B.dim1() == m && B.dim2() == n && B.dim3() == p )
{
for (int i=0; i<m; i++)
for (int j=0; j<n; j++)
for (int k=0; k<p; k++)
A[i][j][k] += B[i][j][k];
}
return A;
}
template <class T>
Array3D<T>& operator-=(Array3D<T> &A, const Array3D<T> &B)
{
int m = A.dim1();
int n = A.dim2();
int p = A.dim3();
if (B.dim1() == m && B.dim2() == n && B.dim3() == p )
{
for (int i=0; i<m; i++)
for (int j=0; j<n; j++)
for (int k=0; k<p; k++)
A[i][j][k] -= B[i][j][k];
}
return A;
}
template <class T>
Array3D<T>& operator*=(Array3D<T> &A, const Array3D<T> &B)
{
int m = A.dim1();
int n = A.dim2();
int p = A.dim3();
if (B.dim1() == m && B.dim2() == n && B.dim3() == p )
{
for (int i=0; i<m; i++)
for (int j=0; j<n; j++)
for (int k=0; k<p; k++)
A[i][j][k] *= B[i][j][k];
}
return A;
}
template <class T>
Array3D<T>& operator/=(Array3D<T> &A, const Array3D<T> &B)
{
int m = A.dim1();
int n = A.dim2();
int p = A.dim3();
if (B.dim1() == m && B.dim2() == n && B.dim3() == p )
{
for (int i=0; i<m; i++)
for (int j=0; j<n; j++)
for (int k=0; k<p; k++)
A[i][j][k] /= B[i][j][k];
}
return A;
}
} // namespace TNT
#endif

View File

@@ -0,0 +1,580 @@
/*
*
* Template Numerical Toolkit (TNT)
*
* Mathematical and Computational Sciences Division
* National Institute of Technology,
* Gaithersburg, MD USA
*
*
* This software was developed at the National Institute of Standards and
* Technology (NIST) by employees of the Federal Government in the course
* of their official duties. Pursuant to title 17 Section 105 of the
* United States Code, this software is not subject to copyright protection
* and is in the public domain. NIST assumes no responsibility whatsoever for
* its use by other parties, and makes no guarantees, expressed or implied,
* about its quality, reliability, or any other characteristic.
*
*/
// C compatible matrix: row-oriented, 0-based [i][j] and 1-based (i,j) indexing
//
#ifndef TNT_CMAT_H
#define TNT_CMAT_H
#include "tnt_subscript.h"
#include "tnt_vec.h"
#include <cstdlib>
#include <cassert>
#include <iostream>
#include <sstream>
namespace TNT
{
template <class T>
class Matrix
{
public:
typedef Subscript size_type;
typedef T value_type;
typedef T element_type;
typedef T* pointer;
typedef T* iterator;
typedef T& reference;
typedef const T* const_iterator;
typedef const T& const_reference;
Subscript lbound() const { return 1;}
protected:
Subscript m_;
Subscript n_;
Subscript mn_; // total size
T* v_;
T** row_;
T* vm1_ ; // these point to the same data, but are 1-based
T** rowm1_;
// internal helper function to create the array
// of row pointers
void initialize(Subscript M, Subscript N)
{
mn_ = M*N;
m_ = M;
n_ = N;
v_ = new T[mn_];
row_ = new T*[M];
rowm1_ = new T*[M];
assert(v_ != NULL);
assert(row_ != NULL);
assert(rowm1_ != NULL);
T* p = v_;
vm1_ = v_ - 1;
for (Subscript i=0; i<M; i++)
{
row_[i] = p;
rowm1_[i] = p-1;
p += N ;
}
rowm1_ -- ; // compensate for 1-based offset
}
void copy(const T* v)
{
Subscript N = m_ * n_;
Subscript i;
#ifdef TNT_UNROLL_LOOPS
Subscript Nmod4 = N & 3;
Subscript N4 = N - Nmod4;
for (i=0; i<N4; i+=4)
{
v_[i] = v[i];
v_[i+1] = v[i+1];
v_[i+2] = v[i+2];
v_[i+3] = v[i+3];
}
for (i=N4; i< N; i++)
v_[i] = v[i];
#else
for (i=0; i< N; i++)
v_[i] = v[i];
#endif
}
void set(const T& val)
{
Subscript N = m_ * n_;
Subscript i;
#ifdef TNT_UNROLL_LOOPS
Subscript Nmod4 = N & 3;
Subscript N4 = N - Nmod4;
for (i=0; i<N4; i+=4)
{
v_[i] = val;
v_[i+1] = val;
v_[i+2] = val;
v_[i+3] = val;
}
for (i=N4; i< N; i++)
v_[i] = val;
#else
for (i=0; i< N; i++)
v_[i] = val;
#endif
}
void destroy()
{
/* do nothing, if no memory has been previously allocated */
if (v_ == NULL) return ;
/* if we are here, then matrix was previously allocated */
if (v_ != NULL) delete [] (v_);
if (row_ != NULL) delete [] (row_);
/* return rowm1_ back to original value */
rowm1_ ++;
if (rowm1_ != NULL ) delete [] (rowm1_);
}
public:
operator T**(){ return row_; }
operator T**() const { return row_; }
Subscript size() const { return mn_; }
// constructors
Matrix() : m_(0), n_(0), mn_(0), v_(0), row_(0), vm1_(0), rowm1_(0) {};
Matrix(const Matrix<T> &A)
{
initialize(A.m_, A.n_);
copy(A.v_);
}
Matrix(Subscript M, Subscript N, const T& value = T())
{
initialize(M,N);
set(value);
}
Matrix(Subscript M, Subscript N, const T* v)
{
initialize(M,N);
copy(v);
}
Matrix(Subscript M, Subscript N, const char *s)
{
initialize(M,N);
//std::istrstream ins(s);
std::istringstream ins(s);
Subscript i, j;
for (i=0; i<M; i++)
for (j=0; j<N; j++)
ins >> row_[i][j];
}
// destructor
//
~Matrix()
{
destroy();
}
// reallocating
//
Matrix<T>& newsize(Subscript M, Subscript N)
{
if (num_rows() == M && num_cols() == N)
return *this;
destroy();
initialize(M,N);
return *this;
}
// assignments
//
Matrix<T>& operator=(const Matrix<T> &A)
{
if (v_ == A.v_)
return *this;
if (m_ == A.m_ && n_ == A.n_) // no need to re-alloc
copy(A.v_);
else
{
destroy();
initialize(A.m_, A.n_);
copy(A.v_);
}
return *this;
}
Matrix<T>& operator=(const T& scalar)
{
set(scalar);
return *this;
}
Subscript dim(Subscript d) const
{
#ifdef TNT_BOUNDS_CHECK
assert( d >= 1);
assert( d <= 2);
#endif
return (d==1) ? m_ : ((d==2) ? n_ : 0);
}
Subscript num_rows() const { return m_; }
Subscript num_cols() const { return n_; }
inline T* operator[](Subscript i)
{
#ifdef TNT_BOUNDS_CHECK
assert(0<=i);
assert(i < m_) ;
#endif
return row_[i];
}
inline const T* operator[](Subscript i) const
{
#ifdef TNT_BOUNDS_CHECK
assert(0<=i);
assert(i < m_) ;
#endif
return row_[i];
}
inline reference operator()(Subscript i)
{
#ifdef TNT_BOUNDS_CHECK
assert(1<=i);
assert(i <= mn_) ;
#endif
return vm1_[i];
}
inline const_reference operator()(Subscript i) const
{
#ifdef TNT_BOUNDS_CHECK
assert(1<=i);
assert(i <= mn_) ;
#endif
return vm1_[i];
}
inline reference operator()(Subscript i, Subscript j)
{
#ifdef TNT_BOUNDS_CHECK
assert(1<=i);
assert(i <= m_) ;
assert(1<=j);
assert(j <= n_);
#endif
return rowm1_[i][j];
}
inline const_reference operator() (Subscript i, Subscript j) const
{
#ifdef TNT_BOUNDS_CHECK
assert(1<=i);
assert(i <= m_) ;
assert(1<=j);
assert(j <= n_);
#endif
return rowm1_[i][j];
}
};
/* *************************** I/O ********************************/
template <class T>
std::ostream& operator<<(std::ostream &s, const Matrix<T> &A)
{
Subscript M=A.num_rows();
Subscript N=A.num_cols();
s << M << " " << N << "\n";
for (Subscript i=0; i<M; i++)
{
for (Subscript j=0; j<N; j++)
{
s << A[i][j] << " ";
}
s << "\n";
}
return s;
}
template <class T>
std::istream& operator>>(std::istream &s, Matrix<T> &A)
{
Subscript M, N;
s >> M >> N;
if ( !(M == A.num_rows() && N == A.num_cols() ))
{
A.newsize(M,N);
}
for (Subscript i=0; i<M; i++)
for (Subscript j=0; j<N; j++)
{
s >> A[i][j];
}
return s;
}
// *******************[ basic matrix algorithms ]***************************
template <class T>
Matrix<T> operator+(const Matrix<T> &A,
const Matrix<T> &B)
{
Subscript M = A.num_rows();
Subscript N = A.num_cols();
assert(M==B.num_rows());
assert(N==B.num_cols());
Matrix<T> tmp(M,N);
Subscript i,j;
for (i=0; i<M; i++)
for (j=0; j<N; j++)
tmp[i][j] = A[i][j] + B[i][j];
return tmp;
}
template <class T>
Matrix<T> operator-(const Matrix<T> &A,
const Matrix<T> &B)
{
Subscript M = A.num_rows();
Subscript N = A.num_cols();
assert(M==B.num_rows());
assert(N==B.num_cols());
Matrix<T> tmp(M,N);
Subscript i,j;
for (i=0; i<M; i++)
for (j=0; j<N; j++)
tmp[i][j] = A[i][j] - B[i][j];
return tmp;
}
template <class T>
Matrix<T> mult_element(const Matrix<T> &A,
const Matrix<T> &B)
{
Subscript M = A.num_rows();
Subscript N = A.num_cols();
assert(M==B.num_rows());
assert(N==B.num_cols());
Matrix<T> tmp(M,N);
Subscript i,j;
for (i=0; i<M; i++)
for (j=0; j<N; j++)
tmp[i][j] = A[i][j] * B[i][j];
return tmp;
}
template <class T>
Matrix<T> transpose(const Matrix<T> &A)
{
Subscript M = A.num_rows();
Subscript N = A.num_cols();
Matrix<T> S(N,M);
Subscript i, j;
for (i=0; i<M; i++)
for (j=0; j<N; j++)
S[j][i] = A[i][j];
return S;
}
template <class T>
inline Matrix<T> matmult(const Matrix<T> &A,
const Matrix<T> &B)
{
#ifdef TNT_BOUNDS_CHECK
assert(A.num_cols() == B.num_rows());
#endif
Subscript M = A.num_rows();
Subscript N = A.num_cols();
Subscript K = B.num_cols();
Matrix<T> tmp(M,K);
T sum;
for (Subscript i=0; i<M; i++)
for (Subscript k=0; k<K; k++)
{
sum = 0;
for (Subscript j=0; j<N; j++)
sum = sum + A[i][j] * B[j][k];
tmp[i][k] = sum;
}
return tmp;
}
template <class T>
inline Matrix<T> operator*(const Matrix<T> &A,
const Matrix<T> &B)
{
return matmult(A,B);
}
template <class T>
inline int matmult(Matrix<T>& C, const Matrix<T> &A,
const Matrix<T> &B)
{
assert(A.num_cols() == B.num_rows());
Subscript M = A.num_rows();
Subscript N = A.num_cols();
Subscript K = B.num_cols();
C.newsize(M,K);
T sum;
const T* row_i;
const T* col_k;
for (Subscript i=0; i<M; i++)
for (Subscript k=0; k<K; k++)
{
row_i = &(A[i][0]);
col_k = &(B[0][k]);
sum = 0;
for (Subscript j=0; j<N; j++)
{
sum += *row_i * *col_k;
row_i++;
col_k += K;
}
C[i][k] = sum;
}
return 0;
}
template <class T>
Vector<T> matmult(const Matrix<T> &A, const Vector<T> &x)
{
#ifdef TNT_BOUNDS_CHECK
assert(A.num_cols() == x.dim());
#endif
Subscript M = A.num_rows();
Subscript N = A.num_cols();
Vector<T> tmp(M);
T sum;
for (Subscript i=0; i<M; i++)
{
sum = 0;
const T* rowi = A[i];
for (Subscript j=0; j<N; j++)
sum = sum + rowi[j] * x[j];
tmp[i] = sum;
}
return tmp;
}
template <class T>
inline Vector<T> operator*(const Matrix<T> &A, const Vector<T> &x)
{
return matmult(A,x);
}
} // namespace TNT
#endif
// CMAT_H

View File

@@ -0,0 +1,267 @@
/*
*
* Template Numerical Toolkit (TNT)
*
* Mathematical and Computational Sciences Division
* National Institute of Technology,
* Gaithersburg, MD USA
*
*
* This software was developed at the National Institute of Standards and
* Technology (NIST) by employees of the Federal Government in the course
* of their official duties. Pursuant to title 17 Section 105 of the
* United States Code, this software is not subject to copyright protection
* and is in the public domain. NIST assumes no responsibility whatsoever for
* its use by other parties, and makes no guarantees, expressed or implied,
* about its quality, reliability, or any other characteristic.
*
*/
#ifndef TNT_FORTRAN_ARRAY1D_H
#define TNT_FORTRAN_ARRAY1D_H
#include <cstdlib>
#include <iostream>
#ifdef TNT_BOUNDS_CHECK
#include <assert.h>
#endif
#include "tnt_i_refvec.h"
namespace TNT
{
template <class T>
class Fortran_Array1D
{
private:
i_refvec<T> v_;
int n_;
T* data_; /* this normally points to v_.begin(), but
* could also point to a portion (subvector)
* of v_.
*/
void initialize_(int n);
void copy_(T* p, const T* q, int len) const;
void set_(T* begin, T* end, const T& val);
public:
typedef T value_type;
Fortran_Array1D();
explicit Fortran_Array1D(int n);
Fortran_Array1D(int n, const T &a);
Fortran_Array1D(int n, T *a);
inline Fortran_Array1D(const Fortran_Array1D &A);
inline Fortran_Array1D & operator=(const T &a);
inline Fortran_Array1D & operator=(const Fortran_Array1D &A);
inline Fortran_Array1D & ref(const Fortran_Array1D &A);
Fortran_Array1D copy() const;
Fortran_Array1D & inject(const Fortran_Array1D & A);
inline T& operator()(int i);
inline const T& operator()(int i) const;
inline int dim1() const;
inline int dim() const;
~Fortran_Array1D();
/* ... extended interface ... */
inline int ref_count() const;
inline Fortran_Array1D<T> subarray(int i0, int i1);
};
template <class T>
Fortran_Array1D<T>::Fortran_Array1D() : v_(), n_(0), data_(0) {}
template <class T>
Fortran_Array1D<T>::Fortran_Array1D(const Fortran_Array1D<T> &A) : v_(A.v_), n_(A.n_),
data_(A.data_)
{
#ifdef TNT_DEBUG
std::cout << "Created Fortran_Array1D(const Fortran_Array1D<T> &A) \n";
#endif
}
template <class T>
Fortran_Array1D<T>::Fortran_Array1D(int n) : v_(n), n_(n), data_(v_.begin())
{
#ifdef TNT_DEBUG
std::cout << "Created Fortran_Array1D(int n) \n";
#endif
}
template <class T>
Fortran_Array1D<T>::Fortran_Array1D(int n, const T &val) : v_(n), n_(n), data_(v_.begin())
{
#ifdef TNT_DEBUG
std::cout << "Created Fortran_Array1D(int n, const T& val) \n";
#endif
set_(data_, data_+ n, val);
}
template <class T>
Fortran_Array1D<T>::Fortran_Array1D(int n, T *a) : v_(a), n_(n) , data_(v_.begin())
{
#ifdef TNT_DEBUG
std::cout << "Created Fortran_Array1D(int n, T* a) \n";
#endif
}
template <class T>
inline T& Fortran_Array1D<T>::operator()(int i)
{
#ifdef TNT_BOUNDS_CHECK
assert(i>= 1);
assert(i <= n_);
#endif
return data_[i-1];
}
template <class T>
inline const T& Fortran_Array1D<T>::operator()(int i) const
{
#ifdef TNT_BOUNDS_CHECK
assert(i>= 1);
assert(i <= n_);
#endif
return data_[i-1];
}
template <class T>
Fortran_Array1D<T> & Fortran_Array1D<T>::operator=(const T &a)
{
set_(data_, data_+n_, a);
return *this;
}
template <class T>
Fortran_Array1D<T> Fortran_Array1D<T>::copy() const
{
Fortran_Array1D A( n_);
copy_(A.data_, data_, n_);
return A;
}
template <class T>
Fortran_Array1D<T> & Fortran_Array1D<T>::inject(const Fortran_Array1D &A)
{
if (A.n_ == n_)
copy_(data_, A.data_, n_);
return *this;
}
template <class T>
Fortran_Array1D<T> & Fortran_Array1D<T>::ref(const Fortran_Array1D<T> &A)
{
if (this != &A)
{
v_ = A.v_; /* operator= handles the reference counting. */
n_ = A.n_;
data_ = A.data_;
}
return *this;
}
template <class T>
Fortran_Array1D<T> & Fortran_Array1D<T>::operator=(const Fortran_Array1D<T> &A)
{
return ref(A);
}
template <class T>
inline int Fortran_Array1D<T>::dim1() const { return n_; }
template <class T>
inline int Fortran_Array1D<T>::dim() const { return n_; }
template <class T>
Fortran_Array1D<T>::~Fortran_Array1D() {}
/* ............................ exented interface ......................*/
template <class T>
inline int Fortran_Array1D<T>::ref_count() const
{
return v_.ref_count();
}
template <class T>
inline Fortran_Array1D<T> Fortran_Array1D<T>::subarray(int i0, int i1)
{
#ifdef TNT_DEBUG
std::cout << "entered subarray. \n";
#endif
if ((i0 > 0) && (i1 < n_) || (i0 <= i1))
{
Fortran_Array1D<T> X(*this); /* create a new instance of this array. */
X.n_ = i1-i0+1;
X.data_ += i0;
return X;
}
else
{
#ifdef TNT_DEBUG
std::cout << "subarray: null return.\n";
#endif
return Fortran_Array1D<T>();
}
}
/* private internal functions */
template <class T>
void Fortran_Array1D<T>::set_(T* begin, T* end, const T& a)
{
for (T* p=begin; p<end; p++)
*p = a;
}
template <class T>
void Fortran_Array1D<T>::copy_(T* p, const T* q, int len) const
{
T *end = p + len;
while (p<end )
*p++ = *q++;
}
} /* namespace TNT */
#endif
/* TNT_FORTRAN_ARRAY1D_H */

View File

@@ -0,0 +1,242 @@
/*
*
* Template Numerical Toolkit (TNT)
*
* Mathematical and Computational Sciences Division
* National Institute of Technology,
* Gaithersburg, MD USA
*
*
* This software was developed at the National Institute of Standards and
* Technology (NIST) by employees of the Federal Government in the course
* of their official duties. Pursuant to title 17 Section 105 of the
* United States Code, this software is not subject to copyright protection
* and is in the public domain. NIST assumes no responsibility whatsoever for
* its use by other parties, and makes no guarantees, expressed or implied,
* about its quality, reliability, or any other characteristic.
*
*/
#ifndef TNT_FORTRAN_ARRAY1D_UTILS_H
#define TNT_FORTRAN_ARRAY1D_UTILS_H
#include <iostream>
namespace TNT
{
/**
Write an array to a character outstream. Output format is one that can
be read back in via the in-stream operator: one integer
denoting the array dimension (n), followed by n elements,
one per line.
*/
template <class T>
std::ostream& operator<<(std::ostream &s, const Fortran_Array1D<T> &A)
{
int N=A.dim1();
s << N << "\n";
for (int j=1; j<=N; j++)
{
s << A(j) << "\n";
}
s << "\n";
return s;
}
/**
Read an array from a character stream. Input format
is one integer, denoting the dimension (n), followed
by n whitespace-separated elments. Newlines are ignored
<p>
Note: the array being read into references new memory
storage. If the intent is to fill an existing conformant
array, use <code> cin >> B; A.inject(B) ); </code>
instead or read the elements in one-a-time by hand.
@param s the charater to read from (typically <code>std::in</code>)
@param A the array to read into.
*/
template <class T>
std::istream& operator>>(std::istream &s, Fortran_Array1D<T> &A)
{
int N;
s >> N;
Fortran_Array1D<T> B(N);
for (int i=1; i<=N; i++)
s >> B(i);
A = B;
return s;
}
template <class T>
Fortran_Array1D<T> operator+(const Fortran_Array1D<T> &A, const Fortran_Array1D<T> &B)
{
int n = A.dim1();
if (B.dim1() != n )
return Fortran_Array1D<T>();
else
{
Fortran_Array1D<T> C(n);
for (int i=1; i<=n; i++)
{
C(i) = A(i) + B(i);
}
return C;
}
}
template <class T>
Fortran_Array1D<T> operator-(const Fortran_Array1D<T> &A, const Fortran_Array1D<T> &B)
{
int n = A.dim1();
if (B.dim1() != n )
return Fortran_Array1D<T>();
else
{
Fortran_Array1D<T> C(n);
for (int i=1; i<=n; i++)
{
C(i) = A(i) - B(i);
}
return C;
}
}
template <class T>
Fortran_Array1D<T> operator*(const Fortran_Array1D<T> &A, const Fortran_Array1D<T> &B)
{
int n = A.dim1();
if (B.dim1() != n )
return Fortran_Array1D<T>();
else
{
Fortran_Array1D<T> C(n);
for (int i=1; i<=n; i++)
{
C(i) = A(i) * B(i);
}
return C;
}
}
template <class T>
Fortran_Array1D<T> operator/(const Fortran_Array1D<T> &A, const Fortran_Array1D<T> &B)
{
int n = A.dim1();
if (B.dim1() != n )
return Fortran_Array1D<T>();
else
{
Fortran_Array1D<T> C(n);
for (int i=1; i<=n; i++)
{
C(i) = A(i) / B(i);
}
return C;
}
}
template <class T>
Fortran_Array1D<T>& operator+=(Fortran_Array1D<T> &A, const Fortran_Array1D<T> &B)
{
int n = A.dim1();
if (B.dim1() == n)
{
for (int i=1; i<=n; i++)
{
A(i) += B(i);
}
}
return A;
}
template <class T>
Fortran_Array1D<T>& operator-=(Fortran_Array1D<T> &A, const Fortran_Array1D<T> &B)
{
int n = A.dim1();
if (B.dim1() == n)
{
for (int i=1; i<=n; i++)
{
A(i) -= B(i);
}
}
return A;
}
template <class T>
Fortran_Array1D<T>& operator*=(Fortran_Array1D<T> &A, const Fortran_Array1D<T> &B)
{
int n = A.dim1();
if (B.dim1() == n)
{
for (int i=1; i<=n; i++)
{
A(i) *= B(i);
}
}
return A;
}
template <class T>
Fortran_Array1D<T>& operator/=(Fortran_Array1D<T> &A, const Fortran_Array1D<T> &B)
{
int n = A.dim1();
if (B.dim1() == n)
{
for (int i=1; i<=n; i++)
{
A(i) /= B(i);
}
}
return A;
}
} // namespace TNT
#endif

View File

@@ -0,0 +1,225 @@
/*
*
* Template Numerical Toolkit (TNT): Two-dimensional Fortran numerical array
*
* Mathematical and Computational Sciences Division
* National Institute of Technology,
* Gaithersburg, MD USA
*
*
* This software was developed at the National Institute of Standards and
* Technology (NIST) by employees of the Federal Government in the course
* of their official duties. Pursuant to title 17 Section 105 of the
* United States Code, this software is not subject to copyright protection
* and is in the public domain. NIST assumes no responsibility whatsoever for
* its use by other parties, and makes no guarantees, expressed or implied,
* about its quality, reliability, or any other characteristic.
*
*/
#ifndef TNT_FORTRAN_ARRAY2D_H
#define TNT_FORTRAN_ARRAY2D_H
#include <cstdlib>
#include <iostream>
#ifdef TNT_BOUNDS_CHECK
#include <assert.h>
#endif
#include "tnt_i_refvec.h"
namespace TNT
{
template <class T>
class Fortran_Array2D
{
private:
i_refvec<T> v_;
int m_;
int n_;
T* data_;
void initialize_(int n);
void copy_(T* p, const T* q, int len);
void set_(T* begin, T* end, const T& val);
public:
typedef T value_type;
Fortran_Array2D();
Fortran_Array2D(int m, int n);
Fortran_Array2D(int m, int n, T *a);
Fortran_Array2D(int m, int n, const T &a);
inline Fortran_Array2D(const Fortran_Array2D &A);
inline Fortran_Array2D & operator=(const T &a);
inline Fortran_Array2D & operator=(const Fortran_Array2D &A);
inline Fortran_Array2D & ref(const Fortran_Array2D &A);
Fortran_Array2D copy() const;
Fortran_Array2D & inject(const Fortran_Array2D & A);
inline T& operator()(int i, int j);
inline const T& operator()(int i, int j) const ;
inline int dim1() const;
inline int dim2() const;
~Fortran_Array2D();
/* extended interface */
inline int ref_count() const;
};
template <class T>
Fortran_Array2D<T>::Fortran_Array2D() : v_(), m_(0), n_(0), data_(0) {}
template <class T>
Fortran_Array2D<T>::Fortran_Array2D(const Fortran_Array2D<T> &A) : v_(A.v_),
m_(A.m_), n_(A.n_), data_(A.data_) {}
template <class T>
Fortran_Array2D<T>::Fortran_Array2D(int m, int n) : v_(m*n), m_(m), n_(n),
data_(v_.begin()) {}
template <class T>
Fortran_Array2D<T>::Fortran_Array2D(int m, int n, const T &val) :
v_(m*n), m_(m), n_(n), data_(v_.begin())
{
set_(data_, data_+m*n, val);
}
template <class T>
Fortran_Array2D<T>::Fortran_Array2D(int m, int n, T *a) : v_(a),
m_(m), n_(n), data_(v_.begin()) {}
template <class T>
inline T& Fortran_Array2D<T>::operator()(int i, int j)
{
#ifdef TNT_BOUNDS_CHECK
assert(i >= 1);
assert(i <= m_);
assert(j >= 1);
assert(j <= n_);
#endif
return v_[ (j-1)*m_ + (i-1) ];
}
template <class T>
inline const T& Fortran_Array2D<T>::operator()(int i, int j) const
{
#ifdef TNT_BOUNDS_CHECK
assert(i >= 1);
assert(i <= m_);
assert(j >= 1);
assert(j <= n_);
#endif
return v_[ (j-1)*m_ + (i-1) ];
}
template <class T>
Fortran_Array2D<T> & Fortran_Array2D<T>::operator=(const T &a)
{
set_(data_, data_+m_*n_, a);
return *this;
}
template <class T>
Fortran_Array2D<T> Fortran_Array2D<T>::copy() const
{
Fortran_Array2D B(m_,n_);
B.inject(*this);
return B;
}
template <class T>
Fortran_Array2D<T> & Fortran_Array2D<T>::inject(const Fortran_Array2D &A)
{
if (m_ == A.m_ && n_ == A.n_)
copy_(data_, A.data_, m_*n_);
return *this;
}
template <class T>
Fortran_Array2D<T> & Fortran_Array2D<T>::ref(const Fortran_Array2D<T> &A)
{
if (this != &A)
{
v_ = A.v_;
m_ = A.m_;
n_ = A.n_;
data_ = A.data_;
}
return *this;
}
template <class T>
Fortran_Array2D<T> & Fortran_Array2D<T>::operator=(const Fortran_Array2D<T> &A)
{
return ref(A);
}
template <class T>
inline int Fortran_Array2D<T>::dim1() const { return m_; }
template <class T>
inline int Fortran_Array2D<T>::dim2() const { return n_; }
template <class T>
Fortran_Array2D<T>::~Fortran_Array2D()
{
}
template <class T>
inline int Fortran_Array2D<T>::ref_count() const { return v_.ref_count(); }
template <class T>
void Fortran_Array2D<T>::set_(T* begin, T* end, const T& a)
{
for (T* p=begin; p<end; p++)
*p = a;
}
template <class T>
void Fortran_Array2D<T>::copy_(T* p, const T* q, int len)
{
T *end = p + len;
while (p<end )
*p++ = *q++;
}
} /* namespace TNT */
#endif
/* TNT_FORTRAN_ARRAY2D_H */

View File

@@ -0,0 +1,236 @@
/*
*
* Template Numerical Toolkit (TNT)
*
* Mathematical and Computational Sciences Division
* National Institute of Technology,
* Gaithersburg, MD USA
*
*
* This software was developed at the National Institute of Standards and
* Technology (NIST) by employees of the Federal Government in the course
* of their official duties. Pursuant to title 17 Section 105 of the
* United States Code, this software is not subject to copyright protection
* and is in the public domain. NIST assumes no responsibility whatsoever for
* its use by other parties, and makes no guarantees, expressed or implied,
* about its quality, reliability, or any other characteristic.
*
*/
#ifndef TNT_FORTRAN_ARRAY2D_UTILS_H
#define TNT_FORTRAN_ARRAY2D_UTILS_H
#include <iostream>
namespace TNT
{
template <class T>
std::ostream& operator<<(std::ostream &s, const Fortran_Array2D<T> &A)
{
int M=A.dim1();
int N=A.dim2();
s << M << " " << N << "\n";
for (int i=1; i<=M; i++)
{
for (int j=1; j<=N; j++)
{
s << A(i,j) << " ";
}
s << "\n";
}
return s;
}
template <class T>
std::istream& operator>>(std::istream &s, Fortran_Array2D<T> &A)
{
int M, N;
s >> M >> N;
Fortran_Array2D<T> B(M,N);
for (int i=1; i<=M; i++)
for (int j=1; j<=N; j++)
{
s >> B(i,j);
}
A = B;
return s;
}
template <class T>
Fortran_Array2D<T> operator+(const Fortran_Array2D<T> &A, const Fortran_Array2D<T> &B)
{
int m = A.dim1();
int n = A.dim2();
if (B.dim1() != m || B.dim2() != n )
return Fortran_Array2D<T>();
else
{
Fortran_Array2D<T> C(m,n);
for (int i=1; i<=m; i++)
{
for (int j=1; j<=n; j++)
C(i,j) = A(i,j) + B(i,j);
}
return C;
}
}
template <class T>
Fortran_Array2D<T> operator-(const Fortran_Array2D<T> &A, const Fortran_Array2D<T> &B)
{
int m = A.dim1();
int n = A.dim2();
if (B.dim1() != m || B.dim2() != n )
return Fortran_Array2D<T>();
else
{
Fortran_Array2D<T> C(m,n);
for (int i=1; i<=m; i++)
{
for (int j=1; j<=n; j++)
C(i,j) = A(i,j) - B(i,j);
}
return C;
}
}
template <class T>
Fortran_Array2D<T> operator*(const Fortran_Array2D<T> &A, const Fortran_Array2D<T> &B)
{
int m = A.dim1();
int n = A.dim2();
if (B.dim1() != m || B.dim2() != n )
return Fortran_Array2D<T>();
else
{
Fortran_Array2D<T> C(m,n);
for (int i=1; i<=m; i++)
{
for (int j=1; j<=n; j++)
C(i,j) = A(i,j) * B(i,j);
}
return C;
}
}
template <class T>
Fortran_Array2D<T> operator/(const Fortran_Array2D<T> &A, const Fortran_Array2D<T> &B)
{
int m = A.dim1();
int n = A.dim2();
if (B.dim1() != m || B.dim2() != n )
return Fortran_Array2D<T>();
else
{
Fortran_Array2D<T> C(m,n);
for (int i=1; i<=m; i++)
{
for (int j=1; j<=n; j++)
C(i,j) = A(i,j) / B(i,j);
}
return C;
}
}
template <class T>
Fortran_Array2D<T>& operator+=(Fortran_Array2D<T> &A, const Fortran_Array2D<T> &B)
{
int m = A.dim1();
int n = A.dim2();
if (B.dim1() == m || B.dim2() == n )
{
for (int i=1; i<=m; i++)
{
for (int j=1; j<=n; j++)
A(i,j) += B(i,j);
}
}
return A;
}
template <class T>
Fortran_Array2D<T>& operator-=(Fortran_Array2D<T> &A, const Fortran_Array2D<T> &B)
{
int m = A.dim1();
int n = A.dim2();
if (B.dim1() == m || B.dim2() == n )
{
for (int i=1; i<=m; i++)
{
for (int j=1; j<=n; j++)
A(i,j) -= B(i,j);
}
}
return A;
}
template <class T>
Fortran_Array2D<T>& operator*=(Fortran_Array2D<T> &A, const Fortran_Array2D<T> &B)
{
int m = A.dim1();
int n = A.dim2();
if (B.dim1() == m || B.dim2() == n )
{
for (int i=1; i<=m; i++)
{
for (int j=1; j<=n; j++)
A(i,j) *= B(i,j);
}
}
return A;
}
template <class T>
Fortran_Array2D<T>& operator/=(Fortran_Array2D<T> &A, const Fortran_Array2D<T> &B)
{
int m = A.dim1();
int n = A.dim2();
if (B.dim1() == m || B.dim2() == n )
{
for (int i=1; i<=m; i++)
{
for (int j=1; j<=n; j++)
A(i,j) /= B(i,j);
}
}
return A;
}
} // namespace TNT
#endif

View File

@@ -0,0 +1,223 @@
/*
*
* Template Numerical Toolkit (TNT): Three-dimensional Fortran numerical array
*
* Mathematical and Computational Sciences Division
* National Institute of Technology,
* Gaithersburg, MD USA
*
*
* This software was developed at the National Institute of Standards and
* Technology (NIST) by employees of the Federal Government in the course
* of their official duties. Pursuant to title 17 Section 105 of the
* United States Code, this software is not subject to copyright protection
* and is in the public domain. NIST assumes no responsibility whatsoever for
* its use by other parties, and makes no guarantees, expressed or implied,
* about its quality, reliability, or any other characteristic.
*
*/
#ifndef TNT_FORTRAN_ARRAY3D_H
#define TNT_FORTRAN_ARRAY3D_H
#include <cstdlib>
#include <iostream>
#ifdef TNT_BOUNDS_CHECK
#include <assert.h>
#endif
#include "tnt_i_refvec.h"
namespace TNT
{
template <class T>
class Fortran_Array3D
{
private:
i_refvec<T> v_;
int m_;
int n_;
int k_;
T* data_;
public:
typedef T value_type;
Fortran_Array3D();
Fortran_Array3D(int m, int n, int k);
Fortran_Array3D(int m, int n, int k, T *a);
Fortran_Array3D(int m, int n, int k, const T &a);
inline Fortran_Array3D(const Fortran_Array3D &A);
inline Fortran_Array3D & operator=(const T &a);
inline Fortran_Array3D & operator=(const Fortran_Array3D &A);
inline Fortran_Array3D & ref(const Fortran_Array3D &A);
Fortran_Array3D copy() const;
Fortran_Array3D & inject(const Fortran_Array3D & A);
inline T& operator()(int i, int j, int k);
inline const T& operator()(int i, int j, int k) const ;
inline int dim1() const;
inline int dim2() const;
inline int dim3() const;
inline int ref_count() const;
~Fortran_Array3D();
};
template <class T>
Fortran_Array3D<T>::Fortran_Array3D() : v_(), m_(0), n_(0), k_(0), data_(0) {}
template <class T>
Fortran_Array3D<T>::Fortran_Array3D(const Fortran_Array3D<T> &A) :
v_(A.v_), m_(A.m_), n_(A.n_), k_(A.k_), data_(A.data_) {}
template <class T>
Fortran_Array3D<T>::Fortran_Array3D(int m, int n, int k) :
v_(m*n*k), m_(m), n_(n), k_(k), data_(v_.begin()) {}
template <class T>
Fortran_Array3D<T>::Fortran_Array3D(int m, int n, int k, const T &val) :
v_(m*n*k), m_(m), n_(n), k_(k), data_(v_.begin())
{
for (T* p = data_; p < data_ + m*n*k; p++)
*p = val;
}
template <class T>
Fortran_Array3D<T>::Fortran_Array3D(int m, int n, int k, T *a) :
v_(a), m_(m), n_(n), k_(k), data_(v_.begin()) {}
template <class T>
inline T& Fortran_Array3D<T>::operator()(int i, int j, int k)
{
#ifdef TNT_BOUNDS_CHECK
assert(i >= 1);
assert(i <= m_);
assert(j >= 1);
assert(j <= n_);
assert(k >= 1);
assert(k <= k_);
#endif
return data_[(k-1)*m_*n_ + (j-1) * m_ + i-1];
}
template <class T>
inline const T& Fortran_Array3D<T>::operator()(int i, int j, int k) const
{
#ifdef TNT_BOUNDS_CHECK
assert(i >= 1);
assert(i <= m_);
assert(j >= 1);
assert(j <= n_);
assert(k >= 1);
assert(k <= k_);
#endif
return data_[(k-1)*m_*n_ + (j-1) * m_ + i-1];
}
template <class T>
Fortran_Array3D<T> & Fortran_Array3D<T>::operator=(const T &a)
{
T *end = data_ + m_*n_*k_;
for (T *p=data_; p != end; *p++ = a);
return *this;
}
template <class T>
Fortran_Array3D<T> Fortran_Array3D<T>::copy() const
{
Fortran_Array3D B(m_, n_, k_);
B.inject(*this);
return B;
}
template <class T>
Fortran_Array3D<T> & Fortran_Array3D<T>::inject(const Fortran_Array3D &A)
{
if (m_ == A.m_ && n_ == A.n_ && k_ == A.k_)
{
T *p = data_;
T *end = data_ + m_*n_*k_;
const T* q = A.data_;
for (; p < end; *p++ = *q++);
}
return *this;
}
template <class T>
Fortran_Array3D<T> & Fortran_Array3D<T>::ref(const Fortran_Array3D<T> &A)
{
if (this != &A)
{
v_ = A.v_;
m_ = A.m_;
n_ = A.n_;
k_ = A.k_;
data_ = A.data_;
}
return *this;
}
template <class T>
Fortran_Array3D<T> & Fortran_Array3D<T>::operator=(const Fortran_Array3D<T> &A)
{
return ref(A);
}
template <class T>
inline int Fortran_Array3D<T>::dim1() const { return m_; }
template <class T>
inline int Fortran_Array3D<T>::dim2() const { return n_; }
template <class T>
inline int Fortran_Array3D<T>::dim3() const { return k_; }
template <class T>
inline int Fortran_Array3D<T>::ref_count() const
{
return v_.ref_count();
}
template <class T>
Fortran_Array3D<T>::~Fortran_Array3D()
{
}
} /* namespace TNT */
#endif
/* TNT_FORTRAN_ARRAY3D_H */

View File

@@ -0,0 +1,249 @@
/*
*
* Template Numerical Toolkit (TNT)
*
* Mathematical and Computational Sciences Division
* National Institute of Technology,
* Gaithersburg, MD USA
*
*
* This software was developed at the National Institute of Standards and
* Technology (NIST) by employees of the Federal Government in the course
* of their official duties. Pursuant to title 17 Section 105 of the
* United States Code, this software is not subject to copyright protection
* and is in the public domain. NIST assumes no responsibility whatsoever for
* its use by other parties, and makes no guarantees, expressed or implied,
* about its quality, reliability, or any other characteristic.
*
*/
#ifndef TNT_FORTRAN_ARRAY3D_UTILS_H
#define TNT_FORTRAN_ARRAY3D_UTILS_H
#include <cstdlib>
#include <cassert>
namespace TNT
{
template <class T>
std::ostream& operator<<(std::ostream &s, const Fortran_Array3D<T> &A)
{
int M=A.dim1();
int N=A.dim2();
int K=A.dim3();
s << M << " " << N << " " << K << "\n";
for (int i=1; i<=M; i++)
{
for (int j=1; j<=N; j++)
{
for (int k=1; k<=K; k++)
s << A(i,j,k) << " ";
s << "\n";
}
s << "\n";
}
return s;
}
template <class T>
std::istream& operator>>(std::istream &s, Fortran_Array3D<T> &A)
{
int M, N, K;
s >> M >> N >> K;
Fortran_Array3D<T> B(M,N,K);
for (int i=1; i<=M; i++)
for (int j=1; j<=N; j++)
for (int k=1; k<=K; k++)
s >> B(i,j,k);
A = B;
return s;
}
template <class T>
Fortran_Array3D<T> operator+(const Fortran_Array3D<T> &A, const Fortran_Array3D<T> &B)
{
int m = A.dim1();
int n = A.dim2();
int p = A.dim3();
if (B.dim1() != m || B.dim2() != n || B.dim3() != p )
return Fortran_Array3D<T>();
else
{
Fortran_Array3D<T> C(m,n,p);
for (int i=1; i<=m; i++)
for (int j=1; j<=n; j++)
for (int k=1; k<=p; k++)
C(i,j,k) = A(i,j,k)+ B(i,j,k);
return C;
}
}
template <class T>
Fortran_Array3D<T> operator-(const Fortran_Array3D<T> &A, const Fortran_Array3D<T> &B)
{
int m = A.dim1();
int n = A.dim2();
int p = A.dim3();
if (B.dim1() != m || B.dim2() != n || B.dim3() != p )
return Fortran_Array3D<T>();
else
{
Fortran_Array3D<T> C(m,n,p);
for (int i=1; i<=m; i++)
for (int j=1; j<=n; j++)
for (int k=1; k<=p; k++)
C(i,j,k) = A(i,j,k)- B(i,j,k);
return C;
}
}
template <class T>
Fortran_Array3D<T> operator*(const Fortran_Array3D<T> &A, const Fortran_Array3D<T> &B)
{
int m = A.dim1();
int n = A.dim2();
int p = A.dim3();
if (B.dim1() != m || B.dim2() != n || B.dim3() != p )
return Fortran_Array3D<T>();
else
{
Fortran_Array3D<T> C(m,n,p);
for (int i=1; i<=m; i++)
for (int j=1; j<=n; j++)
for (int k=1; k<=p; k++)
C(i,j,k) = A(i,j,k)* B(i,j,k);
return C;
}
}
template <class T>
Fortran_Array3D<T> operator/(const Fortran_Array3D<T> &A, const Fortran_Array3D<T> &B)
{
int m = A.dim1();
int n = A.dim2();
int p = A.dim3();
if (B.dim1() != m || B.dim2() != n || B.dim3() != p )
return Fortran_Array3D<T>();
else
{
Fortran_Array3D<T> C(m,n,p);
for (int i=1; i<=m; i++)
for (int j=1; j<=n; j++)
for (int k=1; k<=p; k++)
C(i,j,k) = A(i,j,k)/ B(i,j,k);
return C;
}
}
template <class T>
Fortran_Array3D<T>& operator+=(Fortran_Array3D<T> &A, const Fortran_Array3D<T> &B)
{
int m = A.dim1();
int n = A.dim2();
int p = A.dim3();
if (B.dim1() == m && B.dim2() == n && B.dim3() == p )
{
for (int i=1; i<=m; i++)
for (int j=1; j<=n; j++)
for (int k=1; k<=p; k++)
A(i,j,k) += B(i,j,k);
}
return A;
}
template <class T>
Fortran_Array3D<T>& operator-=(Fortran_Array3D<T> &A, const Fortran_Array3D<T> &B)
{
int m = A.dim1();
int n = A.dim2();
int p = A.dim3();
if (B.dim1() == m && B.dim2() == n && B.dim3() == p )
{
for (int i=1; i<=m; i++)
for (int j=1; j<=n; j++)
for (int k=1; k<=p; k++)
A(i,j,k) -= B(i,j,k);
}
return A;
}
template <class T>
Fortran_Array3D<T>& operator*=(Fortran_Array3D<T> &A, const Fortran_Array3D<T> &B)
{
int m = A.dim1();
int n = A.dim2();
int p = A.dim3();
if (B.dim1() == m && B.dim2() == n && B.dim3() == p )
{
for (int i=1; i<=m; i++)
for (int j=1; j<=n; j++)
for (int k=1; k<=p; k++)
A(i,j,k) *= B(i,j,k);
}
return A;
}
template <class T>
Fortran_Array3D<T>& operator/=(Fortran_Array3D<T> &A, const Fortran_Array3D<T> &B)
{
int m = A.dim1();
int n = A.dim2();
int p = A.dim3();
if (B.dim1() == m && B.dim2() == n && B.dim3() == p )
{
for (int i=1; i<=m; i++)
for (int j=1; j<=n; j++)
for (int k=1; k<=p; k++)
A(i,j,k) /= B(i,j,k);
}
return A;
}
} // namespace TNT
#endif

View File

@@ -0,0 +1,243 @@
/*
*
* Template Numerical Toolkit (TNT)
*
* Mathematical and Computational Sciences Division
* National Institute of Technology,
* Gaithersburg, MD USA
*
*
* This software was developed at the National Institute of Standards and
* Technology (NIST) by employees of the Federal Government in the course
* of their official duties. Pursuant to title 17 Section 105 of the
* United States Code, this software is not subject to copyright protection
* and is in the public domain. NIST assumes no responsibility whatsoever for
* its use by other parties, and makes no guarantees, expressed or implied,
* about its quality, reliability, or any other characteristic.
*
*/
#ifndef TNT_I_REFVEC_H
#define TNT_I_REFVEC_H
#include <cstdlib>
#include <iostream>
#ifdef TNT_BOUNDS_CHECK
#include <assert.h>
#endif
#ifndef NULL
#define NULL 0
#endif
namespace TNT
{
/*
Internal representation of ref-counted array. The TNT
arrays all use this building block.
<p>
If an array block is created by TNT, then every time
an assignment is made, the left-hand-side reference
is decreased by one, and the right-hand-side refernce
count is increased by one. If the array block was
external to TNT, the refernce count is a NULL pointer
regardless of how many references are made, since the
memory is not freed by TNT.
*/
template <class T>
class i_refvec
{
private:
T* data_;
int *ref_count_;
public:
i_refvec();
explicit i_refvec(int n);
inline i_refvec(T* data);
inline i_refvec(const i_refvec &v);
inline T* begin();
inline const T* begin() const;
inline T& operator[](int i);
inline const T& operator[](int i) const;
inline i_refvec<T> & operator=(const i_refvec<T> &V);
void copy_(T* p, const T* q, const T* e);
void set_(T* p, const T* b, const T* e);
inline int ref_count() const;
inline int is_null() const;
inline void destroy();
~i_refvec();
};
template <class T>
void i_refvec<T>::copy_(T* p, const T* q, const T* e)
{
for (T* t=p; q<e; t++, q++)
*t= *q;
}
template <class T>
i_refvec<T>::i_refvec() : data_(NULL), ref_count_(NULL) {}
/**
In case n is 0 or negative, it does NOT call new.
*/
template <class T>
i_refvec<T>::i_refvec(int n) : data_(NULL), ref_count_(NULL)
{
if (n >= 1)
{
#ifdef TNT_DEBUG
std::cout << "new data storage.\n";
#endif
data_ = new T[n];
ref_count_ = new int;
*ref_count_ = 1;
}
}
template <class T>
inline i_refvec<T>::i_refvec(const i_refvec<T> &V): data_(V.data_),
ref_count_(V.ref_count_)
{
if (V.ref_count_ != NULL)
(*(V.ref_count_))++;
}
template <class T>
i_refvec<T>::i_refvec(T* data) : data_(data), ref_count_(NULL) {}
template <class T>
inline T* i_refvec<T>::begin()
{
return data_;
}
template <class T>
inline const T& i_refvec<T>::operator[](int i) const
{
return data_[i];
}
template <class T>
inline T& i_refvec<T>::operator[](int i)
{
return data_[i];
}
template <class T>
inline const T* i_refvec<T>::begin() const
{
return data_;
}
template <class T>
i_refvec<T> & i_refvec<T>::operator=(const i_refvec<T> &V)
{
if (this == &V)
return *this;
if (ref_count_ != NULL)
{
(*ref_count_) --;
if ((*ref_count_) == 0)
destroy();
}
data_ = V.data_;
ref_count_ = V.ref_count_;
if (V.ref_count_ != NULL)
(*(V.ref_count_))++;
return *this;
}
template <class T>
void i_refvec<T>::destroy()
{
if (ref_count_ != NULL)
{
#ifdef TNT_DEBUG
std::cout << "destorying data... \n";
#endif
delete ref_count_;
#ifdef TNT_DEBUG
std::cout << "deleted ref_count_ ...\n";
#endif
if (data_ != NULL)
delete []data_;
#ifdef TNT_DEBUG
std::cout << "deleted data_[] ...\n";
#endif
data_ = NULL;
}
}
/*
* return 1 is vector is empty, 0 otherwise
*
* if is_null() is false and ref_count() is 0, then
*
*/
template<class T>
int i_refvec<T>::is_null() const
{
return (data_ == NULL ? 1 : 0);
}
/*
* returns -1 if data is external,
* returns 0 if a is NULL array,
* otherwise returns the positive number of vectors sharing
* this data space.
*/
template <class T>
int i_refvec<T>::ref_count() const
{
if (data_ == NULL)
return 0;
else
return (ref_count_ != NULL ? *ref_count_ : -1) ;
}
template <class T>
i_refvec<T>::~i_refvec()
{
if (ref_count_ != NULL)
{
(*ref_count_)--;
if (*ref_count_ == 0)
destroy();
}
}
} /* namespace TNT */
#endif
/* TNT_I_REFVEC_H */

View File

@@ -0,0 +1,34 @@
#ifndef MATH_UTILS_H
#define MATH_UTILS_H
/* needed for fabs, sqrt() below */
#include <cmath>
namespace TNT
{
/**
@returns hypotenuse of real (non-complex) scalars a and b by
avoiding underflow/overflow
using (a * sqrt( 1 + (b/a) * (b/a))), rather than
sqrt(a*a + b*b).
*/
template <class Real>
Real hypot(const Real &a, const Real &b)
{
if (a== 0)
return fabs(b);
else
{
Real c = b/a;
return fabs(a) * sqrt(1 + c*c);
}
}
} /* TNT namespace */
#endif
/* MATH_UTILS_H */

View File

@@ -0,0 +1,103 @@
/*
*
* Template Numerical Toolkit (TNT)
*
* Mathematical and Computational Sciences Division
* National Institute of Technology,
* Gaithersburg, MD USA
*
*
* This software was developed at the National Institute of Standards and
* Technology (NIST) by employees of the Federal Government in the course
* of their official duties. Pursuant to title 17 Section 105 of the
* United States Code, this software is not subject to copyright protection
* and is in the public domain. NIST assumes no responsibility whatsoever for
* its use by other parties, and makes no guarantees, expressed or implied,
* about its quality, reliability, or any other characteristic.
*
*/
#ifndef TNT_SPARSE_MATRIX_CSR_H
#define TNT_SPARSE_MATRIX_CSR_H
#include "tnt_array1d.h"
namespace TNT
{
/**
Read-only view of a sparse matrix in compressed-row storage
format. Neither array elements (nonzeros) nor sparsity
structure can be modified. If modifications are required,
create a new view.
<p>
Index values begin at 0.
<p>
<b>Storage requirements:</b> An (m x n) matrix with
nz nonzeros requires no more than ((T+I)*nz + M*I)
bytes, where T is the size of data elements and
I is the size of integers.
*/
template <class T>
class Sparse_Matrix_CompRow {
private:
Array1D<T> val_; // data values (nz_ elements)
Array1D<int> rowptr_; // row_ptr (dim_[0]+1 elements)
Array1D<int> colind_; // col_ind (nz_ elements)
int dim1_; // number of rows
int dim2_; // number of cols
public:
Sparse_Matrix_CompRow(const Sparse_Matrix_CompRow &S);
Sparse_Matrix_CompRow(int M, int N, int nz, const T *val,
const int *r, const int *c);
inline const T& val(int i) const { return val_[i]; }
inline const int& row_ptr(int i) const { return rowptr_[i]; }
inline const int& col_ind(int i) const { return colind_[i];}
inline int dim1() const {return dim1_;}
inline int dim2() const {return dim2_;}
int NumNonzeros() const {return val_.dim1();}
Sparse_Matrix_CompRow& operator=(
const Sparse_Matrix_CompRow &R);
};
/**
Construct a read-only view of existing sparse matrix in
compressed-row storage format.
@param M the number of rows of sparse matrix
@param N the number of columns of sparse matrix
@param nz the number of nonzeros
@param val a contiguous list of nonzero values
@param r row-pointers: r[i] denotes the begining position of row i
(i.e. the ith row begins at val[row[i]]).
@param c column-indices: c[i] denotes the column location of val[i]
*/
template <class T>
Sparse_Matrix_CompRow<T>::Sparse_Matrix_CompRow(int M, int N, int nz,
const T *val, const int *r, const int *c) : val_(nz,val),
rowptr_(M, r), colind_(nz, c), dim1_(M), dim2_(N) {}
}
// namespace TNT
#endif

View File

@@ -0,0 +1,95 @@
/*
*
* Mathematical and Computational Sciences Division
* National Institute of Technology,
* Gaithersburg, MD USA
*
*
* This software was developed at the National Institute of Standards and
* Technology (NIST) by employees of the Federal Government in the course
* of their official duties. Pursuant to title 17 Section 105 of the
* United States Code, this software is not subject to copyright protection
* and is in the public domain. NIST assumes no responsibility whatsoever for
* its use by other parties, and makes no guarantees, expressed or implied,
* about its quality, reliability, or any other characteristic.
*
*/
#ifndef STOPWATCH_H
#define STOPWATCH_H
// for clock() and CLOCKS_PER_SEC
#include <time.h>
namespace TNT
{
inline static double seconds(void)
{
const double secs_per_tick = 1.0 / CLOCKS_PER_SEC;
return ( (double) clock() ) * secs_per_tick;
}
class Stopwatch {
private:
int running_;
double start_time_;
double total_;
public:
inline Stopwatch();
inline void start();
inline double stop();
inline double read();
inline void resume();
inline int running();
};
inline Stopwatch::Stopwatch() : running_(0), start_time_(0.0), total_(0.0) {}
void Stopwatch::start()
{
running_ = 1;
total_ = 0.0;
start_time_ = seconds();
}
double Stopwatch::stop()
{
if (running_)
{
total_ += (seconds() - start_time_);
running_ = 0;
}
return total_;
}
inline void Stopwatch::resume()
{
if (!running_)
{
start_time_ = seconds();
running_ = 1;
}
}
inline double Stopwatch::read()
{
if (running_)
{
stop();
resume();
}
return total_;
}
} /* TNT namespace */
#endif

View File

@@ -0,0 +1,54 @@
/*
*
* Template Numerical Toolkit (TNT)
*
* Mathematical and Computational Sciences Division
* National Institute of Technology,
* Gaithersburg, MD USA
*
*
* This software was developed at the National Institute of Standards and
* Technology (NIST) by employees of the Federal Government in the course
* of their official duties. Pursuant to title 17 Section 105 of the
* United States Code, this software is not subject to copyright protection
* and is in the public domain. NIST assumes no responsibility whatsoever for
* its use by other parties, and makes no guarantees, expressed or implied,
* about its quality, reliability, or any other characteristic.
*
*/
#ifndef TNT_SUBSCRPT_H
#define TNT_SUBSCRPT_H
//---------------------------------------------------------------------
// This definition describes the default TNT data type used for
// indexing into TNT matrices and vectors. The data type should
// be wide enough to index into large arrays. It defaults to an
// "int", but can be overriden at compile time redefining TNT_SUBSCRIPT_TYPE,
// e.g.
//
// c++ -DTNT_SUBSCRIPT_TYPE='unsigned int' ...
//
//---------------------------------------------------------------------
//
#ifndef TNT_SUBSCRIPT_TYPE
#define TNT_SUBSCRIPT_TYPE int
#endif
namespace TNT
{
typedef TNT_SUBSCRIPT_TYPE Subscript;
} /* namespace TNT */
// () indexing in TNT means 1-offset, i.e. x(1) and A(1,1) are the
// first elements. This offset is left as a macro for future
// purposes, but should not be changed in the current release.
//
//
#define TNT_BASE_OFFSET (1)
#endif

View File

@@ -0,0 +1,404 @@
/*
*
* Template Numerical Toolkit (TNT)
*
* Mathematical and Computational Sciences Division
* National Institute of Technology,
* Gaithersburg, MD USA
*
*
* This software was developed at the National Institute of Standards and
* Technology (NIST) by employees of the Federal Government in the course
* of their official duties. Pursuant to title 17 Section 105 of the
* United States Code, this software is not subject to copyright protection
* and is in the public domain. NIST assumes no responsibility whatsoever for
* its use by other parties, and makes no guarantees, expressed or implied,
* about its quality, reliability, or any other characteristic.
*
*/
#ifndef TNT_VEC_H
#define TNT_VEC_H
#include "tnt_subscript.h"
#include <cstdlib>
#include <cassert>
#include <iostream>
#include <sstream>
namespace TNT
{
/**
<b>[Deprecatred]</b> Value-based vector class from pre-1.0
TNT version. Kept here for backward compatiblity, but should
use the newer TNT::Array1D classes instead.
*/
template <class T>
class Vector
{
public:
typedef Subscript size_type;
typedef T value_type;
typedef T element_type;
typedef T* pointer;
typedef T* iterator;
typedef T& reference;
typedef const T* const_iterator;
typedef const T& const_reference;
Subscript lbound() const { return 1;}
protected:
T* v_;
T* vm1_; // pointer adjustment for optimzied 1-offset indexing
Subscript n_;
// internal helper function to create the array
// of row pointers
void initialize(Subscript N)
{
// adjust pointers so that they are 1-offset:
// v_[] is the internal contiguous array, it is still 0-offset
//
assert(v_ == NULL);
v_ = new T[N];
assert(v_ != NULL);
vm1_ = v_-1;
n_ = N;
}
void copy(const T* v)
{
Subscript N = n_;
Subscript i;
#ifdef TNT_UNROLL_LOOPS
Subscript Nmod4 = N & 3;
Subscript N4 = N - Nmod4;
for (i=0; i<N4; i+=4)
{
v_[i] = v[i];
v_[i+1] = v[i+1];
v_[i+2] = v[i+2];
v_[i+3] = v[i+3];
}
for (i=N4; i< N; i++)
v_[i] = v[i];
#else
for (i=0; i< N; i++)
v_[i] = v[i];
#endif
}
void set(const T& val)
{
Subscript N = n_;
Subscript i;
#ifdef TNT_UNROLL_LOOPS
Subscript Nmod4 = N & 3;
Subscript N4 = N - Nmod4;
for (i=0; i<N4; i+=4)
{
v_[i] = val;
v_[i+1] = val;
v_[i+2] = val;
v_[i+3] = val;
}
for (i=N4; i< N; i++)
v_[i] = val;
#else
for (i=0; i< N; i++)
v_[i] = val;
#endif
}
void destroy()
{
/* do nothing, if no memory has been previously allocated */
if (v_ == NULL) return ;
/* if we are here, then matrix was previously allocated */
delete [] (v_);
v_ = NULL;
vm1_ = NULL;
}
public:
// access
iterator begin() { return v_;}
iterator end() { return v_ + n_; }
iterator begin() const { return v_;}
iterator end() const { return v_ + n_; }
// destructor
~Vector()
{
destroy();
}
// constructors
Vector() : v_(0), vm1_(0), n_(0) {};
Vector(const Vector<T> &A) : v_(0), vm1_(0), n_(0)
{
initialize(A.n_);
copy(A.v_);
}
Vector(Subscript N, const T& value = T()) : v_(0), vm1_(0), n_(0)
{
initialize(N);
set(value);
}
Vector(Subscript N, const T* v) : v_(0), vm1_(0), n_(0)
{
initialize(N);
copy(v);
}
Vector(Subscript N, char *s) : v_(0), vm1_(0), n_(0)
{
initialize(N);
std::istringstream ins(s);
Subscript i;
for (i=0; i<N; i++)
ins >> v_[i];
}
// methods
//
Vector<T>& newsize(Subscript N)
{
if (n_ == N) return *this;
destroy();
initialize(N);
return *this;
}
// assignments
//
Vector<T>& operator=(const Vector<T> &A)
{
if (v_ == A.v_)
return *this;
if (n_ == A.n_) // no need to re-alloc
copy(A.v_);
else
{
destroy();
initialize(A.n_);
copy(A.v_);
}
return *this;
}
Vector<T>& operator=(const T& scalar)
{
set(scalar);
return *this;
}
inline Subscript dim() const
{
return n_;
}
inline Subscript size() const
{
return n_;
}
inline reference operator()(Subscript i)
{
#ifdef TNT_BOUNDS_CHECK
assert(1<=i);
assert(i <= n_) ;
#endif
return vm1_[i];
}
inline const_reference operator() (Subscript i) const
{
#ifdef TNT_BOUNDS_CHECK
assert(1<=i);
assert(i <= n_) ;
#endif
return vm1_[i];
}
inline reference operator[](Subscript i)
{
#ifdef TNT_BOUNDS_CHECK
assert(0<=i);
assert(i < n_) ;
#endif
return v_[i];
}
inline const_reference operator[](Subscript i) const
{
#ifdef TNT_BOUNDS_CHECK
assert(0<=i);
assert(i < n_) ;
#endif
return v_[i];
}
};
/* *************************** I/O ********************************/
template <class T>
std::ostream& operator<<(std::ostream &s, const Vector<T> &A)
{
Subscript N=A.dim();
s << N << "\n";
for (Subscript i=0; i<N; i++)
s << A[i] << " " << "\n";
s << "\n";
return s;
}
template <class T>
std::istream & operator>>(std::istream &s, Vector<T> &A)
{
Subscript N;
s >> N;
if ( !(N == A.size() ))
{
A.newsize(N);
}
for (Subscript i=0; i<N; i++)
s >> A[i];
return s;
}
// *******************[ basic matrix algorithms ]***************************
template <class T>
Vector<T> operator+(const Vector<T> &A,
const Vector<T> &B)
{
Subscript N = A.dim();
assert(N==B.dim());
Vector<T> tmp(N);
Subscript i;
for (i=0; i<N; i++)
tmp[i] = A[i] + B[i];
return tmp;
}
template <class T>
Vector<T> operator-(const Vector<T> &A,
const Vector<T> &B)
{
Subscript N = A.dim();
assert(N==B.dim());
Vector<T> tmp(N);
Subscript i;
for (i=0; i<N; i++)
tmp[i] = A[i] - B[i];
return tmp;
}
template <class T>
Vector<T> operator*(const Vector<T> &A,
const Vector<T> &B)
{
Subscript N = A.dim();
assert(N==B.dim());
Vector<T> tmp(N);
Subscript i;
for (i=0; i<N; i++)
tmp[i] = A[i] * B[i];
return tmp;
}
template <class T>
T dot_prod(const Vector<T> &A, const Vector<T> &B)
{
Subscript N = A.dim();
assert(N == B.dim());
Subscript i;
T sum = 0;
for (i=0; i<N; i++)
sum += A[i] * B[i];
return sum;
}
} /* namespace TNT */
#endif
// TNT_VEC_H

View File

@@ -0,0 +1,39 @@
/*
*
* Template Numerical Toolkit (TNT)
*
* Mathematical and Computational Sciences Division
* National Institute of Technology,
* Gaithersburg, MD USA
*
*
* This software was developed at the National Institute of Standards and
* Technology (NIST) by employees of the Federal Government in the course
* of their official duties. Pursuant to title 17 Section 105 of the
* United States Code, this software is not subject to copyright protection
* and is in the public domain. NIST assumes no responsibility whatsoever for
* its use by other parties, and makes no guarantees, expressed or implied,
* about its quality, reliability, or any other characteristic.
*
*/
#ifndef TNT_VERSION_H
#define TNT_VERSION_H
//---------------------------------------------------------------------
// current version
//---------------------------------------------------------------------
#define TNT_MAJOR_VERSION '1'
#define TNT_MINOR_VERSION '2'
#define TNT_SUBMINOR_VERSION '6'
#define TNT_VERSION_STRING "1.2.6"
#endif
// TNT_VERSION_H

View File

@@ -766,6 +766,10 @@
RelativePath="..\..\..\source\blender\makesrna\intern\rna_screen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_sculpt_paint.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_sensor.c"
>
@@ -810,10 +814,6 @@
RelativePath="..\..\..\source\blender\makesrna\intern\rna_vfont.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_vpaint.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_wm.c"
>

View File

@@ -322,6 +322,10 @@
RelativePath="..\..\..\source\blender\makesrna\intern\rna_screen_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_sculpt_paint_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_sensor_gen.c"
>
@@ -362,10 +366,6 @@
RelativePath="..\..\..\source\blender\makesrna\intern\rna_vfont_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_vpaint_gen.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\makesrna\intern\rna_wm_gen.c"
>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 173 KiB

After

Width:  |  Height:  |  Size: 175 KiB

View File

@@ -0,0 +1,780 @@
import bpy
from math import atan, pi, degrees
import subprocess
import os
import sys
import time
import platform as pltfrm
if pltfrm.architecture()[0] == '64bit':
bitness = 64
else:
bitness = 32
def write_pov(filename, scene=None, info_callback = None):
file = open(filename, 'w')
# Only for testing
if not scene:
scene = bpy.data.scenes[0]
render = scene.render_data
materialTable = {}
def saneName(name):
name = name.lower()
for ch in ' /\\+=-[]{}().,<>\'":;~!@#$%^&*|?':
name = name.replace(ch, '_')
return name
def writeMatrix(matrix):
file.write('\tmatrix <%.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f>\n' %\
(matrix[0][0], matrix[0][1], matrix[0][2], matrix[1][0], matrix[1][1], matrix[1][2], matrix[2][0], matrix[2][1], matrix[2][2], matrix[3][0], matrix[3][1], matrix[3][2]) )
def exportCamera():
camera = scene.camera
matrix = camera.matrix
# compute resolution
Qsize=float(render.resolution_x)/float(render.resolution_y)
file.write('camera {\n')
file.write('\tlocation <0, 0, 0>\n')
file.write('\tlook_at <0, 0, -1>\n')
file.write('\tright <%s, 0, 0>\n' % -Qsize)
file.write('\tup <0, 1, 0>\n')
file.write('\tangle %f \n' % (360.0*atan(16.0/camera.data.lens)/pi))
file.write('\trotate <%.6f, %.6f, %.6f>\n' % tuple([degrees(e) for e in matrix.rotationPart().toEuler()]))
file.write('\ttranslate <%.6f, %.6f, %.6f>\n' % (matrix[3][0], matrix[3][1], matrix[3][2]))
file.write('}\n')
def exportLamps(lamps):
# Get all lamps
for ob in lamps:
lamp = ob.data
matrix = ob.matrix
color = tuple([c * lamp.energy for c in lamp.color]) # Colour is modified by energy
file.write('light_source {\n')
file.write('\t< 0,0,0 >\n')
file.write('\tcolor rgb<%.3g, %.3g, %.3g>\n' % color)
if lamp.type == 'POINT': # Point Lamp
pass
elif lamp.type == 'SPOT': # Spot
file.write('\tspotlight\n')
# Falloff is the main radius from the centre line
file.write('\tfalloff %.2f\n' % (lamp.spot_size/2.0) ) # 1 TO 179 FOR BOTH
file.write('\tradius %.6f\n' % ((lamp.spot_size/2.0) * (1-lamp.spot_blend)) )
# Blender does not have a tightness equivilent, 0 is most like blender default.
file.write('\ttightness 0\n') # 0:10f
file.write('\tpoint_at <0, 0, -1>\n')
elif lamp.type == 'AREA':
size_x = lamp.size
samples_x = lamp.shadow_ray_samples_x
if lamp.shape == 'SQUARE':
size_y = size_x
samples_y = samples_x
else:
size_y = lamp.size_y
samples_y = lamp.shadow_ray_samples_y
file.write('\tarea_light <%d,0,0>,<0,0,%d> %d, %d\n' % (size_x, size_y, samples_x, samples_y))
if lamp.shadow_ray_sampling_method == 'CONSTANT_JITTERED':
if lamp.jitter:
file.write('\tjitter\n')
else:
file.write('\tadaptive 1\n')
file.write('\tjitter\n')
if lamp.shadow_method == 'NOSHADOW':
file.write('\tshadowless\n')
file.write('\tfade_distance %.6f\n' % lamp.distance)
file.write('\tfade_power %d\n' % 1) # Could use blenders lamp quad?
writeMatrix(matrix)
file.write('}\n')
def exportMeshs(sel):
def bMat2PovString(material):
povstring = 'finish {'
if world != None:
povstring += 'ambient <%.6f, %.6f, %.6f> ' % tuple([c*material.ambient for c in world.ambient_color])
povstring += 'diffuse %.6f ' % material.diffuse_reflection
povstring += 'specular %.6f ' % material.specular_reflection
if material.raytrace_mirror.enabled:
#povstring += 'interior { ior %.6f } ' % material.IOR
raytrace_mirror= material.raytrace_mirror
if raytrace_mirror.reflect:
povstring += 'reflection {'
povstring += '<%.6f, %.6f, %.6f>' % tuple(material.mirror_color) # Should ask for ray mirror flag
povstring += 'fresnel 1 falloff %.6f exponent %.6f metallic %.6f} ' % (raytrace_mirror.fresnel, raytrace_mirror.fresnel_fac, raytrace_mirror.reflect)
if material.raytrace_transparency.enabled:
#povstring += 'interior { ior %.6f } ' % material.IOR
pass
#file.write('\t\troughness %.6f\n' % (material.hard*0.5))
#file.write('\t\t\tcrand 0.0\n') # Sand granyness
#file.write('\t\t\tmetallic %.6f\n' % material.spec)
#file.write('\t\t\tphong %.6f\n' % material.spec)
#file.write('\t\t\tphong_size %.6f\n' % material.spec)
povstring += 'brilliance %.6f ' % (material.specular_hardness/256.0) # Like hardness
povstring += '}'
#file.write('\t}\n')
return povstring
world = scene.world
# Convert all materials to strings we can access directly per vertex.
for material in bpy.data.materials:
materialTable[material.name] = bMat2PovString(material)
ob_num = 0
for ob in sel:
ob_num+= 1
if ob.type in ('LAMP', 'CAMERA', 'EMPTY'):
continue
me = ob.data
me_materials= me.materials
me = ob.create_render_mesh(scene)
if not me:
continue
if info_callback:
info_callback('Object %2.d of %2.d (%s)' % (ob_num, len(sel), ob.name))
#if ob.type!='MESH':
# continue
# me = ob.data
matrix = ob.matrix
try: uv_layer = me.active_uv_texture.data
except:uv_layer = None
try: vcol_layer = me.active_vertex_color.data
except:vcol_layer = None
def regular_face(f):
fv = f.verts
if fv[3]== 0:
return fv[0], fv[1], fv[2]
return fv[0], fv[1], fv[2], fv[3]
faces_verts = [regular_face(f) for f in me.faces]
faces_normals = [tuple(f.normal) for f in me.faces]
verts_normals = [tuple(v.normal) for v in me.verts]
# quads incur an extra face
quadCount = len([f for f in faces_verts if len(f)==4])
file.write('mesh2 {\n')
file.write('\tvertex_vectors {\n')
file.write('\t\t%s' % (len(me.verts))) # vert count
for v in me.verts:
file.write(',\n\t\t<%.6f, %.6f, %.6f>' % tuple(v.co)) # vert count
file.write('\n }\n')
# Build unique Normal list
uniqueNormals = {}
for fi, f in enumerate(me.faces):
fv = faces_verts[fi]
# [-1] is a dummy index, use a list so we can modify in place
if f.smooth: # Use vertex normals
for v in fv:
key = verts_normals[v]
uniqueNormals[key] = [-1]
else: # Use face normal
key = faces_normals[fi]
uniqueNormals[key] = [-1]
file.write('\tnormal_vectors {\n')
file.write('\t\t%d' % len(uniqueNormals)) # vert count
idx = 0
for no, index in uniqueNormals.items():
file.write(',\n\t\t<%.6f, %.6f, %.6f>' % no) # vert count
index[0] = idx
idx +=1
file.write('\n }\n')
# Vertex colours
vertCols = {} # Use for material colours also.
if uv_layer:
# Generate unique UV's
uniqueUVs = {}
for fi, uv in enumerate(uv_layer):
if len(faces_verts[fi])==4:
uvs = uv.uv1, uv.uv2, uv.uv3, uv.uv4
else:
uvs = uv.uv1, uv.uv2, uv.uv3
for uv in uvs:
uniqueUVs[tuple(uv)] = [-1]
file.write('\tuv_vectors {\n')
#print unique_uvs
file.write('\t\t%s' % (len(uniqueUVs))) # vert count
idx = 0
for uv, index in uniqueUVs.items():
file.write(',\n\t\t<%.6f, %.6f>' % uv)
index[0] = idx
idx +=1
'''
else:
# Just add 1 dummy vector, no real UV's
file.write('\t\t1') # vert count
file.write(',\n\t\t<0.0, 0.0>')
'''
file.write('\n }\n')
if me.vertex_colors:
for fi, f in enumerate(me.faces):
material_index = f.material_index
material = me_materials[material_index]
if material and material.vertex_color_paint:
col = vcol_layer[fi]
if len(faces_verts[fi])==4:
cols = col.color1, col.color2, col.color3, col.color4
else:
cols = col.color1, col.color2, col.color3
for col in cols:
key = col[0], col[1], col[2], material_index # Material index!
vertCols[key] = [-1]
else:
if material:
diffuse_color = tuple(material.diffuse_color)
key = diffuse_color[0], diffuse_color[1], diffuse_color[2], material_index
vertCols[key] = [-1]
else:
# No vertex colours, so write material colours as vertex colours
for i, material in enumerate(me_materials):
if material:
diffuse_color = tuple(material.diffuse_color)
key = diffuse_color[0], diffuse_color[1], diffuse_color[2], i # i == f.mat
vertCols[key] = [-1]
# Vert Colours
file.write('\ttexture_list {\n')
file.write('\t\t%s' % (len(vertCols))) # vert count
idx=0
for col, index in vertCols.items():
if me_materials:
material = me_materials[col[3]]
materialString = materialTable[material.name]
else:
materialString = '' # Dont write anything
float_col = col[0], col[1], col[2], 1-material.alpha, materialString
#print material.apl
file.write(',\n\t\ttexture { pigment {rgbf<%.3g, %.3g, %.3g, %.3g>}%s}' % float_col)
index[0] = idx
idx+=1
file.write( '\n }\n' )
# Face indicies
file.write('\tface_indices {\n')
file.write('\t\t%d' % (len(me.faces) + quadCount)) # faces count
for fi, f in enumerate(me.faces):
fv = faces_verts[fi]
material_index= f.material_index
if len(fv) == 4: indicies = (0,1,2), (0,2,3)
else: indicies = ((0,1,2),)
if vcol_layer:
col = vcol_layer[fi]
if len(fv) == 4:
cols = col.color1, col.color2, col.color3, col.color4
else:
cols = col.color1, col.color2, col.color3
if not me_materials or me_materials[material_index] == None: # No materials
for i1, i2, i3 in indicies:
file.write(',\n\t\t<%d,%d,%d>' % (fv[i1], fv[i2], fv[i3])) # vert count
else:
material = me_materials[material_index]
for i1, i2, i3 in indicies:
if me.vertex_colors and material.vertex_color_paint:
# Colour per vertex - vertex colour
col1 = cols[i1]
col2 = cols[i2]
col3 = cols[i3]
ci1 = vertCols[col1[0], col1[1], col1[2], material_index][0]
ci2 = vertCols[col2[0], col2[1], col2[2], material_index][0]
ci3 = vertCols[col3[0], col3[1], col3[2], material_index][0]
else:
# Colour per material - flat material colour
diffuse_color= material.diffuse_color
ci1 = ci2 = ci3 = vertCols[diffuse_color[0], diffuse_color[1], diffuse_color[2], f.material_index][0]
file.write(',\n\t\t<%d,%d,%d>, %d,%d,%d' % (fv[i1], fv[i2], fv[i3], ci1, ci2, ci3)) # vert count
file.write('\n }\n')
# normal_indices indicies
file.write('\tnormal_indices {\n')
file.write('\t\t%d' % (len(me.faces) + quadCount)) # faces count
for fi, fv in enumerate(faces_verts):
if len(fv) == 4: indicies = (0,1,2), (0,2,3)
else: indicies = ((0,1,2),)
for i1, i2, i3 in indicies:
if f.smooth:
file.write(',\n\t\t<%d,%d,%d>' %\
(uniqueNormals[verts_normals[fv[i1]]][0],\
uniqueNormals[verts_normals[fv[i2]]][0],\
uniqueNormals[verts_normals[fv[i3]]][0])) # vert count
else:
idx = uniqueNormals[faces_normals[fi]][0]
file.write(',\n\t\t<%d,%d,%d>' % (idx, idx, idx)) # vert count
file.write('\n }\n')
if uv_layer:
file.write('\tuv_indices {\n')
file.write('\t\t%d' % (len(me.faces) + quadCount)) # faces count
for fi, fv in enumerate(faces_verts):
if len(fv) == 4: indicies = (0,1,2), (0,2,3)
else: indicies = ((0,1,2),)
uv = uv_layer[fi]
if len(faces_verts[fi])==4:
uvs = tuple(uv.uv1), tuple(uv.uv2), tuple(uv.uv3), tuple(uv.uv4)
else:
uvs = tuple(uv.uv1), tuple(uv.uv2), tuple(uv.uv3)
for i1, i2, i3 in indicies:
file.write(',\n\t\t<%d,%d,%d>' %\
(uniqueUVs[uvs[i1]][0],\
uniqueUVs[uvs[i2]][0],\
uniqueUVs[uvs[i2]][0])) # vert count
file.write('\n }\n')
if me.materials:
material = me.materials[0] # dodgy
if material and material.raytrace_transparency.enabled:
file.write('\tinterior { ior %.6f }\n' % material.raytrace_transparency.ior)
writeMatrix(matrix)
file.write('}\n')
bpy.data.remove_mesh(me)
def exportWorld(world):
if not world:
return
mist = world.mist
if mist.enabled:
file.write('fog {\n')
file.write('\tdistance %.6f\n' % mist.depth)
file.write('\tcolor rgbt<%.3g, %.3g, %.3g, %.3g>\n' % (tuple(world.horizon_color) + (1-mist.intensity,)))
#file.write('\tfog_offset %.6f\n' % mist.start)
#file.write('\tfog_alt 5\n')
#file.write('\tturbulence 0.2\n')
#file.write('\tturb_depth 0.3\n')
file.write('\tfog_type 1\n')
file.write('}\n')
def exportGlobalSettings(scene):
file.write('global_settings {\n')
if scene.pov_radio_enable:
file.write('\tradiosity {\n')
file.write("\t\tadc_bailout %.4g\n" % scene.pov_radio_adc_bailout)
file.write("\t\talways_sample %d\n" % scene.pov_radio_always_sample)
file.write("\t\tbrightness %.4g\n" % scene.pov_radio_brightness)
file.write("\t\tcount %d\n" % scene.pov_radio_count)
file.write("\t\terror_bound %.4g\n" % scene.pov_radio_error_bound)
file.write("\t\tgray_threshold %.4g\n" % scene.pov_radio_gray_threshold)
file.write("\t\tlow_error_factor %.4g\n" % scene.pov_radio_low_error_factor)
file.write("\t\tminimum_reuse %.4g\n" % scene.pov_radio_minimum_reuse)
file.write("\t\tnearest_count %d\n" % scene.pov_radio_nearest_count)
file.write("\t\tnormal %d\n" % scene.pov_radio_normal)
file.write("\t\trecursion_limit %d\n" % scene.pov_radio_recursion_limit)
file.write('\t}\n')
file.write('}\n')
exportCamera()
#exportMaterials()
sel = scene.objects
lamps = [l for l in sel if l.type == 'LAMP']
exportLamps(lamps)
exportMeshs(sel)
exportWorld(scene.world)
exportGlobalSettings(scene)
file.close()
def write_pov_ini(filename_ini, filename_pov, filename_image):
scene = bpy.data.scenes[0]
render = scene.render_data
x= int(render.resolution_x*render.resolution_percentage*0.01)
y= int(render.resolution_y*render.resolution_percentage*0.01)
file = open(filename_ini, 'w')
file.write('Input_File_Name="%s"\n' % filename_pov)
file.write('Output_File_Name="%s"\n' % filename_image)
file.write('Width=%d\n' % x)
file.write('Height=%d\n' % y)
# Needed for border render.
'''
file.write('Start_Column=%d\n' % part.x)
file.write('End_Column=%d\n' % (part.x+part.w))
file.write('Start_Row=%d\n' % (part.y))
file.write('End_Row=%d\n' % (part.y+part.h))
'''
file.write('Display=0\n')
file.write('Pause_When_Done=0\n')
file.write('Output_File_Type=C\n') # TGA, best progressive loading
file.write('Output_Alpha=1\n')
if render.antialiasing:
aa_mapping = {'OVERSAMPLE_5':2, 'OVERSAMPLE_8':3, 'OVERSAMPLE_11':4, 'OVERSAMPLE_16':5} # method 1 assumed
file.write('Antialias=1\n')
file.write('Antialias_Depth=%d\n' % aa_mapping[render.antialiasing_samples])
else:
file.write('Antialias=0\n')
file.close()
class PovrayRender(bpy.types.RenderEngine):
__idname__ = 'POVRAY_RENDER'
__label__ = "Povray"
DELAY = 0.02
def _export(self, scene):
import tempfile
self.temp_file_in = tempfile.mktemp(suffix='.pov')
self.temp_file_out = tempfile.mktemp(suffix='.tga')
self.temp_file_ini = tempfile.mktemp(suffix='.ini')
'''
self.temp_file_in = '/test.pov'
self.temp_file_out = '/test.tga'
self.temp_file_ini = '/test.ini'
'''
def info_callback(txt):
self.update_stats("", "POVRAY: " + txt)
write_pov(self.temp_file_in, scene, info_callback)
def _render(self):
try: os.remove(self.temp_file_out) # so as not to load the old file
except: pass
write_pov_ini(self.temp_file_ini, self.temp_file_in, self.temp_file_out)
print ("***-STARTING-***")
# This works too but means we have to wait until its done
# os.system('povray %s' % self.temp_file_ini)
pov_binary = "povray"
if sys.platform=='win32':
if bitness == 64:
pov_binary = "pvengine64"
else:
pov_binary = "pvengine"
self.process = subprocess.Popen([pov_binary, self.temp_file_ini]) # stdout=subprocess.PIPE, stderr=subprocess.PIPE
print ("***-DONE-***")
def _cleanup(self):
for f in (self.temp_file_in, self.temp_file_ini, self.temp_file_out):
try: os.remove(f)
except: pass
self.update_stats("", "")
def render(self, scene):
self.update_stats("", "POVRAY: Exporting data from Blender")
self._export(scene)
self.update_stats("", "POVRAY: Parsing File")
self._render()
r = scene.render_data
# compute resolution
x= int(r.resolution_x*r.resolution_percentage*0.01)
y= int(r.resolution_y*r.resolution_percentage*0.01)
# Wait for the file to be created
while not os.path.exists(self.temp_file_out):
if self.test_break():
try: self.process.terminate()
except: pass
break
if self.process.poll() != None:
self.update_stats("", "POVRAY: Failed")
break
time.sleep(self.DELAY)
if os.path.exists(self.temp_file_out):
self.update_stats("", "POVRAY: Rendering")
prev_size = -1
def update_image():
result = self.begin_result(0, 0, x, y)
lay = result.layers[0]
# possible the image wont load early on.
try: lay.rect_from_file(self.temp_file_out, 0, 0)
except: pass
self.end_result(result)
# Update while povray renders
while True:
# test if povray exists
if self.process.poll() != None:
update_image();
break
# user exit
if self.test_break():
try: self.process.terminate()
except: pass
break
# Would be nice to redirect the output
# stdout_value, stderr_value = self.process.communicate() # locks
# check if the file updated
new_size = os.path.getsize(self.temp_file_out)
if new_size != prev_size:
update_image()
prev_size = new_size
time.sleep(self.DELAY)
self._cleanup()
bpy.types.register(PovrayRender)
# Use some of the existing buttons.
import buttons_scene
buttons_scene.SCENE_PT_render.COMPAT_ENGINES.add('POVRAY_RENDER')
buttons_scene.SCENE_PT_dimensions.COMPAT_ENGINES.add('POVRAY_RENDER')
buttons_scene.SCENE_PT_antialiasing.COMPAT_ENGINES.add('POVRAY_RENDER')
buttons_scene.SCENE_PT_output.COMPAT_ENGINES.add('POVRAY_RENDER')
del buttons_scene
# Use only a subset of the world panels
import buttons_world
buttons_world.WORLD_PT_preview.COMPAT_ENGINES.add('POVRAY_RENDER')
buttons_world.WORLD_PT_context_world.COMPAT_ENGINES.add('POVRAY_RENDER')
buttons_world.WORLD_PT_world.COMPAT_ENGINES.add('POVRAY_RENDER')
buttons_world.WORLD_PT_mist.COMPAT_ENGINES.add('POVRAY_RENDER')
del buttons_world
# Example of wrapping every class 'as is'
import buttons_material
for member in dir(buttons_material):
subclass = getattr(buttons_material, member)
try: subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
except: pass
del buttons_material
class RenderButtonsPanel(bpy.types.Panel):
__space_type__ = "BUTTONS_WINDOW"
__region_type__ = "WINDOW"
__context__ = "scene"
# COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
def poll(self, context):
rd = context.scene.render_data
return (rd.use_game_engine==False) and (rd.engine in self.COMPAT_ENGINES)
# Radiosity panel, use in the scene for now.
class SCENE_PT_povray_radiosity(RenderButtonsPanel):
__label__ = "Radiosity"
COMPAT_ENGINES = set(['POVRAY_RENDER'])
def draw_header(self, context):
layout = self.layout
scene = context.scene
layout.itemR(scene, "pov_radio_enable", text="")
def draw(self, context):
layout = self.layout
scene = context.scene
rd = scene.render_data
layout.active = scene.pov_radio_enable
split = layout.split()
col = split.column()
col.itemR(scene, "pov_radio_count")
col.itemR(scene, "pov_radio_recursion_limit")
col.itemR(scene, "pov_radio_error_bound")
col.itemR(scene, "pov_radio_display_advanced")
if scene.pov_radio_display_advanced:
col.itemR(scene, "pov_radio_adc_bailout")
col.itemR(scene, "pov_radio_brightness")
col.itemR(scene, "pov_radio_gray_threshold")
col.itemR(scene, "pov_radio_low_error_factor")
col.itemR(scene, "pov_radio_minimum_reuse")
col.itemR(scene, "pov_radio_nearest_count")
col.itemR(scene, "pov_radio_normal")
col.itemR(scene, "pov_radio_always_sample")
bpy.types.register(SCENE_PT_povray_radiosity)
FloatProperty= bpy.types.Scene.FloatProperty
IntProperty= bpy.types.Scene.IntProperty
BoolProperty= bpy.types.Scene.BoolProperty
# Not a real pov option, just to know if we should write
BoolProperty( attr="pov_radio_enable",
name="Enable Radiosity",
description="Enable povrays radiosity calculation.",
default= False)
BoolProperty( attr="pov_radio_display_advanced",
name="Advanced Options",
description="Show advanced options.",
default= False)
# Real pov options
FloatProperty( attr="pov_radio_adc_bailout",
name="ADC Bailout",
description="The adc_bailout for radiosity rays. Use adc_bailout = 0.01 / brightest_ambient_object for good results.",
min=0.0, max=1000.0, soft_min=0.0, soft_max=1.0, default= 0.01)
BoolProperty( attr="pov_radio_always_sample",
name="Always Sample",
description="Only use the data from the pretrace step and not gather any new samples during the final radiosity pass..",
default= True)
FloatProperty( attr="pov_radio_brightness",
name="Brightness",
description="Ammount objects are brightened before being returned upwards to the rest of the system.",
min=0.0, max=1000.0, soft_min=0.0, soft_max=10.0, default= 1.0)
IntProperty( attr="pov_radio_count",
name="Ray Count",
description="number of rays that are sent out whenever a new radiosity value has to be calculated.",
min=1, max=1600, default= 35)
FloatProperty( attr="pov_radio_error_bound",
name="Error Bound",
description="one of the two main speed/quality tuning values, lower values are more accurate.",
min=0.0, max=1000.0, soft_min=0.1, soft_max=10.0, default= 1.8)
FloatProperty( attr="pov_radio_gray_threshold",
name="Gray Threshold",
description="one of the two main speed/quality tuning values, lower values are more accurate.",
min=0.0, max=1.0, default= 0.0)
FloatProperty( attr="pov_radio_low_error_factor",
name="Low Error Factor",
description="If you calculate just enough samples, but no more, you will get an image which has slightly blotchy lighting.",
min=0.0, max=1.0, default= 0.5)
# max_sample - not available yet
FloatProperty( attr="pov_radio_minimum_reuse",
name="Minimum Reuse",
description="Fraction of the screen width which sets the minimum radius of reuse for each sample point (At values higher than 2% expect errors).",
min=0.0, max=1.0, soft_min=0.1, soft_max=0.1, default= 0.015)
IntProperty( attr="pov_radio_nearest_count",
name="Nearest Count",
description="Number of old ambient values blended together to create a new interpolated value.",
min=1, max=20, default= 5)
BoolProperty( attr="pov_radio_normal",
name="Normals",
description="Radiosity estimation can be affected by normals.",
default= False)
IntProperty( attr="pov_radio_recursion_limit",
name="Recursion Limit",
description="how many recursion levels are used to calculate the diffuse inter-reflection.",
min=1, max=20, default= 3)

View File

@@ -130,12 +130,10 @@ def write(filename, scene, ob, \
smooth = f.smooth
# XXX need face normals
"""
if not smooth:
normal = tuple(f.no)
normal = tuple(f.normal)
normal_key = rvec3d(normal)
"""
if faceUV:
uv = active_uv_layer[i]
uv = uv.uv1, uv.uv2, uv.uv3, uv.uv4 # XXX - crufty :/
@@ -149,12 +147,10 @@ def write(filename, scene, ob, \
pf= ply_faces[i]
for j, vidx in enumerate(f_verts):
v = mesh_verts[vidx]
"""
if smooth:
normal= tuple(v.no)
normal= tuple(v.normal)
normal_key = rvec3d(normal)
"""
normal_key = None # XXX
if faceUV:
uvcoord= uv[j][0], 1.0-uv[j][1]

View File

@@ -3,6 +3,7 @@ from bpy.__ops__ import add as op_add
from bpy.__ops__ import remove as op_remove
from bpy.__ops__ import dir as op_dir
from bpy.__ops__ import call as op_call
from bpy.__ops__ import get_rna as op_get_rna
class bpy_ops(object):
'''
@@ -89,13 +90,22 @@ class bpy_ops_submodule_op(object):
self.module = module
self.func = func
def __call__(self, **kw):
def idname(self):
# submod.foo -> SUBMOD_OT_foo
id_name = self.module.upper() + '_OT_' + self.func
# Get the operator from
return op_call(id_name, kw)
return self.module.upper() + '_OT_' + self.func
def __call__(self, **kw):
# Get the operator from blender
return op_call(self.idname(), kw)
def get_rna(self):
'''
currently only used for '__rna__'
'''
return op_get_rna(self.idname())
def __repr__(self):
return "<function bpy.ops.%s.%s at 0x%x'>" % (self.module, self.func, id(self))

View File

@@ -7,10 +7,9 @@ class DataButtonsPanel(bpy.types.Panel):
__context__ = "data"
def poll(self, context):
return (context.armature != None)
return (context.armature)
class DATA_PT_context_arm(DataButtonsPanel):
__idname__ = "DATA_PT_context_arm"
__show_header__ = False
def draw(self, context):
@@ -30,7 +29,6 @@ class DATA_PT_context_arm(DataButtonsPanel):
split.itemS()
class DATA_PT_skeleton(DataButtonsPanel):
__idname__ = "DATA_PT_skeleton"
__label__ = "Skeleton"
def draw(self, context):
@@ -40,47 +38,42 @@ class DATA_PT_skeleton(DataButtonsPanel):
arm = context.armature
space = context.space_data
split = layout.split()
if arm:
split = layout.split()
col = split.column()
col.itemR(arm, "rest_position")
sub = col.column()
sub.itemL(text="Deform:")
sub.itemR(arm, "deform_vertexgroups", text="Vertes Groups")
sub.itemR(arm, "deform_envelope", text="Envelopes")
sub.itemR(arm, "deform_quaternion", text="Quaternion")
sub.itemR(arm, "deform_bbone_rest", text="B-Bones Rest")
#sub.itemR(arm, "x_axis_mirror")
#sub.itemR(arm, "auto_ik")
col = split.column()
col.itemR(arm, "rest_position")
col.itemL(text="Deform:")
col.itemR(arm, "deform_vertexgroups", text="Vertes Groups")
col.itemR(arm, "deform_envelope", text="Envelopes")
col.itemR(arm, "deform_quaternion", text="Quaternion")
col.itemR(arm, "deform_bbone_rest", text="B-Bones Rest")
#col.itemR(arm, "x_axis_mirror")
#col.itemR(arm, "auto_ik")
sub = split.column()
sub.itemL(text="Layers:")
sub.template_layers(arm, "layer")
sub.itemL(text="Protected Layers:")
sub.template_layers(arm, "layer_protection")
col = split.column()
col.itemL(text="Layers:")
col.template_layers(arm, "layer")
col.itemL(text="Protected Layers:")
col.template_layers(arm, "layer_protection")
class DATA_PT_display(DataButtonsPanel):
__idname__ = "DATA_PT_display"
__label__ = "Display"
def draw(self, context):
layout = self.layout
arm = context.armature
layout.row().itemR(arm, "drawtype", expand=True)
sub = layout.column_flow()
sub.itemR(arm, "draw_names", text="Names")
sub.itemR(arm, "draw_axes", text="Axes")
sub.itemR(arm, "draw_custom_bone_shapes", text="Shapes")
sub.itemR(arm, "draw_group_colors", text="Colors")
sub.itemR(arm, "delay_deform", text="Delay Refresh")
flow = layout.column_flow()
flow.itemR(arm, "draw_names", text="Names")
flow.itemR(arm, "draw_axes", text="Axes")
flow.itemR(arm, "draw_custom_bone_shapes", text="Shapes")
flow.itemR(arm, "draw_group_colors", text="Colors")
flow.itemR(arm, "delay_deform", text="Delay Refresh")
class DATA_PT_bone_groups(DataButtonsPanel):
__idname__ = "DATA_PT_bone_groups"
__label__ = "Bone Groups"
def poll(self, context):
@@ -88,28 +81,32 @@ class DATA_PT_bone_groups(DataButtonsPanel):
def draw(self, context):
layout = self.layout
ob = context.object
pose= ob.pose
row = layout.row()
row.template_list(pose, "bone_groups", pose, "active_bone_group_index")
col = row.column(align=True)
col.active = (ob.proxy == None)
col.itemO("pose.group_add", icon="ICON_ZOOMIN", text="")
col.itemO("pose.group_remove", icon="ICON_ZOOMOUT", text="")
group = pose.active_bone_group
if group:
col = layout.column()
col.active= (ob.proxy == None)
col.itemR(group, "name")
split = layout.split(0.5)
split.active= (ob.proxy == None)
split.itemR(group, "color_set")
if group.color_set:
split.template_triColorSet(group, "colors")
row = layout.row(align=True)
row.active = (ob.proxy == None)
row.itemO("pose.group_assign", text="Assign")
row.itemO("pose.group_remove", text="Remove") #row.itemO("pose.bone_group_remove_from", text="Remove")
@@ -117,58 +114,59 @@ class DATA_PT_bone_groups(DataButtonsPanel):
#row.itemO("object.bone_group_deselect", text="Deselect")
class DATA_PT_paths(DataButtonsPanel):
__idname__ = "DATA_PT_paths"
__label__ = "Paths"
def draw(self, context):
layout = self.layout
arm = context.armature
split = layout.split()
sub = split.column()
sub.itemR(arm, "paths_show_around_current_frame", text="Around Frame")
col = sub.column(align=True)
if (arm.paths_show_around_current_frame):
col.itemR(arm, "path_before_current", text="Before")
col.itemR(arm, "path_after_current", text="After")
else:
col.itemR(arm, "path_start_frame", text="Start")
col.itemR(arm, "path_end_frame", text="End")
col.itemR(arm, "path_size", text="Step")
sub.itemR(arm, "paths_calculate_head_positions", text="Head")
col = split.column()
col.itemR(arm, "paths_show_around_current_frame", text="Around Frame")
sub = split.column()
sub.itemL(text="Show:")
sub.itemR(arm, "paths_show_frame_numbers", text="Frame Numbers")
sub.itemR(arm, "paths_highlight_keyframes", text="Keyframes")
sub.itemR(arm, "paths_show_keyframe_numbers", text="Keyframe Numbers")
sub = col.column(align=True)
if (arm.paths_show_around_current_frame):
sub.itemR(arm, "path_before_current", text="Before")
sub.itemR(arm, "path_after_current", text="After")
else:
sub.itemR(arm, "path_start_frame", text="Start")
sub.itemR(arm, "path_end_frame", text="End")
sub.itemR(arm, "path_size", text="Step")
col.itemR(arm, "paths_calculate_head_positions", text="Head")
col = split.column()
col.itemL(text="Show:")
col.itemR(arm, "paths_show_frame_numbers", text="Frame Numbers")
col.itemR(arm, "paths_highlight_keyframes", text="Keyframes")
col.itemR(arm, "paths_show_keyframe_numbers", text="Keyframe Numbers")
class DATA_PT_ghost(DataButtonsPanel):
__idname__ = "DATA_PT_ghost"
__label__ = "Ghost"
def draw(self, context):
layout = self.layout
arm = context.armature
split = layout.split()
sub = split.column()
sub.itemR(arm, "ghost_type", text="Scope")
col = split.column()
col.itemR(arm, "ghost_type", text="Scope")
col = sub.column(align=True)
sub = col.column(align=True)
if arm.ghost_type == 'RANGE':
col.itemR(arm, "ghost_start_frame", text="Start")
col.itemR(arm, "ghost_end_frame", text="End")
col.itemR(arm, "ghost_size", text="Step")
sub.itemR(arm, "ghost_start_frame", text="Start")
sub.itemR(arm, "ghost_end_frame", text="End")
sub.itemR(arm, "ghost_size", text="Step")
elif arm.ghost_type == 'CURRENT_FRAME':
col.itemR(arm, "ghost_step", text="Range")
col.itemR(arm, "ghost_size", text="Step")
sub.itemR(arm, "ghost_step", text="Range")
sub.itemR(arm, "ghost_size", text="Step")
sub = split.column()
sub.itemR(arm, "ghost_only_selected", text="Selected Only")
col = split.column()
col.itemR(arm, "ghost_only_selected", text="Selected Only")
bpy.types.register(DATA_PT_context_arm)
bpy.types.register(DATA_PT_skeleton)

View File

@@ -10,11 +10,11 @@ class BoneButtonsPanel(bpy.types.Panel):
return (context.bone or context.edit_bone)
class BONE_PT_context_bone(BoneButtonsPanel):
__idname__ = "BONE_PT_context_bone"
__show_header__ = False
def draw(self, context):
layout = self.layout
bone = context.bone
if not bone:
bone = context.edit_bone
@@ -24,14 +24,13 @@ class BONE_PT_context_bone(BoneButtonsPanel):
row.itemR(bone, "name", text="")
class BONE_PT_transform(BoneButtonsPanel):
__idname__ = "BONE_PT_transform"
__label__ = "Transform"
def draw(self, context):
layout = self.layout
ob = context.object
bone = context.bone
if not bone:
bone = context.edit_bone
@@ -45,7 +44,7 @@ class BONE_PT_transform(BoneButtonsPanel):
sub.itemR(bone, "roll", text="")
sub.itemL()
sub.itemR(bone, "locked")
sub.itemS()
else:
pchan = ob.pose.pose_channels[context.bone.name]
@@ -70,12 +69,11 @@ class BONE_PT_transform(BoneButtonsPanel):
col.row().itemR(pchan, "euler_rotation", text="")
class BONE_PT_bone(BoneButtonsPanel):
__idname__ = "BONE_PT_bone"
__label__ = "Bone"
def draw(self, context):
layout = self.layout
bone = context.bone
arm = context.armature
if not bone:
@@ -83,31 +81,29 @@ class BONE_PT_bone(BoneButtonsPanel):
split = layout.split()
sub = split.column()
sub.itemL(text="Parent:")
col = split.column()
col.itemL(text="Parent:")
if context.bone:
sub.itemR(bone, "parent", text="")
col.itemR(bone, "parent", text="")
else:
sub.item_pointerR(bone, "parent", arm, "edit_bones", text="")
row = sub.row()
row.itemR(bone, "connected")
col.item_pointerR(bone, "parent", arm, "edit_bones", text="")
row = col.row()
row.active = bone.parent != None
row.itemR(bone, "connected")
sub.itemL(text="Layers:")
sub.template_layers(bone, "layer")
col.itemL(text="Layers:")
col.template_layers(bone, "layer")
sub = split.column()
sub.itemL(text="Inherit:")
sub.itemR(bone, "hinge", text="Rotation")
sub.itemR(bone, "inherit_scale", text="Scale")
sub.itemL(text="Display:")
sub.itemR(bone, "draw_wire", text="Wireframe")
sub.itemR(bone, "hidden", text="Hide")
col = split.column()
col.itemL(text="Inherit:")
col.itemR(bone, "hinge", text="Rotation")
col.itemR(bone, "inherit_scale", text="Scale")
col.itemL(text="Display:")
col.itemR(bone, "draw_wire", text="Wireframe")
col.itemR(bone, "hidden", text="Hide")
class BONE_PT_inverse_kinematics(BoneButtonsPanel):
__idname__ = "BONE_PT_inverse_kinematics"
__label__ = "Inverse Kinematics"
__default_closed__ = True
@@ -123,6 +119,7 @@ class BONE_PT_inverse_kinematics(BoneButtonsPanel):
def draw(self, context):
layout = self.layout
ob = context.object
bone = context.bone
pchan = ob.pose.pose_channels[context.bone.name]
@@ -177,12 +174,12 @@ class BONE_PT_inverse_kinematics(BoneButtonsPanel):
split.itemL()
class BONE_PT_deform(BoneButtonsPanel):
__idname__ = "BONE_PT_deform"
__label__ = "Deform"
__default_closed__ = True
def draw_header(self, context):
layout = self.layout
bone = context.bone
if not bone:
bone = context.edit_bone
@@ -191,6 +188,7 @@ class BONE_PT_deform(BoneButtonsPanel):
def draw(self, context):
layout = self.layout
bone = context.bone
if not bone:
bone = context.edit_bone
@@ -201,6 +199,7 @@ class BONE_PT_deform(BoneButtonsPanel):
col = split.column()
col.itemL(text="Envelope:")
sub = col.column(align=True)
sub.itemR(bone, "envelope_distance", text="Distance")
sub.itemR(bone, "envelope_weight", text="Weight")
@@ -213,6 +212,7 @@ class BONE_PT_deform(BoneButtonsPanel):
col = split.column()
col.itemL(text="Curved Bones:")
sub = col.column(align=True)
sub.itemR(bone, "bbone_segments", text="Segments")
sub.itemR(bone, "bbone_in", text="Ease In")
@@ -226,4 +226,3 @@ bpy.types.register(BONE_PT_transform)
bpy.types.register(BONE_PT_bone)
bpy.types.register(BONE_PT_deform)
bpy.types.register(BONE_PT_inverse_kinematics)

View File

@@ -7,10 +7,9 @@ class DataButtonsPanel(bpy.types.Panel):
__context__ = "data"
def poll(self, context):
return (context.camera != None)
return (context.camera)
class DATA_PT_context_camera(DataButtonsPanel):
__idname__ = "DATA_PT_context_camera"
__show_header__ = False
def draw(self, context):
@@ -30,7 +29,6 @@ class DATA_PT_context_camera(DataButtonsPanel):
split.itemS()
class DATA_PT_camera(DataButtonsPanel):
__idname__ = "DATA_PT_camera"
__label__ = "Lens"
def draw(self, context):
@@ -51,54 +49,49 @@ class DATA_PT_camera(DataButtonsPanel):
elif cam.type == 'ORTHO':
row.itemR(cam, "ortho_scale")
split = layout.split()
split.itemR(cam, "panorama");
split.itemL()
layout.itemR(cam, "panorama");
split = layout.split()
sub = split.column(align=True)
sub.itemL(text="Shift:")
sub.itemR(cam, "shift_x", text="X")
sub.itemR(cam, "shift_y", text="Y")
col = split.column(align=True)
col.itemL(text="Shift:")
col.itemR(cam, "shift_x", text="X")
col.itemR(cam, "shift_y", text="Y")
sub = split.column(align=True)
sub.itemL(text="Clipping:")
sub.itemR(cam, "clip_start", text="Start")
sub.itemR(cam, "clip_end", text="End")
col = split.column(align=True)
col.itemL(text="Clipping:")
col.itemR(cam, "clip_start", text="Start")
col.itemR(cam, "clip_end", text="End")
split = layout.split()
col = split.column()
col.itemL(text="Depth of Field:")
col.itemR(cam, "dof_object", text="")
col = split.column()
col.itemL()
col.itemR(cam, "dof_distance", text="Distance")
layout.itemL(text="Depth of Field:")
row = layout.row()
row.itemR(cam, "dof_object", text="")
row.itemR(cam, "dof_distance", text="Distance")
class DATA_PT_camera_display(DataButtonsPanel):
__idname__ = "DATA_PT_camera_display"
__label__ = "Display"
def draw(self, context):
cam = context.camera
layout = self.layout
cam = context.camera
split = layout.split()
sub = split.column()
sub.itemR(cam, "show_limits", text="Limits")
sub.itemR(cam, "show_mist", text="Mist")
sub.itemR(cam, "show_title_safe", text="Title Safe")
sub.itemR(cam, "show_name", text="Name")
col = split.column()
col.itemR(cam, "show_limits", text="Limits")
col.itemR(cam, "show_mist", text="Mist")
col.itemR(cam, "show_title_safe", text="Title Safe")
col.itemR(cam, "show_name", text="Name")
col = split.column()
col.itemR(cam, "show_passepartout", text="Passepartout")
colsub = col.column()
colsub.active = cam.show_passepartout
colsub.itemR(cam, "passepartout_alpha", text="Alpha", slider=True)
sub = col.column()
sub.active = cam.show_passepartout
sub.itemR(cam, "passepartout_alpha", text="Alpha", slider=True)
col.itemR(cam, "draw_size", text="Size")
bpy.types.register(DATA_PT_context_camera)
bpy.types.register(DATA_PT_camera)
bpy.types.register(DATA_PT_camera_display)

View File

@@ -10,7 +10,6 @@ class DataButtonsPanel(bpy.types.Panel):
return (context.object and context.object.type == 'CURVE' and context.curve)
class DATA_PT_context_curve(DataButtonsPanel):
__idname__ = "DATA_PT_context_curve"
__show_header__ = False
def draw(self, context):
@@ -29,9 +28,7 @@ class DATA_PT_context_curve(DataButtonsPanel):
split.template_ID(space, "pin_id")
split.itemS()
class DATA_PT_shape_curve(DataButtonsPanel):
__idname__ = "DATA_PT_shape_curve"
__label__ = "Shape"
def draw(self, context):
@@ -70,11 +67,11 @@ class DATA_PT_shape_curve(DataButtonsPanel):
# sub.itemR(curve, "vertex_normal_flip")
class DATA_PT_geometry_curve(DataButtonsPanel):
__idname__ = "DATA_PT_geometry_curve"
__label__ = "Geometry "
def draw(self, context):
layout = self.layout
curve = context.curve
split = layout.split()
@@ -92,66 +89,67 @@ class DATA_PT_geometry_curve(DataButtonsPanel):
sub.itemR(curve, "bevel_object", icon="ICON_OUTLINER_OB_CURVE")
class DATA_PT_pathanim(DataButtonsPanel):
__idname__ = "DATA_PT_pathanim"
__label__ = "Path Animation"
def draw_header(self, context):
layout = self.layout
curve = context.curve
layout.itemR(curve, "path", text="")
def draw(self, context):
curve = context.curve
layout = self.layout
curve = context.curve
layout.active = curve.path
split = layout.split()
sub = split.column()
sub.itemR(curve, "path_length", text="Frames")
sub.itemR(curve, "follow")
col = split.column()
col.itemR(curve, "path_length", text="Frames")
col.itemR(curve, "follow")
sub = split.column()
sub.itemR(curve, "stretch")
sub.itemR(curve, "offset_path_distance", text="Offset Children")
col = split.column()
col.itemR(curve, "stretch")
col.itemR(curve, "offset_path_distance", text="Offset Children")
class DATA_PT_current_curve(DataButtonsPanel):
__idname__ = "DATA_PT_current_curve"
__label__ = "Current Curve"
def draw(self, context):
layout = self.layout
currentcurve = context.curve.curves[0] # XXX
split = layout.split()
sub = split.column()
sub.itemL(text="Cyclic:")
sub.itemR(currentcurve, "cyclic_u", text="U")
sub.itemR(currentcurve, "cyclic_v", text="V")
sub.itemL(text="Order:")
sub.itemR(currentcurve, "order_u", text="U")
sub.itemR(currentcurve, "order_v", text="V")
sub.itemL(text="Endpoints:")
sub.itemR(currentcurve, "endpoint_u", text="U")
sub.itemR(currentcurve, "endpoint_v", text="V")
col = split.column()
col.itemL(text="Cyclic:")
col.itemR(currentcurve, "cyclic_u", text="U")
col.itemR(currentcurve, "cyclic_v", text="V")
col.itemL(text="Order:")
col.itemR(currentcurve, "order_u", text="U")
col.itemR(currentcurve, "order_v", text="V")
col.itemL(text="Endpoints:")
col.itemR(currentcurve, "endpoint_u", text="U")
col.itemR(currentcurve, "endpoint_v", text="V")
sub = split.column()
sub.itemL(text="Bezier:")
sub.itemR(currentcurve, "bezier_u", text="U")
sub.itemR(currentcurve, "bezier_v", text="V")
sub.itemL(text="Resolution:")
sub.itemR(currentcurve, "resolution_u", text="U")
sub.itemR(currentcurve, "resolution_v", text="V")
sub.itemL(text="Interpolation:")
sub.itemR(currentcurve, "tilt_interpolation", text="Tilt")
sub.itemR(currentcurve, "radius_interpolation", text="Tilt")
sub.itemR(currentcurve, "smooth")
col = split.column()
col.itemL(text="Bezier:")
col.itemR(currentcurve, "bezier_u", text="U")
col.itemR(currentcurve, "bezier_v", text="V")
col.itemL(text="Resolution:")
col.itemR(currentcurve, "resolution_u", text="U")
col.itemR(currentcurve, "resolution_v", text="V")
col.itemL(text="Interpolation:")
col.itemR(currentcurve, "tilt_interpolation", text="Tilt")
col.itemR(currentcurve, "radius_interpolation", text="Tilt")
col.itemR(currentcurve, "smooth")
bpy.types.register(DATA_PT_context_curve)
bpy.types.register(DATA_PT_shape_curve)
bpy.types.register(DATA_PT_geometry_curve)
bpy.types.register(DATA_PT_pathanim)
bpy.types.register(DATA_PT_current_curve)

View File

@@ -10,11 +10,11 @@ class DataButtonsPanel(bpy.types.Panel):
return (context.object and context.object.type == 'EMPTY')
class DATA_PT_empty(DataButtonsPanel):
__idname__ = "DATA_PT_empty"
__label__ = "Empty"
def draw(self, context):
layout = self.layout
ob = context.object
layout.itemR(ob, "empty_draw_type")

View File

@@ -7,20 +7,17 @@ class DataButtonsPanel(bpy.types.Panel):
__context__ = "data"
def poll(self, context):
return (context.lamp != None)
return (context.lamp)
class DATA_PT_preview(DataButtonsPanel):
__idname__= "DATA_PT_preview"
__label__ = "Preview"
def draw(self, context):
layout = self.layout
lamp = context.lamp
layout.template_preview(lamp)
layout.template_preview(context.lamp)
class DATA_PT_context_lamp(DataButtonsPanel):
__idname__ = "DATA_PT_context_lamp"
__show_header__ = False
def draw(self, context):
@@ -40,7 +37,6 @@ class DATA_PT_context_lamp(DataButtonsPanel):
split.itemS()
class DATA_PT_lamp(DataButtonsPanel):
__idname__ = "DATA_PT_lamp"
__label__ = "Lamp"
def draw(self, context):
@@ -51,60 +47,37 @@ class DATA_PT_lamp(DataButtonsPanel):
layout.itemR(lamp, "type", expand=True)
split = layout.split()
col = split.column()
#col.itemL(text="Type:")
#col.itemR(lamp, "type", text="")
colsub = col.column()
colsub.itemR(lamp, "color", text="")
colsub.itemR(lamp, "energy")
col.itemR(lamp, "negative")
#col.itemR(lamp, "distance")
sub = split.column()
#sub.itemL(text="Influence:")
sub.itemR(lamp, "layer", text="This Layer Only")
sub.itemR(lamp, "specular")
sub.itemR(lamp, "diffuse")
#sub.itemR(lamp, "negative")
sub = col.column()
sub.itemR(lamp, "color", text="")
sub.itemR(lamp, "energy")
if lamp.type in ('POINT', 'SPOT'):
split = layout.split()
col = split.column()
col.itemL(text="Falloff:")
col = col.column(align=True)
col.itemR(lamp, "falloff_type", text="")
col.itemR(lamp, "distance")
col.itemR(lamp, "sphere")
if lamp.falloff_type != 'LINEAR_QUADRATIC_WEIGHTED':
col = split.column()
else:
sub = split.column()
sub.itemL(text="Attenuation Distance:")
sub = sub.column(align=True)
sub.itemL(text="Falloff:")
sub.itemR(lamp, "falloff_type", text="")
sub.itemR(lamp, "distance")
if lamp.falloff_type == 'LINEAR_QUADRATIC_WEIGHTED':
col.itemL(text="Attenuation Factors:")
sub = col.column(align=True)
sub.itemR(lamp, "linear_attenuation", slider=True, text="Linear")
sub.itemR(lamp, "quadratic_attenuation", slider=True, text="Quadratic")
if lamp.type == 'AREA':
split = layout.split()
col = split.column()
col.itemL(text="Shape:")
col = col.column(align=True)
col.itemR(lamp, "shape", text="")
if (lamp.shape == 'SQUARE'):
col.itemR(lamp, "size")
if (lamp.shape == 'RECTANGLE'):
col.itemR(lamp, "size", text="Size X")
col.itemR(lamp, "size_y", text="Size Y")
col.itemR(lamp, "sphere")
sub = split.column()
sub.itemL(text="Gamma:")
sub.itemR(lamp, "gamma", text="Value")
if lamp.type == 'AREA':
col.itemR(lamp, "distance")
col.itemR(lamp, "gamma")
col = split.column()
col.itemR(lamp, "negative")
col.itemR(lamp, "layer", text="This Layer Only")
col.itemR(lamp, "specular")
col.itemR(lamp, "diffuse")
class DATA_PT_sunsky(DataButtonsPanel):
__idname__ = "DATA_PT_sunsky"
__label__ = "Sun/Sky"
def poll(self, context):
@@ -113,6 +86,7 @@ class DATA_PT_sunsky(DataButtonsPanel):
def draw(self, context):
layout = self.layout
lamp = context.lamp.sky
row = layout.row()
@@ -128,30 +102,29 @@ class DATA_PT_sunsky(DataButtonsPanel):
col = split.column()
col.active = lamp.sky
col.itemL(text="Blend Mode:")
colsub = col.column(align=True)
colsub.itemR(lamp, "sky_blend_type", text="")
colsub.itemR(lamp, "sky_blend", text="Factor")
sub = col.column(align=True)
sub.itemR(lamp, "sky_blend_type", text="")
sub.itemR(lamp, "sky_blend", text="Factor")
col.itemL(text="Color Space:")
colsub = col.column(align=True)
colsub.itemR(lamp, "sky_color_space", text="")
colsub.itemR(lamp, "sky_exposure", text="Exposure")
sub = col.column(align=True)
sub.itemR(lamp, "sky_color_space", text="")
sub.itemR(lamp, "sky_exposure", text="Exposure")
col = split.column()
col.active = lamp.sky
col.itemL(text="Horizon:")
colsub = col.column(align=True)
colsub.itemR(lamp, "horizon_brightness", text="Brightness")
colsub.itemR(lamp, "spread", text="Spread")
sub = col.column(align=True)
sub.itemR(lamp, "horizon_brightness", text="Brightness")
sub.itemR(lamp, "spread", text="Spread")
col.itemL(text="Sun:")
colsub = col.column(align=True)
colsub.itemR(lamp, "sun_brightness", text="Brightness")
colsub.itemR(lamp, "sun_size", text="Size")
colsub.itemR(lamp, "backscattered_light", slider=True,text="Back Light")
sub = col.column(align=True)
sub.itemR(lamp, "sun_brightness", text="Brightness")
sub.itemR(lamp, "sun_size", text="Size")
sub.itemR(lamp, "backscattered_light", slider=True,text="Back Light")
row = layout.row()
row.itemS()
layout.itemS()
split = layout.split()
@@ -170,7 +143,6 @@ class DATA_PT_sunsky(DataButtonsPanel):
sub.itemR(lamp, "atmosphere_extinction", slider=True ,text="Extinction")
class DATA_PT_shadow(DataButtonsPanel):
__idname__ = "DATA_PT_shadow"
__label__ = "Shadow"
def poll(self, context):
@@ -179,92 +151,121 @@ class DATA_PT_shadow(DataButtonsPanel):
def draw(self, context):
layout = self.layout
lamp = context.lamp
layout.itemR(lamp, "shadow_method", expand=True)
if lamp.shadow_method != 'NOSHADOW':
split = layout.split()
col = split.column()
col.itemR(lamp, "shadow_color", text="")
sub = split.column()
sub.itemR(lamp, "shadow_layer", text="This Layer Only")
sub.itemR(lamp, "only_shadow")
col = split.column()
col.itemR(lamp, "shadow_layer", text="This Layer Only")
col.itemR(lamp, "only_shadow")
if lamp.shadow_method == 'RAY_SHADOW':
col = layout.column()
col.itemL(text="Sampling:")
col.row().itemR(lamp, "shadow_ray_sampling_method", expand=True)
if lamp.type in ('POINT', 'SUN', 'SPOT'):
split = layout.split()
col = split.column(align=True)
col = split.column()
col.itemR(lamp, "shadow_soft_size", text="Soft Size")
col = split.column(align=True)
col.itemR(lamp, "shadow_ray_samples", text="Samples")
if lamp.shadow_ray_sampling_method == 'ADAPTIVE_QMC':
col.itemR(lamp, "shadow_adaptive_threshold", text="Threshold")
if lamp.type == 'AREA':
split = layout.split()
col = split.column()
if lamp.shadow_ray_sampling_method == 'CONSTANT_JITTERED':
col.itemR(lamp, "umbra")
col.itemR(lamp, "dither")
col.itemR(lamp, "jitter")
else:
col.itemL()
col = split.column(align=True)
col.itemR(lamp, "shadow_ray_samples_x", text="Samples")
elif lamp.type == 'AREA':
split = layout.split()
col = split.column()
sub = split.column(align=True)
if lamp.shape == 'SQUARE':
col.itemR(lamp, "shadow_ray_samples_x", text="Samples")
elif lamp.shape == 'RECTANGLE':
col.itemR(lamp, "shadow_ray_samples_x", text="Samples X")
col.itemR(lamp, "shadow_ray_samples_y", text="Samples Y")
if lamp.shadow_ray_sampling_method == 'ADAPTIVE_QMC':
col.itemR(lamp, "shadow_adaptive_threshold", text="Threshold")
elif lamp.shadow_ray_sampling_method == 'CONSTANT_JITTERED':
sub.itemR(lamp, "umbra")
sub.itemR(lamp, "dither")
sub.itemR(lamp, "jitter")
if lamp.shadow_method == 'BUFFER_SHADOW':
col = layout.column()
col.itemL(text="Buffer Type:")
col.row().itemR(lamp, "shadow_buffer_type", expand=True)
if lamp.shadow_buffer_type in ('REGULAR', 'HALFWAY'):
split = layout.split()
col = split.column()
col.itemL(text="Filter Type:")
col.itemR(lamp, "shadow_filter_type", text="")
colsub = col.column(align=True)
colsub.itemR(lamp, "shadow_buffer_soft", text="Soft")
colsub.itemR(lamp, "shadow_buffer_bias", text="Bias")
sub = col.column(align=True)
sub.itemR(lamp, "shadow_buffer_soft", text="Soft")
sub.itemR(lamp, "shadow_buffer_bias", text="Bias")
col = split.column()
col.itemL(text="Sample Buffers:")
col.itemR(lamp, "shadow_sample_buffers", text="")
sub = col.column(align=True)
sub.itemR(lamp, "shadow_buffer_size", text="Size")
sub.itemR(lamp, "shadow_buffer_samples", text="Samples")
colsub = col.column(align=True)
colsub.itemR(lamp, "shadow_buffer_size", text="Size")
colsub.itemR(lamp, "shadow_buffer_samples", text="Samples")
if (lamp.shadow_buffer_type == 'IRREGULAR'):
row = layout.row()
row.itemR(lamp, "shadow_buffer_bias", text="Bias")
elif lamp.shadow_buffer_type == 'IRREGULAR':
layout.itemR(lamp, "shadow_buffer_bias", text="Bias")
row = layout.row()
row.itemR(lamp, "auto_clip_start", text="Autoclip Start")
if not (lamp.auto_clip_start):
row.itemR(lamp, "shadow_buffer_clip_start", text="Clip Start")
sub = row.row()
sub.active = not lamp.auto_clip_start
sub.itemR(lamp, "shadow_buffer_clip_start", text="Clip Start")
row = layout.row()
row.itemR(lamp, "auto_clip_end", text="Autoclip End")
if not (lamp.auto_clip_end):
row.itemR(lamp, "shadow_buffer_clip_end", text=" Clip End")
sub = row.row()
sub.active = not lamp.auto_clip_end
sub.itemR(lamp, "shadow_buffer_clip_end", text=" Clip End")
class DATA_PT_area(DataButtonsPanel):
__label__ = "Area Shape"
def poll(self, context):
lamp = context.lamp
return (lamp and lamp.type == 'AREA')
def draw(self, context):
layout = self.layout
lamp = context.lamp
split = layout.split()
col = split.column()
col.itemR(lamp, "shape", text="")
sub = col.column(align=True)
if (lamp.shape == 'SQUARE'):
sub.itemR(lamp, "size")
elif (lamp.shape == 'RECTANGLE'):
sub.itemR(lamp, "size", text="Size X")
sub.itemR(lamp, "size_y", text="Size Y")
col = split.column()
class DATA_PT_spot(DataButtonsPanel):
__idname__ = "DATA_PT_spot"
__label__ = "Spot"
__label__ = "Spot Shape"
def poll(self, context):
lamp = context.lamp
@@ -272,9 +273,11 @@ class DATA_PT_spot(DataButtonsPanel):
def draw(self, context):
layout = self.layout
lamp = context.lamp
split = layout.split()
col = split.column()
sub = col.column(align=True)
sub.itemR(lamp, "spot_size", text="Size")
@@ -283,14 +286,13 @@ class DATA_PT_spot(DataButtonsPanel):
col = split.column()
col.itemR(lamp, "halo")
colsub = col.column(align=True)
colsub.active = lamp.halo
colsub.itemR(lamp, "halo_intensity", text="Intensity")
sub = col.column(align=True)
sub.active = lamp.halo
sub.itemR(lamp, "halo_intensity", text="Intensity")
if lamp.shadow_method == 'BUFFER_SHADOW':
colsub.itemR(lamp, "halo_step", text="Step")
sub.itemR(lamp, "halo_step", text="Step")
class DATA_PT_falloff_curve(DataButtonsPanel):
__idname__ = "DATA_PT_falloff_curve"
__label__ = "Falloff Curve"
__default_closed__ = True
@@ -305,6 +307,7 @@ class DATA_PT_falloff_curve(DataButtonsPanel):
def draw(self, context):
layout = self.layout
lamp = context.lamp
layout.template_curve_mapping(lamp.falloff_curve)
@@ -313,7 +316,7 @@ bpy.types.register(DATA_PT_context_lamp)
bpy.types.register(DATA_PT_preview)
bpy.types.register(DATA_PT_lamp)
bpy.types.register(DATA_PT_falloff_curve)
bpy.types.register(DATA_PT_area)
bpy.types.register(DATA_PT_spot)
bpy.types.register(DATA_PT_shadow)
bpy.types.register(DATA_PT_sunsky)
bpy.types.register(DATA_PT_sunsky)

View File

@@ -10,7 +10,6 @@ class DataButtonsPanel(bpy.types.Panel):
return (context.lattice != None)
class DATA_PT_context_lattice(DataButtonsPanel):
__idname__ = "DATA_PT_context_lattice"
__show_header__ = False
def draw(self, context):
@@ -29,9 +28,7 @@ class DATA_PT_context_lattice(DataButtonsPanel):
split.template_ID(space, "pin_id")
split.itemS()
class DATA_PT_lattice(DataButtonsPanel):
__idname__ = "DATA_PT_lattice"
__label__ = "Lattice"
def draw(self, context):
@@ -57,4 +54,3 @@ class DATA_PT_lattice(DataButtonsPanel):
bpy.types.register(DATA_PT_context_lattice)
bpy.types.register(DATA_PT_lattice)

View File

@@ -10,7 +10,6 @@ class DataButtonsPanel(bpy.types.Panel):
return (context.mesh != None)
class DATA_PT_context_mesh(DataButtonsPanel):
__idname__ = "DATA_PT_context_mesh"
__show_header__ = False
def draw(self, context):
@@ -30,7 +29,6 @@ class DATA_PT_context_mesh(DataButtonsPanel):
split.itemS()
class DATA_PT_normals(DataButtonsPanel):
__idname__ = "DATA_PT_normals"
__label__ = "Normals"
def draw(self, context):
@@ -42,15 +40,15 @@ class DATA_PT_normals(DataButtonsPanel):
col = split.column()
col.itemR(mesh, "autosmooth")
colsub = col.column()
colsub.active = mesh.autosmooth
colsub.itemR(mesh, "autosmooth_angle", text="Angle")
sub = col.column()
sub.active = mesh.autosmooth
sub.itemR(mesh, "autosmooth_angle", text="Angle")
sub = split.column()
sub.itemR(mesh, "vertex_normal_flip")
sub.itemR(mesh, "double_sided")
class DATA_PT_vertex_groups(DataButtonsPanel):
__idname__ = "DATA_PT_vertex_groups"
__label__ = "Vertex Groups"
def poll(self, context):
@@ -58,10 +56,10 @@ class DATA_PT_vertex_groups(DataButtonsPanel):
def draw(self, context):
layout = self.layout
ob = context.object
row = layout.row()
row.template_list(ob, "vertex_groups", ob, "active_vertex_group_index")
col = row.column(align=True)
@@ -88,7 +86,6 @@ class DATA_PT_vertex_groups(DataButtonsPanel):
layout.itemR(context.tool_settings, "vertex_group_weight", text="Weight")
class DATA_PT_shape_keys(DataButtonsPanel):
__idname__ = "DATA_PT_shape_keys"
__label__ = "Shape Keys"
def poll(self, context):
@@ -96,6 +93,7 @@ class DATA_PT_shape_keys(DataButtonsPanel):
def draw(self, context):
layout = self.layout
ob = context.object
key = ob.data.shape_keys
kb = ob.active_shape_key
@@ -139,23 +137,22 @@ class DATA_PT_shape_keys(DataButtonsPanel):
row.itemR(key, "relative")
row.itemR(key, "slurph")
row = layout.row()
row.itemR(kb, "name")
layout.itemR(kb, "name")
if context.edit_object:
layout.enabled = False
class DATA_PT_uv_texture(DataButtonsPanel):
__idname__ = "DATA_PT_uv_texture"
__label__ = "UV Texture"
def draw(self, context):
layout = self.layout
me = context.mesh
row = layout.row()
col = row.column()
col.template_list(me, "uv_textures", me, "active_uv_texture_index", rows=2)
col = row.column(align=True)
@@ -167,11 +164,11 @@ class DATA_PT_uv_texture(DataButtonsPanel):
layout.itemR(lay, "name")
class DATA_PT_vertex_colors(DataButtonsPanel):
__idname__ = "DATA_PT_vertex_colors"
__label__ = "Vertex Colors"
def draw(self, context):
layout = self.layout
me = context.mesh
row = layout.row()
@@ -193,4 +190,3 @@ bpy.types.register(DATA_PT_vertex_groups)
bpy.types.register(DATA_PT_shape_keys)
bpy.types.register(DATA_PT_uv_texture)
bpy.types.register(DATA_PT_vertex_colors)

View File

@@ -0,0 +1,112 @@
import bpy
class DataButtonsPanel(bpy.types.Panel):
__space_type__ = "BUTTONS_WINDOW"
__region_type__ = "WINDOW"
__context__ = "data"
def poll(self, context):
return (context.meta_ball)
class DATA_PT_context_metaball(DataButtonsPanel):
__show_header__ = False
def draw(self, context):
layout = self.layout
ob = context.object
mball = context.meta_ball
space = context.space_data
split = layout.split(percentage=0.65)
if ob:
split.template_ID(ob, "data")
split.itemS()
elif mball:
split.template_ID(space, "pin_id")
split.itemS()
class DATA_PT_metaball(DataButtonsPanel):
__label__ = "Metaball"
def draw(self, context):
layout = self.layout
mball = context.meta_ball
split = layout.split()
col = split.column()
col.itemL(text="Resolution:")
sub = col.column(align=True)
sub.itemR(mball, "wire_size", text="View")
sub.itemR(mball, "render_size", text="Render")
col = split.column()
col.itemL(text="Settings:")
col.itemR(mball, "threshold", text="Threshold")
layout.itemL(text="Update:")
layout.itemR(mball, "flag", expand=True)
class DATA_PT_metaball_element(DataButtonsPanel):
__label__ = "Active Element"
def poll(self, context):
return (context.meta_ball and context.meta_ball.last_selected_element)
def draw(self, context):
layout = self.layout
metaelem = context.meta_ball.last_selected_element
split = layout.split(percentage=0.3)
split.itemL(text="Type:")
split.itemR(metaelem, "type", text="")
split = layout.split()
col = split.column()
col.itemL(text="Settings:")
col.itemR(metaelem, "stiffness", text="Stiffness")
col.itemR(metaelem, "negative", text="Negative")
col.itemR(metaelem, "hide", text="Hide")
if metaelem.type == 'BALL':
col = split.column(align=True)
elif metaelem.type == 'CUBE':
col = split.column(align=True)
col.itemL(text="Size:")
col.itemR(metaelem, "sizex", text="X")
col.itemR(metaelem, "sizey", text="Y")
col.itemR(metaelem, "sizez", text="Z")
elif metaelem.type == 'TUBE':
col = split.column(align=True)
col.itemL(text="Size:")
col.itemR(metaelem, "sizex", text="X")
elif metaelem.type == 'PLANE':
col = split.column(align=True)
col.itemL(text="Size:")
col.itemR(metaelem, "sizex", text="X")
col.itemR(metaelem, "sizey", text="Y")
elif metaelem.type == 'ELLIPSOID':
col = split.column(align=True)
col.itemL(text="Size:")
col.itemR(metaelem, "sizex", text="X")
col.itemR(metaelem, "sizey", text="Y")
col.itemR(metaelem, "sizez", text="Z")
bpy.types.register(DATA_PT_context_metaball)
bpy.types.register(DATA_PT_metaball)
bpy.types.register(DATA_PT_metaball_element)

View File

@@ -7,12 +7,12 @@ class DataButtonsPanel(bpy.types.Panel):
__context__ = "modifier"
class DATA_PT_modifiers(DataButtonsPanel):
__idname__ = "DATA_PT_modifiers"
__label__ = "Modifiers"
def draw(self, context):
ob = context.object
layout = self.layout
ob = context.object
row = layout.row()
row.item_menu_enumO("object.modifier_add", "type")
@@ -70,6 +70,8 @@ class DATA_PT_modifiers(DataButtonsPanel):
self.shrinkwrap(box, ob, md)
elif md.type == 'SIMPLE_DEFORM':
self.simpledeform(box, ob, md)
elif md.type == 'SMOKE':
self.smoke(box, ob, md)
elif md.type == 'SMOOTH':
self.smooth(box, ob, md)
elif md.type == 'SOFTBODY':
@@ -85,9 +87,11 @@ class DATA_PT_modifiers(DataButtonsPanel):
def armature(self, layout, ob, md):
layout.itemR(md, "object")
row = layout.row()
row.item_pointerR(md, "vertex_group", ob, "vertex_groups")
row.itemR(md, "invert")
flow = layout.column_flow()
flow.itemR(md, "use_vertex_groups", text="Vertex Groups")
flow.itemR(md, "use_bone_envelopes", text="Bone Envelopes")
@@ -108,34 +112,31 @@ class DATA_PT_modifiers(DataButtonsPanel):
split = layout.split()
col = split.column()
col = col.column()
col.itemR(md, "constant_offset")
colsub = col.column()
colsub.active = md.constant_offset
colsub.itemR(md, "constant_offset_displacement", text="")
sub = col.column()
sub.active = md.constant_offset
sub.itemR(md, "constant_offset_displacement", text="")
col.itemS()
sub = col.row().itemR(md, "merge_adjacent_vertices", text="Merge")
colsub = col.column()
colsub.active = md.merge_adjacent_vertices
colsub.itemR(md, "merge_end_vertices", text="First Last")
colsub.itemR(md, "merge_distance", text="Distance")
col.itemR(md, "merge_adjacent_vertices", text="Merge")
sub = col.column()
sub.active = md.merge_adjacent_vertices
sub.itemR(md, "merge_end_vertices", text="First Last")
sub.itemR(md, "merge_distance", text="Distance")
col = split.column()
col = col.column()
col.itemR(md, "relative_offset")
colsub = col.column()
colsub.active = md.relative_offset
colsub.itemR(md, "relative_offset_displacement", text="")
sub = col.column()
sub.active = md.relative_offset
sub.itemR(md, "relative_offset_displacement", text="")
col.itemS()
col = col.column()
col.itemR(md, "add_offset_object")
colsub = col.column()
colsub.active = md.add_offset_object
colsub.itemR(md, "offset_object", text="")
sub = col.column()
sub.active = md.add_offset_object
sub.itemR(md, "offset_object", text="")
layout.itemS()
@@ -149,14 +150,11 @@ class DATA_PT_modifiers(DataButtonsPanel):
row.itemR(md, "only_vertices")
layout.itemL(text="Limit Method:")
row = layout.row()
row.itemR(md, "limit_method", expand=True)
layout.row().itemR(md, "limit_method", expand=True)
if md.limit_method == 'ANGLE':
row = layout.row()
row.itemR(md, "angle")
layout.itemR(md, "angle")
elif md.limit_method == 'WEIGHT':
row = layout.row()
row.itemR(md, "edge_weight_method", expand=True)
layout.row().itemR(md, "edge_weight_method", expand=True)
def boolean(self, layout, ob, md):
layout.itemR(md, "operation")
@@ -171,23 +169,27 @@ class DATA_PT_modifiers(DataButtonsPanel):
col = split.column()
col.itemR(md, "randomize")
colsub = col.column()
colsub.active = md.randomize
colsub.itemR(md, "seed")
sub = col.column()
sub.active = md.randomize
sub.itemR(md, "seed")
def cast(self, layout, ob, md):
layout.itemR(md, "cast_type")
col = layout.column_flow()
col.itemR(md, "x")
col.itemR(md, "y")
col.itemR(md, "z")
col.itemR(md, "factor")
col.itemR(md, "radius")
col.itemR(md, "size")
layout.itemR(md, "object")
if md.object:
layout.itemR(md, "use_transform")
flow = layout.column_flow()
flow.itemR(md, "x")
flow.itemR(md, "y")
flow.itemR(md, "z")
flow.itemR(md, "factor")
flow.itemR(md, "radius")
flow.itemR(md, "size")
layout.itemR(md, "from_radius")
layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
#Missing: "OB" and "From Radius"
def cloth(self, layout, ob, md):
layout.itemL(text="See Cloth panel.")
@@ -221,9 +223,10 @@ class DATA_PT_modifiers(DataButtonsPanel):
col = split.column()
col.itemR(md, "use_edge_angle", text="Edge Angle")
colsub = col.column()
colsub.active = md.use_edge_angle
colsub.itemR(md, "split_angle")
sub = col.column()
sub.active = md.use_edge_angle
sub.itemR(md, "split_angle")
col = split.column()
col.itemR(md, "use_sharp", text="Sharp Edges")
@@ -234,7 +237,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
layout.itemR(md, "unborn")
layout.itemR(md, "alive")
layout.itemR(md, "dead")
# Missing: "Refresh" and "Clear Vertex Group" ?
# Missing: "Refresh" and "Clear Vertex Group" Operator
def fluid(self, layout, ob, md):
layout.itemL(text="See Fluid panel.")
@@ -244,7 +247,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
layout.itemR(md, "force", slider=True)
layout.itemR(md, "object")
layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
# Missing: "Reset" and "Recenter"
# Missing: "Reset" and "Recenter" Operator
def lattice(self, layout, ob, md):
layout.itemR(md, "object")
@@ -264,6 +267,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
layout.itemR(md, "invert")
layout.itemS()
layout.itemO("object.modifier_mdef_bind", text="Bind")
row = layout.row()
row.itemR(md, "precision")
@@ -273,17 +277,19 @@ class DATA_PT_modifiers(DataButtonsPanel):
layout.itemR(md, "merge_limit")
split = layout.split()
sub = split.column()
sub.itemR(md, "x")
sub.itemR(md, "y")
sub.itemR(md, "z")
sub = split.column()
sub.itemL(text="Textures:")
sub.itemR(md, "mirror_u")
sub.itemR(md, "mirror_v")
sub = split.column()
sub.itemR(md, "clip", text="Do Clipping")
sub.itemR(md, "mirror_vertex_groups", text="Vertex Group")
col = split.column()
col.itemR(md, "x")
col.itemR(md, "y")
col.itemR(md, "z")
col = split.column()
col.itemL(text="Textures:")
col.itemR(md, "mirror_u")
col.itemR(md, "mirror_v")
col = split.column()
col.itemR(md, "clip", text="Do Clipping")
col.itemR(md, "mirror_vertex_groups", text="Vertex Group")
layout.itemR(md, "mirror_object")
@@ -296,19 +302,19 @@ class DATA_PT_modifiers(DataButtonsPanel):
layout.itemR(md, "object")
layout.itemR(md, "particle_system_number")
col = layout.column_flow()
col.itemR(md, "normal")
col.itemR(md, "children")
col.itemR(md, "size")
col.itemR(md, "path")
flow = layout.column_flow()
flow.itemR(md, "normal")
flow.itemR(md, "children")
flow.itemR(md, "size")
flow.itemR(md, "path")
if md.path:
col.itemR(md, "keep_shape")
col.itemR(md, "unborn")
col.itemR(md, "alive")
col.itemR(md, "dead")
col.itemL(md, "")
flow.itemR(md, "keep_shape")
flow.itemR(md, "unborn")
flow.itemR(md, "alive")
flow.itemR(md, "dead")
flow.itemL(md, "")
if md.path:
col.itemR(md, "axis", text="")
flow.itemR(md, "axis", text="")
if md.path:
row = layout.row()
@@ -333,14 +339,13 @@ class DATA_PT_modifiers(DataButtonsPanel):
row.itemR(md, "y")
row.itemR(md, "z")
col = layout.column_flow()
col.itemR(md, "negative")
col.itemR(md, "positive")
col.itemR(md, "cull_front_faces")
col.itemR(md, "cull_back_faces")
flow = layout.column_flow()
flow.itemR(md, "negative")
flow.itemR(md, "positive")
flow.itemR(md, "cull_front_faces")
flow.itemR(md, "cull_back_faces")
elif md.mode == 'NEAREST_SURFACEPOINT':
layout.itemR(md, "keep_above_surface")
# To-Do: Validate if structs
def simpledeform(self, layout, ob, md):
layout.itemR(md, "mode")
@@ -352,16 +357,44 @@ class DATA_PT_modifiers(DataButtonsPanel):
if md.mode in ('TAPER', 'STRETCH'):
layout.itemR(md, "lock_x_axis")
layout.itemR(md, "lock_y_axis")
def smoke(self, layout, ob, md):
layout.itemR(md, "smoke_type")
if md.smoke_type == 'TYPE_DOMAIN':
layout.itemS()
layout.itemR(md.domain_settings, "maxres")
layout.itemR(md.domain_settings, "color")
layout.itemR(md.domain_settings, "amplify")
layout.itemR(md.domain_settings, "highres")
layout.itemR(md.domain_settings, "noise_type")
layout.itemR(md.domain_settings, "visibility")
layout.itemR(md.domain_settings, "alpha")
layout.itemR(md.domain_settings, "beta")
layout.itemR(md.domain_settings, "fluid_group")
layout.itemR(md.domain_settings, "eff_group")
layout.itemR(md.domain_settings, "coll_group")
elif md.smoke_type == 'TYPE_FLOW':
layout.itemS()
layout.itemR(md.flow_settings, "density")
layout.itemR(md.flow_settings, "temperature")
layout.itemL(text="Velocity")
layout.row().itemR(md.flow_settings, "velocity", text="")
layout.item_pointerR(md.flow_settings, "psys", ob, "particle_systems")
elif md.smoke_type == 'TYPE_COLL':
layout.itemS()
def smooth(self, layout, ob, md):
split = layout.split()
sub = split.column()
sub.itemR(md, "x")
sub.itemR(md, "y")
sub.itemR(md, "z")
sub = split.column()
sub.itemR(md, "factor")
sub.itemR(md, "repeat")
col = split.column()
col.itemR(md, "x")
col.itemR(md, "y")
col.itemR(md, "z")
col = split.column()
col.itemR(md, "factor")
col.itemR(md, "repeat")
layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
@@ -370,11 +403,12 @@ class DATA_PT_modifiers(DataButtonsPanel):
def subsurf(self, layout, ob, md):
layout.itemR(md, "subdivision_type")
col = layout.column_flow()
col.itemR(md, "levels", text="Preview")
col.itemR(md, "render_levels", text="Render")
col.itemR(md, "optimal_draw", text="Optimal Display")
col.itemR(md, "subsurf_uv")
flow = layout.column_flow()
flow.itemR(md, "levels", text="Preview")
flow.itemR(md, "render_levels", text="Render")
flow.itemR(md, "optimal_draw", text="Optimal Display")
flow.itemR(md, "subsurf_uv")
def surface(self, layout, ob, md):
layout.itemL(text="See Fields panel.")
@@ -382,7 +416,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
def uvproject(self, layout, ob, md):
if ob.type == 'MESH':
layout.item_pointerR(md, "uv_layer", ob.data, "uv_layers")
layout.itemR(md, "projectors")
#layout.itemR(md, "projectors")
layout.itemR(md, "image")
layout.itemR(md, "horizontal_aspect_ratio")
layout.itemR(md, "vertical_aspect_ratio")
@@ -392,27 +426,27 @@ class DATA_PT_modifiers(DataButtonsPanel):
def wave(self, layout, ob, md):
split = layout.split()
sub = split.column()
sub.itemL(text="Motion:")
sub.itemR(md, "x")
sub.itemR(md, "y")
sub.itemR(md, "cyclic")
col = split.column()
col.itemL(text="Motion:")
col.itemR(md, "x")
col.itemR(md, "y")
col.itemR(md, "cyclic")
sub = split.column()
sub.itemR(md, "normals")
row = sub.row(align=True)
row.active = md.normals
row.itemR(md, "x_normal", text="X", toggle=True)
row.itemR(md, "y_normal", text="Y", toggle=True)
row.itemR(md, "z_normal", text="Z", toggle=True)
col = split.column()
col.itemR(md, "normals")
sub = col.row(align=True)
sub.active = md.normals
sub.itemR(md, "x_normal", text="X", toggle=True)
sub.itemR(md, "y_normal", text="Y", toggle=True)
sub.itemR(md, "z_normal", text="Z", toggle=True)
col = layout.column_flow()
col.itemR(md, "time_offset")
col.itemR(md, "lifetime")
col.itemR(md, "damping_time")
col.itemR(md, "falloff_radius")
col.itemR(md, "start_position_x")
col.itemR(md, "start_position_y")
flow = layout.column_flow()
flow.itemR(md, "time_offset")
flow.itemR(md, "lifetime")
flow.itemR(md, "damping_time")
flow.itemR(md, "falloff_radius")
flow.itemR(md, "start_position_x")
flow.itemR(md, "start_position_y")
layout.itemR(md, "start_position_object")
layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
@@ -423,10 +457,10 @@ class DATA_PT_modifiers(DataButtonsPanel):
elif md.texture_coordinates == 'OBJECT':
layout.itemR(md, "texture_coordinates_object")
col = layout.column_flow()
col.itemR(md, "speed", slider=True)
col.itemR(md, "height", slider=True)
col.itemR(md, "width", slider=True)
col.itemR(md, "narrowness", slider=True)
flow = layout.column_flow()
flow.itemR(md, "speed", slider=True)
flow.itemR(md, "height", slider=True)
flow.itemR(md, "width", slider=True)
flow.itemR(md, "narrowness", slider=True)
bpy.types.register(DATA_PT_modifiers)

View File

@@ -10,7 +10,6 @@ class DataButtonsPanel(bpy.types.Panel):
return (context.object and context.object.type == 'TEXT' and context.curve)
class DATA_PT_context_text(DataButtonsPanel):
__idname__ = "DATA_PT_context_text"
__show_header__ = False
def draw(self, context):
@@ -30,7 +29,6 @@ class DATA_PT_context_text(DataButtonsPanel):
split.itemS()
class DATA_PT_shape_text(DataButtonsPanel):
__idname__ = "DATA_PT_shape_text"
__label__ = "Shape Text"
def draw(self, context):
@@ -45,84 +43,82 @@ class DATA_PT_shape_text(DataButtonsPanel):
split = layout.split()
sub = split.column()
sub.itemL(text="Caps:")
sub.itemR(curve, "front")
sub.itemR(curve, "back")
col = split.column()
col.itemL(text="Caps:")
col.itemR(curve, "front")
col.itemR(curve, "back")
col.itemL(text="Textures:")
col.itemR(curve, "uv_orco")
col.itemR(curve, "auto_texspace")
sub.itemL(text="Textures:")
sub.itemR(curve, "uv_orco")
sub.itemR(curve, "auto_texspace")
sub = split.column()
sub.itemL(text="Resolution:")
col = split.column()
col.itemL(text="Resolution:")
sub = col.column(align=True)
sub.itemR(curve, "resolution_u", text="Preview U")
sub.itemR(curve, "resolution_v", text="Preview V")
sub.itemR(curve, "render_resolution_u", text="Render U")
sub = col.column(align=True)
sub.itemR(curve, "resolution_v", text="Preview V")
sub.itemR(curve, "render_resolution_v", text="Render V")
sub.itemL(text="Display:")
sub.itemR(curve, "fast")
col.itemL(text="Display:")
col.itemR(curve, "fast")
class DATA_PT_geometry_text(DataButtonsPanel):
__idname__ = "DATA_PT_geometry_text"
__label__ = "Geometry"
def draw(self, context):
layout = self.layout
curve = context.curve
split = layout.split()
sub = split.column()
sub.itemL(text="Modification:")
sub.itemR(curve, "width")
sub.itemR(curve, "extrude")
sub.itemR(curve, "taper_object")
col = split.column()
col.itemL(text="Modification:")
col.itemR(curve, "width")
col.itemR(curve, "extrude")
col.itemR(curve, "taper_object")
sub = split.column()
sub.itemL(text="Bevel:")
sub.itemR(curve, "bevel_depth", text="Depth")
sub.itemR(curve, "bevel_resolution", text="Resolution")
sub.itemR(curve, "bevel_object")
col = split.column()
col.itemL(text="Bevel:")
col.itemR(curve, "bevel_depth", text="Depth")
col.itemR(curve, "bevel_resolution", text="Resolution")
col.itemR(curve, "bevel_object")
class DATA_PT_font(DataButtonsPanel):
__idname__ = "DATA_PT_font"
__label__ = "Font"
def draw(self, context):
layout = self.layout
text = context.curve
layout.row()
layout.itemR(text, "font")
split = layout.split()
sub = split.column()
# sub.itemR(text, "style")
# sub.itemR(text, "bold")
# sub.itemR(text, "italic")
# sub.itemR(text, "underline")
col = split.column()
# col.itemR(text, "style")
# col.itemR(text, "bold")
# col.itemR(text, "italic")
# col.itemR(text, "underline")
# ToDo: These settings are in a sub struct (Edit Format).
sub.itemR(text, "text_size")
sub.itemR(text, "shear")
col.itemR(text, "text_size")
col.itemR(text, "shear")
sub = split.column()
sub.itemR(text, "text_on_curve")
sub.itemR(text, "family")
sub.itemL(text="Underline:")
sub.itemR(text, "ul_position", text="Position")
sub.itemR(text, "ul_height", text="Height")
# sub.itemR(text, "edit_format")
col = split.column()
col.itemR(text, "text_on_curve")
col.itemR(text, "family")
col.itemL(text="Underline:")
col.itemR(text, "ul_position", text="Position")
col.itemR(text, "ul_height", text="Height")
# col.itemR(text, "edit_format")
class DATA_PT_paragraph(DataButtonsPanel):
__idname__ = "DATA_PT_paragraph"
__label__ = "Paragraph"
def draw(self, context):
layout = self.layout
text = context.curve
layout.itemL(text="Align:")
@@ -130,25 +126,25 @@ class DATA_PT_paragraph(DataButtonsPanel):
split = layout.split()
sub = split.column()
sub.itemL(text="Spacing:")
sub.itemR(text, "spacing", text="Character")
sub.itemR(text, "word_spacing", text="Word")
sub.itemR(text, "line_dist", text="Line")
col = split.column(align=True)
col.itemL(text="Spacing:")
col.itemR(text, "spacing", text="Character")
col.itemR(text, "word_spacing", text="Word")
col.itemR(text, "line_dist", text="Line")
sub = split.column()
sub.itemL(text="Offset:")
sub.itemR(text, "x_offset", text="X")
sub.itemR(text, "y_offset", text="Y")
#sub.itemR(text, "wrap")
col = split.column(align=True)
col.itemL(text="Offset:")
col.itemR(text, "x_offset", text="X")
col.itemR(text, "y_offset", text="Y")
#col.itemR(text, "wrap")
"""
class DATA_PT_textboxes(DataButtonsPanel):
__idname__ = "DATA_PT_textboxes"
__label__ = "Text Boxes"
def draw(self, context):
layout = self.layout
text = context.curve
"""
@@ -158,4 +154,3 @@ bpy.types.register(DATA_PT_geometry_text)
bpy.types.register(DATA_PT_font)
bpy.types.register(DATA_PT_paragraph)
#bpy.types.register(DATA_PT_textboxes)

View File

@@ -12,76 +12,82 @@ class PhysicsButtonsPanel(bpy.types.Panel):
return ob and ob.game and (rd.engine == 'BLENDER_GAME')
class PHYSICS_PT_game_physics(PhysicsButtonsPanel):
__idname__ = "PHYSICS_PT_game_physics"
__label__ = "Physics"
def draw(self, context):
layout = self.layout
ob = context.active_object
ob = context.active_object
game = ob.game
layout.itemR(game, "physics_type")
layout.itemS()
split = layout.split()
col = split.column()
col.itemR(game, "actor")
col.itemR(game, "ghost")
col.itemR(ob, "restrict_render", text="Invisible") # out of place but useful
col = split.column()
col.itemR(game, "do_fh", text="Use Material Physics")
col.itemR(game, "rotation_fh", text="Rotate From Normal")
col.itemR(game, "no_sleeping")
layout.itemS()
split = layout.split()
col = split.column()
col.itemL(text="Attributes:")
colsub = col.column(align=True)
colsub.itemR(game, "mass")
colsub.itemR(game, "radius")
colsub.itemR(game, "form_factor")
sub = col.column(align=True)
sub.itemR(game, "mass")
sub.itemR(game, "radius")
sub.itemR(game, "form_factor")
col.itemS()
col.itemL(text="Damping:")
colsub = col.column(align=True)
colsub.itemR(game, "damping", text="Translation", slider=True)
colsub.itemR(game, "rotation_damping", text="Rotation", slider=True)
sub = col.column(align=True)
sub.itemR(game, "damping", text="Translation", slider=True)
sub.itemR(game, "rotation_damping", text="Rotation", slider=True)
col = split.column()
col.itemL(text="Velocity:")
colsub = col.column(align=True)
colsub.itemR(game, "minimum_velocity", text="Minimum")
colsub.itemR(game, "maximum_velocity", text="Maximum")
col.itemS()
col.itemR(game, "anisotropic_friction")
sub = col.column(align=True)
sub.itemR(game, "minimum_velocity", text="Minimum")
sub.itemR(game, "maximum_velocity", text="Maximum")
colsub = col.column()
colsub.active = game.anisotropic_friction
colsub.itemR(game, "friction_coefficients", text="", slider=True)
col.itemS()
col.itemR(game, "anisotropic_friction")
sub = col.column()
sub.active = game.anisotropic_friction
sub.itemR(game, "friction_coefficients", text="", slider=True)
layout.itemS()
split = layout.split()
sub = split.column()
sub.itemL(text="Lock Translation:")
sub.itemR(game, "lock_x_axis", text="X")
sub.itemR(game, "lock_y_axis", text="Y")
sub.itemR(game, "lock_z_axis", text="Z")
sub = split.column()
sub.itemL(text="Lock Rotation:")
sub.itemR(game, "lock_x_rot_axis", text="X")
sub.itemR(game, "lock_y_rot_axis", text="Y")
sub.itemR(game, "lock_z_rot_axis", text="Z")
col = split.column()
col.itemL(text="Lock Translation:")
col.itemR(game, "lock_x_axis", text="X")
col.itemR(game, "lock_y_axis", text="Y")
col.itemR(game, "lock_z_axis", text="Z")
col = split.column()
col.itemL(text="Lock Rotation:")
col.itemR(game, "lock_x_rot_axis", text="X")
col.itemR(game, "lock_y_rot_axis", text="Y")
col.itemR(game, "lock_z_rot_axis", text="Z")
class PHYSICS_PT_game_collision_bounds(PhysicsButtonsPanel):
__idname__ = "PHYSICS_PT_game_collision_bounds"
__label__ = "Collision Bounds"
def draw_header(self, context):
layout = self.layout
ob = context.active_object
game = ob.game
@@ -92,17 +98,13 @@ class PHYSICS_PT_game_collision_bounds(PhysicsButtonsPanel):
ob = context.scene.objects[0]
game = ob.game
layout.active = game.use_collision_bounds
layout.itemR(game, "collision_bounds", text="Bounds")
split = layout.split()
sub = split.column()
sub.itemR(game, "collision_compound", text="Compound")
sub = split.column()
sub.itemR(game, "collision_margin", text="Margin", slider=True)
row = layout.row()
row.itemR(game, "collision_compound", text="Compound")
row.itemR(game, "collision_margin", text="Margin", slider=True)
bpy.types.register(PHYSICS_PT_game_physics)
bpy.types.register(PHYSICS_PT_game_collision_bounds)
@@ -121,6 +123,7 @@ class SCENE_PT_game(SceneButtonsPanel):
def draw(self, context):
layout = self.layout
rd = context.scene.render_data
row = layout.row()
@@ -132,64 +135,63 @@ class SCENE_PT_game_player(SceneButtonsPanel):
def draw(self, context):
layout = self.layout
gs = context.scene.game_data
row = layout.row()
row.itemR(gs, "fullscreen")
layout.itemR(gs, "fullscreen")
split = layout.split()
col = split.column()
col.itemL(text="Resolution:")
colsub = col.column(align=True)
colsub.itemR(gs, "resolution_x", slider=False, text="X")
colsub.itemR(gs, "resolution_y", slider=False, text="Y")
sub = col.column(align=True)
sub.itemR(gs, "resolution_x", slider=False, text="X")
sub.itemR(gs, "resolution_y", slider=False, text="Y")
col = split.column()
col.itemL(text="Quality:")
colsub = col.column(align=True)
colsub.itemR(gs, "depth", text="Bit Depth", slider=False)
colsub.itemR(gs, "frequency", text="FPS", slider=False)
sub = col.column(align=True)
sub.itemR(gs, "depth", text="Bit Depth", slider=False)
sub.itemR(gs, "frequency", text="FPS", slider=False)
# framing:
col = layout.column()
col.itemL(text="Framing:")
col.row().itemR(gs, "framing_type", expand=True)
colsub = col.column()
colsub.itemR(gs, "framing_color", text="")
sub = col.column()
sub.itemR(gs, "framing_color", text="")
class SCENE_PT_game_stereo(SceneButtonsPanel):
__label__ = "Stereo"
def draw(self, context):
layout = self.layout
gs = context.scene.game_data
# stereo options:
col= layout.column()
row = col.row()
row.itemR(gs, "stereo", expand=True)
stereo_mode = gs.stereo
# stereo options:
layout.itemR(gs, "stereo", expand=True)
# stereo:
if stereo_mode == 'STEREO':
row = layout.row()
row.itemR(gs, "stereo_mode")
layout.itemR(gs, "stereo_mode")
# dome:
if stereo_mode == 'DOME':
row = layout.row()
row.itemR(gs, "dome_mode", text="Dome Type")
layout.itemR(gs, "dome_mode", text="Dome Type")
split=layout.split()
col=split.column()
col.itemR(gs, "dome_angle", slider=True)
col.itemR(gs, "dome_tesselation", text="Tesselation")
col=split.column()
col.itemR(gs, "dome_tilt")
col.itemR(gs, "dome_buffer_resolution", text="Resolution", slider=True)
col=layout.column()
col.itemR(gs, "dome_text")
layout.itemR(gs, "dome_text")
bpy.types.register(SCENE_PT_game)
bpy.types.register(SCENE_PT_game_player)
@@ -209,7 +211,7 @@ class WORLD_PT_game_context_world(WorldButtonsPanel):
def poll(self, context):
rd = context.scene.render_data
return (context.scene != None) and (rd.use_game_engine)
return (context.scene) and (rd.use_game_engine)
def draw(self, context):
layout = self.layout
@@ -230,6 +232,7 @@ class WORLD_PT_game_world(WorldButtonsPanel):
def draw(self, context):
layout = self.layout
world = context.world
row = layout.row()
@@ -272,35 +275,39 @@ class WORLD_PT_game_physics(WorldButtonsPanel):
def draw(self, context):
layout = self.layout
gs = context.scene.game_data
flow = layout.column_flow()
flow.itemR(gs, "physics_engine")
layout.itemR(gs, "physics_engine")
if gs.physics_engine != "NONE":
flow.itemR(gs, "physics_gravity", text="Gravity")
layout.itemR(gs, "physics_gravity", text="Gravity")
split = layout.split()
col = split.column()
col.itemL(text="Physics Steps:")
colsub = col.column(align=True)
colsub.itemR(gs, "physics_step_max", text="Max")
colsub.itemR(gs, "physics_step_sub", text="Substeps")
sub = col.column(align=True)
sub.itemR(gs, "physics_step_max", text="Max")
sub.itemR(gs, "physics_step_sub", text="Substeps")
col.itemR(gs, "fps", text="FPS")
col = split.column()
col.itemL(text="Logic Steps:")
col.itemR(gs, "logic_step_max", text="Max")
col.itemS()
col.itemR(gs, "use_occlusion_culling", text="Occlusion Culling")
colsub = col.column()
colsub.active = gs.use_occlusion_culling
colsub.itemR(gs, "occlusion_culling_resolution", text="Resolution")
col = layout.column()
col.itemR(gs, "use_occlusion_culling", text="Occlusion Culling")
sub = col.column()
sub.active = gs.use_occlusion_culling
sub.itemR(gs, "occlusion_culling_resolution", text="Resolution")
else:
split = layout.split()
col = split.column()
col.itemL(text="Physics Steps:")
col.itemR(gs, "fps", text="FPS")
col = split.column()
col.itemL(text="Logic Steps:")
col.itemR(gs, "logic_step_max", text="Max")
@@ -308,4 +315,3 @@ class WORLD_PT_game_physics(WorldButtonsPanel):
bpy.types.register(WORLD_PT_game_context_world)
bpy.types.register(WORLD_PT_game_world)
bpy.types.register(WORLD_PT_game_physics)

View File

@@ -5,26 +5,31 @@ class MaterialButtonsPanel(bpy.types.Panel):
__space_type__ = "BUTTONS_WINDOW"
__region_type__ = "WINDOW"
__context__ = "material"
# COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
def poll(self, context):
return (context.material != None)
return (context.material) and (context.scene.render_data.engine in self.COMPAT_ENGINES)
class MATERIAL_PT_preview(MaterialButtonsPanel):
__idname__= "MATERIAL_PT_preview"
__label__ = "Preview"
COMPAT_ENGINES = set(['BLENDER_RENDER', 'BLENDER_GAME'])
def draw(self, context):
layout = self.layout
mat = context.material
layout.template_preview(mat)
class MATERIAL_PT_context_material(MaterialButtonsPanel):
__idname__= "MATERIAL_PT_context_material"
__show_header__ = False
COMPAT_ENGINES = set(['BLENDER_RENDER', 'BLENDER_GAME'])
def poll(self, context):
return (context.object)
# An exception, dont call the parent poll func because
# this manages materials for all engine types
return (context.object) and (context.scene.render_data.engine in self.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
@@ -45,17 +50,19 @@ class MATERIAL_PT_context_material(MaterialButtonsPanel):
if context.edit_object:
row = layout.row(align=True)
row.itemO("object.material_slot_assign", text="Assign")
row.itemO("object.material_slot_select", text="Select")
row.itemO("object.material_slot_deselect", text="Deselect")
split = layout.split(percentage=0.65)
if ob and slot:
split.template_ID(slot, "material", new="material.new")
if ob:
split.template_ID(ob, "active_material", new="material.new")
row = split.row()
row.itemR(slot, "link", expand=True)
if slot:
row.itemR(slot, "link", expand=True)
else:
row.itemL()
elif mat:
split.template_ID(space, "pin_id")
split.itemS()
@@ -63,6 +70,7 @@ class MATERIAL_PT_context_material(MaterialButtonsPanel):
class MATERIAL_PT_material(MaterialButtonsPanel):
__idname__= "MATERIAL_PT_material"
__label__ = "Shading"
COMPAT_ENGINES = set(['BLENDER_RENDER', 'BLENDER_GAME'])
def draw(self, context):
layout = self.layout
@@ -78,207 +86,205 @@ class MATERIAL_PT_material(MaterialButtonsPanel):
if mat.type in ('SURFACE', 'WIRE', 'VOLUME'):
split = layout.split()
sub = split.column()
sub.itemR(mat, "alpha", slider=True)
sub.itemR(mat, "ambient", slider=True)
sub.itemR(mat, "emit")
sub.itemR(mat, "translucency", slider=True)
col = split.column()
col.itemR(mat, "alpha", slider=True)
col.itemR(mat, "ambient", slider=True)
col.itemR(mat, "emit")
col.itemR(mat, "translucency", slider=True)
sub = split.column()
sub.itemR(mat, "z_transparency")
sub.itemR(mat, "shadeless")
sub.itemR(mat, "tangent_shading")
sub.itemR(mat, "cubic", slider=True)
col = split.column()
col.itemR(mat, "z_transparency")
col.itemR(mat, "shadeless")
col.itemR(mat, "tangent_shading")
col.itemR(mat, "cubic", slider=True)
elif mat.type == 'HALO':
layout.itemR(mat, "alpha", slider=True)
class MATERIAL_PT_strand(MaterialButtonsPanel):
__idname__= "MATERIAL_PT_strand"
__label__ = "Strand"
__default_closed__ = True
COMPAT_ENGINES = set(['BLENDER_RENDER'])
def draw(self, context):
layout = self.layout
tan = context.material.strand
mat = context.material
tan = mat.strand
split = layout.split()
sub = split.column()
sub.itemL(text="Size:")
sub.itemR(tan, "start_size", text="Root")
sub.itemR(tan, "end_size", text="Tip")
sub.itemR(tan, "min_size", text="Minimum")
sub.itemR(tan, "blender_units")
colsub = sub.column()
colsub.active = mat.shadeless== False
colsub.itemR(tan, "tangent_shading")
col = split.column()
col.itemL(text="Size:")
col.itemR(tan, "start_size", text="Root")
col.itemR(tan, "end_size", text="Tip")
col.itemR(tan, "min_size", text="Minimum")
col.itemR(tan, "blender_units")
sub = col.column()
sub.active = mat.shadeless == False
sub.itemR(tan, "tangent_shading")
sub = split.column()
sub.itemR(tan, "shape")
sub.itemR(tan, "width_fade")
sub.itemR(tan, "uv_layer")
colsub = sub.column()
colsub.active = mat.shadeless== False
colsub.itemR(tan, "surface_diffuse")
colsubsub = colsub.column()
colsubsub.active = tan.surface_diffuse
colsubsub.itemR(tan, "blend_distance", text="Distance")
col = split.column()
col.itemR(tan, "shape")
col.itemR(tan, "width_fade")
col.itemR(tan, "uv_layer")
sub = col.column()
sub.active = mat.shadeless == False
sub.itemR(tan, "surface_diffuse")
sub = col.column()
sub.active = tan.surface_diffuse
sub.itemR(tan, "blend_distance", text="Distance")
class MATERIAL_PT_options(MaterialButtonsPanel):
__idname__= "MATERIAL_PT_options"
__label__ = "Options"
COMPAT_ENGINES = set(['BLENDER_RENDER', 'BLENDER_GAME'])
def draw(self, context):
layout = self.layout
mat = context.material
split = layout.split()
sub = split.column()
sub.itemR(mat, "traceable")
sub.itemR(mat, "full_oversampling")
sub.itemR(mat, "sky")
sub.itemR(mat, "exclude_mist")
sub.itemR(mat, "invert_z")
col = sub.column(align=True)
col.itemL(text="Light Group:")
col.itemR(mat, "light_group", text="")
row = col.row()
col = split.column()
col.itemR(mat, "traceable")
col.itemR(mat, "full_oversampling")
col.itemR(mat, "sky")
col.itemR(mat, "exclude_mist")
col.itemR(mat, "invert_z")
sub = col.column(align=True)
sub.itemL(text="Light Group:")
sub.itemR(mat, "light_group", text="")
row = sub.row()
row.active = mat.light_group
row.itemR(mat, "light_group_exclusive", text="Exclusive")
sub = split.column()
sub.itemR(mat, "face_texture")
colsub = sub.column()
colsub.active = mat.face_texture
colsub.itemR(mat, "face_texture_alpha")
sub.itemR(mat, "vertex_color_paint")
sub.itemR(mat, "vertex_color_light")
sub.itemR(mat, "object_color")
col = split.column()
col.itemR(mat, "face_texture")
sub = col.column()
sub.active = mat.face_texture
sub.itemR(mat, "face_texture_alpha")
col.itemR(mat, "vertex_color_paint")
col.itemR(mat, "vertex_color_light")
col.itemR(mat, "object_color")
class MATERIAL_PT_shadows(MaterialButtonsPanel):
__idname__= "MATERIAL_PT_shadows"
__label__ = "Shadows"
COMPAT_ENGINES = set(['BLENDER_RENDER', 'BLENDER_GAME'])
def draw(self, context):
layout = self.layout
mat = context.material
split = layout.split()
sub = split.column()
sub.itemR(mat, "shadows", text="Receive")
sub.itemR(mat, "transparent_shadows", text="Receive Transparent")
sub.itemR(mat, "only_shadow", text="Shadows Only")
sub.itemR(mat, "cast_shadows_only", text="Cast Only")
sub.itemR(mat, "shadow_casting_alpha", text="Casting Alpha", slider=True)
sub = split.column()
sub.itemR(mat, "ray_shadow_bias", text="Auto Ray Bias")
colsub = sub.column()
colsub.active = not mat.ray_shadow_bias
colsub.itemR(mat, "shadow_ray_bias", text="Ray Shadow Bias")
col = split.column()
col.itemR(mat, "shadows", text="Receive")
col.itemR(mat, "transparent_shadows", text="Receive Transparent")
col.itemR(mat, "only_shadow", text="Shadows Only")
col.itemR(mat, "cast_shadows_only", text="Cast Only")
col.itemR(mat, "shadow_casting_alpha", text="Casting Alpha", slider=True)
col = split.column()
col.itemR(mat, "ray_shadow_bias", text="Auto Ray Bias")
sub = col.column()
sub.active = not mat.ray_shadow_bias
sub.itemR(mat, "shadow_ray_bias", text="Ray Shadow Bias")
sub.itemR(mat, "cast_buffer_shadows")
sub.itemR(mat, "shadow_buffer_bias", text="Buffer Bias")
class MATERIAL_PT_diffuse(MaterialButtonsPanel):
__idname__= "MATERIAL_PT_diffuse"
__label__ = "Diffuse"
COMPAT_ENGINES = set(['BLENDER_RENDER', 'BLENDER_GAME'])
def poll(self, context):
mat = context.material
return (mat and mat.type != 'HALO')
return (context.material.type != 'HALO') and (context.scene.render_data.engine in self.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
mat = context.material
split = layout.split()
sub = split.column()
sub.itemR(mat, "diffuse_color", text="")
row = sub.row()
row.active = mat.shadeless== False
row.itemR(mat, "diffuse_reflection", text="Intensity", slider=True)
sub = split.column()
col = split.column()
col.itemR(mat, "diffuse_color", text="")
sub = col.column()
sub.active = mat.shadeless== False
sub.itemR(mat, "diffuse_shader", text="")
sub.itemR(mat, "use_diffuse_ramp", text="Ramp")
sub.itemR(mat, "diffuse_reflection", text="Intensity", slider=True)
split = layout.split()
split.active = mat.shadeless== False
sub = split.column()
col = split.column()
col.active = mat.shadeless== False
col.itemR(mat, "diffuse_shader", text="")
col.itemR(mat, "use_diffuse_ramp", text="Ramp")
col = layout.column()
col.active = mat.shadeless== False
if mat.diffuse_shader == 'OREN_NAYAR':
sub.itemR(mat, "roughness")
if mat.diffuse_shader == 'MINNAERT':
sub.itemR(mat, "darkness")
if mat.diffuse_shader == 'TOON':
sub.itemR(mat, "diffuse_toon_size", text="Size")
sub = split.column()
sub.itemR(mat, "diffuse_toon_smooth", text="Smooth")
if mat.diffuse_shader == 'FRESNEL':
sub.itemR(mat, "diffuse_fresnel", text="Fresnel")
sub = split.column()
sub.itemR(mat, "diffuse_fresnel_factor", text="Factor")
if mat.use_diffuse_ramp:
col.itemR(mat, "roughness")
elif mat.diffuse_shader == 'MINNAERT':
col.itemR(mat, "darkness")
elif mat.diffuse_shader == 'TOON':
row = col.row()
row.itemR(mat, "diffuse_toon_size", text="Size")
row.itemR(mat, "diffuse_toon_smooth", text="Smooth")
elif mat.diffuse_shader == 'FRESNEL':
row = col.row()
row.itemR(mat, "diffuse_fresnel", text="Fresnel")
row.itemR(mat, "diffuse_fresnel_factor", text="Factor")
elif mat.use_diffuse_ramp:
layout.template_color_ramp(mat.diffuse_ramp, expand=True)
class MATERIAL_PT_specular(MaterialButtonsPanel):
__idname__= "MATERIAL_PT_specular"
__label__ = "Specular"
COMPAT_ENGINES = set(['BLENDER_RENDER', 'BLENDER_GAME'])
def poll(self, context):
mat = context.material
return (mat and mat.type != 'HALO')
return (context.material.type != 'HALO') and (context.scene.render_data.engine in self.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
mat = context.material
layout.active = mat.shadeless== False
layout.active = mat.shadeless == False
split = layout.split()
sub = split.column()
sub.itemR(mat, "specular_color", text="")
sub.itemR(mat, "specular_reflection", text="Intensity", slider=True)
col = split.column()
col.itemR(mat, "specular_color", text="")
col.itemR(mat, "specular_reflection", text="Intensity", slider=True)
sub = split.column()
sub.itemR(mat, "specular_shader", text="")
sub.itemR(mat, "use_specular_ramp", text="Ramp")
split = layout.split()
sub = split.column()
col = split.column()
col.itemR(mat, "specular_shader", text="")
col.itemR(mat, "use_specular_ramp", text="Ramp")
col = layout.column()
if mat.specular_shader in ('COOKTORR', 'PHONG'):
sub.itemR(mat, "specular_hardness", text="Hardness")
if mat.specular_shader == 'BLINN':
sub.itemR(mat, "specular_hardness", text="Hardness")
sub = split.column()
sub.itemR(mat, "specular_ior", text="IOR")
if mat.specular_shader == 'WARDISO':
sub.itemR(mat, "specular_slope", text="Slope")
if mat.specular_shader == 'TOON':
sub.itemR(mat, "specular_toon_size", text="Size")
sub = split.column()
sub.itemR(mat, "specular_toon_smooth", text="Smooth")
col.itemR(mat, "specular_hardness", text="Hardness")
elif mat.specular_shader == 'BLINN':
row = col.row()
row.itemR(mat, "specular_hardness", text="Hardness")
row.itemR(mat, "specular_ior", text="IOR")
elif mat.specular_shader == 'WARDISO':
col.itemR(mat, "specular_slope", text="Slope")
elif mat.specular_shader == 'TOON':
row = col.row()
row.itemR(mat, "specular_toon_size", text="Size")
row.itemR(mat, "specular_toon_smooth", text="Smooth")
if mat.use_specular_ramp:
layout.template_color_ramp(mat.specular_ramp, expand=True)
class MATERIAL_PT_sss(MaterialButtonsPanel):
__idname__= "MATERIAL_PT_sss"
__label__ = "Subsurface Scattering"
__default_closed__ = True
COMPAT_ENGINES = set(['BLENDER_RENDER'])
def poll(self, context):
mat = context.material
return (mat and (mat.type == 'SURFACE' or mat.type == 'WIRE'))
return (context.material.type in ('SURFACE', 'WIRE')) and (context.scene.render_data.engine in self.COMPAT_ENGINES)
def draw_header(self, context):
layout = self.layout
@@ -288,65 +294,68 @@ class MATERIAL_PT_sss(MaterialButtonsPanel):
def draw(self, context):
layout = self.layout
sss = context.material.subsurface_scattering
mat = context.material
sss = context.material.subsurface_scattering
layout.active = sss.enabled
split = layout.split()
split.active = mat.shadeless== False
sub = split.column()
sub.itemR(sss, "color", text="")
sub.itemL(text="Blend:")
sub.itemR(sss, "color_factor", slider=True)
sub.itemR(sss, "texture_factor", slider=True)
sub.itemL(text="Scattering Weight:")
sub.itemR(sss, "front")
sub.itemR(sss, "back")
col = split.column()
col.itemR(sss, "color", text="")
col.itemL(text="Blend:")
col.itemR(sss, "color_factor", slider=True)
col.itemR(sss, "texture_factor", slider=True)
col.itemL(text="Scattering Weight:")
col.itemR(sss, "front")
col.itemR(sss, "back")
sub = split.column()
sub.itemR(sss, "ior")
sub.itemR(sss, "scale")
sub.itemR(sss, "radius", text="RGB Radius")
sub.itemR(sss, "error_tolerance")
col = split.column()
col.itemR(sss, "ior")
col.itemR(sss, "scale")
col.itemR(sss, "radius", text="RGB Radius")
col.itemR(sss, "error_tolerance")
class MATERIAL_PT_raymir(MaterialButtonsPanel):
__idname__= "MATERIAL_PT_raymir"
__label__ = "Ray Mirror"
__default_closed__ = True
COMPAT_ENGINES = set(['BLENDER_RENDER'])
def poll(self, context):
mat = context.material
return (mat and (mat.type == 'SURFACE' or mat.type == 'WIRE'))
return (context.material.type in 'SURFACE', 'WIRE') and (context.scene.render_data.engine in self.COMPAT_ENGINES)
def draw_header(self, context):
layout = self.layout
raym = context.material.raytrace_mirror
layout.itemR(raym, "enabled", text="")
def draw(self, context):
layout = self.layout
raym = context.material.raytrace_mirror
mat = context.material
raym = context.material.raytrace_mirror
layout.active = raym.enabled
split = layout.split()
sub = split.column()
sub.itemR(raym, "reflect", text="Reflectivity", slider=True)
sub.itemR(mat, "mirror_color", text="")
sub.itemR(raym, "fresnel")
sub.itemR(raym, "fresnel_fac", text="Fac", slider=True)
col = split.column()
col.itemR(raym, "reflect", text="Reflectivity", slider=True)
col.itemR(mat, "mirror_color", text="")
col.itemR(raym, "fresnel")
col.itemR(raym, "fresnel_fac", text="Fac", slider=True)
sub = split.column()
sub.itemR(raym, "gloss", slider=True)
colsub = sub.column()
colsub.active = raym.gloss < 1
colsub.itemR(raym, "gloss_threshold", slider=True, text="Threshold")
colsub.itemR(raym, "gloss_samples", text="Samples")
colsub.itemR(raym, "gloss_anisotropic", slider=True, text="Anisotropic")
col = split.column()
col.itemR(raym, "gloss", slider=True)
sub = col.column()
sub.active = raym.gloss < 1
sub.itemR(raym, "gloss_threshold", slider=True, text="Threshold")
sub.itemR(raym, "gloss_samples", text="Samples")
sub.itemR(raym, "gloss_anisotropic", slider=True, text="Anisotropic")
row = layout.row()
row.itemR(raym, "distance", text="Max Dist")
@@ -355,44 +364,43 @@ class MATERIAL_PT_raymir(MaterialButtonsPanel):
layout.itemR(raym, "fade_to")
class MATERIAL_PT_raytransp(MaterialButtonsPanel):
__idname__= "MATERIAL_PT_raytransp"
__label__= "Ray Transparency"
__default_closed__ = True
COMPAT_ENGINES = set(['BLENDER_RENDER'])
def poll(self, context):
mat = context.material
return (mat and (mat.type == 'SURFACE' or mat.type == 'WIRE'))
return (context.material.type in 'SURFACE', 'WIRE') and (context.scene.render_data.engine in self.COMPAT_ENGINES)
def draw_header(self, context):
layout = self.layout
rayt = context.material.raytrace_transparency
layout.itemR(rayt, "enabled", text="")
def draw(self, context):
layout = self.layout
rayt = context.material.raytrace_transparency
mat = context.material
layout.active = rayt.enabled
mat = context.material
rayt = context.material.raytrace_transparency
layout.active = rayt.enabled and mat.shadeless == False
split = layout.split()
split.active = mat.shadeless== False
sub = split.column()
sub.itemR(rayt, "ior")
sub.itemR(rayt, "fresnel")
sub.itemR(rayt, "fresnel_fac", text="Fac", slider=True)
col = split.column()
col.itemR(rayt, "ior")
col.itemR(rayt, "fresnel")
col.itemR(rayt, "fresnel_fac", text="Fac", slider=True)
sub = split.column()
sub.itemR(rayt, "gloss", slider=True)
colsub = sub.column()
colsub.active = rayt.gloss < 1
colsub.itemR(rayt, "gloss_threshold", slider=True, text="Threshold")
colsub.itemR(rayt, "gloss_samples", text="Samples")
col = split.column()
col.itemR(rayt, "gloss", slider=True)
sub = col.column()
sub.active = rayt.gloss < 1
sub.itemR(rayt, "gloss_threshold", slider=True, text="Threshold")
sub.itemR(rayt, "gloss_samples", text="Samples")
flow = layout.column_flow()
flow.active = mat.shadeless== False
flow.itemR(rayt, "filter", slider=True)
flow.itemR(rayt, "limit")
flow.itemR(rayt, "falloff")
@@ -400,12 +408,11 @@ class MATERIAL_PT_raytransp(MaterialButtonsPanel):
flow.itemR(rayt, "depth")
class MATERIAL_PT_halo(MaterialButtonsPanel):
__idname__= "MATERIAL_PT_halo"
__label__= "Halo"
COMPAT_ENGINES = set(['BLENDER_RENDER'])
def poll(self, context):
mat = context.material
return (mat and mat.type == 'HALO')
return (context.material.type == 'HALO') and (context.scene.render_data.engine in self.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
@@ -420,7 +427,6 @@ class MATERIAL_PT_halo(MaterialButtonsPanel):
col.itemR(halo, "size")
col.itemR(halo, "hardness")
col.itemR(halo, "add", slider=True)
col.itemL(text="Options:")
col.itemR(halo, "use_texture", text="Texture")
col.itemR(halo, "use_vertex_normal", text="Vertex Normal")
@@ -429,30 +435,28 @@ class MATERIAL_PT_halo(MaterialButtonsPanel):
col.itemR(halo, "soft")
col = split.column()
col = col.column()
col.itemR(halo, "ring")
colsub = col.column()
colsub.active = halo.ring
colsub.itemR(halo, "rings")
colsub.itemR(mat, "mirror_color", text="")
sub = col.column()
sub.active = halo.ring
sub.itemR(halo, "rings")
sub.itemR(mat, "mirror_color", text="")
col.itemR(halo, "lines")
colsub = col.column()
colsub.active = halo.lines
colsub.itemR(halo, "line_number", text="Lines")
colsub.itemR(mat, "specular_color", text="")
sub = col.column()
sub.active = halo.lines
sub.itemR(halo, "line_number", text="Lines")
sub.itemR(mat, "specular_color", text="")
col.itemR(halo, "star")
colsub = col.column()
colsub.active = halo.star
colsub.itemR(halo, "star_tips")
sub = col.column()
sub.active = halo.star
sub.itemR(halo, "star_tips")
col.itemR(halo, "flare_mode")
colsub = col.column()
colsub.active = halo.flare_mode
colsub.itemR(halo, "flare_size", text="Size")
colsub.itemR(halo, "flare_subsize", text="Subsize")
colsub.itemR(halo, "flare_boost", text="Boost")
colsub.itemR(halo, "flare_seed", text="Seed")
colsub.itemR(halo, "flares_sub", text="Sub")
sub = col.column()
sub.active = halo.flare_mode
sub.itemR(halo, "flare_size", text="Size")
sub.itemR(halo, "flare_subsize", text="Subsize")
sub.itemR(halo, "flare_boost", text="Boost")
sub.itemR(halo, "flare_seed", text="Seed")
sub.itemR(halo, "flares_sub", text="Sub")
bpy.types.register(MATERIAL_PT_context_material)
bpy.types.register(MATERIAL_PT_preview)

View File

@@ -7,11 +7,11 @@ class ObjectButtonsPanel(bpy.types.Panel):
__context__ = "object"
class OBJECT_PT_context_object(ObjectButtonsPanel):
__idname__ = "OBJECT_PT_context_object"
__show_header__ = False
def draw(self, context):
layout = self.layout
ob = context.object
row = layout.row()
@@ -19,11 +19,11 @@ class OBJECT_PT_context_object(ObjectButtonsPanel):
row.itemR(ob, "name", text="")
class OBJECT_PT_transform(ObjectButtonsPanel):
__idname__ = "OBJECT_PT_transform"
__label__ = "Transform"
def draw(self, context):
layout = self.layout
ob = context.object
row = layout.row()
@@ -32,14 +32,15 @@ class OBJECT_PT_transform(ObjectButtonsPanel):
row.column().itemR(ob, "scale")
class OBJECT_PT_relations(ObjectButtonsPanel):
__idname__ = "OBJECT_PT_relations"
__label__ = "Relations"
def draw(self, context):
layout = self.layout
ob = context.object
split = layout.split()
col = split.column()
col.itemR(ob, "layers")
col.itemS()
@@ -57,11 +58,11 @@ class OBJECT_PT_relations(ObjectButtonsPanel):
sub.active = parent != None
class OBJECT_PT_groups(ObjectButtonsPanel):
__idname__ = "OBJECT_PT_groups"
__label__ = "Groups"
def draw(self, context):
layout = self.layout
ob = context.object
split = layout.split()
@@ -83,11 +84,11 @@ class OBJECT_PT_groups(ObjectButtonsPanel):
split.column().itemR(group, "dupli_offset", text="")
class OBJECT_PT_display(ObjectButtonsPanel):
__idname__ = "OBJECT_PT_display"
__label__ = "Display"
def draw(self, context):
layout = self.layout
ob = context.object
row = layout.row()
@@ -103,11 +104,11 @@ class OBJECT_PT_display(ObjectButtonsPanel):
flow.itemR(ob, "draw_transparent", text="Transparency")
class OBJECT_PT_duplication(ObjectButtonsPanel):
__idname__ = "OBJECT_PT_duplication"
__label__ = "Duplication"
def draw(self, context):
layout = self.layout
ob = context.object
layout.itemR(ob, "dupli_type", expand=True)
@@ -115,13 +116,13 @@ class OBJECT_PT_duplication(ObjectButtonsPanel):
if ob.dupli_type == 'FRAMES':
split = layout.split()
sub = split.column(align=True)
sub.itemR(ob, "dupli_frames_start", text="Start")
sub.itemR(ob, "dupli_frames_end", text="End")
col = split.column(align=True)
col.itemR(ob, "dupli_frames_start", text="Start")
col.itemR(ob, "dupli_frames_end", text="End")
sub = split.column(align=True)
sub.itemR(ob, "dupli_frames_on", text="On")
sub.itemR(ob, "dupli_frames_off", text="Off")
col = split.column(align=True)
col.itemR(ob, "dupli_frames_on", text="On")
col.itemR(ob, "dupli_frames_off", text="Off")
layout.itemR(ob, "dupli_frames_no_speed", text="No Speed")
@@ -137,35 +138,35 @@ class OBJECT_PT_duplication(ObjectButtonsPanel):
layout.itemR(ob, "dupli_group", text="Group")
class OBJECT_PT_animation(ObjectButtonsPanel):
__idname__ = "OBJECT_PT_animation"
__label__ = "Animation"
def draw(self, context):
layout = self.layout
ob = context.object
split = layout.split()
sub = split.column()
sub.itemL(text="Time Offset:")
sub.itemR(ob, "time_offset_edit", text="Edit")
row = sub.row()
col = split.column()
col.itemL(text="Time Offset:")
col.itemR(ob, "time_offset_edit", text="Edit")
row = col.row()
row.itemR(ob, "time_offset_particle", text="Particle")
row.active = len(ob.particle_systems) != 0
row = sub.row()
row = col.row()
row.itemR(ob, "time_offset_parent", text="Parent")
row.active = ob.parent != None
row = sub.row()
row = col.row()
row.itemR(ob, "slow_parent")
row.active = ob.parent != None
sub.itemR(ob, "time_offset", text="Offset")
col.itemR(ob, "time_offset", text="Offset")
sub = split.column()
sub.itemL(text="Track:")
sub.itemR(ob, "track", text="")
sub.itemR(ob, "track_axis", text="Axis")
sub.itemR(ob, "up_axis", text="Up Axis")
row = sub.row()
col = split.column()
col.itemL(text="Track:")
col.itemR(ob, "track", text="")
col.itemR(ob, "track_axis", text="Axis")
col.itemR(ob, "up_axis", text="Up Axis")
row = col.row()
row.itemR(ob, "track_override_parent", text="Override Parent")
row.active = ob.parent != None

View File

@@ -8,6 +8,7 @@ class ConstraintButtonsPanel(bpy.types.Panel):
def draw_constraint(self, con):
layout = self.layout
box = layout.template_constraint(con)
if box:
@@ -91,23 +92,23 @@ class ConstraintButtonsPanel(bpy.types.Panel):
split = layout.split()
sub = split.column()
sub.itemL(text="Location:")
sub.itemR(con, "locationx", text="X")
sub.itemR(con, "locationy", text="Y")
sub.itemR(con, "locationz", text="Z")
col = split.column()
col.itemL(text="Location:")
col.itemR(con, "locationx", text="X")
col.itemR(con, "locationy", text="Y")
col.itemR(con, "locationz", text="Z")
sub = split.column()
sub.itemL(text="Rotation:")
sub.itemR(con, "rotationx", text="X")
sub.itemR(con, "rotationy", text="Y")
sub.itemR(con, "rotationz", text="Z")
col = split.column()
col.itemL(text="Rotation:")
col.itemR(con, "rotationx", text="X")
col.itemR(con, "rotationy", text="Y")
col.itemR(con, "rotationz", text="Z")
sub = split.column()
sub.itemL(text="Scale:")
sub.itemR(con, "sizex", text="X")
sub.itemR(con, "sizey", text="Y")
sub.itemR(con, "sizez", text="Z")
col = split.column()
col.itemL(text="Scale:")
col.itemR(con, "sizex", text="X")
col.itemR(con, "sizey", text="Y")
col.itemR(con, "sizez", text="Z")
row = layout.row()
row.itemO("constraint.childof_set_inverse")
@@ -134,18 +135,18 @@ class ConstraintButtonsPanel(bpy.types.Panel):
if con.pole_target and con.pole_target.type == "ARMATURE":
layout.item_pointerR(con, "pole_subtarget", con.pole_target.data, "bones", text="Bone")
col = layout.column_flow()
col.itemR(con, "iterations")
col.itemR(con, "pole_angle")
col.itemR(con, "weight")
col.itemR(con, "orient_weight")
col.itemR(con, "chain_length")
flow = layout.column_flow()
flow.itemR(con, "iterations")
flow.itemR(con, "pole_angle")
flow.itemR(con, "weight")
flow.itemR(con, "orient_weight")
flow.itemR(con, "chain_length")
col = layout.column_flow()
col.itemR(con, "tail")
col.itemR(con, "rotation")
col.itemR(con, "targetless")
col.itemR(con, "stretch")
flow = layout.column_flow()
flow.itemR(con, "tail")
flow.itemR(con, "rotation")
flow.itemR(con, "targetless")
flow.itemR(con, "stretch")
def follow_path(self, layout, con):
self.target_template(layout, con)
@@ -168,24 +169,24 @@ class ConstraintButtonsPanel(bpy.types.Panel):
col = split.column()
col.itemR(con, "use_limit_x")
colsub = col.column()
colsub.active = con.use_limit_x
colsub.itemR(con, "minimum_x", text="Min")
colsub.itemR(con, "maximum_x", text="Max")
sub = col.column()
sub.active = con.use_limit_x
sub.itemR(con, "minimum_x", text="Min")
sub.itemR(con, "maximum_x", text="Max")
col = split.column()
col.itemR(con, "use_limit_y")
colsub = col.column()
colsub.active = con.use_limit_y
colsub.itemR(con, "minimum_y", text="Min")
colsub.itemR(con, "maximum_y", text="Max")
sub = col.column()
sub.active = con.use_limit_y
sub.itemR(con, "minimum_y", text="Min")
sub.itemR(con, "maximum_y", text="Max")
col = split.column()
col.itemR(con, "use_limit_z")
colsub = col.column()
colsub.active = con.use_limit_z
colsub.itemR(con, "minimum_z", text="Min")
colsub.itemR(con, "maximum_z", text="Max")
sub = col.column()
sub.active = con.use_limit_z
sub.itemR(con, "minimum_z", text="Min")
sub.itemR(con, "maximum_z", text="Max")
row = layout.row()
row.itemR(con, "limit_transform")
@@ -200,33 +201,33 @@ class ConstraintButtonsPanel(bpy.types.Panel):
col = split.column()
col.itemR(con, "use_minimum_x")
colsub = col.column()
colsub.active = con.use_minimum_x
colsub.itemR(con, "minimum_x", text="")
sub = col.column()
sub.active = con.use_minimum_x
sub.itemR(con, "minimum_x", text="")
col.itemR(con, "use_maximum_x")
colsub = col.column()
colsub.active = con.use_maximum_x
colsub.itemR(con, "maximum_x", text="")
sub = col.column()
sub.active = con.use_maximum_x
sub.itemR(con, "maximum_x", text="")
col = split.column()
col.itemR(con, "use_minimum_y")
colsub = col.column()
colsub.active = con.use_minimum_y
colsub.itemR(con, "minimum_y", text="")
sub = col.column()
sub.active = con.use_minimum_y
sub.itemR(con, "minimum_y", text="")
col.itemR(con, "use_maximum_y")
colsub = col.column()
colsub.active = con.use_maximum_y
colsub.itemR(con, "maximum_y", text="")
sub = col.column()
sub.active = con.use_maximum_y
sub.itemR(con, "maximum_y", text="")
col = split.column()
col.itemR(con, "use_minimum_z")
colsub = col.column()
colsub.active = con.use_minimum_z
colsub.itemR(con, "minimum_z", text="")
sub = col.column()
sub.active = con.use_minimum_z
sub.itemR(con, "minimum_z", text="")
col.itemR(con, "use_maximum_z")
colsub = col.column()
colsub.active = con.use_maximum_z
colsub.itemR(con, "maximum_z", text="")
sub = col.column()
sub.active = con.use_maximum_z
sub.itemR(con, "maximum_z", text="")
row = layout.row()
row.itemR(con, "limit_transform")
@@ -241,33 +242,33 @@ class ConstraintButtonsPanel(bpy.types.Panel):
col = split.column()
col.itemR(con, "use_minimum_x")
colsub = col.column()
colsub.active = con.use_minimum_x
colsub.itemR(con, "minimum_x", text="")
sub = col.column()
sub.active = con.use_minimum_x
sub.itemR(con, "minimum_x", text="")
col.itemR(con, "use_maximum_x")
colsub = col.column()
colsub.active = con.use_maximum_x
colsub.itemR(con, "maximum_x", text="")
sub = col.column()
sub.active = con.use_maximum_x
sub.itemR(con, "maximum_x", text="")
col = split.column()
col.itemR(con, "use_minimum_y")
colsub = col.column()
colsub.active = con.use_minimum_y
colsub.itemR(con, "minimum_y", text="")
sub = col.column()
sub.active = con.use_minimum_y
sub.itemR(con, "minimum_y", text="")
col.itemR(con, "use_maximum_y")
colsub = col.column()
colsub.active = con.use_maximum_y
colsub.itemR(con, "maximum_y", text="")
sub = col.column()
sub.active = con.use_maximum_y
sub.itemR(con, "maximum_y", text="")
col = split.column()
col.itemR(con, "use_minimum_z")
colsub = col.column()
colsub.active = con.use_minimum_z
colsub.itemR(con, "minimum_z", text="")
sub = col.column()
sub.active = con.use_minimum_z
sub.itemR(con, "minimum_z", text="")
col.itemR(con, "use_maximum_z")
colsub = col.column()
colsub.active = con.use_maximum_z
colsub.itemR(con, "maximum_z", text="")
sub = col.column()
sub.active = con.use_maximum_z
sub.itemR(con, "maximum_z", text="")
row = layout.row()
row.itemR(con, "limit_transform")
@@ -284,21 +285,21 @@ class ConstraintButtonsPanel(bpy.types.Panel):
col = split.column()
col.itemR(con, "rotate_like_x", text="X")
colsub = col.column()
colsub.active = con.rotate_like_x
colsub.itemR(con, "invert_x", text="Invert")
sub = col.column()
sub.active = con.rotate_like_x
sub.itemR(con, "invert_x", text="Invert")
col = split.column()
col.itemR(con, "rotate_like_y", text="Y")
colsub = col.column()
colsub.active = con.rotate_like_y
colsub.itemR(con, "invert_y", text="Invert")
sub = col.column()
sub.active = con.rotate_like_y
sub.itemR(con, "invert_y", text="Invert")
col = split.column()
col.itemR(con, "rotate_like_z", text="Z")
colsub = col.column()
colsub.active = con.rotate_like_z
colsub.itemR(con, "invert_z", text="Invert")
sub = col.column()
sub.active = con.rotate_like_z
sub.itemR(con, "invert_z", text="Invert")
layout.itemR(con, "offset")
@@ -311,21 +312,21 @@ class ConstraintButtonsPanel(bpy.types.Panel):
col = split.column()
col.itemR(con, "locate_like_x", text="X")
colsub = col.column()
colsub.active = con.locate_like_x
colsub.itemR(con, "invert_x", text="Invert")
sub = col.column()
sub.active = con.locate_like_x
sub.itemR(con, "invert_x", text="Invert")
col = split.column()
col.itemR(con, "locate_like_y", text="Y")
colsub = col.column()
colsub.active = con.locate_like_y
colsub.itemR(con, "invert_y", text="Invert")
sub = col.column()
sub.active = con.locate_like_y
sub.itemR(con, "invert_y", text="Invert")
col = split.column()
col.itemR(con, "locate_like_z", text="Z")
colsub = col.column()
colsub.active = con.locate_like_z
colsub.itemR(con, "invert_z", text="Invert")
sub = col.column()
sub.active = con.locate_like_z
sub.itemR(con, "invert_z", text="Invert")
layout.itemR(con, "offset")
@@ -379,26 +380,29 @@ class ConstraintButtonsPanel(bpy.types.Panel):
def limit_distance(self, layout, con):
self.target_template(layout, con)
layout.itemR(con, "distance")
col = layout.column(align=True);
col.itemR(con, "distance")
col.itemO("constraint.limitdistance_reset")
row = layout.row()
row.itemL(text="Clamp Region:")
row.itemR(con, "limit_mode", text="")
#Missing: Recalculate Button
def stretch_to(self, layout, con):
self.target_template(layout, con)
row = layout.row()
row.itemR(con, "original_length", text="Rest Length")
row.itemR(con, "bulge", text="Volume Variation")
col = layout.column(align=True)
col.itemR(con, "original_length", text="Rest Length")
col.itemO("constraint.stretchto_reset")
col = layout.column()
col.itemR(con, "bulge", text="Volume Variation")
row = layout.row()
row.itemL(text="Volume:")
row.itemR(con, "volume", expand=True)
row.itemL(text="Plane:")
row.itemR(con, "keep_axis", expand=True)
#Missing: Recalculate Button
def floor(self, layout, con):
self.target_template(layout, con)
@@ -509,16 +513,15 @@ class ConstraintButtonsPanel(bpy.types.Panel):
row.itemR(con, "axis_z")
class OBJECT_PT_constraints(ConstraintButtonsPanel):
__idname__ = "OBJECT_PT_constraints"
__label__ = "Constraints"
__context__ = "constraint"
def poll(self, context):
return (context.object != None)
return (context.object)
def draw(self, context):
ob = context.object
layout = self.layout
ob = context.object
row = layout.row()
row.item_menu_enumO("object.constraint_add", "type")
@@ -528,7 +531,6 @@ class OBJECT_PT_constraints(ConstraintButtonsPanel):
self.draw_constraint(con)
class BONE_PT_constraints(ConstraintButtonsPanel):
__idname__ = "BONE_PT_constraints"
__label__ = "Constraints"
__context__ = "bone"
@@ -537,9 +539,10 @@ class BONE_PT_constraints(ConstraintButtonsPanel):
return (ob and ob.type == "ARMATURE" and context.bone)
def draw(self, context):
layout = self.layout
ob = context.object
pchan = ob.pose.pose_channels[context.bone.name]
layout = self.layout
row = layout.row()
row.item_menu_enumO("pose.constraint_add", "type")

View File

@@ -19,7 +19,6 @@ class ParticleButtonsPanel(bpy.types.Panel):
return particle_panel_poll(context)
class PARTICLE_PT_particles(ParticleButtonsPanel):
__idname__= "PARTICLE_PT_particles"
__show_header__ = False
def poll(self, context):
@@ -83,7 +82,6 @@ class PARTICLE_PT_particles(ParticleButtonsPanel):
split.itemR(psys, "reactor_target_particle_system", text="Particle System")
class PARTICLE_PT_emission(ParticleButtonsPanel):
__idname__= "PARTICLE_PT_emission"
__label__ = "Emission"
def poll(self, context):
@@ -135,7 +133,6 @@ class PARTICLE_PT_emission(ParticleButtonsPanel):
row.itemR(part, "grid_resolution")
class PARTICLE_PT_cache(ParticleButtonsPanel):
__idname__= "PARTICLE_PT_cache"
__label__ = "Cache"
__default_closed__ = True
@@ -216,7 +213,6 @@ class PARTICLE_PT_cache(ParticleButtonsPanel):
#row.itemR(cache, "end_frame")
class PARTICLE_PT_initial(ParticleButtonsPanel):
__idname__= "PARTICLE_PT_initial"
__label__ = "Velocity"
def poll(self, context):
@@ -283,7 +279,6 @@ class PARTICLE_PT_initial(ParticleButtonsPanel):
sub.itemR(part, "angular_velocity_factor", text="")
class PARTICLE_PT_physics(ParticleButtonsPanel):
__idname__= "PARTICLE_PT_physics"
__label__ = "Physics"
def poll(self, context):
@@ -427,7 +422,6 @@ class PARTICLE_PT_physics(ParticleButtonsPanel):
layout.itemR(key, "mode", expand=True)
class PARTICLE_PT_boidbrain(ParticleButtonsPanel):
__idname__ = "PARTICLE_PT_boidbrain"
__label__ = "Boid Brain"
def poll(self, context):
@@ -522,7 +516,6 @@ class PARTICLE_PT_boidbrain(ParticleButtonsPanel):
class PARTICLE_PT_render(ParticleButtonsPanel):
__idname__= "PARTICLE_PT_render"
__label__ = "Render"
def poll(self, context):
@@ -664,7 +657,6 @@ class PARTICLE_PT_render(ParticleButtonsPanel):
col.itemL(text="")
class PARTICLE_PT_draw(ParticleButtonsPanel):
__idname__= "PARTICLE_PT_draw"
__label__ = "Display"
__default_closed__ = True
@@ -721,7 +713,6 @@ class PARTICLE_PT_draw(ParticleButtonsPanel):
#subcol.itemL(text="Override material color")
class PARTICLE_PT_children(ParticleButtonsPanel):
__idname__= "PARTICLE_PT_children"
__label__ = "Children"
__default_closed__ = True
@@ -798,7 +789,6 @@ class PARTICLE_PT_children(ParticleButtonsPanel):
sub.itemR(part, "kink_shape", slider=True)
class PARTICLE_PT_effectors(ParticleButtonsPanel):
__idname__= "PARTICLE_PT_effectors"
__label__ = "Effectors"
__default_closed__ = True
@@ -824,7 +814,6 @@ class PARTICLE_PT_effectors(ParticleButtonsPanel):
layout.itemR(part, "eweight_lennardjones", slider=True)
class PARTICLE_PT_vertexgroups(ParticleButtonsPanel):
__idname__= "PARTICLE_PT_vertexgroups"
__label__ = "Vertexgroups"
__default_closed__ = True

View File

@@ -12,7 +12,6 @@ class PhysicButtonsPanel(bpy.types.Panel):
return (ob and ob.type == 'MESH') and (not rd.use_game_engine)
class PHYSICS_PT_cloth(PhysicButtonsPanel):
__idname__ = "PHYSICS_PT_cloth"
__label__ = "Cloth"
def draw(self, context):
@@ -76,7 +75,6 @@ class PHYSICS_PT_cloth(PhysicButtonsPanel):
"""
class PHYSICS_PT_cloth_cache(PhysicButtonsPanel):
__idname__= "PHYSICS_PT_cloth_cache"
__label__ = "Cloth Cache"
__default_closed__ = True
@@ -126,7 +124,6 @@ class PHYSICS_PT_cloth_cache(PhysicButtonsPanel):
layout.itemO("ptcache.bake_all", text="Update All Dynamics to current frame")
class PHYSICS_PT_cloth_collision(PhysicButtonsPanel):
__idname__ = "PHYSICS_PT_clothcollision"
__label__ = "Cloth Collision"
__default_closed__ = True
@@ -159,7 +156,6 @@ class PHYSICS_PT_cloth_collision(PhysicButtonsPanel):
col.itemR(cloth, "self_min_distance", slider=True, text="Distance")
class PHYSICS_PT_cloth_stiffness(PhysicButtonsPanel):
__idname__ = "PHYSICS_PT_stiffness"
__label__ = "Cloth Stiffness Scaling"
__default_closed__ = True
@@ -197,4 +193,3 @@ bpy.types.register(PHYSICS_PT_cloth)
bpy.types.register(PHYSICS_PT_cloth_cache)
bpy.types.register(PHYSICS_PT_cloth_collision)
bpy.types.register(PHYSICS_PT_cloth_stiffness)

View File

@@ -11,12 +11,12 @@ class PhysicButtonsPanel(bpy.types.Panel):
return (context.object != None) and (not rd.use_game_engine)
class PHYSICS_PT_field(PhysicButtonsPanel):
__idname__ = "PHYSICS_PT_field"
__label__ = "Force Fields"
__default_closed__ = True
def draw(self, context):
layout = self.layout
ob = context.object
field = ob.field
@@ -25,65 +25,67 @@ class PHYSICS_PT_field(PhysicButtonsPanel):
split = layout.split(percentage=0.3)
split.itemL(text="Type:")
split.itemR(field, "type", text=""
)
split.itemR(field, "type", text="")
split = layout.split()
sub = split.column()
col = split.column()
if field.type == "GUIDE":
sub = col.column()
sub.itemR(field, "guide_path_add")
col.itemR(field, "guide_path_add")
if field.type == "WIND":
sub.itemR(field, "strength")
sub = split.column()
sub.itemR(field, "noise")
sub.itemR(field, "seed")
elif field.type == "WIND":
col.itemR(field, "strength")
col = split.column()
col.itemR(field, "noise")
col.itemR(field, "seed")
if field.type == "VORTEX":
sub.itemR(field, "strength")
sub = split.column()
sub.itemL(text="")
elif field.type == "VORTEX":
col.itemR(field, "strength")
col = split.column()
col.itemL(text="")
if field.type in ("SPHERICAL", "CHARGE", "LENNARDJ"):
sub.itemR(field, "strength")
sub = split.column()
sub.itemR(field, "planar")
sub.itemR(field, "surface")
elif field.type in ("SPHERICAL", "CHARGE", "LENNARDJ"):
col.itemR(field, "strength")
if field.type == "BOID":
sub.itemR(field, "strength")
sub = split.column()
sub.itemR(field, "surface")
col = split.column()
col.itemR(field, "planar")
col.itemR(field, "surface")
if field.type == "MAGNET":
sub.itemR(field, "strength")
sub = split.column()
sub.itemR(field, "planar")
elif field.type == "BOID":
col.itemR(field, "strength")
if field.type == "HARMONIC":
sub.itemR(field, "strength")
sub.itemR(field, "harmonic_damping", text="Damping")
sub = split.column()
sub.itemR(field, "surface")
sub.itemR(field, "planar")
col = split.column()
col.itemR(field, "surface")
if field.type == "TEXTURE":
sub.itemR(field, "strength")
sub.itemR(field, "texture", text="")
sub.itemR(field, "texture_mode")
sub.itemR(field, "texture_nabla")
sub = split.column()
sub.itemR(field, "use_coordinates")
sub.itemR(field, "root_coordinates")
sub.itemR(field, "force_2d")
elif field.type == "MAGNET":
col.itemR(field, "strength")
col = split.column()
col.itemR(field, "planar")
elif field.type == "HARMONIC":
col.itemR(field, "strength")
col.itemR(field, "harmonic_damping", text="Damping")
col = split.column()
col.itemR(field, "surface")
col.itemR(field, "planar")
elif field.type == "TEXTURE":
col.itemR(field, "strength")
col.itemR(field, "texture", text="")
col.itemR(field, "texture_mode")
col.itemR(field, "texture_nabla")
col = split.column()
col.itemR(field, "use_coordinates")
col.itemR(field, "root_coordinates")
col.itemR(field, "force_2d")
if field.type in ("HARMONIC", "SPHERICAL", "CHARGE", "WIND", "VORTEX", "TEXTURE", "MAGNET", "BOID"):
layout.itemS()
layout.itemL(text="Falloff:")
layout.itemR(field, "falloff_type", expand=True)
@@ -94,19 +96,18 @@ class PHYSICS_PT_field(PhysicButtonsPanel):
layout.itemS()
split = layout.split()
sub = split.column()
sub.itemR(field, "use_min_distance", text="Minimum")
colsub1 = sub.column()
colsub1.active = field.use_min_distance
colsub1.itemR(field, "minimum_distance", text="Distance")
col = split.column()
col.itemR(field, "use_min_distance", text="Minimum")
sub = col.column()
sub.active = field.use_min_distance
sub.itemR(field, "minimum_distance", text="Distance")
sub = split.column()
sub.itemR(field, "use_max_distance", text="Maximum")
colsub2 = sub.column()
colsub2.active = field.use_max_distance
colsub2.itemR(field, "maximum_distance", text="Distance")
col = split.column()
col.itemR(field, "use_max_distance", text="Maximum")
sub = col.column()
sub.active = field.use_max_distance
sub.itemR(field, "maximum_distance", text="Distance")
if field.falloff_type == "CONE":
layout.itemS()
@@ -114,45 +115,43 @@ class PHYSICS_PT_field(PhysicButtonsPanel):
row = layout.row()
row.itemR(field, "radial_falloff", text="Power")
row.itemL(text="")
row.itemL()
split = layout.split()
sub = split.column()
sub.itemR(field, "use_radial_min", text="Minimum")
colsub1 = sub.column()
colsub1.active = field.use_radial_min
colsub1.itemR(field, "radial_minimum", text="Angle")
col = split.column()
col.itemR(field, "use_radial_min", text="Minimum")
sub = col.column()
sub.active = field.use_radial_min
sub.itemR(field, "radial_minimum", text="Angle")
sub = split.column()
sub.itemR(field, "use_radial_max", text="Maximum")
colsub2 = sub.column()
colsub2.active = field.use_radial_max
colsub2.itemR(field, "radial_maximum", text="Angle")
if field.falloff_type == "TUBE":
col = split.column()
col.itemR(field, "use_radial_max", text="Maximum")
sub = col.column()
sub.active = field.use_radial_max
sub.itemR(field, "radial_maximum", text="Angle")
elif field.falloff_type == "TUBE":
layout.itemS()
layout.itemL(text="Radial:")
row = layout.row()
row.itemR(field, "radial_falloff", text="Power")
row.itemL(text="")
row.itemL()
split = layout.split()
sub = split.column()
sub.itemR(field, "use_radial_min", text="Minimum")
colsub1 = sub.column()
colsub1.active = field.use_radial_min
colsub1.itemR(field, "radial_minimum", text="Distance")
col = split.column()
col.itemR(field, "use_radial_min", text="Minimum")
sub = col.column()
sub.active = field.use_radial_min
sub.itemR(field, "radial_minimum", text="Distance")
sub = split.column()
sub.itemR(field, "use_radial_max", text="Maximum")
colsub2 = sub.column()
colsub2.active = field.use_radial_max
colsub2.itemR(field, "radial_maximum", text="Distance")
col = split.column()
col.itemR(field, "use_radial_max", text="Maximum")
sub = col.column()
sub.active = field.use_radial_max
sub.itemR(field, "radial_maximum", text="Distance")
#if ob.type in "CURVE":
#if field.type == "GUIDE":
@@ -166,7 +165,6 @@ class PHYSICS_PT_field(PhysicButtonsPanel):
#layout.itemR(field, "surface")
class PHYSICS_PT_collision(PhysicButtonsPanel):
__idname__ = "PHYSICS_PT_collision"
__label__ = "Collision"
__default_closed__ = True
@@ -181,6 +179,7 @@ class PHYSICS_PT_collision(PhysicButtonsPanel):
def draw(self, context):
layout = self.layout
md = context.collision
settings = context.object.collision
@@ -192,25 +191,25 @@ class PHYSICS_PT_collision(PhysicButtonsPanel):
col.itemL(text="Particle:")
col.itemR(settings, "permeability", slider=True)
col.itemL(text="Particle Damping:")
colsub = col.column(align=True)
colsub.itemR(settings, "damping_factor", text="Factor", slider=True)
colsub.itemR(settings, "random_damping", text="Random", slider=True)
sub = col.column(align=True)
sub.itemR(settings, "damping_factor", text="Factor", slider=True)
sub.itemR(settings, "random_damping", text="Random", slider=True)
col.itemL(text="Soft Body and Cloth:")
colsub = col.column(align=True)
colsub.itemR(settings, "outer_thickness", text="Outer", slider=True)
colsub.itemR(settings, "inner_thickness", text="Inner", slider=True)
sub = col.column(align=True)
sub.itemR(settings, "outer_thickness", text="Outer", slider=True)
sub.itemR(settings, "inner_thickness", text="Inner", slider=True)
col.itemL(text="Force Fields:")
layout.itemL(text="Force Fields:")
layout.itemR(md, "absorption", text="Absorption")
col = split.column()
col.itemL(text="")
col.itemR(settings, "kill_particles")
col.itemL(text="Particle Friction:")
colsub = col.column(align=True)
colsub.itemR(settings, "friction_factor", text="Factor", slider=True)
colsub.itemR(settings, "random_friction", text="Random", slider=True)
sub = col.column(align=True)
sub.itemR(settings, "friction_factor", text="Factor", slider=True)
sub.itemR(settings, "random_friction", text="Random", slider=True)
col.itemL(text="Soft Body Damping:")
col.itemR(settings, "damping", text="Factor", slider=True)

View File

@@ -12,11 +12,11 @@ class PhysicButtonsPanel(bpy.types.Panel):
return (ob and ob.type == 'MESH') and (not rd.use_game_engine)
class PHYSICS_PT_fluid(PhysicButtonsPanel):
__idname__ = "PHYSICS_PT_fluid"
__label__ = "Fluid"
def draw(self, context):
layout = self.layout
md = context.fluid
ob = context.object
@@ -43,9 +43,7 @@ class PHYSICS_PT_fluid(PhysicButtonsPanel):
if fluid:
col = layout.column(align=True)
col.itemR(fluid, "type")
layout.itemR(fluid, "type")
if fluid.type == 'DOMAIN':
layout.itemO("fluid.bake", text="BAKE")
@@ -53,56 +51,58 @@ class PHYSICS_PT_fluid(PhysicButtonsPanel):
col = split.column()
col.itemL(text="Resolution:")
colsub = col.column()
colsub.itemR(fluid, "resolution", text="Final")
colsub.itemL(text="Render Display:")
colsub.itemR(fluid, "render_display_mode", text="")
sub = col.column()
sub.itemR(fluid, "resolution", text="Final")
sub.itemL(text="Render Display:")
sub.itemR(fluid, "render_display_mode", text="")
col.itemL(text="Time:")
colsub = col.column(align=True)
colsub.itemR(fluid, "start_time", text="Start")
colsub.itemR(fluid, "end_time", text="End")
sub = col.column(align=True)
sub.itemR(fluid, "start_time", text="Start")
sub.itemR(fluid, "end_time", text="End")
col = split.column()
colsub = col.column()
colsub.itemL(text="Required Memory: " + fluid.memory_estimate)
colsub.itemR(fluid, "preview_resolution", text="Preview")
colsub.itemL(text="Viewport Display:")
colsub.itemR(fluid, "viewport_display_mode", text="")
colsub = col.column()
colsub.itemL(text="")
colsub.itemR(fluid, "reverse_frames")
colsub.itemR(fluid, "generate_speed_vectors")
col.itemL(text="Required Memory: " + fluid.memory_estimate)
col.itemR(fluid, "preview_resolution", text="Preview")
col.itemL(text="Viewport Display:")
col.itemR(fluid, "viewport_display_mode", text="")
col.itemL()
col.itemR(fluid, "reverse_frames")
col.itemR(fluid, "generate_speed_vectors")
layout.itemL(text="Path:")
layout.itemR(fluid, "path", text="")
if fluid.type == 'FLUID':
elif fluid.type == 'FLUID':
split = layout.split()
col = split.column()
col.itemL(text="Volume Initialization:")
col.itemR(fluid, "volume_initialization", text="")
col.itemR(fluid, "export_animated_mesh")
col = split.column()
col.itemL(text="Initial Velocity:")
col.itemR(fluid, "initial_velocity", text="")
if fluid.type == 'OBSTACLE':
elif fluid.type == 'OBSTACLE':
split = layout.split()
col = split.column()
col.itemL(text="Volume Initialization:")
col.itemR(fluid, "volume_initialization", text="")
col.itemR(fluid, "export_animated_mesh")
col = split.column()
col.itemL(text="Slip Type:")
colsub=col.column(align=True)
colsub.itemR(fluid, "slip_type", text="")
sub = col.column(align=True)
sub.itemR(fluid, "slip_type", text="")
if fluid.slip_type == 'PARTIALSLIP':
colsub.itemR(fluid, "partial_slip_amount", slider=True, text="Amount")
sub.itemR(fluid, "partial_slip_amount", slider=True, text="Amount")
col.itemR(fluid, "impact_factor")
if fluid.type == 'INFLOW':
elif fluid.type == 'INFLOW':
split = layout.split()
col = split.column()
col.itemL(text="Volume Initialization:")
col.itemR(fluid, "volume_initialization", text="")
@@ -113,23 +113,24 @@ class PHYSICS_PT_fluid(PhysicButtonsPanel):
col.itemL(text="Inflow Velocity:")
col.itemR(fluid, "inflow_velocity", text="")
if fluid.type == 'OUTFLOW':
elif fluid.type == 'OUTFLOW':
split = layout.split()
col = split.column()
col.itemL(text="Volume Initialization:")
col.itemR(fluid, "volume_initialization", text="")
col.itemR(fluid, "export_animated_mesh")
col = split.column()
if fluid.type == 'PARTICLE':
split.column()
elif fluid.type == 'PARTICLE':
split = layout.split()
col = split.column()
col.itemL(text="Influence:")
colsub = col.column(align=True)
colsub.itemR(fluid, "particle_influence", text="Size")
colsub.itemR(fluid, "alpha_influence", text="Alpha")
col.itemL(text="Path:")
sub = col.column(align=True)
sub.itemR(fluid, "particle_influence", text="Size")
sub.itemR(fluid, "alpha_influence", text="Alpha")
layout.itemR(fluid, "path", text="")
@@ -139,7 +140,7 @@ class PHYSICS_PT_fluid(PhysicButtonsPanel):
col.itemR(fluid, "floats")
col.itemR(fluid, "tracer")
if fluid.type == 'CONTROL':
elif fluid.type == 'CONTROL':
split = layout.split()
col = split.column()
@@ -149,26 +150,25 @@ class PHYSICS_PT_fluid(PhysicButtonsPanel):
col = split.column()
col.itemL(text="Time:")
col=col.column(align=True)
col.itemR(fluid, "start_time", text="Start")
col.itemR(fluid, "end_time", text="End")
sub = col.column(align=True)
sub.itemR(fluid, "start_time", text="Start")
sub.itemR(fluid, "end_time", text="End")
split = layout.split()
col = split.column()
col.itemL(text="Attraction Force:")
col=col.column(align=True)
col.itemR(fluid, "attraction_strength", text="Strength")
col.itemR(fluid, "attraction_radius", text="Radius")
sub = col.column(align=True)
sub.itemR(fluid, "attraction_strength", text="Strength")
sub.itemR(fluid, "attraction_radius", text="Radius")
col = split.column()
col.itemL(text="Velocity Force:")
col=col.column(align=True)
col.itemR(fluid, "velocity_strength", text="Strength")
col.itemR(fluid, "velocity_radius", text="Radius")
sub = col.column(align=True)
sub.itemR(fluid, "velocity_strength", text="Strength")
sub.itemR(fluid, "velocity_radius", text="Radius")
class PHYSICS_PT_domain_gravity(PhysicButtonsPanel):
__idname__ = "PHYSICS_PT_domain_gravity"
__label__ = "Domain World"
__default_closed__ = True
@@ -183,6 +183,7 @@ class PHYSICS_PT_domain_gravity(PhysicButtonsPanel):
def draw(self, context):
layout = self.layout
fluid = context.fluid.settings
split = layout.split()
@@ -190,29 +191,27 @@ class PHYSICS_PT_domain_gravity(PhysicButtonsPanel):
col = split.column()
col.itemL(text="Gravity:")
col.itemR(fluid, "gravity", text="")
col.itemL(text="Real World Size:")
col.itemR(fluid, "real_world_size", text="Metres")
col = split.column()
col.itemL(text="Viscosity Presets:")
colsub=col.column(align=True)
colsub.itemR(fluid, "viscosity_preset", text="")
sub = col.column(align=True)
sub.itemR(fluid, "viscosity_preset", text="")
if fluid.viscosity_preset == 'MANUAL':
colsub.itemR(fluid, "viscosity_base", text="Base")
colsub.itemR(fluid, "viscosity_exponent", text="Exponent", slider=True)
sub.itemR(fluid, "viscosity_base", text="Base")
sub.itemR(fluid, "viscosity_exponent", text="Exponent", slider=True)
else:
colsub.itemL(text="")
colsub.itemL(text="")
sub.itemL()
sub.itemL()
col.itemL(text="Optimization:")
col=col.column(align=True)
col.itemR(fluid, "grid_levels", slider=True)
col.itemR(fluid, "compressibility", slider=True)
sub = col.column(align=True)
sub.itemR(fluid, "grid_levels", slider=True)
sub.itemR(fluid, "compressibility", slider=True)
class PHYSICS_PT_domain_boundary(PhysicButtonsPanel):
__idname__ = "PHYSICS_PT_domain_boundary"
__label__ = "Domain Boundary"
__default_closed__ = True
@@ -227,23 +226,25 @@ class PHYSICS_PT_domain_boundary(PhysicButtonsPanel):
def draw(self, context):
layout = self.layout
fluid = context.fluid.settings
split = layout.split()
col = split.column()
col.itemL(text="Slip Type:")
col=col.column(align=True)
col.itemR(fluid, "slip_type", text="")
sub = col.column(align=True)
sub.itemR(fluid, "slip_type", text="")
if fluid.slip_type == 'PARTIALSLIP':
col.itemR(fluid, "partial_slip_amount", slider=True, text="Amount")
sub.itemR(fluid, "partial_slip_amount", slider=True, text="Amount")
col = split.column()
col.itemL(text="Surface:")
col=col.column(align=True)
col.itemR(fluid, "surface_smoothing", text="Smoothing")
col.itemR(fluid, "surface_subdivisions", text="Subdivisions")
sub = col.column(align=True)
sub.itemR(fluid, "surface_smoothing", text="Smoothing")
sub.itemR(fluid, "surface_subdivisions", text="Subdivisions")
class PHYSICS_PT_domain_particles(PhysicButtonsPanel):
__idname__ = "PHYSICS_PT_domain_particles"
__label__ = "Domain Particles"
__default_closed__ = True
@@ -258,9 +259,10 @@ class PHYSICS_PT_domain_particles(PhysicButtonsPanel):
def draw(self, context):
layout = self.layout
fluid = context.fluid.settings
col=layout.column(align=True)
col = layout.column(align=True)
col.itemR(fluid, "tracer_particles")
col.itemR(fluid, "generate_particles")

View File

@@ -12,11 +12,11 @@ class PhysicButtonsPanel(bpy.types.Panel):
return (ob and ob.type == 'MESH') and (not rd.use_game_engine)
class PHYSICS_PT_softbody(PhysicButtonsPanel):
__idname__ = "PHYSICS_PT_softbody"
__label__ = "Soft Body"
def draw(self, context):
layout = self.layout
md = context.soft_body
ob = context.object
@@ -51,23 +51,23 @@ class PHYSICS_PT_softbody(PhysicButtonsPanel):
col.itemL(text="Simulation:")
col.itemR(softbody, "gravity")
col.itemR(softbody, "speed")
class PHYSICS_PT_softbody_goal(PhysicButtonsPanel):
__idname__ = "PHYSICS_PT_softbody_goal"
__label__ = "Soft Body Goal"
def poll(self, context):
return (context.soft_body != None)
return (context.soft_body)
def draw_header(self, context):
layout = self.layout
softbody = context.soft_body.settings
layout.itemR(softbody, "use_goal", text="")
def draw(self, context):
layout = self.layout
md = context.soft_body
ob = context.object
@@ -83,35 +83,35 @@ class PHYSICS_PT_softbody_goal(PhysicButtonsPanel):
col = split.column()
col.itemL(text="Goal Strengths:")
col.itemR(softbody, "goal_default", text="Default")
subcol = col.column(align=True)
subcol.itemR(softbody, "goal_min", text="Minimum")
subcol.itemR(softbody, "goal_max", text="Maximum")
sub = col.column(align=True)
sub.itemR(softbody, "goal_min", text="Minimum")
sub.itemR(softbody, "goal_max", text="Maximum")
col = split.column()
col.itemL(text="Goal Settings:")
col.itemR(softbody, "goal_spring", text="Stiffness")
col.itemR(softbody, "goal_friction", text="Damping")
layout.item_pointerR(softbody, "goal_vertex_group", ob, "vertex_groups", text="Vertex Group")
class PHYSICS_PT_softbody_edge(PhysicButtonsPanel):
__idname__ = "PHYSICS_PT_softbody_edge"
__label__ = "Soft Body Edges"
def poll(self, context):
return (context.soft_body != None)
return (context.soft_body)
def draw_header(self, context):
layout = self.layout
softbody = context.soft_body.settings
layout.itemR(softbody, "use_edges", text="")
def draw(self, context):
layout = self.layout
md = context.soft_body
ob = context.object
split = layout.split()
if md:
softbody = md.settings
@@ -131,43 +131,43 @@ class PHYSICS_PT_softbody_edge(PhysicButtonsPanel):
col = split.column()
col.itemR(softbody, "stiff_quads")
subcol = col.column()
subcol.active = softbody.stiff_quads
subcol.itemR(softbody, "shear")
sub = col.column()
sub.active = softbody.stiff_quads
sub.itemR(softbody, "shear")
col.itemR(softbody, "new_aero", text="Aero")
subcol = col.column()
subcol.enabled = softbody.new_aero
subcol.itemR(softbody, "aero", text="Factor")
sub = col.column()
sub.enabled = softbody.new_aero
sub.itemR(softbody, "aero", text="Factor")
col.itemL(text="Collision:")
col.itemR(softbody, "edge_collision", text="Edge")
col.itemR(softbody, "face_collision", text="Face")
class PHYSICS_PT_softbody_collision(PhysicButtonsPanel):
__idname__ = "PHYSICS_PT_softbody_collision"
__label__ = "Soft Body Collision"
def poll(self, context):
return (context.soft_body != None)
return (context.soft_body)
def draw_header(self, context):
layout = self.layout
softbody = context.soft_body.settings
layout.itemR(softbody, "self_collision", text="")
def draw(self, context):
layout = self.layout
md = context.soft_body
ob = context.object
split = layout.split()
if md:
softbody = md.settings
layout.active = softbody.self_collision
layout.itemL(text="Collision Type:")
layout.itemR(softbody, "collision_type", expand=True)
@@ -178,19 +178,17 @@ class PHYSICS_PT_softbody_collision(PhysicButtonsPanel):
col.itemR(softbody, "ball_damp", text="Dampening")
class PHYSICS_PT_softbody_solver(PhysicButtonsPanel):
__idname__ = "PHYSICS_PT_softbody_solver"
__label__ = "Soft Body Solver"
def poll(self, context):
return (context.soft_body != None)
return (context.soft_body)
def draw(self, context):
layout = self.layout
md = context.soft_body
ob = context.object
split = layout.split()
if md:
softbody = md.settings
@@ -205,7 +203,6 @@ class PHYSICS_PT_softbody_solver(PhysicButtonsPanel):
col = split.column()
col.itemR(softbody, "error_limit")
col.itemL(text="Helpers:")
col.itemR(softbody, "choke")
col.itemR(softbody, "fuzzy")

View File

@@ -5,30 +5,35 @@ class RenderButtonsPanel(bpy.types.Panel):
__space_type__ = "BUTTONS_WINDOW"
__region_type__ = "WINDOW"
__context__ = "scene"
# COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
def poll(self, context):
rd = context.scene.render_data
return (not rd.use_game_engine)
return (rd.use_game_engine==False) and (rd.engine in self.COMPAT_ENGINES)
class SCENE_PT_render(RenderButtonsPanel):
__label__ = "Render"
COMPAT_ENGINES = set(['BLENDER_RENDER'])
def draw(self, context):
layout = self.layout
rd = context.scene.render_data
row = layout.row()
row.itemO("screen.render", text="Image", icon='ICON_IMAGE_COL')
row.item_booleanO("screen.render", "animation", True, text="Animation", icon='ICON_SEQUENCE')
row.itemO("screen.render", text="Image", icon='ICON_RENDER_RESULT')
row.item_booleanO("screen.render", "animation", True, text="Animation", icon='ICON_RENDER_ANIMATION')
layout.itemR(rd, "display_mode", text="Display")
class SCENE_PT_layers(RenderButtonsPanel):
__label__ = "Layers"
__default_closed__ = True
COMPAT_ENGINES = set(['BLENDER_RENDER'])
def draw(self, context):
layout = self.layout
scene = context.scene
rd = scene.render_data
@@ -42,6 +47,7 @@ class SCENE_PT_layers(RenderButtonsPanel):
rl = rd.layers[rd.active_layer_index]
split = layout.split()
col = split.column()
col.itemR(scene, "visible_layers", text="Scene")
col = split.column()
@@ -52,6 +58,7 @@ class SCENE_PT_layers(RenderButtonsPanel):
layout.itemS()
layout.itemL(text="Include:")
split = layout.split()
col = split.column()
@@ -79,6 +86,7 @@ class SCENE_PT_layers(RenderButtonsPanel):
layout.itemS()
split = layout.split()
col = split.column()
col.itemL(text="Passes:")
col.itemR(rl, "pass_combined")
@@ -111,9 +119,11 @@ class SCENE_PT_layers(RenderButtonsPanel):
class SCENE_PT_shading(RenderButtonsPanel):
__label__ = "Shading"
COMPAT_ENGINES = set(['BLENDER_RENDER'])
def draw(self, context):
layout = self.layout
rd = context.scene.render_data
split = layout.split()
@@ -132,9 +142,11 @@ class SCENE_PT_shading(RenderButtonsPanel):
class SCENE_PT_performance(RenderButtonsPanel):
__label__ = "Performance"
__default_closed__ = True
COMPAT_ENGINES = set(['BLENDER_RENDER'])
def draw(self, context):
layout = self.layout
rd = context.scene.render_data
split = layout.split()
@@ -142,16 +154,14 @@ class SCENE_PT_performance(RenderButtonsPanel):
col = split.column(align=True)
col.itemL(text="Threads:")
col.row().itemR(rd, "threads_mode", expand=True)
colsub = col.column()
colsub.enabled = rd.threads_mode == 'THREADS_FIXED'
colsub.itemR(rd, "threads")
sub = col.column()
sub.enabled = rd.threads_mode == 'THREADS_FIXED'
sub.itemR(rd, "threads")
col = split.column()
sub = col.column(align=True)
sub.itemL(text="Tiles:")
sub.itemR(rd, "parts_x", text="X")
sub.itemR(rd, "parts_y", text="Y")
col = split.column(align=True)
col.itemL(text="Tiles:")
col.itemR(rd, "parts_x", text="X")
col.itemR(rd, "parts_y", text="Y")
split = layout.split()
@@ -162,21 +172,22 @@ class SCENE_PT_performance(RenderButtonsPanel):
row.enabled = not rd.full_sample
col = split.column()
col.active = rd.use_compositing
col.itemL()
col.itemR(rd, "free_image_textures")
col.active = rd.use_compositing
row = layout.row()
row.active = rd.render_raytracing
row.itemR(rd, "octree_resolution", text="Ray Tracing Octree")
class SCENE_PT_post_processing(RenderButtonsPanel):
__label__ = "Post Processing"
__default_closed__ = True
COMPAT_ENGINES = set(['BLENDER_RENDER'])
def draw(self, context):
layout = self.layout
rd = context.scene.render_data
split = layout.split()
@@ -188,12 +199,12 @@ class SCENE_PT_post_processing(RenderButtonsPanel):
col = split.column()
row = col.row()
row.itemR(rd, "fields", text="Fields")
rowsub = row.row()
rowsub.active = rd.fields
rowsub.itemR(rd, "fields_still", text="Still")
rowsub = col.row()
rowsub.active = rd.fields
rowsub.itemR(rd, "field_order", expand=True)
sub = row.row()
sub.active = rd.fields
sub.itemR(rd, "fields_still", text="Still")
sub = col.row()
sub.active = rd.fields
sub.itemR(rd, "field_order", expand=True)
split = layout.split()
split.itemL()
@@ -201,9 +212,11 @@ class SCENE_PT_post_processing(RenderButtonsPanel):
class SCENE_PT_output(RenderButtonsPanel):
__label__ = "Output"
COMPAT_ENGINES = set(['BLENDER_RENDER'])
def draw(self, context):
layout = self.layout
rd = context.scene.render_data
layout.itemR(rd, "output_path", text="")
@@ -224,6 +237,7 @@ class SCENE_PT_output(RenderButtonsPanel):
elif rd.file_format == 'OPENEXR':
split = layout.split()
col = split.column()
col.itemR(rd, "exr_codec")
@@ -263,6 +277,7 @@ class SCENE_PT_output(RenderButtonsPanel):
class SCENE_PT_encoding(RenderButtonsPanel):
__label__ = "Encoding"
__default_closed__ = True
COMPAT_ENGINES = set(['BLENDER_RENDER'])
def poll(self, context):
rd = context.scene.render_data
@@ -270,9 +285,11 @@ class SCENE_PT_encoding(RenderButtonsPanel):
def draw(self, context):
layout = self.layout
rd = context.scene.render_data
split = layout.split()
split.itemR(rd, "ffmpeg_format")
if rd.ffmpeg_format in ('AVI', 'QUICKTIME', 'MKV', 'OGG'):
split.itemR(rd, "ffmpeg_codec")
@@ -309,15 +326,18 @@ class SCENE_PT_encoding(RenderButtonsPanel):
class SCENE_PT_antialiasing(RenderButtonsPanel):
__label__ = "Anti-Aliasing"
COMPAT_ENGINES = set(['BLENDER_RENDER'])
def draw_header(self, context):
layout = self.layout
rd = context.scene.render_data
layout.itemR(rd, "antialiasing", text="")
def draw(self, context):
layout = self.layout
rd = context.scene.render_data
layout.active = rd.antialiasing
@@ -334,6 +354,7 @@ class SCENE_PT_antialiasing(RenderButtonsPanel):
class SCENE_PT_dimensions(RenderButtonsPanel):
__label__ = "Dimensions"
COMPAT_ENGINES = set(['BLENDER_RENDER'])
def draw(self, context):
layout = self.layout
@@ -373,15 +394,18 @@ class SCENE_PT_dimensions(RenderButtonsPanel):
class SCENE_PT_stamp(RenderButtonsPanel):
__label__ = "Stamp"
__default_closed__ = True
COMPAT_ENGINES = set(['BLENDER_RENDER'])
def draw_header(self, context):
layout = self.layout
rd = context.scene.render_data
layout = self.layout
layout.itemR(rd, "render_stamp", text="")
def draw(self, context):
layout = self.layout
rd = context.scene.render_data
layout.active = rd.render_stamp
@@ -398,17 +422,17 @@ class SCENE_PT_stamp(RenderButtonsPanel):
col.itemR(rd, "stamp_marker", text="Marker")
col.itemR(rd, "stamp_sequence_strip", text="Seq. Strip")
sub = split.column()
sub.active = rd.render_stamp
sub.itemR(rd, "stamp_foreground", slider=True)
sub.itemR(rd, "stamp_background", slider=True)
sub.itemR(rd, "stamp_font_size", text="Font Size")
col = split.column()
col.active = rd.render_stamp
col.itemR(rd, "stamp_foreground", slider=True)
col.itemR(rd, "stamp_background", slider=True)
col.itemR(rd, "stamp_font_size", text="Font Size")
row = layout.split(percentage=0.2)
row.itemR(rd, "stamp_note", text="Note")
rowsub = row.row()
rowsub.active = rd.stamp_note
rowsub.itemR(rd, "stamp_note_text", text="")
sub = row.row()
sub.active = rd.stamp_note
sub.itemR(rd, "stamp_note_text", text="")
bpy.types.register(SCENE_PT_render)
bpy.types.register(SCENE_PT_layers)
@@ -420,4 +444,3 @@ bpy.types.register(SCENE_PT_encoding)
bpy.types.register(SCENE_PT_performance)
bpy.types.register(SCENE_PT_post_processing)
bpy.types.register(SCENE_PT_stamp)

View File

@@ -48,26 +48,26 @@ class TEXTURE_PT_context_texture(TextureButtonsPanel):
wo = context.world
br = context.brush
space = context.space_data
slot = context.texture_slot
if ma or la or wo or br:
if ma:
id = ma
elif la:
id = la
elif wo:
id = wo
elif br:
id = br
else:
id = None
if id:
row = layout.row()
if ma:
row.template_list(ma, "textures", ma, "active_texture_index", type="ICONS")
elif la:
row.template_list(la, "textures", la, "active_texture_index", type="ICONS")
elif wo:
row.template_list(wo, "textures", wo, "active_texture_index", type="ICONS")
elif br:
row.template_list(br, "textures", br, "active_texture_index", type="ICONS")
row.template_list(id, "textures", id, "active_texture_index", type="ICONS")
split = layout.split(percentage=0.65)
if ma or la or wo or br:
if slot:
split.template_ID(slot, "texture", new="texture.new")
else:
split.itemS()
if id:
split.template_ID(id, "active_texture", new="texture.new")
elif tex:
split.template_ID(space, "pin_id")
@@ -75,8 +75,6 @@ class TEXTURE_PT_context_texture(TextureButtonsPanel):
(context.sculpt_object or context.vertex_paint_object or \
context.weight_paint_object or context.texture_paint_object):
split.itemR(space, "brush_texture", text="Brush", toggle=True)
else:
split.itemS()
layout.itemS()

View File

@@ -5,14 +5,16 @@ class WorldButtonsPanel(bpy.types.Panel):
__space_type__ = "BUTTONS_WINDOW"
__region_type__ = "WINDOW"
__context__ = "world"
# COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
def poll(self, context):
rd = context.scene.render_data
return (context.world != None) and (not rd.use_game_engine)
return (context.world != None) and (not rd.use_game_engine) and (rd.engine in self.COMPAT_ENGINES)
class WORLD_PT_preview(WorldButtonsPanel):
__label__ = "Preview"
COMPAT_ENGINES = set(['BLENDER_RENDER'])
def draw(self, context):
layout = self.layout
world = context.world
@@ -21,10 +23,11 @@ class WORLD_PT_preview(WorldButtonsPanel):
class WORLD_PT_context_world(WorldButtonsPanel):
__show_header__ = False
COMPAT_ENGINES = set(['BLENDER_RENDER'])
def poll(self, context):
rd = context.scene.render_data
return (context.scene != None) and (not rd.use_game_engine)
return (not rd.use_game_engine) and (rd.engine in self.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
@@ -42,6 +45,7 @@ class WORLD_PT_context_world(WorldButtonsPanel):
class WORLD_PT_world(WorldButtonsPanel):
__label__ = "World"
COMPAT_ENGINES = set(['BLENDER_RENDER'])
def draw(self, context):
layout = self.layout
@@ -64,6 +68,7 @@ class WORLD_PT_world(WorldButtonsPanel):
class WORLD_PT_mist(WorldButtonsPanel):
__label__ = "Mist"
COMPAT_ENGINES = set(['BLENDER_RENDER'])
def draw_header(self, context):
layout = self.layout
@@ -81,12 +86,13 @@ class WORLD_PT_mist(WorldButtonsPanel):
flow.itemR(world.mist, "start")
flow.itemR(world.mist, "depth")
flow.itemR(world.mist, "height")
flow.itemR(world.mist, "intensity")
flow.itemR(world.mist, "intensity", slider=True)
layout.itemR(world.mist, "falloff")
class WORLD_PT_stars(WorldButtonsPanel):
__label__ = "Stars"
COMPAT_ENGINES = set(['BLENDER_RENDER'])
def draw_header(self, context):
layout = self.layout
@@ -108,6 +114,7 @@ class WORLD_PT_stars(WorldButtonsPanel):
class WORLD_PT_ambient_occlusion(WorldButtonsPanel):
__label__ = "Ambient Occlusion"
COMPAT_ENGINES = set(['BLENDER_RENDER'])
def draw_header(self, context):
layout = self.layout
@@ -156,12 +163,21 @@ class WORLD_PT_ambient_occlusion(WorldButtonsPanel):
col.itemR(ao, "pixel_cache")
col.itemR(ao, "correction")
col = layout.column(align=True)
col = layout.column()
col.itemL(text="Influence:")
row = col.row()
row.itemR(ao, "blend_mode", text="")
row.itemR(ao, "color", text="")
row.itemR(ao, "energy", text="")
col.row().itemR(ao, "blend_mode", expand=True)
split = layout.split()
col = split.column()
col.itemR(ao, "energy")
col = split.column()
colsub = col.split(percentage=0.3)
colsub.itemL(text="Color:")
colsub.itemR(ao, "color", text="")
bpy.types.register(WORLD_PT_context_world)
bpy.types.register(WORLD_PT_preview)

View File

@@ -3,7 +3,6 @@ import bpy
class Buttons_HT_header(bpy.types.Header):
__space_type__ = "BUTTONS_WINDOW"
__idname__ = "BUTTONS_HT_header"
def draw(self, context):
layout = self.layout

View File

@@ -6,7 +6,6 @@ del bpy_ops
class CONSOLE_HT_header(bpy.types.Header):
__space_type__ = "CONSOLE"
__idname__ = "CONSOLE_HT_header"
def draw(self, context):
sc = context.space_data
@@ -51,6 +50,7 @@ class CONSOLE_MT_console(bpy.types.Menu):
layout.column()
layout.itemO("console.clear")
layout.itemO("console.copy")
layout.itemO("console.paste")
class CONSOLE_MT_report(bpy.types.Menu):
__space_type__ = "CONSOLE"
@@ -183,7 +183,7 @@ class CONSOLE_OT_exec(bpy.types.Operator):
else: sc.prompt = self.PROMPT
# insert a new blank line
bpy.ops.console.history_append(text="", current_character=0)
bpy.ops.console.history_append(text="", current_character=0, remove_duplicates= True)
# Insert the output into the editor
# not quite correct because the order might have changed, but ok 99% of the time.

View File

@@ -4,7 +4,6 @@ import bpy
class FILEBROWSER_HT_header(bpy.types.Header):
__space_type__ = "FILE_BROWSER"
__idname__ = "FILEBROWSER_HT_header"
def draw(self, context):
st = context.space_data
@@ -12,18 +11,16 @@ class FILEBROWSER_HT_header(bpy.types.Header):
params = st.params
layout.template_header()
if context.area.show_menus:
row = layout.row()
row.itemM("FILEBROWSER_MT_directory")
row.itemM("FILEBROWSER_MT_bookmarks")
row = layout.row(align=True)
row.itemO("file.parent", text="", icon='ICON_FILE_PARENT')
row.itemO("file.refresh", text="", icon='ICON_FILE_REFRESH')
row.itemO("file.previous", text="", icon='ICON_PREV_KEYFRAME')
row.itemO("file.next", text="", icon='ICON_NEXT_KEYFRAME')
row = layout.row(align=True)
row.itemO("file.directory_new", text="", icon='ICON_NEWFOLDER')
layout.itemR(params, "display", expand=True, text="")
layout.itemR(params, "sort", expand=True, text="")
@@ -42,26 +39,5 @@ class FILEBROWSER_HT_header(bpy.types.Header):
row.active = params.do_filter
class FILEBROWSER_MT_directory(bpy.types.Menu):
__space_type__ = "FILE_BROWSER"
__label__ = "Directory"
def draw(self, context):
layout = self.layout
layout.itemO("file.refresh", text="Refresh", icon='ICON_FILE_REFRESH')
layout.itemO("file.parent", text="Parent", icon='ICON_FILE_PARENT')
class FILEBROWSER_MT_bookmarks(bpy.types.Menu):
__space_type__ = "FILE_BROWSER"
__label__ = "Bookmarks"
def draw(self, context):
layout = self.layout
layout.itemO("file.add_bookmark", text="Add current directory", icon='ICON_BOOKMARKS')
bpy.types.register(FILEBROWSER_HT_header)
bpy.types.register(FILEBROWSER_MT_directory)
bpy.types.register(FILEBROWSER_MT_bookmarks)

View File

@@ -275,8 +275,9 @@ class IMAGE_PT_game_properties(bpy.types.Panel):
__label__ = "Game Properties"
def poll(self, context):
rd = context.scene.render_data
sima = context.space_data
return (sima and sima.image)
return (sima and sima.image) and (rd.engine == 'BLENDER_GAME')
def draw(self, context):
sima = context.space_data

View File

@@ -3,7 +3,6 @@ import bpy
class INFO_HT_header(bpy.types.Header):
__space_type__ = "USER_PREFERENCES"
__idname__ = "INFO_HT_header"
def draw(self, context):
st = context.space_data
@@ -114,7 +113,7 @@ class INFO_MT_add(bpy.types.Menu):
layout.item_menu_enumO( "OBJECT_OT_mesh_add", "type", text="Mesh", icon="ICON_OUTLINER_OB_MESH")
layout.item_menu_enumO( "OBJECT_OT_curve_add", "type", text="Curve", icon="ICON_OUTLINER_OB_CURVE")
layout.item_menu_enumO( "OBJECT_OT_surface_add", "type", text="Surface", icon="ICON_OUTLINER_OB_SURFACE")
layout.item_enumO("OBJECT_OT_object_add", "type", "META", icon="ICON_OUTLINER_OB_META")
layout.item_menu_enumO( "OBJECT_OT_metaball_add", "type", "META", icon="ICON_OUTLINER_OB_META")
layout.itemO("OBJECT_OT_text_add", text="Text", icon="ICON_OUTLINER_OB_FONT")
layout.itemS()

View File

@@ -3,7 +3,6 @@ import bpy
class OUTLINER_HT_header(bpy.types.Header):
__space_type__ = "OUTLINER"
__idname__ = "OUTLINER_HT_header"
def draw(self, context):
so = context.space_data

View File

@@ -8,7 +8,6 @@ def act_strip(context):
# Header
class SEQUENCER_HT_header(bpy.types.Header):
__space_type__ = "SEQUENCE_EDITOR"
__idname__ = "SEQUENCE_HT_header"
def draw(self, context):
@@ -150,10 +149,8 @@ class SEQUENCER_MT_add(bpy.types.Menu):
layout.column()
layout.itemO("sequencer.scene_strip_add", text="Scene")
layout.itemO("sequencer.movie_strip_add", text="Movie")
layout.item_booleanO("sequencer.movie_strip_add", "sound", True, text="Movie & Sound") # FFMPEG ONLY
layout.itemO("sequencer.image_strip_add", text="Image")
layout.itemO("sequencer.sound_strip_add", text="Sound (Ram)")
layout.item_booleanO("sequencer.sound_strip_add", "hd", True, text="Sound (Streaming)") # FFMPEG ONLY
layout.itemO("sequencer.sound_strip_add", text="Sound")
layout.itemM("SEQUENCER_MT_add_effect")
@@ -263,7 +260,6 @@ class SequencerButtonsPanel_Output(bpy.types.Panel):
class SEQUENCER_PT_edit(SequencerButtonsPanel):
__label__ = "Edit Strip"
__idname__ = "SEQUENCER_PT_edit"
def draw(self, context):
layout = self.layout
@@ -302,7 +298,6 @@ class SEQUENCER_PT_edit(SequencerButtonsPanel):
class SEQUENCER_PT_effect(SequencerButtonsPanel):
__label__ = "Effect Strip"
__idname__ = "SEQUENCER_PT_effect"
def poll(self, context):
if context.space_data.display_mode != 'SEQUENCER':
@@ -395,7 +390,6 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel):
class SEQUENCER_PT_input(SequencerButtonsPanel):
__label__ = "Strip Input"
__idname__ = "SEQUENCER_PT_input"
def poll(self, context):
if context.space_data.display_mode != 'SEQUENCER':
@@ -451,7 +445,6 @@ class SEQUENCER_PT_input(SequencerButtonsPanel):
class SEQUENCER_PT_filter(SequencerButtonsPanel):
__label__ = "Filter"
__idname__ = "SEQUENCER_PT_filter"
def poll(self, context):
if context.space_data.display_mode != 'SEQUENCER':
@@ -500,7 +493,6 @@ class SEQUENCER_PT_filter(SequencerButtonsPanel):
class SEQUENCER_PT_proxy(SequencerButtonsPanel):
__label__ = "Proxy"
__idname__ = "SEQUENCER_PT_proxy"
def poll(self, context):
if context.space_data.display_mode != 'SEQUENCER':
@@ -533,7 +525,6 @@ class SEQUENCER_PT_proxy(SequencerButtonsPanel):
class SEQUENCER_PT_view(SequencerButtonsPanel_Output):
__label__ = "View Settings"
__idname__ = "SEQUENCER_PT_view"
def draw(self, context):
st = context.space_data
@@ -560,4 +551,3 @@ bpy.types.register(SEQUENCER_PT_filter)
bpy.types.register(SEQUENCER_PT_proxy)
bpy.types.register(SEQUENCER_PT_view) # view panels

View File

@@ -3,7 +3,6 @@ import bpy
class TEXT_HT_header(bpy.types.Header):
__space_type__ = "TEXT_EDITOR"
__idname__ = "TEXT_HT_header"
def draw(self, context):
st = context.space_data

View File

@@ -187,13 +187,14 @@ class VIEW3D_PT_background_image(bpy.types.Panel):
if bg:
layout.active = view.display_background_image
split = layout.split()
col = split.column()
col = layout.column()
col.itemR(bg, "image", text="")
#col.itemR(bg, "image_user")
col.itemR(bg, "size")
col.itemR(bg, "transparency", slider=True)
col.itemL(text="Offset:")
col = layout.column(align=True)
col.itemR(bg, "x_offset", text="X")
col.itemR(bg, "y_offset", text="Y")

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