Skip to content

Commit

Permalink
fixes, README
Browse files Browse the repository at this point in the history
  • Loading branch information
ivanpopelyshev committed Apr 29, 2018
1 parent 3c7f769 commit 4c4401b
Show file tree
Hide file tree
Showing 12 changed files with 185 additions and 25 deletions.
121 changes: 98 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,30 @@

[![Build Status](https://travis-ci.org/pixijs/pixi-projection.svg?branch=master)](https://travis-ci.org/pixijs/pixi-projection)

Collection of projections, both 2d and 3d.
Collection of projections, both 2d and 3d.

There are many ways to define projections even when we are using only 2 dimensions.

Two-point projections in 2d are good for parallax.

Done:

- Projective 2d transform
- Projective 2d quad mapping
- Bilinear 2d quad mapping
- Option to "drop" projection and go back to PIXI.Matrix in a child

Backlog:

- Projective 2d by euler angles
There are many ways to define projections even when we use only 2 dimensions.

To-do:

- Docs
- Graphics support
- PixiJS v5

## Examples

3d Projection (Yummy!)

[Cards](http://pixijs.github.io/examples/#/projection/cards.js)

[Runner](http://pixijs.github.io/examples/#/projection/runner.js)

Projective sprites: Container2d, Sprite2d, Text2d

[Two-point projection](http://pixijs.github.io/examples/#/projection/basic.js)

[One-point with return to affine](http://pixijs.github.io/examples/#/projection/plane.js)

[Projective transform of quad](http://pixijs.github.io/examples/#/projection/quad-homo.js)

Surface sprites: Container2s, Sprite2s, Text2s for now only bilinear
Expand All @@ -37,26 +34,104 @@ Surface sprites: Container2s, Sprite2s, Text2s for now only bilinear

## Usage

### convert existing elements
### Special classes

Same can be applied to Container2s. You cant use both projective and surface sprites
For every projective way, there are corresponding classes:

```js
* Container2d, Sprite2d, Text2d, TilingSprite2d, Mesh2d, Spine2d
* Container2s, Sprite2s
* Sprite3d, Text3d, Mesh3d2d, Spine3d, Camera3d

We dont support Graphics yet :(

Also you can convert corresponding pixi objects

```
var sprite = new PIXI.Sprite();
sprite.convertTo2d();
sprite.proj; //available now!
sprite.convertTo3d();
sprite.position3d.set(0, 0, 1); //available now!
var container = new PIXI.Container();
container.convertTo2d();
sprite.proj; //available now!
container.convertTo3d();
sprite.position3d.set(0, 0, 1); //available now!
```

You can also convert whole subtree:

```js
var tree = new PIXI.Container();
var child = new PIXI.Container();
tree.addChild(child);
tree.convertSubtreeTo2d(tree);
child.proj; //available now!
child.position3d.set(0, 0, 1); //available now!
```

### 3D transforms

The most useful thing is 3D transforms.

It all, starts from a camera, dont use 3d elements outside of it - it doesnt make sence.

You can create several cameras if you want each element to has his own perspective parameters.

```js
var camera = new PIXI.projection.Camera3d();
camera.setPlanes(400, 10, 10000, false); // true if you want orthographics projection
// I assume you have an app or renderer already
camera.position.set(app.screen.width / 2, app.screen.height / 2);
```

In this case, 400 is focus distance. If width of the screen is 800, that means 90 degrees horizontal FOV.
Everything that's behind `z < -390` will be cut by near plane, everything that's too far away `z > 9600` will be cut too.

We position camera at the center of the screen, so element with `position3d=(0,0,0)` will appear right in center.
However, camera can look at something else - a character, or just the point with same coords as center of the screen.

```js
camera.position3d.set(app.screen.width/2, app.screen.height/2);
```

With this snippet, every element in the camera that does not use extra 3d fields (`z`, `euler`) will appear exactly like in pixi stage.
That's how awesome our Camera implementation is!

Camera transform differs from other elements:

```js
//camera follows player
camera.position3d.copy(player.position3d);
// player is two times smaller now
player.scale3d.set(0.5);
// but camera follows it too, now everything except player is two times bigger on screen :)
camera.scale3d.set(0.5);
```

Containers and Sprites have extra fields for positioning inside 3d space.

PixiJS gives only `position`, `scale`, `rotation`, `pivot`,
and projection plugin adds `position3d`, `euler`, `scale3d`, `pivot3d`. Those fields applied in transforms after vanilla pixi fields.

The only exception is a `Camera3d`, that applies `projection` just after pixi fields, and then applies 3d fields in **reversed** order.
That's why it can follow elements - its transform negates the element transform.

For complex objects like `Spine` there are two ways to add them:

1. Use corresponding class in projection lib: `PIXI.projection.spine.Spine`
2. Create `Container3d` that returns all children to 2d space: `container3d.affine = PIXI.projection.AFFINE.AXIS_X;`
Any 2d elements added to that container will think of it as a simple 2d container, and custom renderers will work with it just fine.

### Sorting

`pixi-projection` provides extra fields to handle sorting.

* `getDepth` returns the distance from near plane to the object local (0,0,0)
* `isFrontFace` detects the face of the object plane

Those fields can be used with custom sorting solution or with [pixi-layers](https://github.com/pixijs/pixi-display/tree/layers/)

### Culling

Will be available after we add it to `pixi-layers`

## Building

You will need to have [node][node] setup on your machine.
Expand Down
8 changes: 8 additions & 0 deletions dist/pixi-projection-spine.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,8 @@ declare module PIXI.projection {
pivot3d: PIXI.PointLike;
}
let container3dToLocal: <T extends PIXI.PointLike>(position: PIXI.PointLike, from?: PIXI.DisplayObject, point?: T, skipUpdate?: boolean, step?: TRANSFORM_STEP) => T;
let container3dGetDepth: (forceUpdate?: boolean) => number;
let container3dIsFrontFace: (forceUpdate?: boolean) => boolean;
}
declare module PIXI.projection {
class Euler implements PIXI.PointLike {
Expand Down Expand Up @@ -479,6 +481,8 @@ declare module PIXI.projection {
proj: Projection3d;
readonly worldTransform: any;
toLocal<T extends PIXI.PointLike>(position: PIXI.PointLike, from?: PIXI.DisplayObject, point?: T, skipUpdate?: boolean, step?: TRANSFORM_STEP): T;
isFrontFace(forceUpdate?: boolean): any;
getDepth(forceUpdate?: boolean): any;
position3d: PIXI.PointLike;
scale3d: PIXI.PointLike;
euler: Euler;
Expand Down Expand Up @@ -565,6 +569,8 @@ declare module PIXI.projection {
containsPoint(point: PIXI.PointLike): boolean;
readonly worldTransform: any;
toLocal<T extends PIXI.PointLike>(position: PIXI.PointLike, from?: PIXI.DisplayObject, point?: T, skipUpdate?: boolean, step?: TRANSFORM_STEP): T;
isFrontFace(forceUpdate?: boolean): any;
getDepth(forceUpdate?: boolean): any;
position3d: PIXI.PointLike;
scale3d: PIXI.PointLike;
euler: Euler;
Expand All @@ -577,6 +583,8 @@ declare module PIXI.projection {
proj: Projection3d;
readonly worldTransform: any;
toLocal<T extends PIXI.PointLike>(position: PIXI.PointLike, from?: PIXI.DisplayObject, point?: T, skipUpdate?: boolean, step?: TRANSFORM_STEP): T;
isFrontFace(forceUpdate?: boolean): any;
getDepth(forceUpdate?: boolean): any;
position3d: PIXI.PointLike;
scale3d: PIXI.PointLike;
euler: Euler;
Expand Down
21 changes: 21 additions & 0 deletions dist/pixi-projection-spine.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/pixi-projection-spine.js.map

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions dist/pixi-projection.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,8 @@ declare module PIXI.projection {
pivot3d: PIXI.PointLike;
}
let container3dToLocal: <T extends PIXI.PointLike>(position: PIXI.PointLike, from?: PIXI.DisplayObject, point?: T, skipUpdate?: boolean, step?: TRANSFORM_STEP) => T;
let container3dGetDepth: (forceUpdate?: boolean) => number;
let container3dIsFrontFace: (forceUpdate?: boolean) => boolean;
}
declare module PIXI.projection {
class Euler implements PIXI.PointLike {
Expand Down Expand Up @@ -479,6 +481,8 @@ declare module PIXI.projection {
proj: Projection3d;
readonly worldTransform: any;
toLocal<T extends PIXI.PointLike>(position: PIXI.PointLike, from?: PIXI.DisplayObject, point?: T, skipUpdate?: boolean, step?: TRANSFORM_STEP): T;
isFrontFace(forceUpdate?: boolean): any;
getDepth(forceUpdate?: boolean): any;
position3d: PIXI.PointLike;
scale3d: PIXI.PointLike;
euler: Euler;
Expand Down Expand Up @@ -565,6 +569,8 @@ declare module PIXI.projection {
containsPoint(point: PIXI.PointLike): boolean;
readonly worldTransform: any;
toLocal<T extends PIXI.PointLike>(position: PIXI.PointLike, from?: PIXI.DisplayObject, point?: T, skipUpdate?: boolean, step?: TRANSFORM_STEP): T;
isFrontFace(forceUpdate?: boolean): any;
getDepth(forceUpdate?: boolean): any;
position3d: PIXI.PointLike;
scale3d: PIXI.PointLike;
euler: Euler;
Expand All @@ -577,6 +583,8 @@ declare module PIXI.projection {
proj: Projection3d;
readonly worldTransform: any;
toLocal<T extends PIXI.PointLike>(position: PIXI.PointLike, from?: PIXI.DisplayObject, point?: T, skipUpdate?: boolean, step?: TRANSFORM_STEP): T;
isFrontFace(forceUpdate?: boolean): any;
getDepth(forceUpdate?: boolean): any;
position3d: PIXI.PointLike;
scale3d: PIXI.PointLike;
euler: Euler;
Expand Down
21 changes: 21 additions & 0 deletions dist/pixi-projection.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/pixi-projection.js.map

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions src/proj3d/Container3d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,6 @@ namespace pixi_projection {
}

export let container3dToLocal = Container3d.prototype.toLocal;
export let container3dGetDepth = Container3d.prototype.getDepth;
export let container3dIsFrontFace = Container3d.prototype.isFrontFace;
}
8 changes: 8 additions & 0 deletions src/proj3d/mesh/Mesh3d2d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ namespace pixi_projection {
return container3dToLocal.call(this, position, from, point, skipUpdate, step);
}

isFrontFace(forceUpdate?: boolean) {
return container3dIsFrontFace.call(this, forceUpdate);
}

getDepth(forceUpdate?: boolean) {
return container3dGetDepth.call(this, forceUpdate);
}

get position3d(): PIXI.PointLike {
return this.proj.position;
}
Expand Down
8 changes: 8 additions & 0 deletions src/proj3d/sprites/Sprite3d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,14 @@ namespace pixi_projection {
step = TRANSFORM_STEP.ALL): T {
return container3dToLocal.call(this, position, from, point, skipUpdate, step);
}

isFrontFace(forceUpdate?: boolean) {
return container3dIsFrontFace.call(this, forceUpdate);
}

getDepth(forceUpdate?: boolean) {
return container3dGetDepth.call(this, forceUpdate);
}

get position3d(): PIXI.PointLike {
return this.proj.position;
Expand Down
8 changes: 8 additions & 0 deletions src/proj3d/sprites/Text3d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ namespace pixi_projection {
return container3dToLocal.call(this, position, from, point, skipUpdate, step);
}

isFrontFace(forceUpdate?: boolean) {
return container3dIsFrontFace.call(this, forceUpdate);
}

getDepth(forceUpdate?: boolean) {
return container3dGetDepth.call(this, forceUpdate);
}

get position3d(): PIXI.PointLike {
return this.proj.position;
}
Expand Down
Loading

0 comments on commit 4c4401b

Please sign in to comment.