Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The sprite in the atlas support rotation #1948

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions packages/core/src/2d/assembler/SimpleSpriteAssembler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,18 +52,15 @@ export class SimpleSpriteAssembler {
const { x, y } = spritePositions[i];
positions[i].set(wE[0] * x + wE[4] * y + wE[12], wE[1] * x + wE[5] * y + wE[13], wE[2] * x + wE[6] * y + wE[14]);
}

BoundingBox.transform(sprite._getBounds(), worldMatrix, renderer._bounds);
}

static updateUVs(renderer: SpriteRenderer | SpriteMask): void {
const spriteUVs = renderer.sprite._getUVs();
const renderUVs = renderer._verticesData.uvs;
const { x: left, y: bottom } = spriteUVs[0];
const { x: right, y: top } = spriteUVs[3];
renderUVs[0].set(left, bottom);
renderUVs[1].set(right, bottom);
renderUVs[2].set(left, top);
renderUVs[3].set(right, top);
renderUVs[0].copyFrom(spriteUVs[0]);
renderUVs[1].copyFrom(spriteUVs[3]);
renderUVs[2].copyFrom(spriteUVs[12]);
renderUVs[3].copyFrom(spriteUVs[15]);
}
}
31 changes: 16 additions & 15 deletions packages/core/src/2d/assembler/SlicedSpriteAssembler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { Matrix, Vector2, Vector3 } from "@galacean/engine-math";
import { StaticInterfaceImplement } from "../../base/StaticInterfaceImplement";
import { SpriteRenderer } from "../sprite/SpriteRenderer";
import { IAssembler } from "./IAssembler";
import { SimpleSpriteAssembler } from "./SimpleSpriteAssembler";

/**
* @internal
Expand All @@ -27,9 +26,8 @@ export class SlicedSpriteAssembler {

static updatePositions(renderer: SpriteRenderer): void {
const { width, height, sprite } = renderer;
const { positions, uvs } = renderer._verticesData;
const { positions } = renderer._verticesData;
const { border } = sprite;
const spriteUVs = sprite._getUVs();
// Update local positions.
const spritePositions = sprite._getPositions();
const { x: left, y: bottom } = spritePositions[0];
Expand Down Expand Up @@ -95,27 +93,24 @@ export class SlicedSpriteAssembler {
wE[14] = pWE[14] - localTransX * wE[2] - localTransY * wE[6];

// ------------------------
// 3 - 7 - 11 - 15
// 12 -13 -14 - 15
// | | | |
// 2 - 6 - 10 - 14
// 8 - 9 - 10 - 11
// | | | |
// 1 - 5 - 9 - 13
// 4 - 5 - 6 - 7
// | | | |
// 0 - 4 - 8 - 12
// 0 - 1 - 2 - 3
// ------------------------
// Assemble position and uv.
// Assemble positions.
for (let i = 0; i < 4; i++) {
const rowValue = row[i];
const rowU = spriteUVs[i].x;
const columnValue = column[i];
for (let j = 0; j < 4; j++) {
const columnValue = column[j];
const idx = i * 4 + j;
positions[idx].set(
const rowValue = row[j];
positions[i * 4 + j].set(
wE[0] * rowValue + wE[4] * columnValue + wE[12],
wE[1] * rowValue + wE[5] * columnValue + wE[13],
wE[2] * rowValue + wE[6] * columnValue + wE[14]
);
uvs[idx].set(rowU, spriteUVs[j].y);
}
}

Expand All @@ -125,5 +120,11 @@ export class SlicedSpriteAssembler {
renderer._bounds.transform(worldMatrix);
}

static updateUVs(renderer: SpriteRenderer): void {}
static updateUVs(renderer: SpriteRenderer): void {
const spriteUVs = renderer.sprite._getUVs();
const renderUVs = renderer._verticesData.uvs;
for (let i = 0; i < 16; i++) {
renderUVs[i].copyFrom(spriteUVs[i]);
}
}
}
142 changes: 67 additions & 75 deletions packages/core/src/2d/assembler/TiledSpriteAssembler.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { MathUtil, Matrix, Vector2, Vector3 } from "@galacean/engine-math";
import { StaticInterfaceImplement } from "../../base/StaticInterfaceImplement";
import { DisorderedArray } from "../../DisorderedArray";
import { SpriteTileMode } from "../enums/SpriteTileMode";
import { Basic2DBatcher } from "../../RenderPipeline/Basic2DBatcher";
import { Logger } from "../../base";
import { StaticInterfaceImplement } from "../../base/StaticInterfaceImplement";
import { SpriteTileMode } from "../enums/SpriteTileMode";
import { Sprite } from "../sprite";
import { SpriteRenderer } from "../sprite/SpriteRenderer";
import { IAssembler } from "./IAssembler";
import { Logger } from "../../base";
import { SimpleSpriteAssembler } from "./SimpleSpriteAssembler";

/**
* @internal
Expand Down Expand Up @@ -37,6 +36,7 @@ export class TiledSpriteAssembler {
const { x: pivotX, y: pivotY } = renderer.sprite.pivot;
const localTransX = renderer.width * pivotX;
const localTransY = renderer.height * pivotY;
const spUVs = sprite._getUVs();
// Renderer's worldMatrix
const { _worldMatrix: worldMatrix } = TiledSpriteAssembler;
const { elements: wE } = worldMatrix;
Expand All @@ -60,11 +60,11 @@ export class TiledSpriteAssembler {
for (let j = 0; j < columnLength; j++) {
const doubleJ = 2 * j;
for (let i = 0; i < rowLength; i++) {
const uvL = uvRow.get(2 * i);
const uvB = uvColumn.get(doubleJ);
const uvR = uvRow.get(2 * i + 1);
const uvT = uvColumn.get(doubleJ + 1);
if (isNaN(uvL) || isNaN(uvL) || isNaN(uvR) || isNaN(uvT)) {
const rFrom = uvRow.get(2 * i);
const rTo = uvRow.get(2 * i + 1);
const cFrom = uvColumn.get(doubleJ);
const cTo = uvColumn.get(doubleJ + 1);
if (isNaN(rFrom) || isNaN(rTo) || isNaN(cFrom) || isNaN(cTo)) {
continue;
}
triangles[trianglesOffset++] = count;
Expand All @@ -73,50 +73,50 @@ export class TiledSpriteAssembler {
triangles[trianglesOffset++] = count + 2;
triangles[trianglesOffset++] = count + 1;
triangles[trianglesOffset++] = count + 3;
const l = posRow.get(i);
const b = posColumn.get(j);
const r = posRow.get(i + 1);
const t = posColumn.get(j + 1);

// left and bottom
uvs[count] ? uvs[count].set(uvL, uvB) : (uvs[count] = new Vector2(uvL, uvB));
let pos = positions[count];
if (pos) {
pos.set(wE0 * l + wE4 * b + wE12, wE1 * l + wE5 * b + wE13, wE2 * l + wE6 * b + wE14);
} else {
positions[count] = new Vector3(wE0 * l + wE4 * b + wE12, wE1 * l + wE5 * b + wE13, wE2 * l + wE6 * b + wE14);
}
const LBPos = (positions[count] ||= new Vector3());
const LBUV = (uvs[count] ||= new Vector2());
count++;

// right and bottom
uvs[count] ? uvs[count].set(uvR, uvB) : (uvs[count] = new Vector2(uvR, uvB));
pos = positions[count];
if (pos) {
pos.set(wE0 * r + wE4 * b + wE12, wE1 * r + wE5 * b + wE13, wE2 * r + wE6 * b + wE14);
} else {
positions[count] = new Vector3(wE0 * r + wE4 * b + wE12, wE1 * r + wE5 * b + wE13, wE2 * r + wE6 * b + wE14);
}
const RBPos = (positions[count] ||= new Vector3());
const RBUV = (uvs[count] ||= new Vector2());
count++;

// left and top
uvs[count] ? uvs[count].set(uvL, uvT) : (uvs[count] = new Vector2(uvL, uvT));
pos = positions[count];
if (pos) {
pos.set(wE0 * l + wE4 * t + wE12, wE1 * l + wE5 * t + wE13, wE2 * l + wE6 * t + wE14);
} else {
positions[count] = new Vector3(wE0 * l + wE4 * t + wE12, wE1 * l + wE5 * t + wE13, wE2 * l + wE6 * t + wE14);
}
const LTPos = (positions[count] ||= new Vector3());
const LTUV = (uvs[count] ||= new Vector2());
count++;

// right and top
uvs[count] ? uvs[count].set(uvR, uvT) : (uvs[count] = new Vector2(uvR, uvT));
pos = positions[count];
if (pos) {
pos.set(wE0 * r + wE4 * t + wE12, wE1 * r + wE5 * t + wE13, wE2 * r + wE6 * t + wE14);
const RTPos = (positions[count] ||= new Vector3());
const RTUV = (uvs[count] ||= new Vector2());
count++;

// update position
const l = posRow.get(i);
const b = posColumn.get(j);
const r = posRow.get(i + 1);
const t = posColumn.get(j + 1);
LBPos.set(wE0 * l + wE4 * b + wE12, wE1 * l + wE5 * b + wE13, wE2 * l + wE6 * b + wE14);
RBPos.set(wE0 * r + wE4 * b + wE12, wE1 * r + wE5 * b + wE13, wE2 * r + wE6 * b + wE14);
LTPos.set(wE0 * l + wE4 * t + wE12, wE1 * l + wE5 * t + wE13, wE2 * l + wE6 * t + wE14);
RTPos.set(wE0 * r + wE4 * t + wE12, wE1 * r + wE5 * t + wE13, wE2 * r + wE6 * t + wE14);

// update uv
LBUV.copyFrom(spUVs[rFrom + cFrom * 4]);
const rowToInteger = rTo % 1;
const colToInteger = cTo % 1;
if (rowToInteger) {
Vector2.lerp(spUVs[Math.floor(rTo) + cFrom * 4], spUVs[Math.ceil(rTo) + cFrom * 4], rowToInteger, RBUV);
} else {
positions[count] = new Vector3(wE0 * r + wE4 * t + wE12, wE1 * r + wE5 * t + wE13, wE2 * r + wE6 * t + wE14);
RBUV.copyFrom(spUVs[rTo + cFrom * 4]);
}
count++;
if (colToInteger) {
Vector2.lerp(spUVs[rFrom + Math.floor(cTo) * 4], spUVs[rFrom + Math.ceil(cTo) * 4], colToInteger, LTUV);
} else {
LTUV.copyFrom(spUVs[rFrom + cTo * 4]);
}
Vector2.add(RBUV, LTUV, RTUV);
RTUV.subtract(LBUV);
}
}

Expand Down Expand Up @@ -145,7 +145,6 @@ export class TiledSpriteAssembler {
const spritePositions = sprite._getPositions();
const { x: left, y: bottom } = spritePositions[0];
const { x: right, y: top } = spritePositions[3];
const [spriteUV0, spriteUV1, spriteUV2, spriteUV3] = sprite._getUVs();
const { width: expectWidth, height: expectHeight } = sprite;
const fixedL = expectWidth * border.x;
const fixedR = expectWidth * border.z;
Expand Down Expand Up @@ -192,8 +191,8 @@ export class TiledSpriteAssembler {
if ((rVertCount - 1) * (cVertCount - 1) * 4 > Basic2DBatcher.MAX_VERTEX_COUNT) {
posRow.add(width * left), posRow.add(width * right);
posColumn.add(height * bottom), posColumn.add(height * top);
uvRow.add(spriteUV0.x), uvRow.add(spriteUV3.x);
uvColumn.add(spriteUV0.y), uvColumn.add(spriteUV3.y);
uvRow.add(0), uvRow.add(3);
uvColumn.add(0), uvColumn.add(3);
Logger.warn(`The number of vertices exceeds the upper limit(${Basic2DBatcher.MAX_VERTEX_COUNT}).`);
return;
}
Expand All @@ -203,24 +202,23 @@ export class TiledSpriteAssembler {
scale = width / fixedLR;
posRow.add(expectWidth * left * scale), posRow.add(fixedL * scale);
posRow.add(width - expectWidth * (1 - right) * scale);
uvRow.add(spriteUV0.x), uvRow.add(spriteUV1.x), uvRow.add(spriteUV2.x), uvRow.add(spriteUV3.x);
uvRow.add(0), uvRow.add(1), uvRow.add(2), uvRow.add(3);
break;
case TiledType.WithoutTiled:
posRow.add(expectWidth * left), posRow.add(fixedL), posRow.add(width - fixedR);
posRow.add(width - expectWidth * (1 - right));
uvRow.add(spriteUV0.x), uvRow.add(spriteUV1.x), uvRow.add(NaN), uvRow.add(NaN);
uvRow.add(spriteUV2.x), uvRow.add(spriteUV3.x);
uvRow.add(0), uvRow.add(1), uvRow.add(NaN), uvRow.add(NaN), uvRow.add(2), uvRow.add(3);
break;
case TiledType.WithTiled:
scale = width / (fixedLR + rRepeatCount * fixedCW);
posRow.add(expectWidth * left * scale), posRow.add(fixedL * scale);
uvRow.add(spriteUV0.x), uvRow.add(spriteUV1.x), uvRow.add(spriteUV1.x);
uvRow.add(0), uvRow.add(1), uvRow.add(1);
for (let i = 0, l = rRepeatCount - 1; i < l; i++) {
posRow.add(fixedL + (i + 1) * fixedCW * scale);
uvRow.add(spriteUV2.x), uvRow.add(spriteUV1.x);
uvRow.add(2), uvRow.add(1);
}
posRow.add(width - fixedR * scale), posRow.add(width - expectWidth * (1 - right) * scale);
uvRow.add(spriteUV2.x), uvRow.add(spriteUV2.x), uvRow.add(spriteUV3.x);
uvRow.add(2), uvRow.add(2), uvRow.add(3);
break;
default:
break;
Expand All @@ -231,24 +229,23 @@ export class TiledSpriteAssembler {
scale = height / fixedTB;
posColumn.add(expectHeight * bottom * scale), posColumn.add(fixedB * scale);
posColumn.add(height - expectHeight * (1 - top) * scale);
uvColumn.add(spriteUV0.y), uvColumn.add(spriteUV1.y), uvColumn.add(spriteUV2.y), uvColumn.add(spriteUV3.y);
uvColumn.add(0), uvColumn.add(1), uvColumn.add(2), uvColumn.add(3);
break;
case TiledType.WithoutTiled:
posColumn.add(expectHeight * bottom), posColumn.add(fixedB), posColumn.add(height - fixedT);
posColumn.add(height - expectHeight * (1 - top));
uvColumn.add(spriteUV0.y), uvColumn.add(spriteUV1.y), uvColumn.add(NaN), uvColumn.add(NaN);
uvColumn.add(spriteUV2.y), uvColumn.add(spriteUV3.y);
uvColumn.add(0), uvColumn.add(1), uvColumn.add(NaN), uvColumn.add(NaN), uvColumn.add(2), uvColumn.add(3);
break;
case TiledType.WithTiled:
scale = height / (fixedTB + cRepeatCount * fixedCH);
posColumn.add(expectHeight * bottom * scale), posColumn.add(fixedB * scale);
uvColumn.add(spriteUV0.y), uvColumn.add(spriteUV1.y), uvColumn.add(spriteUV1.y);
uvColumn.add(0), uvColumn.add(1), uvColumn.add(1);
for (let i = 0, l = cRepeatCount - 1; i < l; i++) {
posColumn.add(fixedB + (i + 1) * fixedCH * scale);
uvColumn.add(spriteUV2.y), uvColumn.add(spriteUV1.y);
uvColumn.add(2), uvColumn.add(1);
}
posColumn.add(height - fixedT * scale), posColumn.add(height - expectHeight * (1 - top) * scale);
uvColumn.add(spriteUV2.y), uvColumn.add(spriteUV2.y), uvColumn.add(spriteUV3.y);
uvColumn.add(2), uvColumn.add(2), uvColumn.add(3);
break;
default:
break;
Expand All @@ -268,7 +265,6 @@ export class TiledSpriteAssembler {
const spritePositions = sprite._getPositions();
const { x: left, y: bottom } = spritePositions[0];
const { x: right, y: top } = spritePositions[3];
const [spriteUV0, spriteUV1, spriteUV2, spriteUV3] = sprite._getUVs();
const { width: expectWidth, height: expectHeight } = sprite;
const fixedL = expectWidth * border.x;
const fixedR = expectWidth * border.z;
Expand Down Expand Up @@ -312,8 +308,8 @@ export class TiledSpriteAssembler {
if ((rVertCount - 1) * (cVertCount - 1) * 4 > Basic2DBatcher.MAX_VERTEX_COUNT) {
posRow.add(width * left), posRow.add(width * right);
posColumn.add(height * bottom), posColumn.add(height * top);
uvRow.add(spriteUV0.x), uvRow.add(spriteUV3.x);
uvColumn.add(spriteUV0.y), uvColumn.add(spriteUV3.y);
uvRow.add(0), uvRow.add(3);
uvColumn.add(0), uvColumn.add(3);
Logger.warn(`The number of vertices exceeds the upper limit(${Basic2DBatcher.MAX_VERTEX_COUNT}).`);
return;
}
Expand All @@ -323,25 +319,23 @@ export class TiledSpriteAssembler {
const scale = width / fixedLR;
posRow.add(expectWidth * left * scale), posRow.add(fixedL * scale);
posRow.add(width - expectWidth * (1 - right) * scale);
uvRow.add(spriteUV0.x), uvRow.add(spriteUV1.x), uvRow.add(spriteUV2.x), uvRow.add(spriteUV3.x);
uvRow.add(0), uvRow.add(1), uvRow.add(2), uvRow.add(3);
break;
case TiledType.WithoutTiled:
posRow.add(expectWidth * left), posRow.add(fixedL), posRow.add(width - fixedR);
posRow.add(width - expectWidth * (1 - right));
uvRow.add(spriteUV0.x), uvRow.add(spriteUV1.x), uvRow.add(NaN), uvRow.add(NaN);
uvRow.add(spriteUV2.x), uvRow.add(spriteUV3.x);
uvRow.add(0), uvRow.add(1), uvRow.add(NaN), uvRow.add(NaN), uvRow.add(2), uvRow.add(3);
break;
case TiledType.WithTiled:
posRow.add(expectWidth * left), posRow.add(fixedL);
uvRow.add(spriteUV0.x), uvRow.add(spriteUV1.x), uvRow.add(spriteUV1.x);
uvRow.add(0), uvRow.add(1), uvRow.add(1);
const countInteger = rRepeatCount | 0;
for (let i = 0; i < countInteger; i++) {
posRow.add(fixedL + (i + 1) * fixedCW);
uvRow.add(spriteUV2.x), uvRow.add(spriteUV1.x);
uvRow.add(2), uvRow.add(1);
}
posRow.add(width - fixedR), posRow.add(width - expectWidth * (1 - right));
uvRow.add((spriteUV2.x - spriteUV1.x) * (rRepeatCount - countInteger) + spriteUV1.x);
uvRow.add(spriteUV2.x), uvRow.add(spriteUV3.x);
uvRow.add(1 + rRepeatCount - countInteger), uvRow.add(2), uvRow.add(3);
break;
default:
break;
Expand All @@ -352,25 +346,23 @@ export class TiledSpriteAssembler {
const scale = height / fixedTB;
posColumn.add(expectHeight * bottom * scale), posColumn.add(fixedB * scale);
posColumn.add(height - expectHeight * (1 - top) * scale);
uvColumn.add(spriteUV0.y), uvColumn.add(spriteUV1.y), uvColumn.add(spriteUV2.y), uvColumn.add(spriteUV3.y);
uvColumn.add(0), uvColumn.add(1), uvColumn.add(2), uvColumn.add(3);
break;
case TiledType.WithoutTiled:
posColumn.add(expectHeight * bottom), posColumn.add(fixedB), posColumn.add(height - fixedT);
posColumn.add(height - expectHeight * (1 - top));
uvColumn.add(spriteUV0.y), uvColumn.add(spriteUV1.y), uvColumn.add(NaN), uvColumn.add(NaN);
uvColumn.add(spriteUV2.y), uvColumn.add(spriteUV3.y);
uvColumn.add(0), uvColumn.add(1), uvColumn.add(NaN), uvColumn.add(NaN), uvColumn.add(2), uvColumn.add(3);
break;
case TiledType.WithTiled:
posColumn.add(expectHeight * bottom), posColumn.add(fixedB);
uvColumn.add(spriteUV0.y), uvColumn.add(spriteUV1.y), uvColumn.add(spriteUV1.y);
uvColumn.add(0), uvColumn.add(1), uvColumn.add(1);
const countInteger = cRepeatCount | 0;
for (let i = 0; i < countInteger; i++) {
posColumn.add(fixedB + (i + 1) * fixedCH);
uvColumn.add(spriteUV2.y), uvColumn.add(spriteUV1.y);
uvColumn.add(2), uvColumn.add(1);
}
posColumn.add(height - fixedT), posColumn.add(height - expectHeight * (1 - top));
uvColumn.add((spriteUV2.y - spriteUV1.y) * (cRepeatCount - countInteger) + spriteUV1.y);
uvColumn.add(spriteUV2.y), uvColumn.add(spriteUV3.y);
uvColumn.add(1 + cRepeatCount - countInteger), uvColumn.add(2), uvColumn.add(3);
break;
default:
break;
Expand Down
Loading