| Line |
Branch |
Exec |
Source |
| 1 |
|
|
// Copyright (c) 2016, Joseph Mirabel |
| 2 |
|
|
// Authors: Joseph Mirabel (joseph.mirabel@laas.fr) |
| 3 |
|
|
// |
| 4 |
|
|
// This file is part of gepetto-viewer. |
| 5 |
|
|
// gepetto-viewer is free software: you can redistribute it |
| 6 |
|
|
// and/or modify it under the terms of the GNU Lesser General Public |
| 7 |
|
|
// License as published by the Free Software Foundation, either version |
| 8 |
|
|
// 3 of the License, or (at your option) any later version. |
| 9 |
|
|
// |
| 10 |
|
|
// gepetto-viewer is distributed in the hope that it will be |
| 11 |
|
|
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty |
| 12 |
|
|
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 13 |
|
|
// General Lesser Public License for more details. You should have |
| 14 |
|
|
// received a copy of the GNU Lesser General Public License along with |
| 15 |
|
|
// gepetto-viewer. If not, see <http://www.gnu.org/licenses/>. |
| 16 |
|
|
|
| 17 |
|
|
#include <gepetto/viewer/blender-geom-writer.h> |
| 18 |
|
|
#include <gepetto/viewer/group-node.h> |
| 19 |
|
|
#include <gepetto/viewer/leaf-node-arrow.h> |
| 20 |
|
|
#include <gepetto/viewer/leaf-node-box.h> |
| 21 |
|
|
#include <gepetto/viewer/leaf-node-capsule.h> |
| 22 |
|
|
#include <gepetto/viewer/leaf-node-collada.h> |
| 23 |
|
|
#include <gepetto/viewer/leaf-node-cone.h> |
| 24 |
|
|
#include <gepetto/viewer/leaf-node-cylinder.h> |
| 25 |
|
|
#include <gepetto/viewer/leaf-node-face.h> |
| 26 |
|
|
#include <gepetto/viewer/leaf-node-ground.h> |
| 27 |
|
|
#include <gepetto/viewer/leaf-node-light.h> |
| 28 |
|
|
#include <gepetto/viewer/leaf-node-line.h> |
| 29 |
|
|
#include <gepetto/viewer/leaf-node-sphere.h> |
| 30 |
|
|
#include <gepetto/viewer/leaf-node-xyzaxis.h> |
| 31 |
|
|
#include <gepetto/viewer/node.h> |
| 32 |
|
|
#include <sys/stat.h> |
| 33 |
|
|
|
| 34 |
|
|
#include <algorithm> |
| 35 |
|
|
#include <osgDB/WriteFile> |
| 36 |
|
|
// #include <gepetto/viewer/node-rod.h> |
| 37 |
|
|
|
| 38 |
|
|
#include "log.hh" |
| 39 |
|
|
|
| 40 |
|
|
namespace gepetto { |
| 41 |
|
|
namespace viewer { |
| 42 |
|
|
namespace { |
| 43 |
|
|
const char indent[] = " "; |
| 44 |
|
|
const char end = '\n'; |
| 45 |
|
|
const char group[] = "##"; |
| 46 |
|
|
const char node[] = "#"; |
| 47 |
|
|
const char varMat[] = "material"; |
| 48 |
|
|
const char warning[] = "# Warning: "; |
| 49 |
|
|
const std::string varShape = "currentShape"; |
| 50 |
|
|
|
| 51 |
|
|
template <typename Vector> |
| 52 |
|
✗ |
std::ostream& writeVectorAsList(std::ostream& os, const Vector& v) { |
| 53 |
|
✗ |
os << "( "; |
| 54 |
|
✗ |
for (int i = 0; i < Vector::num_components; ++i) os << v[i] << ", "; |
| 55 |
|
✗ |
os << ")"; |
| 56 |
|
✗ |
return os; |
| 57 |
|
|
} |
| 58 |
|
|
|
| 59 |
|
|
template <> |
| 60 |
|
✗ |
std::ostream& writeVectorAsList<osg::Quat>(std::ostream& os, |
| 61 |
|
|
const osg::Quat& q) { |
| 62 |
|
✗ |
os << "( " << q.w() << ", " << q.x() << ", " << q.y() << ", " << q.z() |
| 63 |
|
✗ |
<< ", )"; |
| 64 |
|
✗ |
return os; |
| 65 |
|
|
} |
| 66 |
|
|
|
| 67 |
|
✗ |
std::ostream& writeRGB(std::ostream& os, const osgVector4& rgba) { |
| 68 |
|
✗ |
return os << "( " << rgba.r() << ", " << rgba.g() << ", " << rgba.b() |
| 69 |
|
✗ |
<< ", )"; |
| 70 |
|
|
} |
| 71 |
|
|
|
| 72 |
|
✗ |
void writeMaterial(std::ostream& os, const std::string& name, |
| 73 |
|
|
const osg::Material* mat, bool diffuse = true, |
| 74 |
|
|
bool ambient = false, bool specular = false) { |
| 75 |
|
✗ |
const osg::Material::Face face = osg::Material::FRONT; |
| 76 |
|
✗ |
os << varMat << " = bpy.data.materials.new(\"" << name << "\")" << end; |
| 77 |
|
✗ |
if (diffuse) |
| 78 |
|
✗ |
writeRGB(os << varMat << ".diffuse_color = ", mat->getDiffuse(face)) |
| 79 |
|
✗ |
<< end << varMat << ".diffuse_intensity = " << mat->getDiffuse(face).a() |
| 80 |
|
✗ |
<< end; |
| 81 |
|
✗ |
if (ambient) |
| 82 |
|
✗ |
writeRGB(os << varMat << ".ambient_color = ", mat->getAmbient(face)) |
| 83 |
|
✗ |
<< end << varMat << ".ambient_intensity = " << mat->getAmbient(face).a() |
| 84 |
|
✗ |
<< end; |
| 85 |
|
✗ |
if (specular) |
| 86 |
|
✗ |
writeRGB(os << varMat << ".specular_color = ", mat->getSpecular(face)) |
| 87 |
|
|
<< end << varMat |
| 88 |
|
✗ |
<< ".specular_intensity = " << mat->getSpecular(face).a() << end; |
| 89 |
|
|
} |
| 90 |
|
|
|
| 91 |
|
✗ |
void writeMaterial(std::ostream& os, const std::string& name, |
| 92 |
|
|
const osgVector4& rgbaDiffuse) { |
| 93 |
|
✗ |
os << varMat << " = bpy.data.materials.new(\"" << name << "\")" << end; |
| 94 |
|
✗ |
writeRGB(os << varMat << ".diffuse_color = ", rgbaDiffuse) |
| 95 |
|
✗ |
<< end << varMat << ".diffuse_intensity = " << rgbaDiffuse.a() << end; |
| 96 |
|
|
} |
| 97 |
|
|
|
| 98 |
|
|
template <typename NodeType> |
| 99 |
|
✗ |
void setColor(std::ostream& os, NodeType& node, const std::string& var) { |
| 100 |
|
✗ |
writeMaterial(os, node.getID() + "__mat", node.getColor()); |
| 101 |
|
✗ |
os << var << ".materials.append(" << varMat << ')' << end; |
| 102 |
|
|
} |
| 103 |
|
|
|
| 104 |
|
✗ |
void setColor(std::ostream& os, LeafNodeCollada& node) { |
| 105 |
|
✗ |
osg::Material* mat_ptr = dynamic_cast<osg::Material*>( |
| 106 |
|
✗ |
node.getOsgNode()->getStateSet()->getAttribute( |
| 107 |
|
✗ |
osg::StateAttribute::MATERIAL)); |
| 108 |
|
✗ |
if (mat_ptr != NULL) { // Color was set by URDF |
| 109 |
|
✗ |
writeMaterial(os, node.getID() + "__mat", mat_ptr, true, false, false); |
| 110 |
|
✗ |
os << "setMaterial (imported_objects, " << varMat << ')' << end; |
| 111 |
|
|
} |
| 112 |
|
|
} |
| 113 |
|
|
|
| 114 |
|
✗ |
void loadMeshFile(std::ostream& os, const std::string& nodeName, |
| 115 |
|
|
const std::string fn) { |
| 116 |
|
✗ |
os << "tagObjects()" << end; |
| 117 |
|
|
|
| 118 |
|
✗ |
std::string ext = fn.substr(fn.find_last_of(".") + 1, fn.size()); |
| 119 |
|
✗ |
std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower); |
| 120 |
|
✗ |
if (ext == "obj") { |
| 121 |
|
|
os << "bpy.ops.import_scene.obj (filepath=\"" << fn |
| 122 |
|
✗ |
<< "\", axis_forward='Y', axis_up='Z')" << end; |
| 123 |
|
✗ |
} else if (ext == "dae") { |
| 124 |
|
✗ |
os << "bpy.ops.wm.collada_import (filepath=\"" << fn << "\")" << end; |
| 125 |
|
✗ |
} else if (ext == "stl") { |
| 126 |
|
✗ |
os << "bpy.ops.import_mesh.stl (filepath=\"" << fn << "\")" << end; |
| 127 |
|
|
} else { |
| 128 |
|
✗ |
log() << "Extension of file " << fn << " with name " << nodeName |
| 129 |
|
|
<< " is not known." << end |
| 130 |
|
|
<< "You can load the file manually and add it to the empty object " |
| 131 |
|
|
"called " |
| 132 |
|
✗ |
<< nodeName << end << "To fix the issue, upate" __FILE__ ":" |
| 133 |
|
✗ |
<< __LINE__ << std::endl; |
| 134 |
|
✗ |
os << "# Here goes the content of file " << fn << end; |
| 135 |
|
✗ |
os << "# To fix it, upate" __FILE__ ":" << __LINE__ << end; |
| 136 |
|
|
} |
| 137 |
|
|
|
| 138 |
|
|
os << "imported_objects = getNonTaggedObjects ()" << end |
| 139 |
|
|
<< "print(imported_objects)" << end << varShape << " = makeEmpty(\"" |
| 140 |
|
|
<< nodeName << "__shape\")" << end << "setLocQuatSca(" << varShape << ')' |
| 141 |
|
✗ |
<< end << "setParent (imported_objects, " << varShape << ')' << end; |
| 142 |
|
|
} |
| 143 |
|
|
} // namespace |
| 144 |
|
|
|
| 145 |
|
✗ |
BlenderGeomWriterVisitor::BlenderGeomWriterVisitor(const std::string& filename) |
| 146 |
|
✗ |
: NodeVisitor(false), filename_(filename), nodeCount_(0), groupDepth_(0) { |
| 147 |
|
✗ |
bool isNew = !openFile(); |
| 148 |
|
✗ |
const std::string comment = (isNew ? "" : "# "); |
| 149 |
|
✗ |
out() << comment << "import bpy" << end << end << comment |
| 150 |
|
|
<< "## Start convenient functions" << end << comment |
| 151 |
|
|
<< "def checkConf():" << end << comment |
| 152 |
|
|
<< " if bpy.app.version[0:2] != (2, 75):" << end << comment |
| 153 |
|
|
<< " print(\"Using blender version \" + str(bpy.app.version))" << end |
| 154 |
|
|
<< comment << " print(\"Developed under version 2.75.0.\")" << end |
| 155 |
|
|
<< comment << " return False" << end << comment |
| 156 |
|
|
<< " if bpy.context.scene.render.engine != 'CYCLES':" << end << comment |
| 157 |
|
|
<< " print(\"Cycles renderer is prefered\")" << end << comment |
| 158 |
|
|
<< " return False" << end << comment << " return True" << end |
| 159 |
|
|
<< comment << end << comment << "taggedObjects = list()" << end |
| 160 |
|
|
<< comment << "def tagObjects ():" << end << comment |
| 161 |
|
|
<< " global taggedObjects" << end << comment |
| 162 |
|
|
<< " taggedObjects = list ()" << end << comment |
| 163 |
|
|
<< " for obj in bpy.data.objects:" << end << comment |
| 164 |
|
|
<< " taggedObjects.append (obj.name)" << end << comment << "" << end |
| 165 |
|
|
<< comment << "def getNonTaggedObjects ():" << end << comment |
| 166 |
|
|
<< " global taggedObjects" << end << comment |
| 167 |
|
|
<< " return [obj for obj in bpy.data.objects if obj.name not in " |
| 168 |
|
|
"taggedObjects]" |
| 169 |
|
|
<< end << comment << "" << end << comment |
| 170 |
|
|
<< "def setParent (children, parent):" << end << comment |
| 171 |
|
|
<< " for child in children:" << end << comment |
| 172 |
|
|
<< " child.parent = parent" << end << end << comment << "" << end |
| 173 |
|
|
<< comment << "def setMaterial (children, mat):" << end << comment |
| 174 |
|
|
<< " for child in children:" << end << comment |
| 175 |
|
|
<< " child.data.materials.append(mat)" << end << end << comment << "" |
| 176 |
|
|
<< end << comment << "def makeEmpty(objname):" << end << comment |
| 177 |
|
|
<< " bpy.ops.object.empty_add()" << end << comment |
| 178 |
|
|
<< " bpy.context.object.name = objname" << end << comment |
| 179 |
|
|
<< " return bpy.context.object" << end << comment << "" << end |
| 180 |
|
|
<< comment |
| 181 |
|
|
<< "def setLocQuatSca(obj, loc = None, quat=None, sca=None):" << end |
| 182 |
|
|
<< comment << " if loc is not None: obj.location = loc" << end |
| 183 |
|
|
<< comment << " if quat is not None: " << end << comment |
| 184 |
|
|
<< " obj.rotation_mode = 'QUATERNION'" << end << comment |
| 185 |
|
|
<< " obj.rotation_quaternion = quat" << end << comment |
| 186 |
|
|
<< " if sca is not None: obj.scale = sca" << end << comment << "" |
| 187 |
|
|
<< end << comment |
| 188 |
|
|
<< "def makePolyLine(objname, curvename, cList):" << end << comment |
| 189 |
|
|
<< " curvedata = bpy.data.curves.new(name=curvename, type='CURVE')" |
| 190 |
|
|
<< end << comment << " curvedata.dimensions = '3D'" << end << comment |
| 191 |
|
|
<< " curvedata.fill_mode = 'FULL'" << end << comment |
| 192 |
|
|
<< " curvedata.bevel_depth = 0.01" << end << comment |
| 193 |
|
|
<< " curvedata.bevel_resolution = 10" << end << comment << "" << end |
| 194 |
|
|
<< comment << " objectdata = bpy.data.objects.new(objname, curvedata)" |
| 195 |
|
|
<< end << comment << " objectdata.location = (0,0,0) #object origin" |
| 196 |
|
|
<< end << comment << " bpy.context.scene.objects.link(objectdata)" |
| 197 |
|
|
<< end << comment << " w = 1.0" << end << comment |
| 198 |
|
|
<< " polyline = curvedata.splines.new('POLY')" << end << comment |
| 199 |
|
|
<< " polyline.points.add(len(cList)-1)" << end << comment |
| 200 |
|
|
<< " for num in range(len(cList)):" << end << comment |
| 201 |
|
|
<< " x, y, z = cList[num]" << end << comment |
| 202 |
|
|
<< " polyline.points[num].co = (x, y, z, w)" << end << comment |
| 203 |
|
|
<< " return objectdata, curvedata" << end << comment << "" << end |
| 204 |
|
|
<< end << comment << "## End of convenient functions" << end << comment |
| 205 |
|
|
<< "checkConf()" << end << end << comment |
| 206 |
|
|
<< "bpy.ops.view3d.snap_cursor_to_center()" << end << end << comment |
| 207 |
|
✗ |
<< "obj_stack = []" << end; |
| 208 |
|
|
} |
| 209 |
|
|
|
| 210 |
|
✗ |
bool BlenderGeomWriterVisitor::openFile() { |
| 211 |
|
|
struct stat buffer; |
| 212 |
|
✗ |
bool ret = (stat(filename_.c_str(), &buffer) == 0); |
| 213 |
|
✗ |
file_.open(filename_.c_str(), std::ofstream::out | std::ofstream::app); |
| 214 |
|
✗ |
if (!file_.is_open()) |
| 215 |
|
✗ |
throw std::ios_base::failure("Unable to open file " + filename_); |
| 216 |
|
✗ |
return ret; |
| 217 |
|
|
} |
| 218 |
|
|
|
| 219 |
|
✗ |
void BlenderGeomWriterVisitor::apply(Node& node) { |
| 220 |
|
|
std::cerr << "This function should not be called. Type of node " |
| 221 |
|
✗ |
<< node.getID() << " may be unknown" << std::endl; |
| 222 |
|
✗ |
standardApply(node); |
| 223 |
|
|
} |
| 224 |
|
✗ |
void BlenderGeomWriterVisitor::apply(GroupNode& node) { |
| 225 |
|
✗ |
for (std::size_t i = 0; i < groupDepth_ + 1; ++i) out() << group; |
| 226 |
|
✗ |
out() << " Group " << node.getID() << end; |
| 227 |
|
|
|
| 228 |
|
✗ |
out() << "bpy.ops.object.empty_add()" << end << "bpy.context.object.name = \"" |
| 229 |
|
✗ |
<< node.getID() << '"' << end; |
| 230 |
|
|
// Set parent of this group |
| 231 |
|
✗ |
out() << "if obj_stack: bpy.context.object.parent = obj_stack[-1]" << end; |
| 232 |
|
|
|
| 233 |
|
✗ |
++groupDepth_; |
| 234 |
|
✗ |
out() << "obj_stack.append(bpy.context.object)" << end; |
| 235 |
|
✗ |
NodeVisitor::apply(static_cast<Node&>(node)); |
| 236 |
|
✗ |
--groupDepth_; |
| 237 |
|
✗ |
out() << "obj_stack.pop()" << end; |
| 238 |
|
|
|
| 239 |
|
✗ |
for (std::size_t i = 0; i < groupDepth_ + 1; ++i) out() << group; |
| 240 |
|
✗ |
out() << end; |
| 241 |
|
|
} |
| 242 |
|
✗ |
void BlenderGeomWriterVisitor::apply(LeafNodeArrow& node) { |
| 243 |
|
✗ |
unimplemented("LeafNodeArrow", node); |
| 244 |
|
|
} |
| 245 |
|
✗ |
void BlenderGeomWriterVisitor::apply(LeafNodeBox& node) { |
| 246 |
|
✗ |
out() << "bpy.ops.mesh.primitive_cube_add ()" << end << varShape |
| 247 |
|
✗ |
<< " = bpy.context.object" << end; |
| 248 |
|
|
|
| 249 |
|
✗ |
setColor(out(), node, varShape + ".data"); |
| 250 |
|
|
|
| 251 |
|
|
// scale should use getHalfAxis() * getScale() |
| 252 |
|
✗ |
standardApply(node, node.getHalfAxis()); |
| 253 |
|
|
} |
| 254 |
|
✗ |
void BlenderGeomWriterVisitor::apply(LeafNodeCapsule& node) { |
| 255 |
|
✗ |
unimplemented("LeafNodeCapsule", node); |
| 256 |
|
|
} |
| 257 |
|
✗ |
void BlenderGeomWriterVisitor::apply(LeafNodeCollada& node) { |
| 258 |
|
✗ |
loadMeshFile(out(), node.getID(), node.meshFilePath()); |
| 259 |
|
|
|
| 260 |
|
✗ |
setColor(out(), node); |
| 261 |
|
|
|
| 262 |
|
✗ |
standardApply(node); |
| 263 |
|
|
} |
| 264 |
|
✗ |
void BlenderGeomWriterVisitor::apply(LeafNodeCone& node) { |
| 265 |
|
✗ |
out() << "bpy.ops.mesh.primitive_cone_add (radius1=" << node.getRadius() |
| 266 |
|
✗ |
<< ", depth=" << node.getHeight() << ')' << end << varShape |
| 267 |
|
✗ |
<< " = bpy.context.object" << end; |
| 268 |
|
✗ |
setColor(out(), node, varShape + ".data"); |
| 269 |
|
✗ |
standardApply(node); |
| 270 |
|
|
} |
| 271 |
|
✗ |
void BlenderGeomWriterVisitor::apply(LeafNodeCylinder& node) { |
| 272 |
|
✗ |
out() << "bpy.ops.mesh.primitive_cylinder_add (radius=" << node.getRadius() |
| 273 |
|
✗ |
<< ", depth=" << node.getHeight() << ')' << end << varShape |
| 274 |
|
✗ |
<< " = bpy.context.object" << end; |
| 275 |
|
✗ |
setColor(out(), node, varShape + ".data"); |
| 276 |
|
✗ |
standardApply(node); |
| 277 |
|
|
} |
| 278 |
|
✗ |
void BlenderGeomWriterVisitor::apply(LeafNodeFace& node) { |
| 279 |
|
✗ |
unimplemented("LeafNodeFace", node); |
| 280 |
|
|
} |
| 281 |
|
✗ |
void BlenderGeomWriterVisitor::apply(LeafNodeGround& node) { |
| 282 |
|
✗ |
unimplemented("LeafNodeGround", node); |
| 283 |
|
|
} |
| 284 |
|
✗ |
void BlenderGeomWriterVisitor::apply(LeafNodeLight& node) { |
| 285 |
|
✗ |
unimplemented("LeafNodeLight", node); |
| 286 |
|
|
} |
| 287 |
|
✗ |
void BlenderGeomWriterVisitor::apply(LeafNodeLine& node) { |
| 288 |
|
✗ |
if (node.getMode() != GL_LINE_STRIP) { |
| 289 |
|
✗ |
const char varCurve[] = "currentCurve"; |
| 290 |
|
|
|
| 291 |
|
✗ |
::osg::Vec3ArrayRefPtr points = node.getPoints(); |
| 292 |
|
✗ |
out() << "points = ["; |
| 293 |
|
✗ |
for (std::size_t i = 0; i < points->size(); ++i) |
| 294 |
|
✗ |
writeVectorAsList(out(), points->at(i)) << ','; |
| 295 |
|
✗ |
out() << ']' << end; |
| 296 |
|
|
|
| 297 |
|
✗ |
out() << varShape << ", " << varCurve << " = makePolyLine(\"" |
| 298 |
|
✗ |
<< node.getID() << "__shape\", \"" << node.getID() |
| 299 |
|
✗ |
<< "__curve\", points)" << end; |
| 300 |
|
|
|
| 301 |
|
✗ |
setColor(out(), node, varCurve); |
| 302 |
|
✗ |
} else { |
| 303 |
|
✗ |
std::stringstream ss; |
| 304 |
|
✗ |
ss << filename_ << "_curve" << nodeCount_ << ".dae"; |
| 305 |
|
✗ |
std::string fn = ss.str(); |
| 306 |
|
✗ |
osg::ref_ptr<osgDB::Options> os = new osgDB::Options; |
| 307 |
|
✗ |
os->setOptionString("NoExtras"); |
| 308 |
|
✗ |
osgDB::writeNodeFile(*node.asGroup(), fn, os.get()); |
| 309 |
|
|
|
| 310 |
|
✗ |
loadMeshFile(out(), node.getID(), fn); |
| 311 |
|
|
// setColor(out(), node); |
| 312 |
|
|
} |
| 313 |
|
✗ |
standardApply(node); |
| 314 |
|
|
} |
| 315 |
|
✗ |
void BlenderGeomWriterVisitor::apply(LeafNodeSphere& node) { |
| 316 |
|
✗ |
out() << "bpy.ops.mesh.primitive_ico_sphere_add (size=" << node.getRadius() |
| 317 |
|
✗ |
<< ")" << end << varShape << " = bpy.context.object" << end; |
| 318 |
|
✗ |
setColor(out(), node, varShape + ".data"); |
| 319 |
|
✗ |
standardApply(node); |
| 320 |
|
|
} |
| 321 |
|
✗ |
void BlenderGeomWriterVisitor::apply(LeafNodeXYZAxis& node) { |
| 322 |
|
✗ |
unimplemented("LeafNodeXYZAxis", node); |
| 323 |
|
|
} |
| 324 |
|
|
|
| 325 |
|
✗ |
void BlenderGeomWriterVisitor::standardApply(Node& node, osgVector3 scale) { |
| 326 |
|
✗ |
const osgVector3 s = node.getScale(); |
| 327 |
|
✗ |
scale[0] *= s[0]; |
| 328 |
|
✗ |
scale[1] *= s[1]; |
| 329 |
|
✗ |
scale[2] *= s[2]; |
| 330 |
|
✗ |
const std::string& id = node.getID(); |
| 331 |
|
|
// Set name |
| 332 |
|
✗ |
out() << varShape << ".name = \"" << id << "__shape\"" << end |
| 333 |
|
✗ |
<< "setLocQuatSca(" << varShape << ", "; |
| 334 |
|
✗ |
writeVectorAsList(out() << "loc = ", node.getStaticPosition()) << ", "; |
| 335 |
|
✗ |
writeVectorAsList(out() << "quat = ", node.getStaticRotation()) << ", "; |
| 336 |
|
✗ |
writeVectorAsList(out() << "sca = ", scale) << ')' << end; |
| 337 |
|
✗ |
out() << "obj = makeEmpty(\"" << id << "\")" << end << "setLocQuatSca(obj)" |
| 338 |
|
✗ |
<< end << varShape << ".parent = obj" << end; |
| 339 |
|
|
// Set parent group |
| 340 |
|
✗ |
out() << "if obj_stack: obj.parent = obj_stack[-1]" << end; |
| 341 |
|
|
|
| 342 |
|
✗ |
++nodeCount_; |
| 343 |
|
✗ |
NodeVisitor::apply(node); |
| 344 |
|
|
} |
| 345 |
|
|
|
| 346 |
|
✗ |
void BlenderGeomWriterVisitor::unimplemented(const char* type, Node& node) { |
| 347 |
|
✗ |
log() << type << " is not implemented. " << node.getID() << " not added" |
| 348 |
|
✗ |
<< std::endl; |
| 349 |
|
✗ |
out() << varShape << " = makeEmpty(\"" << node.getID() << "\")" << end; |
| 350 |
|
✗ |
standardApply(node); |
| 351 |
|
|
} |
| 352 |
|
|
} // namespace viewer |
| 353 |
|
|
} // namespace gepetto |
| 354 |
|
|
|