fall tree tests, testing utils, assertion macros
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit
This commit is contained in:
parent
9cdfac7898
commit
eff082ca76
@ -98,12 +98,15 @@ public class MovementAudioService {
|
||||
* @return The path to the audio file to play
|
||||
*/
|
||||
public String getAudioPath(int voxelType, InteractionType type){
|
||||
String rVal = null;
|
||||
SurfaceAudioType surfaceAudio = this.defaultSurfaceAudio;
|
||||
|
||||
//Check if ignored
|
||||
for(int ignoredVoxelType : this.ignoredVoxelTypes){
|
||||
if(ignoredVoxelType == voxelType){
|
||||
return null;
|
||||
if(this.ignoredVoxelTypes != null){
|
||||
for(int ignoredVoxelType : this.ignoredVoxelTypes){
|
||||
if(ignoredVoxelType == voxelType){
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -115,31 +118,33 @@ public class MovementAudioService {
|
||||
}
|
||||
|
||||
//gets the list to pull from
|
||||
List<String> availableFiles = surfaceAudio.getFootstepRegularBareAudioPaths();
|
||||
switch(type){
|
||||
case STEP_BARE_REG: {
|
||||
availableFiles = surfaceAudio.getFootstepRegularBareAudioPaths();
|
||||
} break;
|
||||
case STEP_BARE_HEAVY: {
|
||||
availableFiles = surfaceAudio.getFootstepHeavyBareAudioPaths();
|
||||
} break;
|
||||
case STEP_SHOE_REG: {
|
||||
availableFiles = surfaceAudio.getFootstepRegularShoeAudioPaths();
|
||||
} break;
|
||||
case STEP_SHOE_HEAVY: {
|
||||
availableFiles = surfaceAudio.getFootstepHeavyShoeAudioPaths();
|
||||
} break;
|
||||
case JUMP: {
|
||||
availableFiles = surfaceAudio.getJumpAudioPaths();
|
||||
} break;
|
||||
case LAND: {
|
||||
availableFiles = surfaceAudio.getLandAudioPaths();
|
||||
} break;
|
||||
if(surfaceAudio != null){
|
||||
List<String> availableFiles = surfaceAudio.getFootstepRegularBareAudioPaths();
|
||||
switch(type){
|
||||
case STEP_BARE_REG: {
|
||||
availableFiles = surfaceAudio.getFootstepRegularBareAudioPaths();
|
||||
} break;
|
||||
case STEP_BARE_HEAVY: {
|
||||
availableFiles = surfaceAudio.getFootstepHeavyBareAudioPaths();
|
||||
} break;
|
||||
case STEP_SHOE_REG: {
|
||||
availableFiles = surfaceAudio.getFootstepRegularShoeAudioPaths();
|
||||
} break;
|
||||
case STEP_SHOE_HEAVY: {
|
||||
availableFiles = surfaceAudio.getFootstepHeavyShoeAudioPaths();
|
||||
} break;
|
||||
case JUMP: {
|
||||
availableFiles = surfaceAudio.getJumpAudioPaths();
|
||||
} break;
|
||||
case LAND: {
|
||||
availableFiles = surfaceAudio.getLandAudioPaths();
|
||||
} break;
|
||||
}
|
||||
int roll = random.nextInt(availableFiles.size());
|
||||
rVal = availableFiles.get(roll);
|
||||
}
|
||||
|
||||
//return the audio
|
||||
int roll = random.nextInt(availableFiles.size());
|
||||
return availableFiles.get(roll);
|
||||
return rVal;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -466,10 +466,13 @@ public class CollisionEngine {
|
||||
DBody rigidBody = PhysicsEntityUtils.getDBody(physicsEntity);
|
||||
Matrix4d inverseTransform = new Matrix4d();
|
||||
Vector4d rawPos = inverseTransform.transform(new Vector4d(PhysicsUtils.getRigidBodyPosition(rigidBody),1));
|
||||
Vector3d newPosition = new Vector3d(rawPos.x,rawPos.y,rawPos.z);
|
||||
newPosition = this.suggestMovementPosition(collisionWorldData, newPosition);
|
||||
Vector3d calculatedPosition = new Vector3d(rawPos.x,rawPos.y,rawPos.z);
|
||||
Vector3d suggestedPosition = this.suggestMovementPosition(collisionWorldData, calculatedPosition);
|
||||
if(calculatedPosition.distance(suggestedPosition) > 0){
|
||||
collidable.addImpulse(new Impulse(new Vector3d(), new Vector3d(), new Vector3d(), 0, Collidable.TYPE_WORLD_BOUND));
|
||||
}
|
||||
Quaterniond newRotation = PhysicsUtils.getRigidBodyRotation(rigidBody);
|
||||
EntityUtils.getPosition(physicsEntity).set(newPosition);
|
||||
EntityUtils.getPosition(physicsEntity).set(suggestedPosition);
|
||||
EntityUtils.getRotation(physicsEntity).set(newRotation);
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,6 +47,9 @@ public class Collidable {
|
||||
public static final String TYPE_FOLIAGE_STATIC = "foliageStatic";
|
||||
public static final long TYPE_FOLIAGE_BIT = 0x80;
|
||||
|
||||
public static final String TYPE_WORLD_BOUND = "worldBound";
|
||||
public static final long TYPE_WORLD_BOUND_BIT = 0x100;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
||||
@ -44,29 +44,23 @@ public class ServerCollidableTree implements BehaviorTree {
|
||||
public void simulate(float deltaTime){
|
||||
Vector3d position = EntityUtils.getPosition(parent);
|
||||
Quaterniond rotation = EntityUtils.getRotation(parent);
|
||||
Vector3d offsetVector = new Vector3d();
|
||||
Vector3d newPosition = new Vector3d(position);
|
||||
//have we hit a terrain impulse?
|
||||
boolean hitTerrain = false;
|
||||
//handle impulses
|
||||
for(Impulse impulse : collidable.getImpulses()){
|
||||
// collidable.getImpulses().remove(impulse);
|
||||
if(impulse.type.matches(Collidable.TYPE_TERRAIN)){
|
||||
hitTerrain = true;
|
||||
// System.out.println("Impulse force: " + impulseForce);
|
||||
// System.out.println("Position: " + position);
|
||||
}
|
||||
if(impulse.type.matches(Collidable.TYPE_ITEM)){
|
||||
if(ServerGravityTree.getServerGravityTree(parent)!=null){
|
||||
ServerGravityTree.getServerGravityTree(parent).start();
|
||||
}
|
||||
}
|
||||
if(impulse.type.matches(Collidable.TYPE_CREATURE)){
|
||||
// System.out.println(System.currentTimeMillis() + " creature hit!");
|
||||
if(ServerGravityTree.getServerGravityTree(parent)!=null){
|
||||
ServerGravityTree.getServerGravityTree(parent).start();
|
||||
}
|
||||
}
|
||||
if(impulse.type.matches(Collidable.TYPE_WORLD_BOUND)){
|
||||
this.resetGravityFall();
|
||||
}
|
||||
}
|
||||
Realm realm = Globals.realmManager.getEntityRealm(parent);
|
||||
//bound to world bounds
|
||||
@ -101,5 +95,17 @@ public class ServerCollidableTree implements BehaviorTree {
|
||||
return (ServerCollidableTree)e.getData(EntityDataStrings.SERVER_COLLIDABLE_TREE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a terrain collision to the collidable list
|
||||
*/
|
||||
protected void resetGravityFall(){
|
||||
if(ServerGravityTree.getServerGravityTree(parent)!=null){
|
||||
ServerGravityTree.getServerGravityTree(parent).stop();
|
||||
}
|
||||
if(ServerFallTree.getFallTree(parent)!=null){
|
||||
ServerFallTree.getFallTree(parent).land();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -63,6 +63,10 @@ public class ServerGravityTree implements BehaviorTree {
|
||||
if(state == GravityTreeState.NOT_ACTIVE){
|
||||
frameCurrent = 0;
|
||||
}
|
||||
ServerFallTree fallTree;
|
||||
if((fallTree = ServerFallTree.getFallTree(parent))!=null){
|
||||
fallTree.start();
|
||||
}
|
||||
}
|
||||
|
||||
public void interrupt(){
|
||||
|
||||
@ -0,0 +1,61 @@
|
||||
package electrosphere.entity.state.movement.fall;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import org.joml.Vector3d;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.state.movement.jump.ClientJumpTree;
|
||||
import electrosphere.entity.types.creature.CreatureTemplate;
|
||||
import electrosphere.entity.types.creature.CreatureUtils;
|
||||
import electrosphere.test.annotations.IntegrationTest;
|
||||
import electrosphere.test.template.EntityTestTemplate;
|
||||
import electrosphere.test.testutils.TestEngineUtils;
|
||||
import static electrosphere.test.testutils.Assertions.*;
|
||||
|
||||
/**
|
||||
* Tests the fall tree
|
||||
*/
|
||||
public class ClientFallTreeTests extends EntityTestTemplate {
|
||||
|
||||
@IntegrationTest
|
||||
public void isFalling_AtRest_false(){
|
||||
Entity serverEntity = CreatureUtils.serverSpawnBasicCreature(Globals.realmManager.first(), new Vector3d(), "human", CreatureTemplate.createDefault("human"));
|
||||
Entity clientEntity = TestEngineUtils.getClientEquivalent(serverEntity);
|
||||
|
||||
ClientFallTree clientFallTree = ClientFallTree.getFallTree(clientEntity);
|
||||
assertEquals(false, clientFallTree.isFalling());
|
||||
}
|
||||
|
||||
@IntegrationTest
|
||||
public void isFalling_AfterJump_true(){
|
||||
Entity serverEntity = CreatureUtils.serverSpawnBasicCreature(Globals.realmManager.first(), new Vector3d(), "human", CreatureTemplate.createDefault("human"));
|
||||
Entity clientEntity = TestEngineUtils.getClientEquivalent(serverEntity);
|
||||
|
||||
ClientFallTree clientFallTree = ClientFallTree.getFallTree(clientEntity);
|
||||
ClientJumpTree clientJumpTree = ClientJumpTree.getClientJumpTree(clientEntity);
|
||||
clientJumpTree.start();
|
||||
|
||||
//make sure we're in in the air
|
||||
assertEventually(() -> clientFallTree.isFalling(), 100);
|
||||
}
|
||||
|
||||
@IntegrationTest
|
||||
public void isFalling_AfterLand_false(){
|
||||
Entity serverEntity = CreatureUtils.serverSpawnBasicCreature(Globals.realmManager.first(), new Vector3d(), "human", CreatureTemplate.createDefault("human"));
|
||||
Entity clientEntity = TestEngineUtils.getClientEquivalent(serverEntity);
|
||||
|
||||
ClientFallTree clientFallTree = ClientFallTree.getFallTree(clientEntity);
|
||||
ClientJumpTree clientJumpTree = ClientJumpTree.getClientJumpTree(clientEntity);
|
||||
clientJumpTree.start();
|
||||
|
||||
//make sure we're in in the air
|
||||
TestEngineUtils.simulateFrames(3);
|
||||
|
||||
assertEventually(() -> {
|
||||
return !clientFallTree.isFalling();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
package electrosphere.entity.state.movement.fall;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
|
||||
import org.joml.Vector3d;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.state.movement.jump.ServerJumpTree;
|
||||
import electrosphere.entity.types.creature.CreatureTemplate;
|
||||
import electrosphere.entity.types.creature.CreatureUtils;
|
||||
import electrosphere.test.annotations.IntegrationTest;
|
||||
import electrosphere.test.template.EntityTestTemplate;
|
||||
import static electrosphere.test.testutils.Assertions.*;
|
||||
import electrosphere.test.testutils.TestEngineUtils;
|
||||
|
||||
/**
|
||||
* Tests the server fall tree
|
||||
*/
|
||||
public class ServerFallTreeTests extends EntityTestTemplate {
|
||||
|
||||
@IntegrationTest
|
||||
public void isFalling_AtRest_false(){
|
||||
Entity creature = CreatureUtils.serverSpawnBasicCreature(Globals.realmManager.first(), new Vector3d(0,0,0), "human", CreatureTemplate.createDefault("human"));
|
||||
|
||||
ServerFallTree serverFallTree = ServerFallTree.getFallTree(creature);
|
||||
assertEquals(false, serverFallTree.isFalling());
|
||||
}
|
||||
|
||||
@IntegrationTest
|
||||
public void isFalling_AfterJump_true(){
|
||||
Entity creature = CreatureUtils.serverSpawnBasicCreature(Globals.realmManager.first(), new Vector3d(0,0,0), "human", CreatureTemplate.createDefault("human"));
|
||||
|
||||
ServerFallTree serverFallTree = ServerFallTree.getFallTree(creature);
|
||||
ServerJumpTree serverJumpTree = ServerJumpTree.getServerJumpTree(creature);
|
||||
serverJumpTree.start();
|
||||
|
||||
//make sure we're in in the air
|
||||
TestEngineUtils.waitForCondition(() -> !serverJumpTree.isJumping(), 100);
|
||||
|
||||
assertEquals(true, serverFallTree.isFalling());
|
||||
}
|
||||
|
||||
@IntegrationTest
|
||||
public void isFalling_AfterLand_false(){
|
||||
Entity creature = CreatureUtils.serverSpawnBasicCreature(Globals.realmManager.first(), new Vector3d(0,0,0), "human", CreatureTemplate.createDefault("human"));
|
||||
|
||||
ServerFallTree serverFallTree = ServerFallTree.getFallTree(creature);
|
||||
ServerJumpTree serverJumpTree = ServerJumpTree.getServerJumpTree(creature);
|
||||
serverJumpTree.start();
|
||||
|
||||
//make sure we're in in the air
|
||||
TestEngineUtils.simulateFrames(3);
|
||||
|
||||
assertEventually(() -> {
|
||||
return !serverFallTree.isFalling();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@ -6,6 +6,7 @@ import org.junit.jupiter.api.Tag;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
import electrosphere.test.template.extensions.RenderingExtension;
|
||||
import static electrosphere.test.testutils.Assertions.*;
|
||||
import electrosphere.test.testutils.TestRenderingUtils;
|
||||
|
||||
/**
|
||||
@ -26,7 +27,7 @@ public class RenderingTestTemplate {
|
||||
String canonicalName = this.getClass().getCanonicalName();
|
||||
|
||||
//check the render
|
||||
TestRenderingUtils.assertEqualsRender(existingRenderPath, () -> {
|
||||
assertEqualsRender(existingRenderPath, () -> {
|
||||
|
||||
//on failure, save the failed render
|
||||
String failureSavePath = "./.testcache/" + canonicalName + "-" + renderName + ".png";
|
||||
|
||||
110
src/test/java/electrosphere/test/testutils/Assertions.java
Normal file
110
src/test/java/electrosphere/test/testutils/Assertions.java
Normal file
@ -0,0 +1,110 @@
|
||||
package electrosphere.test.testutils;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
|
||||
/**
|
||||
* Custom assertion macros
|
||||
*/
|
||||
public class Assertions {
|
||||
|
||||
/**
|
||||
* The threshold at which we say the colors are 'close enough'
|
||||
*/
|
||||
static final int COLOR_COMPARE_THRESHOLD = 3;
|
||||
|
||||
/**
|
||||
* Asserts that the most recent render matches the image stored at the provided filepath
|
||||
* @param existingRenderPath The filepath of the existing render
|
||||
*/
|
||||
public static void assertEqualsRender(String existingRenderPath, Runnable onFailure){
|
||||
BufferedImage testData = null;
|
||||
try {
|
||||
testData = ImageIO.read(new File(existingRenderPath));
|
||||
} catch (IOException e){
|
||||
fail("Failed to read existing image path " + existingRenderPath);
|
||||
}
|
||||
BufferedImage screenshot = Globals.renderingEngine.defaultFramebuffer.getPixels(Globals.renderingEngine.getOpenGLState());
|
||||
//check basic data
|
||||
//
|
||||
//width
|
||||
if(testData.getWidth() != screenshot.getWidth()){
|
||||
onFailure.run();
|
||||
}
|
||||
assertEquals(testData.getWidth(), screenshot.getWidth());
|
||||
|
||||
//
|
||||
//height
|
||||
if(testData.getHeight() != screenshot.getHeight()){
|
||||
onFailure.run();
|
||||
}
|
||||
assertEquals(testData.getHeight(), screenshot.getHeight());
|
||||
|
||||
//
|
||||
//pixel-by-pixel check
|
||||
//
|
||||
for(int x = 0; x < testData.getWidth(); x++){
|
||||
for(int y = 0; y < testData.getHeight(); y++){
|
||||
|
||||
//get from-disk rgba
|
||||
int sourceRed = testData.getRGB(x, y) & 0xff;
|
||||
int sourceGreen = (testData.getRGB(x, y) & 0xff00) >> 8;
|
||||
int sourceBlue = (testData.getRGB(x, y) & 0xff0000) >> 16;
|
||||
int sourceAlpha = (testData.getRGB(x, y) & 0xff000000) >>> 24;
|
||||
|
||||
//get from-render rgba
|
||||
int renderRed = screenshot.getRGB(x, y) & 0xff;
|
||||
int renderGreen = (screenshot.getRGB(x, y) & 0xff00) >> 8;
|
||||
int renderBlue = (screenshot.getRGB(x, y) & 0xff0000) >> 16;
|
||||
int renderAlpha = (screenshot.getRGB(x, y) & 0xff000000) >>> 24;
|
||||
|
||||
if(
|
||||
Math.abs(sourceRed - renderRed) > COLOR_COMPARE_THRESHOLD ||
|
||||
Math.abs(sourceGreen - renderGreen) > COLOR_COMPARE_THRESHOLD ||
|
||||
Math.abs(sourceBlue - renderBlue) > COLOR_COMPARE_THRESHOLD ||
|
||||
Math.abs(sourceAlpha - renderAlpha) > COLOR_COMPARE_THRESHOLD
|
||||
){
|
||||
|
||||
onFailure.run();
|
||||
String failMessage = "Colors aren't approximately the same!\n" +
|
||||
"Color from disk: " + sourceRed + "," + sourceGreen + "," + sourceBlue + "," + sourceAlpha + "\n" +
|
||||
"Color from render: " + renderRed + "," + renderGreen + "," + renderBlue + "," + renderAlpha + "\n"
|
||||
;
|
||||
fail(failMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that some test is true within a given number of frame simulations
|
||||
* @param test The test
|
||||
* @param maxFrames The number of frames
|
||||
*/
|
||||
public static void assertEventually(Supplier<Boolean> test, int maxFrames){
|
||||
int frameCount = 0;
|
||||
boolean testResult = false;
|
||||
while(!(testResult = test.get()) && frameCount < maxFrames){
|
||||
TestEngineUtils.simulateFrames(1);
|
||||
frameCount++;
|
||||
}
|
||||
org.junit.jupiter.api.Assertions.assertTrue(testResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that some runnable
|
||||
* @param test
|
||||
*/
|
||||
public static void assertEventually(Supplier<Boolean> test){
|
||||
assertEventually(test, 100);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,8 +1,13 @@
|
||||
package electrosphere.test.testutils;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.engine.Main;
|
||||
import electrosphere.engine.profiler.Profiler;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.net.NetUtils;
|
||||
|
||||
/**
|
||||
@ -57,4 +62,53 @@ public class TestEngineUtils {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The maximum number of frames to wait before an entity propagates to the client
|
||||
*/
|
||||
static final int MAX_FRAMES_TO_WAIT_FOR_CLIENT_PROPAGATION = 10;
|
||||
|
||||
/**
|
||||
* Gets the client equivalent of an entity
|
||||
* @param serverEntity The server entity
|
||||
* @return The client entity
|
||||
*/
|
||||
public static Entity getClientEquivalent(Entity serverEntity){
|
||||
int frames = 0;
|
||||
while(frames < MAX_FRAMES_TO_WAIT_FOR_CLIENT_PROPAGATION && !Globals.clientSceneWrapper.containsServerId(serverEntity.getId())){
|
||||
TestEngineUtils.simulateFrames(1);
|
||||
}
|
||||
if(Globals.clientSceneWrapper.containsServerId(serverEntity.getId())){
|
||||
Entity rVal = Globals.clientSceneWrapper.getEntityFromServerId(serverEntity.getId());
|
||||
if(rVal == null){
|
||||
fail("Failed to find client entity at server id lookup for id: " + serverEntity.getId());
|
||||
}
|
||||
return rVal;
|
||||
}
|
||||
fail("Failed to find client entity at server id lookup for id: " + serverEntity.getId());
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for a given test to be true
|
||||
* @param test The test to wait for
|
||||
*/
|
||||
public static void waitForCondition(Supplier<Boolean> test, int maxFrames){
|
||||
int frameCount = 0;
|
||||
boolean testResult = false;
|
||||
while(!(testResult = test.get()) && frameCount < maxFrames){
|
||||
TestEngineUtils.simulateFrames(1);
|
||||
frameCount++;
|
||||
}
|
||||
org.junit.jupiter.api.Assertions.assertTrue(testResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for a given test to be true
|
||||
* @param test The test to wait for
|
||||
*/
|
||||
public static void waitForCondition(Supplier<Boolean> test){
|
||||
waitForCondition(test,100);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -6,8 +6,6 @@ import java.io.IOException;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
|
||||
/**
|
||||
@ -15,74 +13,6 @@ import electrosphere.engine.Globals;
|
||||
*/
|
||||
public class TestRenderingUtils {
|
||||
|
||||
/**
|
||||
* The threshold at which we say the colors are 'close enough'
|
||||
*/
|
||||
static final int COLOR_COMPARE_THRESHOLD = 3;
|
||||
|
||||
/**
|
||||
* Asserts that the most recent render matches the image stored at the provided filepath
|
||||
* @param existingRenderPath The filepath of the existing render
|
||||
*/
|
||||
public static void assertEqualsRender(String existingRenderPath, Runnable onFailure){
|
||||
BufferedImage testData = null;
|
||||
try {
|
||||
testData = ImageIO.read(new File(existingRenderPath));
|
||||
} catch (IOException e){
|
||||
fail("Failed to read existing image path " + existingRenderPath);
|
||||
}
|
||||
BufferedImage screenshot = Globals.renderingEngine.defaultFramebuffer.getPixels(Globals.renderingEngine.getOpenGLState());
|
||||
//check basic data
|
||||
//
|
||||
//width
|
||||
if(testData.getWidth() != screenshot.getWidth()){
|
||||
onFailure.run();
|
||||
}
|
||||
assertEquals(testData.getWidth(), screenshot.getWidth());
|
||||
|
||||
//
|
||||
//height
|
||||
if(testData.getHeight() != screenshot.getHeight()){
|
||||
onFailure.run();
|
||||
}
|
||||
assertEquals(testData.getHeight(), screenshot.getHeight());
|
||||
|
||||
//
|
||||
//pixel-by-pixel check
|
||||
//
|
||||
for(int x = 0; x < testData.getWidth(); x++){
|
||||
for(int y = 0; y < testData.getHeight(); y++){
|
||||
|
||||
//get from-disk rgba
|
||||
int sourceRed = testData.getRGB(x, y) & 0xff;
|
||||
int sourceGreen = (testData.getRGB(x, y) & 0xff00) >> 8;
|
||||
int sourceBlue = (testData.getRGB(x, y) & 0xff0000) >> 16;
|
||||
int sourceAlpha = (testData.getRGB(x, y) & 0xff000000) >>> 24;
|
||||
|
||||
//get from-render rgba
|
||||
int renderRed = screenshot.getRGB(x, y) & 0xff;
|
||||
int renderGreen = (screenshot.getRGB(x, y) & 0xff00) >> 8;
|
||||
int renderBlue = (screenshot.getRGB(x, y) & 0xff0000) >> 16;
|
||||
int renderAlpha = (screenshot.getRGB(x, y) & 0xff000000) >>> 24;
|
||||
|
||||
if(
|
||||
Math.abs(sourceRed - renderRed) > COLOR_COMPARE_THRESHOLD ||
|
||||
Math.abs(sourceGreen - renderGreen) > COLOR_COMPARE_THRESHOLD ||
|
||||
Math.abs(sourceBlue - renderBlue) > COLOR_COMPARE_THRESHOLD ||
|
||||
Math.abs(sourceAlpha - renderAlpha) > COLOR_COMPARE_THRESHOLD
|
||||
){
|
||||
|
||||
onFailure.run();
|
||||
String failMessage = "Colors aren't approximately the same!\n" +
|
||||
"Color from disk: " + sourceRed + "," + sourceGreen + "," + sourceBlue + "," + sourceAlpha + "\n" +
|
||||
"Color from render: " + renderRed + "," + renderGreen + "," + renderBlue + "," + renderAlpha + "\n"
|
||||
;
|
||||
fail(failMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for saving a copy of the current render (ie for generating test data)
|
||||
* @param existingRenderPath The filepath of the existing render
|
||||
|
||||
Loading…
Reference in New Issue
Block a user