old version:
Here is a cleaned up version of the 3D library that I put together for the Pico Fox game.
The demo code is commented in more detail, but here is the basic gist.
Copy the code between Begin Cut and End Cut. (It's a big chunk.) In _init() function include: --init_3d() --Need to call init_3d() to set up player, camera and lights --use load_object(object_vertices,object_faces,x,y,z,ax,ay,az,obstacle,color_mode,color) to load 3D models into the world --use read_vector_string and read_face_string to generate vertex list and face list from string data In _update() function include: --handle_buttons() -- handle default buttons for player-- this can be overwritten obviously. --update_player() -- update the player with default movement, stopping at obstacles --update_camera() -- update the camera based on player location and direction --update_particles() --update 3D particles if used. (I didn't add any for this demo.) --... --update_3d() -- call update_3d() at the end of the _update() function to transform etc. in _draw() function include: --draw_3d() --render objects into triangles, sort the triangles and draw them onto the screen |
Please feel free to use this in your projects as well as to update it and make it work better.
New features for version 2:
--Significant speed increase (2X!)
--Load models from strings to save token space
--Python script to translate from ".obj" files to compressed string
Run the script in the folder with the files that you are converting.
python low_poly_compress-01.py filename.obj
Detailed instructions and script found on GitHub.
https://github.com/electricgryphon/Pico-8-Gryphon-3D-Engine-Library
Thanks for the share, looking forward to seeing some projects using this.
Thanks for sharing! I made a tiny game with this. https://www.lexaloffle.com/bbs/?tid=28139
I optimized the rendering of the engine--more than double the speed for dynamically shaded models.
The most significant tweaks were:
--New triangle rendering code based on the results of the triangle thunderdome thread
--Faster quicksort replaces bubblesort
--Projecting points more efficiently (I was projecting the same vertex multiple times previously
These, combined with some in-lining and other optimizations pushed the speed up quite a bit so that "large=338 faces" models can be rendered in real time with shading.
I also added functions to load objects from strings as opposed to massive arrays of numbers. Those arrays are nice and readable, but they chew through tokens.
The conversion script can be downloaded here: https://github.com/electricgryphon/Pico-8-Gryphon-3D-Engine-Library
How do you do that? Seriously, how do you make a 3D engine? I realize this is probably a really broad question, but I wouldn't even know where to start :o
Edit:
Also, if you can't tell, I'm super impressed. @.@
@electricgryphon: Great job! I loved this before, and this is a huge improvement!
@Lumiette: Definitely check out the code; it's well commented and messing with it a bit should help you start to understand how it works.
Great work! Want to try and make something with this library but the link to the Python script is broken. Could you please reupload it? Thanks!
Try this: http://s000.tinyupload.com/index.php?file_id=56902566375777023329
I updated the link in the description as well.
Thank you, link works now.
Haven't been able to succesfully convert an .obj though.
Tried running the script with Python 2.7 and 3.6 but both don't work. I'm trying to convert a basic cube. (The one you get when you open Blender) I get two errors at the parts when num_text is stored in val. In the model_v line there is an "n" that can't be converted to float and in the model_f line all data looks like "1//2" and thus can't be converted to int.
Have tried simply filtering the n and // out but that doesn't work obviously. :-) Not really familiar with the .obj file structure so not sure what I'm doing wrong.
Thanks for the heads up--I may have tweaked some blender settings.
I'll put together a proper tutorial.
Here's a link to a tutorial on how to convert files using the script:
http://s000.tinyupload.com/index.php?file_id=07536305212150547235
(This is also added to the cart description.)
Let me know if anything is unclear or if you have problems and I will update the document.
Thanks!
Thank you for the tutorial and the fast response! :) Works perfectly and have already started working on some simple player stuff. (Thinking of making a simple shooting gallery)
Hey this is great! I got some models loaded and it's pretty fast! What would be the best way to set the color of the individual faces?
Hey electricgryphon, I'd love to see copies of the .obj files used for these demos and/or picofox as well if you've still got them. Do you think you could put them on Github? I'm new to blender, and it'd be cool to have something to play around with so I know I'm on the right track with the model creation. Thanks!
EDIT: previously, this said I couldn't access any of the tinyupload URLs, the issue has since resolved itself.
Tools and instructions are loaded on GitHub.
https://github.com/electricgryphon/Pico-8-Gryphon-3D-Engine-Library
I have also included a demo blender file for a basic animal.
Currently there is no support for automatic importing blender files with individual face colors. (On the PicoFox program, I did this by hand :-/ ) This is definitely on the list of features to be added in the next version.
-Electric Gryphon
Hi electricgryphon,
I'm trying to port the lib to C, and I'm running into a problem with some of the bitwise operations. Here in particular: https://github.com/computermouth/eg3d/blob/master/render.c#L2020
I can't quite figure out what value this is supposed to be retrieving. I wonder if it's some sort of floating point magic? I tweeted at zep here https://twitter.com/ComputerMouth/status/854203622095077378
At first I thought it was a bug, but the more I look at it, the more it seems like the library actually depends on this behaviour. Any tips?
-- Ben
Hi Computermouth,
Pico 8 stores numbers in a fixed point format of 0xFFFF.FFFF.
In this case, I'm using band(val,0xffff) as a way to speed up floor().
Zep reduced the function overhead CPU cost of bitwise operations so one way to speed up programs is to use these operations whenever possible.
-ElectricGryphon
electricgryphon, I've kept forgetting to reference something I've did months ago, was to work on something with your lib but sadly pico-8 is too limited for it and kinda moved to other non-pico8 related stuff =/
You can have a look at the converter for blender: https://github.com/justburn/EGryphon3DLibPanel
Oh... and as a bonus (Inspired by Picofox):
Hi JustBurner,
Your arrangements of the StarFox songs are great! Could I pull them into the game? Some proper menu music, like you provided, will work wonders.
The blender export will also come in handy--i've been writing offline conversion scripts, but this could save some steps.
-ElectricGryphon
Sure, I'll be glad if you use them into your game! (Corneria is 3 channels instead of 4 for a reason), it will need some tweak to join them together and add sfx.
If you're going to update your game don't forget to fix a bug in the center_text function and "cornerea" typo... could say to upgrade for v2 of the engine but that's asking too much ;)
One thing I'd change would be using checkerboard dithering instead of lines. IMO it would look better.
Also how do I add my models to it and what is reasonable vertex count?
//edit: I've walked into one of the floating tetrahedrons in that temple thingy (one with cube) and it looks like you're not doing backface culling. Any reasons for that?
Welcome back Darkhog.
Check the thread for details and tutorials of how to load models. (There is a script I posted on github.)
I run backface culling for most triangles, but turn it off when triangles are being clipped by the view plane. (The clipping code is a hacky mess, and it loses the winding/normal direction of the triangle.)
I have a raccoon demo posted that shows how to do checkered dithering on the 3D models. It's a little slower than the line shading, but does look cool.
I think I know why it's slower for checkerboard shading. You seem to be copying parts of spritesheet that seems to be a LUT texture which has checkerboard patterns backed in, instead of just storing the gradients somewhere and calculating shading at runitme using line (for # fill first fill with a solid color of internal dots, then plot perpendicular 90 deg. lines of second color, for crisscross just put 45 degrees lines in whatever color order). I think it's be faster that way.
Whelp, Just loaded the doggy model from your Github repo electricgryphon into my 3d engine and my pico8 cpu pegged at 2.2, in your engine the model tops out at a cpu of 1.1.
Even just as a wire frame that model pushes my engine to 1.3 while rotating!
Looks like I have lots of efficiencies to look for, about 0.5 CPU is spent just transforming the co-ords into world space.
Hi, will you update this Engine to support textures with the new tline()?
Hi leissler, I'm not planning on adding to this particular engine now. There are a couple of folks who are doing great things with tline now, including Johan Peitz. https://twitter.com/johanpeitz/status/1266090587683422209
Back in the --ahem-- old days we didn't have tline() and made do with hacky cludges. https://www.lexaloffle.com/bbs/?tid=29819
@electricgryphon I'm trying to do make a 3d face in pico-8 but it gives me this error. here are the variables
model_v="024d0000e83d02cb0000e8c502210000e8c701450000ed4b02920000e97901ac0000ee32f72a1212e8f9f64512bfe92ef70b12bfe960f5430ad1ed12f4a10b3cec3ff44b0bdaed0ffcad0492f2cdfcd104caf401fc090548f3abf89d0509f27bf8830548f3abf7e00492f2cdfd8212bfe960fd621212e8f9f2400000e83df26c0000e8c7f1c20000e8c5f2e10000ee32f1fa0000e979f3480000ed4bfea50000f180feed0000f298feaf0000f2fafe740000f1cdf8760349f42ef8f10488f381f8890331f357fc160000f487fcc10000f533f97d08aff35af97809fff35df9db08aff35afb0f08aff35afb1409fff35df8760000f487f7cb0000f533f8970312f378f8770349f42ef7de083df083f8550762f14df6cf049bf219f86501e3f4b5fa460831f2f0faa30831f2f0fc5607c5f26bfb1308d1f3b6f6190000f1cdf5a00000f298f5e70000f180fa490831f3c9f5de0000f2fafa7c0831f34dfa460831f34d03dc08d1e40002db0c43e400036e0d09e400028d0dbfe400032e0e3de40003630711e400fc380762f14df99a0831f3c9fa46082ef3c7f9610405f434fc1e0354f494fb2c0405f434f15e0e3de400f2000dbfe400f11e0d09e400f1b10c43e400f0b008d1e400f1290711e400fe4712bfe92ef6ba12bfe9cdf71512bfea01fd7812bfea01fdd212bfe9cdf9960831f34dfa35081af3b6f9710926f497fb2503eef394fb2703f3f3b6fa460802f347fba604a4f421fbd703fdf3fdfb9c0488f38101df10f4e71c0171100ce6a3fbda0404f42efb210a8af49af96c0a8af49afb1b0926f497f9b70661f406f82d062bf3fef9bb0639f367face0726f210fb2c0404f42efad60786f33afa4607edf30afa46081af2ddfbbb0391f42ef99c07f7f2c0f6b60ba1ee57f4f60b69edeff2d9087eeee6f3580dfbecb0fbee03c6f42ef7bb04caf401f83009aaf161f2ef0a49ead7f3bd0d3eebe6f9f007c9f37200d00d3eebe6f8e604a4f421f86e0354f494f84801f2f606fc4105dff2c9fdbd049bf219f08d0640e496f11a05f3e44101340dfbecb0f96803eef394f9db07b0f35df9a40d31edc4f8d40bc4ed58f8470e44ed77019d0a49ead7fcae083df083fffb040fef59fbf00509f27bfc040331f357fc160349f42efc0c033cf3b6020e0ad9eb90fbe7034af35ffbcf03eef394f84e092cf053f8030b6decd0fc60062bf3fefc520331f357f8910312f42efad60661f406fc070312f378fc520312f378fc450e44ed77fc520312f42efdf304d4f34300420bdaed0f0053043ff058fcd308adf194f491040fef59f6ea0b06ed75fc2801e3f4b5ffeb0b3cec3ffdd701a5f2bcf27f0ad9eb90ff5e0c1aec40fd890c5bec8bf31c100ce6a304000640e49601b4087eeee6f3440810edfbf2ae10f4e71cf43a043ff058fc640f11ee59ffad0cc5ed0ffdbc0d0aed60faf20dedeeacfbcf0c6bee38fc5c09aaf161fc3e092cf053fad20639f36701480810edfbfc520349f42ef8290f11ee59037305f3e441fda30b06ed75fbb90bc4ed58f69a04d4f343f7b908adf194f9b60786f33afae80d31edc4f84c05dff2c9f8bd0c6bee38f83707c5f26bf52e0c1aec40f6d10d0aed60f4e00cc5ed0ffc4501f2f606fe0e01b0f3eff9be0726f210fc3b00f9f5eff7e10c0eeda9fcac0c0eeda9f85100f9f5eff99a0dedeeacf6b501a5f2bcf67e01b0f3eff7030c5bec8bfc890b6decd0ff960b69edefff490ad1ed12fdd60ba1ee57"
model_f="0102030403050503020506040708090a0b0c0d0e0f10111209130714071315161718191a161a1919171604061b1c1b061d1e1c1e1b1c1f20211e1d2223221d24252627262829222a232a222b212c2d2e2f212b303126322732263334273536372734262738341a37183618372939353a38273b3a2627263a3635392a39293c3d3e3f3e3d403e3f3c413d27284243443845464748494a494b4a4c4a4b4c4b4d4e141325242e084f094f50095113500950135213514e13522e2d252826254453383124264454533a44382426552634555645573b26532453263a5844595a5b5c405d595e5a5f60615561603f5d40335f61613433116263615534116462613438653227475b666167346869313b583157666a323a31686b693b313a595b47665a5e5343386c6d6e6f4f085e70667111636c6e720b7374730b0a6831584443547554435d76147778457554585854447879467553543a325865427a7b7a424645783268587c7d154e527e45567f4454675475678067754547668182836657452742334265337558805d3f847b4285843f3d758053177c1585867b4467384d7d7c2734671f2171877a7b4c4d7c7b880d898a6a3c3e8b8c6a888d8c887b0d878e8f820d0f870e0d880f0e902078771f71781f782088918a7e5251886a8a2c89922b2c920f9093918894919495676138157d166765271496839594970e98907e998b989a9b9c35376567339b33989833908b3e408b405c8b5c7e258e8286041b9c167d8e9d8f765d849e22302930229f76849488a0887ba0861ea08128257c6ea1a07b8617197c9c371a1b1e86a2a396a449489c1a169614769676a2a58ba673a77d737d4da4a8089c7da7734d4b7c19a9aa7e515947467eaaab7ca14c734b49aaacab0e4698a505025fad605faead5fafae9baf5f212f12a5a69a465e594228859a06058685b0a59a05122f10657ab1b0b2866e7ca991b38a898ab362b193726ea90e8946aa51b450b45186b503906793b6b2b0a5413c3c8ba5890e8a6f08a890336797b3959195b3a5b54128b7b0a50201888a0e9c2d2f6a6670a501b58528b00103b5979289a9b8b967ba93896a70830714048603b39789b7bb9646705e7046895f339bb2b5862fbc10843d4163b8718441b560bd726072b924be2eb284b5bfc0c1c21dc32ebec4b878719a1c06aab4ad1dc2c57112111c9a1d72a9b96fc1b4c66c72adaeaabdc672af9b9aaeacaaa78e9cc346c29c8e2d63beb8c31d9a9aa6afaec7acb8beb973a4741dc523252d8ea8a4489e1e22a10c6fbe60b94e5d14afc7aea01e9e4e5c5d7e5c4ec82ac507a40860be55a09e946b2431c8c579c279c5c960adca9c2f4679c231696bc39a989846c3ca2f218a2c8821882c3035ca568c7f217f8c218c886fa8a130293560c9bd9794922b9294bdc0c6246b536bba53bdb4c0888c5b565b8c258281c0b4c153ba43a919185b5766575b56892c8aba80431836a9566a8c583b536a565766575a565a57cbb8a95a568d8c8d56cc828f53ba587483bf392ac8ba6b68949e2bb4bdc9c0bfcccb79782130caba5380c6c0cc23c52a302b9ec9adb4bebac4c87939bbb728cb78b88183bb96bb83be2455740783ca359cba68c4a4077481bb28b796a3504f6fbabe63a3cdb76362bacdb0b76293ba79cb39a2aca380ba67506fb4754380a93639a939cb9fa27658ba802ec4bc7eab99730aa7cecfb684cf9f49a47384b2cfa1a84865c4329fcf99c46832a1484aa29f9999aba2ce99cf10bc64a2abac4a4ca183ccbfc7cda364b1629dc68fa3acc764bcc4c7b6cdb6cfb2cc8fc665b1c464c4b1cdb6b09d6d6cafd0c70a6d9dd0afa6b6c7d09da70ab6d0cec69d6c8b99cecea68bd0a6ce9d8ea75b8d885b5a8d8382cc7a87b1870fb10f93b121127121207f20457f0a0c6da16e6d6f0cc1774520a16d0c0bbf0c2f2ebcbfc10c74bf0b111064"
Hey! i was testing your 3d engine when i got this error. after I looked at the code trying to understand what the error was, I realized that there is no such functions as read_vector_string; read_face_string in the engine code at all, but in your example it was. please correct the error, or correct me if I'm wrong.
--i.o.i.l.
So I figured out what was the problem. the read_vector_string function was outside of the part of the code that needed to be copied. well, okay, I copied the additional part of the code, but the problems did not end. inside the LOGIC OF THE ENGINE, the timer method was called, which was outside the logic of the engine. hmm... I commented out every mention of the timer that caused an error, and now everything works fine. however, that have to be fixed. I would also like a tutorial on setting up light, materials and other graphics settings.
--i.o.i.l.
Hi @ioil13. This may be of help. There are =3= keys to search for code in Pico-8.
CTRL+F = Search in this current TAB.
CTRL+G = Repeat the last search in this current TAB.
CTRL+H = Repeat the last search in ALL tabs.
The last one you may not be aware of as it is not included in the standard Pico-8 HELP file, either included with the system or the main Online help.
Hello @dw817! yes, these hotkeys could be useful in finding the missing code, I'll take note of them. however, I'm still surprised how the library ended up with a piece of code that was completely unrelated to it. plus a very important part of the code, which, on the contrary, is missing from the library. In any case, I'm glad that I managed to fix everything and start using the library. thanks again, cheers.
hello. i don't know if this engine still updates, but i found that changing AX, AY or AZ in load_model function arguments doesn't change anything. its only works when in "model.ay=[angle]" call after model load.
Wonderful library! I am currently trying to implement color values for the faces of the 3D-object. However in the read_face function I dont see any loading of the face colors (which should be assinged to f[4] and f[5]).
function read_face() f={} --verts 1 to 3 for i=1,3 do text=sub(cur_string,cur_string_index,cur_string_index+2) value=read_byte(text) --print(value) f[i]=value cur_string_index+=2 end return f end ``` If I am understanding this correctly, no face color values are included in the compressed string. Because of this I'll add a new data type which contain the face color values as a compressed string. I'll post this in the coming days. I'm also making a fork of your github repo for converting .obj files to strings with support for face color values. |
Currently working on a tool to allow for coloring models in this library. This is just a little preview, I will implement exporting as string soon.
Finished it. The face painter can be found here. Let me know if you have any questions.
[Please log in to post a comment]