How to get original pixel color before shader - openlayers-6

I have an ImageLayer and a RasterSource which uses a shader to manipulate the colors of the image.
While listening to the map's pointermove I get the color of the pixel under the pointer which is the color manipulated by the shader.
How can I get the original color before it was manipulated by the shader?
const extent = [0, 0, 1024, 968]; // the image extent in pixels.
const projection = new Projection({
code: 'xkcd-image',
units: 'pixels',
extent: extent,
});
let staticImage = new Static({ // from 'ol/source/ImageStatic'
attributions: '© xkcd',
url: "./assets/map.png",
projection: projection,
imageExtent: extent
});
let imageLayer = new ImageLayer({ // from 'ol/layer/Image'
source: new RasterSource({
sources: [staticImage],
operation: function (pixels, data) {
let p = pixels[0];
let grayscale = (p[0] + p[1] + p[2]) / 3;
p[0] = grayscale;
p[1] = grayscale;
p[2] = grayscale;
return p;
}
})
});
let map; // Map from 'ol'
map.on('pointermove', (evt) => {
let pixel = evt.pixel;
let color = imageLayer.getRenderer().getDataAtPixel(pixel, evt.framestate, 1);
// color is the one manipulated by the shader
});
More code here:
https://codesandbox.io/s/raster-original-pixel-3mejh9?file=/main.js
Note: because of security restrictions I've had to comment out the shader code which turns the colors gray
Which was adapted from this example:
https://openlayers.org/en/latest/examples/static-image.html

I found a workaround by adding a duplicate RasterLayer with a no-op operation. The trick is to add the layer just after the color manipulated layer, but with an opacity of 0.005 (apparently the lowest possible value) so it's rendered but you don't see it. Then combine the grey color's alpha with the original color's RGB values:
let noopLayer = new ImageLayer({
opacity: 0.005,
source: new RasterSource({
sources: [
staticImage
],
operation: function (pixels, data) {
let p = pixels[0];
return p;
},
}),
});
const map = new Map({
layers: [
rasterLayer,
noopLayer,
],
target: 'map',
view: new View({
projection: projection,
center: getCenter(extent),
zoom: 2,
maxZoom: 8,
}),
});
map.on('pointermove', (evt) => {
const pixel = evt.pixel;
let grey = rasterLayer.getRenderer().getDataAtPixel(pixel, evt.framestate, 1);
let noop = noopLayer.getRenderer().getDataAtPixel(pixel, evt.framestate, 1);
if (grey != null) {
// [228, 228, 228, 255]
console.log('grey:', grey[0], grey[1], grey[2], grey[3]);
// [255, 255, 170, 3]
console.log('noop:', noop[0], noop[1], noop[2], noop[3]);
// [255, 255, 170, 255]
console.log('original:', noop[0], noop[1], noop[2], grey[3]);
}
});

Related

Three.js load a gltf model and set color for it but when zooming out it is all black

Hello everyone,I have meet a strange problem which is that I loaded a gltf model in three.js and set color for it.When zooming in it has colors, but when zooming out,it is all black.And when I directly set color for it's material,it can works well.
Thank you.
here is the sample sreenphotos and code.
loadGlbModel() {
const loader = new GLTFLoader();
loader.load(
`/three/eiffel-tower.gltf`,
(gltf) => {
const geometry = gltf.scene.children[0].geometry;
const positions = geometry.attributes.position;
const count = positions.count;
geometry.setAttribute(
"color",
new THREE.BufferAttribute(new Float32Array(count * 3), 3)
);
const color = new THREE.Color();
const colors = geometry.attributes.color;
const radius = 200;
debugger;
for (let i = 0; i < count; i++) {
color.setHSL(positions.getY(i) / radius / 2, 1.0, 0.5);
colors.setXYZ(i, 1, 0, 0);
}
const material = new THREE.MeshPhongMaterial({
color: 0xffffff,
flatShading: true,
vertexColors: true,
shininess: 0,
});
const wireframeMaterial = new THREE.MeshBasicMaterial({
color: 0x000000,
wireframe: true,
transparent: true,
});
let mesh = new THREE.Mesh(geometry, material);
let wireframe = new THREE.Mesh(geometry, wireframeMaterial);
mesh.add(wireframe);
mesh.scale.set(0.1, 0.1, 0.1);
const redColor = new THREE.Color(1, 0, 0);
console.log(mesh);
// mesh.children[0].material.color = redColor;
const light = new THREE.DirectionalLight(0xffffff);
light.position.set(0, 0, 1);
this.scene.add(light);
this.scene.add(mesh);
},
(xhr) => {
console.log((xhr.loaded / xhr.total) * 100 + "% loaded");
},
(error) => {
console.error(error);
}
);
},
You are rendering the wireframe version too, which consists of lines in screen-space. As you zoom out, these lines maintain the same width in pixels, thus covering everything else.
Do you wish to render the fireframe too? If not, don't. If you do, then consider hiding it as the user zooms out.

How to get value for selected place in particular area when draw polyline or polygon through Javascript ArcGIS Api from TileLayer?

Actually I am using ArcGIS API for JavaScript 4.7 and i have a custom internal layer . I want to get name of place particular area when draw polyline the column name is (PLC_NAME) . How to achieve that ?
Suppose I draw a area through polyline. In this area there are places . Now I need to get name of these places .
you can find the using code in below i am using the TileLayer.
require([
"esri/views/MapView",
"esri/Map",
"esri/Basemap",
"esri/layers/TileLayer",
"esri/layers/MapImageLayer",
"esri/widgets/Sketch/SketchViewModel",
"esri/geometry/geometryEngine",
"esri/widgets/CoordinateConversion",
"esri/geometry/support/webMercatorUtils",
"esri/Graphic",
"esri/layers/GraphicsLayer",
"esri/config",
"esri/core/urlUtils",
"esri/widgets/Search",
"esri/tasks/Locator",
"esri/layers/FeatureLayer",
"esri/widgets/Expand",
"dojo/domReady!"
], function (
MapView, Map, Basemap, TileLayer, MapImageLayer,
SketchViewModel,
geometryEngine,
CoordinateConversion,
webMercatorUtils,
Graphic, GraphicsLayer, esriConfig, urlUtils,Search,Locator,FeatureLayer,Expand
) {
esriConfig.request.proxyUrl = "xxxxxxxxxxxxxxx";
urlUtils.addProxyRule({
urlPrefix: "xxxxxxxxxxxxxxxxxxx",
proxyUrl: "xxxxxxxxxxxxxxxxxx"
});
var tempGraphicsLayer = new GraphicsLayer();
var saveGraphicsLayer = new GraphicsLayer();
var updateGraphic;
let highlight = null;
'xxxxxxxxxxxxxxxxxxxxxxxxx';
var myMap;
var layer = new TileLayer({
url: mapUrl
});
var towerLayer = new MapImageLayer({
url: 'xxxxxxxxxxxxxxxxxxxxxxx'
});
myMap = new Map({
layers: [layer, tempGraphicsLayer, saveGraphicsLayer]
});
myMap.add(towerLayer);
view = new MapView({
center: [-55.1683665, 39.951817],
container: "viewDiv",
map: myMap,
zoom: 14
});
var ccWidget = new CoordinateConversion({
view: view
});
// Adds the search widget below other elements in
// the top left corner of the view
view.ui.add(searchWidget, {
position: "top-right",
index: 1
});
view.ui.add(ccWidget, "bottom-left");
view.ui.add("topbar", "top-right");
var pointSymbol = { // symbol used for points
type: "simple-marker", // autocasts as new SimpleMarkerSymbol()
style: "square",
color: "#8A2BE2",
size: "16px",
outline: { // autocasts as new SimpleLineSymbol()
color: [255, 255, 255],
width: 3 // points
}
}
var polylineSymbol = { // symbol used for polylines
type: "simple-line", // autocasts as new SimpleLineSymbol()
color: "#8A2BE2",
width: "4",
style: "dash"
}
var polygonSymbol = { // symbol used for polygons
type: "simple-fill", // autocasts as new SimpleFillSymbol()
color: "rgba(138,43,226, 0.8)",
style: "solid",
outline: {
color: "white",
width: 1
}
}
var polygonBoundrySymbol = { // symbol used for polygons
type: "simple-line", // autocasts as new SimpleFillSymbol()
color: "red"
}
// ################## U R HERE ################## ################## U R HERE ##################
################## U R HERE ##################
let drawBoundry = function(){
//let boundryJson = '&G_GEO_LIMITS.';
let boundryJson = $v('P0_USER_LIMITS');
if(boundryJson){
// let boundry = Graphic.fromJSON(JSON.parse('&G_GEO_LIMITS.'));
let boundry = Graphic.fromJSON(JSON.parse(boundryJson));
boundry.symbol = polygonBoundrySymbol;
tempGraphicsLayer.add(boundry);
return boundry;
}
}
/*
let boundry = drawBoundry();
*/
view.when(function () {
$('.esri-view-root').on('click', '.esri-print__export-button', function(e){
//console.log('event bubbling', e);
//console.log('event bubbling this', this);
e.preventDefault();
saveExportedImg();
});
// create a new sketch view model
var sketchViewModel = new SketchViewModel({
view: view,
layer: tempGraphicsLayer,
pointSymbol: pointSymbol,
polylineSymbol: polylineSymbol,
polygonSymbol: polygonSymbol
});
//setUpClickHandler();
// ************************************************************
// Get the completed graphic from the event and add it to view.
// This event fires when user presses
// * "C" key to finish sketching point, polygon or polyline.
// * Double-clicks to finish sketching polyline or polygon.
// * Clicks to finish sketching a point geometry.
// ***********************************************************
sketchViewModel.on("draw-complete", addGraphic);
sketchViewModel.on("update-complete", addGraphic);
sketchViewModel.on("update-cancel", addGraphic);
sketchViewModel.on("vertex-add", addGraphic);
function addGraphic(evt) {
// console.log ('graphic.geometry',evt.geometry)
//let currentGraphic = popActiveGraphic(tempGraphicsLayer);
let currentGraphic = saveGraphicsLayer.graphics.items.pop();
var geometry = evt.geometry;
var vertices = evt.vertices;
var symbol;
var attr = {
Name: "Selected Area",
X: $v('P24_X'),
Y: $v('P24_Y')
};
// Choose a valid symbol based on return geometry
switch (geometry.type) {
case "point":
symbol = pointSymbol;
break;
case "polyline":
symbol = polylineSymbol;
break;
default:
symbol = polygonSymbol;
break;
}
// Create a new graphic; add it to the GraphicsLayer
// console.log("b4 graphic");
geometry = webMercatorUtils.webMercatorToGeographic(geometry)
/*if(boundry){
var contains = geometryEngine.contains(boundry.geometry, geometry);
var within = geometryEngine.within(geometry, boundry.geometry);
} else {*/
var within = true;
//}
if(within){
let graphic = new Graphic({
geometry: geometry,
symbol: symbol,
//attributes: attr,
popupTemplate: {
title: "{Name}",
content: [{
type: "fields",
fieldInfos: [{
fieldName: "X"
}, {
fieldName: "Y"
}]
}]
}
});
tempGraphicsLayer.add(graphic);
if(currentGraphic){
//currentGraphic.geometry.rings.push(geometry.rings[0]);
geometry.rings.forEach( ring => currentGraphic.geometry.addRing(ring));
//currentGraphic.geometry.addRing(geometry.rings);
//console.log('current active', geometry);
// console.log('current graphic', currentGraphic.geometry);
graphic = currentGraphic;
}
var saveObj = graphic.toJSON();
// console.log('saveObj', saveObj);
$x('P24_JSON').value = JSON.stringify(saveObj);
} else {
apex.message.alert('&G_MAP_BOUNDRY_MSG.');
}
updateGraphic = null;
}
function addMultiGraph(evt1) {
//let currentGraphic = popActiveGraphic(tempGraphicsLayer);
let currentGraphic = saveGraphicsLayer.graphics.items.pop();
var geometry = evt1.geometry;
var vertices = evt1.vertices;
var symbol;
// Choose a valid symbol based on return geometry
switch (geometry.type) {
case "point":
symbol = pointSymbol;
break;
case "polyline":
symbol = polylineSymbol;
break;
default:
symbol = polygonSymbol;
break;
}
//console.log("ring",geometry.rings )
let graphic = new Graphic({
geometry: geometry,
symbol: symbol,
//attributes: attr,
popupTemplate: {
title: "{Name}",
content: [{
type: "fields",
fieldInfos: [{
fieldName: "X"
}, {
fieldName: "Y"
}]
}]
}
});
tempGraphicsLayer.add(graphic);
if(currentGraphic){
geometry.rings.forEach( ring => currentGraphic.geometry.addRing(ring));
}
var saveObj1 = graphic.toJSON();
//console.log('saveObj', graphic);
$x('P24_JSON').value = JSON.stringify(saveObj1);
updateGraphic = null;
}
window.loadGraphic = function(polygon){
if(polygon===undefined || polygon === ''){
console.error('no polygon');
} else {
var graphic = Graphic.fromJSON(JSON.parse(polygon));
if (graphic.geometry){
addMultiGraph(graphic);
//*********************************************************************
view.center.longitude = graphic.geometry.centroid.longitude;
view.center.latitude = graphic.geometry.centroid.latitude;
view.center = [graphic.geometry.centroid.longitude,
graphic.geometry.centroid.latitude];
view.zoom = 12;
}
}
}
// *************************************
// activate the sketch to create a point
// *************************************
var drawPointButton = document.getElementById("pointButton");
drawPointButton.onclick = function () {
// set the sketch to create a point geometry
sketchViewModel.create("point");
setActiveButton(this);
};
// ****************************************
// activate the sketch to create a polyline
// ****************************************
var drawLineButton = document.getElementById("polylineButton");
drawLineButton.onclick = function () {
// set the sketch to create a polyline geometry
sketchViewModel.create("polyline");
setActiveButton(this);
};
var drawPolygonButton = document.getElementById("polygonButton");
drawPolygonButton.onclick = function () {
// set the sketch to create a polygon geometry
sketchViewModel.create("polygon");
setActiveButton(this);
};
// ***************************************
// activate the sketch to create a rectangle
// ***************************************
var drawRectangleButton = document.getElementById(
"rectangleButton");
drawRectangleButton.onclick = function () {
// set the sketch to create a polygon geometry
sketchViewModel.create("rectangle");
setActiveButton(this);
};
document.getElementById("resetBtn").onclick = function () {
sketchViewModel.reset();
tempGraphicsLayer.removeAll();
saveGraphicsLayer.removeAll();
setActiveButton();
drawBoundry();
};
function setActiveButton(selectedButton) {
// focus the view to activate keyboard shortcuts for sketching
view.focus();
var elements = document.getElementsByClassName("active");
for (var i = 0; i < elements.length; i++) {
elements[i].classList.remove("active");
}
if (selectedButton) {
selectedButton.classList.add("active");
}
}
// ************************************************************************************
// set up logic to handle geometry update and reflect the update on "tempGraphicsLayer"
// ************************************************************************************
function setUpClickHandler() {
view.on("click", function (evt) {
view.hitTest(evt).then(function (response) {
var results = response.results;
// Found a valid graphic
if (results.length && results[results.length - 1]
.graphic) {
// Check if we're already editing a graphic
if (!updateGraphic) {
// Save a reference to the graphic we intend to update
updateGraphic = results[results.length - 1].graphic;
// Remove the graphic from the GraphicsLayer
// Sketch will handle displaying the graphic while being updated
tempGraphicsLayer.remove(updateGraphic);
sketchViewModel.update(updateGraphic.geometry);
}
}
});
});
}
function errorCallback(error) {
console.log('error:', error);
}
// ************************************************************************************
// returns graphic object if drawn on the map to contcat new graphics to it
// ************************************************************************************
function popActiveGraphic(graphicsLayer){
let length = graphicsLayer.graphics.length;
let count = 0;
if($v('P0_USER_LIMITS').length > 0){
count++;
}
if(length > count){ //active drawing detected
let result = graphicsLayer.graphics.items[length-1];
graphicsLayer.remove(result);
return result;
}
}
});
});
OK, you can resolve the queries on the client or on the server. Depends on your task what options you can pick on.
If you are going to use a spatial query, like the one you mention, and you will apply it on a FeatureLayer, you could solve it on the client. This is a good solution because you already have the features, you are seeing them. Here you have a question whis this situation, how-to-get-get-name-of-hospital-or-street-in-particular-area-when-draw-polyline.
Now, If you need to query something that might not be in your extent (you don't have the features) or you are not using a FeatureLayer, you probably will need to command the server to do this. But don't worry the library has several tools to work with, like QueryTask.
Here you have the same example of the answer link before but using QueryTask.
<html>
<head>
<meta charset='utf-8'>
<meta name='viewport' content='initial-scale=1, maximum-scale=1, user-scalable=no'>
<title>Select Feature With Polygon</title>
<style>
html,
body {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
#viewDiv {
padding: 0;
margin: 0;
height: 400px;
width: 100%;
}
#namesDiv {
margin: 10px;
height: 200px;
width: 100%;
font-style: italic;
font-weight: bold;
font-family: Arial, Helvetica, sans-serif;
font-size: 16px;
color: green;
overflow: auto;
}
</style>
<link rel='stylesheet' href='https://js.arcgis.com/4.15/esri/css/main.css'>
<script src='https://js.arcgis.com/4.15/'></script>
<script>
require([
'esri/Map',
'esri/views/MapView',
'esri/layers/MapImageLayer',
'esri/layers/GraphicsLayer',
'esri/widgets/Sketch/SketchViewModel',
'esri/Graphic',
'esri/widgets/Expand',
'esri/tasks/QueryTask',
'esri/tasks/support/Query'
], function (
Map,
MapView,
MapImageLayer,
GraphicsLayer,
SketchViewModel,
Graphic,
Expand,
QueryTask,
Query
) {
let highlight = null;
const states = new MapImageLayer({
url: 'https://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer'
});
const queryTask = new QueryTask({
url: 'https://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer/2'
});
const polygonGraphicsLayer = new GraphicsLayer();
const selected = new GraphicsLayer();
const map = new Map({
basemap: 'streets',
layers: [states, polygonGraphicsLayer, selected]
});
const view = new MapView({
container: 'viewDiv',
map: map,
center: [-75.1683665, 39.951817],
zoom: 8
});
const sketchViewModel = new SketchViewModel({
view: view,
layer: polygonGraphicsLayer,
pointSymbol: {
type: 'simple-marker',
color: [255, 255, 255, 0],
size: '1px',
outline: {
color: 'gray',
width: 0
}
}
});
sketchViewModel.on('create', function (event) {
if (event.state === 'complete') {
polygonGraphicsLayer.remove(event.graphic);
selectFeatures(event.graphic.geometry);
}
});
const namesDiv = document.getElementById('namesDiv');
view.ui.add('select-by-polygon', 'top-left');
const selectButton = document.getElementById('select-by-polygon');
selectButton.addEventListener('click', function () {
clearUpSelection();
sketchViewModel.create('polygon');
});
function selectFeatures(geometry) {
selected.removeAll();
const query = new Query();
query.returnGeometry = true;
query.outFields = ['*'];
query.geometry = geometry;
queryTask
.execute(query)
.then(function (results) {
const graphics = results.features.map(r => {
r.symbol = {
type: 'simple-fill',
fill: 'none',
outline: {
color: 'cyan',
width: 2
}
};
return r;
});
selected.addMany(graphics);
namesDiv.innerHTML = graphics.map(g => g.attributes.NAME).join(',');
})
.catch(errorCallback);
}
function clearUpSelection() {
selected.removeAll();
namesDiv.innerHTML = null;
}
function errorCallback(error) {
console.log('error:', error);
}
});
</script>
</head>
<body>
<div id='viewDiv'>
<div
id="select-by-polygon"
class="esri-widget esri-widget--button esri-widget esri-interactive"
title="Select counties by polygon"
>
<span class="esri-icon-checkbox-unchecked"></span>
</div>
</div>
<div id="namesDiv"></div>
</body>
</html>
To close I leave you this link to the documentation that explains very well all the possibilities, pros and cons.

Print value of an array using three.js TextGeomtery

How can I print the values of an array using three.js textGeometry. Trying the following code but no output.
`for(let i=0;i<=4;i++)
{
let arr = [1,2,3,4,5,6,7,8];
let char = arr[i];
let loader = new THREE.FontLoader();
let font = loader.parse(fontJSON);
let geometry = new THREE.TextBufferGeometry(char ,{font : font , size : 1 , height : 0.1 });
let material = new THREE.MeshBasicMaterial({ color : 0xffffff });
let text = new THREE.Mesh(geometry , material);
text.position.set(i,0,0);
scene.add(text);
}`
You have to make sure to provide a string to TextBufferGeometry, no number. You can easily ensure this by calling toString() on your char variable. I've refactored your code a bit to show you a complete example.
let camera, scene, renderer;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.01, 10);
camera.position.z = 8;
scene = new THREE.Scene();
const material = new THREE.MeshBasicMaterial({
color: 0xffffff
});
const arr = [1, 2, 3, 4, 5, 6, 7, 8];
const loader = new THREE.FontLoader();
loader.load('https://threejs.org/examples/fonts/helvetiker_regular.typeface.json', (font) => {
for (let i = 0; i <= 4; i++) {
const char = arr[i];
const geometry = new THREE.TextBufferGeometry(char.toString(), {
font: font,
size: 1,
height: 0.1
});
const text = new THREE.Mesh(geometry, material);
text.position.set(i, 0, 0);
scene.add(text);
}
});
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
body {
margin: 0;
}
canvas {
display: block;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.117.1/build/three.js"></script>

Keep objects looking at camera

guys I know this question has been asked several times, several different ways, but I just can get it to work. Basically I have 2d clouds, but I want the camera to rotate around an object floating above the clouds. The problem is, when im not looking a the face of the clouds u can tell that they are 2d. Soooo i want the the clouds to "look" at the camera where ever it is. I believe my problem stems from how the cloud geometry is called on to the planes, but here take a look. I put the a lookAt function with in my animate function. I hope you can point me in the right direction at least.
Three.js rev. 70...
container.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.set(0, 0, 100);
scene.add(camera);
controls = new THREE.OrbitControls( camera );
controls.target.copy( new THREE.Vector3( 0, 0,475) );
controls.minDistance = 50;
controls.maxDistance = 200;
controls.autoRotate = true;
controls.autoRotateSpeed = .2; // 30 seconds per round when fps is 60
controls.minPolarAngle = Math.PI/4; // radians
controls.maxPolarAngle = Math.PI/2; // radians
controls.enableDamping = true;
controls.dampingFactor = 0.25;
clock = new THREE.Clock();
cloudGeometry = new THREE.Geometry();
var texture = THREE.ImageUtils.loadTexture('img/cloud10.png', null, animate);
texture.magFilter = THREE.LinearMipMapLinearFilter;
texture.minFilter = THREE.LinearMipMapLinearFilter;
var fog = new THREE.Fog(0x4584b4, -100, 3000);
cloudMaterial = new THREE.ShaderMaterial({
uniforms: {
"map": {
type: "t",
value: texture
},
"fogColor": {
type: "c",
value: fog.color
},
"fogNear": {
type: "f",
value: fog.near
},
"fogFar": {
type: "f",
value: fog.far
},
},
vertexShader: document.getElementById('vs').textContent,
fragmentShader: document.getElementById('fs').textContent,
depthWrite: false,
depthTest: false,
transparent: true
});
var plane = new THREE.Mesh(new THREE.PlaneGeometry(64, 64));
for (var i = 0; i < 8000; i++) {
plane.position.x = Math.random() * 1000 - 500;
plane.position.y = -Math.random() * Math.random() * 200 - 15;
plane.position.z = i;
plane.rotation.z = Math.random() * Math.PI;
plane.scale.x = plane.scale.y = Math.random() * Math.random() * 1.5 + 0.5;
plane.updateMatrix();
cloudGeometry.merge(plane.geometry, plane.matrix);
}
cloud = new THREE.Mesh(cloudGeometry, cloudMaterial);
scene.add(cloud);
cloud = new THREE.Mesh(cloudGeometry, cloudMaterial);
cloud.position.z = -8000;
scene.add(cloud);
var radius = 100;
var xSegments = 50;
var ySegments = 50;
var geo = new THREE.SphereGeometry(radius, xSegments, ySegments);
var mat = new THREE.ShaderMaterial({
uniforms: {
lightPosition: {
type: 'v3',
value: light.position
},
textureMap: {
type: 't',
value: THREE.ImageUtils.loadTexture("img/maps/moon.jpg")
},
normalMap: {
type: 't',
value: THREE.ImageUtils.loadTexture("img/maps/normal.jpg")
},
uvScale: {
type: 'v2',
value: new THREE.Vector2(1.0, 1.0)
}
},
vertexShader: document.getElementById('vertexShader').textContent,
fragmentShader: document.getElementById('fragmentShader').textContent
});
mesh = new THREE.Mesh(geo, mat);
mesh.geometry.computeTangents();
mesh.position.set(0, 50, 0);
mesh.rotation.set(0, 180, 0);
scene.add(mesh);
}
function onWindowResize() {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
}
function animate() {
requestAnimationFrame(animate);
light.orbit(mesh.position, clock.getElapsedTime());
cloud.lookAt( camera );
controls.update(camera);
renderer.render(scene, camera);
}
animate();
window.addEventListener('resize', onWindowResize, false);
just a first guess:
the lookAt function needs Vector3 as parameter. try to use camera.position in the animate function.
cloud.lookAt( camera.position );
first of all, to build 2D objects in a scene that always faces towards the camera, you should use Sprite object, so you don't have to do anything to get this effect. (and have better performance :))
Definition from THREE.org: Sprite - a sprite is a plane in an 3d scene which faces always towards the camera.
var map = THREE.ImageUtils.loadTexture( "sprite.png" );
var material = new THREE.SpriteMaterial( { map: map, color: 0xffffff, fog: true } );
var sprite = new THREE.Sprite( material );
scene.add( sprite );
Please check this example: http://threejs.org/examples/#webgl_points_sprites
I would absolutely agree, I would use Sprite, or even Points, but then, if assign a texture to it, it will render it square-sized. My sprites are animated, and frames cannot be packed in square tiles, cause it would take a lot of space. I might make a mesh and use this lookAt function.

Draw line between two points using OpenLayers

I have two points having lolLat as 0,10 and 30,0
Now to draw a marker at this point i use this transform while generating marker for it
lonLat.transform(
new OpenLayers.Projection("EPSG:4326"), // transform from WGS 1984
map.getProjectionObject() // to Spherical Mercator Projection
)
How can i draw line between them is there any way to do that in openlayers,i have tried doing it with linestring in vector layer but it doesn't seems to be working for me.
In OpenLayers version 3.3, you can do this as
var points = [ [-89.8802, 32.5804], [-95.04286, 46.9235] ];
for (var i = 0; i < points.length; i++) {
points[i] = ol.proj.transform(points[i], 'EPSG:4326', 'EPSG:3857');
}
var featureLine = new ol.Feature({
geometry: new ol.geom.LineString(points)
});
var vectorLine = new ol.source.Vector({});
vectorLine.addFeature(featureLine);
var vectorLineLayer = new ol.layer.Vector({
source: vectorLine,
style: new ol.style.Style({
fill: new ol.style.Fill({ color: '#00FF00', weight: 4 }),
stroke: new ol.style.Stroke({ color: '#00FF00', width: 2 })
})
});
Then add layer to map
map.addLayer(vectorLineLayer);
For example:
map = new OpenLayers.Map();
var start_point = new OpenLayers.Geometry.Point(0,10);
var end_point = new OpenLayers.Geometry.Point(30,0);
var vector = new OpenLayers.Layer.Vector();
vector.addFeatures([new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString([start_point, end_point]))]);
map.addLayers([vector]);
Live demo
I am aware that this is an old question, but no up-to-date answer exists.
Here is a runnable code as an answer, using current version of Openlayers (August 2022).
const Feature = ol.Feature;
const VectorSource = ol.source.Vector;
const VectorLayer = ol.layer.Vector;
const LineString = ol.geom.LineString;
//const Point = ol.geom.Point;
const Style = ol.style.Style;
const Stroke = ol.style.Stroke;
const fromLonLat = ol.proj.fromLonLat;
const Overlay = ol.Overlay;
// Two locations with long/lat values in degrees
const lonlat0 = [100.538142, 13.765230];
const lonlat1 = [100.529321, 13.793656];
/* BEGIN: Code for the line joining the 2 points */
var points = [fromLonLat(lonlat0), fromLonLat(lonlat1)];
var line_feat1 = new Feature({
geometry: new LineString(points),
name: "My_Simple_LineString"
});
var line_vsrc = new VectorSource({
features: [line_feat1],
wrapX: false
});
var lineStyle = new Style({
stroke: new Stroke({
color: "red",
width: 5,
//lineDash: [4, 4, 4],
lineCap: "butt"
/* https://openlayers.org/en/latest/apidoc/module-ol_style_Stroke.html */
})
});
var veclay_line = new VectorLayer({
source: line_vsrc,
style: lineStyle
});
// `veclay_line` is the outcome of this complicate code
/* END: Code for the line joining the 2 points */
// Create map
// Note: `veclay_line`, containing the LineString is used within `layers`
var map = new ol.Map({
target: "map",
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
veclay_line
],
view: new ol.View({
center: ol.proj.fromLonLat(lonlat0),
zoom: 13
})
});
.map {
height: 400px;
width: 100%;
}
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io#master/en/v6.15.1/css/ol.css" type="text/css">
<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io#master/en/v6.15.1/build/ol.js"></script>
<title>OpenLayers 6</title>
</head>
<body>
<div id="map" class="map"></div>
</body>
As this question comes up on top in search results, I figured giving the current v6 answer would be beneficial.
It's a bit more complicated now, need to create a bunch of intermediary objects (at least as far as I understood):
const raster = new ol.layer.Tile({
source: new ol.source.OSM(),
});
const source = new ol.source.Vector();
const p1 = [-12500000, 6500000];
const p2 = [-10000000, 4000000];
const line = new ol.geom.LineString([p1, p2]);
const feature = new ol.Feature({
geometry: line,
name: "Line"
});
source.addFeature(feature);
const vector = new ol.layer.Vector({
source: source,
});
const map = new ol.Map({
layers: [raster, vector],
target: 'mapdiv',
view: new ol.View({
center: [-11000000, 4600000],
zoom: 4,
}),
});
You can then also modify the geometry on the fly with e.g.
line.appendCoodrinate([long,lat]);
and the map will be updated extending the line.
Here's a working demo for v6: Live demo
I don't get why the coord format is this way (10000ths of a degree), the docs on Coordinates, for example, show "normal" values, but code examples use that.