Skip to content

Commit

Permalink
feat: support CZML in reearth/core (#383)
Browse files Browse the repository at this point in the history
* chore: remove legacy prefix for Resource component

* feat: support CZML

* feat: add extractSimpleLayerData util

* Update src/core/engines/Cesium/Feature/Resource/index.stories.tsx

Co-authored-by: rot1024 <aayhrot@gmail.com>

* feat: support glTF on reearth/core (#386)

* feat: support gltf

* fix: add url in model appearance

Co-authored-by: rot1024 <aayhrot@gmail.com>
  • Loading branch information
keiya01 and rot1024 committed Jan 10, 2023
1 parent 4f36add commit f44d986
Show file tree
Hide file tree
Showing 16 changed files with 259 additions and 30 deletions.
55 changes: 55 additions & 0 deletions .storybook/public/testdata/sample.czml
@@ -0,0 +1,55 @@
[
{
"id": "document",
"name": "Japan",
"version": "1.0"
},
{
"id": "1",
"name": "Sendai city",
"description": "This is Sendai city of Miyagi prefecture.",
"position": {
"cartographicDegrees": [
140.87636805791237,
38.26835288549171,
0
]
},
"point": {
"color": { "rgba": [255, 0, 255, 255] },
"pixelSize": 100
}
},
{
"id": "2",
"name": "Fukushima city",
"description": "This is Fukushima city of Fukushima prefecture.",
"position": {
"cartographicDegrees": [
140.47334452422348,
37.76702444930477,
0
]
},
"point": {
"color": { "rgba": [0, 255, 255, 255] },
"pixelSize": 100
}
},
{
"id": "3",
"name": "Tokyo",
"description": "This is Tokyo prefecture.",
"position": {
"cartographicDegrees": [
139.6904487961309,
35.685394553171434,
0
]
},
"point": {
"color": { "rgba": [255, 255, 0, 255] },
"pixelSize": 100
}
}
]
70 changes: 70 additions & 0 deletions .storybook/public/testdata/sample.gltf
@@ -0,0 +1,70 @@
{
"scene": 0,
"scenes" : [
{
"nodes" : [ 0 ]
}
],

"nodes" : [
{
"mesh" : 0
}
],

"meshes" : [
{
"primitives" : [ {
"attributes" : {
"POSITION" : 1
},
"indices" : 0
} ]
}
],

"buffers" : [
{
"uri" : "data:application/octet-stream;base64,AAABAAIAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAA=",
"byteLength" : 44
}
],
"bufferViews" : [
{
"buffer" : 0,
"byteOffset" : 0,
"byteLength" : 6,
"target" : 34963
},
{
"buffer" : 0,
"byteOffset" : 8,
"byteLength" : 36,
"target" : 34962
}
],
"accessors" : [
{
"bufferView" : 0,
"byteOffset" : 0,
"componentType" : 5123,
"count" : 3,
"type" : "SCALAR",
"max" : [ 2 ],
"min" : [ 0 ]
},
{
"bufferView" : 1,
"byteOffset" : 0,
"componentType" : 5126,
"count" : 3,
"type" : "VEC3",
"max" : [ 1.0, 1.0, 0.0 ],
"min" : [ 0.0, 0.0, 0.0 ]
}
],

"asset" : {
"version" : "2.0"
}
}
49 changes: 49 additions & 0 deletions src/core/engines/Cesium/Feature/Model/index.stories.tsx
@@ -0,0 +1,49 @@
import { Meta, Story } from "@storybook/react";

import { engine } from "../../";
import Component, { Props } from "../../../../Map";

export default {
title: "core/engines/Cesium/Feature/Model",
component: Component,
parameters: { actions: { argTypesRegex: "^on.*" } },
} as Meta;

const Template: Story<Props> = args => <Component {...args} />;

export const Default = Template.bind([]);
Default.args = {
engine: "cesium",
engines: {
cesium: engine,
},
ready: true,
layers: [
{
id: "l",
type: "simple",
data: {
type: "geojson",
value: {
type: "Feature",
geometry: {
type: "Point",
coordinates: [0, 0, 1000],
},
},
},
model: {
url: "/BoxAnimated.glb",
scale: 1000000,
},
},
],
property: {
tiles: [
{
id: "default",
tile_type: "default",
},
],
},
};
7 changes: 4 additions & 3 deletions src/core/engines/Cesium/Feature/Model/index.tsx
Expand Up @@ -28,6 +28,7 @@ export default function Model({ id, isVisible, property, geometry, layer, featur

const {
model,
url,
heightReference: hr,
heading,
pitch,
Expand Down Expand Up @@ -69,7 +70,7 @@ export default function Model({ id, isVisible, property, geometry, layer, featur
const modelLightColor = useMemo(() => toColor(lightColor), [lightColor]);
const modelSilhouetteColor = useMemo(() => toColor(silhouetteColor), [silhouetteColor]);

return !isVisible || !model || !position ? null : (
return !isVisible || (!model && !url) || !position ? null : (
<EntityExt
id={id}
position={position}
Expand All @@ -78,7 +79,7 @@ export default function Model({ id, isVisible, property, geometry, layer, featur
featureId={feature?.id}
draggable>
<ModelGraphics
uri={model}
uri={model || url}
scale={scale}
shadows={shadowMode(shadows)}
colorBlendMode={colorBlendMode(colorBlend)}
Expand All @@ -97,5 +98,5 @@ export default function Model({ id, isVisible, property, geometry, layer, featur
}

export const config: FeatureComponentConfig = {
noFeature: true,
noLayer: true,
};
40 changes: 40 additions & 0 deletions src/core/engines/Cesium/Feature/Resource/index.stories.tsx
@@ -0,0 +1,40 @@
import { Meta, Story } from "@storybook/react";

import { engine } from "../..";
import Component, { Props } from "../../../../Map";

export default {
title: "core/engines/Cesium/Feature/Resource",
component: Component,
parameters: { actions: { argTypesRegex: "^on.*" } },
} as Meta;

const Template: Story<Props> = args => <Component {...args} />;

export const Default = Template.bind([]);
Default.args = {
engine: "cesium",
engines: {
cesium: engine,
},
ready: true,
layers: [
{
id: "l",
type: "simple",
data: {
type: "czml",
url: "/testdata/sample.czml",
},
resource: {},
},
],
property: {
tiles: [
{
id: "default",
tile_type: "default",
},
],
},
};
23 changes: 16 additions & 7 deletions src/core/engines/Cesium/Feature/Resource/index.tsx
@@ -1,11 +1,11 @@
import { useMemo } from "react";
import { KmlDataSource, CzmlDataSource, GeoJsonDataSource } from "resium";

import type { LegacyResourceAppearance } from "../../..";
import { type FeatureComponentConfig, type FeatureProps } from "../utils";
import type { ResourceAppearance } from "../../..";
import { extractSimpleLayerData, type FeatureComponentConfig, type FeatureProps } from "../utils";

export type Props = FeatureProps<Property>;
export type Property = LegacyResourceAppearance;
export type Property = ResourceAppearance;
const types: Record<string, "geojson" | "kml" | "czml"> = {
kml: "kml",
geojson: "geojson",
Expand All @@ -18,8 +18,15 @@ const comps = {
geojson: GeoJsonDataSource,
};

export default function Resource({ isVisible, property }: Props) {
const { url, type, clampToGround } = property ?? {};
export default function Resource({ isVisible, property, layer }: Props) {
const { clampToGround } = property ?? {};
const [type, url] = useMemo((): [ResourceAppearance["type"], string | undefined] => {
const data = extractSimpleLayerData(layer);
const type = property?.type;
const url = property?.url;
return [type ?? (data?.type as ResourceAppearance["type"]), url ?? data?.url];
}, [property, layer]);

const ext = useMemo(
() => (!type || type === "auto" ? url?.match(/\.([a-z]+?)(?:\?.*?)?$/) : undefined),
[type, url],
Expand All @@ -29,7 +36,9 @@ export default function Resource({ isVisible, property }: Props) {

if (!isVisible || !Component || !url) return null;

return <Component data={url} clampToGround={clampToGround} />;
return <Component data={url} show={true} clampToGround={clampToGround} />;
}

export const config: FeatureComponentConfig = {};
export const config: FeatureComponentConfig = {
noFeature: true,
};
10 changes: 2 additions & 8 deletions src/core/engines/Cesium/Feature/index.tsx
Expand Up @@ -24,7 +24,7 @@ const components: Record<keyof AppearanceTypes, [FeatureComponent, FeatureCompon
"3dtiles": [Tileset, tilesetConfig],
box: [Box, boxConfig],
photooverlay: [PhotoOverlay, photoOverlayConfig],
legacy_resource: [Resource, resourceConfig],
resource: [Resource, resourceConfig],
};

export default function Feature({
Expand All @@ -37,13 +37,7 @@ export default function Feature({
{[undefined, ...layer.features].flatMap(f =>
(Object.keys(components) as (keyof AppearanceTypes)[]).map(k => {
const [C, config] = components[k] ?? [];
if (
!C ||
(f && !f[k]) ||
!layer[k] ||
(config.noLayer && !f) ||
(config.noFeature && f)
) {
if (!C || (f && !f[k]) || (config.noLayer && !f) || (config.noFeature && f)) {
return null;
}

Expand Down
9 changes: 9 additions & 0 deletions src/core/engines/Cesium/Feature/utils.tsx
Expand Up @@ -10,6 +10,8 @@ import {
} from "react";
import { type CesiumComponentRef, Entity } from "resium";

import { Data } from "@reearth/core/mantle";

import type { ComputedFeature, ComputedLayer, FeatureComponentProps, Geometry } from "../..";

export type FeatureProps<P = any> = {
Expand Down Expand Up @@ -110,3 +112,10 @@ const tagObj: { [k in keyof Tag]: 1 } = {
const tagKeys = Object.keys(tagObj) as (keyof Tag)[];

const tagKey = "__reearth_tag";

export const extractSimpleLayerData = (layer: ComputedLayer | undefined): Data | void => {
if (layer?.layer.type !== "simple") {
return;
}
return layer.layer.data;
};
2 changes: 1 addition & 1 deletion src/core/engines/Cesium/index.tsx
Expand Up @@ -192,5 +192,5 @@ export const engine: Engine = {
component: Component,
featureComponent: Feature,
clusterComponent: Cluster,
// delegatedDataTypes: ["3dtiles", "czml"],
delegatedDataTypes: ["czml"],
};
2 changes: 1 addition & 1 deletion src/core/engines/index.ts
Expand Up @@ -29,5 +29,5 @@ export type {
MarkerAppearance,
ModelAppearance,
LegacyPhotooverlayAppearance,
LegacyResourceAppearance,
ResourceAppearance,
} from "../mantle";
4 changes: 2 additions & 2 deletions src/core/mantle/compat/backward.test.ts
Expand Up @@ -340,12 +340,12 @@ test("3dtiles", () => {
});
});

test("legacy_resource", () => {
test("resource", () => {
expect(
getCompat({
id: "xxx",
type: "simple",
legacy_resource: {
resource: {
url: "xxx",
aaaa: 1,
},
Expand Down
4 changes: 2 additions & 2 deletions src/core/mantle/compat/backward.ts
Expand Up @@ -168,11 +168,11 @@ export function getCompat(l: Layer | undefined): LayerCompat | undefined {
: {}),
},
};
} else if ("legacy_resource" in l) {
} else if ("resource" in l) {
extensionId = "resource";
property = {
default: {
...(l as any).legacy_resource,
...(l as any).resource,
},
};
}
Expand Down
2 changes: 1 addition & 1 deletion src/core/mantle/compat/forward.test.ts
Expand Up @@ -472,7 +472,7 @@ test("resource", () => {
id: "x",
type: "simple",
visible: true,
legacy_resource: {
resource: {
url: "xxx",
hoge: "red",
},
Expand Down

0 comments on commit f44d986

Please sign in to comment.