FVec2 ZViewpoint::zviewpointProjOnPlane( int scnX, int scnY, FVec3 p0, FVec3 planeNrm ) { DMat4 modl = zviewpointReferenceModel; DMat4 _s = scale3D( DVec3(zviewpointScale, zviewpointScale, zviewpointScale)); modl.cat( _s ); DMat4 _t = trans3D( DVec3(zviewpointPermitTransX ? zviewpointTrans[0] : 0.f, zviewpointPermitTransY ? zviewpointTrans[1] : 0.f, zviewpointPermitTransZ ? zviewpointTrans[2] : 0.f)); modl.cat( _t ); FMat4 _v = zviewpointRotQuat.mat(); DMat4 rot = DMat4( _v ); rot.transpose(); modl.cat( rot ); if( zviewpointReferenceViewport[2]==0 || zviewpointReferenceViewport[3]==0 ) { // PROTECT against exception return FVec2( (float)0.f, (float)0.f ); } int viewport[4]; glGetIntegerv( GL_VIEWPORT, viewport ); DMat4 projMat; double world[2][3] = {0,}; gluUnProject( scnX, scnY, 0.f, modl, projMat, viewport, &world[0][0], &world[0][1], &world[0][2] ); gluUnProject( scnX, scnY, 1.f, modl, projMat, viewport, &world[1][0], &world[1][1], &world[1][2] ); FVec3 wp0 = zviewpointLinePlaneIntersect( FVec3::Origin, FVec3::ZAxis, FVec3((float)world[0][0],(float)world[0][1],(float)world[0][2]), FVec3((float)world[1][0],(float)world[1][1],(float)world[1][2]) ); return FVec2( (float)wp0.x, (float)wp0.y ); }
int ZCovarMat2::findEigenvectors( float eigenvalues[2], FVec2 eigenvectors[2] ) { int num_eigenvalues = findEigenvalues(eigenvalues); assert(num_eigenvalues == 2); // Now that we have the quadratic coefficients, find the eigenvectors. const float VANISHING_EPSILON = 1.0e-5f; const float SAMENESS_LOW = 0.9999f; const float SAMENESS_HIGH = 1.0001f; bool punt = false; const float A_EPSILON = 0.0000001f; if( a < A_EPSILON ) { punt = true; } else { float ratio = (float)fabs(eigenvalues[1] / eigenvalues[0]); if ((ratio > SAMENESS_LOW) && (ratio < SAMENESS_HIGH)) punt = true; } if( punt ) { eigenvalues[0] = a; eigenvalues[1] = a; eigenvectors[0] = FVec2(1, 0); eigenvectors[1] = FVec2(0, 1); num_eigenvalues = 2; return num_eigenvalues; } int j; for( j = 0; j < num_eigenvalues; j++ ) { float lambda = eigenvalues[j]; FVec2 result1, result2; result1 = FVec2(-b, a - lambda); result2 = FVec2(-(c - lambda), b); FVec2 result; if (result1.mag2() > result2.mag2()) { result = result1; } else { result = result2; } result.normalize(); eigenvectors[j] = result; } return num_eigenvalues; }
FVec2 EmissionSource::sample(RandomGen &rand) const { switch (type) { case Type::point: return pos; case Type::rect: { auto f2 = rand.getFloat2Fast(); return pos + FVec2((f2.first * 2.0f - 1.0f) * param.x, (f2.second * 2.0f - 1.0f) * param.y); } case Type::sphere: { FVec2 spoint(rand.getFloatFast(-1.0f, 1.0f), rand.getFloatFast(-1.0f, 1.0f)); while(spoint.x * spoint.x + spoint.y * spoint.y > 1.0f) spoint = FVec2(rand.getFloatFast(-1.0f, 1.0f), rand.getFloatFast(-1.0f, 1.0f)); return pos + spoint * param.x; } } return {}; }
void GUI3DDirectionArrow::handleMsg( ZMsg *msg ) { if( zmsgIs(type,MouseClickOn) && zmsgIs(which,L) && zmsgIs(dir,D) ) { startDrag = FVec2( zmsgF(localX), zmsgF(localY) ); startDragMat = mat; requestExclusiveMouse( 1, 1 ); zMsgUsed(); sendMsg(); } else if( zmsgIs(type,MouseReleaseDrag) ) { requestExclusiveMouse( 1, 0 ); zMsgUsed(); } else if( zmsgIs(type,MouseDrag) ) { FVec2 mouseDelta( zmsgF(localX), zmsgF(localY) ); mouseDelta.sub( startDrag ); mouseDelta.mul( 0.03f ); mat = startDragMat; FMat4 eye = mat; eye.setTrans( FVec3::Origin ); eye.inverse(); FVec3 yEye = eye.mul( FVec3::YAxisMinus ); FVec3 xEye = eye.mul( FVec3::XAxis ); mat.cat( rotate3D( yEye, mouseDelta.x ) ); mat.cat( rotate3D( xEye, mouseDelta.y ) ); zMsgUsed(); sendMsg(); } else if( zmsgIs(type,SetDir) ) { FVec3 xaxis( zmsgF(x), zmsgF(y), zmsgF(z) ); xaxis.mul(-1.f); FVec3 yaxis( 0.f, 1.f, 0.f ); yaxis.cross( xaxis ); FVec3 zaxis = yaxis; zaxis.cross( xaxis ); xaxis.normalize(); yaxis.normalize(); zaxis.normalize(); mat.m[0][0] = xaxis.x; mat.m[0][1] = xaxis.y; mat.m[0][2] = xaxis.z; mat.m[0][3] = 0.f; mat.m[1][0] = yaxis.x; mat.m[1][1] = yaxis.y; mat.m[1][2] = yaxis.z; mat.m[1][3] = 0.f; mat.m[2][0] = zaxis.x; mat.m[2][1] = zaxis.y; mat.m[2][2] = zaxis.z; mat.m[2][3] = 0.f; mat.m[3][0] = 0.f; mat.m[3][1] = 0.f; mat.m[3][2] = 0.f; mat.m[3][3] = 1.f; } }
void ZCovarBody2::accumulate(float x, float y, float pointMass) { mass += pointMass; float cx = x * pointMass; float cy = y * pointMass; covariance.a += cx * cx; covariance.b += cx * cy; covariance.c += cy * cy; sum.add( FVec2(x, y) ); count++; }
float zTesselatePlanarPoly( FVec3 *verts, int count, FVec3 normal, int *tris, int &triCount ) { // BUILD an index of verts so that we know which one's // we've eaten up as we gobble convex polys int i, j, k; float area = 0.f; int *index = (int *)alloca( sizeof(int) * count ); int indexCount = count; for( i=0; i<count; i++ ) index[i] = i; int lastIndexCount = 999999999; while( indexCount>=3 && indexCount < lastIndexCount ) { lastIndexCount = indexCount; for( i=0, j=1, k=2; k<indexCount; ) { // ANALYZE the triangle formed by the three points // There are possibilities: // 1. It is wound facing the normal // 2. It is wound facing away from the normal // COMPUTE the facing: FVec3 a = verts[ index[i] ]; FVec3 b = verts[ index[j] ]; FVec3 c = verts[ index[k] ]; FVec3 ab = b; ab.sub( a ); FVec3 bc = c; bc.sub( b ); ab.cross( bc ); float wound = ab.dot( normal ); if( wound > 0.f ) { // CHECK for verts that are inside of this triangle int anyPointInside = 0; for( int l=0; l<indexCount; l++ ) { if( (l<i || l>k) ) { FVec2 tri[3]; tri[0] = FVec2( verts[index[i]].x, verts[index[i]].y ); tri[1] = FVec2( verts[index[j]].x, verts[index[j]].y ); tri[2] = FVec2( verts[index[k]].x, verts[index[k]].y ); FVec2 p = FVec2( verts[index[l]].x, verts[index[l]].y ); if( zTesselatePointInPoly( 3, tri, p ) ) { i = j; j = k; k++; anyPointInside = 1; break; } } } if( !anyPointInside ) { // This poly is wound correctly and doesn't have // any other points inside of it so it is a valid triangle tris[triCount * 3 + 0] = index[i]; tris[triCount * 3 + 1] = index[j]; tris[triCount * 3 + 2] = index[k]; triCount++; FVec3 a1 = verts[index[i]]; a1.sub( verts[index[k]] ); FVec3 a2 = verts[index[j]]; a2.sub( verts[index[k]] ); a1.cross( a2 ); area += a1.mag(); assert( triCount <= count ); // REMOVE the middle point from the consideration list by shifting indexCount--; memmove( &index[j], &index[j+1], sizeof(int)*(indexCount-j) ); } } else { // This tri is wound the wrong way so advance i = j; j = k; k++; } } } return area; }