1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
|
// obj.cmd
// Surface Evolver script for creating Wavefront OBJ format 3D graphics file.
// Result file requires EvolverOBJcolors.mtl file in same directory.
// File format reference: http://www.martinreddy.net/gfx/3d/OBJ.spec
// Edges are shown as 4-sided tubes. The relative tube diameter
// can be adjusted where actual_tube_radius is set below.
/* Usage:
Set which edges and facets you want to show with the
"show edge where ..." and "show facet where ..." commands.
Set obj_double_sided to 1 if you want back sides of facets.
Set obj_edge_flag to 0 if you want no edges shown.
Run obj and redirect output to file, for example
obj >>> "filename.obj"
*/
define vertex attribute obj_vnum integer
obj_double_sided := 0 // set to 1 to do front and back facets
obj_edge_flag := 1 // set to 1 to do small tubes around shown edges
// or 0 to do edges as lines
obj_tube_radius := 0.002; // relative size of edge tubes.
obj_edge_tubes := {
local tube_sides,t_angle,actual_tube_radius;
local ax,ay,az,bx,by,bz,mag,inx,cinx;
// Doing edges one by one, using negative relative vertex indexing, so
// vertices can be listed with the tube faces.
tube_sides := 4;
t_angle := 2*pi/tube_sides;
actual_tube_radius := obj_tube_radius*sqrt(max(vertex,x^2+y^2+z^2));
for ( cinx := 0 ; cinx <= 15 ; cinx += 1 )
{ printf "usemtl color%d\n",cinx;
foreach edge ee where color == cinx and show do
{
// find two orthogonal directions to edge; if possible,
// one along adjacent facet
if ee.valence > 0 then
{ ax := ee.facet[1].x;
ay := ee.facet[1].y;
az := ee.facet[1].z;
}
else
{ if abs(ee.x) < abs(ee.y) and abs(ee.x) < abs(ee.z) then
{ ax := 1; ay := 0; az := 0;}
else if abs(ee.y) < abs(ee.z) then
{ ax := 0; ay := 1; az := 0; }
else
{ ax := 0; ay := 0; az := 1; };
};
bx := ay*ee.z - az*ee.y;
by := az*ee.x - ax*ee.z;
bz := ax*ee.y - ay*ee.x;
ax := by*ee.z - bz*ee.y;
ay := bz*ee.x - bx*ee.z;
az := bx*ee.y - by*ee.x;
// normalize to radius
mag := sqrt(ax^2+ay^2+az^2);
if mag <= 0 then continue;
ax *= actual_tube_radius/mag;
ay *= actual_tube_radius/mag;
az *= actual_tube_radius/mag;
mag := sqrt(bx^2+by^2+bz^2);
if mag <= 0 then continue;
bx *= actual_tube_radius/mag;
by *= actual_tube_radius/mag;
bz *= actual_tube_radius/mag;
for ( inx := 0 ; inx < tube_sides ; inx += 1 )
{
printf "v %f %f %f\n",ee.vertex[1].x+ax*cos(inx*t_angle)+bx*sin(inx*t_angle),
ee.vertex[1].y+ay*cos(inx*t_angle)+by*sin(inx*t_angle),
ee.vertex[1].z+az*cos(inx*t_angle)+bz*sin(inx*t_angle);
printf "v %f %f %f\n",ee.vertex[1].x+ee.x+ax*cos(inx*t_angle)+bx*sin(inx*t_angle),
ee.vertex[1].y+ee.y+ay*cos(inx*t_angle)+by*sin(inx*t_angle),
ee.vertex[1].z+ee.z+az*cos(inx*t_angle)+bz*sin(inx*t_angle);
};
/* quads should work, but Meshlab interprets them as single triangles!
printf "f -6 -5 -7 -8\n";
printf "f -4 -3 -5 -6\n";
printf "f -2 -1 -3 -4\n";
printf "f -8 -7 -1 -2\n";
*/
printf "f -6 -5 -7\n";
printf "f -6 -7 -8\n";
printf "f -4 -3 -5\n";
printf "f -4 -5 -6\n";
printf "f -2 -1 -3\n";
printf "f -2 -3 -4\n";
printf "f -8 -7 -1\n";
printf "f -8 -1 -2\n";
}
}
} // end obj_edge_tubes
// Edges as lines
obj_edge_lines := {
local cinx;
for ( cinx := 0 ; cinx <= 15 ; cinx += 1 )
{ printf "usemtl color%d\n",cinx;
foreach edge ee where color == cinx and show do
{
printf "l %d %d\n",ee.vertex[1].obj_vnum,
ee.vertex[2].obj_vnum;
}
}
} // end obj_edge_lines
obj := {
local vnumber,cinx;
if rgb_colors then
{ errprintf "obj error: obj script does not do RGB colors; do rgb_colors off.\n";
abort;
};
if torus then
{ errprintf "Cannot run 'obj' command in torus mode. Do 'detorus' first.\n";
abort;
};
if symmetry_group then
{ errprintf "Cannot run 'obj' command in symmetry group mode. Do 'detorus' first.\n";
abort;
};
if space_dimension != 3 then
{ errprintf "The 'obj' command must be run in three-dimensional space.\n";
abort;
};
if surface_dimension == 1 then
{ errprintf "The 'obj' command is not meant for the string model.\n";
abort;
};
if simplex_representation then
{ errprintf "The 'obj' command is not meant for the simplex model.\n";
abort;
};
if lagrange_order >= 2 then
{ errprintf "The 'obj' command is meant for the linear model, not quadratic or Lagrange.\n";
abort;
};
printf "# OBJ version of %s \n",datafilename;
printf "# Produced by Surface Evolver with obj.cmd script\n\n";
printf "mtllib EvolverOBJcolors.mtl\n\n";
vnumber := 0;
foreach vertex vv do
{ printf "v %f %f %f\n",vv.x,vv.y,vv.z;
vnumber += 1;
vv.obj_vnum := vnumber;
};
for ( cinx := 0 ; cinx <= 15 ; cinx += 1 )
{ printf "usemtl color%d\n",cinx;
foreach facet ff where show and frontcolor == cinx do
printf "f %d %d %d\n",ff.vertex[1].obj_vnum,
ff.vertex[2].obj_vnum,ff.vertex[3].obj_vnum;
if obj_double_sided then
foreach facet ff where show and backcolor == cinx do
printf "f %d %d %d\n",ff.vertex[1].obj_vnum,
ff.vertex[3].obj_vnum,ff.vertex[2].obj_vnum;
};
if obj_edge_flag then
obj_edge_tubes
else
obj_edge_lines;
} // end obj
/* Usage:
Set which edges and facets you want to show with the
"show edge where ..." and "show facet where ..." commands.
Set obj_double_sided to 1 if you want back sides of facets.
Set obj_edge_flag to 0 if you want no edges shown.
Run obj and redirect output to file, for example
obj >>> "filename.obj"
*/
|