Exemplo n.º 1
0
bool TerrainManager::attachVertices(label blockI){

	// prepare:
	const Foam::vector & n_up = coordinateSystem().e(UP);

	point & p1 = getPoint(blockVertex(blockI,Block::SWL));
	p1        += ( ( p_above_ - p1) & n_up )  * n_up;
	if(!landscape_().attachPoint(p1,p1 - maxDistProj_ * n_up)){
		Info << "TerrainManager: Cannot attach point SWL = " << p1 << " to STL.\n" << endl;
		return false;
	}

	point & p2 = getPoint(blockVertex(blockI,Block::NWL));
	p2        += ( ( p_above_ - p2 ) & n_up ) * n_up;
	if(!landscape_().attachPoint(p2,p2 - maxDistProj_ * n_up)){
		Info << "TerrainManager: Cannot attach point NWL = " << p2 << " to STL.\n" << endl;
		return false;
	}

	point & p3 = getPoint(blockVertex(blockI,Block::SEL));
	p3        += ( ( p_above_ - p3 ) & n_up ) * n_up;
	if(!landscape_().attachPoint(p3,p3 - maxDistProj_ * n_up)){
		Info << "TerrainManager: Cannot attach point SEL = " << p3 << " to STL.\n" << endl;
		return false;
	}

	point & p4 = getPoint(blockVertex(blockI,Block::NEL));
	p4        += ( ( p_above_ - p4 ) & n_up ) * n_up;
	if(!landscape_().attachPoint(p4,p4 - maxDistProj_ * n_up)){
		Info << "TerrainManager: Cannot attach point NEL = " << p4 << " to STL.\n" << endl;
		return false;
	}
	return true;
}
Exemplo n.º 2
0
TEST_F(CoordinateTransformableDataObject_test, PersistentCoordsSpec_ImageData)
{
    auto imageDataSet = vtkSmartPointer<vtkImageData>::New();
    imageDataSet->SetExtent(0, 1, 2, 4, 0, 0);
    imageDataSet->AllocateScalars(VTK_FLOAT, 1);
    
    ImageDataObject dataObject("image", *imageDataSet);

    const auto coordsSpec = ReferencedCoordinateSystemSpecification(
        CoordinateSystemType::geographic,
        "testGeoSystem",
        "testMetricSystem",
        "",
        { 100, 200 }, { 0.2, 0.3 });

    dataObject.specifyCoordinateSystem(coordsSpec);

    const auto fileName = QDir(TestEnvironment::testDirPath()).filePath("PersistentCoordsSpec.vti");

    ASSERT_TRUE(Exporter::exportData(dataObject, fileName));
    auto readDataObject = Loader::readFile<CoordinateTransformableDataObject>(fileName);
    ASSERT_TRUE(readDataObject);

    ASSERT_EQ(coordsSpec, readDataObject->coordinateSystem());
}
Exemplo n.º 3
0
void CObjectRotateCamera::SetUp(float x, float y, float z)
{
    m_axisZ = Point3(x, y, z).Normalize();
    coordinateSystem(m_axisZ, &m_axisX, &m_axisY);
    Point3 eye = Point3(vEyePt.x, vEyePt.y, vEyePt.z);
    Point3 dir = eye - m_center;
    Point3 angle = Dir2Angle(eye - m_center);
    vUpVec.x = x;
    vUpVec.y = y;
    vUpVec.z = z;
    m_anglex = angle.x;
    m_anglez = angle.y;
}
Exemplo n.º 4
0
bool TerrainManager::calcLandscapeSplines(label blockI){

	// prepare:
	const Foam::vector & n_up = coordinateSystem().e(UP);
	labelList groundSplines   = Block::getFaceEdgesI(Block::GROUND);

	// loop over ground spline labels:
	forAll(groundSplines,gsI){

		// get spline label:
		label i = groundSplines[gsI];
		if(i > 11) continue;

		// check if already set:
		if( edges().foundInBlock(blockI,i) ) continue;
		if( edges().foundInBlock(blockI,Block::switchedOrientationLabel(i)) ) continue;

		// prepare:
		const label splinePoints = splinePointNrs_[Block::getDirectionEdge(i)];
		pointField spline(splinePoints);

		// grab spline end points:
		const labelList verticesI = Block::getEdgeVerticesI(i);
		point & pointA = getPoint(blockVertex(blockI,verticesI[0]));
		point & pointB = getPoint(blockVertex(blockI,verticesI[1]));

		// calc delta in x,y:
		point delta = (pointB - pointA) / scalar(splinePoints + 1);

		// loop over spline points:
		for(label u = 0; u < splinePoints; u++){

			point splinePoint = pointA + (1 + u) * delta;

			// make sure point is above surface:
			splinePoint += dot(p_above_ - splinePoint,n_up) * n_up;

			// project to stl_:
			if(!landscape_().attachPoint(splinePoint,splinePoint - maxDistProj_ * n_up)){
				Info << "TerrainManager: Error: Cannot project point p = " << splinePoint << " onto stl_.\n" << endl;
				return false;
			}

			// add:
			spline[u] = splinePoint;
		}

		// set it:
		setEdge(blockI,i,spline);
	}
Exemplo n.º 5
0
vtkSmartPointer<vtkAlgorithm> ImageDataObject::createTransformPipeline(
    const CoordinateSystemSpecification & toSystem,
    vtkAlgorithmOutput * pipelineUpstream) const
{
    if (!GeographicTransformationFilter::IsTransformationSupported(
        coordinateSystem(), toSystem))
    {
        return{};
    }

    auto filter = vtkSmartPointer<GeographicTransformationFilter>::New();
    filter->SetInputConnection(pipelineUpstream);
    filter->SetTargetCoordinateSystem(toSystem);
    return filter;
}
Exemplo n.º 6
0
	DirectionalEmitter(const Properties &props) : Emitter(props) {
		m_type |= EDeltaDirection;

		m_normalIrradiance = props.getSpectrum("irradiance", Spectrum::getD65());
		if (props.hasProperty("direction")) {
			if (props.hasProperty("toWorld"))
				Log(EError, "Only one of the parameters 'direction' and 'toWorld'"
					"can be used at a time!");

			Vector d(normalize(props.getVector("direction"))), u, unused;
			coordinateSystem(d, u, unused);
			m_worldTransform = new AnimatedTransform(
				Transform::lookAt(Point(0.0f), Point(d), u));
		} else {
			if (props.getTransform("toWorld", Transform()).hasScale())
				Log(EError, "Scale factors in the emitter-to-world "
					"transformation are not allowed!");
		}
	}
Exemplo n.º 7
0
TEST_F(CoordinateTransformableDataObject_test, PersistentCoordsSpec_PolyData)
{
    auto dataObject = genPolyData();

    const auto coordsSpec = ReferencedCoordinateSystemSpecification(
        CoordinateSystemType::geographic,
        "testGeoSystem",
        "testMetricSystem",
        "",
        { 100, 200 }, { 0.2, 0.3 });

    dataObject->specifyCoordinateSystem(coordsSpec);

    const auto fileName = QDir(TestEnvironment::testDirPath()).filePath("PersistentCoordsSpec.vtp");

    ASSERT_TRUE(Exporter::exportData(*dataObject, fileName));
    auto readDataObject = Loader::readFile<CoordinateTransformableDataObject>(fileName);
    ASSERT_TRUE(readDataObject);

    ASSERT_EQ(coordsSpec, readDataObject->coordinateSystem());
}
Exemplo n.º 8
0
Arquivo: Mesh.cpp Projeto: dicta/ray
void Mesh::computePartialDerivitives(Face* face) const {
   double uvs[3][2];
   getUVs(uvs, face);

   Vector3D dp1 = *points[face->vertIdxs[0]] - *points[face->vertIdxs[2]];
   Vector3D dp2 = *points[face->vertIdxs[1]] - *points[face->vertIdxs[2]];

   // Compute deltas
   double du1 = uvs[0][0] - uvs[2][0];
   double du2 = uvs[1][0] - uvs[2][0];
   double dv1 = uvs[0][1] - uvs[2][1];
   double dv2 = uvs[1][1] - uvs[2][1];

   double determinant = du1 * dv2 - dv1 * du2;
   if(determinant == 0.0) {
      coordinateSystem(face->p1p3.cross(face->p1p2).normalize(), &face->dpdu, &face->dpdv);
   }
   else {
      face->dpdu = (dp1 * dv2 - dp2 * dv1) / determinant;
      face->dpdu.normalize();
      face->dpdv = (dp1 * -du2 + dp2 * du1) / determinant;
      face->dpdv.normalize();
   }
}
Exemplo n.º 9
0
TerrainManager::TerrainManager(
		const Time & runTime,
		const dictionary & dict,
		const searchableSurface * const stl_
		):
		BlockMeshManager(runTime),
		stl_(stl_),
		blockNrs_(dict.lookup("blocks")),
		cellNrs_(dict.lookup("cells")),
		domainBox_
		(
				CoordinateSystem
				(
						point(dict.lookup("p_corner")),
						List< Foam::vector >(dict.subDict("coordinates").lookup("baseVectors"))
				),
				scalarList(dict.lookup("dimensions")),
				dict.lookupOrDefault< scalar >("boxResolution",0.0001)
		),
		stlBox_(domainBox_),
		splineNormalDist_(0),
		mode_upwardSplines_(0),
		zeroLevel_(0),
		gradingFactors_(dict.lookup("gradingFactors")),
		cylinderModule_(this),
		modificationModule_(this),
		gradingModule_(this),
		blendingFunction_
		(
				new ScalarBlendingFunction()
		){

	// Read dictionary:
	p_above_     = point(dict.lookup("p_above"));
	maxDistProj_ = readScalar(dict.lookup("maxDistProj"));

	// option for stl_ inside the domain box:
	if(dict.found("stlInsideBox")){
		if(dict.subDict("stlInsideBox").found("zeroLevel")){
			zeroLevel_ = readScalar(dict.subDict("stlInsideBox").lookup("zeroLevel"));
		}
		stlBox_ = Box
		(
				CoordinateSystem
				(
						point(dict.subDict("stlInsideBox").lookup("p_corner_inside_stl")),
						coordinateSystem().axes()
				),
				scalarList(dict.subDict("stlInsideBox").lookup("dimensions_inside_stl")),
				dict.subDict("stlInsideBox").lookupOrDefault< scalar >("boxResolution",0.0001)
		);
		blendingFunction_ =
				ScalarBlendingFunction::New
				(
					dict.subDict("stlInsideBox").subDict("blendingFunction")
				);
		if(dict.subDict("stlInsideBox").subDict("blendingFunction").found("writePDF")){
			const dictionary & writeDict = dict.subDict("stlInsideBox").subDict("blendingFunction").subDict("writePDF");
			blendingFunction_().writePDFs
			(
					word(writeDict.lookup("baseName")),
					fileName(writeDict.lookup("resultsFolder")),
					point(writeDict.lookup("probePoint0")),
					point(writeDict.lookup("probePoint1")),
					0,1,
					readLabel(writeDict.lookup("steps")),
					readLabel(writeDict.lookup("plotPoints")),
					readLabel(writeDict.lookup("interpolOrder"))
			);
		} else {
			Info << "TerrainManager: keyword 'writePDF' not found in sub dictionary 'blendingFunction'." << endl;
		}
	}

    // module orography modifications:
    if(dict.found("terrainModification")){
    	Info << "   loading orography modification module" << endl;
    	if(!modificationModule_.load(dict.subDict("terrainModification"))){
    		Info << "\n   TerrainManager: Error while loading orography modification module." << endl;
    		throw;
    	}
    }

    // module block grading:
    if(dict.found("blockGrading")){
    	Info << "   loading block grading module" << endl;
    	if(!gradingModule_.load(dict.subDict("blockGrading"))){
    		Info << "\n   TerrainManager: Error while loading block grading module." << endl;
    		throw;
    	}
    }

    // module outer cylinder:
    if(dict.found("outerCylinder")){
    	Info << "   loading cylinder module" << endl;
    	if(!cylinderModule_.load(dict.subDict("outerCylinder"))){
    		Info << "\n   TerrainManager: Error while loading cylinder module." << endl;
    		throw;
    	}
    }

	// option for othogonalization of upward splines:
	if(dict.found("orthogonalizeUpwardSplines")){
		dictionary upsDict = dict.subDict("orthogonalizeUpwardSplines");
		splineNormalDist_ = readScalar(upsDict.lookup("splineNormalDist"));
		if(upsDict.found("ignoreBoundary")) mode_upwardSplines_ = 2;
		else mode_upwardSplines_ = 1;
	}

	// add patches:
	patchesRef().resize(6);
	patchesRef().set
	(
			Block::WEST,
			new BlockMeshPatch
			(
					*this,
					word(dict.lookup("patch_name_west")),
					word(dict.lookup("patch_type_west"))
			)
	);
	patchesRef().set
	(
			Block::EAST,
			new BlockMeshPatch
			(
					*this,
					word(dict.lookup("patch_name_east")),
					word(dict.lookup("patch_type_east"))
			)
	);
	patchesRef().set
	(
			Block::SOUTH,
			new BlockMeshPatch
			(
					*this,
					word(dict.lookup("patch_name_south")),
					word(dict.lookup("patch_type_south"))
			)
	);
	patchesRef().set
	(
			Block::NORTH,
			new BlockMeshPatch
			(
					*this,
					word(dict.lookup("patch_name_north")),
					word(dict.lookup("patch_type_north"))
			)
	);
	patchesRef().set
	(
			Block::GROUND,
			new BlockMeshPatch
			(
					*this,
					word(dict.lookup("patch_name_ground")),
					word(dict.lookup("patch_type_ground"))
			)
	);
	patchesRef().set
	(
			Block::SKY,
			new BlockMeshPatch
			(
					*this,
					word(dict.lookup("patch_name_sky")),
					word(dict.lookup("patch_type_sky"))
			)
	);

	// only one block in up direction:
	blockNrs_[UP] = 1;

	// set spline point numbers:
	splinePointNrs_.resize(3);
	splinePointNrs_[0] = cellNrs_[0] - 1;
	splinePointNrs_[1] = cellNrs_[1] - 1;
	splinePointNrs_[2] = cellNrs_[2] - 1;

	// init landscape_:
	if(stl_){
		landscape_.set
		(
				new STLLandscape
				(
						stl_,
						&(blendingFunction_()),
						&domainBox_,
						&stlBox_,
						zeroLevel_
				)
		);
	}

	// output boxes:
	domainBox_.writeSTL("domainBox.stl");
	stlBox_.writeSTL("stlBox.stl");
}
Exemplo n.º 10
0
/**
 * Compute the eigenvectors
 *
 * Based on "Geometric Tools" by David Eberly.
 */
static void eig3_evecs(Matrix3x3& A, const Float lambda[3], const Vector& U2, int i0, int i1, int i2) {
	Vector U0, U1;
	coordinateSystem(normalize(U2), U0, U1);

	// V[i2] = c0*U0 + c1*U1,  c0^2 + c1^2=1
	// e2*V[i2] = c0*A*U0 + c1*A*U1
	// e2*c0 = c0*U0.Dot(A*U0) + c1*U0.Dot(A*U1) = d00*c0 + d01*c1
	// e2*c1 = c0*U1.Dot(A*U0) + c1*U1.Dot(A*U1) = d01*c0 + d11*c1
	Vector tmp = A*U0, evecs[3];

	Float p00 = lambda[i2] - dot(U0, tmp),
		  p01 = dot(U1, tmp),
		  p11 = lambda[i2] - dot(U1, A*U1),
		  maxValue = std::abs(p00),
		  absValue = std::abs(p01),
		  invLength;

	if (absValue > maxValue)
		maxValue = absValue;

	int row = 0;
	absValue = std::abs(p11);
	if (absValue > maxValue) {
		maxValue = absValue;
		row = 1;
	}

	if (maxValue >= std::numeric_limits<Float>::epsilon()) {
		if (row == 0) {
			invLength = 1/std::sqrt(p00*p00 + p01*p01);
			p00 *= invLength;
			p01 *= invLength;
			evecs[i2] = p01*U0 + p00*U1;
		} else {
			invLength = 1/std::sqrt(p11*p11 + p01*p01);
			p11 *= invLength;
			p01 *= invLength;
			evecs[i2] = p11*U0 + p01*U1;
		}
	} else {
		if (row == 0)
			evecs[i2] = U1;
		else
			evecs[i2] = U0;
	}

	// V[i0] = c0*U2 + c1*Cross(U2,V[i2]) = c0*R + c1*S
	// e0*V[i0] = c0*A*R + c1*A*S
	// e0*c0 = c0*R.Dot(A*R) + c1*R.Dot(A*S) = d00*c0 + d01*c1
	// e0*c1 = c0*S.Dot(A*R) + c1*S.Dot(A*S) = d01*c0 + d11*c1
	Vector S = cross(U2, evecs[i2]);
	tmp = A*U2;
	p00 = lambda[i0] - dot(U2, tmp);
	p01 = dot(S, tmp);
	p11 = lambda[i0] - dot(S, A*S);
	maxValue = std::abs(p00);
	row = 0;
	absValue = std::abs(p01);
	if (absValue > maxValue)
		maxValue = absValue;
	absValue = std::abs(p11);
	if (absValue > maxValue) {
		maxValue = absValue;
		row = 1;
	}

	if (maxValue >= std::numeric_limits<Float>::epsilon()) {
		if (row == 0) {
			invLength = 1/std::sqrt(p00*p00 + p01*p01);
			p00 *= invLength;
			p01 *= invLength;
			evecs[i0] = p01*U2 + p00*S;
		} else {
			invLength = 1/std::sqrt(p11*p11 + p01*p01);
			p11 *= invLength;
			p01 *= invLength;
			evecs[i0] = p11*U2 + p01*S;
		}
	} else {
		if (row == 0)
			evecs[i0] = S;
		else
			evecs[i0] = U2;
	}

	evecs[i1] = cross(evecs[i2], evecs[i0]);
	A = Matrix3x3(
		evecs[0].x, evecs[1].x, evecs[2].x,
		evecs[0].y, evecs[1].y, evecs[2].y,
		evecs[0].z, evecs[1].z, evecs[2].z
	);
}
Exemplo n.º 11
0
void PreviewWorker::processCoherent(const WorkUnit *workUnit, WorkResult *workResult, 
	const bool &stop) {
#if defined(MTS_HAS_COHERENT_RT)
	const RectangularWorkUnit *rect = static_cast<const RectangularWorkUnit *>(workUnit);
	ImageBlock *block = static_cast<ImageBlock *>(workResult);

	block->setOffset(rect->getOffset());
	block->setSize(rect->getSize());

	/* Some constants */
	const int sx = rect->getOffset().x, sy = block->getOffset().y;
	const int ex = sx + rect->getSize().x, ey = sy + rect->getSize().y;
	const int width = rect->getSize().x;
	const SSEVector MM_ALIGN16 xOffset(0.0f, 1.0f, 0.0f, 1.0f);
	const SSEVector MM_ALIGN16 yOffset(0.0f, 0.0f, 1.0f, 1.0f);
	const int pixelOffset[] = {0, 1, width, width+1};
	const __m128 clamping = _mm_set1_ps(1/(m_minDist*m_minDist));
	uint8_t temp[MTS_KD_INTERSECTION_TEMP*4];

	const __m128 camTL[3] = {
		 _mm_set1_ps(m_cameraTL.x),
		 _mm_set1_ps(m_cameraTL.y),
		 _mm_set1_ps(m_cameraTL.z)
	}; 
	const __m128 camDx[3] = {
		 _mm_set1_ps(m_cameraDx.x),
		 _mm_set1_ps(m_cameraDx.y),
		 _mm_set1_ps(m_cameraDx.z)
	}; 
	const __m128 camDy[3] = {
		 _mm_set1_ps(m_cameraDy.x),
		 _mm_set1_ps(m_cameraDy.y),
		 _mm_set1_ps(m_cameraDy.z)
	}; 
	const __m128 lumPos[3] = {
		_mm_set1_ps(m_vpl.its.p.x),
		_mm_set1_ps(m_vpl.its.p.y),
		_mm_set1_ps(m_vpl.its.p.z)
	};
	const __m128 lumDir[3] = {
		_mm_set1_ps(m_vpl.its.shFrame.n.x),
		_mm_set1_ps(m_vpl.its.shFrame.n.y),
		_mm_set1_ps(m_vpl.its.shFrame.n.z)
	};

	/* Some local variables */
	int pos = 0;
	int numRays = 0;
	RayPacket4 MM_ALIGN16 primRay4, secRay4;
	Intersection4 MM_ALIGN16 its4, secIts4;
	RayInterval4 MM_ALIGN16 itv4, secItv4;
	SSEVector MM_ALIGN16 nSecD[3], cosThetaLight, invLengthSquared;
	Spectrum emitted[4], direct[4];
	Intersection its;
	Vector wo, wi;
	its.hasUVPartials = false;

	bool diffuseVPL = false, vplOnSurface = false;
	Spectrum vplWeight;

	if (m_vpl.type == ESurfaceVPL && (m_diffuseSources || m_vpl.its.shape->getBSDF()->getType() == BSDF::EDiffuseReflection)) {
		diffuseVPL = true;
		vplOnSurface = true;
		vplWeight = m_vpl.its.shape->getBSDF()->getDiffuseReflectance(m_vpl.its) * m_vpl.P / M_PI;
	} else if (m_vpl.type == ELuminaireVPL) {
		vplOnSurface = m_vpl.luminaire->getType() & Luminaire::EOnSurface;
		diffuseVPL = m_vpl.luminaire->getType() & Luminaire::EDiffuseDirection;
		EmissionRecord eRec(m_vpl.luminaire, 
			ShapeSamplingRecord(m_vpl.its.p, m_vpl.its.shFrame.n), m_vpl.its.shFrame.n);
		vplWeight = m_vpl.P * m_vpl.luminaire->evalDirection(eRec);
	}

	primRay4.o[0].ps = _mm_set1_ps(m_cameraO.x);
	primRay4.o[1].ps = _mm_set1_ps(m_cameraO.y);
	primRay4.o[2].ps = _mm_set1_ps(m_cameraO.z);
	secItv4.mint.ps = _mm_set1_ps(ShadowEpsilon);

	/* Work on 2x2 sub-blocks */
	for (int y=sy; y<ey; y += 2, pos += width) {
		for (int x=sx; x<ex; x += 2, pos += 2) {
			/* Generate camera rays without normalization */
			const __m128
				xPixel = _mm_add_ps(xOffset.ps, _mm_set1_ps((float) x)),
				yPixel = _mm_add_ps(yOffset.ps, _mm_set1_ps((float) y));

			primRay4.d[0].ps = _mm_add_ps(camTL[0], _mm_add_ps(
				_mm_mul_ps(xPixel, camDx[0]), _mm_mul_ps(yPixel, camDy[0])));
			primRay4.d[1].ps = _mm_add_ps(camTL[1], _mm_add_ps(
				_mm_mul_ps(xPixel, camDx[1]), _mm_mul_ps(yPixel, camDy[1])));
			primRay4.d[2].ps = _mm_add_ps(camTL[2], _mm_add_ps(
				_mm_mul_ps(xPixel, camDx[2]), _mm_mul_ps(yPixel, camDy[2])));

			primRay4.dRcp[0].ps = _mm_div_ps(SSEConstants::one.ps, primRay4.d[0].ps);
			primRay4.dRcp[1].ps = _mm_div_ps(SSEConstants::one.ps, primRay4.d[1].ps);
			primRay4.dRcp[2].ps = _mm_div_ps(SSEConstants::one.ps, primRay4.d[2].ps);

			/* Ray coherence test */
			const int primSignsX = _mm_movemask_ps(primRay4.d[0].ps);
			const int primSignsY = _mm_movemask_ps(primRay4.d[1].ps);
			const int primSignsZ = _mm_movemask_ps(primRay4.d[2].ps);

			const bool primCoherent =
				   (primSignsX == 0 || primSignsX == 0xF)
				&& (primSignsY == 0 || primSignsY == 0xF)
				&& (primSignsZ == 0 || primSignsZ == 0xF);

			/* Trace the primary rays */
			its4.t = SSEConstants::p_inf;
			if (EXPECT_TAKEN(primCoherent)) {
				primRay4.signs[0][0] = primSignsX ? 1 : 0;
				primRay4.signs[1][0] = primSignsY ? 1 : 0;
				primRay4.signs[2][0] = primSignsZ ? 1 : 0;
				m_kdtree->rayIntersectPacket(primRay4, itv4, its4, temp);
			} else {
				m_kdtree->rayIntersectPacketIncoherent(primRay4, itv4, its4, temp);
			}
			numRays += 4;

			/* Generate secondary rays */
			secRay4.o[0].ps = _mm_add_ps(primRay4.o[0].ps, _mm_mul_ps(its4.t.ps, primRay4.d[0].ps));
			secRay4.o[1].ps = _mm_add_ps(primRay4.o[1].ps, _mm_mul_ps(its4.t.ps, primRay4.d[1].ps));
			secRay4.o[2].ps = _mm_add_ps(primRay4.o[2].ps, _mm_mul_ps(its4.t.ps, primRay4.d[2].ps));
			secRay4.d[0].ps = _mm_sub_ps(lumPos[0], secRay4.o[0].ps);
			secRay4.d[1].ps = _mm_sub_ps(lumPos[1], secRay4.o[1].ps);
			secRay4.d[2].ps = _mm_sub_ps(lumPos[2], secRay4.o[2].ps);

			/* Normalization */
			const __m128 
				lengthSquared = _mm_add_ps(_mm_add_ps(
					_mm_mul_ps(secRay4.d[0].ps, secRay4.d[0].ps),
					_mm_mul_ps(secRay4.d[1].ps, secRay4.d[1].ps)),
					_mm_mul_ps(secRay4.d[2].ps, secRay4.d[2].ps)),
				invLength = _mm_rsqrt_ps(lengthSquared);
	
			invLengthSquared.ps = _mm_min_ps(_mm_rcp_ps(lengthSquared), clamping);

			nSecD[0].ps = _mm_mul_ps(secRay4.d[0].ps, invLength);
			nSecD[1].ps = _mm_mul_ps(secRay4.d[1].ps, invLength);
			nSecD[2].ps = _mm_mul_ps(secRay4.d[2].ps, invLength);

			secRay4.dRcp[0].ps = _mm_div_ps(SSEConstants::one.ps, secRay4.d[0].ps);
			secRay4.dRcp[1].ps = _mm_div_ps(SSEConstants::one.ps, secRay4.d[1].ps);
			secRay4.dRcp[2].ps = _mm_div_ps(SSEConstants::one.ps, secRay4.d[2].ps);

			cosThetaLight.ps = _mm_sub_ps(_mm_setzero_ps(),
				_mm_add_ps(_mm_add_ps(
					_mm_mul_ps(nSecD[0].ps, lumDir[0]),
					_mm_mul_ps(nSecD[1].ps, lumDir[1])),
					_mm_mul_ps(nSecD[2].ps, lumDir[2])));
			secItv4.maxt.ps = _mm_set1_ps(1-ShadowEpsilon);

			/* Shading (scalar) --- this is way too much work and should be 
			   rewritten to be smarter in special cases */
			for (int idx=0; idx<4; ++idx) {
				if (EXPECT_NOT_TAKEN(its4.t.f[idx] == std::numeric_limits<float>::infinity())) {
					/* Don't trace a secondary ray */
					secItv4.maxt.f[idx] = 0;
					emitted[idx] = m_scene->LeBackground(Ray(
						Point(primRay4.o[0].f[idx], primRay4.o[1].f[idx], primRay4.o[2].f[idx]),
						Vector(primRay4.d[0].f[idx], primRay4.d[1].f[idx], primRay4.d[2].f[idx]),
						0.0f
					)) * m_backgroundScale;
					memset(&direct[idx], 0, sizeof(Spectrum));
					continue;
				}
				const unsigned int primIndex = its4.primIndex.i[idx];
				const Shape *shape = (*m_shapes)[its4.shapeIndex.i[idx]];
				const BSDF *bsdf = shape->getBSDF();

				if (EXPECT_NOT_TAKEN(!bsdf)) {
					memset(&emitted[idx], 0, sizeof(Spectrum));
					memset(&direct[idx], 0, sizeof(Spectrum));
					continue;
				}

				if (EXPECT_TAKEN(primIndex != KNoTriangleFlag)) {
					const TriMesh *mesh = static_cast<const TriMesh *>(shape);
					const Triangle &t = mesh->getTriangles()[primIndex];
					const Normal *normals = mesh->getVertexNormals();
					const Point2 *texcoords = mesh->getVertexTexcoords();
					const Spectrum *colors = mesh->getVertexColors();
					const TangentSpace * tangents = mesh->getVertexTangents();
					const Float beta  = its4.u.f[idx],
								gamma = its4.v.f[idx],
								alpha = 1.0f - beta - gamma;
					const uint32_t idx0 = t.idx[0], idx1 = t.idx[1], idx2 = t.idx[2];

					if (EXPECT_TAKEN(normals)) {
						const Normal &n0 = normals[idx0],
							  		 &n1 = normals[idx1],
									 &n2 = normals[idx2];
						its.shFrame.n = normalize(n0 * alpha + n1 * beta + n2 * gamma);
					} else {
						const Point *positions = mesh->getVertexPositions();
						const Point &p0 = positions[idx0],
									&p1 = positions[idx1],
									&p2 = positions[idx2];
						Vector sideA = p1 - p0, sideB = p2 - p0;
						Vector n = cross(sideA, sideB);
						Float nLengthSqr = n.lengthSquared();
						if (nLengthSqr != 0)
							n /= std::sqrt(nLengthSqr);
						its.shFrame.n = Normal(n);
					}

					if (EXPECT_TAKEN(texcoords)) {
						const Point2 &t0 = texcoords[idx0],
							  		 &t1 = texcoords[idx1],
									 &t2 = texcoords[idx2];
						its.uv = t0 * alpha + t1 * beta + t2 * gamma;
					} else {
						its.uv = Point2(0.0f);
					}

					if (EXPECT_NOT_TAKEN(colors)) {
						const Spectrum &c0 = colors[idx0],
							  		   &c1 = colors[idx1],
									   &c2 = colors[idx2];
						its.color = c0 * alpha + c1 * beta + c2 * gamma;
					}

					if (EXPECT_NOT_TAKEN(tangents)) {
						const TangentSpace &t0 = tangents[idx0],
							  			   &t1 = tangents[idx1],
										   &t2 = tangents[idx2];
						its.dpdu = t0.dpdu * alpha + t1.dpdu * beta + t2.dpdu * gamma;
						its.dpdv = t0.dpdv * alpha + t1.dpdv * beta + t2.dpdv * gamma;
					}
				} else {
					Ray ray(
						Point(primRay4.o[0].f[idx], primRay4.o[1].f[idx], primRay4.o[2].f[idx]),
						Vector(primRay4.d[0].f[idx], primRay4.d[1].f[idx], primRay4.d[2].f[idx]),
						0.0f
					);
					its.t = its4.t.f[idx];
					shape->fillIntersectionRecord(ray, temp + idx * MTS_KD_INTERSECTION_TEMP + 8, its);
					bsdf = its.shape->getBSDF();
				}

				wo.x = nSecD[0].f[idx]; wo.y = nSecD[1].f[idx]; wo.z = nSecD[2].f[idx];

				if (EXPECT_TAKEN(!shape->isLuminaire())) {
					memset(&emitted[idx], 0, sizeof(Spectrum));
				} else {
					Vector d(-primRay4.d[0].f[idx], -primRay4.d[1].f[idx], -primRay4.d[2].f[idx]);
					emitted[idx] = shape->getLuminaire()->Le(ShapeSamplingRecord(its.p, its.shFrame.n), d);
				}

				if (EXPECT_TAKEN(bsdf->getType() == BSDF::EDiffuseReflection && diffuseVPL)) {
					/* Fast path */
					direct[idx] = (bsdf->getDiffuseReflectance(its) * vplWeight)
						* (std::max((Float) 0.0f, dot(wo, its.shFrame.n))
						* (vplOnSurface ? (std::max(cosThetaLight.f[idx], (Float) 0.0f) * INV_PI) : INV_PI)
						* invLengthSquared.f[idx]);
				} else {
					wi.x = -primRay4.d[0].f[idx];
					wi.y = -primRay4.d[1].f[idx];
					wi.z = -primRay4.d[2].f[idx];
					its.p.x = secRay4.o[0].f[idx];
					its.p.y = secRay4.o[1].f[idx];
					its.p.z = secRay4.o[2].f[idx];
					if (EXPECT_NOT_TAKEN(bsdf->getType() & BSDF::EAnisotropic)) {
						its.shFrame.s = normalize(its.dpdu - its.shFrame.n
							* dot(its.shFrame.n, its.dpdu));
						its.shFrame.t = cross(its.shFrame.n, its.shFrame.s);
					} else {
						coordinateSystem(its.shFrame.n, its.shFrame.s, its.shFrame.t);
					}
					const Float ctLight = cosThetaLight.f[idx];
					wi = normalize(wi);

					its.wi = its.toLocal(wi);
					wo = its.toLocal(wo);

					if (!diffuseVPL) {
						if (m_vpl.type == ESurfaceVPL) {
							BSDFQueryRecord bRec(m_vpl.its, m_vpl.its.toLocal(wi));
							bRec.quantity = EImportance;
							vplWeight = m_vpl.its.shape->getBSDF()->eval(bRec) * m_vpl.P;
						} else {
							EmissionRecord eRec(m_vpl.luminaire, 
								ShapeSamplingRecord(m_vpl.its.p, m_vpl.its.shFrame.n), wi);
							eRec.type = EmissionRecord::EPreview;
							vplWeight = m_vpl.luminaire->evalDirection(eRec) * m_vpl.P;
						}
					}

					if (EXPECT_TAKEN(ctLight >= 0)) {
						direct[idx] = (bsdf->eval(BSDFQueryRecord(its, wo)) * vplWeight
							* ((vplOnSurface ? std::max(ctLight, (Float) 0.0f) : 1.0f) * invLengthSquared.f[idx]));
					} else {
						memset(&direct[idx], 0, sizeof(Spectrum));
					}
				}
				++numRays;
			}

			/* Shoot the secondary rays */
			const int secSignsX = _mm_movemask_ps(secRay4.d[0].ps);
			const int secSignsY = _mm_movemask_ps(secRay4.d[1].ps);
			const int secSignsZ = _mm_movemask_ps(secRay4.d[2].ps);

			const bool secCoherent =
				   (secSignsX == 0 || secSignsX == 0xF)
				&& (secSignsY == 0 || secSignsY == 0xF)
				&& (secSignsZ == 0 || secSignsZ == 0xF);

			/* Shoot the secondary rays */
			secIts4.t = SSEConstants::p_inf;
			if (EXPECT_TAKEN(secCoherent)) {
				secRay4.signs[0][0] = secSignsX ? 1 : 0;
				secRay4.signs[1][0] = secSignsY ? 1 : 0;
				secRay4.signs[2][0] = secSignsZ ? 1 : 0;
				m_kdtree->rayIntersectPacket(secRay4, secItv4, secIts4, temp);
			} else {
				m_kdtree->rayIntersectPacketIncoherent(secRay4, secItv4, secIts4, temp);
			}

			for (int idx=0; idx<4; ++idx) {
				if (EXPECT_TAKEN(secIts4.t.f[idx] == std::numeric_limits<float>::infinity()))
					block->setPixel(pos+pixelOffset[idx], direct[idx]+emitted[idx]);
				else
					block->setPixel(pos+pixelOffset[idx], emitted[idx]);
			}
		}
	}
	block->setExtra(numRays);
#else
	Log(EError, "Coherent raytracing support was not compiled into this binary!");
#endif
}
Exemplo n.º 12
0
bool TriMesh::computeTangentSpaceBasis() {
	int zeroArea = 0, zeroNormals = 0;
	if (!m_texcoords) {
		bool anisotropic = hasBSDF() && m_bsdf->getType() & BSDF::EAnisotropic;
		if (anisotropic)
			Log(EError, "\"%s\": computeTangentSpace(): texture coordinates "
				"are required to generate tangent vectors. If you want to render with an anisotropic "
				"material, please make sure that all associated shapes have valid texture coordinates.",
				getName().c_str());
		return false;
	}

	if (m_tangents)
		Log(EError, "Tangent space vectors have already been generated!");

	if (!m_normals) {
		Log(EWarn, "Vertex normals are required to compute a tangent space basis!");
		return false;
	}

	m_tangents = new TangentSpace[m_vertexCount];
	memset(m_tangents, 0, sizeof(TangentSpace));

	/* No. of triangles sharing a vertex */
	uint32_t *sharers = new uint32_t[m_vertexCount];

	for (size_t i=0; i<m_vertexCount; i++) {
		m_tangents[i].dpdu = Vector(0.0f);
		m_tangents[i].dpdv = Vector(0.0f);
		if (m_normals[i].isZero()) {
			zeroNormals++;
			m_normals[i] = Normal(1.0f, 0.0f, 0.0f);
		}
		sharers[i] = 0;
	}

	for (size_t i=0; i<m_triangleCount; i++) {
		uint32_t idx0 = m_triangles[i].idx[0],
				 idx1 = m_triangles[i].idx[1],
				 idx2 = m_triangles[i].idx[2];
		const Point &v0 = m_positions[idx0];
		const Point &v1 = m_positions[idx1];
		const Point &v2 = m_positions[idx2];
		const Point2 &uv0 = m_texcoords[idx0];
		const Point2 &uv1 = m_texcoords[idx1];
		const Point2 &uv2 = m_texcoords[idx2];

		Vector dP1 = v1 - v0, dP2 = v2 - v0;
		Vector2 dUV1 = uv1 - uv0, dUV2 = uv2 - uv0;

		Float invDet = 1.0f, determinant = dUV1.x * dUV2.y - dUV1.y * dUV2.x;
		if (determinant != 0)
			invDet = 1.0f / determinant;

		Vector dpdu = ( dUV2.y * dP1 - dUV1.y * dP2) * invDet;
		Vector dpdv = (-dUV2.x * dP1 + dUV1.x * dP2) * invDet;

		if (dpdu.length() == 0.0f) {
			/* Recovery - required to recover from invalid geometry */
			Normal n = Normal(cross(v1 - v0, v2 - v0));
			Float length = n.length();
			if (length != 0) {
				n /= length;
				dpdu = cross(n, dpdv);
				if (dpdu.length() == 0.0f) {
					/* At least create some kind of tangent space basis 
					(fair enough for isotropic BxDFs) */
					coordinateSystem(n, dpdu, dpdv);
				}
			} else {
				zeroArea++;
			}
		}

		if (dpdv.length() == 0.0f) {
			Normal n = Normal(cross(v1 - v0, v2 - v0));
			Float length = n.length();
			if (length != 0) {
				n /= length;
				dpdv = cross(dpdu, n);
				if (dpdv.length() == 0.0f) {
					/* At least create some kind of tangent space basis 
						(fair enough for isotropic BxDFs) */
					coordinateSystem(n, dpdu, dpdv);
				}
			} else {
				zeroArea++;
			}
		}

		m_tangents[idx0].dpdu += dpdu;
		m_tangents[idx1].dpdu += dpdu;
		m_tangents[idx2].dpdu += dpdu;
		m_tangents[idx0].dpdv += dpdv;
		m_tangents[idx1].dpdv += dpdv;
		m_tangents[idx2].dpdv += dpdv;
		sharers[idx0]++; sharers[idx1]++; sharers[idx2]++;
	}

	/* Orthogonalization + Normalization pass */
	for (size_t i=0; i<m_vertexCount; i++) {
		Vector &dpdu = m_tangents[i].dpdu;
		Vector &dpdv = m_tangents[i].dpdv;

		if (dpdu.lengthSquared() == 0.0f || dpdv.lengthSquared() == 0.0f) {
			/* At least create some kind of tangent space basis 
				(fair enough for isotropic BxDFs) */
			coordinateSystem(m_normals[i], dpdu, dpdv);
		} else {
			if (sharers[i] > 0) {
				dpdu /= (Float) sharers[i];
				dpdv /= (Float) sharers[i];
			}
		}
	}
	delete[] sharers;

	if (zeroArea > 0 || zeroNormals > 0)
		Log(EWarn, "\"%s\": computeTangentSpace(): Mesh contains invalid "
			"geometry: %i zero area triangles and %i zero normals found!", 
			m_name.c_str(), zeroArea, zeroNormals);
	return true;
}
Exemplo n.º 13
0
 Frame(const Vector3f& n)
     : n(n)
 {
     coordinateSystem(n, s, t);
 }
Foam::coordinateSystem
Foam::pointToPointPlanarInterpolation::calcCoordinateSystem
(
    const pointField& points
) const
{
    if (points.size() < 3)
    {
        FatalErrorIn
        (
            "pointToPointPlanarInterpolation::calcCoordinateSystem"
            "(const pointField&)"
        )   << "Only " << points.size() << " provided." << nl
            << "Need at least three non-colinear points"
            << " to be able to interpolate."
            << exit(FatalError);
    }

    const point& p0 = points[0];

    // Find furthest away point
    vector e1;
    label index1 = -1;
    scalar maxDist = -GREAT;

    for (label i = 1; i < points.size(); i++)
    {
        const vector d = points[i] - p0;
        scalar magD = mag(d);

        if (magD > maxDist)
        {
            e1 = d/magD;
            index1 = i;
            maxDist = magD;
        }
    }
    // Find point that is furthest away from line p0-p1
    const point& p1 = points[index1];

    label index2 = -1;
    maxDist = -GREAT;
    for (label i = 1; i < points.size(); i++)
    {
        if (i != index1)
        {
            const point& p2 = points[i];
            vector e2(p2 - p0);
            e2 -= (e2&e1)*e1;
            scalar magE2 = mag(e2);

            if (magE2 > maxDist)
            {
                index2 = i;
                maxDist = magE2;
            }
        }
    }
    if (index2 == -1)
    {
        FatalErrorIn
        (
            "pointToPointPlanarInterpolation::calcCoordinateSystem"
            "(const pointField&)"
        )   << "Cannot find points that make valid normal." << nl
            << "Have so far points " << p0 << " and " << p1
            << "Need at least three points which are not in a line."
            << exit(FatalError);
    }

    vector n = e1^(points[index2]-p0);
    n /= mag(n);

    if (debug)
    {
        Info<< "pointToPointPlanarInterpolation::calcCoordinateSystem :"
            << " Used points " << p0 << ' ' << points[index1]
            << ' ' << points[index2]
            << " to define coordinate system with normal " << n << endl;
    }

    return coordinateSystem
    (
        "reference",
        p0,  // origin
        n,   // normal
        e1   // 0-axis
    );
}
Exemplo n.º 15
0
void AbstractRenderView::showDataObjects(
    const QList<DataObject *> & dataObjects,
    QList<DataObject *> & incompatibleObjects,
    unsigned int subViewIndex)
{
    assert(subViewIndex < numberOfSubViews());
    if (subViewIndex >= numberOfSubViews())
    {
        qDebug() << "Trying to AbstractRenderView::showDataObjects on sub-view" << subViewIndex << "while having only" << numberOfSubViews() << "views.";
        return;
    }

    QList<CoordinateTransformableDataObject *> transformableObjects;

    bool hasTransformables = false;
    for (auto dataObject : dataObjects)
    {
        auto transformable = dynamic_cast<CoordinateTransformableDataObject *>(dataObject);
        transformableObjects << transformable;
        if (transformable && transformable->coordinateSystem().isValid())
        {
            hasTransformables = true;
        }
    }

    if (visualizations().isEmpty())
    {
        setCurrentCoordinateSystem({});
    }

    QList<DataObject *> possibleCompatibleObjects;
    bool haveValidSystem = currentCoordinateSystem().isValid();

    // Once there is a valid coordinate system specification, don't allow to mix incompatible
    // representations
    if (hasTransformables || haveValidSystem)
    {
        for (int inIdx = 0; inIdx < dataObjects.size(); ++inIdx)
        {
            auto transformable = transformableObjects[inIdx];
            if (!transformable)
            {
                incompatibleObjects << dataObjects[inIdx];
                continue;
            }

            if (!haveValidSystem)
            {
                // set the coordinate system to the system of the first loaded object
                auto spec = transformable->coordinateSystem();
                if (spec.type == CoordinateSystemType::metricGlobal
                    || spec.type == CoordinateSystemType::metricLocal)
                {
                    spec.unitOfMeasurement = "km";
                }
                setCurrentCoordinateSystem(spec);
                haveValidSystem = true;
                possibleCompatibleObjects << dataObjects[inIdx];
                continue;
            }

            if (!transformable->canTransformTo(currentCoordinateSystem()))
            {
                incompatibleObjects << dataObjects[inIdx];
                continue;
            }

            possibleCompatibleObjects << dataObjects[inIdx];
        }
    }
    else
    {
        possibleCompatibleObjects = dataObjects;
    }

    initializeForFirstPaint();

    showDataObjectsImpl(possibleCompatibleObjects, incompatibleObjects, subViewIndex);
}
	void InvertibleHyperelasticMaterial::modifiedDeformGradient(const Scalar *gradient, Scalar *diags, Scalar *leftOrthoMat, Scalar *rightOrthoMat) const {
		Scalar triMat[6], eigenVals[3];
		Tensor2<Scalar> UT, VT;
		constexpr Scalar epsilon = Scalar(1e-8);
		constexpr int diagIndices[3] = { 0, 3, 5 };

		for (int i = 0; i < 3; i++)
			for (int j = i; j < 3; j++)
				triMat[diagIndices[i] + j - i] = gradient[j * 3 + 0] * gradient[i * 3 + 0] +
				gradient[j * 3 + 1] * gradient[i * 3 + 1] + gradient[j * 3 + 2] * gradient[i * 3 + 2];

		eigenSym3x3(triMat, eigenVals, &UT(0, 0));
		
		if (UT.Determinant() < 0.0) {
			for (int i = 0; i < 3; i++)
				UT(0, i) = -UT(0, i);
		}

		for (int i = 0; i < 3; i++)
			eigenVals[i] = eigenVals[i] > Scalar(0) ? sqrt(eigenVals[i]) : Scalar(0);

		Tensor2<Scalar> F(gradient);
		VT = UT * F;
		int condition = (eigenVals[0] < epsilon) + ((eigenVals[1] < epsilon) << 1) + ((eigenVals[2] < epsilon) << 2);
		switch (condition){
		case 0:
		{
			for (int i = 0; i < 3; i++) {
				Scalar inverse = Scalar(1.0) / eigenVals[i];
				for (int j = 0; j < 3; j++)
					VT(i, j) *= inverse;
			}
			if (VT.Determinant() < 0) {
				int smallestIndex = eigenVals[0] < eigenVals[1] ? (eigenVals[0] < eigenVals[2] ? 0 : 2) : (eigenVals[1] < eigenVals[2] ? 1 : 2);
				for (int i = 0; i < 3; i++)
					VT(smallestIndex, i) = -VT(smallestIndex, i);
				eigenVals[smallestIndex] = -eigenVals[smallestIndex];
			}
			break;
		}
		case 1:
		{
			Scalar inverse1 = Scalar(1.0) / eigenVals[1];
			Scalar inverse2 = Scalar(1.0) / eigenVals[2];
			for (int j = 0; j < 3; j++) {
				VT(1, j) *= inverse1;
				VT(2, j) *= inverse2;
			}
			Vector3 another = Vector3(VT(1, 0), VT(1, 1), VT(1, 2)) %
				Vector3(VT(2, 0), VT(2, 1), VT(2, 2));
			memcpy(&VT(0, 0), &another[0], sizeof(Scalar) * 3);
			break;
		}
		case 2:
		{
			Scalar inverse0 = Scalar(1.0) / eigenVals[0];
			Scalar inverse2 = Scalar(1.0) / eigenVals[2];
			for (int j = 0; j < 3; j++) {
				VT(0, j) *= inverse0;
				VT(2, j) *= inverse2;
			}
			Vector3 another = Vector3(VT(2, 0), VT(2, 1), VT(2, 2)) %
				Vector3(VT(0, 0), VT(0, 1), VT(0, 2));
			memcpy(&VT(1, 0), &another[0], sizeof(Scalar) * 3);
			break;
		}
		case 3:
		{
			Scalar inverse = Scalar(1.0) / eigenVals[2];
			for (int i = 0; i < 3; i++)
				VT(2, i) *= inverse;
			Vector3 v1, v2;
			coordinateSystem(Vector3(VT(2, 0), VT(2, 1), VT(2, 2)), v1, v2);
			memcpy(&VT(0, 0), &v1[0], sizeof(Scalar) * 3);
			memcpy(&VT(1, 0), &v2[0], sizeof(Scalar) * 3);
			break;
		}
		case 4:
		{
			Scalar inverse0 = Scalar(1.0) / eigenVals[0];
			Scalar inverse1 = Scalar(1.0) / eigenVals[1];
			for (int j = 0; j < 3; j++) {
				VT(0, j) *= inverse0;
				VT(1, j) *= inverse1;
			}
			Vector3 another = Vector3(VT(0, 0), VT(0, 1), VT(0, 2)) %
				Vector3(VT(1, 0), VT(1, 1), VT(1, 2));
			memcpy(&VT(2, 0), &another[0], sizeof(Scalar) * 3);
			break;
		}
		case 5:
		{
			Scalar inverse = Scalar(1.0) / eigenVals[1];
			for (int i = 0; i < 3; i++)
				VT(1, i) *= inverse;
			Vector3 v1, v2;
			coordinateSystem(Vector3(VT(1, 0), VT(1, 1), VT(1, 2)), v1, v2);
			memcpy(&VT(2, 0), &v1[0], sizeof(Scalar) * 3);
			memcpy(&VT(0, 0), &v2[0], sizeof(Scalar) * 3);
			break;
		}
		case 6:
		{
			Scalar inverse = Scalar(1.0) / eigenVals[0];
			for (int i = 0; i < 3; i++)
				VT(0, i) *= inverse;
			Vector3 v1, v2;
			coordinateSystem(Vector3(VT(0, 0), VT(0, 1), VT(0, 2)), v1, v2);
			memcpy(&VT(1, 0), &v1[0], sizeof(Scalar) * 3);
			memcpy(&VT(2, 0), &v2[0], sizeof(Scalar) * 3);
			break;
		}
		case 7:
		{
			memset(&VT(0, 0), 0, sizeof(Scalar) * 9);
			VT(0, 0) = VT(1, 1) = VT(2, 2) = 1.0;
			break;
		}
		default:
			Severe("Unexpected condition in InvertibleHyperelasticMaterial::modifiedDeformGradient");
			break;
		}

		for (int i = 0; i < 3; i++)
			diags[i] = std::max(eigenVals[i], trashold);
		for (int i = 0; i < 3; i++)
			for (int j = 0; j < 3; j++)
				leftOrthoMat[i * 3 + j] = UT(j, i);
		memcpy(rightOrthoMat, &VT(0, 0), sizeof(Scalar) * 9);
	}