Skip to content

Commit 3de40f7

Browse files
committed
Update pxt.json, myself.ts, render.ts, class.ts
1 parent 8b3574e commit 3de40f7

4 files changed

Lines changed: 274 additions & 524 deletions

File tree

class.ts

Lines changed: 0 additions & 309 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
namespace Polymesh {
22

3-
class modelDepth { constructor(public mesh: model, public depth: number) { } }
4-
53
export class base {
64
protected __prop_upd: control.FrameCallback; __del: boolean; protected __unDel: boolean; protected __updateLoop: boolean;
75
public pos: Motion3; public rot: Motion3;
@@ -156,313 +154,6 @@ namespace Polymesh {
156154

157155
}
158156

159-
export class view extends base {
160-
161-
points: Vector3[]; zoom: number; near: number; far: number; tpoints: Vector3[]; viewport: Image;
162-
163-
setViewport(viewport: Image) {
164-
if (this.viewport.width === viewport.width &&
165-
this.viewport.height === viewport.height) return;
166-
this.viewport = viewport;
167-
}
168-
169-
initView() {
170-
this.points = [
171-
new Vector3(0, 0, 1/*, Math.idiv(this.near, 50)*/),
172-
new Vector3(Math.SQRT1_2, 0, Math.SQRT1_2),
173-
new Vector3(-Math.SQRT1_2, 0, Math.SQRT1_2),
174-
new Vector3(0, Math.SQRT1_2, Math.SQRT1_2),
175-
new Vector3(0, -Math.SQRT1_2, Math.SQRT1_2),
176-
];
177-
}
178-
179-
pointUpdate() {
180-
for (let i = 0; i < this.points.length; i++) this.tpoints[i] = rotatePoint3Dxyz(this.points[i], this.pos.toVector(), this.rot.toVector());
181-
}
182-
183-
__onDel() {
184-
this.points = [];
185-
this.tpoints = [];
186-
this.viewport = null;
187-
this.zoom = null;
188-
this.near = null;
189-
this.far = null;
190-
}
191-
192-
__onLoop() {
193-
this.viewport.fill(0);
194-
this.pointUpdate();
195-
this.renderMshs(meshAny(), this.viewport);
196-
}
197-
198-
renderMshs(mshs: model[], output: Image, lineren?: boolean) {
199-
if (this.isDel()) return;
200-
const sorted = mshs.map(msh => new modelDepth(msh, msh.zDepth()))
201-
if (sorted.length <= 0) return;
202-
switch (sort) {
203-
case 0x0: sorted.sort((a, b) => b.depth - a.depth); break;
204-
case 0x1: quickSort(sorted, (a, b) => b.depth - a.depth); break;
205-
case 0x2:
206-
default: duoQuickSort(sorted, (a, b) => b.depth - a.depth); break;
207-
}
208-
for (const m of sorted) {
209-
if (m.mesh.flag.invisible) continue;
210-
this.render(m.mesh, output, lineren);
211-
}
212-
}
213-
214-
constructor(undel?: boolean, viewport?: Image) {
215-
super(undel);
216-
if (viewport === undefined) viewport = scene.backgroundImage();
217-
this.viewport = viewport;
218-
this.zoom = 1;
219-
this.near = 150;
220-
this.far = 0;
221-
this.initView();
222-
this.tpoints = []
223-
}
224-
225-
setPos(choice: number, x: number) {
226-
switch (choice) {
227-
case 0xC: if (this.zoom !== x) this.zoom = x; return
228-
case 0xD: if (this.near !== x) this.near = x; this.initView(); return
229-
case 0xE: if (this.far !== x) this.far = x; return
230-
}; super.setPos(choice, x);
231-
}
232-
233-
changePos(choice: number, x: number) {
234-
switch (choice) {
235-
case 0xC: if (this.zoom !== this.zoom + x) this.zoom += x; return
236-
case 0xD: if (this.near !== this.near + x) this.near += x; this.initView(); return
237-
case 0xE: if (this.far !== this.far + x) this.far += x; return
238-
}; super.changePos(choice, x);
239-
}
240-
241-
getPos(choice: number) {
242-
switch (choice) {
243-
case 0xC: return this.zoom
244-
case 0xD: return this.near
245-
case 0xE: return this.far
246-
}; return super.getPos(choice);
247-
}
248-
249-
render(msh: model, output: Image, lineren?: boolean) {
250-
if (this.isDel()) return;
251-
if (msh.isDel()) return;
252-
if (!msh || !output || msh.points.length <= 0 || msh.faces.length <= 0) return;
253-
if (msh.flag.invisible) return;
254-
255-
const dist = this.near, fardist = (this.far === 0 ? 0x7f : this.far), zoom = this.zoom;
256-
257-
const centerX = output.width >>> 1, centerY = output.height >>> 1;
258-
259-
let tmp = 0
260-
const cosX = fcos(camview.rot.x), sinX = fsin(camview.rot.x);
261-
const cosY = fcos(camview.rot.y), sinY = fsin(camview.rot.y);
262-
const cosZ = fcos(camview.rot.z), sinZ = fsin(camview.rot.z);
263-
264-
// Transform vertices
265-
const rotated = msh.pointCam((v) => {
266-
let x = v.x - this.pos.x;
267-
let y = v.y - this.pos.y;
268-
let z = v.z - this.pos.z;
269-
tmp = x * cosY + z * sinY, z = -x * sinY + z * cosY, x = tmp; // --- rotate around y ---
270-
tmp = y * cosX - z * sinX, z = y * sinX + z * cosX, y = tmp; // --- rotate around x ---
271-
tmp = x * cosZ - y * sinZ, y = x * sinZ + y * cosZ, x = tmp; // --- rotate around z ---
272-
273-
const vsum = 1.1 * finv(psqrt((x * x) + (y * y) + (z * z)))
274-
// camera offset
275-
x += (x === 0 ? 0 : Math.sign(x) * vsum);
276-
y += (y === 0 ? 0 : Math.sign(y) * vsum);
277-
z += (z === 0 ? 0 : Math.sign(z) * vsum);
278-
// Perspective
279-
const scale = Math.abs(dist) * finv(Math.abs(dist) + z);
280-
return new Vector3(
281-
centerX + (x * scale * zoom),
282-
centerY - (y * scale * zoom),
283-
z
284-
);
285-
});
286-
287-
// Sort triangles
288-
const trisCMP = (a: Polymesh.FaceLOD, b: Polymesh.FaceLOD) => avgZ(rotated, b.indices) - avgZ(rotated, a.indices)
289-
const tris = msh.vfaces.slice();
290-
//control.runInParallel(() => {
291-
switch (sort) {
292-
case 0x0: tris.sort((a, b) => trisCMP(a, b)); break;
293-
case 0x1: quickSort(tris, (a, b) => trisCMP(a, b)); break;
294-
case 0x2:
295-
default: duoQuickSort(tris, (a, b) => trisCMP(a, b)); break;
296-
}
297-
//})
298-
299-
//pause(0);
300-
301-
// Render
302-
for (let i = 0;i < tris.length;i++) {
303-
const t = tris[i]
304-
const inds = t.indices;
305-
if (inds.some(i => (rotated[i].z < -Math.abs(dist) || (fardist > 0 && rotated[i].z > Math.abs(fardist))))) continue;
306-
//const inds_ = [];
307-
//if (inds.length > 2) inds_[0] = [t.indices[0], t.indices[1], t.indices[2]];
308-
//if (inds.length > 3) inds_[1] = [t.indices[3], t.indices[1], t.indices[2]];
309-
const scale = (Math.abs(dist) * finv(Math.abs(dist) + avgZ(rotated, t.indices)));
310-
// LOD calculating?
311-
let im: Image = null
312-
if (t.img) {
313-
im = t.img;
314-
if (msh.flag.texStream) {
315-
let scaleD = finv(scale * zoom) * 0.2;
316-
scaleD = Math.clamp(0, t.imgs.length-1, Math.round((1.25-scaleD) * (t.imgs.length-1)));
317-
im = t.imgs[scaleD]
318-
if (im == null) im = image.create(1, 1)
319-
}
320-
}
321-
if (t.indices.length === 1) {
322-
const idx = t.indices[0];
323-
const pt = rotated[idx];
324-
325-
// center image
326-
const bq = new pt2_4(
327-
pt.x, pt.y,
328-
pt.x, pt.y,
329-
pt.x, pt.y,
330-
pt.x, pt.y,
331-
)
332-
333-
const square = dist + (2048 * (scale * t.scale) * zoom)
334-
if (im) {
335-
// set scale image from camera distance
336-
const halfW = (im.width * 0.33333333) * scale * t.scale * zoom;
337-
const halfH = (im.height * 0.33333333) * scale * t.scale * zoom;
338-
339-
bq.x0 += halfW, bq.y0 += halfH
340-
bq.x1 -= halfW, bq.y1 += halfH
341-
bq.x2 += halfW, bq.y2 -= halfH
342-
bq.x3 -= halfW, bq.y3 -= halfH
343-
if (bq.toArr.every(v => (isOutOfArea(v.x, v.y, output.width, output.height)))) continue;
344-
} else {
345-
bq.x0 += square, bq.y0 += square
346-
bq.x1 -= square, bq.y1 += square
347-
bq.x2 += square, bq.y2 -= square
348-
bq.x3 -= square, bq.y3 -= square
349-
if (bq.toArr.every(v => (isOutOfArea(v.x, v.y, output.width, output.height)))) continue;
350-
}
351-
} else if (isOutOfAreaOnFace(rotated, inds, output.width, output.height)) if (inds.every(i => isOutOfArea(rotated[i].x, rotated[i].y, output.width, output.height))) continue;
352-
353-
const culling = msh.flag.cull
354-
355-
// Backface culling
356-
//if (culling)
357-
// if ((inds_[0] && !shouldRenderFace(rotated, inds_[0], camview.pos, t.offset)) &&
358-
// (inds_[1] && !shouldRenderFace(rotated, inds_[1], camview.pos, t.offset))) continue;
359-
360-
if (culling) if (shouldCull(avgXYZ(rotated, inds), t.offset)) continue;
361-
362-
const idx = t.indices[0];
363-
const pt = rotated[idx];
364-
// center image
365-
366-
let square = dist + (2048 * (scale * t.scale) * zoom)
367-
368-
let halfW = square + dist;
369-
let halfH = square + dist;
370-
371-
if (t.img) {
372-
// set scale image from camera distance
373-
374-
halfW = (im.width * 0.33333333) * scale * t.scale * zoom;
375-
halfH = (im.height * 0.33333333) * scale * t.scale * zoom;
376-
377-
square = Polymesh.gcd(halfW, halfH)
378-
};
379-
// when have 2D image billboard (indices.length == 1 and img)
380-
if (t.indices.length === 1) {
381-
if (pt.z < -Math.abs(dist)) continue;
382-
383-
// when no image
384-
if (!t.img) { fillCircleImage(output, pt.x, pt.y, square, t.color); continue; }
385-
386-
// fill circle if image is empty
387-
if (isEmptyImage(t.img)) { fillCircleImage(output, pt.x, pt.y, square, t.color); continue; }
388-
389-
halfW *= 0.75;
390-
halfH *= 0.75;
391-
392-
// Draw Simple 2D image (billboard) as quad pixel on image
393-
// use distortImage or drawing without perspective distortion
394-
// I will use distortImage draw as vertex quad
395-
distortImage(im, output,
396-
pt.x + halfW, pt.y - halfH,
397-
pt.x - halfW, pt.y - halfH,
398-
pt.x - halfW, pt.y + halfH,
399-
pt.x + halfW, pt.y + halfH
400-
);
401-
continue;
402-
}
403-
404-
if (inds.length < 2) continue;
405-
// Draw line canvas when have line color index
406-
if (lineren) {
407-
picDrawLine(output, rotated[inds[0]].x, rotated[inds[0]].y, rotated[inds[1]].x, rotated[inds[1]].y, t.color);
408-
if (inds.length < 3) continue;
409-
picDrawLine(output, rotated[inds[0]].x, rotated[inds[0]].y, rotated[inds[2]].x, rotated[inds[2]].y, t.color);
410-
if (inds.length > 3) picDrawLine(output, rotated[inds[3]].x, rotated[inds[3]].y, rotated[inds[1]].x, rotated[inds[1]].y, t.color), picDrawLine(output, rotated[inds[3]].x, rotated[inds[3]].y, rotated[inds[2]].x, rotated[inds[2]].y, t.color);
411-
else picDrawLine(output, rotated[inds[1]].x, rotated[inds[1]].y, rotated[inds[2]].x, rotated[inds[2]].y, t.color);
412-
continue;
413-
}
414-
if (t.color > 0) {
415-
// Draw line when no shape
416-
if (inds.length < 3) {
417-
picDrawLine(output,
418-
rotated[inds[0]].x, rotated[inds[0]].y,
419-
rotated[inds[1]].x, rotated[inds[1]].y,
420-
t.color
421-
);
422-
}
423-
if (inds.length > 2) {
424-
// Draw solid when is vertice shape
425-
helpers.imageFillTriangle(output,
426-
rotated[inds[0]].x, rotated[inds[0]].y,
427-
rotated[inds[1]].x, rotated[inds[1]].y,
428-
rotated[inds[2]].x, rotated[inds[2]].y,
429-
t.color
430-
);
431-
if (inds.length > 3) {
432-
helpers.imageFillTriangle(output,
433-
rotated[inds[3]].x, rotated[inds[3]].y,
434-
rotated[inds[1]].x, rotated[inds[1]].y,
435-
rotated[inds[2]].x, rotated[inds[2]].y,
436-
t.color
437-
);
438-
}
439-
}
440-
}
441-
442-
if ((t.img && isEmptyImage(t.img)) || !t.img) continue;
443-
444-
// Draw texture over
445-
if (inds.length > 2) {
446-
distortImage(im, output,
447-
rotated[inds[3]].x, rotated[inds[3]].y,
448-
rotated[inds[2]].x, rotated[inds[2]].y,
449-
rotated[inds[0]].x, rotated[inds[0]].y,
450-
rotated[inds[1]].x, rotated[inds[1]].y
451-
);
452-
} else if (inds.length > 3) {
453-
distortImage(im, output,
454-
rotated[inds[3]].x, rotated[inds[3]].y,
455-
rotated[inds[2]].x, rotated[inds[2]].y,
456-
rotated[inds[0]].x, rotated[inds[0]].y,
457-
rotated[inds[1]].x, rotated[inds[1]].y
458-
);
459-
}
460-
461-
}
462-
463-
}
464-
}
465-
466157
export class model extends base {
467158

468159
_faces: Polymesh.Face[]; _points: Polymesh.Vector3[]; pivot: Polymesh.Vector3;

myself.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ namespace Polymesh {
5454
return camview.getPos(choice)
5555
}
5656

57-
//% blockId=poly_camera_viewport
57+
//% blockId=poly_camera_viewport_set
5858
//% block=" set camera viewport image to $viewport=image_picker"
5959
//% group="render"
6060
//% weight=9qee

pxt.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "arcade-polymesh - Copy",
2+
"name": "arcade-polymesh",
33
"version": "14.0.0",
44
"description": "basic 3d render like polygon and mesh",
55
"dependencies": {

0 commit comments

Comments
 (0)