1
1
var transparent = require ( 'opaque' ) . transparent ;
2
2
var tic = require ( 'tic' ) ( ) ;
3
+ var createAtlas = require ( 'atlaspack' ) ;
3
4
4
5
function Texture ( opts ) {
5
6
var self = this ;
6
7
if ( ! ( this instanceof Texture ) ) return new Texture ( opts || { } ) ;
7
- this . THREE = opts . THREE || require ( 'three' ) ;
8
- this . materials = [ ] ;
8
+ this . game = opts . game ;
9
+ this . THREE = this . game . THREE ;
10
+ this . materials = Object . create ( null ) ;
9
11
this . texturePath = opts . texturePath || '/textures/' ;
10
12
this . materialParams = opts . materialParams || { } ;
11
13
this . materialType = opts . materialType || this . THREE . MeshLambertMaterial ;
@@ -15,9 +17,24 @@ function Texture(opts) {
15
17
this . applyTextureParams = opts . applyTextureParams || function ( map ) {
16
18
map . magFilter = self . THREE . NearestFilter ;
17
19
map . minFilter = self . THREE . LinearMipMapLinearFilter ;
18
- map . wrapT = self . THREE . RepeatWrapping ;
19
- map . wrapS = self . THREE . RepeatWrapping ;
20
+ //map.wrapT = map.wrapS = self.THREE.RepeatWrapping;
20
21
}
22
+
23
+ // create a canvas for the texture atlas
24
+ this . _canvas = document . createElement ( 'canvas' ) ;
25
+ this . _canvas . width = 64 ;
26
+ this . _canvas . height = 64 ;
27
+
28
+ // create core atlas and texture
29
+ this . _atlas = createAtlas ( this . _canvas ) ;
30
+ this . _atlasuv = false ;
31
+ this . _texture = new this . THREE . Texture ( this . _canvas ) ;
32
+ self . applyTextureParams . call ( self , this . _texture ) ;
33
+
34
+ // create core material for easy application to meshes
35
+ this . material = new this . materialType ( this . materialParams ) ;
36
+ this . material . map = this . _texture ;
37
+ this . material . transparent = true ;
21
38
}
22
39
module . exports = Texture ;
23
40
@@ -26,47 +43,88 @@ Texture.prototype.load = function(names, opts) {
26
43
opts = self . _options ( opts ) ;
27
44
if ( ! isArray ( names ) ) names = [ names ] ;
28
45
if ( ! hasSubArray ( names ) ) names = [ names ] ;
29
- return [ ] . concat . apply ( [ ] , names . map ( function ( name ) {
30
- name = self . _expandName ( name ) ;
31
- self . materialIndex . push ( [ self . materials . length , self . materials . length + name . length ] ) ;
32
- return name . map ( function ( n ) {
33
- if ( n instanceof self . THREE . Texture ) {
34
- var map = n ;
35
- n = n . name ;
36
- } else if ( typeof n === 'string' ) {
37
- var map = self . THREE . ImageUtils . loadTexture ( self . texturePath + ext ( n ) ) ;
38
- } else {
39
- var map = new self . THREE . Texture ( n ) ;
40
- n = map . name ;
41
- }
42
- self . applyTextureParams . call ( self , map ) ;
43
- var mat = new opts . materialType ( opts . materialParams ) ;
44
- mat . map = map ;
45
- mat . name = n ;
46
- if ( opts . transparent == null ) self . _isTransparent ( mat ) ;
47
- self . materials . push ( mat ) ;
48
- return mat ;
46
+
47
+ // create materials
48
+ var created = Object . create ( null ) ;
49
+ function createMaterial ( name , type ) {
50
+ if ( created [ name ] ) return created [ name ] ;
51
+ var mat = new opts . materialType ( opts . materialParams ) ;
52
+ mat . map = self . _texture ;
53
+ mat . name = name ;
54
+ mat . transparent = true ;
55
+ return created [ name ] = mat ;
56
+ }
57
+
58
+ // expand and create materials object
59
+ var type = Object . keys ( self . materials ) . length ;
60
+ var materialSlice = Object . create ( null ) ;
61
+ names . map ( self . _expandName ) . forEach ( function ( group ) {
62
+ var materials = [ ] ;
63
+ group . forEach ( function ( name ) {
64
+ materials . push ( createMaterial ( name , type ) ) ;
49
65
} ) ;
50
- } ) ) ;
66
+ materialSlice [ type ] = self . materials [ type ] = materials ;
67
+ type ++ ;
68
+ } ) ;
69
+
70
+ // load onto the texture atlas
71
+ self . _atlasuv = false ;
72
+ var load = Object . create ( null ) ;
73
+ Object . keys ( materialSlice ) . forEach ( function ( k ) {
74
+ materialSlice [ k ] . forEach ( function ( mat ) {
75
+ load [ mat . name ] = true ;
76
+ } ) ;
77
+ } ) ;
78
+ each ( Object . keys ( load ) , self . pack . bind ( self ) , function ( ) {
79
+ self . _atlasuv = self . _atlas . uv ( ) ;
80
+ self . _texture . needsUpdate = true ;
81
+ self . material . needsUpdate = true ;
82
+ //window.open(self._canvas.toDataURL());
83
+ Object . keys ( self . game . voxels . meshes ) . forEach ( function ( pos ) {
84
+ self . game . voxels . meshes [ pos ] . geometry = self . paint ( self . game . voxels . meshes [ pos ] . geometry ) ;
85
+ } ) ;
86
+ } ) ;
87
+
88
+ return materialSlice ;
51
89
} ;
52
90
53
- Texture . prototype . get = function ( index ) {
54
- if ( index == null ) return this . materials ;
55
- if ( typeof index === 'number' ) {
56
- index = this . materialIndex [ index ] ;
57
- } else {
58
- index = this . materialIndex [ this . findIndex ( index ) - 1 ] ;
91
+ Texture . prototype . pack = function ( name , done ) {
92
+ var self = this ;
93
+ function pack ( img ) {
94
+ var node = self . _atlas . pack ( img ) ;
95
+ if ( node === false ) {
96
+ self . _atlas = self . _atlas . expand ( img ) ;
97
+ }
98
+ done ( ) ;
99
+ }
100
+ if ( typeof name === 'string' ) {
101
+ var img = new Image ( ) ;
102
+ img . src = self . texturePath + ext ( name ) ;
103
+ img . id = name ;
104
+ img . onload = function ( ) {
105
+ pack ( img ) ;
106
+ } ;
59
107
}
60
- return this . materials . slice ( index [ 0 ] , index [ 1 ] ) ;
108
+ return self ;
61
109
} ;
62
110
111
+ Texture . prototype . get = function ( type ) {
112
+ var self = this ;
113
+ if ( type ) return self . materials [ type ] ;
114
+ return [ ] . concat . apply ( [ ] , Object . keys ( self . materials ) . map ( function ( k ) {
115
+ return self . materials [ k ] ;
116
+ } ) ) ;
117
+ } ;
118
+
119
+ /*
63
120
Texture.prototype.find = function(name) {
64
121
for (var i = 0; i < this.materials.length; i++) {
65
122
if (name === this.materials[i].name) return i;
66
123
}
67
124
return -1;
68
125
};
69
126
127
+ // TODO: Change this to find the type of a given name
70
128
Texture.prototype.findIndex = function(name) {
71
129
var index = this.find(name);
72
130
for (var i = 0; i < this.materialIndex.length; i++) {
@@ -77,6 +135,7 @@ Texture.prototype.findIndex = function(name) {
77
135
}
78
136
return 0;
79
137
};
138
+ */
80
139
81
140
Texture . prototype . _expandName = function ( name ) {
82
141
if ( name . top ) return [ name . back , name . front , name . top , name . bottom , name . left , name . right ] ;
@@ -102,21 +161,56 @@ Texture.prototype._options = function(opts) {
102
161
103
162
Texture . prototype . paint = function ( geom ) {
104
163
var self = this ;
164
+ if ( self . _atlasuv === false ) return ;
165
+
105
166
geom . faces . forEach ( function ( face , i ) {
167
+ if ( geom . faceVertexUvs [ 0 ] . length < 1 ) return ;
168
+
106
169
var index = Math . floor ( face . color . b * 255 + face . color . g * 255 * 255 + face . color . r * 255 * 255 * 255 ) ;
107
- index = self . materialIndex [ Math . floor ( Math . max ( 0 , index - 1 ) % self . materialIndex . length ) ] [ 0 ] ;
170
+ var materials = self . materials [ index - 1 ] ;
171
+ if ( ! materials ) materials = self . materials [ 0 ] ;
108
172
109
173
// BACK, FRONT, TOP, BOTTOM, LEFT, RIGHT
110
- if ( face . normal . z === 1 ) index += 1 ;
111
- else if ( face . normal . y === 1 ) index += 2 ;
112
- else if ( face . normal . y === - 1 ) index += 3 ;
113
- else if ( face . normal . x === - 1 ) index += 4 ;
114
- else if ( face . normal . x === 1 ) index += 5 ;
174
+ var name = materials [ 0 ] . name ;
175
+ if ( face . normal . z === 1 ) name = materials [ 1 ] . name ;
176
+ else if ( face . normal . y === 1 ) name = materials [ 2 ] . name ;
177
+ else if ( face . normal . y === - 1 ) name = materials [ 3 ] . name ;
178
+ else if ( face . normal . x === - 1 ) name = materials [ 4 ] . name ;
179
+ else if ( face . normal . x === 1 ) name = materials [ 5 ] . name ;
180
+
181
+ var atlasuv = self . _atlasuv [ name ] ;
182
+ if ( ! atlasuv ) return ;
115
183
116
- face . materialIndex = index ;
184
+ // 0 -- 1
185
+ // | |
186
+ // 3 -- 2
187
+ // faces on these meshes are flipped vertically, so we map in reverse
188
+ if ( face . normal . z === - 1 || face . normal . x === 1 ) {
189
+ geom . faceVertexUvs [ 0 ] [ i ] [ 0 ] . x = atlasuv [ 2 ] [ 0 ] ;
190
+ geom . faceVertexUvs [ 0 ] [ i ] [ 0 ] . y = 1 - atlasuv [ 2 ] [ 1 ] ;
191
+ geom . faceVertexUvs [ 0 ] [ i ] [ 1 ] . x = atlasuv [ 1 ] [ 0 ] ;
192
+ geom . faceVertexUvs [ 0 ] [ i ] [ 1 ] . y = 1 - atlasuv [ 1 ] [ 1 ] ;
193
+ geom . faceVertexUvs [ 0 ] [ i ] [ 2 ] . x = atlasuv [ 0 ] [ 0 ] ;
194
+ geom . faceVertexUvs [ 0 ] [ i ] [ 2 ] . y = 1 - atlasuv [ 0 ] [ 1 ] ;
195
+ geom . faceVertexUvs [ 0 ] [ i ] [ 3 ] . x = atlasuv [ 3 ] [ 0 ] ;
196
+ geom . faceVertexUvs [ 0 ] [ i ] [ 3 ] . y = 1 - atlasuv [ 3 ] [ 1 ] ;
197
+ } else {
198
+ geom . faceVertexUvs [ 0 ] [ i ] [ 0 ] . x = atlasuv [ 3 ] [ 0 ] ;
199
+ geom . faceVertexUvs [ 0 ] [ i ] [ 0 ] . y = 1 - atlasuv [ 3 ] [ 1 ] ;
200
+ geom . faceVertexUvs [ 0 ] [ i ] [ 1 ] . x = atlasuv [ 2 ] [ 0 ] ;
201
+ geom . faceVertexUvs [ 0 ] [ i ] [ 1 ] . y = 1 - atlasuv [ 2 ] [ 1 ] ;
202
+ geom . faceVertexUvs [ 0 ] [ i ] [ 2 ] . x = atlasuv [ 1 ] [ 0 ] ;
203
+ geom . faceVertexUvs [ 0 ] [ i ] [ 2 ] . y = 1 - atlasuv [ 1 ] [ 1 ] ;
204
+ geom . faceVertexUvs [ 0 ] [ i ] [ 3 ] . x = atlasuv [ 0 ] [ 0 ] ;
205
+ geom . faceVertexUvs [ 0 ] [ i ] [ 3 ] . y = 1 - atlasuv [ 0 ] [ 1 ] ;
206
+ }
117
207
} ) ;
208
+
209
+ geom . uvsNeedUpdate = true ;
210
+ return geom ;
118
211
} ;
119
212
213
+ // TODO: fix this to load onto the atlas
120
214
Texture . prototype . sprite = function ( name , w , h , cb ) {
121
215
var self = this ;
122
216
if ( typeof w === 'function' ) { cb = w ; w = null ; }
@@ -144,6 +238,7 @@ Texture.prototype.sprite = function(name, w, h, cb) {
144
238
return self ;
145
239
} ;
146
240
241
+ // TODO: fix this
147
242
Texture . prototype . animate = function ( names , delay ) {
148
243
var self = this ;
149
244
delay = delay || 1000 ;
@@ -170,6 +265,7 @@ Texture.prototype.tick = function(dt) {
170
265
tic . tick ( dt ) ;
171
266
} ;
172
267
268
+ // TODO: Deprecate this
173
269
Texture . prototype . _isTransparent = function ( material ) {
174
270
if ( ! material . map ) return ;
175
271
if ( ! material . map . image ) return ;
@@ -209,3 +305,13 @@ function defaults(obj) {
209
305
} ) ;
210
306
return obj ;
211
307
}
308
+
309
+ function each ( arr , it , done ) {
310
+ var count = 0 ;
311
+ arr . forEach ( function ( a ) {
312
+ it ( a , function ( ) {
313
+ count ++ ;
314
+ if ( count >= arr . length ) done ( ) ;
315
+ } ) ;
316
+ } ) ;
317
+ }
0 commit comments