1131 lines
40 KiB
C++
1131 lines
40 KiB
C++
/*
|
|
* Copyright 2011, Blender Foundation.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "attribute.h"
|
|
#include "mesh.h"
|
|
#include "object.h"
|
|
#include "scene.h"
|
|
#include "curves.h"
|
|
|
|
#include "blender_sync.h"
|
|
#include "blender_util.h"
|
|
|
|
#include "util_foreach.h"
|
|
|
|
CCL_NAMESPACE_BEGIN
|
|
|
|
/* Utilities */
|
|
|
|
/* Hair curve functions */
|
|
|
|
void curveinterp_v3_v3v3v3v3(float3 *p, float3 *v1, float3 *v2, float3 *v3, float3 *v4, const float w[4]);
|
|
void interp_weights(float t, float data[4], int type);
|
|
float shaperadius(float shape, float root, float tip, float time);
|
|
void InterpolateKeySegments(int seg, int segno, int key, int curve, float3 *keyloc, float *time, ParticleCurveData *CData, int interpolation);
|
|
bool ObtainParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData);
|
|
bool ObtainCacheParticleUV(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents);
|
|
bool ObtainCacheParticleVcol(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents, int vcol_num);
|
|
bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents);
|
|
void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int segments, float3 RotCam);
|
|
void ExportCurveTriangleRibbons(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int segments);
|
|
void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int resolution, int segments);
|
|
void ExportCurveSegments(Mesh *mesh, ParticleCurveData *CData, int interpolation, int segments);
|
|
void ExportCurveTriangleUVs(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int segments, int vert_offset, int resol);
|
|
|
|
ParticleCurveData::ParticleCurveData()
|
|
{
|
|
}
|
|
|
|
ParticleCurveData::~ParticleCurveData()
|
|
{
|
|
psys_firstcurve.clear();
|
|
psys_curvenum.clear();
|
|
psys_shader.clear();
|
|
psys_rootradius.clear();
|
|
psys_tipradius.clear();
|
|
psys_shape.clear();
|
|
|
|
curve_firstkey.clear();
|
|
curve_keynum.clear();
|
|
curve_length.clear();
|
|
curve_uv.clear();
|
|
curve_vcol.clear();
|
|
|
|
curvekey_co.clear();
|
|
curvekey_time.clear();
|
|
}
|
|
|
|
void interp_weights(float t, float data[4], int type)
|
|
{
|
|
float t2, t3, fc;
|
|
|
|
if(type == CURVE_LINEAR) {
|
|
data[0] = 0.0f;
|
|
data[1] = -t + 1.0f;
|
|
data[2] = t;
|
|
data[3] = 0.0f;
|
|
}
|
|
else if(type == CURVE_CARDINAL) {
|
|
t2 = t * t;
|
|
t3 = t2 * t;
|
|
fc = 0.71f;
|
|
|
|
data[0] = -fc * t3 + 2.0f * fc * t2 - fc * t;
|
|
data[1] = (2.0f - fc) * t3 + (fc - 3.0f) * t2 + 1.0f;
|
|
data[2] = (fc - 2.0f) * t3 + (3.0f - 2.0f * fc) * t2 + fc * t;
|
|
data[3] = fc * t3 - fc * t2;
|
|
}
|
|
else if(type == CURVE_BSPLINE) {
|
|
t2 = t * t;
|
|
t3 = t2 * t;
|
|
|
|
data[0] = -0.16666666f * t3 + 0.5f * t2 - 0.5f * t + 0.16666666f;
|
|
data[1] = 0.5f * t3 - t2 + 0.66666666f;
|
|
data[2] = -0.5f * t3 + 0.5f * t2 + 0.5f * t + 0.16666666f;
|
|
data[3] = 0.16666666f * t3;
|
|
}
|
|
}
|
|
|
|
void curveinterp_v3_v3v3v3v3(float3 *p, float3 *v1, float3 *v2, float3 *v3, float3 *v4, const float w[4])
|
|
{
|
|
p->x = v1->x * w[0] + v2->x * w[1] + v3->x * w[2] + v4->x * w[3];
|
|
p->y = v1->y * w[0] + v2->y * w[1] + v3->y * w[2] + v4->y * w[3];
|
|
p->z = v1->z * w[0] + v2->z * w[1] + v3->z * w[2] + v4->z * w[3];
|
|
}
|
|
|
|
float shaperadius(float shape, float root, float tip, float time)
|
|
{
|
|
float radius = 1.0f - time;
|
|
if(shape != 0.0f) {
|
|
if(shape < 0.0f)
|
|
radius = (float)pow(1.0f - time, 1.f + shape);
|
|
else
|
|
radius = (float)pow(1.0f - time, 1.f / (1.f - shape));
|
|
}
|
|
return (radius * (root - tip)) + tip;
|
|
}
|
|
|
|
/* curve functions */
|
|
|
|
void InterpolateKeySegments(int seg, int segno, int key, int curve, float3 *keyloc, float *time, ParticleCurveData *CData, int interpolation)
|
|
{
|
|
float3 ckey_loc1 = CData->curvekey_co[key];
|
|
float3 ckey_loc2 = ckey_loc1;
|
|
float3 ckey_loc3 = CData->curvekey_co[key+1];
|
|
float3 ckey_loc4 = ckey_loc3;
|
|
|
|
if(key > CData->curve_firstkey[curve])
|
|
ckey_loc1 = CData->curvekey_co[key - 1];
|
|
|
|
if(key < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2)
|
|
ckey_loc4 = CData->curvekey_co[key + 2];
|
|
|
|
|
|
float time1 = CData->curvekey_time[key]/CData->curve_length[curve];
|
|
float time2 = CData->curvekey_time[key + 1]/CData->curve_length[curve];
|
|
|
|
float dfra = (time2 - time1) / (float)segno;
|
|
|
|
if(time)
|
|
*time = (dfra * seg) + time1;
|
|
|
|
float t[4];
|
|
|
|
interp_weights((float)seg / (float)segno, t, interpolation);
|
|
|
|
if(keyloc)
|
|
curveinterp_v3_v3v3v3v3(keyloc, &ckey_loc1, &ckey_loc2, &ckey_loc3, &ckey_loc4, t);
|
|
}
|
|
|
|
bool ObtainParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData)
|
|
{
|
|
|
|
int curvenum = 0;
|
|
int keyno = 0;
|
|
|
|
if(!(mesh && b_mesh && b_ob && CData))
|
|
return false;
|
|
|
|
BL::Object::modifiers_iterator b_mod;
|
|
for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
|
|
if((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (b_mod->show_viewport()) && (b_mod->show_render())) {
|
|
|
|
BL::ParticleSystemModifier psmd(b_mod->ptr);
|
|
|
|
BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
|
|
|
|
BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
|
|
|
|
if((b_psys.settings().render_type()==BL::ParticleSettings::render_type_PATH)&&(b_psys.settings().type()==BL::ParticleSettings::type_HAIR)) {
|
|
|
|
int mi = clamp(b_psys.settings().material()-1, 0, mesh->used_shaders.size()-1);
|
|
int shader = mesh->used_shaders[mi];
|
|
|
|
int totcurves = b_psys.particles.length();
|
|
|
|
if(totcurves == 0)
|
|
continue;
|
|
|
|
PointerRNA cpsys = RNA_pointer_get(&b_part.ptr, "cycles");
|
|
|
|
CData->psys_firstcurve.push_back(curvenum);
|
|
CData->psys_curvenum.push_back(totcurves);
|
|
CData->psys_shader.push_back(shader);
|
|
|
|
float radius = b_psys.settings().particle_size() * 0.5f;
|
|
|
|
CData->psys_rootradius.push_back(radius * get_float(cpsys, "root_width"));
|
|
CData->psys_tipradius.push_back(radius * get_float(cpsys, "tip_width"));
|
|
CData->psys_shape.push_back(get_float(cpsys, "shape"));
|
|
CData->psys_closetip.push_back(get_boolean(cpsys, "use_closetip"));
|
|
|
|
BL::ParticleSystem::particles_iterator b_pa;
|
|
for(b_psys.particles.begin(b_pa); b_pa != b_psys.particles.end(); ++b_pa) {
|
|
CData->curve_firstkey.push_back(keyno);
|
|
|
|
int keylength = b_pa->hair_keys.length();
|
|
CData->curve_keynum.push_back(keylength);
|
|
|
|
float curve_length = 0.0f;
|
|
float3 pcKey;
|
|
int step_no = 0;
|
|
BL::Particle::hair_keys_iterator b_cKey;
|
|
for(b_pa->hair_keys.begin(b_cKey); b_cKey != b_pa->hair_keys.end(); ++b_cKey) {
|
|
float nco[3];
|
|
b_cKey->co_object( *b_ob, psmd, *b_pa, nco);
|
|
float3 cKey = make_float3(nco[0],nco[1],nco[2]);
|
|
if(step_no > 0)
|
|
curve_length += len(cKey - pcKey);
|
|
CData->curvekey_co.push_back(cKey);
|
|
CData->curvekey_time.push_back(curve_length);
|
|
pcKey = cKey;
|
|
keyno++;
|
|
step_no++;
|
|
}
|
|
|
|
CData->curve_length.push_back(curve_length);
|
|
/*add uvs*/
|
|
BL::Mesh::tessface_uv_textures_iterator l;
|
|
b_mesh->tessface_uv_textures.begin(l);
|
|
|
|
float3 uv = make_float3(0.0f, 0.0f, 0.0f);
|
|
if(b_mesh->tessface_uv_textures.length())
|
|
b_pa->uv_on_emitter(psmd,&uv.x);
|
|
CData->curve_uv.push_back(uv);
|
|
|
|
curvenum++;
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents)
|
|
{
|
|
|
|
int curvenum = 0;
|
|
int keyno = 0;
|
|
|
|
if(!(mesh && b_mesh && b_ob && CData))
|
|
return false;
|
|
|
|
Transform tfm = get_transform(b_ob->matrix_world());
|
|
Transform itfm = transform_quick_inverse(tfm);
|
|
|
|
BL::Object::modifiers_iterator b_mod;
|
|
for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
|
|
if((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (b_mod->show_viewport()) && (b_mod->show_render())) {
|
|
BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
|
|
|
|
BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
|
|
|
|
BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
|
|
|
|
if((b_psys.settings().render_type()==BL::ParticleSettings::render_type_PATH)&&(b_psys.settings().type()==BL::ParticleSettings::type_HAIR)) {
|
|
|
|
int mi = clamp(b_psys.settings().material()-1, 0, mesh->used_shaders.size()-1);
|
|
int shader = mesh->used_shaders[mi];
|
|
int draw_step = b_psys.settings().draw_step();
|
|
int ren_step = (int)pow((float)2.0f,(float)draw_step);
|
|
/*b_psys.settings().render_step(draw_step);*/
|
|
|
|
int totparts = b_psys.particles.length();
|
|
int totchild = b_psys.child_particles.length() * b_psys.settings().draw_percentage() / 100;
|
|
int totcurves = totchild;
|
|
|
|
if(use_parents || b_psys.settings().child_type() == 0)
|
|
totcurves += totparts;
|
|
|
|
if(totcurves == 0)
|
|
continue;
|
|
|
|
PointerRNA cpsys = RNA_pointer_get(&b_part.ptr, "cycles");
|
|
|
|
CData->psys_firstcurve.push_back(curvenum);
|
|
CData->psys_curvenum.push_back(totcurves);
|
|
CData->psys_shader.push_back(shader);
|
|
|
|
float radius = b_psys.settings().particle_size() * 0.5f;
|
|
|
|
CData->psys_rootradius.push_back(radius * get_float(cpsys, "root_width"));
|
|
CData->psys_tipradius.push_back(radius * get_float(cpsys, "tip_width"));
|
|
CData->psys_shape.push_back(get_float(cpsys, "shape"));
|
|
CData->psys_closetip.push_back(get_boolean(cpsys, "use_closetip"));
|
|
|
|
int pa_no = 0;
|
|
if(!use_parents && !(b_psys.settings().child_type() == 0))
|
|
pa_no = totparts;
|
|
|
|
for(; pa_no < totparts+totchild; pa_no++) {
|
|
|
|
CData->curve_firstkey.push_back(keyno);
|
|
CData->curve_keynum.push_back(ren_step+1);
|
|
|
|
float curve_length = 0.0f;
|
|
float3 pcKey;
|
|
for(int step_no = 0; step_no <= ren_step; step_no++) {
|
|
float nco[3];
|
|
b_psys.co_hair(*b_ob, psmd, pa_no, step_no, nco);
|
|
float3 cKey = make_float3(nco[0],nco[1],nco[2]);
|
|
cKey = transform_point(&itfm, cKey);
|
|
if(step_no > 0)
|
|
curve_length += len(cKey - pcKey);
|
|
CData->curvekey_co.push_back(cKey);
|
|
CData->curvekey_time.push_back(curve_length);
|
|
pcKey = cKey;
|
|
keyno++;
|
|
}
|
|
CData->curve_length.push_back(curve_length);
|
|
|
|
curvenum++;
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool ObtainCacheParticleUV(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents)
|
|
{
|
|
int keyno = 0;
|
|
|
|
if(!(mesh && b_mesh && b_ob && CData))
|
|
return false;
|
|
|
|
Transform tfm = get_transform(b_ob->matrix_world());
|
|
Transform itfm = transform_quick_inverse(tfm);
|
|
|
|
BL::Object::modifiers_iterator b_mod;
|
|
for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
|
|
if ((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (b_mod->show_viewport()) && (b_mod->show_render())) {
|
|
BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
|
|
|
|
BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
|
|
|
|
BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
|
|
|
|
if((b_psys.settings().render_type()==BL::ParticleSettings::render_type_PATH)&&(b_psys.settings().type()==BL::ParticleSettings::type_HAIR)) {
|
|
|
|
int mi = clamp(b_psys.settings().material()-1, 0, mesh->used_shaders.size()-1);
|
|
int shader = mesh->used_shaders[mi];
|
|
int draw_step = b_psys.settings().draw_step();
|
|
int ren_step = (int)pow((float)2.0f,(float)draw_step);
|
|
/*b_psys.settings().render_step(draw_step);*/
|
|
|
|
int totparts = b_psys.particles.length();
|
|
int totchild = b_psys.child_particles.length() * b_psys.settings().draw_percentage() / 100;
|
|
int totcurves = totchild;
|
|
|
|
if (use_parents || b_psys.settings().child_type() == 0)
|
|
totcurves += totparts;
|
|
|
|
if (totcurves == 0)
|
|
continue;
|
|
|
|
int pa_no = 0;
|
|
if(!use_parents && !(b_psys.settings().child_type() == 0))
|
|
pa_no = totparts;
|
|
|
|
BL::ParticleSystem::particles_iterator b_pa;
|
|
b_psys.particles.begin(b_pa);
|
|
for(; pa_no < totparts+totchild; pa_no++) {
|
|
|
|
/*add uvs*/
|
|
BL::Mesh::tessface_uv_textures_iterator l;
|
|
b_mesh->tessface_uv_textures.begin(l);
|
|
|
|
float3 uv = make_float3(0.0f, 0.0f, 0.0f);
|
|
if(b_mesh->tessface_uv_textures.length())
|
|
b_psys.uv_on_emitter(psmd, *b_pa, pa_no, &uv.x);
|
|
CData->curve_uv.push_back(uv);
|
|
|
|
if(pa_no < totparts && b_pa != b_psys.particles.end())
|
|
++b_pa;
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool ObtainCacheParticleVcol(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents, int vcol_num)
|
|
{
|
|
int keyno = 0;
|
|
|
|
if(!(mesh && b_mesh && b_ob && CData))
|
|
return false;
|
|
|
|
Transform tfm = get_transform(b_ob->matrix_world());
|
|
Transform itfm = transform_quick_inverse(tfm);
|
|
|
|
BL::Object::modifiers_iterator b_mod;
|
|
for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
|
|
if ((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (b_mod->show_viewport()) && (b_mod->show_render())) {
|
|
BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
|
|
|
|
BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
|
|
|
|
BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
|
|
|
|
if((b_psys.settings().render_type()==BL::ParticleSettings::render_type_PATH)&&(b_psys.settings().type()==BL::ParticleSettings::type_HAIR)) {
|
|
|
|
int mi = clamp(b_psys.settings().material()-1, 0, mesh->used_shaders.size()-1);
|
|
int shader = mesh->used_shaders[mi];
|
|
int draw_step = b_psys.settings().draw_step();
|
|
int ren_step = (int)pow((float)2.0f,(float)draw_step);
|
|
/*b_psys.settings().render_step(draw_step);*/
|
|
|
|
int totparts = b_psys.particles.length();
|
|
int totchild = b_psys.child_particles.length() * b_psys.settings().draw_percentage() / 100;
|
|
int totcurves = totchild;
|
|
|
|
if (use_parents || b_psys.settings().child_type() == 0)
|
|
totcurves += totparts;
|
|
|
|
if (totcurves == 0)
|
|
continue;
|
|
|
|
int pa_no = 0;
|
|
if(!use_parents && !(b_psys.settings().child_type() == 0))
|
|
pa_no = totparts;
|
|
|
|
BL::ParticleSystem::particles_iterator b_pa;
|
|
b_psys.particles.begin(b_pa);
|
|
for(; pa_no < totparts+totchild; pa_no++) {
|
|
|
|
/*add uvs*/
|
|
BL::Mesh::tessface_vertex_colors_iterator l;
|
|
b_mesh->tessface_vertex_colors.begin(l);
|
|
|
|
float3 vcol = make_float3(0.0f, 0.0f, 0.0f);
|
|
if(b_mesh->tessface_vertex_colors.length())
|
|
b_psys.mcol_on_emitter(psmd, *b_pa, pa_no, vcol_num, &vcol.x);
|
|
CData->curve_vcol.push_back(vcol);
|
|
|
|
if(pa_no < totparts && b_pa != b_psys.particles.end())
|
|
++b_pa;
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int segments, float3 RotCam)
|
|
{
|
|
int vertexno = mesh->verts.size();
|
|
int vertexindex = vertexno;
|
|
|
|
for( int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
|
|
for( int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys] ; curve++) {
|
|
|
|
for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
|
|
|
|
int subv = 1;
|
|
float3 xbasis;
|
|
|
|
float3 v1;
|
|
|
|
if(curvekey == CData->curve_firstkey[curve]) {
|
|
subv = 0;
|
|
v1 = CData->curvekey_co[min(curvekey+2,CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)] - CData->curvekey_co[curvekey];
|
|
}
|
|
else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)
|
|
v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[max(curvekey - 2, CData->curve_firstkey[curve])];
|
|
else
|
|
v1 = CData->curvekey_co[curvekey + 1] - CData->curvekey_co[curvekey - 1];
|
|
|
|
|
|
for (; subv <= segments; subv++) {
|
|
|
|
float3 ickey_loc = make_float3(0.0f,0.0f,0.0f);
|
|
float time = 0.0f;
|
|
|
|
if ((interpolation == CURVE_BSPLINE) && (curvekey == CData->curve_firstkey[curve]) && (subv == 0))
|
|
ickey_loc = CData->curvekey_co[curvekey];
|
|
else
|
|
InterpolateKeySegments(subv, segments, curvekey, curve, &ickey_loc, &time, CData , interpolation);
|
|
|
|
float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
|
|
|
|
if(CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1))
|
|
radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f);
|
|
|
|
if((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) && (subv == segments))
|
|
radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], 0.95f);
|
|
|
|
xbasis = normalize(cross(v1,RotCam - ickey_loc));
|
|
float3 ickey_loc_shfl = ickey_loc - radius * xbasis;
|
|
float3 ickey_loc_shfr = ickey_loc + radius * xbasis;
|
|
mesh->verts.push_back(ickey_loc_shfl);
|
|
mesh->verts.push_back(ickey_loc_shfr);
|
|
if(subv!=0) {
|
|
mesh->add_triangle(vertexindex-2, vertexindex, vertexindex-1, CData->psys_shader[sys], use_smooth);
|
|
mesh->add_triangle(vertexindex+1, vertexindex-1, vertexindex, CData->psys_shader[sys], use_smooth);
|
|
}
|
|
vertexindex += 2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
mesh->reserve(mesh->verts.size(), mesh->triangles.size(), 0, 0);
|
|
mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
|
|
mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
|
|
mesh->add_face_normals();
|
|
mesh->add_vertex_normals();
|
|
mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
|
|
|
|
/* texture coords still needed */
|
|
}
|
|
|
|
void ExportCurveTriangleRibbons(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int segments)
|
|
{
|
|
int vertexno = mesh->verts.size();
|
|
int vertexindex = vertexno;
|
|
|
|
for( int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
|
|
for( int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys] ; curve++) {
|
|
|
|
float3 firstxbasis = cross(make_float3(1.0f,0.0f,0.0f),CData->curvekey_co[CData->curve_firstkey[curve]+1] - CData->curvekey_co[CData->curve_firstkey[curve]]);
|
|
if(len_squared(firstxbasis)!= 0.0f)
|
|
firstxbasis = normalize(firstxbasis);
|
|
else
|
|
firstxbasis = normalize(cross(make_float3(0.0f,1.0f,0.0f),CData->curvekey_co[CData->curve_firstkey[curve]+1] - CData->curvekey_co[CData->curve_firstkey[curve]]));
|
|
|
|
for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
|
|
|
|
float3 xbasis = firstxbasis;
|
|
float3 v1;
|
|
float3 v2;
|
|
|
|
if(curvekey == CData->curve_firstkey[curve]) {
|
|
v1 = CData->curvekey_co[min(curvekey+2,CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)] - CData->curvekey_co[curvekey+1];
|
|
v2 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
|
|
}
|
|
else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) {
|
|
v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
|
|
v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[max(curvekey-2,CData->curve_firstkey[curve])];
|
|
}
|
|
else {
|
|
v1 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
|
|
v2 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
|
|
}
|
|
|
|
xbasis = cross(v1,v2);
|
|
|
|
if(len_squared(xbasis) >= 0.05f * len_squared(v1) * len_squared(v2)) {
|
|
firstxbasis = normalize(xbasis);
|
|
break;
|
|
}
|
|
}
|
|
|
|
for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
|
|
|
|
int subv = 1;
|
|
float3 v1;
|
|
float3 v2;
|
|
float3 xbasis;
|
|
|
|
if(curvekey == CData->curve_firstkey[curve]) {
|
|
subv = 0;
|
|
v1 = CData->curvekey_co[min(curvekey+2,CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)] - CData->curvekey_co[curvekey+1];
|
|
v2 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
|
|
}
|
|
else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) {
|
|
v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
|
|
v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[max(curvekey-2,CData->curve_firstkey[curve])];
|
|
}
|
|
else {
|
|
v1 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
|
|
v2 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
|
|
}
|
|
|
|
xbasis = cross(v1,v2);
|
|
|
|
if(len_squared(xbasis) >= 0.05f * len_squared(v1) * len_squared(v2)) {
|
|
xbasis = normalize(xbasis);
|
|
firstxbasis = xbasis;
|
|
}
|
|
else
|
|
xbasis = firstxbasis;
|
|
|
|
for (; subv <= segments; subv++) {
|
|
|
|
float3 ickey_loc = make_float3(0.0f,0.0f,0.0f);
|
|
float time = 0.0f;
|
|
|
|
if ((interpolation == CURVE_BSPLINE) && (curvekey == CData->curve_firstkey[curve]) && (subv == 0))
|
|
ickey_loc = CData->curvekey_co[curvekey];
|
|
else
|
|
InterpolateKeySegments(subv, segments, curvekey, curve, &ickey_loc, &time, CData , interpolation);
|
|
|
|
float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
|
|
|
|
if(CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1))
|
|
radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f);
|
|
|
|
if((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) && (subv == segments))
|
|
radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], 0.95f);
|
|
|
|
float3 ickey_loc_shfl = ickey_loc - radius * xbasis;
|
|
float3 ickey_loc_shfr = ickey_loc + radius * xbasis;
|
|
mesh->verts.push_back(ickey_loc_shfl);
|
|
mesh->verts.push_back(ickey_loc_shfr);
|
|
if(subv!=0) {
|
|
mesh->add_triangle(vertexindex-2, vertexindex, vertexindex-1, CData->psys_shader[sys], use_smooth);
|
|
mesh->add_triangle(vertexindex+1, vertexindex-1, vertexindex, CData->psys_shader[sys], use_smooth);
|
|
}
|
|
vertexindex += 2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
mesh->reserve(mesh->verts.size(), mesh->triangles.size(), 0, 0);
|
|
mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
|
|
mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
|
|
mesh->add_face_normals();
|
|
mesh->add_vertex_normals();
|
|
mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
|
|
/* texture coords still needed */
|
|
|
|
}
|
|
|
|
void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int resolution, int segments)
|
|
{
|
|
int vertexno = mesh->verts.size();
|
|
int vertexindex = vertexno;
|
|
|
|
for( int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
|
|
for( int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys] ; curve++) {
|
|
|
|
float3 firstxbasis = cross(make_float3(1.0f,0.0f,0.0f),CData->curvekey_co[CData->curve_firstkey[curve]+1] - CData->curvekey_co[CData->curve_firstkey[curve]]);
|
|
if(len_squared(firstxbasis)!= 0.0f)
|
|
firstxbasis = normalize(firstxbasis);
|
|
else
|
|
firstxbasis = normalize(cross(make_float3(0.0f,1.0f,0.0f),CData->curvekey_co[CData->curve_firstkey[curve]+1] - CData->curvekey_co[CData->curve_firstkey[curve]]));
|
|
|
|
|
|
for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
|
|
|
|
float3 xbasis = firstxbasis;
|
|
float3 v1;
|
|
float3 v2;
|
|
|
|
if(curvekey == CData->curve_firstkey[curve]) {
|
|
v1 = CData->curvekey_co[min(curvekey+2,CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)] - CData->curvekey_co[curvekey+1];
|
|
v2 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
|
|
}
|
|
else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) {
|
|
v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
|
|
v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[max(curvekey-2,CData->curve_firstkey[curve])];
|
|
}
|
|
else {
|
|
v1 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
|
|
v2 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
|
|
}
|
|
|
|
xbasis = cross(v1,v2);
|
|
|
|
if(len_squared(xbasis) >= 0.05f * len_squared(v1) * len_squared(v2)) {
|
|
firstxbasis = normalize(xbasis);
|
|
break;
|
|
}
|
|
}
|
|
|
|
for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
|
|
|
|
int subv = 1;
|
|
float3 xbasis;
|
|
float3 ybasis;
|
|
float3 v1;
|
|
float3 v2;
|
|
|
|
if(curvekey == CData->curve_firstkey[curve]) {
|
|
subv = 0;
|
|
v1 = CData->curvekey_co[min(curvekey+2,CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)] - CData->curvekey_co[curvekey+1];
|
|
v2 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
|
|
}
|
|
else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) {
|
|
v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
|
|
v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[max(curvekey-2,CData->curve_firstkey[curve])];
|
|
}
|
|
else {
|
|
v1 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
|
|
v2 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
|
|
}
|
|
|
|
xbasis = cross(v1,v2);
|
|
|
|
if(len_squared(xbasis) >= 0.05f * len_squared(v1) * len_squared(v2)) {
|
|
xbasis = normalize(xbasis);
|
|
firstxbasis = xbasis;
|
|
}
|
|
else
|
|
xbasis = firstxbasis;
|
|
|
|
ybasis = normalize(cross(xbasis,v2));
|
|
|
|
for (; subv <= segments; subv++) {
|
|
|
|
float3 ickey_loc = make_float3(0.0f,0.0f,0.0f);
|
|
float time = 0.0f;
|
|
|
|
if ((interpolation == CURVE_BSPLINE) && (curvekey == CData->curve_firstkey[curve]) && (subv == 0))
|
|
ickey_loc = CData->curvekey_co[curvekey];
|
|
else
|
|
InterpolateKeySegments(subv, segments, curvekey, curve, &ickey_loc, &time, CData , interpolation);
|
|
|
|
float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
|
|
|
|
if(CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1))
|
|
radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f);
|
|
|
|
if((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) && (subv == segments))
|
|
radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], 0.95f);
|
|
|
|
float angle = 2 * M_PI_F / (float)resolution;
|
|
for(int section = 0 ; section < resolution; section++) {
|
|
float3 ickey_loc_shf = ickey_loc + radius * (cosf(angle * section) * xbasis + sinf(angle * section) * ybasis);
|
|
mesh->verts.push_back(ickey_loc_shf);
|
|
}
|
|
|
|
if(subv!=0) {
|
|
for(int section = 0 ; section < resolution - 1; section++) {
|
|
mesh->add_triangle(vertexindex - resolution + section, vertexindex + section, vertexindex - resolution + section + 1, CData->psys_shader[sys], use_smooth);
|
|
mesh->add_triangle(vertexindex + section + 1, vertexindex - resolution + section + 1, vertexindex + section, CData->psys_shader[sys], use_smooth);
|
|
}
|
|
mesh->add_triangle(vertexindex-1, vertexindex + resolution - 1, vertexindex - resolution, CData->psys_shader[sys], use_smooth);
|
|
mesh->add_triangle(vertexindex, vertexindex - resolution , vertexindex + resolution - 1, CData->psys_shader[sys], use_smooth);
|
|
}
|
|
vertexindex += resolution;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
mesh->reserve(mesh->verts.size(), mesh->triangles.size(), 0, 0);
|
|
mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
|
|
mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
|
|
mesh->add_face_normals();
|
|
mesh->add_vertex_normals();
|
|
mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
|
|
|
|
/* texture coords still needed */
|
|
}
|
|
|
|
static void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData, int interpolation, int segments)
|
|
{
|
|
int num_keys = 0;
|
|
int num_curves = 0;
|
|
|
|
if(!(mesh->curves.empty() && mesh->curve_keys.empty()))
|
|
return;
|
|
|
|
Attribute *attr_uv = NULL, *attr_intercept = NULL;
|
|
|
|
if(mesh->need_attribute(scene, ATTR_STD_UV))
|
|
attr_uv = mesh->curve_attributes.add(ATTR_STD_UV);
|
|
if(mesh->need_attribute(scene, ATTR_STD_CURVE_INTERCEPT))
|
|
attr_intercept = mesh->curve_attributes.add(ATTR_STD_CURVE_INTERCEPT);
|
|
|
|
for( int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
|
|
|
|
if(CData->psys_curvenum[sys] == 0)
|
|
continue;
|
|
|
|
for( int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys] ; curve++) {
|
|
|
|
if(CData->curve_keynum[curve] <= 1)
|
|
continue;
|
|
|
|
size_t num_curve_keys = 0;
|
|
|
|
for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
|
|
|
|
int subv = 1;
|
|
if(curvekey == CData->curve_firstkey[curve])
|
|
subv = 0;
|
|
|
|
for (; subv <= segments; subv++) {
|
|
|
|
float3 ickey_loc = make_float3(0.0f,0.0f,0.0f);
|
|
float time = 0.0f;
|
|
|
|
if((interpolation == CURVE_BSPLINE) && (curvekey == CData->curve_firstkey[curve]) && (subv == 0))
|
|
ickey_loc = CData->curvekey_co[curvekey];
|
|
else
|
|
InterpolateKeySegments(subv, segments, curvekey, curve, &ickey_loc, &time, CData , interpolation);
|
|
|
|
float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
|
|
|
|
if(CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
|
|
radius =0.0f;
|
|
|
|
mesh->add_curve_key(ickey_loc, radius);
|
|
if(attr_intercept)
|
|
attr_intercept->add(time);
|
|
|
|
num_curve_keys++;
|
|
}
|
|
}
|
|
|
|
mesh->add_curve(num_keys, num_curve_keys, CData->psys_shader[sys]);
|
|
if(attr_uv)
|
|
attr_uv->add(CData->curve_uv[curve]);
|
|
|
|
num_keys += num_curve_keys;
|
|
num_curves++;
|
|
}
|
|
}
|
|
|
|
/* check allocation*/
|
|
if((mesh->curve_keys.size() != num_keys) || (mesh->curves.size() != num_curves)) {
|
|
/* allocation failed -> clear data */
|
|
mesh->curve_keys.clear();
|
|
mesh->curves.clear();
|
|
mesh->curve_attributes.clear();
|
|
}
|
|
}
|
|
|
|
void ExportCurveTriangleUVs(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int segments, int vert_offset, int resol)
|
|
{
|
|
float time = 0.0f;
|
|
float prevtime = 0.0f;
|
|
|
|
Attribute *attr = mesh->attributes.find(ATTR_STD_UV);
|
|
if (attr == NULL)
|
|
return;
|
|
|
|
float3 *uvdata = attr->data_float3();
|
|
|
|
int vertexindex = vert_offset;
|
|
|
|
for( int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
|
|
for( int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys] ; curve++) {
|
|
|
|
for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
|
|
|
|
int subv = 1;
|
|
|
|
if (curvekey == CData->curve_firstkey[curve])
|
|
subv = 0;
|
|
|
|
for (; subv <= segments; subv++) {
|
|
|
|
float3 ickey_loc = make_float3(0.0f,0.0f,0.0f);
|
|
|
|
InterpolateKeySegments(subv, segments, curvekey, curve, &ickey_loc, &time, CData , interpolation);
|
|
|
|
if(subv!=0) {
|
|
for(int section = 0 ; section < resol; section++) {
|
|
uvdata[vertexindex] = CData->curve_uv[curve];
|
|
uvdata[vertexindex].z = prevtime;
|
|
vertexindex++;
|
|
uvdata[vertexindex] = CData->curve_uv[curve];
|
|
uvdata[vertexindex].z = time;
|
|
vertexindex++;
|
|
uvdata[vertexindex] = CData->curve_uv[curve];
|
|
uvdata[vertexindex].z = prevtime;
|
|
vertexindex++;
|
|
uvdata[vertexindex] = CData->curve_uv[curve];
|
|
uvdata[vertexindex].z = time;
|
|
vertexindex++;
|
|
uvdata[vertexindex] = CData->curve_uv[curve];
|
|
uvdata[vertexindex].z = prevtime;
|
|
vertexindex++;
|
|
uvdata[vertexindex] = CData->curve_uv[curve];
|
|
uvdata[vertexindex].z = time;
|
|
vertexindex++;
|
|
}
|
|
}
|
|
|
|
prevtime = time;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
/* Hair Curve Sync */
|
|
|
|
void BlenderSync::sync_curve_settings()
|
|
{
|
|
PointerRNA csscene = RNA_pointer_get(&b_scene.ptr, "cycles_curves");
|
|
|
|
int preset = get_enum(csscene, "preset");
|
|
|
|
CurveSystemManager *curve_system_manager = scene->curve_system_manager;
|
|
CurveSystemManager prev_curve_system_manager = *curve_system_manager;
|
|
|
|
curve_system_manager->use_curves = get_boolean(csscene, "use_curves");
|
|
|
|
if(preset == CURVE_CUSTOM) {
|
|
/*custom properties*/
|
|
curve_system_manager->primitive = get_enum(csscene, "primitive");
|
|
curve_system_manager->line_method = get_enum(csscene, "line_method");
|
|
curve_system_manager->interpolation = get_enum(csscene, "interpolation");
|
|
curve_system_manager->triangle_method = get_enum(csscene, "triangle_method");
|
|
curve_system_manager->resolution = get_int(csscene, "resolution");
|
|
curve_system_manager->segments = get_int(csscene, "segments");
|
|
curve_system_manager->use_smooth = get_boolean(csscene, "use_smooth");
|
|
|
|
curve_system_manager->normalmix = get_float(csscene, "normalmix");
|
|
curve_system_manager->encasing_ratio = get_float(csscene, "encasing_ratio");
|
|
|
|
curve_system_manager->use_cache = get_boolean(csscene, "use_cache");
|
|
curve_system_manager->use_parents = get_boolean(csscene, "use_parents");
|
|
curve_system_manager->use_encasing = get_boolean(csscene, "use_encasing");
|
|
curve_system_manager->use_backfacing = get_boolean(csscene, "use_backfacing");
|
|
curve_system_manager->use_joined = get_boolean(csscene, "use_joined");
|
|
curve_system_manager->use_tangent_normal = get_boolean(csscene, "use_tangent_normal");
|
|
curve_system_manager->use_tangent_normal_geometry = get_boolean(csscene, "use_tangent_normal_geometry");
|
|
curve_system_manager->use_tangent_normal_correction = get_boolean(csscene, "use_tangent_normal_correction");
|
|
}
|
|
else {
|
|
curve_system_manager->primitive = CURVE_LINE_SEGMENTS;
|
|
curve_system_manager->interpolation = CURVE_CARDINAL;
|
|
curve_system_manager->normalmix = 1.0f;
|
|
curve_system_manager->encasing_ratio = 1.01f;
|
|
curve_system_manager->use_cache = true;
|
|
curve_system_manager->use_parents = false;
|
|
curve_system_manager->segments = 1;
|
|
curve_system_manager->use_joined = false;
|
|
|
|
switch(preset) {
|
|
case CURVE_TANGENT_SHADING:
|
|
/*tangent shading*/
|
|
curve_system_manager->line_method = CURVE_UNCORRECTED;
|
|
curve_system_manager->use_encasing = true;
|
|
curve_system_manager->use_backfacing = false;
|
|
curve_system_manager->use_tangent_normal = true;
|
|
curve_system_manager->use_tangent_normal_geometry = true;
|
|
curve_system_manager->use_tangent_normal_correction = false;
|
|
break;
|
|
case CURVE_TRUE_NORMAL:
|
|
/*True Normal*/
|
|
curve_system_manager->line_method = CURVE_CORRECTED;
|
|
curve_system_manager->use_encasing = true;
|
|
curve_system_manager->use_backfacing = false;
|
|
curve_system_manager->use_tangent_normal = false;
|
|
curve_system_manager->use_tangent_normal_geometry = false;
|
|
curve_system_manager->use_tangent_normal_correction = false;
|
|
break;
|
|
case CURVE_ACCURATE_PRESET:
|
|
/*Accurate*/
|
|
curve_system_manager->line_method = CURVE_ACCURATE;
|
|
curve_system_manager->use_encasing = false;
|
|
curve_system_manager->use_backfacing = true;
|
|
curve_system_manager->use_tangent_normal = false;
|
|
curve_system_manager->use_tangent_normal_geometry = false;
|
|
curve_system_manager->use_tangent_normal_correction = false;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
if(curve_system_manager->modified_mesh(prev_curve_system_manager))
|
|
{
|
|
BL::BlendData::objects_iterator b_ob;
|
|
|
|
for(b_data.objects.begin(b_ob); b_ob != b_data.objects.end(); ++b_ob) {
|
|
if(object_is_mesh(*b_ob)) {
|
|
BL::Object::particle_systems_iterator b_psys;
|
|
for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) {
|
|
if((b_psys->settings().render_type()==BL::ParticleSettings::render_type_PATH)&&(b_psys->settings().type()==BL::ParticleSettings::type_HAIR)) {
|
|
BL::ID key = BKE_object_is_modified(*b_ob)? *b_ob: b_ob->data();
|
|
mesh_map.set_recalc(key);
|
|
object_map.set_recalc(*b_ob);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(curve_system_manager->modified(prev_curve_system_manager))
|
|
curve_system_manager->tag_update(scene);
|
|
|
|
}
|
|
|
|
void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool object_updated)
|
|
{
|
|
/* Clear stored curve data */
|
|
mesh->curve_keys.clear();
|
|
mesh->curves.clear();
|
|
mesh->curve_attributes.clear();
|
|
|
|
/* obtain general settings */
|
|
bool use_curves = scene->curve_system_manager->use_curves;
|
|
|
|
if(!(use_curves && b_ob.mode() == b_ob.mode_OBJECT)) {
|
|
mesh->compute_bounds();
|
|
return;
|
|
}
|
|
|
|
int primitive = scene->curve_system_manager->primitive;
|
|
int interpolation = scene->curve_system_manager->interpolation;
|
|
int triangle_method = scene->curve_system_manager->triangle_method;
|
|
int resolution = scene->curve_system_manager->resolution;
|
|
int segments = scene->curve_system_manager->segments;
|
|
bool use_smooth = scene->curve_system_manager->use_smooth;
|
|
bool use_cache = scene->curve_system_manager->use_cache;
|
|
bool use_parents = scene->curve_system_manager->use_parents;
|
|
bool export_tgs = scene->curve_system_manager->use_joined;
|
|
|
|
/* extract particle hair data - should be combined with connecting to mesh later*/
|
|
|
|
ParticleCurveData CData;
|
|
|
|
if(use_cache) {
|
|
ObtainCacheParticleData(mesh, &b_mesh, &b_ob, &CData, use_parents);
|
|
ObtainCacheParticleUV(mesh, &b_mesh, &b_ob, &CData, use_parents);
|
|
}
|
|
else
|
|
ObtainParticleData(mesh, &b_mesh, &b_ob, &CData);
|
|
|
|
/* attach strands to mesh */
|
|
BL::Object b_CamOb = b_scene.camera();
|
|
float3 RotCam = make_float3(0.0f, 0.0f, 0.0f);
|
|
if(b_CamOb) {
|
|
Transform ctfm = get_transform(b_CamOb.matrix_world());
|
|
Transform tfm = get_transform(b_ob.matrix_world());
|
|
Transform itfm = transform_quick_inverse(tfm);
|
|
RotCam = transform_point(&itfm, make_float3(ctfm.x.w, ctfm.y.w, ctfm.z.w));
|
|
}
|
|
|
|
if(primitive == CURVE_TRIANGLES){
|
|
int vert_num = mesh->triangles.size() * 3;
|
|
if(triangle_method == CURVE_CAMERA) {
|
|
ExportCurveTrianglePlanes(mesh, &CData, interpolation, use_smooth, segments, RotCam);
|
|
ExportCurveTriangleUVs(mesh, &CData, interpolation, use_smooth, segments, vert_num, 1);
|
|
}
|
|
else if(triangle_method == CURVE_RIBBONS) {
|
|
ExportCurveTriangleRibbons(mesh, &CData, interpolation, use_smooth, segments);
|
|
ExportCurveTriangleUVs(mesh, &CData, interpolation, use_smooth, segments, vert_num, 1);
|
|
}
|
|
else {
|
|
ExportCurveTriangleGeometry(mesh, &CData, interpolation, use_smooth, resolution, segments);
|
|
ExportCurveTriangleUVs(mesh, &CData, interpolation, use_smooth, segments, vert_num, resolution);
|
|
}
|
|
|
|
}
|
|
else {
|
|
ExportCurveSegments(scene, mesh, &CData, interpolation, segments);
|
|
int ckey_num = mesh->curve_keys.size();
|
|
|
|
/*export tangents or curve data? - not functional yet*/
|
|
if(export_tgs && ckey_num > 1) {
|
|
Attribute *attr_tangent = mesh->curve_attributes.add(ATTR_STD_CURVE_TANGENT);
|
|
float3 *data_tangent = attr_tangent->data_float3();
|
|
|
|
for(int ck = 0; ck < ckey_num; ck++) {
|
|
float3 tg = normalize(normalize(mesh->curve_keys[min(ck + 1, ckey_num - 1)].co - mesh->curve_keys[ck].co) -
|
|
normalize(mesh->curve_keys[max(ck - 1, 0)].co - mesh->curve_keys[ck].co));
|
|
|
|
data_tangent[ck] = tg;
|
|
}
|
|
}
|
|
|
|
/* generated coordinates from first key. we should ideally get this from
|
|
* blender to handle deforming objects */
|
|
if(mesh->need_attribute(scene, ATTR_STD_GENERATED)) {
|
|
float3 loc, size;
|
|
mesh_texture_space(b_mesh, loc, size);
|
|
|
|
Attribute *attr_generated = mesh->curve_attributes.add(ATTR_STD_GENERATED);
|
|
float3 *generated = attr_generated->data_float3();
|
|
size_t i = 0;
|
|
|
|
foreach(Mesh::Curve& curve, mesh->curves) {
|
|
float3 co = mesh->curve_keys[curve.first_key].co;
|
|
generated[i++] = co*size - loc;
|
|
}
|
|
}
|
|
|
|
/* create vertex color attributes */
|
|
BL::Mesh::tessface_vertex_colors_iterator l;
|
|
int vcol_num = 0;
|
|
|
|
for(b_mesh.tessface_vertex_colors.begin(l); l != b_mesh.tessface_vertex_colors.end(); ++l, vcol_num++) {
|
|
if(!mesh->need_attribute(scene, ustring(l->name().c_str())))
|
|
continue;
|
|
|
|
/*error occurs with more than one vertex colour attribute so avoided*/
|
|
if(vcol_num!=0)
|
|
break;
|
|
|
|
Attribute *attr_vcol = mesh->curve_attributes.add(
|
|
ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CURVE);
|
|
|
|
ObtainCacheParticleVcol(mesh, &b_mesh, &b_ob, &CData, use_parents, 0);
|
|
|
|
float3 *vcol = attr_vcol->data_float3();
|
|
|
|
if(vcol) {
|
|
for(size_t curve = 0; curve < CData.curve_vcol.size() ;curve++)
|
|
vcol[curve] = color_srgb_to_scene_linear(CData.curve_vcol[curve]);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mesh->compute_bounds();
|
|
}
|
|
|
|
|
|
CCL_NAMESPACE_END
|
|
|