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

fix zoomto for gltfmarker #32

Merged
merged 3 commits into from
Dec 13, 2024
Merged
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
17 changes: 14 additions & 3 deletions packages/layer-gltf/src/GLTFLineString.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,19 @@ export default class GLTFLineString extends MultiGLTFMarker {
}

toJSON() {
const json = super.toJSON();
json['type'] = 'GLTFLineString';
const json = JSON.parse(JSON.stringify({
coordinates : this._coordinates,
options: this.options,
type: 'GLTFLineString'
}));
const id = this.getId();
if (!Util.isNil(id)) {
json.options['id'] = id;
}
const properties = this.getProperties();
if (json.options) {
json.options['properties'] = properties;
}
return json;
}

Expand Down Expand Up @@ -115,7 +126,7 @@ export default class GLTFLineString extends MultiGLTFMarker {
const scale = [1, 1, 1];
const modelHeight = this.getModelHeight();
if (modelHeight) {
this._calModelHeightScale(scale);
this._calModelHeightScale(scale, modelHeight);
} else {
const symbol = this.getSymbol();
vec3.set(scale, symbol.scaleX || 1, symbol.scaleY || 1, symbol.scaleZ || 1);
Expand Down
86 changes: 59 additions & 27 deletions packages/layer-gltf/src/GLTFMarker.js
Original file line number Diff line number Diff line change
Expand Up @@ -764,7 +764,13 @@ export default class GLTFMarker extends Marker {
}
const bbox = { min, max };
this._markerBBox = bbox;
this._dirtyMarkerBBox = false;
if (this.getGLTFMarkerType() === 'multigltfmarker') {//MultiGLTFMarker的BoundingBox受数据项数量影响, 是否dirty需要特殊处理
if (this._data.length) {
this._dirtyMarkerBBox = false;
}
} else {
this._dirtyMarkerBBox = false;
}
return bbox;
}

Expand Down Expand Up @@ -1627,43 +1633,69 @@ export default class GLTFMarker extends Marker {
return this._gltfModelBBox;
}

zoomTo(zoomOffset, options = { animation: false }) {
/**
* set transltion, rotation and scale for specific node
* @param {Object} options an option object including animation{boolean}、duration{number}、pitch{number}、bearing{number}、zoomOffset{number}、heightOffset{number}
* @param {Function} - step function during animation, animation frame as the parameter
* @return this
*/
zoomTo(options = { animation: true }, step) {
const markerBBox = this.getBoundingBox();
const map = this.getMap();
if (!map || !markerBBox) {
return;
}
const { min, max } = markerBBox;
TEMP_POINT.set(min[0], min[1]);
const minCoord = map.pointAtResToCoordinate(TEMP_POINT, map.getGLRes());
TEMP_POINT.set(max[0], max[1]);
const maxCoord = map.pointAtResToCoordinate(TEMP_POINT, map.getGLRes());
const extent = new Extent(minCoord, maxCoord);
map.fitExtent(extent, zoomOffset, options, (params) => {
if (params.state.playState === 'finished') {
this._zoomToEnd(min, max, extent);
}
});
if (options.animation === false) {
this._zoomToEnd(min, max, extent);
TEMP_POINT.set((min[0] + max[0]) / 2, (min[1] + max[1]) / 2);
const glRes = map.getGLRes();
const bboxCenter = map.pointAtResToCoordinate(TEMP_POINT, glRes);
bboxCenter.z = ((min[2] + max[2]) / 2) / map.altitudeToPoint(1, glRes);
return this._zoomTo(bboxCenter, options, step);
}

_zoomTo(center, options, step) {
const map = this.getMap();
const pitch = options.pitch || map.getPitch();
const bearing = options.bearing || map.getBearing();
const duration = options.duration || 500;
const easing = options.easing || 'linear';
const zoom = this._getFitZoomByBoundingBox(options.heightOffset || 0) + (options.zoomOffset || 0);
if (options.animation || options.animation === undefined) {
map.animateTo({
center,
zoom,
bearing,
pitch
}, {
duration,
easing
}, step);
} else {
map.setView({
center,
zoom,
bearing,
pitch
});
}
return this;
}

_zoomToEnd(min, max, extent) {
_getFitZoomByBoundingBox(heightOffset) {
const map = this.getMap();
const glRes = map.getGLRes();
const h = (min[2] + max[2]) / 2;
const height = h / map.altitudeToPoint(1, glRes);
const cameraPosition = map.cameraPosition;
const cameraCoordinate = map.pointAtResToCoordinate(new Point(cameraPosition), glRes);
const cameraHeight = cameraPosition[2] / map.altitudeToPoint(1, glRes);
cameraCoordinate.z = cameraHeight + height;
map.setCameraOrientation({
position: [cameraCoordinate.x, cameraCoordinate.y, cameraCoordinate.z],
pitch: map.getPitch(),
bearing: map.getBearing()
});
this.fire('zoomtoend', { target: this, extent });
const meterToGLPoint = map.distanceToPointAtRes(100, 0, glRes).x / 100;
const markerBBox = this.getBoundingBox();
const { min, max } = markerBBox;
const maxHeight = max[2] / map.altitudeToPoint(1, glRes) + heightOffset;
const zoom1 = map.getFitZoomForAltitude(maxHeight * meterToGLPoint);
TEMP_POINT.set(min[0], min[1]);
const minCoord = map.pointAtResToCoordinate(TEMP_POINT, map.getGLRes());
TEMP_POINT.set(max[0], max[1]);
const maxCoord = map.pointAtResToCoordinate(TEMP_POINT, map.getGLRes());
const extent = new Extent(minCoord, maxCoord);
const zoom2 = map.getFitZoom(extent);
return zoom1 < zoom2 ? zoom1 : zoom2;
}

_isUniformsDirty() {
Expand Down
15 changes: 15 additions & 0 deletions packages/layer-gltf/src/MultiGLTFMarker.js
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,21 @@ export default class MultiGLTFMarker extends GLTFMarker {
});
this._dirty = true;
}

/**
* set transltion, rotation and scale for specific node
* @param {Object} options an option object including animation{boolean}、duration{number}、pitch{number}、bearing{number}、zoomOffset{number}
* @param {Function} - step function during animation, animation frame as the parameter
* @return this
*/
zoomAt(index, options = { animation: true, zoomOffset: 0 }, step) {
const dataItem = this._data[index];
if (!dataItem) {
throw new Error('data item is not exist');
}
const center = new Coordinate(dataItem.coordinates);
return this._zoomTo(center, options, step);
}
}

MultiGLTFMarker.registerJSONType('MultiGLTFMarker');
34 changes: 33 additions & 1 deletion packages/layer-gltf/test/FixBugSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1918,7 +1918,7 @@ describe('bug', () => {
const pixel = pickPixel(map, map.width / 2, map.height / 2, 1, 1);
expect(pixelMatch([146, 146, 146, 255], pixel)).to.be.eql(true);
done();
}, 100);
}, 600);
}
marker.on('load', () => {
marker.zoomTo();
Expand All @@ -1927,6 +1927,38 @@ describe('bug', () => {
new maptalks.GroupGLLayer('gl', [gltflayer], { sceneConfig }).addTo(map);
});

// it('zoomto with altitude、bearing、pitch、zoomOffset、duration、step', done => {
// const gltflayer = new maptalks.GLTFLayer('gltf');
// const position = center.add(0, 1);
// position.z = 100;
// const marker = new maptalks.GLTFGeometry(position,
// { symbol: { url: url2,
// modelHeight: 100
// }});
// gltflayer.addGeometry(marker);
// let frm = null;
// function checkColor() {
// setTimeout(function() {
// const pixel = pickPixel(map, map.width / 2, map.height / 2 - 50, 1, 1);
// expect(pixelMatch([71, 97, 117, 255], pixel)).to.be.eql(true);
// expect(frm).to.be.ok();
// done();
// }, 400);
// }
// marker.on('load', () => {
// marker.zoomTo({
// bearing: 45,
// pitch: 45,
// zoomOffset: -1,
// duration: 300
// }, (frame) => {
// frm = frame;
// });
// checkColor();
// });
// new maptalks.GroupGLLayer('gl', [gltflayer], { sceneConfig }).addTo(map);
// });

it('highlightNodes before added to gltflayer(maptalks/issues#709)', (done) => {
const gltflayer = new maptalks.GLTFLayer('gltf');
const marker = new maptalks.GLTFGeometry(center,
Expand Down
45 changes: 44 additions & 1 deletion packages/layer-gltf/test/GLTFLineStringSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,5 +84,48 @@ describe('GLTFLineString', () => {
}, 100);
});
new maptalks.GroupGLLayer('gl', [gltflayer], { sceneConfig }).addTo(map);
})
});

it('zoomTo', done => {
map.setCenter([1, 1]);
const gltflayer = new maptalks.GLTFLayer('gltf');
const gltfline = new maptalks.GLTFLineString(coordinates, {
direction: 2,
symbol: {
url: './models/fence/wooden_fence.glb',
rotationZ: 90
},
}).addTo(gltflayer);
gltfline.on('load', () => {
gltfline.zoomTo();
setTimeout(function() {
const pixel1 = pickPixel(map, map.width / 2, map.height / 2, 1, 1);
expect(pixelMatch([62, 48, 37, 255], pixel1)).to.be.eql(true);
const pixel2 = pickPixel(map, 295, 140, 1, 1);
expect(pixelMatch([0, 0, 0, 0], pixel2)).to.be.eql(true);
done();
}, 600);
});
new maptalks.GroupGLLayer('gl', [gltflayer], { sceneConfig }).addTo(map);
});

it('toJSON', done => {
const gltflayer = new maptalks.GLTFLayer('gltf');
const gltfline = new maptalks.GLTFLineString(coordinates, {
direction: 2,
symbol: {
url: './models/fence/wooden_fence.glb',
rotationZ: 90
},
}).addTo(gltflayer);
gltfline.on('load', () => {
gltfline.zoomTo();
setTimeout(function() {
const json = gltfline.toJSON();
expect(json.coordinates.length).to.be.eql(3);
done();
}, 100);
});
new maptalks.GroupGLLayer('gl', [gltflayer], { sceneConfig }).addTo(map);
});
});
6 changes: 4 additions & 2 deletions packages/transform-control/src/common/Util.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { mat4, reshader, quat, vec3, gltf } from '@maptalks/gl';
import { mat4, reshader, quat, vec3 } from '@maptalks/gl';
import partsModels from './models';
import * as maptalks from 'maptalks';
import { getGLTFLoaderBundle } from '@maptalks/gl/dist/transcoders';

const gltfloader = getGLTFLoaderBundle();
const point = [];
function createGLTFMesh(modelName) {
const loader = new gltf.GLTFLoader('', JSON.parse(JSON.stringify(partsModels[modelName])));//避免tc在移除后,再添加新的,内置的gltf受影响
const loader = new gltfloader.GLTFLoader('', JSON.parse(JSON.stringify(partsModels[modelName])));//避免tc在移除后,再添加新的,内置的gltf受影响
return loader.load().then(gltf => {
return gltf;
});
Expand Down