I recently discovered a couple of 3D graphing programs for the fx 9860 calculator and was wondering how they where made.

The 3D engine made by Vanhoa (called Graph3D) is impressive. You can download the source code here:

http://www.planet-casio.com/Fr/programmes/programme2612-last-graph3d-vanhoa-b5.html

While it might take a while to initially process the x,y and z coordinates it does not need to recalculate the coordinates when panning the screen. I then discovered hugh9860 program called Reckon which has one of the best 3D graphers I have ever seen. You can download Reckon here:

http://www.voidware.com/reckon/

Its ability to graph the function in a split second makes it stand out from the rest.

I would like to know how the 3D grapher in Reckon works. The two major questions that come to mind are:

because the fx 9860 doesn't support 3D drawing how do you convert a point in 3D (x,y,z) to a position on the screen (x,y)? From doing some research this involves doing a 3D projection onto a 2D plane (in this case the 2D plane is the calculator screen). But there are a lot of ways to achieve this. How did hugh9860 program do this?

The second question is to do with calculating the z values from an equation that the user entered. for example if I entered the equation "z = x^2+y^2" how do I work out what the value of z is if x=2 and y=3? As a human being I can easily tell the answer is 13 but how do I get a program to work this out for me? I noticed that Vanhoa's 3D grapher using a file called EVALD.C that uses a bunch of if statements to determine the answer, however it is slow. It was only able to process approximately 80 values per second which means that some functions took up to 20 second to graph. With hugh9860 program it takes less than a second. how did he do this?

finally, I couldn't find the source code for reckon. Have a been looking in the wrong places or would hugh9860 prefer not to release it?

thanks in advance.
hugh9860, do you still intend to port Reckon to the fx-CG 10/20? I would be very happy to help, and I'm sure it would be a welcome addition to the Prizm list of add-ins.
Thank you for for your easy to understand posts. The picture really helps with explaining how everything fits together. I still have a lot more questions that I am curious about such as transforming the world space to view space (2D) and how you where able to shade in the surfaces. Because I have many more questions maybe it will be best if you could recommend any resources about 3D graphers or even other people's projects that you found useful when making yours.

That will save you the hassle of digging through your source code that you wrote in the past.
There's quite good overview here, about the 3D transforms and final view space transform.

http://www.codinglabs.net/article_world_view_projection_matrix.aspx

The implementation is much the same as the theory, except you have to decide exactly how you're going to store your transforms and object coordinates. For example in my diagram, the planes actually contain indices (not pointers) to the vertices and the list of vertices is one long list on the model. This means you can transform all your vertices in one hit. You need the planes later for drawing and also the plane normal.

You can decide the types of planes supported by your engine. most support only triangles. I have triangles and quads. There's nothing wrong with having just triangles. Quads are useful for some types of model, they look tidier in some cases. The 3D plot makes quads and then turns some into triangles. Remember quads can be a problem because quads can accidently be non-planar, but triangles cannot.

When you've transformed all your planes into view space, you have to render them. This is shading. I support three kinds of shading in my engine; wire, flat, gouraud. For monochrome (or ones with limited grey shade) displays, everything but wire shading looked just terrible.

So when you draw your planes, you draw them shaded. What i do is draw each plane a horizontal line at a time. The edges of the plane being calculated according to their slopes. Another complication is that you may need to clip a polygon to the view. When you clip a triangle to a box, you can get a quad. so even if you want to render just triangles, you have to deal with quads appearing from clipping. These can be draw as separate triangles, or you can have your shader be really clever with clipping and do it all at the same time.

For the 3D plot, you could probably ignore clipping and instead make sure you don't plot offscreen, but in general it's important. imagine a really large closeup triangle that fills the screen. You dont really want to be plotting 99% offscreen. Your engine will stall because filling the polygons cost the most CPU - even though it's a dumb operation. This is why graphics cards used to talk about "fill rate". Nowadays they're all insanely fast anyhow.
Thank you hugh for sending the link about world projections. I have been looking for a good tutorial and this is exactly what I wanted!

correct me if I am wrong but you shade in a plane by filling in the quad/triangle with lots of lines. This seems like an expensive process for a calculator. I probably won't bother with my 3D grapher but did you reduce the amount of planes to be shaded by only shading in the areas that can be seen by the camera (for example sometimes a function would look a bit like a hill. did you both filling in the areas on the other side of the hill)? just curious.

I noticed while using your 3D grapher that the bottom side of a function was shaded black. This was a really cool thing to do. How exactly did you do this? I suspect you used the function Bdisp_AreaReverseVRAM() somehow...

The reason why I want to make my own 3D grapher is because I find myself working with a lot of 3D functions in my uni degree and a 3D grapher will help my visualize the equations. while your 3D grapher satisfies my goal, what do you think of the following

features:

- Trace. Being able to select a point on the function and display the x,y,z coordinators

- find and display "del f" (the slope vector) of the function f at a given point.

- volume calculations

- catch and handle functions that have a limited domain (e.g. z=sqrt(x) is only valid when x >= 0)

-ability to graph multiple functions at once (maybe with a different style line for the z-frame)

- API support. creating an interface for other programmers will allow them to use your 3D grapher in their programs (i.e. games).

You have obviously put a lot of work into creating your 3D grapher which is why I think your program will be ideal for these features.
Filling polygons is the most expensive operation for a software renderer. When you use OpenGL, all that is done in hardware, but in software you have to fill all the pixels. Gourauld shaders have to interpolate across the fill, both for x and y as well as set them.

Plane visibility check. Yes you absolutely need this. When you transform your planes into world space, you test your plane normals to see if they point away from the viewer (normal dot z). such planes will not be visible. So the back planes are culled this way and this might roughly halve the number of planes left to draw.

The other thing you have to do is sort the planes from back to front. You can sort them on their midpoints, or even just using one vertex appears to work fairly well. You do this sorting so you can draw them in the order far away to near (see painters algorithm). Near planes occlude far ones. If your shape is convex, you can skip this sorting - it's why really old 3D games always had convex spaceships!

The alternative to sort and draw is Z-buffering. for z-buffer you have to have a buffer to remember the depth of each pixel you draw *and* you have to test this depth for each pixel drawn. it slows down a software renderer quite a bit and i prefer the sorting method in software. Hardware GPUs use z-buffers today because they do it all for free in hardware. Also you need enough RAM for your z-buffer which is usually 16 bits per pixel of screen.

The "wire" renderer is actually more intensive than the shaded one. In order to prevent the view "seeing through" the mesh, the planes are filled either white or black and their edges drawn afterwards. If the plane points down, is shade black otherwise i shade white. This makes the image look a bit clearer on such a limited display. A better display probably wouldn't need this trick. you'd be better colour shading and not doing this so-called "wire" view.

The renderer draws everything directly to memory, at the end of a frame, i flip the whole thing onto the screen.

BTW, i like all your ideas. I think they would all be really useful. Originally, i wanted to implement trace, but i never got around to it. Also, i wanted to label the graphs with text.

I'll try to find time to clean up my code a bit to make a source release, probably on github. It might make interesting reading, but for your project i would seriously consider writing your 3D engine in OpenGL. All of the stuff we've talked about is pretty much done for you in OpenGL.

The reason i suggest it, is that software renderers are dead now that GPUs are everywhere. If you wrote an OpenGL 3D graph plot, it would look really, really good. You could run it on your mobile phone or PC or anything and the experience gained would be useful to you in the future.

If you run Android, checkout this free calculator app i wrote in OpenGL

https://play.google.com/store/apps/details?id=com.voidware.retrofree

This is the sort of fidelity you could get with your 3D plot.
I finally got around to trying out the matrix translations/projections you linked me. It was satisfying to draw my first 3D cube with matrix translations. For others reading this thread I found a easy to follow derivation for the Projection Matrix:
http://www.codeguru.com/cpp/misc/misc/graphics/article.php/c10123/Deriving-Projection-Matrices.htm#page-1

I guess if you wanted to label the graph with text it might be easier to do this by add a 2D User Interface (UI). This could be done as a post effect by layering the UI over the rendered picture. With a user interface you would be able to draw a cursor onto the screen for trace and print the coordinates onto the screen. The UI could also be used to setup the boundaries of the 3D grapher and could be used to enter in multiple functions.

Sorry but could you please explain a little more on how the shaded render is less intensive than the “wire” renderer. In my mind I would assume that the shaded render would have to draw the lines and also shade in the planes while wire rendering would just have to draw the lines.

I would really appreciate if you released your code on github (cleaned up or as it is). I am still learning programming and I find having working code to refer to can be very helpful when resolving a problem. The reason why I want a 3D software engine is because we are allowed to use programs on our calculators for tests and exams but not our phones or computers. Plus it says on the wiki page for my calculator that it doesn’t support 3D graphs and I want to prove it wrong, haha.

Btw, your app is amazing. I am going to recommend it to all my friends. Much more entertaining than the default android calculator. Well Done!
I've dug out the code and looking at a clean up. will be a few days before its ready for a release. plan to release on github.
That's great to hear. you don't have to go to too much trouble cleaning up your code. I am sure you have better things to do than rewrite code you wrote in 2011 As long as its got commits I don't mind too much.
the routine to draw a wire polygon, draws a filled polygon then draws the edges of the polygon as lines over the top.

the wire view is more expensive because it needs to occlude the polygons through the gaps. in this sense it's not a true "wire" view.
The project is now on github. There's a visual studio project too for VS2013. You can load in a few objects like a torus and a teapot.
Thank you hugh.

sorry for the late reply, you were just much faster than I thought you would be.

Your work is very impressive. I will need to spend some time reading though your source code but from skimming through some of the files your code seems well spaced out and with comments. Thank you for taking the time to make it easy to read. If I have any further questions, I will post them here.

Correct me if I am wrong but I noticed that your program seems to overclock the calculator when crunching the numbers and then bring it back to normal speed afterwards. I like your style, haha.

I would love a teapot model and torus model. I am having a bit of a problem compiling the source code, so I won't be able to do much with the models for now. I keep on getting errors (for the casio SDK) such as doesn't know what "size_t" is and the key word "inline" seems to confuse it as well (as well as me). I noticed one of your files is called TAGS and seems to define these keywords. do I have to setup TAGS in a special way?




Not to sure if it's helpful but here is the exact error message from the compilar:

Executing Hitachi SH C/C++ Compiler/Assembler phase

set SHC_INC=C:\Program Files\CASIO\fx-9860G SDK\OS\SH\include
set PATH=C:\Program Files\CASIO\fx-9860G SDK\OS\SH\bin
set SHC_LIB=C:\Program Files\CASIO\fx-9860G SDK\OS\SH\bin
set SHC_TMP=C:\Users\CrazySquid1\Documents\CASIO\downloaded programs\reckon-master\reckon-master\Debug
WARNING: The following dependant file(s) do not exist: "2d.h" "2di.h" "bcd.h" "bcdfloat.h" "bcdmath.h" "calc.h" "common.h" "complex.h" "dlist.h" "eeval.h" "mi.h" "plot.h" "l3d\primitiv.h" "region.h" "solve.h" "symbol.h" "types.h" "complex2.h" "finance.h". Line: 205
"C:\Program Files\CASIO\fx-9860G SDK\OS\SH\bin\shc.exe" -subcommand=C:\Users\CRAZYS~1\AppData\Local\Temp\hmk6804.tmp
WARNING: The following dependant file(s) do not exist: "2d.h" "2di.h" "bcd.h" "bcdfloat.h" "bcdmath.h" "calc.h" "common.h" "complex.h" "dlist.h" "eeval.h" "mi.h" "plot.h" "l3d\primitiv.h" "region.h" "solve.h" "symbol.h" "types.h" "complex2.h" "finance.h". Line: 222
"C:\Program Files\CASIO\fx-9860G SDK\OS\SH\bin\shc.exe" -subcommand=C:\Users\CRAZYS~1\AppData\Local\Temp\hmk6A46.tmp
WARNING: The following dependant file(s) do not exist: "2d.h" "2di.h" "bcd.h" "bcdfloat.h" "bcdmath.h" "calc.h" "common.h" "complex.h" "dlist.h" "eeval.h" "mi.h" "plot.h" "l3d\primitiv.h" "region.h" "solve.h" "symbol.h" "types.h" "complex2.h" "finance.h". Line: 239
"C:\Program Files\CASIO\fx-9860G SDK\OS\SH\bin\shc.exe" -subcommand=C:\Users\CRAZYS~1\AppData\Local\Temp\hmk6AB4.tmp
WARNING: The following dependant file(s) do not exist: "2d.h" "2di.h" "bcd.h" "bcdfloat.h" "bcdmath.h" "calc.h" "common.h" "complex.h" "dlist.h" "eeval.h" "mi.h" "plot.h" "l3d\primitiv.h" "region.h" "solve.h" "symbol.h" "types.h" "complex2.h" "finance.h". Line: 256
"C:\Program Files\CASIO\fx-9860G SDK\OS\SH\bin\shc.exe" -subcommand=C:\Users\CRAZYS~1\AppData\Local\Temp\hmk6B71.tmp
WARNING: The following dependant file(s) do not exist: "2d.h" "2di.h" "bcd.h" "bcdfloat.h" "bcdmath.h" "calc.h" "common.h" "complex.h" "dlist.h" "eeval.h" "mi.h" "plot.h" "l3d\primitiv.h" "region.h" "solve.h" "symbol.h" "types.h" "complex2.h" "finance.h". Line: 273
"C:\Program Files\CASIO\fx-9860G SDK\OS\SH\bin\shc.exe" -subcommand=C:\Users\CRAZYS~1\AppData\Local\Temp\hmk6BC0.tmp
WARNING: The following dependant file(s) do not exist: "2d.h" "2di.h" "bcd.h" "bcdfloat.h" "bcdmath.h" "calc.h" "common.h" "complex.h" "dlist.h" "eeval.h" "mi.h" "plot.h" "l3d\primitiv.h" "region.h" "solve.h" "symbol.h" "types.h" "complex2.h" "finance.h". Line: 290
"C:\Program Files\CASIO\fx-9860G SDK\OS\SH\bin\shc.exe" -subcommand=C:\Users\CRAZYS~1\AppData\Local\Temp\hmk6CAB.tmp
WARNING: The following dependant file(s) do not exist: "2d.h" "2di.h" "bcd.h" "bcdfloat.h" "bcdmath.h" "calc.h" "common.h" "complex.h" "dlist.h" "eeval.h" "mi.h" "plot.h" "l3d\primitiv.h" "region.h" "solve.h" "symbol.h" "types.h" "complex2.h" "finance.h". Line: 307
"C:\Program Files\CASIO\fx-9860G SDK\OS\SH\bin\shc.exe" -subcommand=C:\Users\CRAZYS~1\AppData\Local\Temp\hmk6D67.tmp
WARNING: The following dependant file(s) do not exist: "2d.h" "2di.h" "bcd.h" "bcdfloat.h" "bcdmath.h" "calc.h" "common.h" "complex.h" "dlist.h" "eeval.h" "mi.h" "plot.h" "l3d\primitiv.h" "region.h" "solve.h" "symbol.h" "types.h" "complex2.h" "finance.h". Line: 324
"C:\Program Files\CASIO\fx-9860G SDK\OS\SH\bin\shc.exe" -subcommand=C:\Users\CRAZYS~1\AppData\Local\Temp\hmk6DC5.tmp
C:\Users\CrazySquid1\Documents\CASIO\downloaded programs\reckon-master\reckon-master\cutils.h(50) : C2500 (E) Illegal token "int"
C:\Users\CrazySquid1\Documents\CASIO\downloaded programs\reckon-master\reckon-master\cutils.h(50) : C2500 (E) Illegal token "const"
C:\Users\CrazySquid1\Documents\CASIO\downloaded programs\reckon-master\reckon-master\cutils.h(50) : C2500 (E) Illegal token "n"
C:\Users\CrazySquid1\Documents\CASIO\downloaded programs\reckon-master\reckon-master\cutils.h(51) : C2500 (E) Illegal token "{"
C:\Users\CrazySquid1\Documents\CASIO\downloaded programs\reckon-master\reckon-master\common.c(40) : C1016 (W) Argument mismatch
C:\Users\CrazySquid1\Documents\CASIO\downloaded programs\reckon-master\reckon-master\common.c(42) : C1016 (W) Argument mismatch
C:\Users\CrazySquid1\Documents\CASIO\downloaded programs\reckon-master\reckon-master\common.c(43) : C1016 (W) Argument mismatch
C:\Users\CrazySquid1\Documents\CASIO\downloaded programs\reckon-master\reckon-master\common.c(44) : C1016 (W) Argument mismatch
C:\Users\CrazySquid1\Documents\CASIO\downloaded programs\reckon-master\reckon-master\common.c(45) : C1016 (W) Argument mismatch
C:\Users\CrazySquid1\Documents\CASIO\downloaded programs\reckon-master\reckon-master\common.c(601) : C1016 (W) Argument mismatch

HMAKE MAKE UTILITY Ver. 1.1
Copyright (C) Hitachi Micro Systems Europe Ltd. 1998
Copyright (C) Hitachi Ltd. 1998


ERROR: Process failed with return code: 1
Build was not successful.
I will check out the graphics test tomorrow. As for my compile problems I think I will be able to solve them by myself. You have been very helpful however as long as my casio program compiles I should be fine, haha. I plan on using your source code as reference material.
I am curious, do you get a lot of people that ask you for help with regards to programming? because your help is really easy to understand.
I have done a number of presentations in the past. This helps to think about what to say. Also, I usually do a calculator related talk in London, UK every September at the HPCC annual mini-conference.

Last year it was on wearable tech.

Thanks for your comments. let me know if you've any specific code questions.
Two things. Firstly how did you make the 3D models (e.g. teapot)?

and secondly I think your source code might be missing a file (probably called "utils.cpp"). the functions (such as GetVRAMPtr() ) are defined in utils.h but are never implemented in a .cpp file.

the visual studio project doesn't require utils.h so this explains why the visual studio project compiles but the casio SDK doesn't.
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 2
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement