| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403 |
- /******************************************************************************/
- #include "stdafx.h"
- namespace EE{
- /******************************************************************************/
- MeshBase& MeshBase::createPlane(Int x, Int y, UInt flag)
- {
- MAX(x, 2);
- MAX(y, 2);
- create(x*y, 0, 0, (x-1)*(y-1), flag&(VTX_NRM_TAN_BIN|VTX_TEX0));
- // face
- if(VecI4 *quad=T.quad.ind())
- FREPD(sy, y-1)
- FREPD(sx, x-1)
- {
- Int p=sx+sy*x;
- (quad++)->set(p+x, p+1+x, p+1, p);
- }
- // vtx
- if(Vec *pos=vtx.pos())FREPD(sy, y)
- {
- Flt fy=sy/Flt(y-1);
- FREPD(sx, x)(pos++)->set(sx/Flt(x-1), fy, 0);
- }
- if(Vec *nrm=vtx.nrm())REPA(vtx)(nrm++)->set(0, 0, -1);
- if(Vec *tan=vtx.tan())REPA(vtx)(tan++)->set(1, 0, 0);
- if(Vec *bin=vtx.bin())REPA(vtx)(bin++)->set(0, -1, 0);
- if(vtx.tex0())texMap();
- return T;
- }
- MeshBase& MeshBase::createGrid(Int x, Int y, Bool fast)
- {
- MAX(x, 2);
- MAX(y, 2);
- if(fast)create(x*2+(y-2)*2, x+y , 0, 0);
- else create(x*y , y*(x-1)+x*(y-1), 0, 0);
- // vtx
- Vec *pos=vtx.pos();
- if(fast)
- {
- FREPD(sx, x) (pos++)->set( sx/Flt(x-1), 1, 0);
- FREPD(sx, x) (pos++)->set( sx/Flt(x-1), 0, 0);
- for(Int sy=1; sy<y-1; sy++)(pos++)->set(0, sy/Flt(y-1), 0 );
- for(Int sy=1; sy<y-1; sy++)(pos++)->set(1, sy/Flt(y-1), 0 );
- }else
- FREPD(sy, y)
- {
- Flt fy=sy/Flt(y-1);
- FREPD(sx, x)(pos++)->set(sx/Flt(x-1), fy, 0);
- }
- // edge
- VecI2 *edge=T.edge.ind();
- if(fast)
- {
- FREPD(sx, x )(edge++)->set( sx, sx+x);
- (edge++)->set( x, x+x-1);
- FREPD(sy, y-2)(edge++)->set(x+x+sy, x+x+sy+y-2);
- (edge++)->set( 0, x-1);
- }else
- {
- FREPD(sy, y)FREPD(sx, x-1)(edge++)->set(sx+sy*x, sx+1+(sy )*x);
- FREPD(sx, x)FREPD(sy, y-1)(edge++)->set(sx+sy*x, sx +(sy+1)*x);
- }
- return T;
- }
- /******************************************************************************/
- MeshBase& MeshBase::createFast(C Box &box)
- {
- create(8, 0, 0, 6);
- // vtx
- FREP(8)vtx.pos(i).set(( i &1) ? box.max.x : box.min.x,
- ((i>>1)&1) ? box.max.y : box.min.y,
- ((i>>2)&1) ? box.max.z : box.min.z);
- // face
- // x
- quad.ind(0).set(1|2|0, 1|2|4, 1|0|4, 1|0|0);
- quad.ind(1).set(0|0|0, 0|0|4, 0|2|4, 0|2|0);
- // y
- quad.ind(2).set(2|4|0, 2|4|1, 2|0|1, 2|0|0);
- quad.ind(3).set(0|0|0, 0|0|1, 0|4|1, 0|4|0);
- // z
- quad.ind(4).set(4|1|2, 4|0|2, 4|0|0, 4|1|0);
- quad.ind(5).set(0|1|0, 0|0|0, 0|0|2, 0|1|2);
- return T;
- }
- MeshBase& MeshBase::createBox(C Matrix &matrix, UInt flag, Int resolution)
- {
- Matrix m; MeshBase mesh[6]; REPA(mesh)
- {
- m.setOrient(DIR_ENUM(i));
- m.anchor(0.5f);
- m*=matrix;
- mesh[i].createPlane(resolution, resolution, flag).transform(m);
- }
- create(mesh, Elms(mesh));
- if(!(flag&(VTX_TAN_BIN|VTX_TEX0)))weldVtx(VTX_ALL, EPS, EPS_COL_COS, -1);
- return T;
- }
- MeshBase& MeshBase::create(C Box & box, UInt flag, Int resolution) {return createBox(Matrix( box.size(), box.min) , flag, resolution);}
- MeshBase& MeshBase::create(C OBox &obox, UInt flag, Int resolution) {return createBox(Matrix(obox.box.size(), obox.box.min)*obox.matrix, flag, resolution);}
- /******************************************************************************/
- MeshBase& MeshBase::create(C Ball &ball, UInt flag, Int resolution)
- {
- if(resolution<0)resolution=7;else MAX(resolution, 2); // default size else min size
- Int face_vtxs=resolution*resolution;
- create(face_vtxs*6, 0, 0, (resolution-1)*(resolution-1)*6, flag&VTX_TEX0);
- Vec *pos = vtx .pos ();
- Vec2 *tex = vtx .tex0();
- VecI4 *quad=T.quad.ind ();
- // vtx
- FREPD(y, resolution)
- {
- Flt fy=y/Flt(resolution-1), sy=-Tan(fy*PI_2-PI_4);
- FREPD(x, resolution)
- {
- Flt fx=x/Flt(resolution-1), sx=-Tan(fx*PI_2-PI_4);
- pos[face_vtxs*0].set( sx, sy, 1 );
- pos[face_vtxs*1].set( 1 , sy, -sx);
- pos[face_vtxs*2].set(-sx, sy, -1 );
- pos[face_vtxs*3].set(-1 , sy, sx);
- pos[face_vtxs*4].set(-sx, 1, sy);
- pos[face_vtxs*5].set(-sx, -1, -sy);
- pos++;
- if(tex)
- {
- tex[face_vtxs*0].set(fx, fy);
- tex[face_vtxs*1].set(fx, fy);
- tex[face_vtxs*2].set(fx, fy);
- tex[face_vtxs*3].set(fx, fy);
- tex[face_vtxs*4].set(fx, fy);
- tex[face_vtxs*5].set(fx, fy);
- tex++;
- }
- }
- }
- // face
- FREPD(f, 6)
- FREPD(y, resolution-1)
- FREPD(x, resolution-1)
- {
- Int p=x + y*resolution + f*face_vtxs;
- (quad++)->set(p, p+1, p+1+resolution, p+resolution);
- }
- if(!(flag&VTX_TEX0))weldVtx(VTX_ALL, EPS, EPS_COL_COS, -1);
- Normalize(vtx.pos(), vtxs());
- if(flag&VTX_NRM)
- {
- include(VTX_NRM);
- CopyN (vtx.nrm(), vtx.pos(), vtxs());
- }
- transform(Matrix(ball.r, ball.pos));
- if(flag&VTX_TAN)setTangents ();
- if(flag&VTX_BIN)setBinormals();
- return T;
- }
- MeshBase& MeshBase::createHalf(C Ball &ball, UInt flag, Int resolution)
- {
- if(resolution<0)resolution=7;else MAX(resolution, 2); // default size else min size
- #if 1 // floor
- Int res_half=Max((resolution+1)/2, 2),
- #else // ceil
- Int res_half=resolution/2+1,
- #endif
- face_vtxs=resolution*resolution,
- half_vtxs=resolution*res_half;
- create(half_vtxs*4 + face_vtxs, 0, 0, (resolution-1)*(res_half-1)*4 + (resolution-1)*(resolution-1), flag&VTX_TEX0);
- Vec *pos = vtx .pos ();
- Vec2 *tex = vtx .tex0();
- VecI4 *quad=T.quad.ind ();
- // vtx
- FREPD(y, res_half)
- {
- Flt fy=y/Flt((res_half-1)*2), sy=-Tan(fy*PI_2-PI_4);
- FREPD(x, resolution)
- {
- Flt fx=x/Flt(resolution-1), sx=-Tan(fx*PI_2-PI_4);
- pos[half_vtxs*0].set( sx, sy, 1 );
- pos[half_vtxs*1].set( 1 , sy, -sx);
- pos[half_vtxs*2].set(-sx, sy, -1 );
- pos[half_vtxs*3].set(-1 , sy, sx);
- pos++;
- if(tex)
- {
- tex[half_vtxs*0].set(fx, fy);
- tex[half_vtxs*1].set(fx, fy);
- tex[half_vtxs*2].set(fx, fy);
- tex[half_vtxs*3].set(fx, fy);
- tex++;
- }
- }
- }
- pos+=resolution*res_half*3;
- if(tex)tex+=resolution*res_half*3;
- FREPD(y, resolution)
- {
- Flt fy=y/Flt(resolution-1), sy=-Tan(fy*PI_2-PI_4);
- FREPD(x, resolution)
- {
- Flt fx=x/Flt(resolution-1), sx=-Tan(fx*PI_2-PI_4);
- (pos++)->set(-sx, 1, sy);
- if(tex)(tex++)->set( fx, fy);
- }
- }
- // face
- FREPD(f, 4)
- FREPD(y, res_half -1)
- FREPD(x, resolution-1)
- {
- Int p=x + y*resolution + f*half_vtxs;
- (quad++)->set(p, p+1, p+1+resolution, p+resolution);
- }
- FREPD(y, resolution-1)
- FREPD(x, resolution-1)
- {
- Int p=x + y*resolution + 4*half_vtxs;
- (quad++)->set(p, p+1, p+1+resolution, p+resolution);
- }
- if(!(flag&VTX_TEX0))weldVtx(VTX_ALL, EPS, EPS_COL_COS, -1);
- Normalize(vtx.pos(), vtxs());
- if(flag&VTX_NRM)
- {
- include(VTX_NRM);
- CopyN (vtx.nrm(), vtx.pos(), vtxs());
- }
- transform(Matrix(ball.r, ball.pos));
- if(flag&VTX_TAN)setTangents ();
- if(flag&VTX_BIN)setBinormals();
- return T;
- }
- /******************************************************************************/
- MeshBase& MeshBase::create2(C Ball &ball, UInt flag, Int resolution, Int resolution2)
- {
- if(resolution <0)resolution =24;else MAX(resolution , 3); // default size else min size
- if(resolution2<0)resolution2=13;else MAX(resolution2, 3); // default size else min size
- create((resolution+1)*resolution2, 0, resolution*2, resolution*(resolution2-3), flag&VTX_TEX0);
- // vertexes
- REPD(y, resolution2)
- {
- Flt cy, sy; CosSin(cy, sy, y/Flt(resolution2-1)*PI-PI_2);
- REPD(x, resolution+1)
- {
- Flt cx, sx; CosSin(cx, sx, x/Flt(resolution)*PI2);
- vtx.pos (x+y*(resolution+1)).set(cx*cy, sy, sx*cy);
- if(vtx.tex0())vtx.tex0(x+y*(resolution+1)).set(x/Flt(resolution), y/Flt(resolution2-1));
- }
- }
- // triangles
- REPD(x, resolution)
- {
- Int i=x+ 0 *(resolution+1); tri.ind(x ).set(i+resolution+1, i+resolution+1+1, i);
- i=x+(resolution2-2)*(resolution+1); tri.ind(x+resolution).set(i+resolution+1, i+1 , i);
- }
- // quads
- REPD(y, resolution2-3)
- REPD(x, resolution)
- {
- Int i=x+(y+1)*(resolution+1); quad.ind(x+y*resolution).set(i+resolution+1, i+resolution+1+1, i+1, i);
- }
- if(!(flag&VTX_TEX0))weldVtx(VTX_ALL, EPS, EPS_COL_COS, -1);
- Normalize(vtx.pos(), vtxs());
- if(flag&VTX_NRM)
- {
- include(VTX_NRM);
- CopyN (vtx.nrm(), vtx.pos(), vtxs());
- }
- transform(Matrix(ball.r, ball.pos));
- if(flag&VTX_TAN)setTangents ();
- if(flag&VTX_BIN)setBinormals();
- return T;
- }
- /******************************************************************************/
- //VecD2 p((1+Sqrt(5.0))/2, 1); p.normalize();
- #define X 0.85065080835203999f // p.x
- #define Y 0.52573111211913359f // p.y
- static const Vec IcoVtxs[]=
- {
- Vec( Y, 0,-X), Vec(-Y, 0,-X), Vec( Y, 0, X), Vec(-Y, 0, X),
- Vec( 0,-X,-Y), Vec( 0,-X, Y), Vec( 0, X,-Y), Vec( 0, X, Y),
- Vec(-X,-Y, 0), Vec( X,-Y, 0), Vec(-X, Y, 0), Vec( X, Y, 0),
- };
- static const VecI IcoTris[]=
- {
- VecI(0, 4, 1), VecI(0,9, 4), VecI(9, 5,4), VecI( 4,5,8), VecI(4,8, 1),
- VecI(8,10, 1), VecI(8,3,10), VecI(5, 3,8), VecI( 5,2,3), VecI(2,7, 3),
- VecI(7,10, 3), VecI(7,6,10), VecI(7,11,6), VecI(11,0,6), VecI(0,1, 6),
- VecI(6, 1,10), VecI(9,0,11), VecI(9,11,2), VecI( 9,2,5), VecI(7,2,11),
- };
- #undef X
- #undef Y
- MeshBase& MeshBase::createIco(C Ball &ball, UInt flag, Int resolution)
- {
- if(resolution< 0)resolution=3; // default
- if(resolution<=0) // simple
- {
- create(Elms(IcoVtxs), 0, Elms(IcoTris), 0);
- CopyN(vtx.pos(), IcoVtxs, vtxs());
- CopyN(tri.ind(), IcoTris, tris());
- }else // subdivision
- {
- resolution++;
- const Int vtxs=(resolution+1)*(resolution+2)/2, tris=resolution*resolution, sides=Elms(IcoTris);
- create(vtxs*sides, 0, tris*sides, 0);
- Int vtx_offset=0;
- Vec *p=vtx.pos();
- VecI *t=tri.ind();
- REP(sides)
- {
- C VecI &tri_ind=IcoTris[i];
- C Vec &v0 =IcoVtxs[tri_ind.x],
- &v1 =IcoVtxs[tri_ind.y],
- &v2 =IcoVtxs[tri_ind.z];
- Vec v01 =(v1-v0)/resolution,
- v02 =(v2-v0)/resolution,
- vy =v0;
- for(Int y=0; y<=resolution; y++)
- {
- Vec vx=vy;
- Int xs=resolution-y;
- for(Int x=0; x<=xs; x++)
- {
- *p++=vx;
- vx+=v01;
- if(y!=resolution && x!=xs)
- {
- (t++)->set(vtx_offset , vtx_offset+1, vtx_offset+xs+1);
- if(x+1<xs)(t++)->set(vtx_offset+xs+1, vtx_offset+1, vtx_offset+xs+2);
- }
- vtx_offset++;
- }
- vy+=v02;
- }
- }
- weldVtx(VTX_ALL, EPS, EPS_COL_COS, -1);
- Normalize(vtx.pos(), T.vtxs());
- }
- if(flag&VTX_NRM)
- {
- include(VTX_NRM);
- CopyN (vtx.nrm(), vtx.pos(), T.vtxs());
- }
- transform(Matrix(ball.r, ball.pos));
- if(flag&VTX_TAN)setTangents ();
- if(flag&VTX_BIN)setBinormals();
- return T;
- }
- /******************************************************************************/
- MeshBase& MeshBase::createIcoHalf(C Ball &ball, UInt flag, Int resolution)
- {
- createIco(Ball(1), 0, resolution);
- Memt<Bool> is; is.setNumZero(vtxs());
- REPA(tri)
- {
- C VecI &t=tri.ind(i);
- if(vtx.pos(t.x).y>EPS
- || vtx.pos(t.y).y>EPS
- || vtx.pos(t.z).y>EPS)is[t.x]=is[t.y]=is[t.z]=true;
- }
- keepVtxs(is);
- REPA(vtx){Vec &p=vtx.pos(i); if(p.y<0){p.y=0; p.normalize();}}
- if(flag&VTX_NRM)
- {
- include(VTX_NRM);
- CopyN (vtx.nrm(), vtx.pos(), T.vtxs());
- }
- transform(Matrix(ball.r, ball.pos));
- if(flag&VTX_TAN)setTangents ();
- if(flag&VTX_BIN)setBinormals();
- return T;
- }
- /******************************************************************************/
- MeshBase& MeshBase::create(C Capsule &capsule, UInt flag, Int resolution, Int resolution2)
- {
- if(resolution <0)resolution =12;else MAX(resolution , 3);
- if(resolution2<0)resolution2= 5;else MAX(resolution2, 2);
- Flt r=Min(capsule.r, capsule.h*0.5f);
- create((resolution+1)*(resolution2-1)*2+2, 0, resolution*2, resolution+(resolution2-2)*resolution*2, flag&VTX_TEX0);
- REPD(y, resolution2-1)
- {
- Flt cy, sy; CosSin(cy, sy, y/Flt(resolution2-1)*PI_2);
- REPD(x, resolution+1)
- {
- Flt cx, sx; CosSin(cx, sx, x/Flt(resolution)*PI2);
- Int i0=x+ y *(resolution+1),
- i1=x+(y+resolution2-1)*(resolution+1);
- vtx.pos(i0).set(cy*cx*r, capsule.h*0.5f-r+sy*r, cy*sx*r);
- CHS((vtx.pos(i1)=vtx.pos(i0)).y);
- if(vtx.tex0())
- {
- vtx.tex0(i0).set(x/Flt(resolution), (y/Flt(resolution2-1)*r + capsule.h*0.5f-r)/(capsule.h*0.5f)*0.5f+0.5f);
- vtx.tex0(i1).set(vtx.tex0(i0).x, 1-vtx.tex0(i0).y);
- }
- }
- }
- vtx.pos(vtxs()-2).set(0, capsule.h*0.5f, 0);
- vtx.pos(vtxs()-1).set(0, -capsule.h*0.5f, 0);
- if(vtx.tex0())
- {
- vtx.tex0(vtxs()-2).set(0.5f, 1);
- vtx.tex0(vtxs()-1).set(0.5f, 0);
- }
- REP(resolution)
- {
- Int lo=(resolution2-1)*(resolution+1),
- o =lo-(resolution+1);
- tri .ind(i ).set(o+ i+1, o+ i, vtxs()-2);
- tri .ind(i+resolution).set(o+lo+i, o+lo+i+1, vtxs()-1);
- quad.ind(i ).set(lo+i+1, lo+i, i, i+1);
- REPD(y, resolution2-2)
- {
- o=y*(resolution+1);
- quad.ind(resolution+resolution* y +i).set(o+i+1, o+i, o+(resolution+1)+i, o+(resolution+1)+i+1); o+=lo;
- quad.ind(resolution+resolution*(y+resolution2-2)+i).set(o+(resolution+1)+i+1, o+(resolution+1)+i, o+i, o+i+1);
- }
- }
- if(!(flag&VTX_TEX0))weldVtx(VTX_ALL, EPS, EPS_COL_COS, -1);
- transform(Matrix().setPosUp(capsule.pos, capsule.up));
- if(flag&VTX_NRM)setVtxDup ().setNormals().exclude(VTX_DUP);
- if(flag&VTX_TAN)setTangents ();
- if(flag&VTX_BIN)setBinormals();
- return T;
- }
- /******************************************************************************/
- MeshBase& MeshBase::createFast(C Tube &tube, Int resolution)
- {
- if(resolution<0)resolution=12;else MAX(resolution, 3);
- Flt h_2=tube.h/2;
- create(resolution*2, 0, (resolution-2)*2+resolution*2, 0);
- VecI *tri=T.tri.ind();
- REP(resolution)
- {
- Flt c, s; CosSin(c, s, i*PI2/resolution);
- vtx.pos( i).set(c*tube.r, h_2, s*tube.r);
- vtx.pos(resolution+i).set(c*tube.r, -h_2, s*tube.r);
- (tri++)->set(i, (i+1)%resolution, resolution+i);
- (tri++)->set((i+1)%resolution, (i+1)%resolution+resolution, resolution+i);
- }
- REP(resolution-2)
- {
- tri[ i].set( 0, i+2, i+1);
- tri[resolution-2+i].set(resolution, resolution+i+1, resolution+i+2);
- }
- transform(Matrix().setPosUp(tube.pos, tube.up));
- return T;
- }
- MeshBase& MeshBase::create(C Tube &tube, UInt flag, Int resolution)
- {
- if(resolution<0)resolution=12;else MAX(resolution, 3);
- Int offset,
- resolution1=resolution+1;
- Flt h_2=tube.h/2;
- create(resolution*2 + resolution1*2, 0, (resolution-2)*2, resolution, flag&(VTX_NRM_TAN_BIN|VTX_TEX0));
- VecI *tri =T.tri .ind();
- VecI4 *quad=T.quad.ind();
- // vtxs
- REP(resolution)
- {
- Flt c, s; CosSin(c, s, i*PI2/resolution);
- vtx.pos( i).set(c*tube.r, h_2, s*tube.r);
- vtx.pos(resolution+i).set(c*tube.r, -h_2, s*tube.r);
- if(vtx.nrm())
- {
- vtx.nrm( i).set(0, 1, 0);
- vtx.nrm(resolution+i).set(0, -1, 0);
- }
- if(vtx.tan())
- {
- vtx.tan( i).set(1, 0, 0);
- vtx.tan(resolution+i).set(1, 0, 0);
- }
- if(vtx.bin())
- {
- vtx.bin( i).set(0, 0, -1);
- vtx.bin(resolution+i).set(0, 0, 1);
- }
- if(vtx.tex0())
- {
- vtx.tex0( i).set(c*0.5f+0.5f, -s*0.5f+0.5f);
- vtx.tex0(resolution+i).set(c*0.5f+0.5f, s*0.5f+0.5f);
- }
- }
- offset=resolution*2; REP(resolution1)
- {
- Flt c, s; CosSin(c, s, i*PI2/resolution);
- vtx.pos(offset+ i).set(c*tube.r, h_2, s*tube.r);
- vtx.pos(offset+resolution1+i).set(c*tube.r, -h_2, s*tube.r);
- if(vtx.nrm())
- {
- vtx.nrm(offset+ i).set(c, 0, s);
- vtx.nrm(offset+resolution1+i).set(c, 0, s);
- }
- if(vtx.tan())
- {
- vtx.tan(offset+ i).set(-s, 0, c);
- vtx.tan(offset+resolution1+i).set(-s, 0, c);
- }
- if(vtx.bin())
- {
- vtx.bin(offset+ i).set(0, -1, 0);
- vtx.bin(offset+resolution1+i).set(0, -1, 0);
- }
- if(vtx.tex0())
- {
- vtx.tex0(offset+ i).set(Flt(i)/resolution, 0);
- vtx.tex0(offset+resolution1+i).set(Flt(i)/resolution, 1);
- }
- }
- // tris
- REP(resolution-2)
- {
- tri[ i].set( 0, i+2, i+1);
- tri[resolution-2+i].set(resolution, resolution+i+1, resolution+i+2);
- }
- // quads
- REP(resolution)(quad++)->set(offset+i, offset+i+1, offset+resolution1+i+1, offset+resolution1+i); // sides
- if(!(flag&VTX_TEX0))weldVtx(VTX_ALL, EPS, EPS_COL_COS, -1);
- transform(Matrix().setPosUp(tube.pos, tube.up));
- return T;
- }
- /******************************************************************************/
- MeshBase& MeshBase::create(C Cone &cone, UInt flag, Int resolution)
- {
- if( resolution<0)resolution=12;else MAX(resolution, 3);
- Int resolution1 =resolution+1,
- offset;
- if(cone.r_low >EPS
- && cone.r_high>EPS)
- {
- offset=resolution*2;
- create(resolution*2+resolution1*2, 0, (resolution-2)*2, resolution, flag&(VTX_NRM_TAN_BIN|VTX_TEX0));
- VecI *tri =T.tri .ind();
- VecI4 *quad=T.quad.ind();
- // vtxs
- REP(resolution)
- {
- Flt c, s; CosSin(c, s, i*PI2/resolution);
- vtx.pos( i).set(c*cone.r_high, cone.h, s*cone.r_high);
- vtx.pos(resolution+i).set(c*cone.r_low , 0, s*cone.r_low );
- if(vtx.nrm())
- {
- vtx.nrm( i).set(0, 1, 0);
- vtx.nrm(resolution+i).set(0, -1, 0);
- }
- if(vtx.tan())
- {
- vtx.tan( i).set(1, 0, 0);
- vtx.tan(resolution+i).set(1, 0, 0);
- }
- if(vtx.bin())
- {
- vtx.bin( i).set(0, 0, -1);
- vtx.bin(resolution+i).set(0, 0, 1);
- }
- if(vtx.tex0())
- {
- vtx.tex0( i).set(c, 1-s);
- vtx.tex0(resolution+i).set(c, s);
- }
- }
- Vec2 N(cone.r_high-cone.r_low, cone.h); N=PerpN(N);
- REP(resolution1)
- {
- Flt c, s; CosSin(c, s, i*PI2/resolution);
- vtx.pos(offset+ i).set(c*cone.r_high, cone.h, s*cone.r_high);
- vtx.pos(offset+resolution1+i).set(c*cone.r_low , 0, s*cone.r_low );
- if(vtx.nrm())
- {
- vtx.nrm(offset+ i).set(N.x*c, N.y, N.x*s);
- vtx.nrm(offset+resolution1+i).set(N.x*c, N.y, N.x*s);
- }
- if(vtx.tan())
- {
- vtx.tan(offset+ i).set(-s,0,c);
- vtx.tan(offset+resolution1+i).set(-s,0,c);
- }
- if(vtx.bin())
- {
- vtx.bin(offset+ i).set(N.y*c, -N.x, N.y*s);
- vtx.bin(offset+resolution1+i).set(N.y*c, -N.x, N.y*s);
- }
- if(vtx.tex0())
- {
- vtx.tex0(offset+ i).set(Flt(i)/resolution, 0);
- vtx.tex0(offset+resolution1+i).set(Flt(i)/resolution, 1);
- }
- }
- // tris
- REP(resolution-2)
- {
- tri[ i].set( 0, i+2, i+1);
- tri[resolution-2+i].set(resolution, resolution+i+1, resolution+i+2);
- }
- // quads
- REP(resolution)(quad++)->set(offset+i, offset+i+1, offset+resolution1+i+1, offset+resolution1+i); // sides
- transform(Matrix().setPosUp(cone.pos, cone.up));
- }else
- if(cone.r_low>EPS)
- {
- offset=resolution;
- create(resolution+resolution1*2, 0, resolution-2+resolution, 0, flag&(VTX_NRM_TAN_BIN|VTX_TEX0));
- VecI *tri=T.tri.ind();
- // vtxs
- REP(resolution)
- {
- Flt c, s; CosSin(c, s, i*PI2/resolution);
- vtx.pos (i).set(c*cone.r_low, 0, s*cone.r_low);
- if(vtx.nrm ())vtx.nrm (i).set(0, -1, 0);
- if(vtx.tan ())vtx.tan (i).set(1, 0, 0);
- if(vtx.bin ())vtx.bin (i).set(0, 0, 1);
- if(vtx.tex0())vtx.tex0(i).set(c, s );
- }
- Vec2 N(cone.r_high-cone.r_low, cone.h); N=PerpN(N);
- REP(resolution1)
- {
- Flt c, s; CosSin(c, s, i*PI2/resolution);
- vtx.pos(offset+ i).set(c*cone.r_high, cone.h, s*cone.r_high);
- vtx.pos(offset+resolution1+i).set(c*cone.r_low , 0, s*cone.r_low );
- if(vtx.nrm())
- {
- vtx.nrm(offset+ i).set( 0, 1, 0);
- vtx.nrm(offset+resolution1+i).set(N.x*c, N.y, N.x*s);
- }
- if(vtx.tan())
- {
- vtx.tan(offset+ i).set(-s, 0, c);
- vtx.tan(offset+resolution1+i).set(-s, 0, c);
- }
- if(vtx.bin())
- {
- vtx.bin(offset+ i).set(N.y*c, -N.x, N.y*s);
- vtx.bin(offset+resolution1+i).set(N.y*c, -N.x, N.y*s);
- }
- if(vtx.tex0())
- {
- vtx.tex0(offset+ i).set( 0.5f, 0);
- vtx.tex0(offset+resolution1+i).set(Flt(i)/resolution, 1);
- }
- }
- // bottom
- REP(resolution-2)(tri++)->set(0, i+1, i+2);
- // sides
- REP(resolution)(tri++)->set(offset+i, offset+resolution1+i+1, offset+resolution1+i);
- transform(Matrix().setPosUp(cone.pos, cone.up));
- }else
- if(cone.r_high>EPS)
- {
- offset=resolution;
- create(resolution+resolution1*2, 0, resolution-2+resolution, 0, flag&(VTX_NRM_TAN_BIN|VTX_TEX0));
- VecI *tri=T.tri.ind();
- // vtxs
- REP(resolution)
- {
- Flt c, s; CosSin(c, s, i*PI2/resolution);
- vtx.pos (i).set(c*cone.r_high, cone.h, s*cone.r_high);
- if(vtx.nrm ())vtx.nrm (i).set(0, 1, 0);
- if(vtx.tan ())vtx.tan (i).set(1, 0, 0);
- if(vtx.bin ())vtx.bin (i).set(0, 0, -1);
- if(vtx.tex0())vtx.tex0(i).set(c, 1-s );
- }
- Vec2 N(cone.r_high-cone.r_low, cone.h); N=PerpN(N);
- REP(resolution1)
- {
- Flt c, s; CosSin(c, s, i*PI2/resolution);
- vtx.pos(offset+ i).set(c*cone.r_high, cone.h, s*cone.r_high);
- vtx.pos(offset+resolution1+i).set(c*cone.r_low , 0, s*cone.r_low );
- if(vtx.nrm())
- {
- vtx.nrm(offset+ i).set(N.x*c, N.y, N.x*s);
- vtx.nrm(offset+resolution1+i).set( 0, -1, 0);
- }
- if(vtx.tan())
- {
- vtx.tan(offset+ i).set(-s, 0, c);
- vtx.tan(offset+resolution1+i).set(-s, 0, c);
- }
- if(vtx.bin())
- {
- vtx.bin(offset+ i).set(N.y*c, -N.x, N.y*s);
- vtx.bin(offset+resolution1+i).set(N.y*c, -N.x, N.y*s);
- }
- if(vtx.tex0())
- {
- vtx.tex0(offset+ i).set(Flt(i)/resolution, 0);
- vtx.tex0(offset+resolution1+i).set( 0.5f, 1);
- }
- }
- // bottom
- REP(resolution-2)(tri++)->set(0, i+2, i+1);
- // sides
- REP(resolution)(tri++)->set(offset+i, offset+i+1, offset+resolution1+i);
- transform(Matrix().setPosUp(cone.pos, cone.up));
- }else
- {
- del();
- }
- if(!(flag&VTX_TEX0))weldVtx(VTX_ALL, EPS, EPS_COL_COS, -1);
- return T;
- }
- /******************************************************************************/
- MeshBase& MeshBase::create(C Torus &torus, UInt flag, Int resolution, Int resolution2)
- {
- if(resolution <0)resolution =12;else MAX(resolution , 3);
- if(resolution2<0)resolution2=12;else MAX(resolution2, 3);
- create((resolution+1)*(resolution2+1), 0, 0, resolution*resolution2, flag&(VTX_NRM_TAN_BIN|VTX_TEX0));
- VecI4 *quad=T.quad.ind();
- Matrix3 m; m.setUp(torus.up);
- // vtxs
- REP(resolution+1)
- {
- Vec2 cs; CosSin(cs.x, cs.y, i*PI2/resolution);
- Vec d=cs.x*m.x + cs.y*m.z;
- REPD(i2, resolution2+1)
- {
- Vec2 cs2; CosSin(cs2.x, cs2.y, i2*PI2/resolution2);
- Vec d2=cs2.x*d + cs2.y*m.y;
- Int j=i*(resolution2+1)+i2;
- vtx.pos (j)=torus.pos + d*torus.R + d2*torus.r;
- if(vtx.nrm ())vtx.nrm (j)=d2;
- if(vtx.tan ())vtx.tan (j)=cs.y*m.x - cs.x*m.z;
- if(vtx.bin ())vtx.bin (j)=cs2.x*m.y - cs2.y*d;
- if(vtx.tex0())vtx.tex0(j).set((1-Flt(i)/resolution)*4, Flt(i2)/resolution2);
- }
- }
- // quads
- REPD(i , resolution )
- REPD(i2, resolution2)(quad++)->set( i *(resolution2+1) + i2 , i *(resolution2+1) + i2+1,
- (i+1)*(resolution2+1) + i2+1, (i+1)*(resolution2+1) + i2 );
- if(!(flag&VTX_TEX0))weldVtx(VTX_ALL, EPS, EPS_COL_COS, -1);
- return T;
- }
- /******************************************************************************/
- MeshBase& MeshBase::createEdge(C Rect &rect, Bool solid)
- {
- create(4, 4, 0, 0, solid ? EDGE_FLAG : 0);
- vtx .pos(0).set(rect.min.x, rect.max.y, 0);
- vtx .pos(1).set(rect.max.x, rect.max.y, 0);
- vtx .pos(2).set(rect.max.x, rect.min.y, 0);
- vtx .pos(3).set(rect.min.x, rect.min.y, 0);
- edge.ind(0).set(0, 1);
- edge.ind(1).set(1, 2);
- edge.ind(2).set(2, 3);
- edge.ind(3).set(3, 0);
- if(edge.flag())edge.flag(0)=edge.flag(1)=edge.flag(2)=edge.flag(3)=ETQ_R;
- return T;
- }
- /******************************************************************************/
- MeshBase& MeshBase::create(C Shape &shape, UInt flag, Int resolution, Int resolution2)
- {
- switch(shape.type)
- {
- case SHAPE_BOX : return create(shape.box , flag, resolution);
- case SHAPE_OBOX : return create(shape.obox , flag, resolution);
- case SHAPE_BALL : return create(shape.ball , flag, resolution);
- case SHAPE_CAPSULE: return create(shape.capsule, flag, resolution, resolution2);
- case SHAPE_TUBE : return create(shape.tube , flag, resolution);
- case SHAPE_CONE : return create(shape.cone , flag, resolution);
- case SHAPE_TORUS : return create(shape.torus , flag, resolution, resolution2);
- default : return del();
- }
- }
- /******************************************************************************/
- MeshBase& MeshBase::createEdge(C Circle &circle, Bool solid, Int resolution)
- {
- if(resolution<0)resolution=24;else MAX(resolution, 3);
- create(resolution, resolution, 0, 0, solid ? EDGE_FLAG : 0);
- FREP(resolution)
- {
- Vec2 v; CosSin(v.x, v.y, i*-PI2/resolution);
- vtx .pos (i).set(circle.pos+v*circle.r, 0);
- edge.ind (i).set(i, (i+1)%resolution);
- if(edge.flag())edge.flag(i)=ETQ_R;
- }
- return T;
- }
- /******************************************************************************/
- MeshBase& MeshBase::createEdgeStar(Flt r1, Flt r2, Bool solid, Int resolution)
- {
- MAX(resolution, 3); resolution*=2;
- create(resolution, resolution, 0, 0, solid ? EDGE_FLAG : 0);
- FREP(resolution)
- {
- Flt x, y; CosSin(x, y, PI_2-i*PI2/resolution);
- if(i&1) vtx .pos (i).set(x*r1, y*r1, 0);
- else vtx .pos (i).set(x*r2, y*r2, 0);
- edge.ind (i).set(i, (i+1)%resolution);
- if(edge.flag())edge.flag(i)=ETQ_R;
- }
- return T;
- }
- /******************************************************************************/
- // CONVEX
- /******************************************************************************/
- struct Face
- {
- VecI tri ;
- Plane plane;
- };
- struct Convex
- {
- Memb<Vec > pos ;
- Memb<Face> face;
- void newFace(Int p0, Int p1, Int p2)
- {
- Face &f=face.New();
- f.tri .set(p0, p1, p2);
- f.plane.set(pos[p0], GetNormal(pos[p0], pos[p1], pos[p2]));
- }
- Bool cutsEps(Vec &pos)
- {
- if(face.elms())
- {
- REPA(face)if(Dist(pos, face[i].plane)>EPS)return false;
- return true;
- }
- return false;
- }
- Flt distPlanar(Vec &pos)
- {
- Flt d=0; REPA(face)MAX(d, Dist(pos, face[i].plane));
- return d;
- }
- void include(C Vec &pos)
- {
- Int pos_index=-1;
- Memc<VecI2> edge;
- REPA(face) // order is important
- {
- Face &f=face[i];
- Flt d=Dist(pos, f.plane);
- if( d>EPS) // face requires removing
- {
- if(pos_index<0){pos_index=T.pos.elms(); T.pos.add(pos);} // add point to container
- VecI2 test;
- Int t;
- test.set(f.tri.c[0], f.tri.c[1]); t=edge.find(test); if(t>=0)edge.remove(t);else{test.reverse(); edge.add(test);}
- test.set(f.tri.c[1], f.tri.c[2]); t=edge.find(test); if(t>=0)edge.remove(t);else{test.reverse(); edge.add(test);}
- test.set(f.tri.c[2], f.tri.c[0]); t=edge.find(test); if(t>=0)edge.remove(t);else{test.reverse(); edge.add(test);}
- face.remove(i);
- }
- }
- // add faces
- REPA(edge)newFace(pos_index, edge[i].y, edge[i].x);
- }
- };
- MeshBase& MeshBase::createConvex(C Vec *point, Int points, Int max_points)
- {
- MeshBase temp; // use 'temp' in case the 'point' comes from 'this'
- if(points>=4)
- {
- Int bound[8]={-1,-1,-1,-1, -1,-1,-1,-1};
- Flt dist [8];
- // get center
- Vec center=0; REP(points)center+=point[i]; center/=points;
- // get boundaries
- REP(points)
- {
- Flt d;
- Int o=0;
- Vec D=point[i]-center;
- d= D.x+D.y+D.z; if(bound[o]<0 || d>dist[o]){bound[o]=i; dist[o]=d;} o++;
- d= D.x+D.y-D.z; if(bound[o]<0 || d>dist[o]){bound[o]=i; dist[o]=d;} o++;
- d= D.x-D.y+D.z; if(bound[o]<0 || d>dist[o]){bound[o]=i; dist[o]=d;} o++;
- d= D.x-D.y-D.z; if(bound[o]<0 || d>dist[o]){bound[o]=i; dist[o]=d;} o++;
- d=-D.x+D.y+D.z; if(bound[o]<0 || d>dist[o]){bound[o]=i; dist[o]=d;} o++;
- d=-D.x+D.y-D.z; if(bound[o]<0 || d>dist[o]){bound[o]=i; dist[o]=d;} o++;
- d=-D.x-D.y+D.z; if(bound[o]<0 || d>dist[o]){bound[o]=i; dist[o]=d;} o++;
- d=-D.x-D.y-D.z; if(bound[o]<0 || d>dist[o]){bound[o]=i; dist[o]=d;} o++;
- }
- // move indexes left and remove duplicates
- Int bounds=0;
- {
- Int bound_new[Elms(bound)];
- FREPA(bound) // preserve order
- {
- Int b=bound[i]; if(b>=0)
- {
- REP(bounds)if(bound_new[i]==b)goto skip;
- bound_new[bounds++]=b;
- skip:;
- }
- }
- Swap(bound_new, bound);
- }
- Convex convex;
- /*TODO: optimize this?
- if(bounds==8) special case of box
- {
- }else*/
- if(bounds>=4)
- {
- // take 3 first
- VecI trii(bound[0], bound[1], bound[2]);
- Tri tri (point[trii.x], point[trii.y], point[trii.z]);
- // from the rest take the most distant
- Int disti=-1;
- Flt dist;
- for(Int i=3; i<bounds; i++)
- {
- Flt d=DistPointPlane(point[bound[i]], tri);
- if(disti<0 || Abs(d)>Abs(dist)){disti=i; dist=d;}
- }
- if(dist<=EPS) // if found point is coplanar to the triangle
- REP(points) // find a point that is most distant from the triangle plane
- {
- Flt d=DistPointPlane(point[i], tri);
- if(Abs(d)>Abs(dist)){bound[disti]=i; dist=d;}
- }
- // adjust
- if(dist>0)trii.reverse();
- Swap(bound[disti], bound[3]);
- // build convex from the 4 points
- convex.pos.New()=point[trii.x];
- convex.pos.New()=point[trii.y];
- convex.pos.New()=point[trii.z];
- convex.pos.New()=point[bound[3]];
- convex.newFace(0, 1, 2);
- convex.newFace(1, 0, 3);
- convex.newFace(2, 1, 3);
- convex.newFace(0, 2, 3);
- for(Int i=4; i<bounds; i++)convex.include(point[bound[i]]);
- }
- if(convex.pos.elms())
- {
- Memc<Vec> left; REP(points)
- {
- REPD(b, bounds)if(bound[b]==i)goto already_added;
- left.add(point[i]);
- already_added:;
- }
- if(max_points<=0) // insert all
- {
- REPA(left)if(convex.cutsEps(left[i]))left.remove(i); // early out
- REPA(left) convex.include(left[i]);
- }
- else // limit the vtx number
- {
- for(; left.elms() && convex.pos.elms()<max_points; )
- {
- // find the most distant
- Int disti=-1;
- Flt dist;
- for(Int i=0; i<Elms(left); ) // order is important
- {
- Flt d=convex.distPlanar(left[i]);
- if( d>EPS) // potentially to be added
- {
- if(disti<0 || d>dist){disti=i; dist=d;}
- i++;
- }
- else // it's too close so it can be thrown out
- {
- left.remove(i);
- }
- }
- if(disti<0)break;
- convex.include(left[disti]);
- left .remove ( disti );
- }
- }
- temp.create(convex.pos.elms(), 0, convex.face.elms(), 0);
- REPA(temp.vtx)temp.vtx.pos(i)=convex.pos [i];
- REPA(temp.tri)temp.tri.ind(i)=convex.face[i].tri;
- }
- }
- Swap(T, temp);
- return T;
- }
- /******************************************************************************
- MeshBase& createBlade( Int resolution=2, Flt width=0.06f, Flt angle=1.0f, Bool center=false, Flt normal_x_add=2, Flt normal_y_add=3); // create mesh as grass blade, 'resolution'=resolution, 'width'=blade width, 'angle'=blade bend angle, 'center'=if create center vertexes, 'normal_x_add normal_y_add' offsets to vertex normal
- MeshBase& createGrass(Int num, C Shape &shape=Shape(Circle(1)), Flt pitch=0.3f, Int resolution=2, Flt width=0.06f, Flt angle=1.0f, Bool center=false, Flt normal_x_add=2, Flt normal_y_add=3); // create mesh as grass , 'num'=number of blades, 'shape'=grass positions, 'pitch'=max angle of blade pitch, 'resolution'=resolution, 'width'=blade width, 'angle'=blade bend angle, 'center'=if create center vertexes, 'normal_x_add normal_y_add' offsets to vertex normal
- MeshBase& createRock (Int resolution=3, Int subdivisions=2 ); // create mesh as rock
- enum MESH_TREE_FLAG // Mesh Tree Creation Flags
- {
- MESH_TREE_LEAF_FLAT =0x1, // leafs will be created flat instead of geometrical
- MESH_TREE_LEAF_CENTER=0x2, // leafs will be created at center of the branch (valid only with MESH_TREE_LEAF_FLAT flag)
- };
- Mesh& createTree(MaterialPtr bark_material, Memb<MaterialPtr> &leaf_materials, UInt tree_flag=0, Flt leaf_scale=1, Flt leaf_intensity=1); // create a random tree mesh, 'tree_flag'=MESH_TREE_FLAG
- /******************************************************************************/
- // GRASS
- /******************************************************************************
- MeshBase& MeshBase::createBlade(Int resolution, Flt width, Flt angle, Bool center, Flt nrm_x_add, Flt nrm_y_add)
- {
- if(center)create(1 + (resolution+1)*3 + 1,0,4,resolution*2,VTX_TEX0);
- else create(1 + (resolution+1)*2 + 1,0,2,resolution ,VTX_TEX0);
- Vec *pos =T.vtx .pos ();
- Vec2 *tex =T.vtx .tex0();
- VecI *tri =T.tri .ind ();
- VecI4 *quad=T.quad.ind ();
- // vtxs
- (pos++)->zero();
- (tex++)->set (0.5f,1.0f);
- for(Int i=0; i<=resolution; i++)
- {
- Flt s=(i+1)/Flt(resolution+2),
- w=Sin(s*PI)*width,
- y= Sin(s*angle),
- z=1-Cos(s*angle);
- if(center)
- {
- (pos++)->set(-w,y-z*w,z+(1-y)*w); (tex++)->set(0 ,1-s);
- (pos++)->set( 0,y ,z ); (tex++)->set(0.5f,1-s);
- (pos++)->set( w,y-z*w,z+(1-y)*w); (tex++)->set(1 ,1-s);
- }else
- {
- (pos++)->set(-w,y,z); (tex++)->set(0,1-s);
- (pos++)->set( w,y,z); (tex++)->set(1,1-s);
- }
- }
- pos->set(0,Sin(angle),1-Cos(angle));
- tex->set(0.5f,0.0f);
- // tris
- if(center)
- {
- tri[0].set(0,1,2);
- tri[1].set(0,2,3); Int a=vtxs()-1, b=a-1, c=a-2, d=a-3;
- tri[2].set(a,b,c);
- tri[3].set(a,c,d);
- }else
- {
- tri[0].set(0,1,2); Int a=vtxs()-1, b=a-1, c=a-2;
- tri[1].set(a,b,c);
- }
- // quads
- FREP(resolution)
- {
- if(center)
- {
- Int i3=i*3;
- (quad++)->set(1+i3 , 1+i3+3 , 1+i3+3+1, 1+i3+1);
- (quad++)->set(1+i3+1, 1+i3+3+1, 1+i3+3+2, 1+i3+2);
- }else
- {
- Int i2=i*2;
- (quad++)->set(1+i2, 1+i2+2, 1+i2+2+1, 1+i2+1);
- }
- }
- // nrm
- setNormals();
- if(nrm_x_add || nrm_y_add)
- {
- Vec *pos=T.vtx.pos();
- Vec *nrm=T.vtx.nrm();
- REPA(vtx)
- {
- nrm[i].x+=nrm_x_add*Sign(pos[i].x);
- nrm[i].y+=nrm_y_add;
- nrm[i].normalize();
- }
- }
- return T;
- }
- MeshBase& MeshBase::createGrass(Int num, C Shape &shape, Flt pitch, Int resolution, Flt width, Flt angle, Bool center, Flt nrm_x_add, Flt nrm_y_add)
- {
- MeshBase *mshb; AllocZero(mshb,num);
- REP(num)
- {
- Vec offset=Random(shape);
- if(ShapeType2D(shape.type))Swap(offset.y,offset.z);
- else offset.y=0;
- mshb[i].createBlade(resolution, Random.f(0.9f,1.1f)*width, Random.f(0.9f,1.1f)*angle,center,nrm_x_add,nrm_y_add).transform(Matrix().setRotateXY(Random.f(-pitch,pitch), Random.f(PI2)).move(offset));
- }
- create(mshb,num);
- REP(num)mshb[i].del(); Free(mshb);
- return T;
- }
- /******************************************************************************/
- // ROCK
- /******************************************************************************
- MeshBase& MeshBase::createRock(Int resolution, Int subdivisions)
- {
- create(Ball(0.5),VTX_TEX0,resolution).quadToTri();
- // vtxs
- setVtxDup();
- Vec *pos=vtx.pos();
- Int *dup=vtx.dup();
- REPA(vtx)if(dup[i]==i)pos[i]+=Random(Ball(0.15f));
- REPA(vtx)pos[i]=pos[dup[i]];
- // scale
- Flt f=0.6f,t=1/f;
- scale(Vec(Random.f(f,t), Random.f(f,t), Random.f(f,t)));
- // smooth
- REP(subdivisions)subdivide().setVtxDup();
- // finish
- setTangents();
- return T;
- }
- /******************************************************************************/
- // TREE
- /******************************************************************************/
- #define RES 7
- #define STEP 2
- /******************************************************************************
- struct Branch
- {
- Vec pos[RES+1];
- Flt r [RES+1];
- Flt length;
- Int num,parent;
- Flt step(Flt frac, Vec &pos, Vec &dir)
- {
- Flt length=0;
- FREP(num)
- {
- Vec &p0=T.pos[i],
- &p1=T.pos[i+1],
- d =p1-p0;
- Flt l =d.normalize()/T.length;
- if(frac>=length && frac<=length+l)
- {
- frac=(frac-length)/l;
- dir=d;
- pos=Lerp(p0 ,p1 ,frac);
- return Lerp(r[i],r[i+1],frac);
- }
- length+=l;
- }
- pos=T.pos[0];
- return 0;
- }
- };
- struct Leaf
- {
- Matrix m;
- };
- /******************************************************************************
- static void BranchAdd(Memb<Branch> &branch, C Vec &pos, C Vec &dir, Flt r, Flt length, Int parent, Int step)
- {
- Int num=Mid(Round((length/20)*2*RES),1,RES),
- cur=branch.elms();
- Branch &b=branch.New();
- b.length =length;
- b.parent =parent;
- b.num =num;
- Vec p=pos,
- d=dir;
- FREP(num)
- {
- b.pos[i]=p;
- b.r [i]=r;
- p+=d*length/num;
- d =Random.dir(d,step ? 0.5f : 0.15f);
- r*=Random.f(0.75f,0.85f);
- }
- b.pos[num]=p;
- b.r [num]=0;
- if(step<=STEP)REPD(c,Round(Random.f(0.2f,1.1f)*length))
- {
- Vec pos,dir;
- Flt f=Random.f(0.3f,0.95f);
- Flt r=b.step(f,pos,dir);
- BranchAdd(branch, pos, Random.dir(dir,0.5f,1.2f), Random.f(0.75f,0.85f)*r, Random.f(0.8f,1.2f)*(1-f)*length,cur,step+1);
- }
- }
- static void BranchCreate(Memb<Branch> &branch)
- {
- BranchAdd(branch, Vec(0, 0, 0), Vec(0, 1, 0), Random.f(0.25f, 0.5f), Random.f(15, 20), -1, 0);
- }
- static void BranchDraw(Memb<Branch> &branch)
- {
- REPA(branch)
- {
- Branch &b=branch[i];
- Int r=Max(3,Round(Sqrt(b.r[0])*16));
- REP(b.num)
- {
- Vec &p0=b.pos[i ],
- &p1=b.pos[i+1];
- Cone(b.r[i],b.r[i+1],Dist(p0,p1),p0,!(p1-p0)).draw(WHITE,false,r);
- }
- }
- }
- static void CreateMesh(MeshBase &mshb, Branch &b, MeshBase *inside)
- {
- if(!b.num)mshb.del();else
- {
- Int r =Max(3,Round(Sqrt(b.r[0])*16)),
- r1=r+1;
- mshb.create(r1*b.num+1,0,r,r*(b.num-1), VTX_NRM|VTX_TEX0);
- Vec *pos =mshb.vtx .pos ();
- Vec *nrm =mshb.vtx .nrm ();
- Vec2 *tex =mshb.vtx .tex0();
- VecI *tri =mshb.tri .ind ();
- VecI4 *quad=mshb.quad.ind ();
- Matrix matrix=MatrixIdentity;
- Int v=0;
- Flt t=Random.f();
- FREP(b.num)
- {
- Vec dir =b.pos[i+1]-b.pos[i]; Flt length=dir.normalize();
- matrix.orn()*=Matrix3().setRotation(matrix.y, dir);
- matrix.pos =b.pos[i];
- REPD(j,r1)
- {
- Flt c, s; CosSin(c, s, j*PI2/r);
- pos[v+j].set(c*b.r[i],0,s*b.r[i]);
- nrm[v+j].set(c ,0,s );
- tex[v+j].set(Flt(j)/r,t);
- }
- Transform(pos+v,matrix ,r1);
- Transform(nrm+v,matrix.orn(),r1); Normalize(nrm+v,r1);
- if(i==b.num-1)
- {
- Int last=mshb.vtxs()-1;
- REPD(j,r)(tri++)->set(last,v+j+1,v+j);
- }else
- {
- REPD(j,r)(quad++)->set(v+r1+j,v+r1+j+1,v+j+1,v+j);
- }
- if(inside && i==2)
- {
- inside->create(r,0,r-2,0, VTX_TEX0);
- REPD(j,r)
- {
- Flt c, s; CosSin(c, s, j*PI2/r);
- inside->vtx.pos (j)=pos[v+j];
- inside->vtx.tex0(j).set(c*0.3f+0.5f,s*-0.3f+0.5f);
- }
- REPD(j,r-2)inside->tri.ind(j).set(0,j+2,j+1);
- }
- t-=length;
- v+=r1;
- }
- pos[v]=b.pos[b.num];
- nrm[v]=matrix.y;
- tex[v].set(0.5f,t);
- mshb.texScale(Vec2(1,(b.parent==-1) ? 0.35f : 0.1f/b.r[0]))
- .texMove (Random.vec2());
- }
- }
- static void LeafCreate(Memb<Leaf> &leaf, Memb<Branch> &branch, UInt tree_flag, Flt leaf_scale, Flt leaf_intensity)
- {
- FREPA(branch)
- {
- Branch &b=branch[i];
- REPD(j,b.num)
- {
- Flt r=Avg(b.r[j],b.r[j+1]);
- if( r<=0.1f)
- {
- Vec &p0 =b.pos[j],
- &p1 =b.pos[j+1],
- dir =p1-p0;
- Flt length=dir.normalize();
- REPD(cn,Round(Random.f(0.75f,1.25f)*10*length*leaf_intensity))
- {
- Leaf &l=leaf.New();
- Matrix &m=l.m;
- m.setRotateX(Random.f(DegToRad(45),(tree_flag&MESH_TREE_LEAF_FLAT) ? DegToRad(180) : DegToRad(90)))
- . rotateY(Random.f(PI2))
- . scale (Random.f(0.75f,1.3f)*((tree_flag&MESH_TREE_LEAF_FLAT) ? 0.4f : 0.5f)*leaf_scale);
- Flt c, s; CosSin(c, s, Random.f(PI2));
- Flt f=Random.f();
- Vec y=PerpN ( dir),
- x=CrossN (y,dir);
- r=Lerp (b.r[j],b.r[j+1],f);
- m+=p0
- +dir*(f*length)
- +x *(r* c)
- +y *(r* s);
- }
- }
- }
- }
- }
- static void CreateMesh(MeshBase &mshb,Leaf &leaf,UInt tree_flag)
- {
- if(tree_flag&MESH_TREE_LEAF_FLAT)
- {
- mshb.createPlane(2,2,VTX_TEX0|VTX_NRM).move(Vec(-0.5,0,0));
- REPA(mshb.vtx)
- {
- mshb.vtx.nrm(i).x+=Sign(mshb.vtx.pos(i).x);
- mshb.vtx.nrm(i) +=Random.vec(-0.2f,0.2f);
- mshb.vtx.nrm(i).normalize();
- }
- if(tree_flag&MESH_TREE_LEAF_CENTER)mshb.move(Vec(0,-0.5,0));
- }else
- {
- mshb.createBlade(1,0.2f,1.5f,false,1,0);
- }
- mshb*=leaf.m;
- mshb.include(VTX_HLP); REPA(mshb.vtx)mshb.vtx.hlp(i)=leaf.m.pos; // set helper positions to leaf start
- }
- static Mesh& setTree(Mesh &mesh, MaterialPtr bark_material, Memb<MaterialPtr> &leaf_materials, Memb<Branch> &branch, UInt tree_flag, Flt leaf_scale, Flt leaf_intensity)
- {
- Bool inside=false;
- Memc<MeshPart> p;
- // inside
- if(inside)
- {
- MeshPart &part=p.New(); // create 0-th MeshPart for 'inside'
- part.flag=MSHP_NO_PHYS_BODY;
- }
- // branches
- REPA(branch)
- {
- MeshPart &part=p.New();
- part.material(bark_material);
- CreateMesh(part.base,branch[i],(!inside || i) ? null : &p(0).base);
- }
- // leafs
- if(leaf_materials.elms())
- {
- Memb<Leaf> leaf; LeafCreate(leaf,branch,tree_flag,leaf_scale,leaf_intensity);
- REPA(leaf)
- {
- MeshPart &part=p.New();
- CreateMesh(part.base,leaf[i],tree_flag);
- part.material(leaf_materials[i%leaf_materials.elms()]);
- part.flag=MSHP_NO_PHYS_BODY;
- }
- }
- // finish
- {
- mesh.create (p.elms() ); FREPA(mesh)Swap(mesh.part(i),p[i]);
- mesh.joinAll(true, true, false, 0);
- mesh.setTangents()
- .setBox ();
- }
- return mesh;
- }
- Mesh& Mesh::createTree(MaterialPtr bark_material, Memb<MaterialPtr> &leaf_materials, UInt tree_flag, Flt leaf_scale, Flt leaf_intensity)
- {
- Memb<Branch> branch;
- BranchCreate(branch);
- setTree(T,bark_material,leaf_materials,branch,tree_flag,leaf_scale,leaf_intensity);
- return T;
- }
- /******************************************************************************/
- }
- /******************************************************************************/
|