1 /***** 2 * drawsurface.h 3 * 4 * Stores a surface that has been added to a picture. 5 *****/ 6 7 #ifndef DRAWSURFACE_H 8 #define DRAWSURFACE_H 9 10 #include "drawelement.h" 11 #include "arrayop.h" 12 #include "path3.h" 13 #include "beziercurve.h" 14 #include "bezierpatch.h" 15 16 namespace run { 17 void inverse(double *a, size_t n); 18 } 19 20 const string need3pens="array of 3 pens required"; 21 22 namespace camp { 23 24 #ifdef HAVE_LIBGLM 25 void storecolor(GLfloat *colors, int i, const vm::array &pens, int j); 26 #endif 27 28 class drawSurface : public drawElement { 29 protected: 30 triple *controls; 31 size_t ncontrols; 32 triple center; 33 bool straight; // True iff Bezier patch is planar and has straight edges. 34 prc::RGBAColour diffuse; 35 prc::RGBAColour emissive; 36 prc::RGBAColour specular; 37 prc::RGBAColour *colors; 38 double opacity; 39 double shininess; 40 double metallic; 41 double fresnel0; 42 bool invisible; 43 Interaction interaction; 44 bool billboard; 45 size_t centerIndex; 46 47 triple Min,Max; 48 int digits; 49 bool primitive; 50 51 public: 52 #ifdef HAVE_GL 53 BezierCurve C; 54 bool transparent; 55 #endif 56 wrongsize()57 string wrongsize() { 58 return (ncontrols == 16 ? "4x4" : "triangular")+ 59 string(" array of triples and array of 4 pens required"); 60 } 61 init()62 void init() { 63 #ifdef HAVE_LIBOSMESA 64 billboard=false; 65 #else 66 billboard=interaction == BILLBOARD; 67 #endif 68 centerIndex=0; 69 } 70 71 drawSurface(const vm::array& g, size_t ncontrols, triple center, 72 bool straight, const vm::array&p, double opacity, 73 double shininess, double metallic, double fresnel0, 74 const vm::array &pens, Interaction interaction, int digits, 75 bool primitive=true, const string& key="") : drawElement(key)76 drawElement(key), ncontrols(ncontrols), center(center), straight(straight), 77 opacity(opacity), shininess(shininess), metallic(metallic), 78 fresnel0(fresnel0), interaction(interaction), digits(digits), 79 primitive(primitive) { 80 init(); 81 if(checkArray(&g) != 4 || checkArray(&p) != 3) 82 reportError(wrongsize()); 83 84 size_t k=0; 85 controls=new(UseGC) triple[ncontrols]; 86 for(unsigned int i=0; i < 4; ++i) { 87 vm::array *gi=vm::read<vm::array*>(g,i); 88 size_t n=(ncontrols == 16 ? 4 : i+1); 89 if(checkArray(gi) != n) 90 reportError(wrongsize()); 91 for(unsigned int j=0; j < n; ++j) 92 controls[k++]=vm::read<triple>(gi,j); 93 } 94 95 pen surfacepen=vm::read<camp::pen>(p,0); 96 invisible=surfacepen.invisible(); 97 98 diffuse=rgba(surfacepen); 99 emissive=rgba(vm::read<camp::pen>(p,1)); 100 specular=rgba(vm::read<camp::pen>(p,2)); 101 102 size_t nodes=(ncontrols == 16 ? 4 : 3); 103 size_t size=checkArray(&pens); 104 if(size > 0) { 105 if(size != nodes) reportError("one vertex pen required per node"); 106 colors=new(UseGC) prc::RGBAColour[nodes]; 107 for(size_t i=0; i < nodes; ++i) 108 colors[i]=rgba(vm::read<camp::pen>(pens,i)); 109 } else colors=NULL; 110 } 111 drawSurface(const double * t,const drawSurface * s)112 drawSurface(const double* t, const drawSurface *s) : 113 drawElement(s->KEY), ncontrols(s->ncontrols), straight(s->straight), 114 diffuse(s->diffuse), emissive(s->emissive), specular(s->specular), 115 colors(s->colors), opacity(s->opacity), shininess(s->shininess), 116 metallic(s->metallic), fresnel0(s->fresnel0), invisible(s->invisible), 117 interaction(s->interaction), digits(s->digits), primitive(s->primitive) { 118 init(); 119 if(s->controls) { 120 controls=new(UseGC) triple[ncontrols]; 121 for(unsigned int i=0; i < ncontrols; ++i) 122 controls[i]=t*s->controls[i]; 123 } else controls=NULL; 124 125 center=t*s->center; 126 } 127 ~drawSurface()128 virtual ~drawSurface() {} 129 is3D()130 bool is3D() {return true;} 131 }; 132 133 class drawBezierPatch : public drawSurface { 134 public: 135 #ifdef HAVE_GL 136 BezierPatch S; 137 #endif 138 drawBezierPatch(const vm::array & g,triple center,bool straight,const vm::array & p,double opacity,double shininess,double metallic,double fresnel0,const vm::array & pens,Interaction interaction,int digits,bool primitive)139 drawBezierPatch(const vm::array& g, triple center, bool straight, 140 const vm::array&p, double opacity, double shininess, 141 double metallic, double fresnel0, const vm::array &pens, 142 Interaction interaction, int digits, bool primitive) : 143 drawSurface(g,16,center,straight,p,opacity,shininess,metallic,fresnel0, 144 pens,interaction,digits,primitive) {} 145 drawBezierPatch(const double * t,const drawBezierPatch * s)146 drawBezierPatch(const double* t, const drawBezierPatch *s) : 147 drawSurface(t,s) {} 148 149 void bounds(const double* t, bbox3& b); 150 151 void ratio(const double* t, pair &b, double (*m)(double, double), 152 double fuzz, bool &first); 153 meshinit()154 void meshinit() { 155 if(billboard) 156 centerIndex=centerindex(center); 157 } 158 159 bool write(prcfile *out, unsigned int *, double, groupsmap&); 160 bool write(jsfile *out); 161 162 void render(double, const triple& b, const triple& B, 163 double perspective, bool remesh); 164 drawElement *transformed(const double* t); 165 }; 166 167 class drawBezierTriangle : public drawSurface { 168 public: 169 #ifdef HAVE_GL 170 BezierTriangle S; 171 #endif 172 drawBezierTriangle(const vm::array & g,triple center,bool straight,const vm::array & p,double opacity,double shininess,double metallic,double fresnel0,const vm::array & pens,Interaction interaction,int digits,bool primitive)173 drawBezierTriangle(const vm::array& g, triple center, bool straight, 174 const vm::array&p, double opacity, double shininess, 175 double metallic, double fresnel0, const vm::array &pens, 176 Interaction interaction, int digits, bool primitive) : 177 drawSurface(g,10,center,straight,p,opacity,shininess,metallic,fresnel0, 178 pens,interaction,digits,primitive) {} 179 drawBezierTriangle(const double * t,const drawBezierTriangle * s)180 drawBezierTriangle(const double* t, const drawBezierTriangle *s) : 181 drawSurface(t,s) {} 182 183 void bounds(const double* t, bbox3& b); 184 185 void ratio(const double* t, pair &b, double (*m)(double, double), 186 double fuzz, bool &first); 187 meshinit()188 void meshinit() { 189 if(billboard) 190 centerIndex=centerindex(center); 191 } 192 193 bool write(prcfile *out, unsigned int *, double, groupsmap&); 194 bool write(jsfile *out); 195 196 void render(double, const triple& b, const triple& B, 197 double perspective, bool remesh); 198 drawElement *transformed(const double* t); 199 }; 200 201 class drawNurbs : public drawElement { 202 protected: 203 size_t udegree,vdegree; 204 size_t nu,nv; 205 triple *controls; 206 double *weights; 207 double *uknots, *vknots; 208 prc::RGBAColour diffuse; 209 prc::RGBAColour emissive; 210 prc::RGBAColour specular; 211 double opacity; 212 double shininess; 213 double metallic; 214 double fresnel0; 215 triple normal; 216 bool invisible; 217 218 triple Min,Max; 219 220 #ifdef HAVE_LIBGLM 221 GLfloat *colors; 222 GLfloat *Controls; 223 GLfloat *uKnots; 224 GLfloat *vKnots; 225 #endif 226 227 public: 228 drawNurbs(const vm::array& g, const vm::array* uknot, const vm::array* vknot, 229 const vm::array* weight, const vm::array&p, double opacity, 230 double shininess, double metallic, double fresnel0, 231 const vm::array &pens, const string& key="") drawElement(key)232 : drawElement(key), opacity(opacity), shininess(shininess), 233 metallic(metallic), fresnel0(fresnel0) { 234 size_t weightsize=checkArray(weight); 235 236 const string wrongsize="Inconsistent NURBS data"; 237 nu=checkArray(&g); 238 239 if(nu == 0 || (weightsize != 0 && weightsize != nu) || checkArray(&p) != 3) 240 reportError(wrongsize); 241 242 vm::array *g0=vm::read<vm::array*>(g,0); 243 nv=checkArray(g0); 244 245 size_t n=nu*nv; 246 controls=new(UseGC) triple[n]; 247 248 size_t k=0; 249 for(size_t i=0; i < nu; ++i) { 250 vm::array *gi=vm::read<vm::array*>(g,i); 251 if(checkArray(gi) != nv) 252 reportError(wrongsize); 253 for(size_t j=0; j < nv; ++j) 254 controls[k++]=vm::read<triple>(gi,j); 255 } 256 257 if(weightsize > 0) { 258 size_t k=0; 259 weights=new(UseGC) double[n]; 260 for(size_t i=0; i < nu; ++i) { 261 vm::array *weighti=vm::read<vm::array*>(weight,i); 262 if(checkArray(weighti) != nv) 263 reportError(wrongsize); 264 for(size_t j=0; j < nv; ++j) 265 weights[k++]=vm::read<double>(weighti,j); 266 } 267 } else weights=NULL; 268 269 size_t nuknots=checkArray(uknot); 270 size_t nvknots=checkArray(vknot); 271 272 if(nuknots <= nu+1 || nuknots > 2*nu || nvknots <= nv+1 || nvknots > 2*nv) 273 reportError(wrongsize); 274 275 udegree=nuknots-nu-1; 276 vdegree=nvknots-nv-1; 277 278 run::copyArrayC(uknots,uknot,0,UseGC); 279 run::copyArrayC(vknots,vknot,0,UseGC); 280 281 pen surfacepen=vm::read<camp::pen>(p,0); 282 invisible=surfacepen.invisible(); 283 284 diffuse=rgba(surfacepen); 285 emissive=rgba(vm::read<camp::pen>(p,1)); 286 specular=rgba(vm::read<camp::pen>(p,2)); 287 288 #ifdef HAVE_LIBGLM 289 Controls=NULL; 290 int size=checkArray(&pens); 291 if(size > 0) { 292 colors=new(UseGC) GLfloat[16]; 293 if(size != 4) reportError(wrongsize); 294 storecolor(colors,0,pens,0); 295 storecolor(colors,8,pens,1); 296 storecolor(colors,12,pens,2); 297 storecolor(colors,4,pens,3); 298 } else colors=NULL; 299 #endif 300 } 301 drawNurbs(const double * t,const drawNurbs * s)302 drawNurbs(const double* t, const drawNurbs *s) : 303 drawElement(s->KEY), udegree(s->udegree), vdegree(s->vdegree), nu(s->nu), 304 nv(s->nv), weights(s->weights), uknots(s->uknots), vknots(s->vknots), 305 diffuse(s->diffuse), 306 emissive(s->emissive), specular(s->specular), opacity(s->opacity), 307 shininess(s->shininess), invisible(s->invisible) { 308 309 const size_t n=nu*nv; 310 controls=new(UseGC) triple[n]; 311 for(unsigned int i=0; i < n; ++i) 312 controls[i]=t*s->controls[i]; 313 314 #ifdef HAVE_LIBGLM 315 Controls=NULL; 316 colors=s->colors; 317 #endif 318 } 319 is3D()320 bool is3D() {return true;} 321 322 void bounds(const double* t, bbox3& b); 323 ~drawNurbs()324 virtual ~drawNurbs() {} 325 326 bool write(prcfile *out, unsigned int *, double, groupsmap&); 327 328 void displacement(); 329 void ratio(const double* t, pair &b, double (*m)(double, double), double, 330 bool &first); 331 332 void render(double size2, const triple& b, const triple& B, 333 double perspective, bool remesh); 334 335 drawElement *transformed(const double* t); 336 }; 337 338 // Draw a transformed PRC object. 339 class drawPRC : public drawElementLC { 340 protected: 341 prc::RGBAColour diffuse; 342 prc::RGBAColour emissive; 343 prc::RGBAColour specular; 344 double opacity; 345 double shininess; 346 double metallic; 347 double fresnel0; 348 bool invisible; 349 public: init(const vm::array & p)350 void init(const vm::array&p) { 351 if(checkArray(&p) != 3) 352 reportError(need3pens); 353 354 pen surfacepen=vm::read<camp::pen>(p,0); 355 invisible=surfacepen.invisible(); 356 357 diffuse=rgba(surfacepen); 358 emissive=rgba(vm::read<camp::pen>(p,1)); 359 specular=rgba(vm::read<camp::pen>(p,2)); 360 } 361 drawPRC(const vm::array & t,const vm::array & p,double opacity,double shininess,double metallic,double fresnel0)362 drawPRC(const vm::array& t, const vm::array&p, double opacity, 363 double shininess, double metallic, double fresnel0) : 364 drawElementLC(t), opacity(opacity), shininess(shininess), 365 metallic(metallic), fresnel0(fresnel0) { 366 init(p); 367 } 368 drawPRC(const vm::array & p,double opacity,double shininess,double metallic,double fresnel0)369 drawPRC(const vm::array&p, double opacity, 370 double shininess, double metallic, double fresnel0) : 371 drawElementLC(NULL), opacity(opacity), shininess(shininess), 372 metallic(metallic), fresnel0(fresnel0) { 373 init(p); 374 } 375 drawPRC(const double * t,const drawPRC * s)376 drawPRC(const double* t, const drawPRC *s) : 377 drawElementLC(t,s), diffuse(s->diffuse), 378 emissive(s->emissive), specular(s->specular), opacity(s->opacity), 379 shininess(s->shininess), metallic(s->metallic), fresnel0(s->fresnel0), 380 invisible(s->invisible) { 381 } 382 383 virtual void P(triple& t, double x, double y, double z); 384 write(prcfile * out,unsigned int *,double,groupsmap &)385 virtual bool write(prcfile *out, unsigned int *, double, groupsmap&) { 386 return true; 387 } 388 write(jsfile * out)389 virtual bool write(jsfile *out) {return true;} 390 transformedbounds(const double *,bbox3 &)391 virtual void transformedbounds(const double*, bbox3&) {} transformedratio(const double *,pair &,double (*)(double,double),double,bool &)392 virtual void transformedratio(const double*, pair&, 393 double (*)(double, double), double, bool&) {} 394 395 }; 396 397 // Output a unit sphere primitive. 398 class drawSphere : public drawPRC { 399 bool half; 400 int type; 401 public: drawSphere(const vm::array & t,bool half,const vm::array & p,double opacity,double shininess,double metallic,double fresnel0,int type)402 drawSphere(const vm::array& t, bool half, const vm::array&p, double opacity, 403 double shininess, double metallic, double fresnel0, int type) : 404 drawPRC(t,p,opacity,shininess,metallic,fresnel0), half(half), type(type) {} 405 drawSphere(const double * t,const drawSphere * s)406 drawSphere(const double* t, const drawSphere *s) : 407 drawElement(s->KEY), drawPRC(t,s), half(s->half), type(s->type) {} 408 409 void P(triple& t, double x, double y, double z); 410 411 bool write(prcfile *out, unsigned int *, double, groupsmap&); 412 bool write(jsfile *out); 413 transformed(const double * t)414 drawElement *transformed(const double* t) { 415 return new drawSphere(t,this); 416 } 417 }; 418 419 // Output a unit cylinder primitive. 420 class drawCylinder : public drawPRC { 421 bool core; 422 public: 423 drawCylinder(const vm::array& t, const vm::array&p, 424 double opacity, double shininess, double metallic, 425 double fresnel0, bool core=false) : drawPRC(t,p,opacity,shininess,metallic,fresnel0)426 drawPRC(t,p,opacity,shininess,metallic,fresnel0), core(core) {} 427 drawCylinder(const double * t,const drawCylinder * s)428 drawCylinder(const double* t, const drawCylinder *s) : 429 drawPRC(t,s), core(s->core) {} 430 431 bool write(prcfile *out, unsigned int *, double, groupsmap&); 432 bool write(jsfile *out); 433 transformed(const double * t)434 drawElement *transformed(const double* t) { 435 return new drawCylinder(t,this); 436 } 437 }; 438 439 // Draw a unit disk. 440 class drawDisk : public drawPRC { 441 public: drawDisk(const vm::array & t,const vm::array & p,double opacity,double shininess,double metallic,double fresnel0)442 drawDisk(const vm::array& t, const vm::array&p, double opacity, 443 double shininess, double metallic, double fresnel0) : 444 drawPRC(t,p,opacity,shininess,metallic,fresnel0) {} 445 drawDisk(const double * t,const drawDisk * s)446 drawDisk(const double* t, const drawDisk *s) : 447 drawPRC(t,s) {} 448 449 bool write(prcfile *out, unsigned int *, double, groupsmap&); 450 bool write(jsfile *out); 451 transformed(const double * t)452 drawElement *transformed(const double* t) { 453 return new drawDisk(t,this); 454 } 455 }; 456 457 // Draw a tube. 458 class drawTube : public drawPRC { 459 protected: 460 triple *g; 461 double width; 462 triple m,M; 463 bool core; 464 public: drawTube(const vm::array & G,double width,const vm::array & p,double opacity,double shininess,double metallic,double fresnel0,const triple & m,const triple & M,bool core)465 drawTube(const vm::array&G, double width, const vm::array&p, double opacity, 466 double shininess, double metallic, double fresnel0, 467 const triple& m, const triple& M, bool core) : 468 drawPRC(p,opacity,shininess,metallic,fresnel0), width(width), m(m), M(M), 469 core(core) { 470 if(vm::checkArray(&G) != 4) 471 reportError("array of 4 triples required"); 472 473 g=new(UseGC) triple[4]; 474 for(size_t i=0; i < 4; ++i) 475 g[i]=vm::read<triple>(G,i); 476 } 477 drawTube(const double * t,const drawTube * s)478 drawTube(const double* t, const drawTube *s) : 479 drawElement(s->KEY), drawPRC(t,s), width(s->width), m(s->m), M(s->M), 480 core(s->core) { 481 g=new(UseGC) triple[4]; 482 for(size_t i=0; i < 4; ++i) 483 g[i]=t*s->g[i]; 484 } 485 486 bool write(jsfile *out); 487 transformed(const double * t)488 drawElement *transformed(const double* t) { 489 return new drawTube(t,this); 490 } 491 }; 492 493 494 class drawBaseTriangles : public drawElement { 495 protected: 496 #ifdef HAVE_GL 497 Triangles R; 498 bool transparent; 499 #endif 500 501 size_t nP; 502 triple* P; 503 size_t nN; 504 triple* N; 505 size_t nI; 506 size_t Ni; 507 uint32_t (*PI)[3]; 508 uint32_t (*NI)[3]; 509 510 triple Min,Max; 511 512 static const string wrongsize; 513 static const string outofrange; 514 515 public: drawBaseTriangles(const vm::array & v,const vm::array & vi,const vm::array & n,const vm::array & ni)516 drawBaseTriangles(const vm::array& v, const vm::array& vi, 517 const vm::array& n, const vm::array& ni) { 518 nP=checkArray(&v); 519 P=new(UseGC) triple[nP]; 520 for(size_t i=0; i < nP; ++i) 521 P[i]=vm::read<triple>(v,i); 522 523 nI=checkArray(&vi); 524 PI=new(UseGC) uint32_t[nI][3]; 525 for(size_t i=0; i < nI; ++i) { 526 vm::array *vii=vm::read<vm::array*>(vi,i); 527 if(checkArray(vii) != 3) reportError(wrongsize); 528 uint32_t *PIi=PI[i]; 529 for(size_t j=0; j < 3; ++j) { 530 size_t index=unsignedcast(vm::read<Int>(vii,j)); 531 if(index >= nP) reportError(outofrange); 532 PIi[j]=index; 533 } 534 } 535 536 nN=checkArray(&n); 537 if(nN) { 538 N=new(UseGC) triple[nN]; 539 for(size_t i=0; i < nN; ++i) 540 N[i]=vm::read<triple>(n,i); 541 542 Ni=checkArray(&ni); 543 if(Ni == 0 && nN == nP) 544 NI=PI; 545 else { 546 if(Ni != nI) 547 reportError("Index arrays have different lengths"); 548 NI=new(UseGC) uint32_t[nI][3]; 549 for(size_t i=0; i < nI; ++i) { 550 vm::array *nii=vm::read<vm::array*>(ni,i); 551 if(checkArray(nii) != 3) reportError(wrongsize); 552 uint32_t *NIi=NI[i]; 553 for(size_t j=0; j < 3; ++j) { 554 size_t index=unsignedcast(vm::read<Int>(nii,j)); 555 if(index >= nN) reportError(outofrange); 556 NIi[j]=index; 557 } 558 } 559 } 560 } else Ni=0; 561 } 562 drawBaseTriangles(const double * t,const drawBaseTriangles * s)563 drawBaseTriangles(const double* t, const drawBaseTriangles *s) : 564 drawElement(s->KEY), nP(s->nP), nN(s->nN), nI(s->nI), Ni(s->Ni) { 565 P=new(UseGC) triple[nP]; 566 for(size_t i=0; i < nP; i++) 567 P[i]=t*s->P[i]; 568 569 PI=new(UseGC) uint32_t[nI][3]; 570 for(size_t i=0; i < nI; ++i) { 571 uint32_t *PIi=PI[i]; 572 uint32_t *sPIi=s->PI[i]; 573 for(size_t j=0; j < 3; ++j) 574 PIi[j]=sPIi[j]; 575 } 576 577 if(nN) { 578 N=new(UseGC) triple[nN]; 579 if(t == NULL) { 580 for(size_t i=0; i < nN; i++) 581 N[i]=s->N[i]; 582 } else { 583 double T[]={t[0],t[1],t[2], 584 t[4],t[5],t[6], 585 t[8],t[9],t[10]}; 586 run::inverse(T,3); 587 for(size_t i=0; i < nN; i++) 588 N[i]=unit(Transform3(s->N[i],T)); 589 } 590 591 if(Ni == 0) { 592 NI=PI; 593 } else { 594 NI=new(UseGC) uint32_t[nI][3]; 595 for(size_t i=0; i < nI; ++i) { 596 uint32_t *NIi=NI[i]; 597 uint32_t *sNIi=s->NI[i]; 598 for(size_t j=0; j < 3; ++j) 599 NIi[j]=sNIi[j]; 600 } 601 } 602 } 603 } 604 is3D()605 bool is3D() {return true;} 606 607 void bounds(const double* t, bbox3& b); 608 609 void ratio(const double* t, pair &b, double (*m)(double, double), 610 double fuzz, bool &first); 611 ~drawBaseTriangles()612 virtual ~drawBaseTriangles() {} 613 transformed(const double * t)614 drawElement *transformed(const double* t) { 615 return new drawBaseTriangles(t,this); 616 } 617 }; 618 619 class drawTriangles : public drawBaseTriangles { 620 size_t nC; 621 prc::RGBAColour*C; 622 uint32_t (*CI)[3]; 623 size_t Ci; 624 625 // Asymptote material data 626 prc::RGBAColour diffuse; 627 prc::RGBAColour emissive; 628 prc::RGBAColour specular; 629 double opacity; 630 double shininess; 631 double metallic; 632 double fresnel0; 633 bool invisible; 634 635 public: drawTriangles(const vm::array & v,const vm::array & vi,const vm::array & n,const vm::array & ni,const vm::array & p,double opacity,double shininess,double metallic,double fresnel0,const vm::array & c,const vm::array & ci)636 drawTriangles(const vm::array& v, const vm::array& vi, 637 const vm::array& n, const vm::array& ni, 638 const vm::array&p, double opacity, double shininess, 639 double metallic, double fresnel0, 640 const vm::array& c, const vm::array& ci) : 641 drawBaseTriangles(v,vi,n,ni), opacity(opacity), shininess(shininess), 642 metallic(metallic), fresnel0(fresnel0) { 643 644 if(checkArray(&p) != 3) 645 reportError(need3pens); 646 647 const pen surfacepen=vm::read<camp::pen>(p,0); 648 invisible=surfacepen.invisible(); 649 diffuse=rgba(surfacepen); 650 651 nC=checkArray(&c); 652 if(nC) { 653 C=new(UseGC) prc::RGBAColour[nC]; 654 for(size_t i=0; i < nC; ++i) 655 C[i]=rgba(vm::read<camp::pen>(c,i)); 656 657 size_t nI=checkArray(&vi); 658 659 Ci=checkArray(&ci); 660 if(Ci == 0 && nC == nP) 661 CI=PI; 662 else { 663 if(Ci != nI) 664 reportError("Index arrays have different lengths"); 665 CI=new(UseGC) uint32_t[nI][3]; 666 for(size_t i=0; i < nI; ++i) { 667 vm::array *cii=vm::read<vm::array*>(ci,i); 668 if(checkArray(cii) != 3) reportError(wrongsize); 669 uint32_t *CIi=CI[i]; 670 for(size_t j=0; j < 3; ++j) { 671 size_t index=unsignedcast(vm::read<Int>(cii,j)); 672 if(index >= nC) reportError(outofrange); 673 CIi[j]=index; 674 } 675 } 676 } 677 } else { 678 emissive=rgba(vm::read<camp::pen>(p,1)); 679 } 680 specular=rgba(vm::read<camp::pen>(p,2)); 681 } 682 drawTriangles(const double * t,const drawTriangles * s)683 drawTriangles(const double* t, const drawTriangles *s) : 684 drawBaseTriangles(t,s), nC(s->nC), 685 diffuse(s->diffuse), emissive(s->emissive), 686 specular(s->specular), opacity(s->opacity), shininess(s->shininess), 687 metallic(s->metallic), fresnel0(s->fresnel0), invisible(s->invisible) { 688 689 if(nC) { 690 C=new(UseGC) prc::RGBAColour[nC]; 691 for(size_t i=0; i < nC; ++i) 692 C[i]=s->C[i]; 693 694 CI=new(UseGC) uint32_t[nI][3]; 695 for(size_t i=0; i < nI; ++i) { 696 uint32_t *CIi=CI[i]; 697 uint32_t *sCIi=s->CI[i]; 698 for(size_t j=0; j < 3; ++j) 699 CIi[j]=sCIi[j]; 700 } 701 } 702 } 703 ~drawTriangles()704 virtual ~drawTriangles() {} 705 706 void render(double size2, const triple& b, const triple& B, 707 double perspective, bool remesh); 708 709 bool write(prcfile *out, unsigned int *, double, groupsmap&); 710 bool write(jsfile *out); 711 transformed(const double * t)712 drawElement *transformed(const double* t) { 713 return new drawTriangles(t,this); 714 } 715 }; 716 717 } 718 719 #endif 720