⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 shadedsurface.java

📁 Developing Games in Java 源代码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:


    /**
        Gets the surface bounds for this ShadedSurface.
    */
    public Rectangle3D getSurfaceBounds() {
        return surfaceBounds;
    }


    /**
        Builds the surface. First, this method calls
        retrieveSurface() to see if the surface needs to be
        rebuilt. If not, the surface is built by tiling the
        source texture and apply the shade map.
    */
    public void buildSurface() {

        if (retrieveSurface()) {
            return;
        }

        int width = (int)surfaceBounds.getWidth();
        int height = (int)surfaceBounds.getHeight();

        // create a new surface (buffer)
        newSurface(width, height);

        // builds the surface.
        // assume surface bounds and texture bounds are aligned
        // (possibly with different origins)
        Vector3D origin = sourceTextureBounds.getOrigin();
        Vector3D directionU = sourceTextureBounds.getDirectionU();
        Vector3D directionV = sourceTextureBounds.getDirectionV();

        Vector3D d = new Vector3D(surfaceBounds.getOrigin());
        d.subtract(origin);
        int startU = (int)((d.getDotProduct(directionU) -
            SURFACE_BORDER_SIZE));
        int startV = (int)((d.getDotProduct(directionV) -
            SURFACE_BORDER_SIZE));
        int offset = 0;
        int shadeMapOffsetU = SHADE_RES - SURFACE_BORDER_SIZE -
            startU;
        int shadeMapOffsetV = SHADE_RES - SURFACE_BORDER_SIZE -
            startV;

        for (int v=startV; v<startV + height; v++) {
            sourceTexture.setCurrRow(v);
            int u = startU;
            int amount = SURFACE_BORDER_SIZE;
            while (u < startU + width) {
                getInterpolatedShade(u + shadeMapOffsetU,
                    v + shadeMapOffsetV);

                // keep drawing until we need to recalculate
                // the interpolated shade. (every SHADE_RES pixels)
                int endU = Math.min(startU + width, u + amount);
                while (u < endU) {
                    buffer[offset++] =
                        sourceTexture.getColorCurrRow(u,
                             shadeValue >> SHADE_RES_SQ_BITS);
                    shadeValue+=shadeValueInc;
                    u++;
                }
                amount = SHADE_RES;
            }
        }

        // if the surface bounds is not aligned with the texture
        // bounds, use this (slower) code.
        /*Vector3D origin = sourceTextureBounds.getOrigin();
        Vector3D directionU = sourceTextureBounds.getDirectionU();
        Vector3D directionV = sourceTextureBounds.getDirectionV();

        Vector3D d = new Vector3D(surfaceBounds.getOrigin());
        d.subtract(origin);
        int initTextureU = (int)(SCALE *
            (d.getDotProduct(directionU) - SURFACE_BORDER_SIZE));
        int initTextureV = (int)(SCALE *
            (d.getDotProduct(directionV) - SURFACE_BORDER_SIZE));
        int textureDu1 = (int)(SCALE * directionU.getDotProduct(
            surfaceBounds.getDirectionV()));
        int textureDv1 = (int)(SCALE * directionV.getDotProduct(
            surfaceBounds.getDirectionV()));
        int textureDu2 = (int)(SCALE * directionU.getDotProduct(
            surfaceBounds.getDirectionU()));
        int textureDv2 = (int)(SCALE * directionV.getDotProduct(
            surfaceBounds.getDirectionU()));

        int shadeMapOffset = SHADE_RES - SURFACE_BORDER_SIZE;

        for (int v=0; v<height; v++) {
            int textureU = initTextureU;
            int textureV = initTextureV;

            for (int u=0; u<width; u++) {
                if (((u + shadeMapOffset) & SHADE_RES_MASK) == 0) {
                    getInterpolatedShade(u + shadeMapOffset,
                        v + shadeMapOffset);
                }
                buffer[offset++] = sourceTexture.getColor(
                        textureU >> SCALE_BITS,
                        textureV >> SCALE_BITS,
                        shadeValue >> SHADE_RES_SQ_BITS);
                    textureU+=textureDu2;
                    textureV+=textureDv2;
                    shadeValue+=shadeValueInc;

            }
            initTextureU+=textureDu1;
            initTextureV+=textureDv1;
        }*/
    }


    /**
        Gets the shade (from the shade map) for the  specified
        (u,v) location. The u and v values should be
        left-shifted by SHADE_RES_BITS, and the extra bits are
        used to interpolate between values. For an interpolation
        example, a location halfway between shade values 1 and 3
        would return 2.
    */
    public int getInterpolatedShade(int u, int v) {

        int fracU = u & SHADE_RES_MASK;
        int fracV = v & SHADE_RES_MASK;

        int offset = (u >> SHADE_RES_BITS) +
            ((v >> SHADE_RES_BITS) * shadeMapWidth);

        int shade00 = (SHADE_RES-fracV) * shadeMap[offset];
        int shade01 = fracV * shadeMap[offset + shadeMapWidth];
        int shade10 = (SHADE_RES-fracV) * shadeMap[offset + 1];
        int shade11 = fracV * shadeMap[offset + shadeMapWidth + 1];

        shadeValue = SHADE_RES_SQ/2 +
            (SHADE_RES-fracU) * shade00 +
            (SHADE_RES-fracU) * shade01 +
            fracU * shade10 +
            fracU * shade11;

        // the value to increment as u increments
        shadeValueInc = -shade00 - shade01 + shade10 + shade11;

        return shadeValue >> SHADE_RES_SQ_BITS;
    }



    /**
        Gets the shade (from the built shade map) for the
        specified (u,v) location.
    */
    public int getShade(int u, int v) {
        return shadeMap[u + v * shadeMapWidth];
    }


    /**
        Builds the shade map for this surface from the specified
        list of point lights and the ambiant light intensity.
    */
    public void buildShadeMap(List pointLights,
        float ambientLightIntensity)
    {

        Vector3D surfaceNormal = surfaceBounds.getNormal();

        int polyWidth = (int)surfaceBounds.getWidth() -
            SURFACE_BORDER_SIZE*2;
        int polyHeight = (int)surfaceBounds.getHeight() -
            SURFACE_BORDER_SIZE*2;
        // assume SURFACE_BORDER_SIZE is <= SHADE_RES
        shadeMapWidth = polyWidth / SHADE_RES + 4;
        shadeMapHeight = polyHeight / SHADE_RES + 4;
        shadeMap = new byte[shadeMapWidth * shadeMapHeight];

        // calculate the shade map origin
        Vector3D origin = new Vector3D(surfaceBounds.getOrigin());
        Vector3D du = new Vector3D(surfaceBounds.getDirectionU());
        Vector3D dv = new Vector3D(surfaceBounds.getDirectionV());
        du.multiply(SHADE_RES - SURFACE_BORDER_SIZE);
        dv.multiply(SHADE_RES - SURFACE_BORDER_SIZE);
        origin.subtract(du);
        origin.subtract(dv);

        // calculate the shade for each sample point.
        Vector3D point = new Vector3D();
        du.setTo(surfaceBounds.getDirectionU());
        dv.setTo(surfaceBounds.getDirectionV());
        du.multiply(SHADE_RES);
        dv.multiply(SHADE_RES);
        for (int v=0; v<shadeMapHeight; v++) {
            point.setTo(origin);
            for (int u=0; u<shadeMapWidth; u++) {
                shadeMap[u + v * shadeMapWidth] =
                    calcShade(surfaceNormal, point,
                    pointLights, ambientLightIntensity);
                point.add(du);
            }
            origin.add(dv);
        }
    }


    /**
        Determine the shade of a point on the polygon.
        This computes the Lambertian reflection for a point on
        the plane. Each point light has an intensity and a
        distance falloff value, but no specular reflection or
        shadows from other polygons are computed. The value
        returned is from 0 to ShadedTexture.MAX_LEVEL.
    */
    protected byte calcShade(Vector3D normal, Vector3D point,
        List pointLights, float ambientLightIntensity)
    {
        float intensity = 0;
        Vector3D directionToLight = new Vector3D();

        for (int i=0; i<pointLights.size(); i++) {
            PointLight3D light = (PointLight3D)pointLights.get(i);
            directionToLight.setTo(light);
            directionToLight.subtract(point);

            float distance = directionToLight.length();
            directionToLight.normalize();
            float lightIntensity = light.getIntensity(distance)
                * directionToLight.getDotProduct(normal);
            lightIntensity = Math.min(lightIntensity, 1);
            lightIntensity = Math.max(lightIntensity, 0);
            intensity += lightIntensity;
        }

        intensity = Math.min(intensity, 1);
        intensity = Math.max(intensity, 0);

        intensity+=ambientLightIntensity;

        intensity = Math.min(intensity, 1);
        intensity = Math.max(intensity, 0);
        int level = Math.round(intensity*ShadedTexture.MAX_LEVEL);
        return (byte)level;
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -