def testWorldToRasterPerspective(self): v = GafferUI.ViewportGadget() v.setViewport(imath.V2i(500, 250)) v.setCamera( IECoreScene.Camera( parameters={ "resolution": imath.V2i(500, 250), "screenWindow": imath.Box2f(imath.V2f(-1, -.5), imath.V2f(1, .5)), "projection": "perspective", "projection:fov": 50.0, "clippingPlanes": imath.V2f(.1, 10), })) r = imath.Rand48() for i in range(0, 100): rasterPosition = imath.V2f(r.nexti() % 500, r.nexti() % 250) line = v.rasterToWorldSpace(rasterPosition) nearProjected = v.worldToRasterSpace(line.p0) farProjected = v.worldToRasterSpace(line.p1) self.failUnless( nearProjected.equalWithAbsError(farProjected, 0.0001)) self.failUnless( imath.V2f(rasterPosition.x, rasterPosition.y).equalWithAbsError( nearProjected, 0.0001))
def rectanglePoints(self, bound=imath.Box2f(imath.V2f(-1), imath.V2f(1)), divisions=imath.V2i(10)): r = imath.Rand48() pData = IECore.V3fVectorData() uData = IECore.FloatVectorData() vData = IECore.FloatVectorData() floatUserData = IECore.FloatVectorData() colorUserData = IECore.Color3fVectorData() for y in range(0, divisions.y): for x in range(0, divisions.x): u = float(x) / float(divisions.x - 1) v = float(y) / float(divisions.y - 1) pData.append( imath.V3f(bound.min().x + u * bound.size().x, bound.min().y + v * bound.size().y, 0)) uData.append(u) vData.append(v) floatUserData.append(r.nextf(0, 1)) colorUserData.append( imath.Color3f(r.nextf(), r.nextf(), r.nextf())) return IECore.CompoundData({ "P": pData, "u": uData, "v": vData, "floatUserData": floatUserData, "colorUserData": colorUserData, })
def testWorldToRasterOrthographic(self): v = GafferUI.ViewportGadget() v.setViewport(imath.V2i(500, 250)) v.setPlanarMovement(False) v.setCamera( IECoreScene.Camera( parameters={ "resolution": imath.V2i(500, 250), "screenWindow": imath.Box2f(imath.V2f(-2, -1), imath.V2f(2, 1)), "projection": "orthographic", "clippingPlanes": imath.V2f(.1, 10), })) r = imath.Rand48() for i in range(0, 100): rasterPosition = imath.V2f(r.nexti() % 500, r.nexti() % 250) line = v.rasterToWorldSpace(rasterPosition) nearProjected = v.worldToRasterSpace(line.p0) farProjected = v.worldToRasterSpace(line.p1) self.assertTrue( nearProjected.equalWithAbsError(farProjected, 0.0001)) self.assertTrue( imath.V2f(rasterPosition.x, rasterPosition.y).equalWithAbsError( nearProjected, 0.0001))
def testAspectAndRotation(self): fragmentSource = """ void main() { gl_FragColor = vec4( 1, 1, 1, 1 ); } """ random = imath.Rand48() p = IECore.V3fVectorData() r = IECore.FloatVectorData() w = IECore.FloatVectorData() a = IECore.FloatVectorData() for x in range(-2, 3): for y in range(-2, 3): p.append(imath.V3f(x, y, 0)) r.append(random.nextf(0, 360)) w.append(random.nextf(0.25, 0.5)) a.append(random.nextf(0.5, 2)) renderer = IECoreGL.Renderer() renderer.setOption("gl:mode", IECore.StringData("immediate")) renderer.setOption("gl:searchPath:shaderInclude", IECore.StringData("./glsl")) renderer.camera( "main", { "projection": IECore.StringData("orthographic"), "resolution": IECore.V2iData(imath.V2i(512)), "clippingPlanes": IECore.V2fData(imath.V2f(1, 1000)), "screenWindow": IECore.Box2fData(imath.Box2f(imath.V2f(-3), imath.V2f(3))) }) renderer.display(self.outputFileName, "exr", "rgba", {"quantize": IECore.FloatVectorData([0, 0, 0, 0])}) with IECoreScene.WorldBlock(renderer): renderer.concatTransform(imath.M44f().translate(imath.V3f( 0, 0, -6))) renderer.shader( "surface", "white", {"gl:fragmentSource": IECore.StringData(fragmentSource)}) renderer.points( p.size(), { "P": IECoreScene.PrimitiveVariable( IECoreScene.PrimitiveVariable.Interpolation.Vertex, p), "patchrotation": IECoreScene.PrimitiveVariable( IECoreScene.PrimitiveVariable.Interpolation.Vertex, r), "width": IECoreScene.PrimitiveVariable( IECoreScene.PrimitiveVariable.Interpolation.Vertex, w), "patchaspectratio": IECoreScene.PrimitiveVariable( IECoreScene.PrimitiveVariable.Interpolation.Vertex, a), "type": IECoreScene.PrimitiveVariable( IECoreScene.PrimitiveVariable.Interpolation.Uniform, IECore.StringData("patch")), }) expectedImage = IECore.Reader.create( os.path.dirname(__file__) + "/expectedOutput/rotatedPointPatches.exr").read() actualImage = IECore.Reader.create(self.outputFileName).read() self.assertEqual( IECoreImage.ImageDiffOp()(imageA=expectedImage, imageB=actualImage, maxError=0.08).value, False)
def testSimple(self): """ Test SpherePrimitiveEvaluator """ random.seed(1) rand = imath.Rand48(1) numTests = 50 for i in range(0, numTests): center = imath.V3f(0, 0, 0) radius = random.uniform(0.1, 5) sphere = IECoreScene.SpherePrimitive(radius) # Add some UV data in "bowtie" order - when we read it back it should then match the geometric UVs # if we're doing everything correctly. testData = IECore.V3fVectorData() testData.append(imath.V3f(0, 0, 0)) testData.append(imath.V3f(1, 0, 0)) testData.append(imath.V3f(0, 1, 0)) testData.append(imath.V3f(1, 1, 0)) testPrimVar = IECoreScene.PrimitiveVariable( IECoreScene.PrimitiveVariable.Interpolation.Varying, testData) sphere["testPrimVar"] = testPrimVar se = IECoreScene.PrimitiveEvaluator.create(sphere) result = se.createResult() testPoint = imath.V3f(random.uniform(-10, 10), random.uniform(-10, 10), random.uniform(-10, 10)) found = se.closestPoint(testPoint, result) self.assertTrue(found) # The closest point should lie on the sphere self.assertTrue( math.fabs((result.point() - center).length() - radius) < 0.001) uv = result.uv() self.assertTrue(uv[0] >= 0) self.assertTrue(uv[0] <= 1) self.assertTrue(uv[1] >= 0) self.assertTrue(uv[1] <= 1) # Make sure our "fake" UVs match the geometric UVs testPrimVarValue = result.vectorPrimVar(testPrimVar) self.assertAlmostEqual(testPrimVarValue[0], uv[0], 3) self.assertAlmostEqual(testPrimVarValue[1], uv[1], 3) closestPoint = result.point() found = se.pointAtUV(uv, result) self.assertTrue(found) self.assertAlmostEqual(result.uv()[0], uv[0], 3) self.assertAlmostEqual(result.uv()[1], uv[1], 3) # Pick a random point inside the sphere... origin = center + rand.nextSolidSphere(imath.V3f()) * radius * 0.9 self.assertTrue((origin - center).length() < radius) # And a random (unnormalized!) direction direction = rand.nextHollowSphere(imath.V3f()) * random.uniform( 0.5, 10) found = se.intersectionPoint(origin, direction, result) if found: # The intersection point should lie on the sphere self.assertTrue( math.fabs((result.point() - center).length() - radius) < 0.001) results = se.intersectionPoints(origin, direction) self.assertTrue(len(results) >= 0) self.assertTrue(len(results) <= 1) for result in results: # The intersection point should lie on the sphere self.assertTrue( math.fabs((result.point() - center).length() - radius) < 0.001) # Pick a random point outside the sphere... origin = center + rand.nextHollowSphere(imath.V3f()) * radius * 2 self.assertTrue((origin - center).length() > radius) found = se.intersectionPoint(origin, direction, result) if found: # The intersection point should lie on the sphere self.assertTrue( math.fabs((result.point() - center).length() - radius) < 0.001) results = se.intersectionPoints(origin, direction) # We can get a maximum of 2 intersection points from outside the sphere self.assertTrue(len(results) >= 0) self.assertTrue(len(results) <= 2) # If we get 1 result, the ray glances the sphere. Assert this. if len(results) == 1: self.assertTrue( math.fabs(direction.dot(result.normal()) < 0.1)) for result in results: # The intersection point should lie on the sphere self.assertTrue( math.fabs((result.point() - center).length() - radius) < 0.001)
def testRandomTriangles(self): """ Testing MeshPrimitiveEvaluator with random triangles""" random.seed(100) rand = imath.Rand48(100) numConfigurations = 100 numTests = 50 numTriangles = 250 for config in range(0, numConfigurations): P = IECore.V3fVectorData() verticesPerFace = IECore.IntVectorData() vertexIds = IECore.IntVectorData() vertexId = 0 for tri in range(0, numTriangles): verticesPerFace.append(3) P.append( imath.V3f(random.uniform(-10, 10), random.uniform(-10, 10), random.uniform(-10, 10))) P.append( imath.V3f(random.uniform(-10, 10), random.uniform(-10, 10), random.uniform(-10, 10))) P.append( imath.V3f(random.uniform(-10, 10), random.uniform(-10, 10), random.uniform(-10, 10))) vertexIds.append(vertexId + 0) vertexIds.append(vertexId + 1) vertexIds.append(vertexId + 2) vertexId = vertexId + 3 m = IECoreScene.MeshPrimitive(verticesPerFace, vertexIds) m["P"] = IECoreScene.PrimitiveVariable( IECoreScene.PrimitiveVariable.Interpolation.Vertex, P) mpe = IECoreScene.PrimitiveEvaluator.create(m) r = mpe.createResult() r2 = mpe.createResult() # Make sure that the closest hit point found with intersectionPoint() is actually the closest, by # comparing long-hand with the list of all intersections. for test in range(0, numTests): origin = imath.V3f(0, 0, 0) direction = rand.nextHollowSphere(imath.V3f()) hit = mpe.intersectionPoint(origin, direction, r) if hit: hits = mpe.intersectionPoints(origin, direction) self.assertTrue(hits) closestHitDist = 100000 closestHit = None for hit in hits: hitDist = (origin - hit.point()).length() if hitDist < closestHitDist: closestHitDist = hitDist closestHit = hit self.assertTrue( (r.point() - closestHit.point()).length() < 1.e-4) barycentricQuerySucceeded = mpe.barycentricPosition( r.triangleIndex(), r.barycentricCoordinates(), r2) self.assertTrue(barycentricQuerySucceeded) self.assertTrue(r.point().equalWithAbsError( r2.point(), 0.00001)) self.assertTrue(r.normal().equalWithAbsError( r2.normal(), 0.00001)) self.assertTrue( r.barycentricCoordinates().equalWithAbsError( r2.barycentricCoordinates(), 0.00001)) self.assertEqual(r.triangleIndex(), r2.triangleIndex()) else: hits = mpe.intersectionPoints(origin, direction) self.assertFalse(hits)
def testSphereMesh(self): """ Testing MeshPrimitiveEvaluator with sphere mesh""" # File represents a sphere of radius 1.0 at the origin reader = IECore.Reader.create( "test/IECore/data/cobFiles/pSphereShape1.cob") m = reader.read() self.assertTrue(m.isInstanceOf("MeshPrimitive")) numTriangles = len(m.verticesPerFace) mpe = IECoreScene.PrimitiveEvaluator.create(m) maxAbsError = 0.2 # Test volume against (theoretical) 4/3 * pi * r^3 self.assertTrue( math.fabs(4.0 / 3.0 * math.pi * (1.0 * 1.0 * 1.0) - mpe.volume()) < maxAbsError) # Center of gravity should be at origin self.assertTrue(mpe.centerOfGravity().length() < maxAbsError) # Test surface area against (theoretical) 4 * pi * r^20 self.assertTrue( math.fabs(4.0 * math.pi * (1.0 * 1.0) - mpe.surfaceArea()) < maxAbsError) r = mpe.createResult() random.seed(1) # Perform 100 closest point queries for i in range(0, 100): # Pick a random point outside the sphere testPt = None while not testPt or testPt.length() < 1.5: testPt = 3 * imath.V3f(random.uniform( -1, 1), random.uniform(-1, 1), random.uniform(-1, 1)) foundClosest = mpe.closestPoint(testPt, r) self.assertTrue(foundClosest) # Closest point should lie on unit sphere self.assertTrue(math.fabs(r.point().length() - 1.0) < maxAbsError) # Distance to closest point should be approximately distance to origin minus sphere radius - allow some error # because our source mesh does not represent a perfect sphere. absError = math.fabs((testPt - r.point()).length() - (testPt.length() - 1.0)) self.assertTrue(absError < maxAbsError) self.assertTrue(r.triangleIndex() >= 0) self.assertTrue(r.triangleIndex() < numTriangles) # Origin->Closest point should be roughly same direction as Origin->Test point, for a sphere self.assertTrue( r.point().normalized().dot(testPt.normalized()) > 0.5) geometricNormal = r.normal().normalized() shadingNormal = r.vectorPrimVar(m["N"]).normalized() # Geometric and shading normals should be facing the same way, roughly self.assertTrue(geometricNormal.dot(shadingNormal) > 0.5) # Shading normal should be pointing away from the origin at the closest point self.assertTrue(shadingNormal.dot(r.point().normalized()) > 0.5) # Vector from closest point to test point should be roughly the same direction as the normal self.assertTrue( shadingNormal.dot((testPt - r.point()).normalized()) > 0.5) rand = imath.Rand48() # Perform 100 ray intersection queries from inside the sphere, in random directions for i in range(0, 100): origin = rand.nextSolidSphere(imath.V3f()) * 0.5 direction = rand.nextHollowSphere(imath.V3f()) hit = mpe.intersectionPoint(origin, direction, r) self.assertTrue(hit) self.assertTrue(math.fabs(r.point().length() - 1) < 0.1) hits = mpe.intersectionPoints(origin, direction) self.assertEqual(len(hits), 1) for hit in hits: self.assertTrue(math.fabs(hit.point().length() - 1) < 0.1) # Perform 100 nearest ray intersection queries from outside the sphere, going outwards for i in range(0, 100): direction = rand.nextHollowSphere(imath.V3f()) origin = direction * 2 hit = mpe.intersectionPoint(origin, direction, r) self.assertFalse(hit) hits = mpe.intersectionPoints(origin, direction) self.assertFalse(hits) # Perform 100 nearest ray intersection queries from outside the sphere, going inwards for i in range(0, 100): direction = -rand.nextHollowSphere(imath.V3f()) origin = -direction * 2 hit = mpe.intersectionPoint(origin, direction, r) self.assertTrue(hit) self.assertTrue(math.fabs(r.point().length() - 1) < 0.1) # Make sure we get the nearest point, not the furthest self.assertTrue((origin - r.point()).length() < 1.1) hits = mpe.intersectionPoints(origin, direction) # There should be 0, 1, or 2 intersections self.assertTrue(len(hits) >= 0) self.assertTrue(len(hits) <= 2) for hit in hits: self.assertTrue(math.fabs(hit.point().length() - 1) < 0.1)