Omnimaga
Calculator Community => HP Calculators => Topic started by: Han on December 18, 2013, 02:54:12 pm
-
Since I cannot upload yet, here is the source. More info here: http://www.hpmuseum.org/forum/thread-95.html (http://www.hpmuseum.org/forum/thread-95.html)
// Graph 3D v2.221 (16-DEC-2013)
// by Han Duong
g3D_setdefault();
g3D_getfunc();
g3D_getsettings();
g3D_getwin();
g3D_setgrid();
g3D_getangles();
g3D_rotmatrix();
g3D_compute();
g3D_project();
g3D_draw();
g3D_keys();
xmin3D,xmax3D;
ymin3D,ymax3D;
zmin3D,zmax3D;
grid3D,zoom3D;
rotx,roty,rotz,Rx,Ry,Rz,Rot;
xc,yc,zc;
Zvals,Points2D,Point,zColor,zClip;
redraw3D=1,recompute3D=1,init3D=0;
minD,fxy="";
//----------------------------
// START FUNCTION
//----------------------------
view "Edit Function",START()
begin
if init3D==0 then
g3D_setdefault();
end;
startview(0,1);
end;
//----------------------------
// RESET FUNCTION
//----------------------------
View "Reset Plot Settings",RESET()
begin
g3D_setdefault();
end;
//----------------------------
// Symb FUNCTION
//----------------------------
Symb()
begin
startview(0,1);
end;
//----------------------------
// SymbSetup FUNCTION
//----------------------------
SymbSetup()
begin
msgbox("Use X and Y as the input variables.")
end;
//----------------------------
// PlotSetup FUNCTION
//----------------------------
PlotSetup()
begin
if init3D==0 then
g3D_setdefault();
end;
g3D_getsettings();
end;
//----------------------------
// Plot FUNCTION
//----------------------------
Plot()
begin
if init3D==0 then
g3D_setdefault();
end;
g3D_draw();
end;
//----------------------------
// Numb FUNCTION
//----------------------------
Num()
begin
local z_Values;
if init3D==0 then
g3D_setdefault();
end;
g3D_compute();
z_Values:=Zvals .+ zc;
editmat(Zvals);
end;
//----------------------------
// NumSetup FUNCTION
//----------------------------
NumSetup()
begin
if init3D==0 then
g3D_setdefault();
end;
g3D_setgrid();
end;
//----------------------------
// g3D_setdefault
//----------------------------
g3D_setdefault()
begin
xmin3D:=-10; xmax3D:=10;
ymin3D:=-10; ymax3D:=10;
zmin3D:=-10; zmax3D:=10;
zoom3D:=10; grid3D:=15;
rotx:=105; roty:=0; rotz:=5;
xc:=0; yc:=0; zc:=0;
redraw3D:=1;
recompute3D:=1;
init3D:=1;
fxy:="";
g3D_getfunc();
end;
//----------------------------
// g3D_getfunc
//----------------------------
g3D_getfunc()
begin
local i, ftot=0, fnew, fsel;
for i from 0 to 9 do
if ISCHECK(i) then
fsel:=i; ftot:=ftot+1;
end;
end;
if ftot==0 then
msgbox("Please enter/select a function!");
startview(0,1);
kill;
end;
if ftot>1 then
msgbox("Please select only one function!");
startview(0,1);
kill;
end;
fnew:=expr("STRING(V"+fsel+")");
if fnew<>fxy then
fxy:=fnew;
recompute3D:=1;
end;
return(recompute3D);
end;
//----------------------------
// g3d_getsettings
//----------------------------
view "Plot Settings (all)",g3D_getsettings()
begin
if init3D==0 then
g3D_setdefault();
end;
g3D_getwin();
g3D_getangles();
end;
//----------------------------
// g3D_getwin
//----------------------------
view "Set Viewing Window",g3D_getwin()
begin
local xmin,xmax,ymin,ymax,zmin,zmax;
local zoom;
if init3D==0 then
g3D_setdefault();
end;
xmin:=xmin3D; xmax:=xmax3D;
ymin:=ymin3D; ymax:=ymax3D;
zmin:=zmin3D; zmax:=zmax3D;
zoom:=zoom3D;
if input(
{xmin,xmax,ymin,ymax,zmin,zmax,zoom},
"Graph 3D View Window",
{
"Xmin=", "Xmax=",
"Ymin=", "Ymax=",
"Zmin=", "Zmax=",
"Zoom factor="
},
{
"Enter the value of back side of the viewing box",
"Enter the value of front side of the viewing box",
"Enter the value of left side of the viewing box",
"Enter the value of right side of the viewing box",
"Enter the value of bottom side of the viewing box",
"Enter the value of top side of the viewing box",
"Enter the zoom factor (must be > 0)"
},
{xmin3D,xmax3D,ymin3D,ymax3D,zmin3D,zmax3D,zoom3D})
then
if xmin>=xmax then
msgbox("Warning: Invalid Xmin/Xmax! Setting Xmax:=Xmin+1");
xmax:=xmin+1;
end;
if ymin>=ymax then
msgbox("Warning: Invalid Ymin/Ymax! Setting Ymax:=Ymin+1");
ymax:=ymin+1;
end;
if zmin>=zmax then
msgbox("Warning: Invalid Zmin/Zmax! Setting Zmax:=Zmin+1");
zmax:=zmin+1;
end;
if zoom3D<1 then
msgbox("Warning: zoom must be > 0; reset to 10");
zoom:=10;
end;
if (xmin<>xmin3D) or (xmax<>xmax3D) or
(ymin<>ymin3D) or (ymax<>ymax3D) or
(zmin<>zmin3D) or (zmax<>zmax3D)
then
recompute3D:=1;
xmax3D:=xmax; xmin3D:=xmin;
ymax3D:=ymax; ymin3D:=ymin;
zmax3D:=zmax; zmin3D:=zmin;
xc:=(xmax3D+xmin3D)/2;
yc:=(ymax3D+ymin3D)/2;
zc:=(zmax3D+zmin3D)/2;
end;
zoom3D:=zoom;
end;
end;
//----------------------------
// g3D_setgrid
//----------------------------
view "Set Grid Size",g3D_setgrid()
begin
local grid;
if init3D==0 then
g3D_setdefault();
end;
grid:=grid3D;
if input(grid,"Graph 3D Grid Size","Grid Size=","Enter N for an NxN grid",grid3D) then
if grid<1 then
msgbox("Warning: grid size must be > 0; reset to 15");
grid:=15;
end;
end;
if grid<>grid3D then
recompute3D:=1;
end;
grid3D:=grid;
end;
//----------------------------
// g3D_getangles
//----------------------------
view "Set Rotation Angles",g3D_getangles()
begin
local rx,ry,rz;
if init3D==0 then
g3D_setdefault();
end;
rx:=rotx; ry:=roty; rz:=rotz;
if input({rx,ry,rz},
"Graph 3D Rotation Angles",
{ "X-angle=", "Y-angle=", "Z-angle=" },
{
"Enter the angle (deg) about the x-axis",
"Enter the angle (deg) about the y-axis",
"Enter the angel (deg) about the z-axis"
},
{rotx,roty,rotz})
then
if (rx<>rotx) or (ry<>roty) or (rz<>rotz) then
rotx:=rx; roty:=ry; rotz:=rz;
end;
end;
end;
//----------------------------
// g3D_rotmatrix
//----------------------------
g3D_rotmatrix()
begin
A:=rotx; B:=roty; C:=rotz;
if HAngle==0 then
A:=A*PI/180; B:=B*PI/180; C:=C*PI/180;
end;
Rx:=[[1.,0.,0.],[0.,COS(A),-SIN(A)],[0.,SIN(A),COS(A)]];
Ry:=[[COS(B),0.,-SIN(B)],[0.,1.,0.],[SIN(B),0.,COS(B)]];
Rz:=[[COS(C),-SIN(C),0.],[SIN(C),COS(C),0.],[0.,0.,1.]];
Rot:=Rx*Ry*Rz;
Rot(3,4):=minD;
end;
//----------------------------
// g3D_compute
//----------------------------
g3D_compute()
begin
local i,j,dx,dy,xm,ym,func;
local m,minZ,maxZ;
if g3D_getfunc() then
iferr func:=STRING(V0); then func:=""; end;
V0:=fxy;
if recompute3D then
zColor:=makemat(RGB((grid3D+1-J)/grid3D*255,0,(I-1)/grid3D*255),grid3D+1,grid3D+1);
dx:=(xmax3D-xmin3D)/grid3D;
dy:=(ymax3D-ymin3D)/grid3D;
xm:=xmin3D-dx; ym:=ymin3D-dy;
Points2D:=makemat((xm+dx*I-xc,ym+dy*J-yc),grid3D+1,grid3D+1);
// apps currently have terrible bug handling
iferr
Zvals:=makemat(V0(xm+dx*I,ym+dy*J)-zc,grid3D+1,grid3D+1);
then
recompute3D:=1;
msgbox("Error during evaluation of function!");
V0:=func;
kill;
end; // end error trap
recompute3D:=0;
// get longest distance from center to prevent inversion
minZ:=min(Zvals); maxZ:=max(Zvals);
minD:=10+(max(abs(minZ),abs(maxZ))^2+(xmax3D-xc)^2+(ymax3D-yc)^2)^(.5);
end; // if recompute3D
V0:=func;
end; // if g3D_getfunc
end;
//----------------------------
// g3D_project
//----------------------------
g3D_project()
begin
local clip;
g3D_rotmatrix();
dimgrob_p(G1, 320, 240);
clip:=triangle(G1);
triangle_p(G1, Points2D, zColor, Zvals, { "N", -160, -120, minD*zoom3D }, Rot, clip);
blit_p(G0,G1);
end;
//----------------------------
// g3D_draw
//----------------------------
g3D_draw()
begin
if init3D==0 then
g3D_setdefault();
end;
g3D_compute();
g3D_project();
g3D_keys();
freeze;
end;
//----------------------------
// g3D_draw
//----------------------------
g3D_keys()
begin
local key,mousein, dx, dy;
while 1 do
key:=wait(-1);
if TYPE(key)==6 then break; end;
if key==-1 then break; end;
repeat
case
if key==1 then roty:=(roty+5) MOD 360; end;
if key==3 then roty:=(roty-5) MOD 360; end;
if key==4 then kill; end;
if key==7 then rotz:=(rotz-5) MOD 360; end;
if key==8 then rotz:=(rotz+5) MOD 360; end;
if key==2 then rotx:=(rotx-5) MOD 360; end;
if key==12 then rotx:=(rotx+5) MOD 360; end;
if key==45 then zoom3D:=max(zoom3D/1.05,.01); end;
if key==50 then zoom3D:=zoom3D*1.05; end;
end;
g3D_project();
until NOT IsKeyDown(key);
end; // end while
end;
-
Heya, thanks for posting this here too. I am glad that you finally added filled polygons. What I am curious about is how we could write a program that shows the graph rotating, just to demonstrate how fast Graph 3D can be? I checked the app and it renders incredibly fast. I'm planning to create a Youtube video to showcase the capabilities of the HP PPL language.
EDIT: Nevermind, we can now rotate with arrow keys :)
By the way, although you can't upload in the downloads section yet, you can still upload files below posts on the forums. Just click EDIT then look for the upload form below your post text. :)
-
A sneak peak of what's to come.
-
Wow, HP definitively won't need to add 3D graphing to the calc, that's for sure, as you already did it and it's really impressive. I wonder if they could maybe pre-package this with the calc? It would be amazing (assuming they give you credits of course).
-
Wow, that is looking awesome, you did some great work on it!
:thumbsup:
-
Source is now available at http://www.hpmuseum.org/forum/thread-95-post-2243.html#pid2243
-
Thanks for the post. Gonna try this on the emulator soon. Have apps been fixed on calc yet? I heard horror stories before, but it was on the previous firmware.
-
As far as I know, apps have become quite stable since the update.
-
Ok good to hear. By the way, the video shows a lower frame rate than the previous version. Is it due to the emulator being capped at 10 images/seconds or has rendering speed slowed down?
-
It is slower because I am using a different rendering method. The previous version uses TRIANGLE, which did z-clipping and perspective projection within the command. However, it did not allow alpha blending. So I ended up having to do my own projection calculations as well as render with FILLPOLY (for the alpha blending) which is much slower.
-
Oh right, I didn't realize that TRIANGLE lacked Alpha blending. I wish Alpha blending was extended to other commands, including BLIT, TEXTOUT and RECT.
Also how do we rotate in this version? I tried the arrow keys and they no longer let me rotate. I can zoom in/out with + and -, though.
EDIT: Nevermind, it seems that Symb and Help rotates, although it seems to behave weirdly
-
The direction keys rotate; it may be that your grid size is so large the rotation gets super slowed down. Imagine the default axes set up such that negative x points behind your screen, and positive x points towards you, the user. Negative y points left, and positive y points right. Positive z is up, and negative z is down. The left/right arrows rotate around the z-axis, up down rotate around the y-axis, and symb/help rotate around the x axis.
-
Wow this is awesome! :o They should definitely package this with the calc!
-
Also how do we rotate in this version? I tried the arrow keys and they no longer let me rotate. I can zoom in/out with + and -, though.
EDIT: Nevermind, it seems that Symb and Help rotates, although it seems to behave weirdly
Ensure radian mode is on. It seems my attempt to account for various angle modes did not work properly.
The rotation bug was due to me setting all the angles to rotx! There's a new version up (same version number, different date) that fixes this among a few other issues.
-
Wow Han, that is impressive! Do you think complex graphing would be possible, too? Since this would map a complex number to a complex number (C→C) it requires 4 dimensions, so typically 3D+color is used. That would be pretty cool for complex analysis:)
-
Wow Han, that is impressive! Do you think complex graphing would be possible, too? Since this would map a complex number to a complex number (C→C) it requires 4 dimensions, so typically 3D+color is used. That would be pretty cool for complex analysis:)
I had given it some thought once someone reported some inconsistencies with complex mode on. If there is enough demand, I may add it in a future update.
-
I would like complex mode also, if you're counting.
-
Also how do we rotate in this version? I tried the arrow keys and they no longer let me rotate. I can zoom in/out with + and -, though.
EDIT: Nevermind, it seems that Symb and Help rotates, although it seems to behave weirdly
Ensure radian mode is on. It seems my attempt to account for various angle modes did not work properly.
The rotation bug was due to me setting all the angles to rotx! There's a new version up (same version number, different date) that fixes this among a few other issues.
Ok thanks! :D
-
Graph3D has been updated to work with the latest firmware (6030). If you updated to the most recent firmware, then the older versions no longer work due to updates to the TRIANGLE command. Version 2.2polytrace still works, but uses a very slow rendering routine. Version 2.3 (the latest) now combines all the features of the previous versions into a single app.
-
Thanks for the update. :D I wish that some of the other early HP Prime developers would update their programs to work with the new firmware.
-
You can get a preview of the 3D contour here: HP Prime Graph3D with contours (https://www.youtube.com/watch?v=x2WitB0E7NU)
-
Very good job! I wonder how fast it will run on the real calculator?
-
Source is available, now: Source code: http://www.hpmuseum.org/forum/thread-95-post-362.html
-
Thanks for posting. :) I'll try to install this on my calculator when I have some time. :)