The source code needs some implementation of point3 and point4.
/* Duopyramid VRML generator
* (C) 2012-2013 CC-By 3.0 Claudio Rocchini
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "point3.h"
#include "point4.h"
const double PI = 3.1415926535897932384626433832795;
const double S = 100;
const double K1 = 0.03;
const double K2 = 0.06;
static void draw_sphere( FILE * fo, const point3 & p, double r ) {
fprintf(fo,
"Separator{\n"
"\tTranslation { translation %g %g %g }\n"
"\tSphere { radius %g }\n"
"}\n"
,p.x*S,p.y*S,p.z*S,r*S
);
}
static void draw_edge( FILE * fo, const point3 & p1, double r1, const point3 & p2, double r2 ) {
point3 d = p2-p1; double l = lenght(d); normalize(d);
point3 c = (p1+p2)/2.0;
point3 Y(0,1,0);
point3 rd = d^Y; normalize(rd); double ra = -acos(d*Y);
double r = (r1+r2)/2;
fprintf(fo,
"Separator{\n"
"\tTranslation { translation %g %g %g }\n"
"\t\tRotation { rotation %g %g %g %g }\n"
"\t\tCylinder {\n\t\tparts SIDES\n"
"\t\tradius %g\n\t\theight %g\n"
"\t}\n}\n"
,c.x*S,c.y*S,c.z*S
,rd.x,rd.y,rd.z,ra
,r*S,l*S
);
}
void rotate( point4 & p ) {
double theta = PI/2; double cs = cos(theta); double sn = sin(theta);
double z = p.y;
double v = p.v;
p.y = z * cs - v * sn;
p.v = z * sn + v * cs;
}
void proj( const point4 & v, point3 & w, double & R ) {
w.x = v.x / (2-v.v); w.y = v.y / (2-v.v);
w.z = v.z / (2-v.v); R = 1.0 / (2-v.v);
}
int main() {
const int P = 6;
const int Q = 4;
int i,j;
const int NV = P*Q; point4 VNV];
for(i=0;i<P;++i) {
double ai = i*2*PI/P;
for(j=0;j<Q;++j) {
double aj = j*2*PI/Q;
Vi*Q+j].x = cos(ai); Vi*Q+j].y = sin(ai);
Vi*Q+j].z = cos(aj); Vi*Q+j].v = sin(aj);
}
}
const int NV2 = P+Q; point4 V2NV2];
for(i=0;i<P;++i) {
double a1 = i*2*PI/P; double x1 = cos(a1); double y1 = sin(a1);
double a2 = ((i+1)%P)*2*PI/P; double x2 = cos(a2); double y2 = sin(a2);
V2i+0].x = (x1+x2)/2; V2i+0].z = 0;
V2i+0].y = (y1+y2)/2; V2i+0].v = 0;
}
for(j=0;j<Q;++j) {
double a1 = j*2*PI/Q; double z1 = cos(a1); double v1 = sin(a1);
double a2 = ((j+1)%Q)*2*PI/Q; double z2 = cos(a2); double v2 = sin(a2);
V2j+P].x = 0; V2j+P].z = (z1+z2)/2;
V2j+P].y = 0; V2j+P].v = (v1+v2)/2;
}
point3 VPNV]; double RNV];
point3 VP2NV2]; double R2NV2];
for(i=0;i<NV;++i) {
rotate(Vi]); proj(Vi],VPi],Ri]);
}
for(i=0;i<NV2;++i) {
rotate(V2i]); proj(V2i],VP2i],R2i]);
}
FILE * fo = fopen("duppyramid.wrl","w");
fprintf(fo, "#VRML V1.0 ascii\n" );
fprintf(fo,
"Material {\n"
"\tdiffuseColor [0.4 0.1 0.0]\n"
"\tspecularColor [0.7 0.7 0.7]\n"
"\temissiveColor[]\n"
"\tambientColor[0.4 0.4 0.4]\n"
"\tshininess 0.16\n"
"\ttransparency 0.5\n"
"}\n"
);
for(i=0;i<NV;++i)
draw_sphere(fo,VPi],Ri*K2);
for(j=0;j<Q;++j)
for(i=0;i<P;++i) {
draw_edge(fo,VPi*Q+j],Ri*Q+j*K1,VP[((i+1)%P)*Q+j],R[((i+1)%P)*Q+j*K1);
draw_edge(fo,VPi*Q+j],Ri*Q+j*K1,VPi*Q+(j+1)%Q],Ri*Q+(j+1)%Q*K1);
}
fprintf(fo,
"Material {\n"
"\tdiffuseColor [0.1 0.2 0.5]\n"
"\tspecularColor [0.7 0.7 0.7]\n"
"\temissiveColor[]\n"
"\tambientColor[0.4 0.4 0.4]\n"
"\tshininess 0.16\n"
"\ttransparency 0.0\n"
"}\n"
);
for(i=0;i<NV2;++i)
draw_sphere(fo,VP2i],R2i*K2);
for(i=0;i<P;++i)
draw_edge(fo,VP2i],R2i*K1,VP2[(i+1)%P],R2[(i+1)%P*K1);
for(j=0;j<Q;++j)
draw_edge(fo,VP2P+j],R2P+j*K1,VP2P+(j+1)%Q],R2P+(j+1)%Q*K1);
for(i=0;i<P;++i)
for(j=0;j<Q;++j)
draw_edge(fo,VP20+i],R20+i*K1,VP2P+j],R2P+j*K1);
fclose(fo);
return 0;
}