zildo.platform.engine.LwjglSpriteEngine.java Source code

Java tutorial

Introduction

Here is the source code for zildo.platform.engine.LwjglSpriteEngine.java

Source

/**
 * The Land of Alembrum
 * Copyright (C) 2006-2013 Evariste Boussaton
 * 
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

package zildo.platform.engine;

import java.util.HashMap;
import java.util.Map;

import org.lwjgl.opengl.ARBShaderObjects;
import org.lwjgl.opengl.GL11;

import zildo.client.ClientEngineZildo;
import zildo.fwk.bank.SpriteBank;
import zildo.fwk.gfx.EngineFX;
import zildo.fwk.gfx.GFXBasics;
import zildo.fwk.gfx.engine.SpriteEngine;
import zildo.fwk.gfx.engine.TextureEngine;
import zildo.monde.sprites.SpriteModel;
import zildo.monde.sprites.SpriteStore;
import zildo.monde.sprites.desc.Outfit;
import zildo.monde.util.Point;
import zildo.monde.util.Vector3f;
import zildo.monde.util.Vector4f;
import zildo.server.SpriteManagement;

// SpriteEngine.cpp: implementation of the SpriteEngine class.
//
//////////////////////////////////////////////////////////////////////

public class LwjglSpriteEngine extends SpriteEngine {

    public LwjglSpriteEngine(TextureEngine texEngine) {
        this.textureEngine = texEngine;
    }

    float gamma;

    ///////////////////////////////////////////////////////////////////////////////////////
    // render
    ///////////////////////////////////////////////////////////////////////////////////////
    // Draw every sprite's primitives
    ///////////////////////////////////////////////////////////////////////////////////////
    // IN: true=render BACKground
    //      false=render FOREground
    ///////////////////////////////////////////////////////////////////////////////////////
    @Override
    public void render(int floor, boolean backGround) {

        // Display every sprites
        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
        GL11.glEnable(GL11.GL_BLEND);
        float[] color = textureEngine.graphicStuff.getFloat(GL11.GL_CURRENT_COLOR, 4);

        Vector3f ambient = ClientEngineZildo.ortho.getAmbientColor();
        Vector4f ambient4f = new Vector4f(1, 1, 1, 1);
        if (ambient != null) {
            color[0] = ambient.x;
            color[1] = ambient.y;
            color[2] = ambient.z;
            ambient4f = new Vector4f(color[0], color[1], color[2], 1);
        }
        // Respect order from bankOrder
        boolean endSequence = false;
        int posBankOrder = 0;

        // Retrieve the sprite's order
        int[][][] bankOrder = ClientEngineZildo.spriteDisplay.getBankOrder();

        int phase = (backGround) ? 0 : 1;
        while (!endSequence) {
            int numBank = bankOrder[floor][phase][posBankOrder * 4];
            if (numBank == -1) {
                endSequence = true;
            } else {
                // Render the n sprites from this bank
                int nbQuads = bankOrder[floor][phase][posBankOrder * 4 + 1];
                int iCurrentFX = bankOrder[floor][phase][posBankOrder * 4 + 2];
                int alpha = bankOrder[floor][phase][posBankOrder * 4 + 3];
                EngineFX currentFX = EngineFX.values()[iCurrentFX];
                int texId = textureEngine.getNthTexture(numBank);
                GL11.glBindTexture(GL11.GL_TEXTURE_2D, texId);

                // Select the right pixel shader (if needed)
                if (pixelShaderSupported) {
                    switch (currentFX) {
                    case NO_EFFECT:
                        ARBShaderObjects.glUseProgramObjectARB(0);
                        break;
                    case PERSO_HURT:
                        // A sprite has been hurt
                        ARBShaderObjects.glUseProgramObjectARB(ClientEngineZildo.pixelShaders.getPixelShader(1));
                        ClientEngineZildo.pixelShaders.setParameter(1, "randomColor", new Vector4f(
                                (float) Math.random(), (float) Math.random(), (float) Math.random(), 1));
                        break;
                    case YELLOW_HALO:
                        ARBShaderObjects.glUseProgramObjectARB(ClientEngineZildo.pixelShaders.getPixelShader(2));
                        ClientEngineZildo.pixelShaders.setParameter(2, "factor",
                                new Vector4f((float) (0.6 + 0.4 * Math.cos(3 * gamma)), 0, 0, 1));
                        break;
                    case STAR:
                        ARBShaderObjects.glUseProgramObjectARB(ClientEngineZildo.pixelShaders.getPixelShader(3));
                        ClientEngineZildo.pixelShaders.setParameter(3, "noise",
                                new Vector4f(gamma, (float) Math.random(), 0, 1));
                        break;
                    case FIRE:
                        ARBShaderObjects.glUseProgramObjectARB(ClientEngineZildo.pixelShaders.getPixelShader(4));
                        //ClientEngineZildo.pixelShaders.setParameter(4, "iResolution", new Vector4f(Zildo.viewPortX, Zildo.viewPortY, 0, 0));
                        ClientEngineZildo.pixelShaders.setParameter(4, "iGlobalTime", new Vector4f(gamma, 0, 0, 0));
                        break;
                    default:
                        if (currentFX.needPixelShader()) {
                            // This is a color replacement, so get the right ones
                            Vector4f[] tabColors = ClientEngineZildo.pixelShaders
                                    .getConstantsForSpecialEffect(currentFX);

                            // And enable the 'color replacement' pixel shader
                            ARBShaderObjects
                                    .glUseProgramObjectARB(ClientEngineZildo.pixelShaders.getPixelShader(0));
                            ClientEngineZildo.pixelShaders.setParameter(0, "Color1", tabColors[2]); //.scale(color[0]));
                            ClientEngineZildo.pixelShaders.setParameter(0, "Color2", tabColors[3]); //.scale(color[0]));
                            ClientEngineZildo.pixelShaders.setParameter(0, "Color3", tabColors[0]);
                            ClientEngineZildo.pixelShaders.setParameter(0, "Color4", tabColors[1]);
                            ClientEngineZildo.pixelShaders.setParameter(0, "curColor", ambient4f);
                        } else {
                            ARBShaderObjects.glUseProgramObjectARB(0);
                        }
                    }
                }
                switch (currentFX) {
                case SHINY:
                    GL11.glBlendFunc(GL11.GL_SRC_COLOR, GL11.GL_ONE); // _MINUS_SRC_ALPHA);
                    GL11.glColor4f(1, (float) Math.random(), 0, (float) Math.random());
                    break;
                case QUAD:
                    //GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
                    //GL11.glColor4f(0.5f + 0.5f * (float) Math.random(), 0.5f * (float) Math.random(), 0, 1);
                    GL11.glColor4f(0.7f, 0.6f, 0.8f, 1);
                    break;
                /*
                case WHITE_HALO:
                float r = (float) (0.6 + 0.4 * Math.random());
                GL11.glColor4f(r, 0, 0, 1);
                GL11.glBlendFunc(GL11.GL_SRC_COLOR, GL11.GL_ONE_MINUS_SRC_ALPHA);
                break;
                */
                case FOCUSED:
                    GL11.glColor4f(1.0f, 1.0f, 1.0f, alpha / 255.0f);
                    break;
                case FONT_PEOPLENAME:
                    GL11.glColor4f(0.9f, 0.5f, 0.2f, alpha / 255.0f);
                    break;
                case INFO:
                    GL11.glColor4f(0.9f, 0.8f, 0.72f, alpha / 255.0f);
                    break;
                default:
                    color[3] = alpha / 255.0f;
                    textureEngine.graphicStuff.setCurrentColor(color);
                    GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
                }
                meshSprites[numBank].render(nbQuads);
                posBankOrder++;
            }
        }

        // Deactivate pixel shader
        if (pixelShaderSupported) {
            ARBShaderObjects.glUseProgramObjectARB(0);
        }
        GL11.glDisable(GL11.GL_BLEND);

        gamma += 0.01f;
    }

    @Override
    public void loadTextures(SpriteStore p_spriteStore) {
        // Load sprite banks
        textureEngine.init();
        for (int i = 0; i < SpriteManagement.sprBankName.length; i++) {
            SpriteBank sprBank = p_spriteStore.getSpriteBank(i);

            createModelsFromSpriteBank(sprBank);

            // Create a DirectX9 texture based on the current tiles
            createTextureFromSpriteBank(sprBank);
            //textureEngine.loadTexture("sprite"+i);
        }

        // Create Zildo with all outfits
        if (!ClientEngineZildo.editing) {
            // textureEngine.setCurentTexture(SpriteBank.BANK_ZILDOOUTFIT);
            // createTextureFromAnotherReplacement(SpriteBank.BANK_ZILDO,
            // ZildoOutfit.class);
        }

        // Prepare screen copy texture
        // textureTab[SpriteBank.BANK_COPYSCREEN]=generateTexture(0,64); //,
        // 1024); //, Zildo.viewPortY);
        // n_Texture++;
    }

    ///////////////////////////////////////////////////////////////////////////////////////
    // createTextureFromSpriteBank
    ///////////////////////////////////////////////////////////////////////////////////////
    // IN: Bank to transform into texture
    ///////////////////////////////////////////////////////////////////////////////////////
    // Create a Direct3DTexture9 object from a sprite bank. Every sprite is added at the
    // right side of the previous one. If it is too long, we shift to next line, which is
    // calculated as the highest sprite on the line. And so on.
    // Here we use a GFXBasics object to gain in readability and comfort. This one will be deleted
    // at the end, indeed. So we can say this is a beautiful method.
    private void createTextureFromSpriteBank(SpriteBank sBank) {

        GFXBasics surfaceGfx = textureEngine.prepareSurfaceForTexture(true);

        surfaceGfx.StartRendering();

        // Default place on classic palette
        GFXBasics.switchPalette(1);

        int palNum = 1;
        for (int n = 0; n < sBank.getNSprite(); n++) {
            SpriteModel spr = sBank.get_sprite(n);
            int longX = spr.getTaille_x();
            int longY = spr.getTaille_y();
            int x = spr.getTexPos_x();
            int y = spr.getTexPos_y();
            // On place le sprite sur la texture
            short[] motif = sBank.getSpriteGfx(n);
            Vector4f replacedColor;
            for (int j = 0; j < longY; j++) {

                for (int i = 0; i < longX; i++) {
                    int a = motif[i + j * longX];
                    if (a != 255) {
                        // Regular size
                        long modifiedColor = -1;
                        if (pixelShaderSupported) {
                            modifiedColor = sBank.modifyPixel(n, a);
                        }
                        int newPalNum = sBank.whichPalette(n);
                        if (newPalNum != palNum) {
                            GFXBasics.switchPalette(newPalNum);
                            palNum = newPalNum;
                        }
                        replacedColor = modifiedColor == -1 ? null
                                : textureEngine.graphicStuff.createColor(modifiedColor);
                        surfaceGfx.pset(i + x, j + y, a, replacedColor);
                    }
                }
            }
        }
        //sBank.freeTempBuffer();
        GFXBasics.switchPalette(1);

        textureEngine.generateTexture();
    }

    /**
      * Create a new texture from a given one, and replace colors as specified by
      * the {@link Outfit} class.<br/>
      * 
      * @param p_originalTexture
      * @param p_replacements
      *            list of replacements : for a point (x,y), color-index <b>x</b>
      *            become color-index <b>y</b>.
      */
    private void createTextureFromAnotherReplacement(int p_originalTexture, Class<? extends Outfit> p_outfitClass) {

        GFXBasics surfaceGfx = textureEngine.prepareSurfaceForTexture(true);

        // 1) Store the color indexes once for all
        textureEngine.getTextureImage(p_originalTexture);
        Map<Integer, Integer> colorIndexes = new HashMap<Integer, Integer>();
        int i, j;
        for (j = 0; j < 256; j++) {
            for (i = 0; i < 256; i++) {
                Vector4f color = surfaceGfx.getPixel(i, j);
                if (color.w != 0) {
                    colorIndexes.put(j * 256 + i, surfaceGfx.getPalIndex(color));
                }
            }
        }

        // 2) Create all textures according to the outfits
        boolean textureReady = true;
        Outfit[] outfits = p_outfitClass.getEnumConstants();
        for (Outfit outfit : outfits) {
            Point[] replacements = outfit.getTransforms();
            if (replacements.length == 0) {
                continue; // No replacements
            }
            if (!textureReady) {
                surfaceGfx = textureEngine.prepareSurfaceForTexture(true);
            }
            surfaceGfx.StartRendering();
            for (j = 0; j < 256; j++) {
                for (i = 0; i < 256; i++) {
                    Integer palIndex = colorIndexes.get(j * 256 + i);
                    if (palIndex != null) {
                        for (Point p : replacements) {
                            if (palIndex == p.x) {
                                surfaceGfx.pset(i, j, p.y, null);
                            }
                        }
                    }
                }
            }

            textureEngine.generateTexture();
            textureReady = false;
        }
    }

    @Override
    public void saveTextures() {
        textureEngine.saveAllTextures("sprite");
    }

}