| 1 | # PySoy's materials.Textured class |
|---|
| 2 | # |
|---|
| 3 | # Copyright (C) 2006,2007,2008 PySoy Group |
|---|
| 4 | # |
|---|
| 5 | # This program is free software; you can redistribute it and/or modify |
|---|
| 6 | # it under the terms of the GNU Affero General Public License as published |
|---|
| 7 | # by the Free Software Foundation, either version 3 of the License, or |
|---|
| 8 | # (at your option) any later version. |
|---|
| 9 | # |
|---|
| 10 | # This program is distributed in the hope that it will be useful, |
|---|
| 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 13 | # GNU Affero General Public License for more details. |
|---|
| 14 | # |
|---|
| 15 | # You should have received a copy of the GNU Affero General Public License |
|---|
| 16 | # along with this program; if not, see http://www.gnu.org/licenses |
|---|
| 17 | # |
|---|
| 18 | # $Id: Material.pxi 1206 2008-03-22 18:42:26Z ArcRiley $ |
|---|
| 19 | |
|---|
| 20 | cdef class Textured(Material) : |
|---|
| 21 | '''soy.materials.Textured |
|---|
| 22 | |
|---|
| 23 | Textured materials support one or more basic textures in addition to the |
|---|
| 24 | standard Material colors (ambient, diffuse, specular, emission) which |
|---|
| 25 | are multiplied by the texture color to provide light-based shading. |
|---|
| 26 | |
|---|
| 27 | Currently .colormap and .glowmap are supported. |
|---|
| 28 | ''' |
|---|
| 29 | |
|---|
| 30 | ############################################################################ |
|---|
| 31 | # |
|---|
| 32 | # Python functions |
|---|
| 33 | # |
|---|
| 34 | |
|---|
| 35 | def __cinit__(self, |
|---|
| 36 | soy.colors.Color ambient=None, |
|---|
| 37 | soy.colors.Color diffuse=None, |
|---|
| 38 | soy.colors.Color specular=None, |
|---|
| 39 | soy.colors.Color emissive=None, |
|---|
| 40 | float shininess=0.5, |
|---|
| 41 | soy.textures.Texture colormap=None, |
|---|
| 42 | soy.textures.Texture glowmap=None) : |
|---|
| 43 | ###################################### |
|---|
| 44 | # |
|---|
| 45 | # import soy.colors locally for setting defaults |
|---|
| 46 | # |
|---|
| 47 | import soy.colors |
|---|
| 48 | # |
|---|
| 49 | ###################################### |
|---|
| 50 | # |
|---|
| 51 | # assign each color as argument or default |
|---|
| 52 | # |
|---|
| 53 | # None should never be stored in these values so that |
|---|
| 54 | # we can use ._rgba without testing each first in _render |
|---|
| 55 | # |
|---|
| 56 | if ambient : |
|---|
| 57 | self._ambient = ambient |
|---|
| 58 | else : |
|---|
| 59 | self._ambient = soy.colors.white |
|---|
| 60 | if diffuse : |
|---|
| 61 | self._diffuse = diffuse |
|---|
| 62 | else : |
|---|
| 63 | self._diffuse = soy.colors.white |
|---|
| 64 | if specular : |
|---|
| 65 | self._specular = specular |
|---|
| 66 | else : |
|---|
| 67 | self._specular = soy.colors.white |
|---|
| 68 | if emissive : |
|---|
| 69 | self._emissive = emissive |
|---|
| 70 | else : |
|---|
| 71 | self._emissive = soy.colors.black |
|---|
| 72 | # |
|---|
| 73 | ###################################### |
|---|
| 74 | # |
|---|
| 75 | # shininess is the size of the specularity dot |
|---|
| 76 | # |
|---|
| 77 | self._shininess = shininess |
|---|
| 78 | # |
|---|
| 79 | ###################################### |
|---|
| 80 | # |
|---|
| 81 | # store the texture arguments |
|---|
| 82 | # |
|---|
| 83 | self._colormap = colormap |
|---|
| 84 | self._glowmap = glowmap |
|---|
| 85 | # |
|---|
| 86 | ###################################### |
|---|
| 87 | |
|---|
| 88 | |
|---|
| 89 | ############################################################################ |
|---|
| 90 | # |
|---|
| 91 | # Properties |
|---|
| 92 | # |
|---|
| 93 | |
|---|
| 94 | property colormap : |
|---|
| 95 | '''soy.materials.Textured.colormap |
|---|
| 96 | |
|---|
| 97 | When a texture is assigned to this property a colormap texture is rendered. |
|---|
| 98 | |
|---|
| 99 | In OpenGL terms, this texture is set GL_MODULATE to the lit material color |
|---|
| 100 | which provides it's shading. Textures with an alpha component will be |
|---|
| 101 | translucent to the material's lit color, so to achieve actual translucency |
|---|
| 102 | this material's colors (ambient/diffuse) must also be translucent. |
|---|
| 103 | |
|---|
| 104 | Default is None (disabled). |
|---|
| 105 | ''' |
|---|
| 106 | |
|---|
| 107 | def __get__(self) : |
|---|
| 108 | return self._colormap |
|---|
| 109 | |
|---|
| 110 | def __set__(self, soy.textures.Texture _value) : |
|---|
| 111 | self._colormap = _value |
|---|
| 112 | |
|---|
| 113 | def __del__(self) : |
|---|
| 114 | self._colormap = None |
|---|
| 115 | |
|---|
| 116 | |
|---|
| 117 | property glowmap : |
|---|
| 118 | '''soy.materials.Textured.glowmap |
|---|
| 119 | |
|---|
| 120 | When a texture is assigned to this property a glowmap texture is rendered. |
|---|
| 121 | |
|---|
| 122 | In OpenGL terms, this texture is set GL_ADD. |
|---|
| 123 | |
|---|
| 124 | Default is None (disabled). |
|---|
| 125 | ''' |
|---|
| 126 | |
|---|
| 127 | def __get__(self) : |
|---|
| 128 | return self._glowmap |
|---|
| 129 | |
|---|
| 130 | def __set__(self, soy.textures.Texture _value) : |
|---|
| 131 | self._glowmap = _value |
|---|
| 132 | |
|---|
| 133 | def __del__(self) : |
|---|
| 134 | self._glowmap = None |
|---|
| 135 | |
|---|
| 136 | |
|---|
| 137 | ############################################################################ |
|---|
| 138 | # |
|---|
| 139 | # General C functions |
|---|
| 140 | # |
|---|
| 141 | cdef int _isTransparent(self): |
|---|
| 142 | # |
|---|
| 143 | # textures are only translucent to the colors, so if either lack |
|---|
| 144 | # translucency this check will return False |
|---|
| 145 | # |
|---|
| 146 | if self._colormap is not None and self._colormap._chans %2 == 1 : |
|---|
| 147 | return 0 |
|---|
| 148 | if self._ambient._rgba[3] != 1.0 : |
|---|
| 149 | return 1 |
|---|
| 150 | if self._diffuse._rgba[3] != 1.0 : |
|---|
| 151 | return 1 |
|---|
| 152 | return 0 |
|---|
| 153 | |
|---|
| 154 | |
|---|
| 155 | ############################################################################ |
|---|
| 156 | # |
|---|
| 157 | # WindowLoop functions |
|---|
| 158 | # |
|---|
| 159 | |
|---|
| 160 | cdef int _render(self, int _pass, float* _texcoords, float* _tslvs) nogil : |
|---|
| 161 | cdef int _i, _unit=0 |
|---|
| 162 | ###################################### |
|---|
| 163 | # |
|---|
| 164 | # Textured materials are 1-pass |
|---|
| 165 | # |
|---|
| 166 | if _pass == 0 : |
|---|
| 167 | #################################### |
|---|
| 168 | # |
|---|
| 169 | # number of shades, currently just 0 or 1 |
|---|
| 170 | # |
|---|
| 171 | if self._shades == 0 : |
|---|
| 172 | gl.glShadeModel(gl.GL_SMOOTH) |
|---|
| 173 | else : |
|---|
| 174 | gl.glShadeModel(gl.GL_FLAT) |
|---|
| 175 | # |
|---|
| 176 | #################################### |
|---|
| 177 | # |
|---|
| 178 | # lit material colors and settings |
|---|
| 179 | # |
|---|
| 180 | gl.glMaterialfv(gl.GL_FRONT, gl.GL_AMBIENT, self._ambient._rgba) |
|---|
| 181 | gl.glMaterialfv(gl.GL_FRONT, gl.GL_DIFFUSE, self._diffuse._rgba) |
|---|
| 182 | gl.glMaterialfv(gl.GL_FRONT, gl.GL_SPECULAR, self._specular._rgba) |
|---|
| 183 | gl.glMaterialfv(gl.GL_FRONT, gl.GL_EMISSION, self._emissive._rgba) |
|---|
| 184 | gl.glMaterialf (gl.GL_FRONT, gl.GL_SHININESS, self._shininess) |
|---|
| 185 | # |
|---|
| 186 | #################################### |
|---|
| 187 | # |
|---|
| 188 | # render the colormap |
|---|
| 189 | # |
|---|
| 190 | if self._colormap is not None : |
|---|
| 191 | gl.glActiveTexture(_texunits[_unit]) |
|---|
| 192 | gl.glEnableClientState(gl.GL_TEXTURE_COORD_ARRAY) |
|---|
| 193 | gl.glTexCoordPointer(3, gl.GL_FLOAT, 48, _texcoords) |
|---|
| 194 | gl.glTexEnvi(gl.GL_TEXTURE_ENV, gl.GL_TEXTURE_ENV_MODE, gl.GL_MODULATE) |
|---|
| 195 | self._colormap._enable() |
|---|
| 196 | _unit += 1 |
|---|
| 197 | # |
|---|
| 198 | #################################### |
|---|
| 199 | # |
|---|
| 200 | # render the glowmap |
|---|
| 201 | # |
|---|
| 202 | if self._glowmap is not None : |
|---|
| 203 | gl.glActiveTexture(_texunits[_unit]) |
|---|
| 204 | gl.glEnableClientState(gl.GL_TEXTURE_COORD_ARRAY) |
|---|
| 205 | gl.glTexCoordPointer(3, gl.GL_FLOAT, 48, _texcoords) |
|---|
| 206 | gl.glTexEnvi(gl.GL_TEXTURE_ENV, gl.GL_TEXTURE_ENV_MODE, gl.GL_ADD) |
|---|
| 207 | gl.glEnable(gl.GL_BLEND) |
|---|
| 208 | gl.glBlendFunc(gl.GL_ONE, gl.GL_ONE) |
|---|
| 209 | self._glowmap._enable() |
|---|
| 210 | _unit += 1 |
|---|
| 211 | # |
|---|
| 212 | #################################### |
|---|
| 213 | # |
|---|
| 214 | # disable what we're not using and return |
|---|
| 215 | # |
|---|
| 216 | # |
|---|
| 217 | for _i from _unit <= _i < 4 : |
|---|
| 218 | gl.glActiveTexture(_texunits[_i]) |
|---|
| 219 | gl.glDisableClientState(gl.GL_TEXTURE_COORD_ARRAY) |
|---|
| 220 | return 1 |
|---|
| 221 | # |
|---|
| 222 | ###################################### |
|---|
| 223 | # |
|---|
| 224 | # disable textures from last pass |
|---|
| 225 | # |
|---|
| 226 | else : |
|---|
| 227 | _unit = 0 |
|---|
| 228 | if self._colormap is not None : |
|---|
| 229 | gl.glActiveTexture(_texunits[_unit]) |
|---|
| 230 | self._colormap._disable() |
|---|
| 231 | _unit += 1 |
|---|
| 232 | if self._glowmap is not None : |
|---|
| 233 | gl.glActiveTexture(_texunits[_unit]) |
|---|
| 234 | self._glowmap._disable() |
|---|
| 235 | return 0 |
|---|
| 236 | # |
|---|
| 237 | ###################################### |
|---|