package org.terasology.componentSystem.rendering; import com.google.common.collect.Maps; import org.lwjgl.opengl.GL11; import org.terasology.componentSystem.RenderSystem; import org.terasology.components.CharacterMovementComponent; import org.terasology.components.InventoryComponent; import org.terasology.components.ItemComponent; import org.terasology.components.LocalPlayerComponent; import org.terasology.components.world.BlockItemComponent; import org.terasology.entitySystem.EntityRef; import org.terasology.entitySystem.RegisterComponentSystem; import org.terasology.game.CoreRegistry; import org.terasology.logic.LocalPlayer; import org.terasology.logic.manager.AssetManager; import org.terasology.logic.manager.ShaderManager; import org.terasology.logic.world.WorldProvider; import org.terasology.math.Side; import org.terasology.math.TeraMath; import org.terasology.model.blocks.BlockFamily; import org.terasology.model.inventory.Icon; import org.terasology.rendering.assets.Texture; import org.terasology.rendering.primitives.Mesh; import org.terasology.rendering.primitives.MeshFactory; import org.terasology.rendering.primitives.Tessellator; import org.terasology.rendering.primitives.TessellatorHelper; import org.terasology.rendering.shader.ShaderProgram; import org.terasology.rendering.world.WorldRenderer; import org.terasology.teraspout.TeraBlock; import javax.vecmath.Vector2f; import javax.vecmath.Vector3f; import javax.vecmath.Vector4f; import java.util.Map; import static org.lwjgl.opengl.GL11.*; /** * @author Immortius <immortius@gmail.com> */ @RegisterComponentSystem(headedOnly = true) public class FirstPersonRenderer implements RenderSystem { private WorldProvider worldProvider; private LocalPlayer localPlayer; private WorldRenderer worldRenderer; private Mesh handMesh; private Texture handTex; private Map<String, Mesh> iconMeshes = Maps.newHashMap(); @Override public void initialise() { localPlayer = CoreRegistry.get(LocalPlayer.class); worldProvider = CoreRegistry.get(WorldProvider.class); worldRenderer = CoreRegistry.get(WorldRenderer.class); Vector2f texPos = new Vector2f(40.0f * 0.015625f, 32.0f * 0.03125f); Vector2f texWidth = new Vector2f(4.0f * 0.015625f, -12.0f * 0.03125f); Tessellator tessellator = new Tessellator(); TessellatorHelper.addBlockMesh(tessellator, new Vector4f(1, 1, 1, 1), texPos, texWidth, 1.0f, 1.0f, 0.9f, 0.0f, 0.0f, 0.0f); handMesh = tessellator.generateMesh(); handTex = AssetManager.loadTexture("engine:char"); } @Override public void shutdown() { } @Override public void renderOpaque() { } @Override public void renderTransparent() { } @Override public void renderFirstPerson() { CharacterMovementComponent charMoveComp = localPlayer.getEntity().getComponent(CharacterMovementComponent.class); float bobOffset = calcBobbingOffset(charMoveComp.footstepDelta / charMoveComp.distanceBetweenFootsteps, (float) java.lang.Math.PI / 8f, 0.05f, 1f); float handMovementAnimationOffset = localPlayer.getEntity().getComponent(LocalPlayerComponent.class).handAnimation; int invSlotIndex = localPlayer.getEntity().getComponent(LocalPlayerComponent.class).selectedTool; EntityRef heldItem = localPlayer.getEntity().getComponent(InventoryComponent.class).itemSlots.get(invSlotIndex); ItemComponent heldItemComp = heldItem.getComponent(ItemComponent.class); BlockItemComponent blockItem = heldItem.getComponent(BlockItemComponent.class); if (blockItem != null) { renderBlock(blockItem.blockFamily, bobOffset, handMovementAnimationOffset); } else if (heldItemComp != null && heldItemComp.renderWithIcon) { renderIcon(heldItemComp.icon, bobOffset, handMovementAnimationOffset); } else { renderHand(bobOffset, handMovementAnimationOffset); } } @Override public void renderOverlay() { } private void renderHand(float bobOffset, float handMovementAnimationOffset) { ShaderProgram shader = ShaderManager.getInstance().getShaderProgram("block"); shader.enable(); shader.setFloat("light", worldRenderer.getRenderingLightValue()); glBindTexture(GL11.GL_TEXTURE_2D, handTex.getId()); glPushMatrix(); glTranslatef(0.8f, -0.8f + bobOffset - handMovementAnimationOffset * 0.5f, -1.0f - handMovementAnimationOffset * 0.5f); glRotatef(-45f - handMovementAnimationOffset * 64.0f, 1.0f, 0.0f, 0.0f); glRotatef(35f, 0.0f, 1.0f, 0.0f); glTranslatef(0f, 0.25f, 0f); glScalef(0.3f, 0.6f, 0.3f); handMesh.render(); glPopMatrix(); } private void renderIcon(String iconName, float bobOffset, float handMovementAnimationOffset) { ShaderProgram shader = ShaderManager.getInstance().getShaderProgram("block"); shader.enable(); shader.setInt("textured", 0); shader.setFloat("light", worldRenderer.getRenderingLightValue()); glPushMatrix(); glTranslatef(1.0f, -0.7f + bobOffset - handMovementAnimationOffset * 0.5f, -1.5f - handMovementAnimationOffset * 0.5f); glRotatef(-handMovementAnimationOffset * 64.0f, 1.0f, 0.0f, 0.0f); glRotatef(-20f, 1.0f, 0.0f, 0.0f); glRotatef(-80f, 0.0f, 1.0f, 0.0f); glRotatef(45f, 0.0f, 0.0f, 1.0f); Mesh itemMesh = iconMeshes.get(iconName); if (itemMesh == null) { Icon icon = Icon.get(iconName); itemMesh = MeshFactory.getInstance().generateItemMesh(icon.getX(), icon.getY()); iconMeshes.put(iconName, itemMesh); } itemMesh.render(); glPopMatrix(); } private void renderBlock(BlockFamily blockFamily, float bobOffset, float handMovementAnimationOffset) { TeraBlock activeBlock = blockFamily.getArchetypeBlock(); Vector3f playerPos = localPlayer.getPosition(); // Adjust the brightness of the block according to the current position of the player ShaderProgram shader = ShaderManager.getInstance().getShaderProgram("block"); shader.enable(); // Apply biome and overall color offset // TODO: Should get temperature, etc from world provider Vector4f color = activeBlock.calcColorOffsetFor(Side.FRONT); shader.setFloat3("colorOffset", color.x, color.y, color.z); glEnable(GL11.GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glAlphaFunc(GL_GREATER, 0.1f); if (activeBlock.isTranslucent()) { glEnable(GL11.GL_ALPHA_TEST); } glPushMatrix(); glTranslatef(1.0f, -0.7f + bobOffset - handMovementAnimationOffset * 0.5f, -1.5f - handMovementAnimationOffset * 0.5f); glRotatef(-25f - handMovementAnimationOffset * 64.0f, 1.0f, 0.0f, 0.0f); glRotatef(35f, 0.0f, 1.0f, 0.0f); glTranslatef(0f, 0.25f, 0f); activeBlock.renderWithLightValue(worldRenderer.getRenderingLightValue()); glPopMatrix(); if (activeBlock.isTranslucent()) { glDisable(GL11.GL_ALPHA_TEST); } glDisable(GL11.GL_BLEND); } private float calcBobbingOffset(float counter, float phaseOffset, float amplitude, float frequency) { return (float) java.lang.Math.sin(2 * Math.PI * counter * frequency + phaseOffset) * amplitude; } }