TXGridTriangle::TXGridTriangle(TXTriangle *tp) { m_t = tp; m_n = m_t->m_norm; CVector3f tmp; tmp.Sub(m_t->m_v[0]->m_pos,m_t->m_v[1]->m_pos); tmp.Cross(tmp,m_n); m_en1.Normalize(tmp); tmp.Sub(m_t->m_v[1]->m_pos,m_t->m_v[2]->m_pos); tmp.Cross(tmp,m_n); m_en2.Normalize(tmp); tmp.Sub(m_t->m_v[2]->m_pos,m_t->m_v[0]->m_pos); tmp.Cross(tmp,m_n); m_en3.Normalize(tmp); }
// intersect a box bool TXDualEdge::Touch(const CVector3f& minp, const CVector3f& maxp) const { int m = 4; CVector3f step; step.Sub(m_dp[1], m_dp[0]); step.ScaleInPlace(1/4); CVector3f A = m_dp[0]; CVector3f B; B.Add(m_dp[0],step); for (int i = 0; i < m; i++) { CVector3f bmin(MIN(A.GetX(),B.GetX()),MIN(A.GetY(),B.GetY()),MIN(A.GetZ(),B.GetZ())); CVector3f bmax(MAX(A.GetX(),B.GetX()),MAX(A.GetY(),B.GetY()),MAX(A.GetZ(),B.GetZ())); if (bmin.GetX() <= maxp.GetX() && minp.GetX() <= bmax.GetX() && bmin.GetY() <= maxp.GetY() && minp.GetY() <= bmax.GetY() && bmin.GetZ() <= maxp.GetZ() && minp.GetZ() <= bmax.GetZ()) return true; A = B; B += step; } return false; }
// intersect a ray with the mesh bool TXGrid3D::IntersectRay(const CVector3f& start, const CVector3f& end) { // pick rays m_rays.push_back(TXRay(start, end)); CVector3f dir; dir.Sub(start,end); int idir[3] = { fabs(dir.GetX()) < DBL_EPSILON ? 0 : (dir.GetX() > 0 ? 1 : -1), fabs(dir.GetY()) < DBL_EPSILON ? 0 : (dir.GetY() > 0 ? 1 : -1), fabs(dir.GetZ()) < DBL_EPSILON ? 0 : (dir.GetZ() > 0 ? 1 : -1) }; double dist = 0; CVector3f pos; pos.Sub(end, m_min); int ix = (int)floor((end.GetX() - m_min.GetX())/m_xstep), iy = (int)floor((end.GetY() - m_min.GetY())/m_ystep), iz = (int)floor((end.GetZ() - m_min.GetZ())/m_zstep); double tx = 1.0, ty = 1.0, tz = 1.0; // first cell ix = MIN(MAX(ix, 0), m_size-1); iy = MIN(MAX(iy, 0), m_size-1); iz = MIN(MAX(iz, 0), m_size-1); // intersection test, from end to start while ((dist < 1) && (ix >= 0) && (ix < m_size) &&(iy >= 0) && (iy < m_size) && (iz >= 0) && (iz < m_size)) { int csz = m_grid[ix][iy][iz].size(); for (int i=0; i<csz; i++) { TXGridTriangle* gt = m_grid[ix][iy][iz][i]; double rpdot = dir.Dot(gt->m_n); if (rpdot != 0) { CVector3f tmp; tmp.Sub(gt->m_t->m_v[0]->m_pos,end); double t = tmp.Dot(gt->m_n) / rpdot; if (t > DBL_EPSILON && t < 1) { CVector3f pt; pt.ScaleAdd(t,dir,end); CVector3f pt0,pt1,pt2; pt0.Sub(pt,gt->m_t->m_v[0]->m_pos); pt1.Sub(pt,gt->m_t->m_v[1]->m_pos); pt2.Sub(pt,gt->m_t->m_v[2]->m_pos); if (pt0.Dot(gt->m_en1)> -DBL_EPSILON && pt1.Dot(gt->m_en2)>-DBL_EPSILON && pt2.Dot(gt->m_en3)>-DBL_EPSILON) { m_rays[m_rays.size()-1].m_p = t; return true; } } } } // next cell if (idir[0] != 0) tx = (m_min.GetX() + (ix+(idir[0]+1)/2)*m_xstep - end.GetX()) / dir.GetX(); if (idir[1] != 0) ty = (m_min.GetY() + (iy+(idir[1]+1)/2)*m_ystep - end.GetY()) / dir.GetY(); if (idir[2] != 0) tz = (m_min.GetZ() + (iz+(idir[2]+1)/2)*m_zstep - end.GetZ()) / dir.GetZ(); if ((tx <= ty) && (tx <= tz)) { dist = tx, ix += idir[0]; if (ty == tx) iy += idir[1]; if (tz == tx) iz += idir[2]; } else if (ty <= tz) { dist = ty, iy += idir[1]; if (tz == ty) iz += idir[2]; } else dist = tz, iz += idir[2]; } return false; }
XSIPLUGINCALLBACK CStatus nest_LatticeDeform_Evaluate( ICENodeContext& in_ctxt ) { // The current output port being evaluated... ULONG out_portID = in_ctxt.GetEvaluatedOutputPortID( ); switch( out_portID ) { case Array_ID_OUT_Result: { siICENodeDataType dataType; siICENodeStructureType struType; siICENodeContextType contType; in_ctxt.GetPortInfo(Lattice_ID_IN_Point,dataType,struType,contType); // get all of the data that is the same for any structure CDataArrayVector3f SubdivData( in_ctxt, Lattice_ID_IN_Subdivision ); CDataArrayVector3f StepData( in_ctxt, Lattice_ID_IN_Step ); CDataArray2DVector3f ReferenceData( in_ctxt, Lattice_ID_IN_Reference ); CDataArray2DVector3f CurrentData( in_ctxt, Lattice_ID_IN_Current ); CDataArray2DVector3f::Accessor ReferenceDataSub = ReferenceData[0]; CDataArray2DVector3f::Accessor CurrentDataSub = CurrentData[0]; // define the things we need to calculate long subdiv[3]; subdiv[0] = long(floor(SubdivData[0].GetX())); subdiv[1] = long(floor(SubdivData[0].GetY())); subdiv[2] = long(floor(SubdivData[0].GetZ())); long subdiv1[3]; subdiv1[0] = subdiv[0]+1; subdiv1[1] = subdiv[1]+1; subdiv1[2] = subdiv[2]+1; float step[3]; step[0] = 1.0f / StepData[0].GetX(); step[1] = 1.0f / StepData[0].GetY(); step[2] = 1.0f / StepData[0].GetZ(); float steplength = StepData[0].GetLength(); long indexX[8]; long indexY[8]; long indexZ[8]; long index[8]; long lastIndex[3]; lastIndex[0] = -1; lastIndex[1] = -1; lastIndex[2] = -1; CVector3f posCp; CVector3f pos; CVector3f diff[8]; CVector3f motion[8]; CVector3f motionScl[8]; CVector3f deform; float weight[8]; float xyz0[3]; float xyz1[3]; float weightSum; if(struType == siICENodeStructureSingle) { // two behaviours based on the datatype... // Get the output port array ... CDataArrayVector3f outData( in_ctxt ); // Get the input data buffers for each port CDataArrayVector3f PointData( in_ctxt, Lattice_ID_IN_Point ); // iterate each subset! CIndexSet IndexSet( in_ctxt ); for(CIndexSet::Iterator it = IndexSet.Begin(); it.HasNext(); it.Next()) { // first let's find the index inside the box! posCp.Set(PointData[it].GetX(),PointData[it].GetY(),PointData[it].GetZ()); // substract the lowest corner pos.Sub(posCp,ReferenceDataSub[0]); pos.Set(pos.GetX() * step[0], pos.GetY() * step[1], pos.GetZ() * step[2]); xyz0[0] = pos.GetX() - floor(pos.GetX()); xyz0[1] = pos.GetY() - floor(pos.GetY()); xyz0[2] = pos.GetZ() - floor(pos.GetZ()); xyz1[0] = 1.0 - xyz0[0]; xyz1[1] = 1.0 - xyz0[1]; xyz1[2] = 1.0 - xyz0[2]; // calculate the indices (decomposed) indexX[0] = clampl(long(floor(pos.GetX())),0,subdiv[0]); indexY[0] = clampl(long(floor(pos.GetY())),0,subdiv[1]); indexZ[0] = clampl(long(floor(pos.GetZ())),0,subdiv[2]); if(lastIndex[0] != indexX[0] || lastIndex[1] != indexY[0] || lastIndex[2] != indexZ[0]) { indexX[1] = clampl(indexX[0]+1 ,0,subdiv[0]); indexY[1] = clampl(indexY[0] ,0,subdiv[1]); indexZ[1] = clampl(indexZ[0] ,0,subdiv[2]); indexX[2] = clampl(indexX[0]+1 ,0,subdiv[0]); indexY[2] = clampl(indexY[0]+1 ,0,subdiv[1]); indexZ[2] = clampl(indexZ[0] ,0,subdiv[2]); indexX[3] = clampl(indexX[0]+1 ,0,subdiv[0]); indexY[3] = clampl(indexY[0] ,0,subdiv[1]); indexZ[3] = clampl(indexZ[0]+1 ,0,subdiv[2]); indexX[4] = clampl(indexX[0]+1 ,0,subdiv[0]); indexY[4] = clampl(indexY[0]+1 ,0,subdiv[1]); indexZ[4] = clampl(indexZ[0]+1 ,0,subdiv[2]); indexX[5] = clampl(indexX[0] ,0,subdiv[0]); indexY[5] = clampl(indexY[0]+1 ,0,subdiv[1]); indexZ[5] = clampl(indexZ[0] ,0,subdiv[2]); indexX[6] = clampl(indexX[0] ,0,subdiv[0]); indexY[6] = clampl(indexY[0] ,0,subdiv[1]); indexZ[6] = clampl(indexZ[0]+1 ,0,subdiv[2]); indexX[7] = clampl(indexX[0] ,0,subdiv[0]); indexY[7] = clampl(indexY[0]+1 ,0,subdiv[1]); indexZ[7] = clampl(indexZ[0]+1 ,0,subdiv[2]); for(int i=0;i<8;i++) { // compose the indices! index[i] = compose(indexX[i],indexY[i],indexZ[i],subdiv1[1],subdiv1[2]); // calculate the motions motion[i].Sub(CurrentDataSub[index[i]],ReferenceDataSub[index[i]]); } } else { // for performance, remember the last used index lastIndex[0] = indexX[0]; lastIndex[1] = indexY[0]; lastIndex[2] = indexZ[0]; } // compute the weights weight[0] = xyz1[0] * xyz1[1] * xyz1[2]; weight[1] = xyz0[0] * xyz1[1] * xyz1[2]; weight[2] = xyz0[0] * xyz0[1] * xyz1[2]; weight[3] = xyz0[0] * xyz1[1] * xyz0[2]; weight[4] = xyz0[0] * xyz0[1] * xyz0[2]; weight[5] = xyz1[0] * xyz0[1] * xyz1[2]; weight[6] = xyz1[0] * xyz1[1] * xyz0[2]; weight[7] = xyz1[0] * xyz0[1] * xyz0[2]; // sum up all weighted motions deform.SetNull(); for(int i=0;i<8;i++) { motionScl[i].Scale(weight[i],motion[i]); deform.AddInPlace(motionScl[i]); } // output the deformed position outData[it] = deform; } } else { // two behaviours based on the datatype... // Get the output port array ... CDataArray2DVector3f outData( in_ctxt ); // Get the input data buffers for each port CDataArray2DVector3f PointData( in_ctxt, Lattice_ID_IN_Point ); // iterate each subset! CIndexSet IndexSet( in_ctxt ); for(CIndexSet::Iterator it = IndexSet.Begin(); it.HasNext(); it.Next()) { CDataArray2DVector3f::Accessor PointDataSub = PointData[it]; long subCount = PointDataSub.GetCount(); Application().LogMessage(CString((LONG)subCount)); outData.Resize(it,subCount); for(long k=0;k<subCount;k++) { // first let's find the index inside the box! posCp.Set(PointDataSub[k].GetX(),PointDataSub[k].GetY(),PointDataSub[k].GetZ()); // substract the lowest corner pos.Sub(posCp,ReferenceDataSub[0]); pos.Set(pos.GetX() * step[0], pos.GetY() * step[1], pos.GetZ() * step[2]); xyz0[0] = pos.GetX() - floor(pos.GetX()); xyz0[1] = pos.GetY() - floor(pos.GetY()); xyz0[2] = pos.GetZ() - floor(pos.GetZ()); xyz1[0] = 1.0 - xyz0[0]; xyz1[1] = 1.0 - xyz0[1]; xyz1[2] = 1.0 - xyz0[2]; // calculate the indices (decomposed) indexX[0] = clampl(long(floor(pos.GetX())),0,subdiv[0]); indexY[0] = clampl(long(floor(pos.GetY())),0,subdiv[1]); indexZ[0] = clampl(long(floor(pos.GetZ())),0,subdiv[2]); if(lastIndex[0] != indexX[0] || lastIndex[1] != indexY[0] || lastIndex[2] != indexZ[0]) { indexX[1] = clampl(indexX[0]+1 ,0,subdiv[0]); indexY[1] = clampl(indexY[0] ,0,subdiv[1]); indexZ[1] = clampl(indexZ[0] ,0,subdiv[2]); indexX[2] = clampl(indexX[0]+1 ,0,subdiv[0]); indexY[2] = clampl(indexY[0]+1 ,0,subdiv[1]); indexZ[2] = clampl(indexZ[0] ,0,subdiv[2]); indexX[3] = clampl(indexX[0]+1 ,0,subdiv[0]); indexY[3] = clampl(indexY[0] ,0,subdiv[1]); indexZ[3] = clampl(indexZ[0]+1 ,0,subdiv[2]); indexX[4] = clampl(indexX[0]+1 ,0,subdiv[0]); indexY[4] = clampl(indexY[0]+1 ,0,subdiv[1]); indexZ[4] = clampl(indexZ[0]+1 ,0,subdiv[2]); indexX[5] = clampl(indexX[0] ,0,subdiv[0]); indexY[5] = clampl(indexY[0]+1 ,0,subdiv[1]); indexZ[5] = clampl(indexZ[0] ,0,subdiv[2]); indexX[6] = clampl(indexX[0] ,0,subdiv[0]); indexY[6] = clampl(indexY[0] ,0,subdiv[1]); indexZ[6] = clampl(indexZ[0]+1 ,0,subdiv[2]); indexX[7] = clampl(indexX[0] ,0,subdiv[0]); indexY[7] = clampl(indexY[0]+1 ,0,subdiv[1]); indexZ[7] = clampl(indexZ[0]+1 ,0,subdiv[2]); for(int i=0;i<8;i++) { // compose the indices! index[i] = compose(indexX[i],indexY[i],indexZ[i],subdiv1[1],subdiv1[2]); // calculate the motions motion[i].Sub(CurrentDataSub[index[i]],ReferenceDataSub[index[i]]); } } else { // for performance, remember the last used index lastIndex[0] = indexX[0]; lastIndex[1] = indexY[0]; lastIndex[2] = indexZ[0]; } // compute the weights weight[0] = xyz1[0] * xyz1[1] * xyz1[2]; weight[1] = xyz0[0] * xyz1[1] * xyz1[2]; weight[2] = xyz0[0] * xyz0[1] * xyz1[2]; weight[3] = xyz0[0] * xyz1[1] * xyz0[2]; weight[4] = xyz0[0] * xyz0[1] * xyz0[2]; weight[5] = xyz1[0] * xyz0[1] * xyz1[2]; weight[6] = xyz1[0] * xyz1[1] * xyz0[2]; weight[7] = xyz1[0] * xyz0[1] * xyz0[2]; // sum up all weighted motions deform.SetNull(); for(int i=0;i<8;i++) { motionScl[i].Scale(weight[i],motion[i]); deform.AddInPlace(motionScl[i]); } // output the deformed position outData[it][k] = deform; } } } } break; // Other output ports... }; return CStatus::OK; }