I have loaded one model (obj file) in three js and applied custom checker texture image on all objects. Texture is applied on Model. But, issue is that - checker are not like uniformly - some checker are look small and some are look larger.
Here is link of screenshot.
Is there any way to fix it ? I mean - any calculation on geometry or any in-built properties of texture etc. in three js.
Here is link of model file Model.obj
loaded this model in three js and applied texture image.
// Below some code which I have tried.
function loadModel() {
object.traverse( function ( child ) {
if (child.type.toLowerCase() == "mesh" && child.material) {
if (child.material.length) {
for (var i=0; i < child.material.length; i++) {
child.material[i].map = texture;
child.material[i].needsUpdate = true;
}
}
else {
child.material.map = texture;
child.material.needsUpdate = true;
}
}
} );
scene.add( object );
}
manager = new THREE.LoadingManager( loadModel );
manager.onProgress = function ( item, loaded, total ) {
console.log( item, loaded, total );
};
textureLoader = new THREE.TextureLoader( manager );
texture = textureLoader.load(currentTextureUrl); // texture checker image
texture.onUpdate = true;
function onProgress( xhr ) {
if ( xhr.lengthComputable ) {
var percentComplete = xhr.loaded / xhr.total * 100;
console.log( 'model ' + Math.round( percentComplete, 2 ) + '% downloaded' );
}
}
function onError() {}
var loader = new THREE.OBJLoader( manager );
loader.load(modals.currentModal.objectFile, function ( obj ) {
object = obj;
}, onProgress, onError );
Kendo pie chart explode function not working:
$( e.sender.dataSource.options.data ) //this line become null..
following are javascript:
seriesClick: function(e){
$( e.sender.dataSource.options.data ).each( function ( i, item ) {
if ( item.Description != e.category )
{
item.Exploded= false;
}
else
{
item.Exploded= true;
}
} );
createChart();
}
The Explode clicked pie chart segment demo shows how to do this. Here is the relevant code:
seriesClick: function(e){
$.each(e.sender.dataSource.view(), function() {
// Clean up exploded state
this.explode = false;
});
// Disable animations
e.sender.options.transitions = false;
// Explode the current slice
e.dataItem.explode = true;
e.sender.refresh();
}
Using Three.js r68+ I have been needing to very slightly modify the source to get my animations working correctly. Unmodified only one of each type of model are animated (there are multiple spawns of each type of model).
This is the modified source at line 29407 (posted code beginning at 29389):
THREE.AnimationHandler = {
LINEAR: 0,
CATMULLROM: 1,
CATMULLROM_FORWARD: 2,
//
add: function () { console.warn( 'THREE.AnimationHandler.add() has been deprecated.' ); },
get: function () { console.warn( 'THREE.AnimationHandler.get() has been deprecated.' ); },
remove: function () { console.warn( 'THREE.AnimationHandler.remove() has been deprecated.' ); },
//
animations: [],
init: function ( data ) {
// original -> if ( data.initialized === true ) return;
if ( data.initialized === true ) return data; //<-- modified
The function now returns the animation data if initialized. I'm assuming it doesn't do so because of caching. My question is what is the best practice for animating multiple models that have the same animation names? I tried naming them uniquely per model name ie: "Death_MaleWarrior" but this had no effect.
Currently my models and animations are handled like so:
var modelArray = [];
var geoCache = [];
var loader = new THREE.JSONLoader(true);
var _MODEL = function(data){
this.data = data;
this.mesh = null;
this.animations = {};
this.canAnimate = false;
this.parseAnimations = function () {
var len,i,anim;
if (this.mesh) {
if( this.mesh.geometry.animations ){
this.canAnimate = true;
len = this.mesh.geometry.animations.length;
if( len ){
for(i=0;i<len;i++){
anim = this.mesh.geometry.animations[i];
if( anim ){
this.animations[anim.name] = new THREE.Animation( this.mesh, anim );
}
}
}
}
}
};
this.playAnimation = function(label){
if (this.canAnimate) {
if( this.animations[label] ){
//if( this.animations[label].data ){
this.animations[label].play(0,1);
//}
}
}
return false;
};
this.load = function(geo){
var mat;
mat = new THREE.MeshPhongMaterial({color:somecolor, skinning:true})
this.mesh = new THREE.SkinnedMesh(geo,mat);
this.mesh.position.x = this.data.position[0];
this.mesh.position.y = this.data.position[1];
this.mesh.position.z = this.data.position[2];
this.parseAnimations();
scene.add(this.mesh);
this.playAnimation('Idle');
};
this.init = function(){
var geo;
if( geoCache[this.data.name] ){
geo = geoCache[this.data.name];
this.load(geo);
}else{
geo = loader.parse(JSON.parse(this.data.json)).geometry;
geoCache[this.data.name] = geo;
this.load(geo);
}
};
this.init();
};
var dataArray = [{name:'MaleWarrior',json:'json_data',position:[x,y,z]},{name:'FemaleWarrior',json:'json_data',position:[x,y,z]},{name:'MaleWarrior',json:'json_data',position:[x,y,z]}];
for(var i=0, len=objectArray.length; i<len; i++){
modelArray.push(new _MODEL(dataArray[i]) );
}
In this example the first MaleWarrior will animate but the second will not. If there was a second female she would not be animated either as the animation (even though it is a new THREE.Animation() ) will be considered initialized and will not return any data. If I do not check for the existence of animations.data in playAnimation I get the error ""Uncaught TypeError: Cannot read property 'name' of undefined " on line 29665".
Is what I'm doing bypassing animation caching and hurting performance? I feel like I'm missing something. How will an animation play without data?
All animation names are the same for every model "Idle", "Run", "Attack" etc.
Any help would be appreciated. If I'm not being clear enough please let me know. I have added additional detail.
This turned out to be an official three.js bug.
https://github.com/mrdoob/three.js/issues/5516
I am developing an app for iOS using Phonegap bundled with jQuery Mobile 1.1.1. I have a div on my page that is listening for both tap and taphold events.
The problem I am facing is that the tap event is fired after the taphold event once I lift my finger. How do I prevent this?
A solution is provided here but is this the only way to do this? Kinda nullifies the whole point of having two different events for tap & taphold if you need to use a boolean flag to differentiate the two.
Following is my code:
$('#pageOne').live('pageshow', function(event) {
$('#divOne').bind('taphold', function (event) {
console.log("TAP HOLD!!");
});
$('#divOne').bind('tap', function () {
console.log("TAPPED!!");
});
});
Would greatly appreciate the help. Thanks!
Simply set this at the top of your document or anywhere before you define your even:
$.event.special.tap.emitTapOnTaphold = false;
Then you can use it like this:
$('#button').on('tap',function(){
console.log('tap!');
}).on('taphold',function(){
console.log('taphold!');
});
[Tried and Tested]
I checked jQuery Mobile's implementation. They are firing the 'tap' event after 'taphold' every time on 'vmouseup'.
Workaround would be not to fire the 'tap' event if the 'taphold' has been fired. Create a custom event or modify the source as per you need as follows:
$.event.special.tap = {
tapholdThreshold: 750,
setup: function() {
var thisObject = this,
$this = $( thisObject );
$this.bind( "vmousedown", function( event ) {
if ( event.which && event.which !== 1 ) {
return false;
}
var origTarget = event.target,
origEvent = event.originalEvent,
/****************Modified Here**************************/
tapfired = false,
timer;
function clearTapTimer() {
clearTimeout( timer );
}
function clearTapHandlers() {
clearTapTimer();
$this.unbind( "vclick", clickHandler )
.unbind( "vmouseup", clearTapTimer );
$( document ).unbind( "vmousecancel", clearTapHandlers );
}
function clickHandler( event ) {
clearTapHandlers();
// ONLY trigger a 'tap' event if the start target is
// the same as the stop target.
/****************Modified Here**************************/
//if ( origTarget === event.target) {
if ( origTarget === event.target && !tapfired) {
triggerCustomEvent( thisObject, "tap", event );
}
}
$this.bind( "vmouseup", clearTapTimer )
.bind( "vclick", clickHandler );
$( document ).bind( "vmousecancel", clearTapHandlers );
timer = setTimeout( function() {
tapfired = true;/****************Modified Here**************************/
triggerCustomEvent( thisObject, "taphold", $.Event( "taphold", { target: origTarget } ) );
}, $.event.special.tap.tapholdThreshold );
});
}
};
You can use stopImmediatePropagation() method of jquery to solve this issue. According to the explanation in jquery api, stopImmediatePropagation() method
"Keeps the rest of the handlers from being executed and prevents the
event from bubbling up the DOM tree."
put this in your taphold event handler... this suggestion assumes o is a jQuery object that fired the taphold
jQuery(o).one('tap click', function(){ return false; });
the binding to the one method will fire the event only once. returning false will stop the execution of that event if it was an < a > tag.
Since swipe, triggers taphold then I was able to keep it simple with:
$(c).bind("taphold",function(e){
if(e.target.wait){
e.target.wait = false;
}else{
alert("fire the taphold");
}//eo if not waiting
});
$(c).bind("swipe",function(e){
e.target.wait = true;//taphold will come next if I don't wave it off
alert(e.target.text+"("+e.target.attributes.dataId.value+") got swiped");
return false;
});
To support tap too then I'd defer the wait clear until the tap event which will also always fire.
I still have problems, with jquery-mobile's taphold, I solved the problem of the click called after taphold, putting a timeout on the element.
JQM 1.4 with emitTapOnTaphold = false;
Example:
$(".element").on("taphold", function () {
// function her
setTimeout (function () {
$(this).blur();
400);
});
$.event.special.tap = {
tapholdThreshold: 750,
setup: function() {
var thisObject = this,
$this = $( thisObject );
$this.bind( "vmousedown", function( event ) {
if ( event.which && event.which !== 1 ) {
return false;
}
var origTarget = event.target,
origEvent = event.originalEvent,
/****************Modified Here**************************/
tapfired = false,
timer;
function clearTapTimer() {
clearTimeout( timer );
}
function clearTapHandlers() {
clearTapTimer();
$this.unbind( "vclick", clickHandler )
.unbind( "vmouseup", clearTapTimer );
$( document ).unbind( "vmousecancel", clearTapHandlers );
}
function clickHandler( event ) {
clearTapHandlers();
// ONLY trigger a 'tap' event if the start target is
// the same as the stop target.
/****************Modified Here**************************/
//if ( origTarget === event.target) {
if ( origTarget === event.target && !tapfired) {
triggerCustomEvent( thisObject, "tap", event );
}
}
$this.bind( "vmouseup", clearTapTimer )
.bind( "vclick", clickHandler );
$( document ).bind( "vmousecancel", clearTapHandlers );
timer = setTimeout( function() {
tapfired = true;/****************Modified Here**************************/
triggerCustomEvent( thisObject, "taphold", $.Event( "taphold", { target: origTarget } ) );
}, $.event.special.tap.tapholdThreshold );
});
}
};
#Akash Budhia: Thanks for your solutions.
It's great, sounds it work for me!
ok so im having a hard time hiding some layout sections (divs in my layout page and im using mvc3).
I have this js fragment which is basically the main logic:
$('.contentExpand').bind('click', function () {
$.cookie('right_container_visible', "false");
});
//Cookies Functions========================================================
//Cookie for showing the right container
if ($.cookie('right_container_visible') === 'false') {
if ($('#RightContainer:visible')) {
$('#RightContainer').hide();
}
$.cookie('right_container_visible', null);
} else {
if ($('#RightContainer:hidden')) {
$('#RightContainer').show();
}
}
as you can see, im hidding the container whenever i click into some links that have a specific css. This seems to work fine for simple tests. But when i start testing it like
.contentExpand click --> detail button click --> .contentExpand click --> [here unexpected issue: the line $.cookie('right_container_visible', null); is read but it doesnt set the vaule to null as if its ignoring it]
Im trying to understand whats the right logic to implement this. Anyone knows how i can solve this?
The simpliest solution is to create variable outside delegate of bind.
For example:
var rightContVisibility = $.cookie('right_container_visible');
$('.contentExpand').bind('click', function () {
$.cookie('right_container_visible', "false");
rightContVisibility = "false";
});
if (rightContVisibility === 'false') {
...
}
The best thing that worked for me was to create an event that can catch the resize of an element. I got this from another post but I dont remember which one. Anyway here is the code for the event:
//Event to catch rezising============================================================================
(function () {
var interval;
jQuery.event.special.contentchange = {
setup: function () {
var self = this,
$this = $(this),
$originalContent = $this.text();
interval = setInterval(function () {
if ($originalContent != $this.text()) {
$originalContent = $this.text();
jQuery.event.handle.call(self, { type: 'contentchange' });
}
}, 100);
},
teardown: function () {
clearInterval(interval);
}
};
})();
//=========================================================================================
//Function to resize the right container============================================================
(function ($) {
$.fn.fixRightContainer = function () {
this.each(function () {
var width = $(this).width();
var parentWidth = $(this).offsetParent().width();
var percent = Math.round(100 * width / parentWidth);
if (percent > 62) {
$('#RightContainer').remove();
}
});
};
})(jQuery);
//===================================================================================================