Package org.lwjgl.util.glu

Source Code of org.lwjgl.util.glu.MipMap

/*
* Copyright (c) 2002-2008 LWJGL Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
*   notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
*   notice, this list of conditions and the following disclaimer in the
*   documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'LWJGL' nor the names of
*   its contributors may be used to endorse or promote products derived
*   from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.lwjgl.util.glu;

import java.nio.ByteBuffer;

import org.lwjgl.BufferUtils;

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.util.glu.GLU.*;

/**
* MipMap.java
*
*
* Created 11-jan-2004
* @author Erik Duijs
*/
public class MipMap extends Util {

  /**
   * Method gluBuild2DMipmaps
   *
   * @param target
   * @param components
   * @param width
   * @param height
   * @param format
   * @param type
   * @param data
   * @return int
   */
  public static int gluBuild2DMipmaps(final int target,
                                      final int components, final int width, final int height,
                                      final int format, final int type, final ByteBuffer data) {
    if ( width < 1 || height < 1 ) return GLU_INVALID_VALUE;

    final int bpp = bytesPerPixel(format, type);
    if ( bpp == 0 )
      return GLU_INVALID_ENUM;

    final int maxSize = glGetIntegerv(GL_MAX_TEXTURE_SIZE);

    int w = nearestPower(width);
    if ( w > maxSize )
      w = maxSize;

    int h = nearestPower(height);
    if ( h > maxSize )
      h = maxSize;

    // Get current glPixelStore state
    PixelStoreState pss = new PixelStoreState();

    // set pixel packing
    glPixelStorei(GL_PACK_ROW_LENGTH, 0);
    glPixelStorei(GL_PACK_ALIGNMENT, 1);
    glPixelStorei(GL_PACK_SKIP_ROWS, 0);
    glPixelStorei(GL_PACK_SKIP_PIXELS, 0);

    ByteBuffer image;
    int retVal = 0;
    boolean done = false;

    if ( w != width || h != height ) {
      // must rescale image to get "top" mipmap texture image
      image = BufferUtils.createByteBuffer((w + 4) * h * bpp);
      int error = gluScaleImage(format, width, height, type, data, w, h, type, image);
      if ( error != 0 ) {
        retVal = error;
        done = true;
      }

      /* set pixel unpacking */
      glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
      glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
      glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
      glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
    } else {
      image = data;
    }

    ByteBuffer bufferA = null;
    ByteBuffer bufferB = null;

    int level = 0;
    while ( !done ) {
      if (image != data) {
        /* set pixel unpacking */
        glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
        glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
      }

      glTexImage2D(target, level, components, w, h, 0, format, type, image);

      if ( w == 1 && h == 1 )
        break;

      final int newW = (w < 2) ? 1 : w >> 1;
      final int newH = (h < 2) ? 1 : h >> 1;

      final ByteBuffer newImage;

      if ( bufferA == null )
        newImage = (bufferA = BufferUtils.createByteBuffer((newW + 4) * newH * bpp));
      else if ( bufferB == null )
        newImage = (bufferB = BufferUtils.createByteBuffer((newW + 4) * newH * bpp));
      else
        newImage = bufferB;

      int error = gluScaleImage(format, w, h, type, image, newW, newH, type, newImage);
      if ( error != 0 ) {
        retVal = error;
        done = true;
      }

      image = newImage;
      if ( bufferB != null )
        bufferB = bufferA;

      w = newW;
      h = newH;
      level++;
    }

    // Restore original glPixelStore state
    pss.save();

    return retVal;
  }

  /**
   * Method gluScaleImage.
   * @param format
   * @param widthIn
   * @param heightIn
   * @param typein
   * @param dataIn
   * @param widthOut
   * @param heightOut
   * @param typeOut
   * @param dataOut
   * @return int
   */
  public static int gluScaleImage(int format,
                                  int widthIn, int heightIn, int typein, ByteBuffer dataIn,
                                  int widthOut, int heightOut, int typeOut, ByteBuffer dataOut) {

    final int components = compPerPix(format);
    if ( components == -1 )
      return GLU_INVALID_ENUM;

    int i, j, k;
    float[] tempIn, tempOut;
    float sx, sy;
    int sizein, sizeout;
    int rowstride, rowlen;

    // temp image data
    tempIn = new float[widthIn * heightIn * components];
    tempOut = new float[widthOut * heightOut * components];

    // Determine bytes per input type
    switch ( typein ) {
      case GL_UNSIGNED_BYTE:
        sizein = 1;
        break;
      case GL_FLOAT:
        sizein = 4;
        break;
      default:
        return GL_INVALID_ENUM;
    }

    // Determine bytes per output type
    switch ( typeOut ) {
      case GL_UNSIGNED_BYTE:
        sizeout = 1;
        break;
      case GL_FLOAT:
        sizeout = 4;
        break;
      default:
        return GL_INVALID_ENUM;
    }

    // Get glPixelStore state
    PixelStoreState pss = new PixelStoreState();

    //Unpack the pixel data and convert to floating point
    if ( pss.unpackRowLength > 0 )
      rowlen = pss.unpackRowLength;
    else
      rowlen = widthIn;

    if ( sizein >= pss.unpackAlignment )
      rowstride = components * rowlen;
    else
      rowstride = pss.unpackAlignment / sizein * ceil(components * rowlen * sizein, pss.unpackAlignment);

    switch ( typein ) {
      case GL_UNSIGNED_BYTE:
        k = 0;
        dataIn.rewind();
        for ( i = 0; i < heightIn; i++ ) {
          int ubptr = i * rowstride + pss.unpackSkipRows * rowstride + pss.unpackSkipPixels * components;
          for ( j = 0; j < widthIn * components; j++ ) {
            tempIn[k++] = dataIn.get(ubptr++) & 0xff;
          }
        }
        break;
      case GL_FLOAT:
        k = 0;
        dataIn.rewind();
        for ( i = 0; i < heightIn; i++ )
        {
          int fptr = 4 * (i * rowstride + pss.unpackSkipRows * rowstride + pss.unpackSkipPixels * components);
          for ( j = 0; j < widthIn * components; j++ )
          {
            tempIn[k++] = dataIn.getFloat(fptr);
            fptr += 4;
          }
        }
        break;
      default:
        return GLU_INVALID_ENUM;
    }

    // Do scaling
    sx = (float)widthIn / (float)widthOut;
    sy = (float)heightIn / (float)heightOut;

    float[] c = new float[components];
    int src, dst;

    for ( int iy = 0; iy < heightOut; iy++ ) {
      for ( int ix = 0; ix < widthOut; ix++ ) {
        int x0 = (int)(ix * sx);
        int x1 = (int)((ix + 1) * sx);
        int y0 = (int)(iy * sy);
        int y1 = (int)((iy + 1) * sy);

        int readPix = 0;

        // reset weighted pixel
        for ( int ic = 0; ic < components; ic++ ) {
          c[ic] = 0;
        }

        // create weighted pixel
        for ( int ix0 = x0; ix0 < x1; ix0++ ) {
          for ( int iy0 = y0; iy0 < y1; iy0++ ) {

            src = (iy0 * widthIn + ix0) * components;

            for ( int ic = 0; ic < components; ic++ ) {
              c[ic] += tempIn[src + ic];
            }

            readPix++;
          }
        }

        // store weighted pixel
        dst = (iy * widthOut + ix) * components;

        if ( readPix == 0 ) {
          // Image is sized up, caused by non power of two texture as input
          src = (y0 * widthIn + x0) * components;
          for ( int ic = 0; ic < components; ic++ ) {
            tempOut[dst++] = tempIn[src + ic];
          }
        } else {
          // sized down
          for ( k = 0; k < components; k++ ) {
            tempOut[dst++] = c[k] / readPix;
          }
        }
      }
    }


    // Convert temp output
    if ( pss.packRowLength > 0 )
      rowlen = pss.packRowLength;
    else
      rowlen = widthOut;

    if ( sizeout >= pss.packAlignment )
      rowstride = components * rowlen;
    else
      rowstride = pss.packAlignment / sizeout * ceil(components * rowlen * sizeout, pss.packAlignment);

    switch ( typeOut ) {
      case GL_UNSIGNED_BYTE:
        k = 0;
        for ( i = 0; i < heightOut; i++ ) {
          int ubptr = i * rowstride + pss.packSkipRows * rowstride + pss.packSkipPixels * components;

          for ( j = 0; j < widthOut * components; j++ ) {
            dataOut.put(ubptr++, (byte)tempOut[k++]);
          }
        }
        break;
      case GL_FLOAT:
        k = 0;
        for ( i = 0; i < heightOut; i++ ) {
          int fptr = 4 * (i * rowstride + pss.unpackSkipRows * rowstride + pss.unpackSkipPixels * components);

          for ( j = 0; j < widthOut * components; j++ ) {
            dataOut.putFloat(fptr, tempOut[k++]);
            fptr += 4;
          }
        }
        break;
      default:
        return GLU_INVALID_ENUM;
    }

    return 0;
  }
}
TOP

Related Classes of org.lwjgl.util.glu.MipMap

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.