0001: // ----------------------------------------------------------------------------
0002: //
0003: // noise.h - ノイズテクスチャの生成
0004: // 
0005: // Copyright (c) 2002 今給黎 隆 (imagire@nify.com)
0006: // All Rights Reserved.
0007: //
0008: // ----------------------------------------------------------------------------
0009: 
0010: #include <stdlib.h>
0011: #include <stdio.h>
0012: #include <math.h>
0013: #include <GL/glut.h>
0014: #include <GL/glext.h>
0015: #include <glh_extensions.h>
0016: #include "noise.h"
0017: 
0018: 
0019: #define SAFE_DELETE_ARRAY(p) if(p)delete[] (p);(p)=NULL
0020: 
0021: 
0022: // x を a から b の間に範囲を収める
0023: static float clamp(float x, float a, float b)
0024: {
0025:     return (x < a ? a : (x > b ? b : x));
0026: }
0027: // ---------------------------------------------------------------------------
0028: // コンストラクタ
0029: // ---------------------------------------------------------------------------
0030: CNoise::CNoise()
0031: {
0032:     m_pBuf = NULL;
0033: }
0034: // ---------------------------------------------------------------------------
0035: // デストラクタ
0036: // ---------------------------------------------------------------------------
0037: CNoise::~CNoise()
0038: {
0039:     SAFE_DELETE_ARRAY(m_pBuf);
0040: }
0041: // ---------------------------------------------------------------------------
0042: float CNoise::noise3D(int x, int y, int z)
0043: {
0044:     x = x & (m_size[0] - 1);
0045:     y = y & (m_size[1] - 1);
0046:     z = z & (m_size[2] - 1);
0047: 
0048:     return m_pBuf[(z*m_size[0]*m_size[1]) + (y*m_size[0]) + x];
0049: }
0050: // ---------------------------------------------------------------------------
0051: // OpenGL 3D テクスチャを作る
0052: // ---------------------------------------------------------------------------
0053: GLuint CNoise::CreateNoiseTexture3D(int w, int h, int d, float scale, float amp)
0054: {
0055:     int i, j, k;
0056: 
0057:     m_size[0] = w;
0058:     m_size[1] = h;
0059:     m_size[2] = d;
0060:     
0061:     // ノイズの種になる乱数の設定
0062:     SAFE_DELETE_ARRAY(m_pBuf);// すでに作られていたら、開放
0063:     m_pBuf = new float[w * h * d];
0064: 
0065:     // -1~1の範囲で3D空間全体に乱数を作る
0066:     float *ptr = m_pBuf;
0067:     for( i=0; i<w*h*d ; i++ ) {
0068:         *ptr++ = (2.0 * rand() / (float) RAND_MAX) - 1.0;
0069:     }
0070: 
0071:     GLubyte *img = new GLubyte[w * h * d];
0072: 
0073:     GLubyte *p = img;
0074:     for( i=0; i<d; i++ ) {
0075:         for( j=0; j<h; j++ ) {
0076:             for( k=0; k<w; k++ ) {
0077: 
0078:                 float fx = (k / scale) - 0.5;// 0.5 は、切捨てで問題が出ないような調整
0079:                 float fy = (j / scale) - 0.5;
0080:                 float fz = (i / scale) - 0.5;
0081: 
0082:                 float n;
0083:                 n = (noise3D((int)fx, (int)fy, (int)fz) + 1.0) * 0.5;
0084:                 n = clamp(n, 0.0, 1.0);
0085:                 *p++ = (GLubyte) (n * amp * 0xff);
0086:             }
0087:         }
0088:     }
0089: 
0090:     GLuint texid;
0091:     glGenTextures(1, &texid);
0092:     glBindTexture(GL_TEXTURE_3D, texid);
0093: 
0094:     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
0095:     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
0096:     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT);
0097:     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT);
0098:     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT);
0099:     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
0100: 
0101:     PFNGLTEXIMAGE3DEXTPROC glTexImage3DEXT;
0102:     glTexImage3DEXT = (PFNGLTEXIMAGE3DEXTPROC) wglGetProcAddress("glTexImage3DEXT");
0103:     if (glTexImage3DEXT != NULL)
0104:         glTexImage3DEXT(GL_TEXTURE_3D, 0, GL_LUMINANCE, w, h, d
0105:                         , 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, img);
0106: 
0107:     delete [] img;
0108:     
0109:     return texid;
0110: }
0111: