How to draw a 3D sphere? - html

I want to draw a 3D ball or sphere in HTML 5.0 canvas. I want to understand the Algorithm about how to draw a 3D sphere. Who can share this with me?

You will need to model a sphere, and have it be varying colors so that as it rotates you can see that it is not only a sphere, but being rendered.
Otherwise, a sphere in space, with not point of reference around it looks like a circle, if it is all one solid color.
To start with you will want to try drawing a circle with rectangles, as that is the main primitive you have.
Once you understand how to do that, or create a new primitive, such as a triangle, using the Path method, and create a circle, then you are ready to move it to 3D.
3D is just a trick, as you will take your model, probably generated by an equation, and then flatten it, as you determine which parts will be seen, and then display it.
But, you will want to change the color of the triangles based on how far they are from a source of light, as well as based on the angle of that part to the light source.
This is where you can start to do optimizations, as, if you do this pixel by pixel then you are raytracing. If you have larger blocks, and a point source of light, and the object is rotating but not moving around then you can recalculate how the color changes for each triangle, then it is just a matter of changing colors to simulate rotating.
The algorithm will depend on what simplifications you want to make, so as you gain experience come back and ask, showing what you have done so far.
Here is an example of doing it, and below I copied the 3D sphere part, but please look at the entire article.
function Sphere3D(radius) {
this.point = new Array();
this.color = "rgb(100,0,255)"
this.radius = (typeof(radius) == "undefined") ? 20.0 : radius;
this.radius = (typeof(radius) != "number") ? 20.0 : radius;
this.numberOfVertexes = 0;
// Loop from 0 to 360 degrees with a pitch of 10 degrees ...
for(alpha = 0; alpha <= 6.28; alpha += 0.17) {
p = this.point[this.numberOfVertexes] = new Point3D();
p.x = Math.cos(alpha) * this.radius;
p.y = 0;
p.z = Math.sin(alpha) * this.radius;
this.numberOfVertexes++;
}
// Loop from 0 to 90 degrees with a pitch of 10 degrees ...
// (direction = 1)
// Loop from 0 to 90 degrees with a pitch of 10 degrees ...
// (direction = -1)
for(var direction = 1; direction >= -1; direction -= 2) {
for(var beta = 0.17; beta < 1.445; beta += 0.17) {
var radius = Math.cos(beta) * this.radius;
var fixedY = Math.sin(beta) * this.radius * direction;
for(var alpha = 0; alpha < 6.28; alpha += 0.17) {
p = this.point[this.numberOfVertexes] = new Point3D();
p.x = Math.cos(alpha) * radius;
p.y = fixedY;
p.z = Math.sin(alpha) * radius;
this.numberOfVertexes++;
}
}
}
}

u can try with three.js library , which abstracts a lot of code from core webgl programming. Include three.js library in your html from three.js lib.
u can use canvas renderer for safari browser , webgl works for chrome
please find the JS FIDDLE FOR SPHERE
var camera, scene, material, mesh, geometry, renderer
function drawSphere() {
init();
animate();
}
function init() {
// camera
scene = new THREE.Scene()
camera = new THREE.PerspectiveCamera(50, window.innerWidth / innerHeight, 1, 1000);
camera.position.z = 300;
scene.add(camera);
// sphere object
var radius = 50,
segments = 10,
rings = 10;
geometry = new THREE.SphereGeometry(radius, segments, rings);
material = new THREE.MeshNormalMaterial({
color: 0x002288
});
mesh = new THREE.Mesh(geometry, material);
//scene
;
scene.add(mesh);
// renderer
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
mesh.rotation.x += .01;
mesh.rotation.y += .02;
renderer.render(scene, camera);
}
// fn callin
drawSphere();

Update: This code is quite old and limited. There are libraries for doing 3D spheres now: http://techslides.com/d3-globe-with-canvas-webgl-and-three-js/
Over ten years ago I wrote a Java applet to render a textured sphere by actually doing the math to work out where the surface of the sphere was in the scene (not using triangles).
I've rewritten it in JavaScript for canvas and I've got a demo rendering the earth as a sphere:
(source: haslers.info)
I get around 22 fps on my machine. Which is about as fast as the Java version it was based on renders at, if not a little faster!
Now it's a long time since I wrote the Java code - and it was quite obtuse - so I don't really remember exactly how it works, I've just ported it JavaScript. However this is from a slow version of the code and I'm not sure if the faster version was due to optimisations in the Java methods I used to manipulate pixels or from speedups in the math it does to work out which pixel to render from the texture. I was also corresponding at the time with someone who had a similar applet that was much faster than mine but again I don't know if any of the speed improvements they had would be possible in JavaScript as it may have relied on Java libraries. (I never saw their code so I don't know how they did it.)
So it may be possible to improve on the speed. But this works well as a proof of concept.
I'll have a go at converting my faster version some time to see if I can get any speed improvements into the JavaScript version.

Well, an image of a sphere will always have a circular shape on your screen, so the only thing that matters is the shading. This will be determined by where you place your light source.
As for algorithms, ray tracing is the simplest, but also the slowest by far — so you probably wouldn't want to use it to do anything very complicated in a <CANVAS> (especially given the lack of graphics acceleration available in that environment), but it might be fast enough if you just wanted to do a single sphere.

Related

Trying to generate sword swinging attack using Box2D in Citrus Engine

I've been banging my head up against a wall for the past couple of days trying to figure out how to properly extend CitrusEngine's Box2DPhysicsObjects to generate my custom objects. My goal is to generate this behavior:
example of desired behavior.
This is designed to simulate my hero dashing at a direction determined by using input while swinging his sword to attack. The sword "sleeps" until the attack state is activated.
I think I have a fundamental misunderstanding of how to properly use Box2D (especially joints). If someone could point me in the right direction I would be eternally grateful. I can't really provide my current code because it's become beyond broken.
An implementation such as the one above would have very poor performance and would likely tunnel in almost every situation. Therefore a solution is to add a sensor with a funnel shape and add a joint between this sensor and my hero. The implementation:
override protected function createShape():void{
var radius:Number = 4;
var vertices:Vector.<b2Vec2> = new Vector.<b2Vec2>();
vertices.push(new b2Vec2(0,0));
for (var i:int = 0; i < 7; i++) {
var angle:Number = i / 6.0 * .5* Math.PI;
vertices.push(
new b2Vec2( radius * Math.cos(angle),
radius * Math.sin(angle) ));
}
var sword_shape:b2PolygonShape = new b2PolygonShape();
sword_shape.SetAsVector(vertices,8);
_shape = sword_shape;
}

In canvas the alpha value of a stroke gets lost after another one

I'm creating a drawing program witch should also use semi-transparent brushes. When I use a transparent brush I end up with some transparent strokes, witch are the lasts until I release the mouse. If I then draw a new stroke again my old strokes get full opacity, even if I don't come across them. The program works getting mouse coordinates, waiting for position changed, and then draws (and strokes) a line which goes from the first point to the second. I have seen that some tutorial suggests to store in memory (array) all the path and draw it again on every mouse release, but I'm not sure due to memory consumption. The program is written in QML + javascript, but canvas works in the same way as does in HTML5.
Thank you in advance to everybody.
The following is the context call:
function pencilBehaviour() {
if (canvas.isPressed){
var ctx = canvas.getContext('2d')
if ((canvas.bufferX != -1) || (canvas.bufferY != -1)){
ctx.globalCompositeOperation = "source-atop"
ctx.moveTo(canvas.bufferX, canvas.bufferY)
ctx.lineTo(canvas.px, canvas.py)
ctx.globalAlpha = 0.4
ctx.lineCap = "round"
ctx.lineJoin = "round"
ctx.strokeStyle = "white"
ctx.lineWidth = 3
ctx.stroke()
console.log("pencil invoking canvas")
//Buffers are needed to draw a line from buffer to current position
canvas.bufferX = canvas.px
canvas.bufferY = canvas.py
}
else{
//Buffers are needed to draw a line from buffer to current position
canvas.bufferX = canvas.px
canvas.bufferY = canvas.py
}
}
}
Hard to know without code, but here is a guess...
Make sure all your new strokes begin with context.beginPath() so the context is not "remembering" your previous strokes.

AS3:Move Objects in a curve path using as3 programming?

I need to move many objects in a curve path across screen randomly. The objects start path and towards path also should take randomly. I had searched on google and finally i found one usefull tutorial to draw a curve. But i don't know how to move the objects using that curve path. But i am sure there would be some formula in as3 which has to use sin and cos theta. So please let me know if anybody have a solution for my problem. And also if i got any sample projects also would be very usefull for me.
And the link which i got to draw curve is as follows.
http://active.tutsplus.com/tutorials/actionscript/the-math-and-actionscript-of-curves-drawing-quadratic-and-cubic-curves/?search_index=4.
Thanks in advance.Immediate Help would be appreciated.
A quick'n'dirty would be using polar to cartesian coordinates(sin and cos) as you mentioned:
import flash.events.Event;
var a:Number = 0;//angle
var ra:Number = .01;//random angle increment
var rx:Number = 100;//random trajectory width
var ry:Number = 100;//random trajectory height
graphics.lineStyle(1);
addEventListener(Event.ENTER_FRAME,function (event:Event):void{
a += ra;//increment angle
rx += a;//fidle with radii otherwise it's gonna be a circle
ry += a;//feel free to play with these
graphics.lineTo(225 + (Math.cos(a) * rx),//offset(225,200)
200 + (Math.sin(a) * ry));//and use pol to car conversion
if(a > Math.PI) reset();//reset at 180 or any angle you like
});
function reset():void{
trace('reset');//more values to tweak here
a = Math.random();
ra = Math.random() * .0001;
rx = 20 + Math.random() * 200;
ry = 20 + Math.random() * 200;
}
Random numbers need tweaking to get mostly rounder ellipses (rather than flatter ones), but the principle is the same.
If you don't mind using libraries, why not try TweenLite's BezierPlugin or BezierThroughPlugin. Should be easy to randomize start/end points.
Also you can check out the first part of this older answer on quadratic,cubic and hermite interpolation
In my example I'm drawing a path, but of course, you could use those computed x,y coordinates to plug into a DisplayObject to move it on screen.

HTML5 Canvas DrawImage Stutter / Choppiness

PROBLEM
I am trying to get an image on a canvas to move from left to right smoothly. It's not too bad on Chrome/Safari (still stutters a little), but there is noticeable stutter in Firefox on multiple machines (tried on Windows and Mac). I'm a bit stumped as to how to solve this.
WHAT I TRIED
I am using requestAnimationFrame instead of setTimeout. I am using clearRect instead of setting the canvas width, though I am clearing the entire canvas instead of the minimum bounding box as I wanted to test it in the worst case scenario. I did close extra tabs. I even disabled Firebug. I am using drawImage instead of the image data functions. Since I'm not doing anything else but clearRect and drawImage, I avoided using an offscreen canvas.
EXAMPLE 1: http://jsfiddle.net/QkvYs/
This one has a set framerate where it ensures that the position is correct regardless of how often the game loop runs. It displays the number of frames skipped. This example is closer to what I'm aiming for. Note that it looks choppy even when no frames are being skipped. I have also played around with the framerate with no success, though I'd like to aim for about 30 fps (var frameRate = 33;).
EXAMPLE 2: http://jsfiddle.net/R8sEV/
Here is a simple one where all it does is move the image. This stutters for me on multiple machines.
//loop
function loop() {
//request anim frame
requestAnimationFrame(loop);
//set canvas once able
if (!canvas) {
var temp = document.getElementById("testCanvas");
if (temp) {
canvas = temp;
ctx = canvas.getContext('2d');
}
}
//update and render if able
if (canvas) {
//increase x
x += 5;
//start from beginning
if (x > canvas.width) {
x = 0;
}
//clear
ctx.clearRect(0, 0, canvas.width, canvas.height);
//image
ctx.drawImage(image, x, 200);
}
}
//start
loop();
WHAT I LOOKED AT
I realize that this question has been asked before and I did look before asking. However, the answers given have unfortunately not helped.
https://gamedev.stackexchange.com/questions/37298/slow-firefox-javascript-canvas-performance
HTML5 Canvas Animation Has Occasional Jitter / Hesitation / Stutter
Canvas animation stutters in FireFox but is perfect in Chrome
Is there a solution for HTML5 canvas animation stutter?
Thanks for the help! I appreciate it.
For instance use time delta in your position calculations. This will ensure that object is moved by certain value in given time regardless of FPS and delay between frames.
Edited your fiddle:
http://jsfiddle.net/R8sEV/2/
wrong approach:
x += 5
good approach:
x += speed * delta / 1000
where delta is time in [ms] which passed from last frame - and speed is measured in [pixels/second]
You are getting the element every frame?!
That can cause a lot of lag.
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var x = 0;
function loop() {
requestAnimationFrame(loop);
x += 5;
ctx.drawImage(IMAGE, x, 0);
}
loop();

How can I resize bitmap data without having to edit the transform matrix and maintain good quality

I am trying to resize a bitmap for a project we are working on at work in as 3.0. Basically we have a bunch of sprites that get drawn on a bitmapData and then are stored in a vector. The data in the vector eventually gets stored in a bitmap object. Now I want to make the BitmapData sprites smaller but don't want to have to update 100 matrix to do it. Is there another way?
I had some success by scaling the bitmap that gets displayed but the image is a bit jagged looking and the models don't turn around just moon walk.
I have also tired Matrix.a = 0.4 and matrix.d = 0.4 but that did nothing.
When I did bitmap.scalex = 0.7 and the same for scaleY it made it smaller but now they are in the air as the x and y aren't right and the code for them to go in reverse was just doing scalX *= -1 which now doesn't seem to work either. Also I figured out how to get them out of the air but they are as said before jagged and moon walking. Please help as I am attempting to fix code that was written before I got here.
Bascially here is some code, I got approval from the CEO:
we have this:
var b:BitmapData = new BitmapData(CustomerRenderer.BLIT_WIDTH,
CustomerRenderer.BLIT_HEIGHT, true, 0x00000000);
for(var i:int=0; i<WRAPPER.numChildren; i++)
{
b.draw(Sprite(WRAPPER.getChildAt(i)),
WRAPPER.getChildAt(i).transform.matrix, null, null, b.rect, true);
}
_spriteSheet[_currentFrame] = b;
Then we use that data in
BAKED_BITMAP.bitmapData = _spriteSheet[_currentFrame];
to display it where BAKED_BITMAP is a Bitmap
then to flip all the person was doing was:
BAKED_BITMAP.scaleX *= -1;
BAKED_BITMAP.x = (BAKED_BITMAP.scaleX >= 0) ? 0 : BLIT_WIDTH;
thanks
You can try setting the smoothing property of the Bitmap object to see if it gives you the desired effect.