@erik9994857/cag 2.0.0 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/api/model-api.js +36 -2
- package/src/cli/cag-cli.js +21 -11
- package/src/runtime/electron-runner.js +158 -74
package/package.json
CHANGED
package/src/api/model-api.js
CHANGED
|
@@ -72,14 +72,26 @@ class ModelAPI {
|
|
|
72
72
|
valid: false
|
|
73
73
|
};
|
|
74
74
|
|
|
75
|
+
let embeddedTextures = [];
|
|
76
|
+
|
|
75
77
|
if (resource.model) {
|
|
76
78
|
const modelData = this.parseBBModel(resource.model);
|
|
77
79
|
result.geometry = modelData.geometry;
|
|
78
80
|
result.uvMappings = modelData.uvMappings;
|
|
81
|
+
embeddedTextures = modelData.embeddedTextures || [];
|
|
79
82
|
}
|
|
80
83
|
|
|
81
84
|
if (resource.texture) {
|
|
82
85
|
result.texture = this.loadTexture(resource.texture);
|
|
86
|
+
} else if (embeddedTextures.length > 0) {
|
|
87
|
+
result.texture = {
|
|
88
|
+
path: null,
|
|
89
|
+
width: result.geometry ? result.geometry.resolution.width : 16,
|
|
90
|
+
height: result.geometry ? result.geometry.resolution.height : 16,
|
|
91
|
+
format: "png",
|
|
92
|
+
size: 0,
|
|
93
|
+
dataURL: embeddedTextures[0].source
|
|
94
|
+
};
|
|
83
95
|
}
|
|
84
96
|
|
|
85
97
|
if (result.geometry && result.texture && result.uvMappings) {
|
|
@@ -148,7 +160,21 @@ class ModelAPI {
|
|
|
148
160
|
geometry.bones = this.parseOutliner(data.outliner);
|
|
149
161
|
}
|
|
150
162
|
|
|
151
|
-
|
|
163
|
+
const embeddedTextures = [];
|
|
164
|
+
if (data.textures && Array.isArray(data.textures)) {
|
|
165
|
+
for (let i = 0; i < data.textures.length; i++) {
|
|
166
|
+
const tex = data.textures[i];
|
|
167
|
+
if (tex.source) {
|
|
168
|
+
embeddedTextures.push({
|
|
169
|
+
index: tex.id !== undefined ? tex.id : i,
|
|
170
|
+
name: tex.name || "texture_" + i,
|
|
171
|
+
source: tex.source
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return { geometry, uvMappings, embeddedTextures };
|
|
152
178
|
}
|
|
153
179
|
|
|
154
180
|
parseOutliner(outliner) {
|
|
@@ -191,12 +217,16 @@ class ModelAPI {
|
|
|
191
217
|
}
|
|
192
218
|
}
|
|
193
219
|
|
|
220
|
+
const base64 = buffer.toString("base64");
|
|
221
|
+
const mime = ext === ".png" ? "image/png" : (ext === ".jpg" || ext === ".jpeg") ? "image/jpeg" : "image/" + ext.substring(1);
|
|
222
|
+
|
|
194
223
|
return {
|
|
195
224
|
path: filePath,
|
|
196
225
|
width: width,
|
|
197
226
|
height: height,
|
|
198
227
|
format: ext.substring(1),
|
|
199
|
-
size: buffer.length
|
|
228
|
+
size: buffer.length,
|
|
229
|
+
dataURL: "data:" + mime + ";base64," + base64
|
|
200
230
|
};
|
|
201
231
|
}
|
|
202
232
|
|
|
@@ -269,6 +299,10 @@ class ModelAPI {
|
|
|
269
299
|
isModelLoaded(name) {
|
|
270
300
|
return this.loadedModels[name] !== undefined;
|
|
271
301
|
}
|
|
302
|
+
|
|
303
|
+
getLoadedModels() {
|
|
304
|
+
return this.loadedModels;
|
|
305
|
+
}
|
|
272
306
|
}
|
|
273
307
|
|
|
274
308
|
module.exports = ModelAPI;
|
package/src/cli/cag-cli.js
CHANGED
|
@@ -72,9 +72,6 @@ class CagCLI {
|
|
|
72
72
|
|
|
73
73
|
this.printLine("Project: " + engine.getInfo().ID);
|
|
74
74
|
this.printLine("Version: " + engine.getInfo().version);
|
|
75
|
-
this.printLine("Dependencies: " + engine.getDependencies().join(", "));
|
|
76
|
-
this.printLine("Code files: " + engine.getCodeFiles().length);
|
|
77
|
-
this.printLine("Resources: " + Object.keys(engine.getResourceMap()).length);
|
|
78
75
|
this.printLine("");
|
|
79
76
|
|
|
80
77
|
const CagcParser = require("../parser/cagc-parser");
|
|
@@ -91,26 +88,39 @@ class CagCLI {
|
|
|
91
88
|
const fileName = path.basename(filePath);
|
|
92
89
|
const content = fs.readFileSync(filePath, "utf-8");
|
|
93
90
|
|
|
94
|
-
this.printLine("Executing: " + fileName);
|
|
95
|
-
|
|
96
91
|
const parsed = cagcParser.parse(content, fileName);
|
|
97
92
|
const result = executor.execute(parsed);
|
|
98
93
|
|
|
99
94
|
if (result.errors && result.errors.length > 0) {
|
|
100
95
|
for (let j = 0; j < result.errors.length; j++) {
|
|
101
|
-
this.printError(
|
|
96
|
+
this.printError(result.errors[j]);
|
|
102
97
|
}
|
|
103
98
|
}
|
|
99
|
+
}
|
|
104
100
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
101
|
+
const registry = executor.getRegistry();
|
|
102
|
+
if (registry.has("Model.API")) {
|
|
103
|
+
const modelAPI = registry.get("Model.API");
|
|
104
|
+
const loadedModels = modelAPI.getLoadedModels();
|
|
105
|
+
const modelNames = Object.keys(loadedModels);
|
|
106
|
+
if (modelNames.length > 0) {
|
|
107
|
+
this.printLine("Reading UV mapping...");
|
|
108
|
+
for (let i = 0; i < modelNames.length; i++) {
|
|
109
|
+
const name = modelNames[i];
|
|
110
|
+
const model = loadedModels[name];
|
|
111
|
+
if (model && model.valid && model.texture) {
|
|
112
|
+
this.printSuccess("Auto Mapped Custom UV for " + name);
|
|
113
|
+
} else if (model && model.valid) {
|
|
114
|
+
this.printLine(" " + name + " (no texture paired)");
|
|
115
|
+
} else {
|
|
116
|
+
this.printError("Failed to map UV for " + name);
|
|
117
|
+
}
|
|
108
118
|
}
|
|
119
|
+
this.printLine("");
|
|
109
120
|
}
|
|
110
121
|
}
|
|
111
122
|
|
|
112
|
-
this.printLine("");
|
|
113
|
-
this.printSuccess("Execution complete. Launching game...");
|
|
123
|
+
this.printLine("Launching game...");
|
|
114
124
|
this.printLine("");
|
|
115
125
|
|
|
116
126
|
const settings = ElectronRunner.extractSettings(executor);
|
|
@@ -18,35 +18,37 @@ ElectronRunner.prototype.run = function () {
|
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
ElectronRunner.prototype.ensureDirectories = function () {
|
|
21
|
-
if (fs.existsSync(this.tempDir)) {
|
|
22
|
-
this.removeDirectory(this.tempDir);
|
|
23
|
-
}
|
|
24
21
|
fs.mkdirSync(this.tempDir, { recursive: true });
|
|
25
22
|
};
|
|
26
23
|
|
|
27
24
|
ElectronRunner.prototype.generateApp = function () {
|
|
28
|
-
var
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
25
|
+
var pkgPath = path.join(this.tempDir, "package.json");
|
|
26
|
+
if (!fs.existsSync(pkgPath)) {
|
|
27
|
+
var pkg = {
|
|
28
|
+
name: "cag-runner",
|
|
29
|
+
version: "1.0.0",
|
|
30
|
+
main: "main.js",
|
|
31
|
+
dependencies: {}
|
|
32
|
+
};
|
|
33
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
|
|
34
|
+
}
|
|
35
35
|
fs.writeFileSync(path.join(this.tempDir, "main.js"), this.getMainProcessSource());
|
|
36
36
|
fs.writeFileSync(path.join(this.tempDir, "index.html"), this.getRendererSource());
|
|
37
37
|
};
|
|
38
38
|
|
|
39
39
|
ElectronRunner.prototype.installAndLaunch = function () {
|
|
40
|
-
childProcess.execSync("npm install electron@latest --save --no-audit --no-fund", {
|
|
41
|
-
cwd: this.tempDir,
|
|
42
|
-
stdio: "inherit"
|
|
43
|
-
});
|
|
44
|
-
|
|
45
40
|
var electronBin = path.join(this.tempDir, "node_modules", ".bin", "electron");
|
|
46
41
|
if (process.platform === "win32") {
|
|
47
42
|
electronBin = electronBin + ".cmd";
|
|
48
43
|
}
|
|
49
44
|
|
|
45
|
+
if (!fs.existsSync(electronBin)) {
|
|
46
|
+
childProcess.execSync("npm install electron --save --no-audit --no-fund", {
|
|
47
|
+
cwd: this.tempDir,
|
|
48
|
+
stdio: "inherit"
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
50
52
|
childProcess.execSync("\"" + electronBin + "\" .", {
|
|
51
53
|
cwd: this.tempDir,
|
|
52
54
|
stdio: "inherit",
|
|
@@ -147,15 +149,15 @@ ElectronRunner.prototype.getRendererSource = function () {
|
|
|
147
149
|
|
|
148
150
|
var vsSrc = [
|
|
149
151
|
"attribute vec3 aPos;",
|
|
150
|
-
"attribute
|
|
152
|
+
"attribute vec2 aUV;",
|
|
151
153
|
"attribute vec3 aNormal;",
|
|
152
154
|
"uniform mat4 uProj;",
|
|
153
155
|
"uniform mat4 uView;",
|
|
154
|
-
"varying
|
|
156
|
+
"varying vec2 vUV;",
|
|
155
157
|
"varying vec3 vNormal;",
|
|
156
158
|
"varying vec3 vWorldPos;",
|
|
157
159
|
"void main() {",
|
|
158
|
-
"
|
|
160
|
+
" vUV = aUV;",
|
|
159
161
|
" vNormal = aNormal;",
|
|
160
162
|
" vWorldPos = aPos;",
|
|
161
163
|
" gl_Position = uProj * uView * vec4(aPos, 1.0);",
|
|
@@ -164,9 +166,10 @@ ElectronRunner.prototype.getRendererSource = function () {
|
|
|
164
166
|
|
|
165
167
|
var fsSrc = [
|
|
166
168
|
"precision mediump float;",
|
|
167
|
-
"varying
|
|
169
|
+
"varying vec2 vUV;",
|
|
168
170
|
"varying vec3 vNormal;",
|
|
169
171
|
"varying vec3 vWorldPos;",
|
|
172
|
+
"uniform sampler2D uTexture;",
|
|
170
173
|
"uniform vec3 uSunDir;",
|
|
171
174
|
"uniform vec3 uSunColor;",
|
|
172
175
|
"uniform vec3 uAmbient;",
|
|
@@ -175,13 +178,14 @@ ElectronRunner.prototype.getRendererSource = function () {
|
|
|
175
178
|
"uniform float uFogFar;",
|
|
176
179
|
"uniform vec3 uCamPos;",
|
|
177
180
|
"void main() {",
|
|
181
|
+
" vec4 texColor = texture2D(uTexture, vUV);",
|
|
178
182
|
" vec3 norm = normalize(vNormal);",
|
|
179
183
|
" float diff = max(dot(norm, normalize(uSunDir)), 0.0);",
|
|
180
|
-
" vec3 lit =
|
|
184
|
+
" vec3 lit = texColor.rgb * (uAmbient + uSunColor * diff);",
|
|
181
185
|
" float dist = length(vWorldPos - uCamPos);",
|
|
182
186
|
" float fog = clamp((dist - uFogNear) / (uFogFar - uFogNear), 0.0, 1.0);",
|
|
183
187
|
" vec3 final = mix(lit, uFogColor, fog);",
|
|
184
|
-
" gl_FragColor = vec4(final,
|
|
188
|
+
" gl_FragColor = vec4(final, texColor.a);",
|
|
185
189
|
"}"
|
|
186
190
|
].join("\\n");
|
|
187
191
|
|
|
@@ -193,6 +197,33 @@ ElectronRunner.prototype.getRendererSource = function () {
|
|
|
193
197
|
js.push("var VS_SRC = \"" + vsSrc + "\";");
|
|
194
198
|
js.push("var FS_SRC = \"" + fsSrc + "\";");
|
|
195
199
|
js.push("");
|
|
200
|
+
|
|
201
|
+
var modelDataForRenderer = {};
|
|
202
|
+
if (s.models) {
|
|
203
|
+
var sModelNames = Object.keys(s.models);
|
|
204
|
+
for (var mi = 0; mi < sModelNames.length; mi++) {
|
|
205
|
+
var smName = sModelNames[mi];
|
|
206
|
+
var smData = s.models[smName];
|
|
207
|
+
var faceUVMap = {};
|
|
208
|
+
if (smData.uvMappings) {
|
|
209
|
+
for (var ui = 0; ui < smData.uvMappings.length; ui++) {
|
|
210
|
+
var mapping = smData.uvMappings[ui];
|
|
211
|
+
if (!faceUVMap[mapping.face]) {
|
|
212
|
+
faceUVMap[mapping.face] = mapping.uv;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
modelDataForRenderer[smName] = {
|
|
217
|
+
textureDataURL: smData.textureDataURL || null,
|
|
218
|
+
resW: smData.resolution ? smData.resolution.width : 16,
|
|
219
|
+
resH: smData.resolution ? smData.resolution.height : 16,
|
|
220
|
+
faceUV: faceUVMap
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
js.push("var MODELS = " + JSON.stringify(modelDataForRenderer) + ";");
|
|
225
|
+
js.push("");
|
|
226
|
+
|
|
196
227
|
js.push("var game = {");
|
|
197
228
|
js.push(" gl: null, canvas: null, program: null,");
|
|
198
229
|
js.push(" camX: " + spX + ", camY: " + spY + ", camZ: " + spZ + ",");
|
|
@@ -225,34 +256,62 @@ ElectronRunner.prototype.getRendererSource = function () {
|
|
|
225
256
|
js.push("");
|
|
226
257
|
|
|
227
258
|
// Face helper
|
|
228
|
-
js.push("function addFace(pos,
|
|
259
|
+
js.push("function addFace(pos, uvArr, nrm, v0, v1, v2, v3, fuv, normal) {");
|
|
229
260
|
js.push(" pos.push(v0[0],v0[1],v0[2], v1[0],v1[1],v1[2], v2[0],v2[1],v2[2]);");
|
|
230
261
|
js.push(" pos.push(v0[0],v0[1],v0[2], v2[0],v2[1],v2[2], v3[0],v3[1],v3[2]);");
|
|
262
|
+
js.push(" uvArr.push(fuv[0],fuv[1], fuv[2],fuv[1], fuv[2],fuv[3]);");
|
|
263
|
+
js.push(" uvArr.push(fuv[0],fuv[1], fuv[2],fuv[3], fuv[0],fuv[3]);");
|
|
231
264
|
js.push(" for (var i = 0; i < 6; i++) {");
|
|
232
|
-
js.push(" col.push(color[0], color[1], color[2]);");
|
|
233
265
|
js.push(" nrm.push(normal[0], normal[1], normal[2]);");
|
|
234
266
|
js.push(" }");
|
|
235
267
|
js.push("}");
|
|
236
268
|
js.push("");
|
|
237
269
|
|
|
270
|
+
// UV normalization helper
|
|
271
|
+
js.push("function normUV(faceUV, resW, resH) {");
|
|
272
|
+
js.push(" if (!faceUV) return [0, 1, 1, 0];");
|
|
273
|
+
js.push(" return [faceUV[0]/resW, 1.0-faceUV[1]/resH, faceUV[2]/resW, 1.0-faceUV[3]/resH];");
|
|
274
|
+
js.push("}");
|
|
275
|
+
js.push("");
|
|
276
|
+
|
|
277
|
+
// Get UV coordinates for a model by name (case-insensitive)
|
|
278
|
+
js.push("function getModelUVs(name) {");
|
|
279
|
+
js.push(" var ln = name.toLowerCase();");
|
|
280
|
+
js.push(" var keys = Object.keys(MODELS);");
|
|
281
|
+
js.push(" for (var i = 0; i < keys.length; i++) {");
|
|
282
|
+
js.push(" if (keys[i].toLowerCase() === ln) {");
|
|
283
|
+
js.push(" var m = MODELS[keys[i]];");
|
|
284
|
+
js.push(" var f = m.faceUV || {};");
|
|
285
|
+
js.push(" return {");
|
|
286
|
+
js.push(" up: normUV(f.up, m.resW, m.resH),");
|
|
287
|
+
js.push(" down: normUV(f.down, m.resW, m.resH),");
|
|
288
|
+
js.push(" north: normUV(f.north, m.resW, m.resH),");
|
|
289
|
+
js.push(" south: normUV(f.south, m.resW, m.resH),");
|
|
290
|
+
js.push(" east: normUV(f.east, m.resW, m.resH),");
|
|
291
|
+
js.push(" west: normUV(f.west, m.resW, m.resH)");
|
|
292
|
+
js.push(" };");
|
|
293
|
+
js.push(" }");
|
|
294
|
+
js.push(" }");
|
|
295
|
+
js.push(" return { up:[0,1,1,0], down:[0,1,1,0], north:[0,1,1,0], south:[0,1,1,0], east:[0,1,1,0], west:[0,1,1,0] };");
|
|
296
|
+
js.push("}");
|
|
297
|
+
js.push("");
|
|
298
|
+
|
|
238
299
|
// Build mesh for a chunk
|
|
239
300
|
js.push("function buildChunkMesh(blocks, blockMap) {");
|
|
240
|
-
js.push(" var pos = [],
|
|
241
|
-
js.push(" var
|
|
242
|
-
js.push(" var sideC = [0.50, 0.38, 0.22];");
|
|
243
|
-
js.push(" var botC = [0.45, 0.32, 0.17];");
|
|
301
|
+
js.push(" var pos = [], uvArr = [], nrm = [];");
|
|
302
|
+
js.push(" var uv = getModelUVs('Grass');");
|
|
244
303
|
js.push(" for (var i = 0; i < blocks.length; i++) {");
|
|
245
304
|
js.push(" var b = blocks[i];");
|
|
246
305
|
js.push(" var x = b.x, y = b.y, z = b.z;");
|
|
247
306
|
js.push(" var k = function(bx,by,bz) { return bx+','+by+','+bz; };");
|
|
248
|
-
js.push(" if (!blockMap[k(x,y+1,z)]) addFace(pos,
|
|
249
|
-
js.push(" if (!blockMap[k(x,y-1,z)]) addFace(pos,
|
|
250
|
-
js.push(" if (!blockMap[k(x,y,z-1)]) addFace(pos,
|
|
251
|
-
js.push(" if (!blockMap[k(x,y,z+1)]) addFace(pos,
|
|
252
|
-
js.push(" if (!blockMap[k(x
|
|
253
|
-
js.push(" if (!blockMap[k(x
|
|
307
|
+
js.push(" if (!blockMap[k(x,y+1,z)]) addFace(pos,uvArr,nrm, [x,y+1,z],[x+1,y+1,z],[x+1,y+1,z+1],[x,y+1,z+1], uv.up, [0,1,0]);");
|
|
308
|
+
js.push(" if (!blockMap[k(x,y-1,z)]) addFace(pos,uvArr,nrm, [x,y,z+1],[x+1,y,z+1],[x+1,y,z],[x,y,z], uv.down, [0,-1,0]);");
|
|
309
|
+
js.push(" if (!blockMap[k(x,y,z-1)]) addFace(pos,uvArr,nrm, [x,y,z],[x+1,y,z],[x+1,y+1,z],[x,y+1,z], uv.north, [0,0,-1]);");
|
|
310
|
+
js.push(" if (!blockMap[k(x,y,z+1)]) addFace(pos,uvArr,nrm, [x+1,y,z+1],[x,y,z+1],[x,y+1,z+1],[x+1,y+1,z+1], uv.south, [0,0,1]);");
|
|
311
|
+
js.push(" if (!blockMap[k(x+1,y,z)]) addFace(pos,uvArr,nrm, [x+1,y,z],[x+1,y,z+1],[x+1,y+1,z+1],[x+1,y+1,z], uv.east, [1,0,0]);");
|
|
312
|
+
js.push(" if (!blockMap[k(x-1,y,z)]) addFace(pos,uvArr,nrm, [x,y,z+1],[x,y,z],[x,y+1,z],[x,y+1,z+1], uv.west, [-1,0,0]);");
|
|
254
313
|
js.push(" }");
|
|
255
|
-
js.push(" return { positions: pos,
|
|
314
|
+
js.push(" return { positions: pos, uvs: uvArr, normals: nrm };");
|
|
256
315
|
js.push("}");
|
|
257
316
|
js.push("");
|
|
258
317
|
|
|
@@ -286,17 +345,16 @@ ElectronRunner.prototype.getRendererSource = function () {
|
|
|
286
345
|
js.push(" var vertCount = mesh.positions.length / 3;");
|
|
287
346
|
js.push(" var gl = game.gl;");
|
|
288
347
|
js.push(" var vbo = gl.createBuffer();");
|
|
289
|
-
js.push(" var data = new Float32Array(vertCount *
|
|
348
|
+
js.push(" var data = new Float32Array(vertCount * 8);");
|
|
290
349
|
js.push(" for (var v = 0; v < vertCount; v++) {");
|
|
291
|
-
js.push(" data[v*
|
|
292
|
-
js.push(" data[v*
|
|
293
|
-
js.push(" data[v*
|
|
294
|
-
js.push(" data[v*
|
|
295
|
-
js.push(" data[v*
|
|
296
|
-
js.push(" data[v*
|
|
297
|
-
js.push(" data[v*
|
|
298
|
-
js.push(" data[v*
|
|
299
|
-
js.push(" data[v*9+8] = mesh.normals[v*3+2];");
|
|
350
|
+
js.push(" data[v*8+0] = mesh.positions[v*3+0];");
|
|
351
|
+
js.push(" data[v*8+1] = mesh.positions[v*3+1];");
|
|
352
|
+
js.push(" data[v*8+2] = mesh.positions[v*3+2];");
|
|
353
|
+
js.push(" data[v*8+3] = mesh.uvs[v*2+0];");
|
|
354
|
+
js.push(" data[v*8+4] = mesh.uvs[v*2+1];");
|
|
355
|
+
js.push(" data[v*8+5] = mesh.normals[v*3+0];");
|
|
356
|
+
js.push(" data[v*8+6] = mesh.normals[v*3+1];");
|
|
357
|
+
js.push(" data[v*8+7] = mesh.normals[v*3+2];");
|
|
300
358
|
js.push(" }");
|
|
301
359
|
js.push(" gl.bindBuffer(gl.ARRAY_BUFFER, vbo);");
|
|
302
360
|
js.push(" gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);");
|
|
@@ -359,7 +417,7 @@ ElectronRunner.prototype.getRendererSource = function () {
|
|
|
359
417
|
js.push(" gl.attachShader(this.program, vs);");
|
|
360
418
|
js.push(" gl.attachShader(this.program, fsh);");
|
|
361
419
|
js.push(" gl.bindAttribLocation(this.program, 0, 'aPos');");
|
|
362
|
-
js.push(" gl.bindAttribLocation(this.program, 1, '
|
|
420
|
+
js.push(" gl.bindAttribLocation(this.program, 1, 'aUV');");
|
|
363
421
|
js.push(" gl.bindAttribLocation(this.program, 2, 'aNormal');");
|
|
364
422
|
js.push(" gl.linkProgram(this.program);");
|
|
365
423
|
js.push(" gl.useProgram(this.program);");
|
|
@@ -373,6 +431,7 @@ ElectronRunner.prototype.getRendererSource = function () {
|
|
|
373
431
|
js.push(" this.uFogNear = gl.getUniformLocation(this.program, 'uFogNear');");
|
|
374
432
|
js.push(" this.uFogFar = gl.getUniformLocation(this.program, 'uFogFar');");
|
|
375
433
|
js.push(" this.uCamPos = gl.getUniformLocation(this.program, 'uCamPos');");
|
|
434
|
+
js.push(" this.uTexture = gl.getUniformLocation(this.program, 'uTexture');");
|
|
376
435
|
js.push("");
|
|
377
436
|
js.push(" gl.uniform3f(this.uSunDir, " + sunD.x + ", " + sunD.y + ", " + sunD.z + ");");
|
|
378
437
|
js.push(" gl.uniform3f(this.uSunColor, 1.0, 0.95, 0.8);");
|
|
@@ -381,6 +440,24 @@ ElectronRunner.prototype.getRendererSource = function () {
|
|
|
381
440
|
js.push(" gl.uniform1f(this.uFogNear, " + fogNear + ");");
|
|
382
441
|
js.push(" gl.uniform1f(this.uFogFar, " + fogFar + ");");
|
|
383
442
|
js.push("");
|
|
443
|
+
js.push(" this.blockTexture = gl.createTexture();");
|
|
444
|
+
js.push(" gl.bindTexture(gl.TEXTURE_2D, this.blockTexture);");
|
|
445
|
+
js.push(" gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([128,128,128,255]));");
|
|
446
|
+
js.push(" var texKeys = Object.keys(MODELS);");
|
|
447
|
+
js.push(" if (texKeys.length > 0 && MODELS[texKeys[0]].textureDataURL) {");
|
|
448
|
+
js.push(" var texImg = new Image();");
|
|
449
|
+
js.push(" texImg.onload = function() {");
|
|
450
|
+
js.push(" var g = game.gl;");
|
|
451
|
+
js.push(" g.bindTexture(g.TEXTURE_2D, game.blockTexture);");
|
|
452
|
+
js.push(" g.texImage2D(g.TEXTURE_2D, 0, g.RGBA, g.RGBA, g.UNSIGNED_BYTE, texImg);");
|
|
453
|
+
js.push(" g.texParameteri(g.TEXTURE_2D, g.TEXTURE_MIN_FILTER, g.NEAREST);");
|
|
454
|
+
js.push(" g.texParameteri(g.TEXTURE_2D, g.TEXTURE_MAG_FILTER, g.NEAREST);");
|
|
455
|
+
js.push(" g.texParameteri(g.TEXTURE_2D, g.TEXTURE_WRAP_S, g.CLAMP_TO_EDGE);");
|
|
456
|
+
js.push(" g.texParameteri(g.TEXTURE_2D, g.TEXTURE_WRAP_T, g.CLAMP_TO_EDGE);");
|
|
457
|
+
js.push(" };");
|
|
458
|
+
js.push(" texImg.src = MODELS[texKeys[0]].textureDataURL;");
|
|
459
|
+
js.push(" }");
|
|
460
|
+
js.push("");
|
|
384
461
|
js.push(" gl.enable(gl.DEPTH_TEST);");
|
|
385
462
|
js.push(" gl.enable(gl.CULL_FACE);");
|
|
386
463
|
js.push(" gl.cullFace(gl.BACK);");
|
|
@@ -407,16 +484,8 @@ ElectronRunner.prototype.getRendererSource = function () {
|
|
|
407
484
|
js.push("");
|
|
408
485
|
js.push(" setInterval(function () { game.fps = game.frames; game.frames = 0; }, 1000);");
|
|
409
486
|
js.push("");
|
|
410
|
-
js.push("
|
|
411
|
-
js.push("
|
|
412
|
-
js.push(" var overlayEl = document.getElementById('click-overlay');");
|
|
413
|
-
js.push(" overlayEl.style.display = 'flex';");
|
|
414
|
-
js.push(" overlayEl.addEventListener('click', function () {");
|
|
415
|
-
js.push(" overlayEl.style.display = 'none';");
|
|
416
|
-
js.push(" game.canvas.requestPointerLock();");
|
|
417
|
-
js.push(" game.started = true;");
|
|
418
|
-
js.push(" game.loop();");
|
|
419
|
-
js.push(" });");
|
|
487
|
+
js.push(" game.started = true;");
|
|
488
|
+
js.push(" game.loop();");
|
|
420
489
|
js.push("};");
|
|
421
490
|
js.push("");
|
|
422
491
|
|
|
@@ -495,7 +564,11 @@ ElectronRunner.prototype.getRendererSource = function () {
|
|
|
495
564
|
js.push(" gl.uniformMatrix4fv(this.uView, false, view);");
|
|
496
565
|
js.push(" gl.uniform3f(this.uCamPos, this.camX, this.camY, this.camZ);");
|
|
497
566
|
js.push("");
|
|
498
|
-
js.push("
|
|
567
|
+
js.push(" gl.activeTexture(gl.TEXTURE0);");
|
|
568
|
+
js.push(" gl.bindTexture(gl.TEXTURE_2D, this.blockTexture);");
|
|
569
|
+
js.push(" gl.uniform1i(this.uTexture, 0);");
|
|
570
|
+
js.push("");
|
|
571
|
+
js.push(" var stride = 8 * 4;");
|
|
499
572
|
js.push(" var keys = Object.keys(this.chunks);");
|
|
500
573
|
js.push(" for (var i = 0; i < keys.length; i++) {");
|
|
501
574
|
js.push(" var chunk = this.chunks[keys[i]];");
|
|
@@ -505,8 +578,8 @@ ElectronRunner.prototype.getRendererSource = function () {
|
|
|
505
578
|
js.push(" gl.enableVertexAttribArray(1);");
|
|
506
579
|
js.push(" gl.enableVertexAttribArray(2);");
|
|
507
580
|
js.push(" gl.vertexAttribPointer(0, 3, gl.FLOAT, false, stride, 0);");
|
|
508
|
-
js.push(" gl.vertexAttribPointer(1,
|
|
509
|
-
js.push(" gl.vertexAttribPointer(2, 3, gl.FLOAT, false, stride,
|
|
581
|
+
js.push(" gl.vertexAttribPointer(1, 2, gl.FLOAT, false, stride, 12);");
|
|
582
|
+
js.push(" gl.vertexAttribPointer(2, 3, gl.FLOAT, false, stride, 20);");
|
|
510
583
|
js.push(" gl.drawArrays(gl.TRIANGLES, 0, chunk.vertCount);");
|
|
511
584
|
js.push(" }");
|
|
512
585
|
js.push("};");
|
|
@@ -547,28 +620,13 @@ ElectronRunner.prototype.getRendererSource = function () {
|
|
|
547
620
|
js.push("};");
|
|
548
621
|
js.push("");
|
|
549
622
|
|
|
550
|
-
|
|
551
|
-
js.push("var bar = document.getElementById('bar-inner');");
|
|
552
|
-
js.push("var status = document.getElementById('load-status');");
|
|
553
|
-
js.push("setTimeout(function () { bar.style.width = '25%'; status.textContent = 'Compiling shaders...'; }, 200);");
|
|
554
|
-
js.push("setTimeout(function () { bar.style.width = '50%'; status.textContent = 'Generating chunks...'; }, 600);");
|
|
555
|
-
js.push("setTimeout(function () { bar.style.width = '75%'; status.textContent = 'Building meshes...'; }, 1000);");
|
|
556
|
-
js.push("setTimeout(function () { bar.style.width = '100%'; status.textContent = 'Ready!'; status.style.color = '#4ecca3'; }, 1400);");
|
|
557
|
-
js.push("setTimeout(function () { game.init(); }, 1800);");
|
|
623
|
+
js.push("game.init();");
|
|
558
624
|
|
|
559
625
|
var html = "<!DOCTYPE html>\n<html>\n<head>\n";
|
|
560
626
|
html += "<meta charset='utf-8'>\n";
|
|
561
627
|
html += "<title>" + windowTitle + " - CaG Engine</title>\n";
|
|
562
628
|
html += "<style>\n" + css + "\n</style>\n";
|
|
563
629
|
html += "</head>\n<body>\n";
|
|
564
|
-
html += "<div id='loading'>\n";
|
|
565
|
-
html += " <h1>CaG</h1>\n";
|
|
566
|
-
html += " <h2>" + infoID + "</h2>\n";
|
|
567
|
-
html += " <div id='load-status'>Starting...</div>\n";
|
|
568
|
-
html += " <div id='bar-outer'><div id='bar-inner'></div></div>\n";
|
|
569
|
-
html += " <div class='version-tag'>v" + infoVer + "</div>\n";
|
|
570
|
-
html += "</div>\n";
|
|
571
|
-
html += "<div id='click-overlay' style='display:none'><div class='play-icon'><div class='play-triangle'></div></div><span>CLICK TO PLAY</span></div>\n";
|
|
572
630
|
html += "<div id='crosshair' style='display:none'></div>\n";
|
|
573
631
|
html += "<div id='hud'><div id='hud-box'><div id='hud-info'></div></div></div>\n";
|
|
574
632
|
html += "<div id='controls-hint'><b>WASD</b> Move <b>Mouse</b> Look <b>Space</b> Jump <b>Shift</b> Sprint <b>F11</b> Fullscreen <b>Esc</b> Release</div>\n";
|
|
@@ -638,6 +696,32 @@ ElectronRunner.extractSettings = function (executor) {
|
|
|
638
696
|
settings.renderDistance = chunkAPI.renderDistance;
|
|
639
697
|
}
|
|
640
698
|
|
|
699
|
+
if (registry.has("Model.API")) {
|
|
700
|
+
var modelAPI = registry.get("Model.API");
|
|
701
|
+
var loadedModels = modelAPI.getLoadedModels();
|
|
702
|
+
settings.models = {};
|
|
703
|
+
if (loadedModels) {
|
|
704
|
+
var modelNames = Object.keys(loadedModels);
|
|
705
|
+
for (var mi = 0; mi < modelNames.length; mi++) {
|
|
706
|
+
var mName = modelNames[mi];
|
|
707
|
+
var model = loadedModels[mName];
|
|
708
|
+
if (model && model.valid) {
|
|
709
|
+
var texW = model.texture ? model.texture.width : 0;
|
|
710
|
+
var texH = model.texture ? model.texture.height : 0;
|
|
711
|
+
if (!texW || !texH) {
|
|
712
|
+
texW = model.geometry ? model.geometry.resolution.width : 16;
|
|
713
|
+
texH = model.geometry ? model.geometry.resolution.height : 16;
|
|
714
|
+
}
|
|
715
|
+
settings.models[mName] = {
|
|
716
|
+
uvMappings: model.uvMappings || [],
|
|
717
|
+
resolution: { width: texW, height: texH },
|
|
718
|
+
textureDataURL: model.texture && model.texture.dataURL ? model.texture.dataURL : null
|
|
719
|
+
};
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
|
|
641
725
|
return settings;
|
|
642
726
|
};
|
|
643
727
|
|