void prop(std::vector<double> &pos, std::vector<double> &vel, double dt, int i){ // Updating Distance Between Bodies double r = mag(VecSub(pos, bodies[i].getPos())); // Updating Net Force std::vector<double> fNet = VecScaleMulti((VecSub(pos, bodies[i].getPos())), (G*bodies[0].getMass()*bodies[1].getMass())/(r*r*r)); // Update Netforce // Updating Pmomentum vel = VecAdd(vel, VecScaleMulti(fNet, dt/bodies[(i+1)%2].getMass())); // Updating Pos pos=VecAdd(pos, VecScaleMulti(vel, dt)); }
void FractalProjector:: new_vertex(Vertex* vrt, Face* parent) { // set the vertex to the center by calling the parents method RefinementCallbackLinear<APosition>::new_vertex(vrt, parent); // calculate the normal of the face vector3 n; CalculateNormal(n, parent, m_aaPos); // we have to alter the length. // first scale it to the average length of the faces edges, // then scale it with the given scaleFac. number avLen = 0; size_t numVrts = parent->num_vertices(); for(size_t i = 0; i < numVrts; ++i){ avLen += VecDistance(m_aaPos[parent->vertex(i)], m_aaPos[parent->vertex((i+1)% numVrts)]); } avLen /= (number)numVrts; VecScale (n, n, m_scaleFac * avLen); // offset the vertex by the calculated normal VecAdd(m_aaPos[vrt], m_aaPos[vrt], n); }
/************* * DESCRIPTION: Adjust the initial ray to account for an aperture and a focal * distance. The ray argument is assumed to be an initial ray, and * always reset to the eye point. It is assumed to be unit length. * INPUT: ray pointer to ray structure * world pointer to world structure * OUTPUT: none *************/ void CAMERA::FocusBlurRay(RAY *ray, WORLD *world) { VECTOR circle_point, aperture_inc; /* * Find a point on a unit circle and scale by aperture size. * This simulates rays passing thru different parts of the aperture. * Treat the point as a vector and rotate it so the circle lies * in the plane of the screen. Add the aperture increment to the * starting position of the ray. Stretch the ray to be focaldist * in length. Subtract the aperture increment from the end of the * long ray. This insures that the ray heads toward a point at * the specified focus distance, so that point will be in focus. * Normalize the ray, and that's it. Really. */ world->UnitCirclePoint(&circle_point, ray->sample); VecComb(aperture * circle_point.x, &scrni, aperture * circle_point.y, &scrnj, &aperture_inc); VecAdd(&aperture_inc, &pos, &(ray->start)); VecScale(focaldist, &ray->dir, &(ray->dir)); VecSub(&ray->dir, &aperture_inc, &(ray->dir)); VecNormalizeNoRet(&ray->dir); }
/************* * DESCRIPTION: sets the new object specs * INPUT: disp pointer to display structure * pos translate factor * ox,oy,oz rotate factor * size scale factor * OUTPUT: none *************/ void CAMERA::SetObject(DISPLAY *disp, VECTOR *pos, VECTOR *ox, VECTOR *oy, VECTOR *oz, VECTOR *size) { MATRIX m; if(disp) { if(disp->view->viewmode == VIEW_CAMERA) { VecAdd(pos,&this->pos,&disp->view->pos); if(!track) { InvOrient(ox, oy, oz, &disp->view->axis_x, &disp->view->axis_y, &disp->view->axis_z); m.SetOMatrix(&orient_x,&orient_y,&orient_z); m.MultVectMat(&disp->view->axis_x); m.MultVectMat(&disp->view->axis_y); m.MultVectMat(&disp->view->axis_z); } else { UpdateTracking(&disp->view->pos); InvOrient(&orient_x, &orient_y, &orient_z, &disp->view->axis_x, &disp->view->axis_y, &disp->view->axis_z); } } } SetVector(&bboxmin, -this->size.z*.5f, -this->size.z*.5f, -this->size.z); SetVector(&bboxmax, this->size.z*.5f, this->size.z*1.3f, this->size.z*1.5f); }
int main(int argc, char** argv) { int i; int sz = atoi(argv[1]); int element = atoi(argv[2]); srand( (unsigned)time( NULL )); IntVectorPtr vector = VecNew(initialCapacity); for(i=0;i<sz+1;i++) vector = VecAdd(vector,rand()%100); printlist(vector, sz); if (argc == 3) { VecQuickSort(vector); printf("\nThe position of the number %d is %d\n", element, VecBinarySearch(vector, element)); } else if ( strcmp(argv[3], "-l") == 0 ) { VecQuickSort2(vector, 1, sz-1); printf("\nThe position of the number %d is %d\n", element, VecBinarySearch2(vector->data, 0, sz, element)); } printlist(vector, sz); VecDelete(vector); return 0; }
//////////////////////////////////////////////////////////////////////// // CalculateVertexNormals bool CalculateVertexNormals(Grid& grid, Grid::AttachmentAccessor<Vertex, APosition>& aaPos, Grid::AttachmentAccessor<Vertex, ANormal>& aaNorm) { // set all normals to zero { for(VertexIterator iter = grid.begin<Vertex>(); iter != grid.end<Vertex>(); iter++) aaNorm[*iter] = vector3(0, 0, 0); } // loop through all the faces, calculate their normal and add them to their connected points { for(FaceIterator iter = grid.begin<Face>(); iter != grid.end<Face>(); iter++) { Face* f = *iter; vector3 vN; CalculateNormal(vN, f, aaPos); for(size_t i = 0; i < f->num_vertices(); ++i) VecAdd(aaNorm[f->vertex(i)], aaNorm[f->vertex(i)], vN); } } // loop through all the points and normalize their normals { for(VertexIterator iter = grid.begin<Vertex>(); iter != grid.end<Vertex>(); iter++) VecNormalize(aaNorm[*iter], aaNorm[*iter]); } // done return true; }
//给定两个R矩阵,和测得的l1,l2,(l1,l2均为3*1向量即[0;0;l1])求末端轨迹P void SolveP(const float* R1, const float* R2, const float* l1, const float* l2, float *P) { float M1[3]; float M2[3]; MatMultVec(R1, l1, M1); MatMultVec(R2, l2, M2); VecAdd(M1,M2,P); }
/************* * DESCRIPTION: transfer camera data to RayStorm Interface * INPUT: stack matrix stack * object pointer to created rsi object * OUTPUT: rsiERR_NONE if ok else error number *************/ rsiResult CAMERA::ToRSI(rsiCONTEXT *rc, MATRIX_STACK *stack, void **object) { VECTOR up, look, orient_x, orient_y, orient_z, pos; MATRIX m, m1; int rsiflags; rsiResult err; stack->GenerateAxis(&orient_x, &orient_y, &orient_z, &pos); m.SetOMatrix(&orient_x, &orient_y, &orient_z); if(track) { track->GetObjectMatrix(&m1); m1.GenerateAxis(&orient_x, &orient_x, &orient_x, &look); } else { SetVector(&look, 0.f, 0.f, 1000.f); m.MultVectMat(&look); VecAdd(&look, &pos, &look); } SetVector(&up, 0.f, 1.f, 0.f); m.MultVectMat(&up); err = PPC_STUB(rsiSetCamera)(CTXT, rsiTCameraPos, &pos, rsiTCameraViewUp, &up, rsiTCameraLook, &look, rsiTDone); if(err) return err; if(flags & OBJECT_CAMERA_VFOV) vfov = hfov*global.yres/global.xres; if(flags & OBJECT_CAMERA_FOCUSTRACK) { VecSub(&look, &pos, &look); focaldist = VecNormalize(&look); } rsiflags = 0; if (flags & OBJECT_CAMERA_FASTDOF) rsiflags |= rsiFCameraFastDOF; return PPC_STUB(rsiSetCamera)(CTXT, rsiTCameraPos, &pos, rsiTCameraHFov, atan(hfov) * 2 * INV_PI_180, rsiTCameraVFov, atan(vfov) * 2 * INV_PI_180, rsiTCameraFocalDist, focaldist, rsiTCameraAperture, aperture, rsiTCameraFlags, rsiflags, rsiTDone); }
//构造末端所需要的力F,输入起始点P,垂足Pp,P与Pp的距离d,控制参数an,输出力F void MakeF(const float *P, const float *Pp, const float d, const float an, float* F) { float para = an * log(1+d); float Fn[3] = {0,0,0}; float Ft[3] = {0,0,0}; Fn[0] = para * (Pp[0]-P[0]); Fn[1] = para * (Pp[1]-P[1]); Fn[2] = para * (Pp[2]-P[2]); VecAdd(Fn,Ft,F); }
typename TAAPosVRT::ValueType CalculateCenter(TIterator begin, TIterator end, TAAPosVRT& aaPos) { int counter = 0; typename TAAPosVRT::ValueType center; VecSet(center, 0); for(TIterator iter = begin; iter != end; ++iter, ++counter) VecAdd(center, center, CalculateCenter(*iter, aaPos)); if(counter > 0) VecScale(center, center, 1./(number)counter); return center; }
/************* * DESCRIPTION: Modify given normal by "bumping" it. * INPUT: norm normal * dpdu delta u * dpdv delta v * fu * fv * OUTPUT: none *************/ void MakeBump(VECTOR *norm, VECTOR *dpdu, VECTOR *dpdv, float fu, float fv) { VECTOR tmp1, tmp2; VecCross(norm, dpdv, &tmp1); tmp1.x *= fu; tmp1.y *= fu; tmp1.z *= fu; VecCross(norm, dpdu, &tmp2); tmp2.x *= fv; tmp2.y *= fv; tmp2.z *= fv; VecSub(&tmp1, &tmp2, &tmp1); VecAdd(norm, &tmp1, norm); VecNormalizeNoRet(norm); }
/* * Compute intensity ('color') of extended light source 'lp' from 'pos'. */ static int ExtendedIntens( LightRef lr, Color *lcolor, ShadowCache *cache, Ray *ray, Float /*dist*/, int noshadow, Color *color) { Extended *lp = (Extended*)lr; Float jit, vpos, upos, lightdist; Ray newray; Vector Uaxis, Vaxis, ldir; if (noshadow) { *color = *lcolor; return TRUE; } newray = *ray; /* * Determinte two orthoganal vectors that lay in the plane * whose normal is defined by the vector from the center * of the light source to the point of intersection and * passes through the center of the light source. */ VecSub(lp->pos, ray->pos, &ldir); VecCoordSys(&ldir, &Uaxis, &Vaxis); jit = 2. * lp->radius * Sampling.spacing; /* * Sample a single point, determined by SampleNumber, * on the extended source. */ vpos = -lp->radius + (ray->sample % Sampling.sidesamples)*jit; upos = -lp->radius + (ray->sample / Sampling.sidesamples)*jit; vpos += nrand() * jit; upos += nrand() * jit; VecComb(upos, Uaxis, vpos, Vaxis, &newray.dir); VecAdd(ldir, newray.dir, &newray.dir); lightdist = VecNormalize(&newray.dir); return !Shadowed(color, lcolor, cache, &newray, lightdist, noshadow); }
void FractalProjector:: new_vertex(Vertex* vrt, Edge* parent) { // set the vertex to the center by calling the parents method RefinementCallbackLinear<APosition>::new_vertex(vrt, parent); // calculate the normal of the edge vector3 n; CalculateNormal(n, *m_pGrid, parent, m_aaPos); // first scale it to the same length as the edge, then scale it with the // given scaleFac number len = VecDistance(m_aaPos[parent->vertex(0)], m_aaPos[parent->vertex(1)]); VecScale (n, n, m_scaleFac * len); // offset the vertex by the calculated normal VecAdd(m_aaPos[vrt], m_aaPos[vrt], n); }
//末端力转化到关节力矩,输入末端轨迹R1,R2,l1,l2,输出ts,te void TransformF(const float* R1, const float* R2, const float* l1,const float* l2, const float *F, float *ts, float *te) { float P1[3]; float P2[3]; float P[3]; MatMultVec(R1, l1, P1); MatMultVec(R2, l2, P2); VecAdd(P1,P2,P); VecCross(F,P,ts); float tmp[3]; VecCross(F,P2,tmp); te[0] = -VecDot(tmp,R1); te[1] = 0; te[2] = 0; }
std::vector<std::vector<double>> netForce(){ size_t n = bodies.size(); double totMass = 1.0; std::vector<double> pos = {0, 0, 0}; std::vector<std::vector<double>> output; for(unsigned int i = 0; i < n; ++i){ totMass *= bodies[i].getMass(); for(unsigned int j = 0; j < n && i!=j; ++j){ double magnitude = mag(VecSub(bodies[i].getPos(), bodies[j].getPos())); pos = VecAdd(pos, VecScaleMulti((VecSub(bodies[i].getPos(), bodies[j].getPos())), (1.0/(magnitude * magnitude * magnitude)))); } output.push_back(VecScaleMulti(pos, totMass*G)); } return output; }
void CalculateVertexNormal(vector3& nOut, Grid& grid, Vertex* vrt, TAAPosVRT& aaPos) { // set all normal to zero nOut = vector3(0, 0, 0); // loop through all associated faces, calculate their normal and add them to thee normal Grid::AssociatedFaceIterator iterEnd = grid.associated_faces_end(vrt); for(Grid::AssociatedFaceIterator iter = grid.associated_faces_begin(vrt); iter != iterEnd; iter++) { vector3 vN; CalculateNormal(vN, *iter, aaPos); VecAdd(nOut, nOut, vN); } VecNormalize(nOut, nOut); }
typename TAPosition::ValueType CalculateBarycenter(TVrtIter vrtsBegin, TVrtIter vrtsEnd, Grid::VertexAttachmentAccessor<TAPosition>& aaPos) { typename TAPosition::ValueType v; VecSet(v, 0); int counter = 0; for(TVrtIter iter = vrtsBegin; iter != vrtsEnd; ++iter) { VecAdd(v,v,aaPos[*iter]); counter++; } if(counter>0) VecScale(v,v,1.f/counter); return v; }
void JTModelAppend(JTModel *Self, DefNode *Parent, DefNode *Node) { VNode *view; Vec *vec = Parent->Children; if (!vec) { vec = VecInit(NULL); Parent->Children = vec; } VecAdd(vec, Node); view = Parent->tnode.NextView; Node->Parent = Parent; while (view) { JTreeAddView(view->Tree, view, &Node->tnode); view = view->NextView; } }
std::vector<double> accelFunc(std::vector<double> pos, std::vector<double> vel, double t){ std::vector<double> accel = {0, 0, 0}; double r; for(size_t i=0; i<bodies.size();++i){ r = mag(VecSub(pos, bodies[i].getPos())); if(r==0){ // If comparing body is same as current body continue; }else{ // If comparing to foreign body //accel+=bodies[i].getMass()/(r*r*r); accel= VecAdd(accel, VecScaleMulti(VecSub(pos, bodies[i].getPos()), (G*bodies[i].getMass()/(r*r*r)) ) ); } } return accel; }
/************* * DESCRIPTION: Update brush parameters * INPUT: time current time * OUTPUT: none *************/ void BRUSH::Update(const float time) { TIME t; VECTOR a; if((actor->time.begin != this->time) || (actor->time.end != time)) { t.begin = this->time; t.end = time; actor->Animate(&t); } actor->matrix->MultVectMat(&pos); a = actor->act_align; VecAdd(&a,&align,&a); CalcOrient(&a, &orient_x, &orient_y, &orient_z); this->time = time; }
typename ntree<tree_dim, world_dim, elem_t, common_data_t>::vector_t ntree<tree_dim, world_dim, elem_t, common_data_t>:: calculate_center_of_mass(Node& node) { vector_t centerOfMass; VecSet(centerOfMass, 0); for(size_t entryInd = node.firstEntryInd; entryInd != s_invalidIndex;){ Entry& entry = m_entries[entryInd]; vector_t center; traits::calculate_center(center, entry.elem, m_commonData); VecAdd(centerOfMass, centerOfMass, center); entryInd = entry.nextEntryInd; } if(node.numEntries > 0) VecScale(centerOfMass, centerOfMass, (real_t)1 / (real_t)node.numEntries); return centerOfMass; }
int main(){ int maxsize = 1000; std::vector<int>num1; std::vector<int>num2; std::vector<int>num3; num1.push_back(1); num2.push_back(1); int counter = 2; while(num1.size()+1 <= maxsize){ num3 = num1; num1 = VecAdd(num2, num3); num2 = num3; counter++; } std::cout << counter; }
void CalculateBoundaryVertexNormal3D(vector3& nOut, Grid& grid, Vertex* vrt, TAAPosVRT& aaPos) { // The algorithm is a little cumbersome. However, through this setup, we // make sure that the orientation of the normal indeed points outwards, // based only on the topology. // set nOut to 0 VecSet(nOut, 0); // iterate over associated volumes std::vector<Volume*> vols; CollectAssociated(vols, grid, vrt); FaceDescriptor fd; for(size_t i_vol = 0; i_vol < vols.size(); ++i_vol){ Volume* v = vols[i_vol]; // check for each side of f whether it is a boundary edge for(size_t i_side = 0; i_side < v->num_sides(); ++i_side){ if(IsBoundaryFace3D(grid, grid.get_face(v, i_side))){ v->face_desc(i_side, fd); // make sure that fd contains the given vertex if(!FaceContains(&fd, vrt)) continue; // the normal pointing outwards is clearly defined from the // orientation of the face descriptor vector3 n; CalculateNormal(n, &fd, aaPos); VecAdd(nOut, nOut, n); } } } VecNormalize(nOut, nOut); }
VOID PolyRead(OBJECT *po, FILE *pf) { INT i, j; /* Indices. */ INT instat; /* Read status. */ INT *vindex; INT totalverts; /* Total # of vertices in poly mesh. */ CHAR normstr[5]; /* Face/vertex normal flag string. */ BOOL pnormals; /* Face normals present? */ VEC3 pnorm; /* Polygon normal accumulator. */ VEC3 *vlist, *vptr, *vp; /* Ptr to vertex list. */ VEC3 *vptmp, *vptmp2; /* Ptr to vertex list. */ VEC3 tmppnt, tmppnt2, cross; POLY *pp; /* Ptr to polygon data. */ ELEMENT *pe; /* Ptr to polygon element. */ pe = po->pelem; /* Allocate space for object data. */ instat = fscanf(pf, "%ld", &totalverts); if (instat != 1) { printf("Error in PolyRead: totalverts.\n"); exit(-1); } pp = GlobalMalloc(sizeof(POLY)*po->numelements, "poly.c"); vlist = GlobalMalloc(sizeof(VEC3)*(totalverts + 1), "poly.c"); vptr = vlist; /* Are polygon face normals supplied? */ instat = fscanf(pf, "%s\n", normstr); if (instat != 1) { printf("Error in PolyRead: face normal indicator.\n"); exit(-1); } pnormals = (normstr[2] == 'y' ? TRUE : FALSE); /* Read vertex list. */ for (i = 0; i < totalverts; i++) { instat = fscanf(pf, "%lf %lf %lf", &(*vptr)[0], &(*vptr)[1], &(*vptr)[2]); if (instat != 3) { printf("Error in PolyRead: vertex %ld.\n", i); exit(-1); } vptr++; } (*vptr)[0] = HUGE_REAL; (*vptr)[1] = HUGE_REAL; (*vptr)[2] = HUGE_REAL; /* Read polygon list. */ for (i = 0; i < po->numelements; i++) { instat = fscanf(pf, "%ld", &(pp->nverts)); if (instat != 1) { printf("Error in PolyRead: vertex count.\n"); exit(-1); } if (pp->nverts > MAX_VERTS) { printf("Polygon vertex count, %ld, exceeds maximum.\n", pp->nverts); exit(-1); } if (pnormals) { instat = fscanf(pf, " %lf %lf %lf", &(pp->norm[0]), &(pp->norm[1]), &(pp->norm[2])); if (instat != 3) { printf("Error in PolyRead: face normal %ld.\n", i); exit(-1); } } pp->vptr = vlist; pp->vindex = GlobalMalloc(sizeof(INT)*pp->nverts, "poly.c"); vindex = pp->vindex; for (j = 0; j < pp->nverts; j++) { instat = fscanf(pf, "%ld", vindex++); if (instat != 1) { printf("Error in PolyRead: vertex index %ld.\n", i); exit(-1); } } /* If not supplied, calculate plane normal. */ vindex = pp->vindex; vptr = vlist; if (!pnormals) { vp = vptr + (*vindex); VecZero(pnorm); for (j = 0; j < pp->nverts - 2; j++) { vptmp = vptr + (*(vindex + 1)); vptmp2 = vptr + (*(vindex + 2)); VecSub(tmppnt, (*vptmp), (*vp)); VecSub(tmppnt2, (*vptmp2), (*vptmp)); VecCross(cross, tmppnt, tmppnt2); VecAdd(pnorm, pnorm, cross); vp = vptmp; vindex += 1; } VecSub(tmppnt, (*vptmp2), (*vp)); vindex = pp->vindex; vp = vptr + (*vindex); VecSub(tmppnt2, (*vp), (*vptmp2)); VecCross(cross, tmppnt, tmppnt2); VecAdd(pnorm, pnorm, cross); vp = vptr + (*vindex); VecSub(tmppnt, (*vp), (*vptmp2)); vptmp = vptr + (*(vindex + 1)); VecSub(tmppnt2, (*vptmp), (*vp)); VecCross(cross, tmppnt, tmppnt2); VecAdd(pnorm, pnorm, cross); VecScale(pp->norm, 1.0/VecLen(pnorm), pnorm); } /* Calculate plane equation d. */ vp = pp->vptr + *(pp->vindex); pp->d = -(pp->norm[0]*(*vp)[0] + pp->norm[1]*(*vp)[1] + pp->norm[2]*(*vp)[2]); pe->data = (CHAR *)pp; pe->parent = po; PolyElementBoundBox(pe, pp); pp++; pe++; } }
//求雅克比矩阵。 void SolveJacob(const float* MechPara, const float* R1, const float* R2, float* jacob_s, float* jacob_e) { float A1[3],A2[3],A3[3],A4[3],B1[3],B2[3],B3[3],B4[3],B5[3],B6[3],C1[3],C2[3]; const float l1 = MechPara[0]; //const float l2 = MechPara[1]; const float d1 = MechPara[2]; const float r1 = MechPara[3]; const float d2 = MechPara[4]; const float r2 = MechPara[5]; const float d3 = MechPara[6]; const float r3 = MechPara[7]; const float alphaa1 = MechPara[8]; const float psta2 = MechPara[9]; const float psta3 = MechPara[10]; const float alphaa4 = MechPara[11]; const float alphab1 = MechPara[12]; const float alphab2 = MechPara[13]; const float alphab3 = MechPara[14]; const float alphab4 = MechPara[15]; const float alphab5 = MechPara[16]; const float alphab6 = MechPara[17]; const float alphac1 = MechPara[18]; const float alphac2 = MechPara[19]; SolveTmpVec(r1,alphaa1,d1,A1); SolveTmpVec(r1,alphaa4,d1,A4); SolveTmpVec(r2,alphab1,d2,B1); SolveTmpVec(r2,alphab2,d2,B2); SolveTmpVec(r2,alphab3,d2,B3); SolveTmpVec(r2,alphab4,d2,B4); SolveTmpVec(r2,alphab5,d2,B5); SolveTmpVec(r2,alphab6,d2,B6); SolveTmpVec(r3,alphac1,d3,C1); SolveTmpVec(r3,alphac2,d3-84,C2); A2[0] = psta2; A2[1] = r1; A2[2] = d1; A3[0] = psta3; A3[1] = -r1; A3[2] = d1; float A[3] = {0,0,0}; float B[3]; float tmpl[3]; tmpl[0] = tmpl[1] = 0; tmpl[2] = l1; MatMultVec(R1,tmpl,B); float B1_r[3], B2_r[3], B3_r[3], B4_r[3], B5_r[3], B6_r[3], C1_r[3], C2_r[3], ld1[3], ld2[3], ld3[3], ld4[3], ld5[3], ld6[3]; MatMultVec(R1,B1,B1_r); MatMultVec(R1,B2,B2_r); MatMultVec(R1,B3,B3_r); MatMultVec(R1,B4,B4_r); MatMultVec(R1,B5,B5_r); MatMultVec(R1,B6,B6_r); MatMultVec(R2,C1,C1_r); MatMultVec(R2,C2,C2_r); VecAdd(B,C1_r,C1_r); VecAdd(B,C2_r,C2_r); VecSub(B1_r,A1,ld1); VecSub(B2_r,A2,ld2); VecSub(B3_r,A3,ld3); VecSub(B4_r,A4,ld4); VecSub(C1_r,B5,ld5); VecSub(C2_r,B6,ld6); Normalization(ld1); Normalization(ld2); Normalization(ld3); Normalization(ld4); Normalization(ld5); Normalization(ld6); float B1_r_A[3], B2_r_A[3], B3_r_A[3], B4_r_A[3], C1_r_B[3], C2_r_B[3]; VecSub(B1_r,A,B1_r_A); VecSub(B2_r,A,B2_r_A); VecSub(B3_r,A,B3_r_A); VecSub(B4_r,A,B4_r_A); VecSub(C1_r,B,C1_r_B); VecSub(C2_r,B,C2_r_B); float tmp[3]; VecCross(B1_r_A,ld1,tmp); jacob_s[0] = tmp[0]; jacob_s[4] = tmp[1]; jacob_s[8] = tmp[2]; VecCross(B2_r_A,ld2,tmp); jacob_s[1] = tmp[0]; jacob_s[5] = tmp[1]; jacob_s[9] = tmp[2]; VecCross(B3_r_A,ld3,tmp); jacob_s[2] = tmp[0]; jacob_s[6] = tmp[1]; jacob_s[10] = tmp[2]; VecCross(B4_r_A,ld4,tmp); jacob_s[3] = tmp[0]; jacob_s[7] = tmp[1]; jacob_s[11] = tmp[2]; VecCross(C1_r_B,ld5,tmp); jacob_e[0] = tmp[0]; jacob_e[2] = tmp[1]; jacob_e[4] = tmp[2]; VecCross(C2_r_B,ld6,tmp); jacob_e[1] = tmp[0]; jacob_e[3] = tmp[1]; jacob_e[5] = tmp[2]; }
int Refine(int* newIndsOut, int* newEdgeVrts, bool& newCenterOut, vector3* corners, bool*) { newCenterOut = false; // If a refinement rule is not implemented, fillCount will stay at 0. // Before returning, we'll check, whether fillCount is at 0 and will // perform refinement with an additional vertex in this case. // corner status is used to mark vertices, which are connected to refined edges // the value tells, how many associated edges are refined. int cornerStatus[4] = {0, 0, 0, 0}; // here we'll store the index of each edge, which will be refined. // Size of the valid sub-array is numNewVrts, which is calculated below. int refEdgeInds[NUM_EDGES]; // count the number of new vertices and fill newVrtEdgeInds int numNewVrts = 0; for(int i = 0; i < NUM_EDGES; ++i){ if(newEdgeVrts[i]){ refEdgeInds[numNewVrts] = i; ++numNewVrts; // adjust corner status of associated vertices const int* evi = EDGE_VRT_INDS[i]; ++cornerStatus[evi[0]]; ++cornerStatus[evi[1]]; } } // the fillCount tells how much data has already been written to newIndsOut. int fillCount = 0; // depending on the number of new vertices, we will now apply different // refinement rules. Further distinction may have to be done. switch(numNewVrts){ case 0: { // simply put the default tetrahedron back to newIndsOut newIndsOut[fillCount++] = GOID_TETRAHEDRON; newIndsOut[fillCount++] = 0; newIndsOut[fillCount++] = 1; newIndsOut[fillCount++] = 2; newIndsOut[fillCount++] = 3; }break; case 1: { int refEdgeInd = refEdgeInds[0]; // the two faces which are not connected to the refined edge // serve as bottom for the new tetrahedrons. for(int i_face = 0; i_face < NUM_FACES; ++i_face){ if(!FACE_CONTAINS_EDGE[i_face][refEdgeInd]){ const int* fvi = FACE_VRT_INDS[i_face]; newIndsOut[fillCount++] = GOID_TETRAHEDRON; newIndsOut[fillCount++] = fvi[0]; newIndsOut[fillCount++] = fvi[1]; newIndsOut[fillCount++] = fvi[2]; newIndsOut[fillCount++] = NUM_VERTICES + refEdgeInd; } } }break; case 2: { // two types exist: The two refined edges share a vertex or not. if(OPPOSED_EDGE[refEdgeInds[0]] == refEdgeInds[1]){ // they do not share an edge // we create a local order from refEdgeInds[0], which // always has to be an edge in the base-triangle and // refEdgeInds[1], which always connects a base-corner with // the top. const int v0 = EDGE_VRT_INDS[refEdgeInds[0]][0]; const int v1 = EDGE_VRT_INDS[refEdgeInds[0]][1]; const int v2 = EDGE_VRT_INDS[refEdgeInds[1]][0]; const int v3 = EDGE_VRT_INDS[refEdgeInds[1]][1]; const int n0 = refEdgeInds[0] + NUM_VERTICES; const int n1 = refEdgeInds[1] + NUM_VERTICES; // from this local order we can now construct the 4 new tetrahedrons. int& fi = fillCount; int* inds = newIndsOut; inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = v0; inds[fi++] = n0; inds[fi++] = v2; inds[fi++] = n1; inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = v0; inds[fi++] = n0; inds[fi++] = n1; inds[fi++] = v3; inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = n0; inds[fi++] = v1; inds[fi++] = v2; inds[fi++] = n1; inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = n0; inds[fi++] = v1; inds[fi++] = n1; inds[fi++] = v3; } else{ // they share an edge // We have to create a pyramid and a tetrahedron. // get the triangle, which contains both refEdges int refTriInd = FACE_FROM_EDGES[refEdgeInds[0]][refEdgeInds[1]]; const int* f = FACE_VRT_INDS[refTriInd]; // find the edge (v0, v1) in refTri, which won't be refined int v0 = -1; int v1 = -1; int v2 = -1; for(int i = 0; i < 3; ++i){ v0 = f[i]; v1 = f[(i+1)%3]; v2 = f[(i+2)%3]; if(cornerStatus[v0] == 1 && cornerStatus[v1] == 1) break; } // make sure that v2 is connected to two refined edges assert(cornerStatus[v2] == 2); // get the new vertex on edge v1v2 and on v2v0 int v1v2 = EDGE_FROM_VRTS[v1][v2] + NUM_VERTICES; int v2v0 = EDGE_FROM_VRTS[v2][v0] + NUM_VERTICES; // get the top (vertex with cornerState 0) int vtop = -1; for(int i = 0; i < NUM_VERTICES; ++i){ if(cornerStatus[i] == 0){ vtop = i; break; } } // now lets build the pyramid int& fi = fillCount; int* inds = newIndsOut; inds[fi++] = GOID_PYRAMID; inds[fi++] = v0; inds[fi++] = v1; inds[fi++] = v1v2; inds[fi++] = v2v0; inds[fi++] = vtop; // and now the terahedron inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = v2; inds[fi++] = vtop; inds[fi++] = v2v0; inds[fi++] = v1v2; } }break; case 3: { // different possibilities exist. First we'll treat the one, // where all new vertices lie on the edges of one triangle. // Note that refTriInd could be -1 after the call. int refTriInd = FACE_FROM_EDGES[refEdgeInds[0]][refEdgeInds[1]]; if(refTriInd == FACE_FROM_EDGES[refEdgeInds[1]][refEdgeInds[2]]) { // all three lie in one plane (refTriInd has to be != -1 to get here) // get the top (vertex with cornerState 0) int vtop = -1; for(int i = 0; i < NUM_VERTICES; ++i){ if(cornerStatus[i] == 0){ vtop = i; break; } } const int* f = FACE_VRT_INDS[refTriInd]; // create four new tetrahedrons const int v0 = f[0]; const int v1 = f[1]; const int v2 = f[2]; const int v0v1 = EDGE_FROM_VRTS[v0][v1] + NUM_VERTICES; const int v1v2 = EDGE_FROM_VRTS[v1][v2] + NUM_VERTICES; const int v2v0 = EDGE_FROM_VRTS[v2][v0] + NUM_VERTICES; int& fi = fillCount; int* inds = newIndsOut; inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = v0; inds[fi++] = vtop; inds[fi++] = v0v1; inds[fi++] = v2v0; inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = v1; inds[fi++] = vtop; inds[fi++] = v1v2; inds[fi++] = v0v1; inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = v2; inds[fi++] = vtop; inds[fi++] = v2v0; inds[fi++] = v1v2; inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = v0v1; inds[fi++] = vtop; inds[fi++] = v1v2; inds[fi++] = v2v0; } else{ // we have to further distinguish. // gather the corners with corner-state 3 and corner state 1 int corner3 = -1; int freeCorner[NUM_VERTICES]; int freeCount = 0; for(int i = 0; i < NUM_VERTICES; ++i){ if(cornerStatus[i] == 3) corner3 = i; else freeCorner[freeCount++] = i; } if(corner3 != -1){ // a corner with corner state 3 exists. assert(freeCount == 3); // get the face which won't be refined (required for correct orientation) int freeTriInd = FACE_FROM_VRTS[freeCorner[0]][freeCorner[1]] [freeCorner[2]]; // the free tri is the new base, corner3 the top const int* f = FACE_VRT_INDS[freeTriInd]; int v2v3 = EDGE_FROM_VRTS[f[2]][corner3] + NUM_VERTICES; int v1v3 = EDGE_FROM_VRTS[f[1]][corner3] + NUM_VERTICES; int v0v3 = EDGE_FROM_VRTS[f[0]][corner3] + NUM_VERTICES; // add a prism and a tetrahedron int& fi = fillCount; int* inds = newIndsOut; inds[fi++] = GOID_PRISM; inds[fi++] = f[0]; inds[fi++] = f[1]; inds[fi++] = f[2]; inds[fi++] = v0v3; inds[fi++] = v1v3; inds[fi++] = v2v3; inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = v2v3; inds[fi++] = corner3; inds[fi++] = v0v3; inds[fi++] = v1v3; } } }break; case 4: { // multiple settings with 4 refined edges exist. // Either two opposing edges are not marked (case all2 == true) // or the two unmarked edges are contained in 1 triangle // check whether all vertices have corner state 2 bool all2 = true; for(int i = 0; i < NUM_VERTICES; ++i){ if(cornerStatus[i] !=2){ all2 = false; break; } } if(all2){ // we've got a straight cut. // we'll rotate the tetrahedron around the tip so, that edge 2 won't be refined. int steps = 0; if(!newEdgeVrts[EDGE_FROM_VRTS[0][1]]) steps = 2; else if(!newEdgeVrts[EDGE_FROM_VRTS[1][2]]) steps = 1; int t[NUM_VERTICES] = {0, 1, 2, 3}; TetRotation(t, 3, steps); const int v0v1 = EDGE_FROM_VRTS[t[0]][t[1]] + NUM_VERTICES; const int v1v2 = EDGE_FROM_VRTS[t[1]][t[2]] + NUM_VERTICES; const int v0v3 = EDGE_FROM_VRTS[t[0]][t[3]] + NUM_VERTICES; const int v2v3 = EDGE_FROM_VRTS[t[2]][t[3]] + NUM_VERTICES; assert(newEdgeVrts[v0v1 - NUM_VERTICES]); assert(newEdgeVrts[v1v2 - NUM_VERTICES]); assert(newEdgeVrts[v0v3 - NUM_VERTICES]); assert(newEdgeVrts[v2v3 - NUM_VERTICES]); // now build two prisms int& fi = fillCount; int* inds = newIndsOut; inds[fi++] = GOID_PRISM; inds[fi++] = t[0]; inds[fi++] = v0v3; inds[fi++] = v0v1; inds[fi++] = t[2]; inds[fi++] = v2v3; inds[fi++] = v1v2; inds[fi++] = GOID_PRISM; inds[fi++] = t[1]; inds[fi++] = v1v2; inds[fi++] = v0v1; inds[fi++] = t[3]; inds[fi++] = v2v3; inds[fi++] = v0v3; } else{ // one corner has state 1, one has state 3 and two have state 2. // Rotate the tet so that 1 is at the top and 4 is at the origin int I[NUM_VERTICES] = {0, 1, 2, 3}; int s1 = -1; for(int i = 0; i < 4; ++i){ if(cornerStatus[i] == 1){ s1 = i; break; } } if(s1 != 3){ const int fixedPoint = (s1 + 2) % 3; TetRotation(I, fixedPoint, 1); } if(cornerStatus[I[1]] == 3) TetRotation(I, 3, 2); else if(cornerStatus[I[2]] == 3) TetRotation(I, 3, 1); // indices of edge-center vertices const int v01 = EDGE_FROM_VRTS[I[0]][I[1]] + NUM_VERTICES; const int v02 = EDGE_FROM_VRTS[I[0]][I[2]] + NUM_VERTICES; const int v03 = EDGE_FROM_VRTS[I[0]][I[3]] + NUM_VERTICES; const int v12 = EDGE_FROM_VRTS[I[1]][I[2]] + NUM_VERTICES; int& fi = fillCount; int* inds = newIndsOut; inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = I[0]; inds[fi++] = v01; inds[fi++] = v02; inds[fi++] = v03; inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = v01; inds[fi++] = v12; inds[fi++] = v02; inds[fi++] = v03; inds[fi++] = GOID_PYRAMID; inds[fi++] = I[3]; inds[fi++] = I[1]; inds[fi++] = v01; inds[fi++] = v03; inds[fi++] = v12; inds[fi++] = GOID_PYRAMID; inds[fi++] = I[2]; inds[fi++] = I[3]; inds[fi++] = v03; inds[fi++] = v02; inds[fi++] = v12; } }break; case 5:{ // only one edge is not marked for refinement int unmarkedEdge = 0; for(int i = 0; i < NUM_EDGES; ++i){ if(!newEdgeVrts[i]){ unmarkedEdge = i; break; } } int uei0 = EDGE_VRT_INDS[unmarkedEdge][0]; int uei1 = EDGE_VRT_INDS[unmarkedEdge][1]; // orientate the tetrahedron so that the unmarked edge connects // vertices 2 and 3 int I[NUM_VERTICES] = {0, 1, 2, 3}; // if the unmarked edge lies in the base triangle, we'll first have to // rotate so that it connects a base-vertex with the top if(unmarkedEdge < 3){ const int fixedPoint = (uei1 + 1) % 3; TetRotation(I, fixedPoint, 1); int IInv[4]; InverseTetTransform(IInv, I); uei0 = IInv[uei0]; uei1 = IInv[uei1]; unmarkedEdge = EDGE_FROM_VRTS[uei0][uei1]; } // now rotate the tet to its final place if(unmarkedEdge == 3) TetRotation(I, 3, 2); else if(unmarkedEdge == 4) TetRotation(I, 3, 1); // We obtained the final permutation I. Now create new elements // indices of edge-center vertices const int v01 = EDGE_FROM_VRTS[I[0]][I[1]] + NUM_VERTICES; const int v02 = EDGE_FROM_VRTS[I[0]][I[2]] + NUM_VERTICES; const int v03 = EDGE_FROM_VRTS[I[0]][I[3]] + NUM_VERTICES; const int v12 = EDGE_FROM_VRTS[I[1]][I[2]] + NUM_VERTICES; const int v13 = EDGE_FROM_VRTS[I[1]][I[3]] + NUM_VERTICES; int& fi = fillCount; int* inds = newIndsOut; inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = I[0]; inds[fi++] = v01; inds[fi++] = v02; inds[fi++] = v03; inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = I[1]; inds[fi++] = v12; inds[fi++] = v01; inds[fi++] = v13; inds[fi++] = GOID_PYRAMID; inds[fi++] = v02; inds[fi++] = v12; inds[fi++] = v13; inds[fi++] = v03; inds[fi++] = v01; inds[fi++] = GOID_PRISM; inds[fi++] = v02; inds[fi++] = v12; inds[fi++] = I[2]; inds[fi++] = v03; inds[fi++] = v13; inds[fi++] = I[3]; }break; // REGULAR REFINEMENT case 6: { // depending on the user specified global refinement rule, we will now apply different // refinement rules. switch(g_refinementRule){ case STANDARD: { int& fi = fillCount; int* inds = newIndsOut; inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = 0; inds[fi++] = NUM_VERTICES + 0; inds[fi++] = NUM_VERTICES + 2; inds[fi++] = NUM_VERTICES + 3; inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = 1; inds[fi++] = NUM_VERTICES + 1; inds[fi++] = NUM_VERTICES + 0; inds[fi++] = NUM_VERTICES + 4; inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = 2; inds[fi++] = NUM_VERTICES + 2; inds[fi++] = NUM_VERTICES + 1; inds[fi++] = NUM_VERTICES + 5; inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = NUM_VERTICES + 3; inds[fi++] = NUM_VERTICES + 4; inds[fi++] = NUM_VERTICES + 5; inds[fi++] = 3; // for the remaining four tetrahedrons, we'll choose the shortest diagonal int bestDiag = 2; if(corners){ // there are three diagonals between the following edge-centers: // 0-5, 1-3, 2-4 vector3 c1, c2; // 0-5 VecAdd(c1, corners[0], corners[1]); VecScale(c1, c1, 0.5); VecAdd(c2, corners[2], corners[3]); VecScale(c2, c2, 0.5); number d05 = VecDistanceSq(c1, c2); // 1-3 VecAdd(c1, corners[1], corners[2]); VecScale(c1, c1, 0.5); VecAdd(c2, corners[0], corners[3]); VecScale(c2, c2, 0.5); number d13 = VecDistanceSq(c1, c2); // 2-4 VecAdd(c1, corners[0], corners[2]); VecScale(c1, c1, 0.5); VecAdd(c2, corners[1], corners[3]); VecScale(c2, c2, 0.5); number d = VecDistanceSq(c1, c2); if(d13 < d){ bestDiag = 1; d = d13; } if(d05 < d){ bestDiag = 0; } } switch(bestDiag){ case 0:// diag: 0-5 inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = NUM_VERTICES + 0; inds[fi++] = NUM_VERTICES + 1; inds[fi++] = NUM_VERTICES + 2; inds[fi++] = NUM_VERTICES + 5; inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = NUM_VERTICES + 1; inds[fi++] = NUM_VERTICES + 4; inds[fi++] = NUM_VERTICES + 5; inds[fi++] = NUM_VERTICES + 0; inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = NUM_VERTICES + 2; inds[fi++] = NUM_VERTICES + 5; inds[fi++] = NUM_VERTICES + 3; inds[fi++] = NUM_VERTICES + 0; inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = NUM_VERTICES + 0; inds[fi++] = NUM_VERTICES + 3; inds[fi++] = NUM_VERTICES + 4; inds[fi++] = NUM_VERTICES + 5; break; case 1:// diag: 1-3 inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = NUM_VERTICES + 0; inds[fi++] = NUM_VERTICES + 1; inds[fi++] = NUM_VERTICES + 2; inds[fi++] = NUM_VERTICES + 3; inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = NUM_VERTICES + 1; inds[fi++] = NUM_VERTICES + 4; inds[fi++] = NUM_VERTICES + 5; inds[fi++] = NUM_VERTICES + 3; inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = NUM_VERTICES + 2; inds[fi++] = NUM_VERTICES + 5; inds[fi++] = NUM_VERTICES + 3; inds[fi++] = NUM_VERTICES + 1; inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = NUM_VERTICES + 0; inds[fi++] = NUM_VERTICES + 3; inds[fi++] = NUM_VERTICES + 4; inds[fi++] = NUM_VERTICES + 1; break; case 2:// diag 2-4 inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = NUM_VERTICES + 0; inds[fi++] = NUM_VERTICES + 2; inds[fi++] = NUM_VERTICES + 3; inds[fi++] = NUM_VERTICES + 4; inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = NUM_VERTICES + 1; inds[fi++] = NUM_VERTICES + 2; inds[fi++] = NUM_VERTICES + 0; inds[fi++] = NUM_VERTICES + 4; inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = NUM_VERTICES + 2; inds[fi++] = NUM_VERTICES + 3; inds[fi++] = NUM_VERTICES + 4; inds[fi++] = NUM_VERTICES + 5; inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = NUM_VERTICES + 4; inds[fi++] = NUM_VERTICES + 1; inds[fi++] = NUM_VERTICES + 2; inds[fi++] = NUM_VERTICES + 5; break; } }break; case HYBRID_TET_OCT: { // REGULAR REFINEMENT int& fi = fillCount; int* inds = newIndsOut; // outer tetrahedrons analogously defined to STANDARD case inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = 0; inds[fi++] = NUM_VERTICES + 0; inds[fi++] = NUM_VERTICES + 2; inds[fi++] = NUM_VERTICES + 3; inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = 1; inds[fi++] = NUM_VERTICES + 1; inds[fi++] = NUM_VERTICES + 0; inds[fi++] = NUM_VERTICES + 4; inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = 2; inds[fi++] = NUM_VERTICES + 2; inds[fi++] = NUM_VERTICES + 1; inds[fi++] = NUM_VERTICES + 5; inds[fi++] = GOID_TETRAHEDRON; inds[fi++] = NUM_VERTICES + 3; inds[fi++] = NUM_VERTICES + 4; inds[fi++] = NUM_VERTICES + 5; inds[fi++] = 3; // inner octahedron: // For the remaining inner cavity we'll choose the shortest diagonal // and order the octahedral nodes, so that, the implicit // subdivision of the octahedron into tetrahedrons during // discretization happens alongside exactly this shortest diagonal. int bestDiag = 2; if(corners){ // there are three diagonals between the following edge-centers: // 0-5, 1-3, 2-4 vector3 c1, c2; // 0-5 VecAdd(c1, corners[0], corners[1]); VecScale(c1, c1, 0.5); VecAdd(c2, corners[2], corners[3]); VecScale(c2, c2, 0.5); number d05 = VecDistanceSq(c1, c2); // 1-3 VecAdd(c1, corners[1], corners[2]); VecScale(c1, c1, 0.5); VecAdd(c2, corners[0], corners[3]); VecScale(c2, c2, 0.5); number d13 = VecDistanceSq(c1, c2); // 2-4 VecAdd(c1, corners[0], corners[2]); VecScale(c1, c1, 0.5); VecAdd(c2, corners[1], corners[3]); VecScale(c2, c2, 0.5); number d = VecDistanceSq(c1, c2); if(d13 < d){ bestDiag = 1; d = d13; } if(d05 < d){ bestDiag = 0; } } switch(bestDiag){ case 0:// diag: 0-5 inds[fi++] = GOID_OCTAHEDRON; inds[fi++] = NUM_VERTICES + 1; inds[fi++] = NUM_VERTICES + 0; inds[fi++] = NUM_VERTICES + 4; inds[fi++] = NUM_VERTICES + 5; inds[fi++] = NUM_VERTICES + 2; inds[fi++] = NUM_VERTICES + 3; break; case 1:// diag: 1-3 inds[fi++] = GOID_OCTAHEDRON; inds[fi++] = NUM_VERTICES + 0; inds[fi++] = NUM_VERTICES + 3; inds[fi++] = NUM_VERTICES + 4; inds[fi++] = NUM_VERTICES + 1; inds[fi++] = NUM_VERTICES + 2; inds[fi++] = NUM_VERTICES + 5; break; case 2:// diag 2-4 inds[fi++] = GOID_OCTAHEDRON; inds[fi++] = NUM_VERTICES + 1; inds[fi++] = NUM_VERTICES + 2; inds[fi++] = NUM_VERTICES + 0; inds[fi++] = NUM_VERTICES + 4; inds[fi++] = NUM_VERTICES + 5; inds[fi++] = NUM_VERTICES + 3; break; }break; }break; } }break; } if(fillCount == 0){ // call recursive refine fillCount = shared_rules::RecursiveRefine(newIndsOut, newEdgeVrts, FACE_VRT_INDS, FACE_EDGE_INDS, NUM_VERTICES, NUM_EDGES, NUM_FACES); // the rule requires a new center vertex newCenterOut = true; } return fillCount; }
/************* * DESCRIPTION: - * INPUT: pointer to chunk * OUTPUT: - *************/ static void ParseNamedObject(HANDLER_DATA *data, CHUNK *mainchunk) { CHUNK chunk; TRIANGLE *triangle; TRILIST *ph1,*ph2; float angle; UWORD p1, p2, p3; UWORD *edges; int i, h; ReadASCIIZ(data, data->ObjName); do { BeginChunk(data, &chunk); switch (chunk.id) { case ID_TRIANGLE: ParseTriObject(data, &chunk); break; } EndChunk(data, &chunk); } while (INCHUNK); if (data->TriList && (data->link->type == LINK_RENDERER)) { // go through all vertices and calculate normals (only for renderer) for (i = 0; i < data->pointcount; i++) { data->VertNorms[i].x = data->VertNorms[i].y = data->VertNorms[i].z = 0.f; ph1 = data->TriList[i]; while (ph1) { for (ph2 = ph1->next; ph2 != NULL; ph2 = ph2->next) { if (!ph1->flag || !ph2->flag) { // test angle between two triangles angle = VecAngle(data->TriNorms[ph1->tri], data->TriNorms[ph2->tri]); // if (angle < 2*PI && angle > /*cos_*/smooth_angle) if (angle >0 && angle < /*cos_*/data->smooth_angle) { if (!ph1->flag) { VecAdd(&data->VertNorms[i], &data->TriNorms[ph1->tri], &data->VertNorms[i]); ph1->flag = TRUE; data->TriSmooth[ph1->tri] = TRUE; } if (!ph2->flag) { VecAdd(&data->VertNorms[i], &data->TriNorms[ph2->tri], &data->VertNorms[i]); ph2->flag = TRUE; data->TriSmooth[ph2->tri] = TRUE; } } } } ph2 = ph1; ph1 = ph1->next; delete ph2; } VecNormalize(&data->VertNorms[i]); } } if (data->face) { data->link->ObjectBegin(data->rc); data->defaultsurface = data->link->SurfaceAdd(data->rc); if (!data->defaultsurface) { data->err = ERR_MEM; return; } data->link->SurfaceName(data->rc, data->defaultsurface, "default"); data->link->SurfaceDiffuse(data->rc, data->defaultsurface, 0.9f, 0.9f, 0.9f); data->link->SurfaceAmbient(data->rc, data->defaultsurface, 0.1f, 0.1f, 0.1f); data->link->SurfaceRefPhong(data->rc, data->defaultsurface, 49.f); triangle = data->link->TriangleAdd(data->rc, data->facecount,data->defaultsurface,data->mainactor); if (!triangle) { data->err = ERR_MEM; return; } if (data->link->type == LINK_SCENARIO) { // modeler needs points,edges and faces seperate if (data->link->TriangleAddPoints(data->rc, data->pointcount,data->points) == -1) { data->err = ERR_MEM; return; } edges = new UWORD[data->facecount*6]; if (!edges) { data->err = ERR_MEM; return; } for (i = 0; i < data->facecount; i++) { h = i*6; edges[h++] = data->face[i].p1; edges[h++] = data->face[i].p2; edges[h++] = data->face[i].p2; edges[h++] = data->face[i].p3; edges[h++] = data->face[i].p3; edges[h++] = data->face[i].p1; } if (data->link->TriangleAddEdges(data->rc, data->facecount*3,edges) == -1) { delete edges; data->err = ERR_MEM; return; } delete edges; } for (i = 0; i < data->facecount; i++) { p1 = data->face[i].p1; p2 = data->face[i].p3; p3 = data->face[i].p2; if(data->replacesurface) data->link->TriangleSurface(data->rc, triangle, data->replacesurface); else { if(!data->material[i]) data->link->TriangleSurface(data->rc, triangle, data->defaultsurface); else data->link->TriangleSurface(data->rc, triangle, data->material[i]); } if (data->link->type == LINK_SCENARIO) { // modeler needs edges data->link->TriangleSetEdges(data->rc, triangle,i*3,i*3+1,i*3+2); } else { // raystorm renderer needs triangles and normals data->link->TrianglePoints(data->rc, triangle,&data->points[p1],&data->points[p2],&data->points[p3]); if (!VecZero(data->TriNorms[i])) { // generate smooth triangle when smooth flag is set if (data->TriSmooth[i]) { data->link->TriangleVNorm(data->rc, triangle, VecZero(data->VertNorms[p1]) ? &data->TriNorms[i] : &data->VertNorms[p1], VecZero(data->VertNorms[p2]) ? &data->TriNorms[i] : &data->VertNorms[p2], VecZero(data->VertNorms[p3]) ? &data->TriNorms[i] : &data->VertNorms[p3]); } } if(data->mapping) { data->link->TriangleUV(data->rc, triangle, &data->mapping[p1], &data->mapping[p2], &data->mapping[p3]); } } // next triangle triangle = data->link->TriangleGetNext(data->rc, triangle); } data->link->ObjectEnd(data->rc); } CleanupMesh(data); }
/************* * DESCRIPTION: generate normal for one triangle point * INPUT: tnum current triangle index * n calculated normal * normals flat normal array * edgidx index array which points to two triangles for each edge * p point to generate normal of * edges edge array * trias triangle array * OUTPUT: - *************/ static void GenerateNormal(UWORD tnum, VECTOR *n, VECTOR *normals, UWORD *edgidx, UWORD p, EDGE *edges, MESH *trias) { UWORD e[2], edge, edge2, oldtria; int j, i; MESH *tria, *t; tria = &trias[tnum]; j = 0; if((p == edges[tria->e[0]].p[0]) || (p == edges[tria->e[0]].p[1])) e[j++] = tria->e[0]; if((p == edges[tria->e[1]].p[0]) || (p == edges[tria->e[1]].p[1])) e[j++] = tria->e[1]; if((p == edges[tria->e[2]].p[0]) || (p == edges[tria->e[2]].p[1])) { // degenerated triangle ? if(j==2) return; e[j++] = tria->e[2]; } for(j=0; j<2; j++) { edge = e[j]; oldtria = tnum; i = 0; while(!(edges[edge].flags & EDGE_SHARP) && i<50) { // get next triangle with same edge edge2 = edge*2; if(oldtria != edgidx[edge2]) { oldtria = edgidx[edge2]; t = &trias[oldtria]; } else { oldtria = edgidx[edge2+1]; if(oldtria == 0xffff) break; t = &trias[oldtria]; } if(t == tria) { // avoid endless loops break; } // add normal if(dotp(n, &normals[oldtria]) < 0.f) VecSub(n, &normals[oldtria], n); else VecAdd(n, &normals[oldtria], n); // get new edge if((edge != t->e[0]) && ((p == edges[t->e[0]].p[0]) || (p == edges[t->e[0]].p[1]))) edge = t->e[0]; else { if((edge != t->e[1]) && ((p == edges[t->e[1]].p[0]) || (p == edges[t->e[1]].p[1]))) edge = t->e[1]; else { if((edge != t->e[2]) && ((p == edges[t->e[2]].p[0]) || (p == edges[t->e[2]].p[1]))) edge = t->e[2]; } } // continue the search with the new edge i++; } } // Normalize VecNormalize(n); }