I realize this probably isn’t a ThreeJS problem, the only reason I want this to work in IE 11 is because that is what everyone in our work environment uses(sadly)… but is there anyone out there that maybe has run into the same issue? Anyone that has been using Three JS within an ASP.Net application? When I check console, I see warnings… but i don’t know why that would have anything to do with my texture not rendering. You can see that the scene renders fine, but you can’t see the earth texture image. The warnings I see in console:
Here is what it looks like at runtime: (You can see the labels that I have added on top of the sphere/earth, just not the earth itself)
Anyone know anything that I can check? Here is the main JS code:
//Define namespace
var EarthView3D = EarthView3D || {};
//THREE JS setup variables
var camera, scene, renderer, labelRenderer, earth;
$(document).ready(function () {
EarthView3D.GetSites(); // This must run before initializing EarthView, Init() is called in success property of ajax call.
}); /* END DOCUMENT READY */
EarthView3D.GetSites = function () {
$.ajax({
url: basePath + 'EarthView3D/GetSites',
type: 'GET',
dataType: 'html',
cache: false,
success: function (data) {
// Set the siteObjects, defined at the top of this file.
var siteObjects = JSON.parse(data);
EarthView3D.Init(siteObjects, EarthView3D.Animate);
},
error: function (jqXHR, textStatus, errorThrown) {
alert('Error retrieving site coordinates for earth view.');
},
complete: function (jqXHR, textStatus) {
}
});
};
EarthView3D.ViewSite = function (_siteID) {
$('#loading').show();
$.ajax({
url: basePath + 'EarthView3D/ViewSite',
type: 'GET',
dataType: 'html',
data: { siteID: _siteID },
cache: false,
success: function (data) {
$('#earth_view_site_modal').html(data).modal('show');
},
error: function (jqXHR, textStatus, errorThrown) {
alert('Error retrieving site info');
},
complete: function (jqXHR, textStatus) {
$('#loading').hide();
}
});
};
EarthView3D.Init = function (siteObjects, animateCallback) {
const EARTH_RADIUS = 225;
const EARTH_SEGMENTS = 75;
const EARTH_RINGS = 75;
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 2000); //-87 pixels for header and dev environment bar.
camera.position.set(-70, 375, 500);
scene = new THREE.Scene();
var light = new THREE.PointLight(0xffffff, 1, Infinity);
camera.add(light);
scene.add(camera);
// Starfield
var starGeometry = new THREE.SphereGeometry(1000, 50, 50); //basically creates another sphere around the earth's sphere, and covers it in starfield image.
var starMaterial = new THREE.MeshPhongMaterial({
map: new THREE.ImageUtils.loadTexture(basePath + 'Content/images/galaxy_starfield.png'),
side: THREE.DoubleSide,
shininess: 0
});
var starField = new THREE.Mesh(starGeometry, starMaterial);
scene.add(starField);
// Create group to hold sphere and texture, makes up the earth.
earth = new THREE.Group();
scene.add(earth);
//paths to each of the texture images.
var earthNoCloudsTex = basePath + 'Content/images/earth_no_clouds_12k.jpg';
var earthDarkTex = basePath + 'Content/images/earth_dark_12k.jpg';
var earthDarkInvertTex = basePath + 'Content/images/earth_dark_invert_12k.jpg';
var earthRedTex = basePath + 'Content/images/earth_dark_red_12k.jpg';
// Flag for current texture that is displaying
var currentTexture = earthNoCloudsTex;
//for loading earth texture images.
var loader = new THREE.TextureLoader();
// Instantiate material to later be wrapped around the sphere.
var material = new THREE.MeshBasicMaterial();
// Create the sphere
var sphere = new THREE.SphereGeometry(EARTH_RADIUS, EARTH_SEGMENTS, EARTH_RINGS);
// Instantiate mesh to later combine sphere with material
var mesh;
loader.load(currentTexture, function (texture) {
// Map the texture to the material.
material = new THREE.MeshBasicMaterial({
map: texture
});
// Create a new mesh with sphere geometry.
mesh = new THREE.Mesh(sphere, material);
// Add mesh to globe
earth.add(mesh);
});
scene.add(earth);
//Add toggle click event for changing earth background texture
$('.texture_change_button').on("click", function (e) {
//figure out which button was clicked
var buttonClicked = $(this).attr('id');
//disable all currently disabled buttons before disabling another
$(":disabled").attr('disabled', false);
//disable button clicked so that it can't be clicked twice.
$(this).attr('disabled', true);
//depending on the id of the buttonClicked, update the currentTexture
switch (buttonClicked) {
case 'earth_no_clouds_button':
currentTexture = earthNoCloudsTex;
break;
case 'earth_dark_button':
currentTexture = earthDarkTex;
break;
case 'earth_dark_invert_button':
currentTexture = earthDarkInvertTex;
break;
case 'earth_red_button':
currentTexture = earthRedTex;
}
//switch out the image with new currentTexture
loader.load(currentTexture, function (texture) {
//this actually updates the image
material.map = texture;
earth.add(mesh);
});
});
// Add siteObjects to Earth
for (var i = 0; i < siteObjects.length; i++) {
var siteID = siteObjects[i].SiteID;
var name = siteObjects[i].Name;
var desc = siteObjects[i].Description;
var lat = siteObjects[i].LAT;
var lon = siteObjects[i].LON;
var status = siteObjects[i].Status;
// Create dot for each site
var siteDiv = document.createElement('div');
siteDiv.setAttribute("id", name);
//set data attributes to later use when clicking dot.
siteDiv.setAttribute("data-siteid", siteID);
siteDiv.setAttribute("title", name);
siteDiv.classList = status.toLowerCase() == "fmc" ? "site_status fmc" :
status.toLowerCase() == "pmc" ? "site_status pmc" :
"site_status nmc";
//Create label to append to each site's dot
var siteDivLabel = document.createElement('label');
siteDivLabel.setAttribute("id", name + '_label');
siteDivLabel.setAttribute("title", name + ' label');
siteDivLabel.textContent = name;
//Setting the label's class (Some labels need to display on different sides of the dot so that all can be seen in initial view.)
if (siteID == 6 || siteID == 9) { // 6 is BUckley, 9 is COD
siteDivLabel.className = 'label_top_right earth_view_label';
} else if (siteID == 12 || siteID == 20 || siteID == 19) { // 12 is FGA, 20 is PAFB, 19 is MDIOC
siteDivLabel.className = 'label_bottom_right earth_view_label';
} else if (siteID == 8) { // 8 is CMD
siteDivLabel.className = 'label_bottom_left earth_view_label';
} else {
siteDivLabel.className = 'label_top_left earth_view_label';
}
siteDiv.appendChild(siteDivLabel);
var siteDot = new THREE.CSS2DObject(siteDiv);
siteDiv.parent = siteDot;
siteDot.element.style.cursor = "pointer";
// Add click event for each dot/label that takes them to the site section for the dashboard homepage.
siteDot.element.onclick = function () {
var siteSK = $(this).data('siteid');
EarthView3D.ViewSite(siteSK);
};
var sitePosition = EarthView3D.CalcPosFromLatLonRad(lat, lon, EARTH_RADIUS);
// Some code to slightly move certain site markers around from their original position so that they don't overlap each other too much.
if (siteID == 5) { // 5 is boulder
siteDot.position.set(sitePosition[0] - 1, sitePosition[1] + 1, Math.abs(sitePosition[2]));
} else if (siteID == 8) { // 8 is CMD
siteDot.position.set(sitePosition[0] - 1, sitePosition[1] - 1, Math.abs(sitePosition[2]));
} else if (siteID == 20) { // 20 is PAFB
siteDot.position.set(sitePosition[0] + 1, sitePosition[1] - 6, Math.abs(sitePosition[2]));
} else if (siteID == 19) { // 19 is MDIOC
siteDot.position.set(sitePosition[0] + 5, sitePosition[1] + 4, Math.abs(sitePosition[2]));
} else if (siteID == 6) { // 6 is Buckley
siteDot.position.set(sitePosition[0] + 2, sitePosition[1] + 3, Math.abs(sitePosition[2]));
} else {
siteDot.position.set(sitePosition[0], sitePosition[1], Math.abs(sitePosition[2]));
}
earth.add(siteDot);
}
renderer = new THREE.WebGLRenderer({ alpha: true });
renderer.setClearColor(0xffffff, 0);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
var earthContainer = document.getElementById('earth_container');
earthContainer.appendChild(renderer.domElement);
labelRenderer = new THREE.CSS2DRenderer();
labelRenderer.setSize(window.innerWidth, window.innerHeight);
labelRenderer.domElement.style.position = 'absolute';
labelRenderer.domElement.style.top = 0;
document.body.appendChild(labelRenderer.domElement);
// For rotation and mouse controls
var controls = new THREE.OrbitControls(camera, labelRenderer.domElement);
controls.minDistance = 400;
controls.maxDistance = 800;
animateCallback(siteObjects); //Running Animate right after Init.
};
/* Referenced from answer found here:
https://stackoverflow.com/questions/28365948/javascript-latitude-longitude-to-xyz-position-on-earth-threejs
*/
EarthView3D.CalcPosFromLatLonRad = function (lat, lon, radius) {
var phi = (90 - lat) * (Math.PI / 180)
var theta = (lon + 180) * (Math.PI / 180)
x = -((radius) * Math.sin(phi) * Math.cos(theta))
z = ((radius) * Math.sin(phi) * Math.sin(theta))
y = ((radius) * Math.cos(phi))
return [x, y, z];
};
EarthView3D.Animate = function () {
//earth.rotation.y -= .0004; - Rotation was causing shaking of markers/labels, so commented out.
requestAnimationFrame(EarthView3D.Animate);
renderer.render(scene, camera);
labelRenderer.render(scene, camera);
};
Also, if my starfield texture is rendering just fine in IE11… Why can my earth texture not render? They both create a sphere and then wrap the texture around sphere… The only difference is my starfield uses the deprecated THREE.ImageUtils.loadTexture() function, and earth uses TextureLoader(), and creates a group. Maybe the group is what messes it up? I am going to try and take the earth texture and sphere and all that out of the group, and do it just like the starfield. I will keep everyone updated.