Added support for gpu skinning. Added animation system.

This commit is contained in:
2014-05-27 13:45:58 -04:30
parent 5ef7928706
commit 686f263b0d
4 changed files with 176 additions and 51 deletions

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) 2014 Miguel Angel Astor Romero
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ve.ucv.ciens.ccg.nxtar.components;
import java.util.LinkedList;
import java.util.List;
import com.artemis.Component;
import com.badlogic.gdx.graphics.g3d.ModelInstance;
import com.badlogic.gdx.graphics.g3d.utils.AnimationController;
public class AnimationComponent extends Component {
public AnimationController controller;
public List<String> animationsIds;
public int current;
public int next;
public AnimationComponent(ModelInstance instance) throws IllegalArgumentException{
if(instance == null)
throw new IllegalArgumentException("Instance is null.");
controller = new AnimationController(instance);
animationsIds = new LinkedList<String>();
current = -1;
next = -1;
for(int i = 0; i < instance.animations.size; i++){
animationsIds.add(instance.animations.get(i).id);
}
}
}

View File

@@ -19,6 +19,7 @@ import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Camera; import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.VertexAttributes;
import com.badlogic.gdx.graphics.g3d.Renderable; import com.badlogic.gdx.graphics.g3d.Renderable;
import com.badlogic.gdx.graphics.g3d.Shader; import com.badlogic.gdx.graphics.g3d.Shader;
import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute; import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
@@ -30,28 +31,34 @@ import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.GdxRuntimeException; import com.badlogic.gdx.utils.GdxRuntimeException;
public class SingleLightPerPixelShader implements Shader{ public class SingleLightPerPixelShader implements Shader{
private static final int MAX_NUM_BONES = 4;
private static final Matrix4 IDENTITY = new Matrix4();
private static final String VERTEX_SHADER_PATH = "shaders/directionalPerPixelSingleLight/directionalPerPixel_vert.glsl"; private static final String VERTEX_SHADER_PATH = "shaders/directionalPerPixelSingleLight/directionalPerPixel_vert.glsl";
private static final String FRAGMENT_SHADER_PATH = "shaders/directionalPerPixelSingleLight/directionalPerPixel_frag.glsl"; private static final String FRAGMENT_SHADER_PATH = "shaders/directionalPerPixelSingleLight/directionalPerPixel_frag.glsl";
private static final String INCLUDE_SKINNING = "#define SKINNING\n";
private ShaderProgram program; private ShaderProgram skinningProgram;
private ShaderProgram baseProgram;
private Camera camera; private Camera camera;
private RenderContext context; private RenderContext context;
private Matrix4 normalMatrix; private Matrix4 normalMatrix;
// Uniform locations. // Uniform locations.
private int u_geomTrans; private int[] u_geomTrans;
private int u_projTrans; private int[] u_projTrans;
private int u_lightPos; private int[] u_lightPos;
private int u_lightDiffuse; private int[] u_lightDiffuse;
private int u_specular; private int[] u_specular;
private int u_ambient; private int[] u_ambient;
private int u_shiny; private int[] u_shiny;
private int u_cameraPos; private int[] u_cameraPos;
private int u_materialDiffuse; private int[] u_materialDiffuse;
private int u_normalMatrix; private int[] u_normalMatrix;
private int[] u_bones;
public SingleLightPerPixelShader(){ public SingleLightPerPixelShader(){
program = null; skinningProgram = null;
baseProgram = null;
camera = null; camera = null;
context = null; context = null;
} }
@@ -59,30 +66,65 @@ public class SingleLightPerPixelShader implements Shader{
@Override @Override
public void init() throws GdxRuntimeException{ public void init() throws GdxRuntimeException{
normalMatrix = new Matrix4().idt(); normalMatrix = new Matrix4().idt();
u_bones = new int[MAX_NUM_BONES];
// Compile the shader. // Compile the shader.
program = new ShaderProgram(Gdx.files.internal(VERTEX_SHADER_PATH), Gdx.files.internal(FRAGMENT_SHADER_PATH)); String vertexCode = Gdx.files.internal(VERTEX_SHADER_PATH).readString();
String fragmentCode = Gdx.files.internal(FRAGMENT_SHADER_PATH).readString();
if(!program.isCompiled()) skinningProgram = new ShaderProgram(INCLUDE_SKINNING + vertexCode, fragmentCode);
throw new GdxRuntimeException(program.getLog()); baseProgram = new ShaderProgram(vertexCode, fragmentCode);
if(!skinningProgram.isCompiled())
throw new GdxRuntimeException(skinningProgram.getLog());
if(!baseProgram.isCompiled())
throw new GdxRuntimeException(skinningProgram.getLog());
// Create uniform locations.
u_projTrans = new int[2];
u_geomTrans = new int[2];
u_lightPos = new int[2];
u_lightDiffuse = new int[2];
u_specular = new int[2];
u_ambient = new int[2];
u_shiny = new int[2];
u_cameraPos = new int[2];
u_materialDiffuse = new int[2];
u_normalMatrix = new int[2];
// Cache uniform locations. // Cache uniform locations.
u_projTrans = program.getUniformLocation("u_projTrans"); u_projTrans [0] = skinningProgram.getUniformLocation("u_projTrans");
u_geomTrans = program.getUniformLocation("u_geomTrans"); u_geomTrans [0] = skinningProgram.getUniformLocation("u_geomTrans");
u_lightPos = program.getUniformLocation("u_lightPos"); u_lightPos [0] = skinningProgram.getUniformLocation("u_lightPos");
u_lightDiffuse = program.getUniformLocation("u_lightDiffuse"); u_lightDiffuse [0] = skinningProgram.getUniformLocation("u_lightDiffuse");
u_specular = program.getUniformLocation("u_specular"); u_specular [0] = skinningProgram.getUniformLocation("u_specular");
u_ambient = program.getUniformLocation("u_ambient"); u_ambient [0] = skinningProgram.getUniformLocation("u_ambient");
u_shiny = program.getUniformLocation("u_shiny"); u_shiny [0] = skinningProgram.getUniformLocation("u_shiny");
u_cameraPos = program.getUniformLocation("u_cameraPos"); u_cameraPos [0] = skinningProgram.getUniformLocation("u_cameraPos");
u_materialDiffuse = program.getUniformLocation("u_materialDiffuse"); u_materialDiffuse [0] = skinningProgram.getUniformLocation("u_materialDiffuse");
u_normalMatrix = program.getUniformLocation("u_normalMatrix"); u_normalMatrix [0] = skinningProgram.getUniformLocation("u_normalMatrix");
u_projTrans [1] = baseProgram.getUniformLocation("u_projTrans");
u_geomTrans [1] = baseProgram.getUniformLocation("u_geomTrans");
u_lightPos [1] = baseProgram.getUniformLocation("u_lightPos");
u_lightDiffuse [1] = baseProgram.getUniformLocation("u_lightDiffuse");
u_specular [1] = baseProgram.getUniformLocation("u_specular");
u_ambient [1] = baseProgram.getUniformLocation("u_ambient");
u_shiny [1] = baseProgram.getUniformLocation("u_shiny");
u_cameraPos [1] = baseProgram.getUniformLocation("u_cameraPos");
u_materialDiffuse [1] = baseProgram.getUniformLocation("u_materialDiffuse");
u_normalMatrix [1] = baseProgram.getUniformLocation("u_normalMatrix");
for(int i = 0; i < MAX_NUM_BONES; i++){
u_bones[i] = skinningProgram.getUniformLocation("u_bone" + Integer.toString(i));
}
} }
@Override @Override
public void dispose(){ public void dispose(){
if(program != null) if(skinningProgram != null) skinningProgram.dispose();
program.dispose(); if(baseProgram != null) baseProgram.dispose();
} }
@Override @Override
@@ -118,11 +160,6 @@ public class SingleLightPerPixelShader implements Shader{
this.camera = camera; this.camera = camera;
this.context = context; this.context = context;
program.begin();
// Set camera dependant uniforms.
program.setUniformMatrix(u_projTrans, this.camera.combined);
program.setUniformf(u_cameraPos, this.camera.position);
// Set render context. // Set render context.
this.context.setDepthTest(GL20.GL_LEQUAL); this.context.setDepthTest(GL20.GL_LEQUAL);
@@ -131,6 +168,10 @@ public class SingleLightPerPixelShader implements Shader{
@Override @Override
public void render(Renderable renderable){ public void render(Renderable renderable){
ShaderProgram program;
int index;
boolean bonesEnabled;
// Get material colors. // Get material colors.
Vector3 lightPosition = renderable.environment.directionalLights.get(0).direction; Vector3 lightPosition = renderable.environment.directionalLights.get(0).direction;
Color diffuseLightColor = renderable.environment.directionalLights.get(0).color; Color diffuseLightColor = renderable.environment.directionalLights.get(0).color;
@@ -139,24 +180,49 @@ public class SingleLightPerPixelShader implements Shader{
Color ambientColor = ((ColorAttribute)renderable.environment.get(ColorAttribute.AmbientLight)).color; Color ambientColor = ((ColorAttribute)renderable.environment.get(ColorAttribute.AmbientLight)).color;
float shininess = ((FloatAttribute)renderable.material.get(FloatAttribute.Shininess)).value; float shininess = ((FloatAttribute)renderable.material.get(FloatAttribute.Shininess)).value;
// Set model dependant uniforms. if(renderable.mesh.getVertexAttribute(VertexAttributes.Usage.BoneWeight) != null){
program.setUniformMatrix(u_geomTrans, renderable.worldTransform); program = skinningProgram;
program.setUniformMatrix(u_normalMatrix, normalMatrix.idt().mul(renderable.worldTransform).inv().tra()); index = 0;
program.setUniformf(u_lightPos, lightPosition); bonesEnabled = true;
program.setUniformf(u_lightDiffuse, diffuseLightColor); }else{
program.setUniformf(u_materialDiffuse, diffuseColor); program = baseProgram;
program.setUniformf(u_specular, specularColor); index = 1;
program.setUniformf(u_ambient, ambientColor); bonesEnabled = false;
program.setUniformf(u_shiny, shininess); }
program.begin();
// Set camera dependant uniforms.
program.setUniformMatrix(u_projTrans[index], this.camera.combined);
program.setUniformf(u_cameraPos[index], this.camera.position);
// Set model dependant uniforms.
program.setUniformMatrix(u_geomTrans[index], renderable.worldTransform);
program.setUniformMatrix(u_normalMatrix[index], normalMatrix.idt().mul(renderable.worldTransform).inv().tra());
program.setUniformf(u_lightPos[index], lightPosition);
program.setUniformf(u_lightDiffuse[index], diffuseLightColor);
program.setUniformf(u_materialDiffuse[index], diffuseColor);
program.setUniformf(u_specular[index], specularColor);
program.setUniformf(u_ambient[index], ambientColor);
program.setUniformf(u_shiny[index], shininess);
// Set the bones uniforms.
if(bonesEnabled){
for(int i = 0; i < MAX_NUM_BONES; i++){
if(renderable.bones != null && i < renderable.bones.length && renderable.bones[i] != null)
skinningProgram.setUniformMatrix(u_bones[i], renderable.bones[i]);
else
skinningProgram.setUniformMatrix(u_bones[i], IDENTITY);
}
}
// Render.
renderable.mesh.render(program, renderable.primitiveType, renderable.meshPartOffset, renderable.meshPartSize); renderable.mesh.render(program, renderable.primitiveType, renderable.meshPartOffset, renderable.meshPartSize);
program.end();
} }
@Override @Override
public void end(){ public void end(){
program.end();
this.camera = null; this.camera = null;
this.context = null; this.context = null;
} }

View File

@@ -27,6 +27,7 @@ import ve.ucv.ciens.ccg.nxtar.graphics.RenderParameters;
import ve.ucv.ciens.ccg.nxtar.interfaces.ImageProcessor.MarkerData; import ve.ucv.ciens.ccg.nxtar.interfaces.ImageProcessor.MarkerData;
import ve.ucv.ciens.ccg.nxtar.network.monitors.MotorEventQueue; import ve.ucv.ciens.ccg.nxtar.network.monitors.MotorEventQueue;
import ve.ucv.ciens.ccg.nxtar.network.monitors.VideoFrameMonitor; import ve.ucv.ciens.ccg.nxtar.network.monitors.VideoFrameMonitor;
import ve.ucv.ciens.ccg.nxtar.systems.AnimationSystem;
import ve.ucv.ciens.ccg.nxtar.systems.MarkerPositioningSystem; import ve.ucv.ciens.ccg.nxtar.systems.MarkerPositioningSystem;
import ve.ucv.ciens.ccg.nxtar.systems.MarkerRenderingSystem; import ve.ucv.ciens.ccg.nxtar.systems.MarkerRenderingSystem;
import ve.ucv.ciens.ccg.nxtar.systems.ObjectRenderingSystem; import ve.ucv.ciens.ccg.nxtar.systems.ObjectRenderingSystem;
@@ -191,14 +192,19 @@ public class InGameState extends BaseState{
// Set up the game world. // Set up the game world.
gameWorld = new World(); gameWorld = new World();
entityCreator = new MarkerTestEntityCreator(); entityCreator = new MarkerTestEntityCreator();
entityCreator.setWorld(gameWorld); entityCreator.setWorld(gameWorld);
entityCreator.createAllEntities(); entityCreator.createAllEntities();
gameWorld.setSystem(new MarkerPositioningSystem()); gameWorld.setSystem(new MarkerPositioningSystem());
gameWorld.setSystem(new AnimationSystem());
markerRenderingSystem = new MarkerRenderingSystem(modelBatch); markerRenderingSystem = new MarkerRenderingSystem(modelBatch);
objectRenderingSystem = new ObjectRenderingSystem(modelBatch); objectRenderingSystem = new ObjectRenderingSystem(modelBatch);
gameWorld.setSystem(markerRenderingSystem, true); gameWorld.setSystem(markerRenderingSystem, true);
gameWorld.setSystem(objectRenderingSystem, true); gameWorld.setSystem(objectRenderingSystem, true);
gameWorld.initialize(); gameWorld.initialize();
} }

View File

@@ -15,23 +15,32 @@
*/ */
package ve.ucv.ciens.ccg.nxtar.systems; package ve.ucv.ciens.ccg.nxtar.systems;
import ve.ucv.ciens.ccg.nxtar.components.ModelComponent; import ve.ucv.ciens.ccg.nxtar.components.AnimationComponent;
import com.artemis.Aspect; import com.artemis.Aspect;
import com.artemis.ComponentMapper;
import com.artemis.Entity; import com.artemis.Entity;
import com.artemis.annotations.Mapper;
import com.artemis.systems.EntityProcessingSystem; import com.artemis.systems.EntityProcessingSystem;
import com.badlogic.gdx.Gdx;
public class AnimationSystem extends EntityProcessingSystem { public class AnimationSystem extends EntityProcessingSystem {
@Mapper ComponentMapper<AnimationComponent> animationMapper;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public AnimationSystem(){ public AnimationSystem(){
super(Aspect.getAspectForAll(ModelComponent.class)); super(Aspect.getAspectForAll(AnimationComponent.class));
} }
@Override @Override
protected void process(Entity e) { protected void process(Entity e) {
// TODO Auto-generated method stub AnimationComponent animation = animationMapper.get(e);
if(animation.current != animation.next){
animation.controller.setAnimation(animation.animationsIds.get(animation.next));
}
animation.controller.update(Gdx.graphics.getDeltaTime());
} }
} }