#google-maps #google-maps-api-3 #three.js #webgl #webgloverlayview
Вопрос:
Как я могу сделать так, чтобы 3D-объекты, которые я загружаю на карту, используя WebGL overlay API, отбрасывали тени на плитки карты и на другие загруженные объекты?
Мне кажется, что это еще не поддерживается (или эта функция удалена), так есть ли какое-либо обходное решение?
Предпочитаемый фреймворк WebGL: ThreeJS
Комментарии:
1. Кто-нибудь получил ответ на этот вопрос?
Ответ №1:
Обходным решением с помощью ThreeJS было бы поместить на землю тонкую рамку (с которой она не будет работать planeGeometry
), которая полностью прозрачна, но получает тень. это может быть достигнуто с помощью shadowMaterial
Примечание: при этом будут отображаться только тени от сеток, добавленных в webgloverlay, а не от зданий на карте
Ответ №2:
У нас пока нет этой опции на карте Google, потому что наложение карты, которую мы получаем из «webgloverlayview», не имеет опции получения тени.
Я попытался создать свою собственную плоскость поверх карты Google и добиться непрозрачности тени, непрозрачность моей плоскости очень легкая, как 0,3. Я также добавил изображение ниже в цветной плоскости, чтобы объяснить.
Пожалуйста, обратитесь к @yosan_melese, ответьте префекту, чтобы использовать ShadowMaterial
вот пример кода
import { Loader } from '@googlemaps/js-api-loader';
import * as THREE from 'three';
import {FBXLoader} from 'three/examples/jsm/loaders/FBXLoader.js';
const apiOptions = {
apiKey: 'A***********8',
version: "beta",
map_ids: [""]
};
let directionalLight = '';
const mapOptions = {
"tilt": 0,
"heading": 0,
"zoom": 18,
"center": { lat: 33.57404, lng: 73.1637 },
"mapId": "" ,
"mapTypeId": 'roadmap'
}
/*
roadmap: the default map that you usually see.
satellite: satellite view of Google Maps and Google Earth, when available.
hybrid: a mixture of roadmap and satellite view.
terrain: a map based on terrain information, such as mountains and valleys.
*/
async function initMap() {
const mapDiv = document.getElementById("map");
const apiLoader = new Loader(apiOptions);
await apiLoader.load();
return new google.maps.Map(mapDiv, mapOptions);
}
let scene, renderer, camera, loader,loader1,controls;
function initWebglOverlayView(map) {
const webglOverlayView = new google.maps.WebglOverlayView();
webglOverlayView.onAdd = () => {
// set up the scene
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera();
const ambientLight = new THREE.AmbientLight( 0xffffff, 0.75 ); // soft white light
scene.add(ambientLight);
directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.x = (-90)
directionalLight.position.y = 0
directionalLight.position.z = 20
directionalLight.castShadow = true
const d = 100;
directionalLight.shadow.camera.left = - d;
directionalLight.shadow.camera.right = d;
directionalLight.shadow.camera.top = d;
directionalLight.shadow.camera.bottom = - d;
scene.add(directionalLight);
scene.add( new THREE.CameraHelper( directionalLight.shadow.camera ) );
// FLOOR
/*
const plane = new THREE.Mesh(new THREE.PlaneGeometry(2050, 2200, 300),
new THREE.MeshPhongMaterial({ color: 0xF3F4F5, opacity: 0.3, transparent: true}));
plane.rotation.x = 0;
plane.rotation.y = 0;
plane.rotation.z = 0;
plane.castShadow = true
plane.receiveShadow = true
scene.add(plane);
*/
//after yosan_melese answer i am using ShadowMaterial
const geometry = new THREE.PlaneGeometry( 2000, 2000 );
geometry.rotateX( - Math.PI / 2 );
const material = new THREE.ShadowMaterial();
material.opacity = 0.5;
const plane = new THREE.Mesh( geometry, material );
plane.rotation.x = 2;
plane.position.x = 0;
plane.position.y = 0;
plane.position.z = 0;
plane.receiveShadow = true;
scene.add( plane );
loader = new FBXLoader();
loader.load( 'model/name_model.fbx', function ( object ) {
object.scale.set( 1, 1, 1 );
object.rotation.x = 1.480;
object.rotation.y = 0.950;
object.rotation.z = 0.070;
object.castShadow = true;
object.receiveShadow = true;
object.name = "name_model";
object.traverse( function ( child ) {
if(child.isMesh ) {
child.castShadow = true;
child.receiveShadow = true;
}
});
scene.add( object );
});
}
webglOverlayView.onContextRestored = (gl) => {
// create the three.js renderer, using the
// maps's WebGL rendering context.
renderer = new THREE.WebGLRenderer({
canvas: gl.canvas,
context: gl,
...gl.getContextAttributes(),
});
renderer.autoClear = false;
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.receiveShadow = true;
renderer.castShadow = true;
}
webglOverlayView.onDraw = (gl, coordinateTransformer) => {
// update camera matrix to ensure the model is georeferenced correctly on the map
const matrix = coordinateTransformer.fromLatLngAltitude(mapOptions.center, 10);
camera.projectionMatrix = new THREE.Matrix4().fromArray(matrix);
webglOverlayView.requestRedraw();
renderer.render(scene, camera);
// always reset the GL state
renderer.resetState();
}
webglOverlayView.setMap(map);
}
(async () => {
const map = await initMap();
initWebglOverlayView(map);
})();
Комментарии:
1. попробуйте использовать shadowmaterial