Skip to content

Commit e56a81e

Browse files
committed
Begin implementing atlaspack in
1 parent 5967081 commit e56a81e

File tree

2 files changed

+147
-43
lines changed

2 files changed

+147
-43
lines changed

index.js

+145-39
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
var transparent = require('opaque').transparent;
22
var tic = require('tic')();
3+
var createAtlas = require('atlaspack');
34

45
function Texture(opts) {
56
var self = this;
67
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);
911
this.texturePath = opts.texturePath || '/textures/';
1012
this.materialParams = opts.materialParams || {};
1113
this.materialType = opts.materialType || this.THREE.MeshLambertMaterial;
@@ -15,9 +17,24 @@ function Texture(opts) {
1517
this.applyTextureParams = opts.applyTextureParams || function(map) {
1618
map.magFilter = self.THREE.NearestFilter;
1719
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;
2021
}
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;
2138
}
2239
module.exports = Texture;
2340

@@ -26,47 +43,88 @@ Texture.prototype.load = function(names, opts) {
2643
opts = self._options(opts);
2744
if (!isArray(names)) names = [names];
2845
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));
4965
});
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;
5189
};
5290

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+
};
59107
}
60-
return this.materials.slice(index[0], index[1]);
108+
return self;
61109
};
62110

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+
/*
63120
Texture.prototype.find = function(name) {
64121
for (var i = 0; i < this.materials.length; i++) {
65122
if (name === this.materials[i].name) return i;
66123
}
67124
return -1;
68125
};
69126
127+
// TODO: Change this to find the type of a given name
70128
Texture.prototype.findIndex = function(name) {
71129
var index = this.find(name);
72130
for (var i = 0; i < this.materialIndex.length; i++) {
@@ -77,6 +135,7 @@ Texture.prototype.findIndex = function(name) {
77135
}
78136
return 0;
79137
};
138+
*/
80139

81140
Texture.prototype._expandName = function(name) {
82141
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) {
102161

103162
Texture.prototype.paint = function(geom) {
104163
var self = this;
164+
if (self._atlasuv === false) return;
165+
105166
geom.faces.forEach(function(face, i) {
167+
if (geom.faceVertexUvs[0].length < 1) return;
168+
106169
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];
108172

109173
// 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;
115183

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+
}
117207
});
208+
209+
geom.uvsNeedUpdate = true;
210+
return geom;
118211
};
119212

213+
// TODO: fix this to load onto the atlas
120214
Texture.prototype.sprite = function(name, w, h, cb) {
121215
var self = this;
122216
if (typeof w === 'function') { cb = w; w = null; }
@@ -144,6 +238,7 @@ Texture.prototype.sprite = function(name, w, h, cb) {
144238
return self;
145239
};
146240

241+
// TODO: fix this
147242
Texture.prototype.animate = function(names, delay) {
148243
var self = this;
149244
delay = delay || 1000;
@@ -170,6 +265,7 @@ Texture.prototype.tick = function(dt) {
170265
tic.tick(dt);
171266
};
172267

268+
// TODO: Deprecate this
173269
Texture.prototype._isTransparent = function(material) {
174270
if (!material.map) return;
175271
if (!material.map.image) return;
@@ -209,3 +305,13 @@ function defaults(obj) {
209305
});
210306
return obj;
211307
}
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+
}

package.json

+2-4
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,10 @@
2828
"start": "cd example && ../node_modules/.bin/browservefy world.js 8080 -- -d",
2929
"gh-pages": "cp -R ./example/* ./ && browserify world.js -o world.js"
3030
},
31-
"peerDependencies": {
32-
"three": "*"
33-
},
3431
"dependencies": {
3532
"opaque": "0.0.1",
36-
"tic": "~0.2.0"
33+
"tic": "~0.2.0",
34+
"atlaspack": "~0.2.1"
3735
},
3836
"devDependencies": {
3937
"voxel-engine": "~0.16.3",

0 commit comments

Comments
 (0)