├── .gitattributes ├── .github ├── plush.png ├── screenshot1.png ├── screenshot2.png ├── screenshot3.png └── screenshot4.png ├── .gitignore ├── CMakeLists.txt ├── COPYING ├── README.md ├── archive ├── cube_win.zip ├── duckdemo.zip ├── ex01.zip ├── flurry.zip ├── fly-linux.tar.gz ├── fly30src.zip ├── pl_dj.zip ├── pl_vc.zip ├── pl_wc.zip ├── plush-1.1.3-source.zip ├── plush100.zip ├── plush110.zip ├── plush111.zip ├── plush113.zip ├── plush_120.zip ├── plushtst.zip └── tank.zip ├── cmake └── plush.pc.in ├── default.nix ├── examples ├── eggbug.3ds ├── eggbug.c ├── eggbug.pcx ├── ex.h ├── ex1.c ├── ex2.c ├── ex3.c ├── ex4.c ├── fly.c ├── fork.3ds ├── ground.pcx ├── model.c ├── sky.pcx ├── sky2.pcx ├── texture.c ├── texture1.h └── texture1.pcx ├── flake.lock ├── flake.nix ├── include └── plush │ ├── pl_conf.h │ ├── pl_defs.h │ ├── pl_types.h │ └── plush.h └── source ├── cam.c ├── clip.c ├── light.c ├── make.c ├── mat.c ├── math.c ├── obj.c ├── pf_ptex.c ├── pf_solid.c ├── pf_tex.c ├── pf_trans.c ├── plush.c ├── putface.h ├── read_3ds.c ├── read_cob.c ├── read_jaw.c ├── read_pcx.c ├── render.c ├── spline.c ├── text.c └── texture.c /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | 3 | *.pcx filter=lfs diff=lfs merge=lfs -text 4 | *.png filter=lfs diff=lfs merge=lfs -text 5 | *.zip filter=lfs diff=lfs merge=lfs -text 6 | *.3ds filter=lfs diff=lfs merge=lfs -text 7 | -------------------------------------------------------------------------------- /.github/plush.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3547a29ce9781f481740897c6fe1221e867d9a05388332de6ad23d87c6b6af12 3 | size 75624 4 | -------------------------------------------------------------------------------- /.github/screenshot1.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:405f851f2fe83986b8d05df2bfc606f2a776bcf3c992462ebfd0568230446823 3 | size 40615 4 | -------------------------------------------------------------------------------- /.github/screenshot2.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:75e1037cbedcee2b9a26ae656a3b6d6745bc5b2b675f0348bec211a82258d2e0 3 | size 8958 4 | -------------------------------------------------------------------------------- /.github/screenshot3.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d30e0b73d3c9610755d91dd19a6423efb7079f2c093c4bea857352e4a045f3ef 3 | size 115405 4 | -------------------------------------------------------------------------------- /.github/screenshot4.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3842237a12ae4801c46946918c083ce3eebfcf6868042f1615c40adcd7fc41bf 3 | size 106365 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | untracked/ 2 | cmake-build*/ 3 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.28) 2 | project(plush 3 | DESCRIPTION "A neat, portable, realtime 3D rendering library." 4 | HOMEPAGE_URL "https://github.com/erysdren/plush" 5 | LANGUAGES C 6 | VERSION 1.2.0 7 | ) 8 | 9 | # options 10 | 11 | option(PLUSH_BUILD_EXAMPLES "Build Plush Examples" ON) 12 | 13 | # library 14 | 15 | add_library(plush STATIC) 16 | 17 | add_library(plush::plush ALIAS plush) 18 | 19 | target_sources(plush PRIVATE 20 | ${PROJECT_SOURCE_DIR}/source/cam.c 21 | ${PROJECT_SOURCE_DIR}/source/clip.c 22 | ${PROJECT_SOURCE_DIR}/source/light.c 23 | ${PROJECT_SOURCE_DIR}/source/make.c 24 | ${PROJECT_SOURCE_DIR}/source/mat.c 25 | ${PROJECT_SOURCE_DIR}/source/math.c 26 | ${PROJECT_SOURCE_DIR}/source/obj.c 27 | ${PROJECT_SOURCE_DIR}/source/pf_ptex.c 28 | ${PROJECT_SOURCE_DIR}/source/pf_solid.c 29 | ${PROJECT_SOURCE_DIR}/source/pf_tex.c 30 | ${PROJECT_SOURCE_DIR}/source/pf_trans.c 31 | ${PROJECT_SOURCE_DIR}/source/plush.c 32 | ${PROJECT_SOURCE_DIR}/source/read_3ds.c 33 | ${PROJECT_SOURCE_DIR}/source/read_cob.c 34 | ${PROJECT_SOURCE_DIR}/source/read_jaw.c 35 | ${PROJECT_SOURCE_DIR}/source/read_pcx.c 36 | ${PROJECT_SOURCE_DIR}/source/render.c 37 | ${PROJECT_SOURCE_DIR}/source/spline.c 38 | ${PROJECT_SOURCE_DIR}/source/text.c 39 | ${PROJECT_SOURCE_DIR}/source/texture.c 40 | ) 41 | 42 | target_include_directories(plush 43 | PUBLIC 44 | $ 45 | $ 46 | PRIVATE 47 | $ 48 | ) 49 | 50 | find_library(MATH m) 51 | if(MATH) 52 | target_link_libraries(plush PUBLIC ${MATH}) 53 | endif() 54 | 55 | # examples 56 | 57 | if(PLUSH_BUILD_EXAMPLES) 58 | 59 | find_package(SDL2) 60 | 61 | if(SDL2_FOUND) 62 | 63 | # build examples 64 | 65 | foreach(example eggbug ex1 ex2 ex3 ex4 fly model texture) 66 | add_executable(${example} ${PROJECT_SOURCE_DIR}/examples/${example}.c) 67 | target_link_libraries(${example} PUBLIC plush ${SDL2_LIBRARIES}) 68 | target_include_directories(${example} PUBLIC ${SDL2_INCLUDE_DIRS}) 69 | if(CMAKE_C_COMPILER_ID STREQUAL "TinyCC") 70 | target_compile_definitions(${example} PUBLIC SDL_DISABLE_IMMINTRIN_H) 71 | endif() 72 | if(PSP) 73 | create_pbp_file( 74 | TARGET ${example} 75 | ICON_PATH NULL 76 | BACKGROUND_PATH NULL 77 | PREVIEW_PATH NULL 78 | TITLE ${PROJECT_NAME}-${example} 79 | VERSION ${PROJECT_VERSION} 80 | ) 81 | endif() 82 | endforeach() 83 | 84 | # copy texture files 85 | 86 | foreach(file eggbug.3ds eggbug.pcx fork.3ds ground.pcx sky.pcx sky2.pcx texture1.pcx) 87 | configure_file(${PROJECT_SOURCE_DIR}/examples/${file} ${PROJECT_BINARY_DIR}/${file} COPYONLY) 88 | endforeach() 89 | 90 | else() 91 | 92 | message(WARNING "SDL2 not found, cannot build Plush examples") 93 | 94 | endif() 95 | 96 | endif() 97 | 98 | # install 99 | 100 | include(GNUInstallDirs) 101 | include(CMakePackageConfigHelpers) 102 | 103 | configure_file(${PROJECT_SOURCE_DIR}/cmake/plush.pc.in ${PROJECT_BINARY_DIR}/plush.pc @ONLY) 104 | write_basic_package_version_file(${PROJECT_BINARY_DIR}/plush-config-version.cmake COMPATIBILITY AnyNewerVersion) 105 | 106 | install( 107 | FILES ${PROJECT_BINARY_DIR}/plush.pc 108 | DESTINATION lib/pkgconfig 109 | ) 110 | 111 | install( 112 | TARGETS plush 113 | EXPORT plush-targets 114 | INCLUDES DESTINATION include 115 | ) 116 | 117 | install( 118 | EXPORT plush-targets 119 | DESTINATION lib/cmake 120 | NAMESPACE plush:: 121 | FILE plush-config.cmake 122 | ) 123 | 124 | install( 125 | FILES ${PROJECT_BINARY_DIR}/plush-config-version.cmake 126 | DESTINATION lib/cmake 127 | ) 128 | 129 | install( 130 | DIRECTORY 131 | "${PROJECT_SOURCE_DIR}/include/" 132 | TYPE INCLUDE 133 | FILES_MATCHING PATTERN "*.h" 134 | ) 135 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright (C) 1996-1998, Justin Frankel 2 | Copyright (C) 1998-2000, Nullsoft, Inc. 3 | Copyright (C) 2024, erysdren (it/she/they) 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any damages 7 | arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any purpose, 10 | including commercial applications, and to alter it and redistribute it 11 | freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must not 14 | claim that you wrote the original software. If you use this software 15 | in a product, an acknowledgment in the product documentation would be 16 | appreciated but is not required. 17 | 2. Altered source versions must be plainly marked as such, and must not be 18 | misrepresented as being the original software. 19 | 3. This notice may not be removed or altered from any source distribution. 20 | 21 | Justin Frankel 22 | justin@nullsoft.com 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Plush 3D v1.2.0](/.github/plush.png) 2 | 3 | | | | 4 | |---|---| 5 | | ![](.github/screenshot1.png) | ![](.github/screenshot2.png) | 6 | | ![](.github/screenshot3.png) | ![](.github/screenshot4.png) | 7 | 8 | A neat, portable, realtime 3D rendering library originally created between 1996 and 2000 by Justin Frankel and Nullsoft, Inc. 9 | 10 | This version has been updated with some minor modernization tweaks, including the use of `stdint.h` and packaging through CMake and pkg-config. The original examples have also been ported to SDL2. 11 | 12 | Original homepage: [1014.org](http://1014.org/code/nullsoft/plush/) 13 | 14 | ## Todo 15 | 16 | - Add more format loaders 17 | - Allow library user to override what I/O functions it uses (rather than libc) 18 | - Run clang-format on the code 19 | 20 | ## Notes 21 | 22 | - [Eggbug model created by Xenon Fossil](https://xenonfossil.itch.io/low-poly-eggbug) 23 | 24 | ## Features 25 | 26 | - Rasterization: 27 | - 8bpp only 28 | - Z-buffer or painters algorithm 29 | - Solid, Environment, Textured, Perspective Textured, Perspective Environment, Textured Environment, Translucent fills 30 | - None, Flat, Gouraud, Distance lightshading 31 | - Unlimited number of cameras 32 | - Pitch, Pan, and Roll control 33 | - Target tracking 34 | - Unlimited number of point and directional lights, each with own intensity 35 | - Point lights with distance falloff 36 | - Hierarchical Objects 37 | - .3DS Mesh Reader 38 | - .COB Mesh Reader 39 | - .JAW Mesh Reader 40 | - Textures 41 | - PCX texture reader with palette optimization and auto-rescaling 42 | - Perspective Correct modes have piecewise linear approximation every n pixels. 43 | - Spline interpolation with tension, continuity, and bias control 44 | - 4x4 Matrix manipulation library 45 | - Easy to use, cross-platform API 46 | - Architecture that makes it simple to add new rasterizers 47 | 48 | ## Portability 49 | 50 | Plush is designed to be highly portable. It has been tested to work with the 51 | following compilers: 52 | 53 | - gcc 14.2.1 54 | - g++ 14.2.1 55 | - Clang 18.1.8 56 | - TinyCC 0.9.28rc 57 | - cproc #f66a6613 58 | - Open Watcom 1.9 59 | 60 | ## License 61 | 62 | Copyright (C) 1996-1998, Justin Frankel 63 | 64 | Copyright (C) 1998-2000, Nullsoft, Inc. 65 | 66 | Copyright (C) 2024, erysdren (it/she/they) 67 | 68 | This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. 69 | 70 | Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 71 | 72 | 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 73 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 74 | 3. This notice may not be removed or altered from any source distribution. 75 | 76 | Justin Frankel 77 | justin@nullsoft.com 78 | -------------------------------------------------------------------------------- /archive/cube_win.zip: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b8053ffe699c7a80c3116075b0474ff783af4cb5ea5e5ffd1e9b4c14d00ae2dd 3 | size 11398 4 | -------------------------------------------------------------------------------- /archive/duckdemo.zip: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d5863e1ebba3911fe445739ec2d3e91e1dedf0c831a441cbd72b8aa681f165e6 3 | size 10722 4 | -------------------------------------------------------------------------------- /archive/ex01.zip: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:52d2a5b629e70f1102ad2b4403d28b71d242d3830470df8d4c531ee6a4dbbb11 3 | size 14847 4 | -------------------------------------------------------------------------------- /archive/flurry.zip: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:1fb6dd77944a8d2ef88384d55445ba5c7d690e3ddc3787012441807f271f51fa 3 | size 4553 4 | -------------------------------------------------------------------------------- /archive/fly-linux.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erysdren/plush/21484991c17b1cb2a1e97bcb67999d0354af5ae9/archive/fly-linux.tar.gz -------------------------------------------------------------------------------- /archive/fly30src.zip: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:df19d591ceb58754d8eb14069288b8c8fe6ddb93d6efd29bec828444702988c6 3 | size 80566 4 | -------------------------------------------------------------------------------- /archive/pl_dj.zip: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e7f3f8c14b0a1cce07c6ee1b2b62f61631701cb3e617f90a8b53be0a7b791478 3 | size 47796 4 | -------------------------------------------------------------------------------- /archive/pl_vc.zip: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e8f09fa431d9b9e316f59074574f9b22845be31eeccfb93b602f2b941a39a2dd 3 | size 48655 4 | -------------------------------------------------------------------------------- /archive/pl_wc.zip: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:eb11267e4e577deacfe4ec0d73f74b3546b7ba8e0911fd5feb948a650e3a53a1 3 | size 47376 4 | -------------------------------------------------------------------------------- /archive/plush-1.1.3-source.zip: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:970c69d1eb27de26cb91d0502152a839a1e2394861fdd5174fd1096c05faf54e 3 | size 54345 4 | -------------------------------------------------------------------------------- /archive/plush100.zip: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ca81004c8f5e22429130af80d08e54d4398369bb2ae0e7118783beb3a4cea238 3 | size 43694 4 | -------------------------------------------------------------------------------- /archive/plush110.zip: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:80085faecfc9aeba59b35da82e0a863da885f34315b11f5ae7a742d0a3d2ab31 3 | size 53793 4 | -------------------------------------------------------------------------------- /archive/plush111.zip: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e80ab6a6588d46c02f4556eed15c24f55d3c0572b8a8ebf02898738b95abe232 3 | size 44549 4 | -------------------------------------------------------------------------------- /archive/plush113.zip: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:c26805a173d29e83716fee25a193255e8007ea61f08e82087399bcf0230c9556 3 | size 46441 4 | -------------------------------------------------------------------------------- /archive/plush_120.zip: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:89bd3abdbda6c142d28c85a9765f28399983094436b61113467f8988d2f25952 3 | size 45266 4 | -------------------------------------------------------------------------------- /archive/plushtst.zip: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9b4f3cffc813c87ed02b6742dc9ed208c63b12c716697d5f6cf07920433f65e0 3 | size 85334 4 | -------------------------------------------------------------------------------- /archive/tank.zip: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b26face4820c641cb61e6f10ea53d0639c9451b992d9808a1085fcf37b741fb0 3 | size 82768 4 | -------------------------------------------------------------------------------- /cmake/plush.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@CMAKE_INSTALL_PREFIX@ 2 | includedir=@CMAKE_INSTALL_FULL_LIBDIR@ 3 | libdir=@CMAKE_INSTALL_FULL_LIBDIR@ 4 | 5 | Name: @PROJECT_NAME@ 6 | Description: @PROJECT_DESCRIPTION@ 7 | URL: @PROJECT_HOMEPAGE_URL@ 8 | Version: @PROJECT_VERSION@ 9 | Cflags: -I${includedir} 10 | Libs: -L${libdir} -l@PROJECT_NAME@ 11 | -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | { stdenv 2 | , cmake 3 | , SDL2 4 | , version 5 | }: 6 | 7 | stdenv.mkDerivation(finalAttrs: { 8 | inherit version; 9 | 10 | pname = "plush"; 11 | 12 | src = ./.; 13 | 14 | nativeBuildInputs = [ 15 | cmake 16 | ]; 17 | 18 | buildInputs = [ 19 | SDL2 20 | ]; 21 | }) 22 | -------------------------------------------------------------------------------- /examples/eggbug.3ds: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:6ad3cfb124b2cfe2b6924aa1eadcf4c401205039de7dd86767ab4fcab06a14ba 3 | size 23045 4 | -------------------------------------------------------------------------------- /examples/eggbug.c: -------------------------------------------------------------------------------- 1 | // model.c: eggbug model example 2 | // <3 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include "ex.h" 12 | 13 | pl_Obj *model; 14 | pl_Mat *material; 15 | pl_Cam *camera; 16 | uint8_t framebuffer[W * H]; 17 | pl_ZBuffer zbuffer[W * H]; 18 | uint8_t palette[768]; 19 | 20 | #define NUM_EGGBUGS (32) 21 | struct { 22 | pl_Float speed; 23 | pl_Obj *model; 24 | } eggbugs[NUM_EGGBUGS]; 25 | 26 | static int rangerandom(int min, int max) 27 | { 28 | return rand() % (max + 1 - min) + min; 29 | } 30 | 31 | int main(int argc, char **argv) 32 | { 33 | int now, then; 34 | float dt; 35 | int i; 36 | 37 | /* setup graphics mode */ 38 | exSetGraphics(); 39 | 40 | /* create material */ 41 | material = plMatCreate(); 42 | material->ShadeType = PL_SHADE_FLAT; 43 | material->NumGradients = 1500; 44 | material->Texture = plReadPCXTex("eggbug.pcx", 1, 1); 45 | material->Diffuse[0] = material->Diffuse[1] = material->Diffuse[2] = 0; 46 | material->TexScaling = 1; 47 | material->Shininess = 0; 48 | plMatInit(material); 49 | 50 | /* create palette */ 51 | plMatMakeOptPal(palette, 1, 255, &material, 1); 52 | palette[0] = 32; 53 | palette[1] = 32; 54 | palette[2] = 32; 55 | plMatMapToPal(material, palette, 0, 255); 56 | 57 | exSetPalette(palette); 58 | 59 | /* create camera */ 60 | camera = plCamCreate(W, H, W * 3.0 / (H * 4.0), 90.0, framebuffer, zbuffer); 61 | camera->Pitch = -45; 62 | camera->Pan = 45; 63 | camera->X = 256; 64 | camera->Y = 384; 65 | camera->Z = -256; 66 | 67 | /* seed random timer */ 68 | srand(time(NULL)); 69 | 70 | /* setup eggbugs */ 71 | for (i = 0; i < NUM_EGGBUGS; i++) 72 | { 73 | eggbugs[i].model = plRead3DSObj("eggbug.3ds", material); 74 | eggbugs[i].model->Xa = 90; 75 | eggbugs[i].model->Ya = -90; 76 | eggbugs[i].model->Xp = rangerandom(-256, 256); 77 | eggbugs[i].model->Yp = rangerandom(-256, 256); 78 | eggbugs[i].model->Zp = rangerandom(-256, 256) + 512; 79 | eggbugs[i].speed = rangerandom(16, 64); 80 | } 81 | 82 | /* main loop */ 83 | then = exClock(); 84 | while (!exGetKey()) 85 | { 86 | now = exClock(); 87 | dt = (float)(now - then) / (float)exClockPerSecond(); 88 | then = now; 89 | 90 | /* move eggbugs */ 91 | for (i = 0; i < NUM_EGGBUGS; i++) 92 | { 93 | eggbugs[i].model->Zp -= eggbugs[i].speed * dt; 94 | 95 | /* reset if needed */ 96 | if (eggbugs[i].model->Zp < -512) 97 | { 98 | eggbugs[i].model->Xp = rangerandom(-256, 256); 99 | eggbugs[i].model->Yp = rangerandom(-256, 256); 100 | eggbugs[i].model->Zp = rangerandom(-256, 256) + 512; 101 | eggbugs[i].speed = rangerandom(32, 128); 102 | } 103 | } 104 | 105 | /* clear back buffer */ 106 | memset(zbuffer, 0, sizeof(zbuffer)); 107 | memset(framebuffer, 0, sizeof(framebuffer)); 108 | 109 | /* render frame */ 110 | plRenderBegin(camera); 111 | 112 | /* render eggbugs */ 113 | for (i = 0; i < NUM_EGGBUGS; i++) 114 | plRenderObj(eggbugs[i].model); 115 | 116 | plRenderEnd(); 117 | 118 | /* wait for vsync, then copy to screen */ 119 | exWaitVSync(); 120 | memcpy(exGraphMem, framebuffer, sizeof(framebuffer)); 121 | } 122 | 123 | /* clean up */ 124 | for (i = 0; i < NUM_EGGBUGS; i++) 125 | plObjDelete(eggbugs[i].model); 126 | plCamDelete(camera); 127 | plMatDelete(material); 128 | 129 | /* shut down video */ 130 | exSetText(); 131 | 132 | return 0; 133 | } 134 | -------------------------------------------------------------------------------- /examples/eggbug.pcx: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e1564461e0fed95a546f9611478cb6c7f51d0c1b3877da34f7206394e2a74214 3 | size 2403 4 | -------------------------------------------------------------------------------- /examples/ex.h: -------------------------------------------------------------------------------- 1 | // ex.h: provides a standard interface for video and keyboard for the 2 | // example programs to use. 3 | 4 | #include "SDL.h" 5 | 6 | #ifdef __PSP__ 7 | #define W (480) 8 | #define H (272) 9 | #else 10 | #define W (640) 11 | #define H (480) 12 | #endif 13 | 14 | static uint8_t *exGraphMem = NULL; 15 | static SDL_Window *exWindow = NULL; 16 | static SDL_Renderer *exRenderer = NULL; 17 | static SDL_Texture *exTexture = NULL; 18 | static SDL_Surface *exWindowSurface = NULL; 19 | static SDL_Surface *exSurface = NULL; 20 | static int exMouseButtons = 0; 21 | static int exMouseX = 0; 22 | static int exMouseY = 0; 23 | static int exMouseDeltaX = 0; 24 | static int exMouseDeltaY = 0; 25 | 26 | static int exClockPerSecond(void) 27 | { 28 | return 1000; 29 | } 30 | 31 | static int exClock(void) 32 | { 33 | return (int)SDL_GetTicks(); 34 | } 35 | 36 | static int exGetKey(void) 37 | { 38 | SDL_Event event; 39 | int lastkey = 0; 40 | 41 | exMouseDeltaX = exMouseDeltaY = 0; 42 | 43 | while (SDL_PollEvent(&event)) 44 | { 45 | switch (event.type) 46 | { 47 | case SDL_QUIT: 48 | exit(0); 49 | 50 | case SDL_MOUSEBUTTONDOWN: 51 | if (event.button.button == SDL_BUTTON_LEFT) 52 | exMouseButtons |= 1; 53 | if (event.button.button == SDL_BUTTON_RIGHT) 54 | exMouseButtons |= 2; 55 | break; 56 | 57 | case SDL_MOUSEBUTTONUP: 58 | if (event.button.button == SDL_BUTTON_LEFT) 59 | exMouseButtons &= ~1; 60 | if (event.button.button == SDL_BUTTON_RIGHT) 61 | exMouseButtons &= ~2; 62 | break; 63 | 64 | case SDL_MOUSEMOTION: 65 | exMouseX = event.motion.x; 66 | exMouseY = event.motion.y; 67 | exMouseDeltaX = event.motion.xrel; 68 | exMouseDeltaY = event.motion.yrel; 69 | break; 70 | 71 | case SDL_KEYDOWN: 72 | lastkey = event.key.keysym.sym; 73 | break; 74 | } 75 | } 76 | 77 | return lastkey; 78 | } 79 | 80 | static void exWaitVSync(void) 81 | { 82 | void *pixels; 83 | int pitch; 84 | 85 | if (SDL_LockTexture(exTexture, NULL, &pixels, &pitch) == 0) 86 | { 87 | SDL_BlitSurface(exSurface, NULL, exWindowSurface, NULL); 88 | SDL_memcpy(pixels, exWindowSurface->pixels, exWindowSurface->pitch * exWindowSurface->h); 89 | SDL_UnlockTexture(exTexture); 90 | } 91 | 92 | SDL_RenderClear(exRenderer); 93 | SDL_RenderCopy(exRenderer, exTexture, NULL, NULL); 94 | SDL_RenderPresent(exRenderer); 95 | } 96 | 97 | static void exSetPalette(uint8_t palette[768]) 98 | { 99 | int i; 100 | SDL_Color colors[256]; 101 | 102 | for (i = 0; i < 256; i++) 103 | { 104 | colors[i].r = palette[i * 3]; 105 | colors[i].g = palette[i * 3 + 1]; 106 | colors[i].b = palette[i * 3 + 2]; 107 | colors[i].a = 255; 108 | } 109 | 110 | SDL_SetPaletteColors(exSurface->format->palette, colors, 0, 256); 111 | } 112 | 113 | static void exSetGraphics(void) 114 | { 115 | Uint32 format; 116 | 117 | SDL_Init(SDL_INIT_VIDEO); 118 | 119 | exWindow = SDL_CreateWindow("Plush Example", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, W, H, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE); 120 | 121 | exRenderer = SDL_CreateRenderer(exWindow, -1, SDL_RENDERER_PRESENTVSYNC); 122 | 123 | SDL_RenderSetLogicalSize(exRenderer, W, H); 124 | 125 | format = SDL_GetWindowPixelFormat(exWindow); 126 | 127 | exTexture = SDL_CreateTexture(exRenderer, format, SDL_TEXTUREACCESS_STREAMING, W, H); 128 | 129 | exWindowSurface = SDL_CreateRGBSurfaceWithFormat(0, W, H, 0, format); 130 | 131 | exSurface = SDL_CreateRGBSurfaceWithFormat(0, W, H, 0, SDL_PIXELFORMAT_INDEX8); 132 | 133 | exGraphMem = (uint8_t *)exSurface->pixels; 134 | } 135 | 136 | static void exSetText(void) 137 | { 138 | SDL_FreeSurface(exWindowSurface); 139 | SDL_FreeSurface(exSurface); 140 | SDL_DestroyTexture(exTexture); 141 | SDL_DestroyRenderer(exRenderer); 142 | SDL_DestroyWindow(exWindow); 143 | SDL_Quit(); 144 | } 145 | -------------------------------------------------------------------------------- /examples/ex1.c: -------------------------------------------------------------------------------- 1 | // Ex1.c: simple Plush example 2 | // Rotates a flat shaded cube 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | // Include the plush header file 10 | #include 11 | 12 | // Include our example graphics interface module 13 | #include "ex.h" 14 | 15 | // Our variables 16 | pl_Light *TheLight; // Our light 17 | pl_Obj *TheCube; // Our cube object 18 | pl_Mat *CubeMat; // The material for the cube 19 | pl_Mat *AllMaterials[2]; // Used for creating palette 20 | pl_Cam *TheCamera; // Our camera 21 | pl_uChar TheFrameBuffer[W*H]; // Our framebuffer to render to 22 | pl_uChar ThePalette[768]; 23 | 24 | int main(int argc, char **argv) { // Main 25 | int i; 26 | #if defined(DJGPP) || defined(__WATCOMC__) 27 | // Put the fpu in a low precision, no exception state 28 | _control87(MCW_EM|PC_24,MCW_EM|MCW_PC); 29 | #endif 30 | 31 | exSetGraphics(); // Set graphics 32 | 33 | CubeMat = plMatCreate(); // Create the material for the cube 34 | CubeMat->NumGradients = 100; // Have it use 100 colors 35 | CubeMat->ShadeType = PL_SHADE_FLAT; // Make the cube flat shaded 36 | plMatInit(CubeMat); // Initialize the material 37 | 38 | AllMaterials[0] = CubeMat; // Make list of materials 39 | AllMaterials[1] = 0; // Null terminate list of materials 40 | plMatMakeOptPal(ThePalette,1,255,AllMaterials,1); // Create a nice palette 41 | 42 | ThePalette[0] = ThePalette[1] = ThePalette[2] = 0; // Color 0 is black 43 | 44 | plMatMapToPal(CubeMat,ThePalette,0,255); // Map the material to our palette 45 | 46 | // Convert std 8 bit/chan palette to vga's 6 bit/chan palette 47 | // for (i = 0; i < 768; i ++) ThePalette[i] >>= 2; 48 | exSetPalette(ThePalette); // Set the palette 49 | 50 | TheCube = plMakeBox(100.0,100.0,100.0,CubeMat); // Create the cube 51 | 52 | TheCamera = plCamCreate(W, // Screen width 53 | H, // Screen height 54 | W*3.0/(H*4.0), // Aspect ratio 55 | 90.0, // Field of view 56 | TheFrameBuffer, // Framebuffer 57 | NULL // ZBuffer (none) 58 | ); // Create the camera 59 | TheCamera->Z = -300; // Back the camera up from the origin 60 | 61 | TheLight = plLightSet(plLightCreate(), // Create a light to be set up 62 | PL_LIGHT_VECTOR, // vector light 63 | 0.0,0.0,0.0, // rotation angles 64 | 1.0, // intensity 65 | 1.0); // falloff, not used for vector lights 66 | 67 | while (!exGetKey()) { // While the keyboard hasn't been touched 68 | TheCube->Xa += 1.0; // Rotate by 1 degree on each axis 69 | TheCube->Ya += 1.0; 70 | TheCube->Za += 1.0; 71 | memset(TheFrameBuffer,0,W*H); // clear framebuffer for next frame 72 | plRenderBegin(TheCamera); // Start rendering with the camera 73 | plRenderLight(TheLight); // Render our light 74 | plRenderObj(TheCube); // Render our object 75 | plRenderEnd(); // Finish rendering 76 | exWaitVSync(); // Sync with retrace 77 | memcpy(exGraphMem,TheFrameBuffer,W*H); // dump to screen 78 | } 79 | exSetText(); // Restore text mode 80 | return 0; // Quit 81 | } 82 | -------------------------------------------------------------------------------- /examples/ex2.c: -------------------------------------------------------------------------------- 1 | // Ex2.c: simple Plush example 2 | // Rotates a flat shaded cube 3 | // The cube is now a different colored cube then ex1.c 4 | // ZBuffering has been added, as well as dynamic framebuffer allocation 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | // Include the plush header file 12 | #include 13 | 14 | // Include our example graphics interface module 15 | #include "ex.h" 16 | 17 | // Our variables 18 | pl_Light *TheLight; // Our light 19 | pl_Obj *TheCube; // Our cube object 20 | pl_Mat *CubeMat; // The material for the cube 21 | pl_Mat *AllMaterials[2]; // Used for creating palette 22 | pl_Cam *TheCamera; // Our camera 23 | pl_uChar *TheFrameBuffer; // Our framebuffer to render to 24 | pl_ZBuffer *TheZBuffer; // Our zbuffer 25 | pl_uChar ThePalette[768]; 26 | 27 | int main(int argc, char **argv) { // Main 28 | int i; 29 | #if defined(DJGPP) || defined(__WATCOMC__) 30 | // Put the fpu in a low precision, no exception state 31 | _control87(MCW_EM|PC_24,MCW_EM|MCW_PC); 32 | #endif 33 | exSetGraphics(); // Set graphics 34 | 35 | TheFrameBuffer = (pl_uChar *) malloc(W*H); // Alloc framebuffer 36 | if (!TheFrameBuffer) { 37 | exSetText(); 38 | printf("Out of memory!\n"); 39 | exit(1); 40 | } 41 | // Alloc z-buffer 42 | TheZBuffer = (pl_ZBuffer *) malloc(W*H*sizeof(pl_ZBuffer)); 43 | 44 | CubeMat = plMatCreate(); // Create the material for the cube 45 | CubeMat->NumGradients = 100; // Have it use 100 colors 46 | CubeMat->ShadeType = PL_SHADE_FLAT; // Make the cube flat shaded 47 | 48 | CubeMat->Ambient[0] = 32; // Set red ambient component 49 | CubeMat->Ambient[1] = 0; // Set green ambient component 50 | CubeMat->Ambient[2] = 16; // Set blue ambient component 51 | 52 | CubeMat->Diffuse[0] = 200; // Set red diffuse component 53 | CubeMat->Diffuse[1] = 100; // Set green diffuse component 54 | CubeMat->Diffuse[2] = 150; // Set blue diffuse component 55 | 56 | plMatInit(CubeMat); // Initialize the material 57 | 58 | AllMaterials[0] = CubeMat; // Make list of materials 59 | AllMaterials[1] = 0; // Null terminate list of materials 60 | plMatMakeOptPal(ThePalette,1,255,AllMaterials,1); // Create a nice palette 61 | 62 | ThePalette[0] = ThePalette[1] = ThePalette[2] = 0; // Color 0 is black 63 | 64 | plMatMapToPal(CubeMat,ThePalette,0,255); // Map the material to our palette 65 | 66 | // Convert std 8 bit/chan palette to vga's 6 bit/chan palette 67 | // for (i = 0; i < 768; i ++) ThePalette[i] >>= 2; 68 | exSetPalette(ThePalette); // Set the palette 69 | 70 | TheCube = plMakeBox(100.0,100.0,100.0,CubeMat); // Create the cube 71 | 72 | TheCamera = plCamCreate(W, // Screen width 73 | H, // Screen height 74 | W*3.0/(H*4.0), // Aspect ratio 75 | 90.0, // Field of view 76 | TheFrameBuffer, // Framebuffer 77 | TheZBuffer // ZBuffer 78 | ); // Create the camera 79 | TheCamera->Z = -300; // Back the camera up from the origin 80 | TheCamera->Sort = 0; // We don't need to sort since zbuffering takes care 81 | // of it for us! 82 | 83 | TheLight = plLightSet(plLightCreate(), // Create a light to be set up 84 | PL_LIGHT_VECTOR, // vector light 85 | 0.0,0.0,0.0, // rotation angles 86 | 1.0, // intensity 87 | 1.0); // falloff, not used for vector lights 88 | 89 | while (!exGetKey()) { // While the keyboard hasn't been touched 90 | TheCube->Xa += 1.0; // Rotate by 1 degree on each axis 91 | TheCube->Ya += 1.0; 92 | TheCube->Za += 1.0; 93 | 94 | // clear zbuffer for next frame 95 | memset(TheZBuffer,0,W*H*sizeof(pl_ZBuffer)); 96 | memset(TheFrameBuffer,0,W*H); // clear framebuffer for next frame 97 | plRenderBegin(TheCamera); // Start rendering with the camera 98 | plRenderLight(TheLight); // Render our light 99 | plRenderObj(TheCube); // Render our object 100 | plRenderEnd(); // Finish rendering 101 | exWaitVSync(); // Sync with retrace 102 | memcpy(exGraphMem,TheFrameBuffer,W*H); // dump to screen 103 | } 104 | exSetText(); // Restore text mode 105 | return 0; // Quit 106 | } 107 | -------------------------------------------------------------------------------- /examples/ex3.c: -------------------------------------------------------------------------------- 1 | // Ex3.c: simple Plush example 2 | // Rotates a flat shaded cube AND a gouraud torus 3 | // Uses z-buffering for smooth intersections 4 | // Also rotates the lightsource around 5 | // Added from ex2: frees up memory at the end (good to do :) 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | // Include the plush header file 13 | #include 14 | 15 | // Include our example graphics interface module 16 | #include "ex.h" 17 | 18 | // Our variables 19 | pl_Light *TheLight; // Our light 20 | pl_Float TheLight_Xa, TheLight_Ya, TheLight_Za; 21 | // The rotation angles of our light 22 | pl_Obj *TheCube; // Our cube object 23 | pl_Obj *TheTorus; // Our torus object 24 | pl_Mat *CubeMat; // The material for the cube 25 | pl_Mat *TorusMat; // The material for the torus 26 | pl_Mat *AllMaterials[3]; // Used for creating palette 27 | pl_Cam *TheCamera; // Our camera 28 | pl_uChar *TheFrameBuffer; // Our framebuffer to render to 29 | pl_ZBuffer *TheZBuffer; // Our zbuffer 30 | pl_uChar ThePalette[768]; 31 | 32 | int main(int argc, char **argv) { // Main 33 | int i; 34 | #if defined(DJGPP) || defined(__WATCOMC__) 35 | // Put the fpu in a low precision, no exception state 36 | _control87(MCW_EM|PC_24,MCW_EM|MCW_PC); 37 | #endif 38 | exSetGraphics(); // Set graphics 39 | 40 | TheFrameBuffer = (pl_uChar *) malloc(W*H); // Alloc framebuffer 41 | if (!TheFrameBuffer) { 42 | exSetText(); 43 | printf("Out of memory!\n"); 44 | exit(1); 45 | } 46 | // Alloc z-buffer 47 | TheZBuffer = (pl_ZBuffer *) malloc(W*H*sizeof(pl_ZBuffer)); 48 | 49 | CubeMat = plMatCreate(); // Create the material for the cube 50 | CubeMat->NumGradients = 100; // Have it use 100 colors 51 | CubeMat->ShadeType = PL_SHADE_FLAT; // Make the cube flat shaded 52 | 53 | CubeMat->Ambient[0] = 32; // Set red ambient component 54 | CubeMat->Ambient[1] = 0; // Set green ambient component 55 | CubeMat->Ambient[2] = 16; // Set blue ambient component 56 | 57 | CubeMat->Diffuse[0] = 200; // Set red diffuse component 58 | CubeMat->Diffuse[1] = 100; // Set green diffuse component 59 | CubeMat->Diffuse[2] = 150; // Set blue diffuse component 60 | 61 | plMatInit(CubeMat); // Initialize the material 62 | 63 | TorusMat = plMatCreate(); // Create the material for the torus 64 | TorusMat->NumGradients = 100; // Have it use 100 colors 65 | TorusMat->ShadeType = PL_SHADE_GOURAUD; // Make the torus gouraud shaded 66 | TorusMat->Shininess = 10; // Make the torus a bit more shiny 67 | 68 | TorusMat->Ambient[0] = 0; // Set red ambient component 69 | TorusMat->Ambient[1] = 12; // Set green ambient component 70 | TorusMat->Ambient[2] = 4; // Set blue ambient component 71 | 72 | TorusMat->Diffuse[0] = 20; // Set red diffuse component 73 | TorusMat->Diffuse[1] = 60; // Set green diffuse component 74 | TorusMat->Diffuse[2] = 70; // Set blue diffuse component 75 | 76 | TorusMat->Specular[0] = 100; // Set red specular component 77 | TorusMat->Specular[1] = 200; // Set green specular component 78 | TorusMat->Specular[2] = 150; // Set blue specular component 79 | 80 | AllMaterials[0] = CubeMat; // Make list of materials 81 | AllMaterials[1] = TorusMat; // Make list of materials 82 | AllMaterials[2] = 0; // Null terminate list of materials 83 | plMatMakeOptPal(ThePalette,1,255,AllMaterials,2); // Create a nice palette 84 | 85 | ThePalette[0] = ThePalette[1] = ThePalette[2] = 0; // Color 0 is black 86 | 87 | plMatMapToPal(CubeMat,ThePalette,0,255); // Map the material to our palette 88 | plMatMapToPal(TorusMat,ThePalette,0,255); // Map the material to our palette 89 | 90 | // Convert std 8 bit/chan palette to vga's 6 bit/chan palette 91 | // for (i = 0; i < 768; i ++) ThePalette[i] >>= 2; 92 | exSetPalette(ThePalette); // Set the palette 93 | 94 | TheCube = plMakeBox(100.0,100.0,100.0,CubeMat); // Create the cube 95 | TheTorus = plMakeTorus(40.0,100.0,10,8,TorusMat); // Create the torus 96 | 97 | TheTorus->Xp = -70.0; // Shift the torus to the left a bit 98 | 99 | TheCamera = plCamCreate(W, // Screen width 100 | H, // Screen height 101 | W*3.0/(H*4.0), // Aspect ratio 102 | 90.0, // Field of view 103 | TheFrameBuffer, // Framebuffer 104 | TheZBuffer // ZBuffer 105 | ); // Create the camera 106 | TheCamera->Z = -300; // Back the camera up from the origin 107 | TheCamera->Sort = 0; // We don't need to sort since zbuffering takes care 108 | // of it for us! 109 | 110 | TheLight = plLightCreate(); // Create the light. Will be set up every frame 111 | 112 | while (!exGetKey()) { // While the keyboard hasn't been touched 113 | TheCube->Xa += 1.0; // Rotate cube by 1 degree on each axis 114 | TheCube->Ya += 1.0; 115 | TheCube->Za += 1.0; 116 | 117 | TheTorus->Xa += 1.9; // Rotate the torus 118 | TheTorus->Ya -= 1.0; 119 | TheTorus->Za += 0.3; 120 | 121 | TheLight_Za += 1.0; // Rotate the light 122 | TheLight_Xa = 50.0; 123 | 124 | plLightSet(TheLight, PL_LIGHT_VECTOR, // Set the newly rotated light 125 | TheLight_Xa, TheLight_Ya, TheLight_Za, // angles 126 | 1.0, // intensity 127 | 1.0); // falloff, not used for vector lights 128 | 129 | // clear zbuffer for next frame 130 | memset(TheZBuffer,0,W*H*sizeof(pl_ZBuffer)); 131 | memset(TheFrameBuffer,0,W*H); // clear framebuffer for next frame 132 | plRenderBegin(TheCamera); // Start rendering with the camera 133 | plRenderLight(TheLight); // Render our light 134 | plRenderObj(TheCube); // Render our cube 135 | plRenderObj(TheTorus); // Render our torus 136 | plRenderEnd(); // Finish rendering 137 | exWaitVSync(); // Sync with retrace 138 | memcpy(exGraphMem,TheFrameBuffer,W*H); // dump to screen 139 | } 140 | free(TheFrameBuffer); // Free up memory 141 | free(TheZBuffer); 142 | plCamDelete(TheCamera); 143 | plLightDelete(TheLight); 144 | plObjDelete(TheCube); 145 | plObjDelete(TheTorus); 146 | plMatDelete(CubeMat); 147 | plMatDelete(TorusMat); 148 | exSetText(); // Restore text mode 149 | return 0; // Quit 150 | } 151 | -------------------------------------------------------------------------------- /examples/ex4.c: -------------------------------------------------------------------------------- 1 | // Ex4.c: simple Plush example 2 | // Rotates a flat shaded texture mapped cube 3 | // Reads texture from texture1.pcx 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | // Include the plush header file 11 | #include 12 | 13 | // Include our example graphics interface module 14 | #include "ex.h" 15 | 16 | // Our variables 17 | pl_Light *TheLight; // Our light 18 | pl_Obj *TheCube; // Our cube object 19 | pl_Mat *CubeMat; // The material for the cube 20 | pl_Mat *AllMaterials[2]; // Used for creating palette 21 | pl_Cam *TheCamera; // Our camera 22 | pl_uChar TheFrameBuffer[W*H]; // Our framebuffer to render to 23 | pl_uChar ThePalette[768]; 24 | 25 | int main(int argc, char **argv) { // Main 26 | int i, done; 27 | // Show user controls 28 | printf("Controls:\n" 29 | " SPACE: toggle perspective correction\n" 30 | " ESC: quit\n" 31 | " Hit any key to begin\n"); 32 | #if 0 33 | while (!exGetKey()); // Wait for key 34 | while (exGetKey()); // Make sure no other keys are in the queue 35 | #endif 36 | 37 | #if defined(DJGPP) || defined(__WATCOMC__) 38 | // Put the fpu in a low precision, no exception state 39 | _control87(MCW_EM|PC_24,MCW_EM|MCW_PC); 40 | #endif 41 | exSetGraphics(); // Set graphics 42 | 43 | CubeMat = plMatCreate(); // Create the material for the cube 44 | CubeMat->NumGradients = 256; // Have it use 256 colors 45 | CubeMat->ShadeType = PL_SHADE_FLAT; // Make the cube flat shaded 46 | CubeMat->Texture = plReadPCXTex("texture1.pcx", 47 | 1, // Rescale the texture if necessary 48 | 1 // Tell it to optimize the texture's palette 49 | ); 50 | CubeMat->PerspectiveCorrect = 0; // No correction by default 51 | // These are 128 by default, but make it to bright for this app 52 | CubeMat->Diffuse[0] = CubeMat->Diffuse[1] = CubeMat->Diffuse[2] = 0; 53 | plMatInit(CubeMat); // Initialize the material 54 | 55 | AllMaterials[0] = CubeMat; // Make list of materials 56 | AllMaterials[1] = 0; // Null terminate list of materials 57 | plMatMakeOptPal(ThePalette,1,255,AllMaterials,1); // Create a nice palette 58 | 59 | ThePalette[0] = ThePalette[1] = ThePalette[2] = 0; // Color 0 is black 60 | 61 | plMatMapToPal(CubeMat,ThePalette,0,255); // Map the material to our palette 62 | 63 | // Convert std 8 bit/chan palette to vga's 6 bit/chan palette 64 | // for (i = 0; i < 768; i ++) ThePalette[i] >>= 2; 65 | exSetPalette(ThePalette); // Set the palette 66 | 67 | TheCube = plMakeBox(100.0,100.0,100.0,CubeMat); // Create the cube 68 | 69 | TheCamera = plCamCreate(W, // Screen width 70 | H, // Screen height 71 | W*3.0/(H*4.0), // Aspect ratio 72 | 60.0, // Field of view 73 | TheFrameBuffer, // Framebuffer 74 | NULL // ZBuffer (none) 75 | ); // Create the camera 76 | TheCamera->Z = -300; // Back the camera up from the origin 77 | 78 | TheLight = plLightSet(plLightCreate(), // Create a light to be set up 79 | PL_LIGHT_VECTOR, // vector light 80 | 0.0,0.0,0.0, // rotation angles 81 | 1.0, // intensity 82 | 1.0); // falloff, not used for vector lights 83 | 84 | done = 0; 85 | while (!done) { // While the keyboard hasn't been touched 86 | TheCube->Xa += 1.0; // Rotate by 1 degree on each axis 87 | TheCube->Ya += 1.0; 88 | TheCube->Za += 1.0; 89 | memset(TheFrameBuffer,0,W*H); // clear framebuffer for next frame 90 | plRenderBegin(TheCamera); // Start rendering with the camera 91 | plRenderLight(TheLight); // Render our light 92 | plRenderObj(TheCube); // Render our object 93 | plRenderEnd(); // Finish rendering 94 | exWaitVSync(); // Sync with retrace 95 | memcpy(exGraphMem,TheFrameBuffer,W*H); // dump to screen 96 | switch (exGetKey()) { 97 | case 0: break; // no key 98 | case 27: done = 1; break; // esc 99 | case ' ': // space 100 | CubeMat->PerspectiveCorrect ^= 8; // Toggle whether or not it's 8 101 | plMatInit(CubeMat); 102 | break; 103 | } 104 | } 105 | exSetText(); // Restore text mode 106 | return 0; // Quit 107 | } 108 | -------------------------------------------------------------------------------- /examples/fly.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include "ex.h" 9 | 10 | /* Physical size of land */ 11 | #define LAND_SIZE 65000 12 | /* Number of divisions of the land. Higher number == more polygons */ 13 | #define LAND_DIV 32 14 | 15 | /* Mouse interface functions */ 16 | // mouse sensitivity 17 | float mouse_sens = 2048.0/32768.0; 18 | 19 | /* Misc functions */ 20 | // Sets up the materials 21 | void setup_materials(pl_Mat **mat, pl_uChar *pal); 22 | // Sets up the landscape and skies 23 | pl_Obj *setup_landscape(pl_Mat *m, pl_Mat *sm, pl_Mat *sm2); 24 | 25 | /* Main!!! */ 26 | int main(int argc, char **argv) { 27 | char lastmessage[80] = "Fly 3.0"; // last message used for status line 28 | int draw_sky = 1; // do we draw the sky? 29 | int wait_vsync = 1; // do we wait for vsync? 30 | int frames, t; // for framerate counter 31 | int i; 32 | int c; 33 | 34 | pl_uChar *framebuffer; // our doublebuffer 35 | pl_Mat *mat[3+1]; // our materials, we have 1 extra for null 36 | // termination for plMatMakeOptPal2() 37 | pl_Cam *cam; // our camera 38 | pl_Obj *land; // the land object 39 | pl_Obj *sky, *sky2; // the two skies 40 | int done = 0; 41 | 42 | pl_uChar pal[768]; // our palette 43 | 44 | srand(0); // initialize rng 45 | 46 | printf("Plush 3D Fly v3.0.\n" 47 | " %s\n" 48 | " %s\n",plVersionString,plCopyrightString); 49 | // print out startup info 50 | 51 | printf("\n\nControls:\n" 52 | " Mouse: rotate\n" 53 | " Mouse buttons: left=move forward, right=move forward fast\n" 54 | " s: toggle sky (default on)\n" 55 | " -,+: adjust fov (default 90)\n" 56 | " [,]: adjust mouse sensitivity\n" 57 | " v: toggle vsync (default off)\n\n"); 58 | 59 | exSetGraphics(); // intialize graphics 60 | framebuffer = (pl_uChar *) malloc(W*H); // allocate framebuffer 61 | // create camera 62 | cam = plCamCreate(W, // width 63 | H, // height 64 | W/H*3.0/4.0, // aspect ratio 65 | 90.0, // fov 66 | framebuffer, // framebuffer (our doublebuffer) 67 | 0); // zbuffer (not used) 68 | cam->Y = 800; // move the camera up from the ground 69 | 70 | setup_materials(mat,pal); // intialize materials and palette 71 | 72 | land = setup_landscape(mat[0],mat[1],mat[2]); // create landscape 73 | sky = land->Children[0]; // unhierarchicalize the sky from the land 74 | land->Children[0] = 0; 75 | sky2 = land->Children[1]; 76 | land->Children[1] = 0; 77 | 78 | frames = 0; // set up for framerate counter 79 | t = exClock(); 80 | while (!done) { // main loop 81 | // save time when the frame began, to be used later. 82 | float prevtime = exClock() / (float) exClockPerSecond(); 83 | frames++; // update for framerate counter 84 | 85 | memset(framebuffer,1,W*H); // clear our doublebuffer 86 | 87 | // lots of rendering special casing 88 | if (draw_sky) { // if we're drawing the sky 89 | if (cam->Y > 2000) { // if above the sky, only render the skies, with 90 | // no far clip plane 91 | cam->ClipBack = 0.0; 92 | plRenderBegin(cam); 93 | plRenderObj(sky); 94 | plRenderObj(sky2); 95 | } else { // otherwise, render the sky (but not the second sky), 96 | // and the land, with a far clip plane 97 | cam->ClipBack = 10000.0; 98 | plRenderBegin(cam); 99 | plRenderObj(sky); 100 | plRenderObj(land); 101 | } 102 | } else { // not drawing sky, just render the land 103 | cam->ClipBack = 10000.0; 104 | plRenderBegin(cam); 105 | plRenderObj(land); 106 | } 107 | plRenderEnd(); // finish rendering 108 | 109 | // display framerate counter 110 | plTextPrintf(cam,cam->ClipLeft+5,cam->ClipTop,0.0,156,"%.2f fps", 111 | (frames/ (float) (exClock() - t)) * (float) exClockPerSecond()); 112 | // display last message 113 | plTextPrintf(cam,cam->ClipLeft+5,cam->ClipBottom-16,0.0,156,lastmessage); 114 | 115 | 116 | if (wait_vsync) exWaitVSync(); // wait for vsync 117 | /* blit to screen. This is pretty darn fast on ip5's but on a 486 you 118 | would probably be faster doing a plain memcpy(), i.e: 119 | memcpy((void *) __djgpp_conventional_base+0xA0000,framebuffer,64000); 120 | */ 121 | memcpy(exGraphMem,framebuffer,W*H); 122 | 123 | // We calculate the amount of time in thousanths of seconds this frame took 124 | prevtime = ((exClock() / (float) exClockPerSecond()) - prevtime)*1000.0; 125 | if (exMouseButtons & 2) { // if right button hit, we go forward quickly 126 | cam->X -= 127 | prevtime*4*sin(cam->Pan*PL_PI/180.0)*cos(cam->Pitch*PL_PI/180.0); 128 | cam->Z += 129 | prevtime*4*cos(cam->Pan*PL_PI/180.0)*cos(cam->Pitch*PL_PI/180.0); 130 | cam->Y += 131 | prevtime*4*sin(cam->Pitch*PL_PI/180.0); 132 | } else if (exMouseButtons & 1) { // if left button hit, we go forward slowly 133 | cam->X -= 134 | prevtime*2*sin(cam->Pan*PL_PI/180.0)*cos(cam->Pitch*PL_PI/180.0); 135 | cam->Z += 136 | prevtime*2*cos(cam->Pan*PL_PI/180.0)*cos(cam->Pitch*PL_PI/180.0); 137 | cam->Y += 138 | prevtime*2*sin(cam->Pitch*PL_PI/180.0); 139 | } 140 | cam->Pitch -= (exMouseDeltaY*mouse_sens); // update pitch and pan of ship 141 | cam->Pan -= (exMouseDeltaX*mouse_sens); 142 | 143 | if (cam->X > LAND_SIZE/2) cam->X = LAND_SIZE/2; // make sure we don't go 144 | if (cam->X < -LAND_SIZE/2) cam->X = -LAND_SIZE/2; // too far away 145 | if (cam->Z > LAND_SIZE/2) cam->Z = LAND_SIZE/2; 146 | if (cam->Z < -LAND_SIZE/2) cam->Z = -LAND_SIZE/2; 147 | if (cam->Y < 0) cam->Y = 0; 148 | if (cam->Y > 8999) cam->Y = 8999; 149 | 150 | while ((c = exGetKey())) switch(c) { // handle keystrokes 151 | case 27: done++; break; // ESC == quit 152 | // + is for zooming in. 153 | case '=': case '+': cam->Fov -= 1.0; if (cam->Fov < 1.0) cam->Fov = 1.0; 154 | sprintf(lastmessage,"FOV: %2.f",cam->Fov); 155 | break; 156 | // - is for zooming out 157 | case '-': cam->Fov += 1.0; if (cam->Fov > 179.0) cam->Fov = 179.0; 158 | sprintf(lastmessage,"FOV: %2.f",cam->Fov); 159 | break; 160 | // [ decreases mouse sensitivity 161 | case '[': mouse_sens /= 1.1; 162 | sprintf(lastmessage,"MouseSens: %.3f",mouse_sens); 163 | break; 164 | // ] increases mouse sensitivity 165 | case ']': mouse_sens *= 1.1; 166 | sprintf(lastmessage,"MouseSens: %.3f",mouse_sens); 167 | break; 168 | // v toggles vsync 169 | case 'v': wait_vsync ^= 1; 170 | sprintf(lastmessage,"VSync %s",wait_vsync ? "on" : "off"); 171 | break; 172 | // s toggles sky 173 | case 's': draw_sky ^= 1; 174 | sprintf(lastmessage,"Sky %s",draw_sky ? "on" : "off"); 175 | break; 176 | } 177 | } 178 | // set text mode 179 | exSetText(); 180 | // clean up 181 | free(framebuffer); 182 | plObjDelete(land); 183 | plObjDelete(sky); 184 | plObjDelete(sky2); 185 | plMatDelete(mat[0]); 186 | plMatDelete(mat[1]); 187 | plMatDelete(mat[2]); 188 | plCamDelete(cam); 189 | 190 | printf("This has been a Plush demo app.\n" 191 | "Visit the Plush 3D homepage at: \n" 192 | " http://nullsoft.home.ml.org/plush/\n\n"); 193 | 194 | return 0; 195 | } 196 | 197 | void setup_materials(pl_Mat **mat, pl_uChar *pal) { 198 | int i; 199 | // create our 3 materials, make the fourth null so that plMatMakeOptPal2() 200 | // knows where to stop 201 | mat[0] = plMatCreate(); 202 | mat[1] = plMatCreate(); 203 | mat[2] = plMatCreate(); 204 | mat[3] = 0; 205 | 206 | pal[0] = pal[1] = pal[2] = 0; // make color 0 black. 207 | 208 | // set up material 0 (the ground) 209 | mat[0]->ShadeType = PL_SHADE_GOURAUD_DISTANCE; 210 | mat[0]->Shininess = 1; 211 | mat[0]->NumGradients = 2500; 212 | mat[0]->Ambient[0] = pal[0]*2 - 255; // these calculations are to get the 213 | mat[0]->Ambient[1] = pal[1]*2 - 255; // distance shading to work right 214 | mat[0]->Ambient[2] = pal[2]*2 - 255; 215 | mat[0]->Diffuse[0] = 127-pal[0]; 216 | mat[0]->Diffuse[1] = 127-pal[1]; 217 | mat[0]->Diffuse[2] = 127-pal[2]; 218 | mat[0]->Specular[0] = 127-pal[0]; 219 | mat[0]->Specular[1] = 127-pal[1]; 220 | mat[0]->Specular[2] = 127-pal[2]; 221 | mat[0]->FadeDist = 10000.0; 222 | mat[0]->Texture = plReadPCXTex("ground.pcx",1,1); 223 | mat[0]->TexScaling = 40.0*LAND_SIZE/50000; 224 | mat[0]->PerspectiveCorrect = 16; 225 | 226 | // set up material 1 (the sky) 227 | mat[1]->ShadeType = PL_SHADE_GOURAUD_DISTANCE; 228 | mat[1]->Shininess = 1; 229 | mat[1]->NumGradients = 1500; 230 | mat[1]->Ambient[0] = pal[0]*2 - 255; 231 | mat[1]->Ambient[1] = pal[1]*2 - 255; 232 | mat[1]->Ambient[2] = pal[2]*2 - 255; 233 | mat[1]->Diffuse[0] = 127-pal[0]; 234 | mat[1]->Diffuse[1] = 127-pal[1]; 235 | mat[1]->Diffuse[2] = 127-pal[2]; 236 | mat[1]->Specular[0] = 127-pal[0]; 237 | mat[1]->Specular[1] = 127-pal[1]; 238 | mat[1]->Specular[2] = 127-pal[2]; 239 | mat[1]->FadeDist = 10000.0; 240 | mat[1]->Texture = plReadPCXTex("sky.pcx",1,1); 241 | mat[1]->TexScaling = 45.0*LAND_SIZE/50000; 242 | mat[1]->PerspectiveCorrect = 32; 243 | 244 | // set up material 2 (the second sky) 245 | mat[2]->ShadeType = PL_SHADE_NONE; 246 | mat[2]->Shininess = 1; 247 | mat[2]->NumGradients = 1500; 248 | mat[2]->Texture = plReadPCXTex("sky2.pcx",1,1); 249 | mat[2]->TexScaling = 10.0; //200.0*LAND_SIZE/50000; 250 | mat[2]->PerspectiveCorrect = 2; 251 | 252 | // intialize the materials 253 | plMatInit(mat[0]); 254 | plMatInit(mat[1]); 255 | plMatInit(mat[2]); 256 | 257 | // make a nice palette 258 | plMatMakeOptPal(pal,1,255,mat,3); 259 | 260 | // map the materials to this new palette 261 | plMatMapToPal(mat[0],pal,0,255); 262 | plMatMapToPal(mat[1],pal,0,255); 263 | plMatMapToPal(mat[2],pal,0,255); 264 | 265 | // set the new palette 266 | exSetPalette(pal); 267 | } 268 | 269 | pl_Obj *setup_landscape(pl_Mat *m, pl_Mat *sm, pl_Mat *sm2) { 270 | int i; 271 | // make our root object the land 272 | pl_Obj *o = plMakePlane(LAND_SIZE,LAND_SIZE,LAND_DIV-1,m); 273 | // give it a nice random bumpy effect 274 | for (i = 0; i < o->NumVertices; i ++) 275 | o->Vertices[i].y += (float) (rand()%1400)-700; 276 | // gotta recalculate normals for backface culling to work right 277 | plObjCalcNormals(o); 278 | 279 | // Make our first child the first sky 280 | o->Children[0] = plMakePlane(LAND_SIZE,LAND_SIZE,1,sm); 281 | o->Children[0]->Yp = 2000; 282 | o->Children[0]->BackfaceCull = 0; 283 | 284 | // and the second the second sky 285 | o->Children[1] = plMakeSphere(LAND_SIZE,10,10,sm2); 286 | o->Children[1]->Yp = 2000; 287 | plObjFlipNormals(o->Children[1]); 288 | 289 | return (o); 290 | } 291 | -------------------------------------------------------------------------------- /examples/fork.3ds: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:26925fe8c6cae425ded0cd551bd676fc5f3acdd67efd3284b93cbc08c834a857 3 | size 4533 4 | -------------------------------------------------------------------------------- /examples/ground.pcx: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:acfb7935de2e7cdd2bd8b159ceee43276a43a809dabbe6a85c3ad4cad6ee6e02 3 | size 4763 4 | -------------------------------------------------------------------------------- /examples/model.c: -------------------------------------------------------------------------------- 1 | // model.c: 3DS model loading example 2 | // owo 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include "ex.h" 12 | 13 | pl_Light *light; 14 | pl_Obj *model; 15 | pl_Mat *material; 16 | pl_Cam *camera; 17 | uint8_t framebuffer[W * H]; 18 | uint8_t palette[768]; 19 | 20 | int main(int argc, char **argv) 21 | { 22 | /* setup graphics mode */ 23 | exSetGraphics(); 24 | 25 | /* create material */ 26 | material = plMatCreate(); 27 | material->NumGradients = 100; 28 | material->ShadeType = PL_SHADE_FLAT; 29 | plMatInit(material); 30 | 31 | /* create palette */ 32 | plMatMakeOptPal(palette, 1, 255, &material, 1); 33 | palette[0] = palette[1] = palette[2] = 0; 34 | plMatMapToPal(material, palette, 0, 255); 35 | 36 | exSetPalette(palette); 37 | 38 | /* load fork model */ 39 | model = plRead3DSObj("fork.3ds", material); 40 | 41 | /* create camera */ 42 | camera = plCamCreate(W, H, W * 3.0 / (H * 4.0), 90.0, framebuffer, NULL); 43 | camera->Z = -300; 44 | 45 | /* create light */ 46 | light = plLightSet(plLightCreate(), PL_LIGHT_VECTOR, 0.0, 0.0, 0.0, 1.0, 1.0); 47 | 48 | /* main loop */ 49 | while (!exGetKey()) 50 | { 51 | /* rotate model */ 52 | model->Xa += 1.0; 53 | model->Ya += 1.0; 54 | model->Za += 1.0; 55 | 56 | /* clear back buffer */ 57 | memset(framebuffer, 0, W * H); 58 | 59 | /* render frame */ 60 | plRenderBegin(camera); 61 | plRenderLight(light); 62 | plRenderObj(model); 63 | plRenderEnd(); 64 | 65 | /* wait for vsync, then copy to screen */ 66 | exWaitVSync(); 67 | memcpy(exGraphMem, framebuffer, W * H); 68 | } 69 | 70 | /* clean up */ 71 | plCamDelete(camera); 72 | plLightDelete(light); 73 | plObjDelete(model); 74 | plMatDelete(material); 75 | 76 | /* shut down video */ 77 | exSetText(); 78 | 79 | return 0; 80 | } 81 | -------------------------------------------------------------------------------- /examples/sky.pcx: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f6509f782d8aab81cbf4c82d3ee509e483109f1d39a57f3829adb9f10f553401 3 | size 6811 4 | -------------------------------------------------------------------------------- /examples/sky2.pcx: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:adf2d01a7cbaa820704f3b71fe534b3c913d687356d35696370cf156d499832c 3 | size 1173 4 | -------------------------------------------------------------------------------- /examples/texture.c: -------------------------------------------------------------------------------- 1 | // texture.c: custom texture example 2 | // owo 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include "ex.h" 12 | 13 | #include "texture1.h" 14 | 15 | pl_Light *light; 16 | pl_Obj *model; 17 | pl_Mat *material; 18 | pl_Cam *camera; 19 | uint8_t framebuffer[W * H]; 20 | uint8_t palette[768]; 21 | 22 | int main(int argc, char **argv) 23 | { 24 | /* setup graphics mode */ 25 | exSetGraphics(); 26 | 27 | /* create material */ 28 | material = plMatCreate(); 29 | material->NumGradients = 256; 30 | material->ShadeType = PL_SHADE_FLAT; 31 | material->Texture = plTexCreate(64, 64, texture1_pixels, 256, texture1_palette); 32 | material->Diffuse[0] = material->Diffuse[1] = material->Diffuse[2] = 0; 33 | plMatInit(material); 34 | 35 | /* create palette */ 36 | plMatMakeOptPal(palette, 1, 255, &material, 1); 37 | palette[0] = palette[1] = palette[2] = 0; 38 | plMatMapToPal(material, palette, 0, 255); 39 | 40 | exSetPalette(palette); 41 | 42 | /* create cube */ 43 | model = plMakeBox(100, 100, 100, material); 44 | 45 | /* create camera */ 46 | camera = plCamCreate(W, H, W * 3.0 / (H * 4.0), 90.0, framebuffer, NULL); 47 | camera->Z = -300; 48 | 49 | /* create light */ 50 | light = plLightSet(plLightCreate(), PL_LIGHT_VECTOR, 0.0, 0.0, 0.0, 1.0, 1.0); 51 | 52 | /* main loop */ 53 | while (!exGetKey()) 54 | { 55 | /* rotate model */ 56 | model->Xa += 1.0; 57 | model->Ya += 1.0; 58 | model->Za += 1.0; 59 | 60 | /* clear back buffer */ 61 | memset(framebuffer, 0, W * H); 62 | 63 | /* render frame */ 64 | plRenderBegin(camera); 65 | plRenderLight(light); 66 | plRenderObj(model); 67 | plRenderEnd(); 68 | 69 | /* wait for vsync, then copy to screen */ 70 | exWaitVSync(); 71 | memcpy(exGraphMem, framebuffer, W * H); 72 | } 73 | 74 | /* clean up */ 75 | plCamDelete(camera); 76 | plLightDelete(light); 77 | plObjDelete(model); 78 | plMatDelete(material); 79 | 80 | /* shut down video */ 81 | exSetText(); 82 | 83 | return 0; 84 | } 85 | -------------------------------------------------------------------------------- /examples/texture1.pcx: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:fdd1c2529fed76b3a4d8430c120f0784b8a5957dc78252fbd4907a12104a4774 3 | size 12786 4 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "nixpkgs": { 4 | "locked": { 5 | "lastModified": 1728901079, 6 | "narHash": "sha256-wu/EKnJfAK7+4Brql/igzkHHJVtHVmCYCo0TJIT94Gk=", 7 | "owner": "NixOS", 8 | "repo": "nixpkgs", 9 | "rev": "0ebf6d5c0212366e85a5a6d303ad62980517004e", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "owner": "NixOS", 14 | "repo": "nixpkgs", 15 | "type": "github" 16 | } 17 | }, 18 | "root": { 19 | "inputs": { 20 | "nixpkgs": "nixpkgs" 21 | } 22 | } 23 | }, 24 | "root": "root", 25 | "version": 7 26 | } 27 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "A neat, portable, realtime 3D rendering library"; 3 | 4 | inputs.nixpkgs.url = github:NixOS/nixpkgs; 5 | 6 | outputs = { self, nixpkgs, ... }: { 7 | packages.x86_64-linux.default = nixpkgs.legacyPackages.x86_64-linux.callPackage ./default.nix { 8 | version = self.lastModifiedDate; 9 | }; 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /include/plush/pl_conf.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | pl_conf.h 3 | PLUSH 3D VERSION 1.2 CONFIGURATION HEADER 4 | Copyright (c) 1996-2000, Justin Frankel 5 | ******************************************************************************/ 6 | 7 | #ifndef _PL_CONF_H_ 8 | #define _PL_CONF_H_ 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | /* Maximum children per object */ 15 | #define PL_MAX_CHILDREN (16) 16 | 17 | /* Maximum lights per scene -- if you exceed this, they will be ignored */ 18 | #define PL_MAX_LIGHTS (32) 19 | 20 | /* Maximum number of triangles per scene -- if you exceed this, entire 21 | objects will be ignored. You can increase this if you need it. It takes 22 | approximately 8*PL_MAX_TRIANGLES bytes of memory. i.e. the default of 23 | 16384 consumes 128kbytes of memory. not really a big deal, 24 | */ 25 | 26 | #define PL_MAX_TRIANGLES (16384) 27 | 28 | typedef float pl_ZBuffer; /* z-buffer type (must be float) */ 29 | typedef float pl_Float; /* IEEE 32 bit floating point */ 30 | typedef int32_t pl_sInt32; /* signed 32 bit integer */ 31 | typedef uint32_t pl_uInt32; /* unsigned 32 bit integer */ 32 | typedef int16_t pl_sInt16; /* signed 16 bit integer */ 33 | typedef uint16_t pl_uInt16; /* unsigned 16 bit integer */ 34 | typedef int32_t pl_sInt; /* signed optimal integer */ 35 | typedef uint32_t pl_uInt; /* unsigned optimal integer */ 36 | typedef int pl_Bool; /* boolean */ 37 | typedef uint8_t pl_uChar; /* unsigned 8 bit integer */ 38 | typedef int8_t pl_sChar; /* signed 8 bit integer */ 39 | 40 | #ifdef __cplusplus 41 | } 42 | #endif 43 | 44 | #endif /* !_PL_CONF_H_ */ 45 | -------------------------------------------------------------------------------- /include/plush/pl_defs.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | pl_defs.h 3 | PLUSH 3D VERSION 1.2 CONSTANTS DEFINITION HEADER 4 | Copyright (c) 1996-2000, Justin Frankel 5 | ******************************************************************************/ 6 | 7 | #ifndef _PL_DEFS_H_ 8 | #define _PL_DEFS_H_ 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | /* true and false */ 15 | #define PL_TRUE (1) 16 | #define PL_FALSE (0) 17 | 18 | /* pi! */ 19 | #ifdef M_PI 20 | #define PL_PI M_PI 21 | #else 22 | #define PL_PI 3.14159265359 23 | #endif 24 | 25 | /* Utility min() and max() functions */ 26 | #define plMin(x,y) (( ( x ) > ( y ) ? ( y ) : ( x ))) 27 | #define plMax(x,y) (( ( x ) < ( y ) ? ( y ) : ( x ))) 28 | 29 | /* 30 | ** Shade modes. Used with plMat.ShadeType 31 | ** Note that (PL_SHADE_GOURAUD|PL_SHADE_GOURAUD_DISTANCE) and 32 | ** (PL_SHADE_FLAT|PL_SHADE_FLAT_DISTANCE) are valid shading modes. 33 | */ 34 | #define PL_SHADE_NONE (1) 35 | #define PL_SHADE_FLAT (2) 36 | #define PL_SHADE_FLAT_DISTANCE (4) 37 | #define PL_SHADE_GOURAUD (8) 38 | #define PL_SHADE_GOURAUD_DISTANCE (16) 39 | 40 | /* 41 | ** Light modes. Used with plLight.Type or plLightSet(). 42 | ** Note that PL_LIGHT_POINT_ANGLE assumes no falloff and uses the angle between 43 | ** the light and the point, PL_LIGHT_POINT_DISTANCE has falloff with proportion 44 | ** to distance**2 (see plLightSet() for setting it), PL_LIGHT_POINT does both. 45 | */ 46 | #define PL_LIGHT_NONE (0x0) 47 | #define PL_LIGHT_VECTOR (0x1) 48 | #define PL_LIGHT_POINT (0x2|0x4) 49 | #define PL_LIGHT_POINT_DISTANCE (0x2) 50 | #define PL_LIGHT_POINT_ANGLE (0x4) 51 | 52 | /* Used internally; PL_FILL_* are stored in plMat._st. */ 53 | #define PL_FILL_SOLID (0x0) 54 | #define PL_FILL_TEXTURE (0x1) 55 | #define PL_FILL_ENVIRONMENT (0x2) 56 | #define PL_FILL_TRANSPARENT (0x4) 57 | 58 | #define PL_TEXENV_ADD (0) 59 | #define PL_TEXENV_MUL (1) 60 | #define PL_TEXENV_AVG (2) 61 | #define PL_TEXENV_TEXMINUSENV (3) 62 | #define PL_TEXENV_ENVMINUSTEX (4) 63 | #define PL_TEXENV_MIN (5) 64 | #define PL_TEXENV_MAX (6) 65 | 66 | #ifdef __cplusplus 67 | } 68 | #endif 69 | 70 | #endif /* !_PL_DEFS_H_ */ 71 | -------------------------------------------------------------------------------- /include/plush/pl_types.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | pl_types.h 3 | PLUSH 3D VERSION 1.2 TYPES DEFINITION HEADER 4 | Copyright (c) 1996-2000 Justin Frankel 5 | ******************************************************************************/ 6 | 7 | #ifndef _PL_TYPES_H_ 8 | #define _PL_TYPES_H_ 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | /* 15 | ** Texture type. Read textures with plReadPCXTex(), and assign them to 16 | ** plMat.Environment or plMat.Texture. 17 | */ 18 | typedef struct _pl_Texture { 19 | pl_uChar *Data; /* Texture data */ 20 | pl_uChar *PaletteData; /* Palette data (NumColors bytes) */ 21 | pl_uChar Width, Height; /* Log2 of dimensions */ 22 | pl_uInt iWidth, iHeight; /* Integer dimensions */ 23 | pl_Float uScale, vScale; /* Scaling (usually 2**Width, 2**Height) */ 24 | pl_uInt NumColors; /* Number of colors used in texture */ 25 | } pl_Texture; 26 | 27 | /* 28 | ** Material type. Create materials with plMatCreate(). 29 | */ 30 | typedef struct _pl_Face pl_Face; 31 | typedef struct _pl_Cam pl_Cam; 32 | typedef struct _pl_Mat { 33 | pl_sInt Ambient[3]; /* RGB of surface (0-255 is a good range) */ 34 | pl_sInt Diffuse[3]; /* RGB of diffuse (0-255 is a good range) */ 35 | pl_sInt Specular[3]; /* RGB of "specular" highlights (0-255) */ 36 | pl_uInt Shininess; /* Shininess of material. 1 is dullest */ 37 | pl_Float FadeDist; /* For distance fading, distance at 38 | which intensity is 0 */ 39 | pl_uChar ShadeType; /* Shade type: PL_SHADE_* */ 40 | pl_uChar Transparent; /* Transparency index (0 = none), 4 = alot 41 | Note: transparencies disable textures */ 42 | pl_uChar PerspectiveCorrect; /* Correct textures every n pixels */ 43 | pl_Texture *Texture; /* Texture map (see pl_Texture) above */ 44 | pl_Texture *Environment; /* Environment map (ditto) */ 45 | pl_Float TexScaling; /* Texture map scaling */ 46 | pl_Float EnvScaling; /* Environment map scaling */ 47 | pl_uChar TexEnvMode; /* TexEnv combining mode (PL_TEXENV_*) */ 48 | pl_Bool zBufferable; /* Can this material be zbuffered? */ 49 | pl_uInt NumGradients; /* Desired number of gradients to be used */ 50 | /* The following are used mostly internally */ 51 | pl_uInt _ColorsUsed; /* Number of colors actually used */ 52 | pl_uChar _st, _ft; /* The shadetype and filltype */ 53 | pl_uInt _tsfact; /* Translucent shading factor */ 54 | pl_uInt16 *_AddTable; /* Shading/Translucent/etc table */ 55 | pl_uChar *_ReMapTable; /* Table to remap colors to palette */ 56 | pl_uChar *_RequestedColors; /* _ColorsUsed colors, desired colors */ 57 | void (*_PutFace)(pl_Cam *, pl_Face *); 58 | /* Function that renders the triangle with this 59 | material */ 60 | } pl_Mat; 61 | 62 | /* 63 | ** Vertex, used within pl_Obj 64 | */ 65 | typedef struct _pl_Vertex { 66 | pl_Float x, y, z; /* Vertex coordinate (objectspace) */ 67 | pl_Float xformedx, xformedy, xformedz; 68 | /* Transformed vertex 69 | coordinate (cameraspace) */ 70 | pl_Float nx, ny, nz; /* Unit vertex normal (objectspace) */ 71 | pl_Float xformednx, xformedny, xformednz; 72 | /* Transformed unit vertex normal 73 | (cameraspace) */ 74 | } pl_Vertex; 75 | 76 | /* 77 | ** Face 78 | */ 79 | typedef struct _pl_Face { 80 | pl_Vertex *Vertices[3]; /* Vertices of triangle */ 81 | pl_Float nx, ny, nz; /* Normal of triangle (object space) */ 82 | pl_Mat *Material; /* Material of triangle */ 83 | pl_sInt32 Scrx[3], Scry[3]; /* Projected screen coordinates 84 | (12.20 fixed point) */ 85 | pl_Float Scrz[3]; /* Projected 1/Z coordinates */ 86 | pl_sInt32 MappingU[3], MappingV[3]; 87 | /* 16.16 Texture mapping coordinates */ 88 | pl_sInt32 eMappingU[3], eMappingV[3]; 89 | /* 16.16 Environment map coordinates */ 90 | pl_Float fShade; /* Flat intensity */ 91 | pl_Float sLighting; /* Face static lighting. Should usually be 0.0 */ 92 | pl_Float Shades[3]; /* Vertex intensity */ 93 | pl_Float vsLighting[3]; /* Vertex static lighting. Should be 0.0 */ 94 | } pl_Face; 95 | 96 | /* 97 | ** Object 98 | */ 99 | typedef struct _pl_Obj { 100 | pl_uInt32 NumVertices; /* Number of vertices */ 101 | pl_uInt32 NumFaces; /* Number of faces */ 102 | pl_Vertex *Vertices; /* Array of vertices */ 103 | pl_Face *Faces; /* Array of faces */ 104 | struct _pl_Obj *Children[PL_MAX_CHILDREN]; 105 | /* Children */ 106 | pl_Bool BackfaceCull; /* Are backfacing polys drawn? */ 107 | pl_Bool BackfaceIllumination; /* Illuminated by lights behind them? */ 108 | pl_Bool GenMatrix; /* Generate Matrix from the following 109 | if set */ 110 | pl_Float Xp, Yp, Zp, Xa, Ya, Za; /* Position and rotation of object: 111 | Note: rotations are around 112 | X then Y then Z. Measured in degrees */ 113 | pl_Float Matrix[16]; /* Transformation matrix */ 114 | pl_Float RotMatrix[16]; /* Rotation only matrix (for normals) */ 115 | } pl_Obj; 116 | 117 | /* 118 | ** Spline type. See plSpline*(). 119 | */ 120 | typedef struct _pl_Spline { 121 | pl_Float *keys; /* Key data, keyWidth*numKeys */ 122 | pl_sInt keyWidth; /* Number of floats per key */ 123 | pl_sInt numKeys; /* Number of keys */ 124 | pl_Float cont; /* Continuity. Should be -1.0 -> 1.0 */ 125 | pl_Float bias; /* Bias. -1.0 -> 1.0 */ 126 | pl_Float tens; /* Tension. -1.0 -> 1.0 */ 127 | } pl_Spline; 128 | 129 | /* 130 | ** Light type. See plLight*(). 131 | */ 132 | typedef struct _pl_Light { 133 | pl_uChar Type; /* Type of light: PL_LIGHT_* */ 134 | pl_Float Xp, Yp, Zp; /* If Type=PL_LIGHT_POINT*, 135 | this is Position (PL_LIGHT_POINT_*), 136 | otherwise if PL_LIGHT_VECTOR, 137 | Unit vector */ 138 | pl_Float Intensity; /* Intensity. 0.0 is off, 1.0 is full */ 139 | pl_Float HalfDistSquared; /* Distance squared at which 140 | PL_LIGHT_POINT_DISTANCE is 50% */ 141 | } pl_Light; 142 | 143 | /* 144 | ** Camera Type. 145 | */ 146 | typedef struct _pl_Cam { 147 | pl_Float Fov; /* FOV in degrees valid range is 1-179 */ 148 | pl_Float AspectRatio; /* Aspect ratio (usually 1.0) */ 149 | pl_sChar Sort; /* Sort polygons, -1 f-t-b, 1 b-t-f, 0 no */ 150 | pl_Float ClipBack; /* Far clipping ( < 0.0 is none) */ 151 | pl_sInt ClipTop, ClipLeft; /* Screen Clipping */ 152 | pl_sInt ClipBottom, ClipRight; 153 | pl_uInt ScreenWidth, ScreenHeight; /* Screen dimensions */ 154 | pl_sInt CenterX, CenterY; /* Center of screen */ 155 | pl_Float X, Y, Z; /* Camera position in worldspace */ 156 | pl_Float Pitch, Pan, Roll; /* Camera angle in degrees in worldspace */ 157 | pl_uChar *frameBuffer; /* Framebuffer (ScreenWidth*ScreenHeight) */ 158 | pl_ZBuffer *zBuffer; /* Z Buffer (NULL if none) */ 159 | } pl_Cam; 160 | 161 | #ifdef __cplusplus 162 | } 163 | #endif 164 | 165 | #endif /* !_PL_TYPES_H_ */ 166 | -------------------------------------------------------------------------------- /source/cam.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Plush Version 1.2 3 | cam.c 4 | Camera Control 5 | Copyright (c) 1996-2000, Justin Frankel 6 | ******************************************************************************/ 7 | 8 | #include 9 | 10 | void plCamDelete(pl_Cam *c) { 11 | if (c) free(c); 12 | } 13 | 14 | void plCamSetTarget(pl_Cam *c, pl_Float x, pl_Float y, pl_Float z) { 15 | double dx, dy, dz; 16 | dx = x - c->X; 17 | dy = y - c->Y; 18 | dz = z - c->Z; 19 | c->Roll = 0; 20 | if (dz > 0.0001f) { 21 | c->Pan = (pl_Float) (-atan(dx/dz)*(180.0/PL_PI)); 22 | dz /= cos(c->Pan*(PL_PI/180.0)); 23 | c->Pitch = (pl_Float) (atan(dy/dz)*(180.0/PL_PI)); 24 | } else if (dz < -0.0001f) { 25 | c->Pan = (pl_Float) (180.0-atan(dx/dz)*(180.0/PL_PI)); 26 | dz /= cos((c->Pan-180.0f)*(PL_PI/180.0)); 27 | c->Pitch = (pl_Float) (-atan(dy/dz)*(180.0/PL_PI)); 28 | } else { 29 | c->Pan = 0.0f; 30 | c->Pitch = -90.0f; 31 | } 32 | } 33 | 34 | pl_Cam *plCamCreate(pl_uInt sw, pl_uInt sh, pl_Float ar, pl_Float fov, 35 | pl_uChar *fb, pl_ZBuffer *zb) { 36 | pl_Cam *c; 37 | c = (pl_Cam *)malloc(sizeof(pl_Cam)); 38 | if (!c) return 0; 39 | memset(c,0,sizeof(pl_Cam)); 40 | c->Fov = fov; 41 | c->AspectRatio = ar; 42 | c->ClipRight = c->ScreenWidth = sw; 43 | c->ClipBottom = c->ScreenHeight = sh; 44 | c->CenterX = sw>>1; 45 | c->CenterY = sh>>1; 46 | c->ClipBack = 8.0e30f; 47 | c->frameBuffer = fb; 48 | c->zBuffer = zb; 49 | c->Sort = 1; 50 | if (zb) c->Sort = 0; 51 | return (c); 52 | } 53 | -------------------------------------------------------------------------------- /source/clip.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Plush Version 1.2 3 | clip.c 4 | 3D Frustum Clipping 5 | Copyright (c) 1996-2000, Justin Frankel 6 | ******************************************************************************/ 7 | 8 | #include 9 | 10 | #define NUM_CLIP_PLANES 5 11 | 12 | typedef struct 13 | { 14 | pl_Vertex newVertices[8]; 15 | double Shades[8]; 16 | double MappingU[8]; 17 | double MappingV[8]; 18 | double eMappingU[8]; 19 | double eMappingV[8]; 20 | } _clipInfo; 21 | 22 | 23 | static _clipInfo m_cl[2]; 24 | 25 | 26 | static double m_clipPlanes[NUM_CLIP_PLANES][4]; 27 | static pl_Cam *m_cam; 28 | static pl_sInt32 m_cx, m_cy; 29 | static double m_fov; 30 | static double m_adj_asp; 31 | 32 | static void _FindNormal(double x2, double x3, 33 | double y2, double y3, 34 | double zv, 35 | double *res); 36 | 37 | /* Returns: 0 if nothing gets in, 1 or 2 if pout1 & pout2 get in */ 38 | static pl_uInt _ClipToPlane(pl_uInt numVerts, double *plane); 39 | 40 | void plClipSetFrustum(pl_Cam *cam) { 41 | m_adj_asp = 1.0 / cam->AspectRatio; 42 | m_fov = plMin(plMax(cam->Fov,1.0),179.0); 43 | m_fov = (1.0/tan(m_fov*(PL_PI/360.0)))*(double) (cam->ClipRight-cam->ClipLeft); 44 | m_cx = cam->CenterX<<20; 45 | m_cy = cam->CenterY<<20; 46 | m_cam = cam; 47 | memset(m_clipPlanes,0,sizeof(m_clipPlanes)); 48 | 49 | /* Back */ 50 | m_clipPlanes[0][2] = -1.0; 51 | m_clipPlanes[0][3] = -cam->ClipBack; 52 | 53 | /* Left */ 54 | m_clipPlanes[1][3] = 0.00000001; 55 | if (cam->ClipLeft == cam->CenterX) { 56 | m_clipPlanes[1][0] = 1.0; 57 | } 58 | else _FindNormal(-100,-100, 59 | 100, -100, 60 | m_fov*-100.0/(cam->ClipLeft-cam->CenterX), 61 | m_clipPlanes[1]); 62 | if (cam->ClipLeft > cam->CenterX) { 63 | m_clipPlanes[1][0] = -m_clipPlanes[1][0]; 64 | m_clipPlanes[1][1] = -m_clipPlanes[1][1]; 65 | m_clipPlanes[1][2] = -m_clipPlanes[1][2]; 66 | } 67 | 68 | /* Right */ 69 | m_clipPlanes[2][3] = 0.00000001; 70 | if (cam->ClipRight == cam->CenterX) { 71 | m_clipPlanes[2][0] = -1.0; 72 | } 73 | else _FindNormal(100,100, 74 | -100, 100, 75 | m_fov*100.0/(cam->ClipRight-cam->CenterX), 76 | m_clipPlanes[2]); 77 | if (cam->ClipRight < cam->CenterX) { 78 | m_clipPlanes[2][0] = -m_clipPlanes[2][0]; 79 | m_clipPlanes[2][1] = -m_clipPlanes[2][1]; 80 | m_clipPlanes[2][2] = -m_clipPlanes[2][2]; 81 | } 82 | /* Top */ 83 | m_clipPlanes[3][3] = 0.00000001; 84 | if (cam->ClipTop == cam->CenterY) { 85 | m_clipPlanes[3][1] = -1.0; 86 | } else _FindNormal(100, -100, 87 | 100, 100, 88 | m_fov*m_adj_asp*100.0/(cam->CenterY-cam->ClipTop), 89 | m_clipPlanes[3]); 90 | if (cam->ClipTop > cam->CenterY) { 91 | m_clipPlanes[3][0] = -m_clipPlanes[3][0]; 92 | m_clipPlanes[3][1] = -m_clipPlanes[3][1]; 93 | m_clipPlanes[3][2] = -m_clipPlanes[3][2]; 94 | } 95 | 96 | /* Bottom */ 97 | m_clipPlanes[4][3] = 0.00000001; 98 | if (cam->ClipBottom == cam->CenterY) { 99 | m_clipPlanes[4][1] = 1.0; 100 | } else _FindNormal(-100, 100, 101 | -100, -100, 102 | m_fov*m_adj_asp*-100.0/(cam->CenterY-cam->ClipBottom), 103 | m_clipPlanes[4]); 104 | if (cam->ClipBottom < cam->CenterY) { 105 | m_clipPlanes[4][0] = -m_clipPlanes[4][0]; 106 | m_clipPlanes[4][1] = -m_clipPlanes[4][1]; 107 | m_clipPlanes[4][2] = -m_clipPlanes[4][2]; 108 | } 109 | } 110 | 111 | 112 | void plClipRenderFace(pl_Face *face) { 113 | pl_uInt k, a, w, numVerts; 114 | double tmp, tmp2; 115 | pl_Face newface; 116 | 117 | for (a = 0; a < 3; a ++) { 118 | m_cl[0].newVertices[a] = *(face->Vertices[a]); 119 | m_cl[0].Shades[a] = face->Shades[a]; 120 | m_cl[0].MappingU[a] = face->MappingU[a]; 121 | m_cl[0].MappingV[a] = face->MappingV[a]; 122 | m_cl[0].eMappingU[a] = face->eMappingU[a]; 123 | m_cl[0].eMappingV[a] = face->eMappingV[a]; 124 | } 125 | 126 | numVerts = 3; 127 | a = (m_clipPlanes[0][3] < 0.0 ? 0 : 1); 128 | while (a < NUM_CLIP_PLANES && numVerts > 2) 129 | { 130 | numVerts = _ClipToPlane(numVerts, m_clipPlanes[a]); 131 | memcpy(&m_cl[0],&m_cl[1],sizeof(m_cl)/2); 132 | a++; 133 | } 134 | if (numVerts > 2) { 135 | memcpy(&newface,face,sizeof(pl_Face)); 136 | for (k = 2; k < numVerts; k ++) { 137 | newface.fShade = plMax(0,plMin(face->fShade,1)); 138 | for (a = 0; a < 3; a ++) { 139 | if (a == 0) w = 0; 140 | else w = a+(k-2); 141 | newface.Vertices[a] = m_cl[0].newVertices+w; 142 | newface.Shades[a] = (pl_Float) m_cl[0].Shades[w]; 143 | newface.MappingU[a] = (pl_sInt32)m_cl[0].MappingU[w]; 144 | newface.MappingV[a] = (pl_sInt32)m_cl[0].MappingV[w]; 145 | newface.eMappingU[a] = (pl_sInt32)m_cl[0].eMappingU[w]; 146 | newface.eMappingV[a] = (pl_sInt32)m_cl[0].eMappingV[w]; 147 | newface.Scrz[a] = 1.0f/newface.Vertices[a]->xformedz; 148 | tmp2 = m_fov * newface.Scrz[a]; 149 | tmp = tmp2*newface.Vertices[a]->xformedx; 150 | tmp2 *= newface.Vertices[a]->xformedy; 151 | newface.Scrx[a] = m_cx + ((pl_sInt32)((tmp*(float) (1<<20)))); 152 | newface.Scry[a] = m_cy - ((pl_sInt32)((tmp2*m_adj_asp*(float) (1<<20)))); 153 | } 154 | newface.Material->_PutFace(m_cam,&newface); 155 | plRender_TriStats[3] ++; 156 | } 157 | plRender_TriStats[2] ++; 158 | } 159 | } 160 | 161 | pl_sInt plClipNeeded(pl_Face *face) { 162 | double dr,dl,db,dt; 163 | double f; 164 | dr = (m_cam->ClipRight-m_cam->CenterX); 165 | dl = (m_cam->ClipLeft-m_cam->CenterX); 166 | db = (m_cam->ClipBottom-m_cam->CenterY); 167 | dt = (m_cam->ClipTop-m_cam->CenterY); 168 | f = m_fov*m_adj_asp; 169 | return ((m_cam->ClipBack <= 0.0 || 170 | face->Vertices[0]->xformedz <= m_cam->ClipBack || 171 | face->Vertices[1]->xformedz <= m_cam->ClipBack || 172 | face->Vertices[2]->xformedz <= m_cam->ClipBack) && 173 | (face->Vertices[0]->xformedz >= 0 || 174 | face->Vertices[1]->xformedz >= 0 || 175 | face->Vertices[2]->xformedz >= 0) && 176 | (face->Vertices[0]->xformedx*m_fov<=dr*face->Vertices[0]->xformedz || 177 | face->Vertices[1]->xformedx*m_fov<=dr*face->Vertices[1]->xformedz || 178 | face->Vertices[2]->xformedx*m_fov<=dr*face->Vertices[2]->xformedz) && 179 | (face->Vertices[0]->xformedx*m_fov>=dl*face->Vertices[0]->xformedz || 180 | face->Vertices[1]->xformedx*m_fov>=dl*face->Vertices[1]->xformedz || 181 | face->Vertices[2]->xformedx*m_fov>=dl*face->Vertices[2]->xformedz) && 182 | (face->Vertices[0]->xformedy*f<=db*face->Vertices[0]->xformedz || 183 | face->Vertices[1]->xformedy*f<=db*face->Vertices[1]->xformedz || 184 | face->Vertices[2]->xformedy*f<=db*face->Vertices[2]->xformedz) && 185 | (face->Vertices[0]->xformedy*f>=dt*face->Vertices[0]->xformedz || 186 | face->Vertices[1]->xformedy*f>=dt*face->Vertices[1]->xformedz || 187 | face->Vertices[2]->xformedy*f>=dt*face->Vertices[2]->xformedz)); 188 | } 189 | 190 | 191 | 192 | static void _FindNormal(double x2, double x3,double y2, double y3, 193 | double zv, double *res) { 194 | res[0] = zv*(y2-y3); 195 | res[1] = zv*(x3-x2); 196 | res[2] = x2*y3 - y2*x3; 197 | } 198 | 199 | /* Returns: 0 if nothing gets in, 1 or 2 if pout1 & pout2 get in */ 200 | static pl_uInt _ClipToPlane(pl_uInt numVerts, double *plane) 201 | { 202 | pl_uInt i, nextvert, curin, nextin; 203 | double curdot, nextdot, scale; 204 | pl_uInt invert, outvert; 205 | invert = 0; 206 | outvert = 0; 207 | curdot = m_cl[0].newVertices[0].xformedx*plane[0] + 208 | m_cl[0].newVertices[0].xformedy*plane[1] + 209 | m_cl[0].newVertices[0].xformedz*plane[2]; 210 | curin = (curdot >= plane[3]); 211 | 212 | for (i=0 ; i < numVerts; i++) { 213 | nextvert = (i + 1) % numVerts; 214 | if (curin) { 215 | m_cl[1].Shades[outvert] = m_cl[0].Shades[invert]; 216 | m_cl[1].MappingU[outvert] = m_cl[0].MappingU[invert]; 217 | m_cl[1].MappingV[outvert] = m_cl[0].MappingV[invert]; 218 | m_cl[1].eMappingU[outvert] = m_cl[0].eMappingU[invert]; 219 | m_cl[1].eMappingV[outvert] = m_cl[0].eMappingV[invert]; 220 | m_cl[1].newVertices[outvert++] = m_cl[0].newVertices[invert]; 221 | } 222 | nextdot = m_cl[0].newVertices[nextvert].xformedx*plane[0] + 223 | m_cl[0].newVertices[nextvert].xformedy*plane[1] + 224 | m_cl[0].newVertices[nextvert].xformedz*plane[2]; 225 | nextin = (nextdot >= plane[3]); 226 | if (curin != nextin) { 227 | scale = (plane[3] - curdot) / (nextdot - curdot); 228 | m_cl[1].newVertices[outvert].xformedx = (pl_Float) (m_cl[0].newVertices[invert].xformedx + 229 | (m_cl[0].newVertices[nextvert].xformedx - m_cl[0].newVertices[invert].xformedx) 230 | * scale); 231 | m_cl[1].newVertices[outvert].xformedy = (pl_Float) (m_cl[0].newVertices[invert].xformedy + 232 | (m_cl[0].newVertices[nextvert].xformedy - m_cl[0].newVertices[invert].xformedy) 233 | * scale); 234 | m_cl[1].newVertices[outvert].xformedz = (pl_Float) (m_cl[0].newVertices[invert].xformedz + 235 | (m_cl[0].newVertices[nextvert].xformedz - m_cl[0].newVertices[invert].xformedz) 236 | * scale); 237 | m_cl[1].Shades[outvert] = m_cl[0].Shades[invert] + 238 | (m_cl[0].Shades[nextvert] - m_cl[0].Shades[invert]) * scale; 239 | m_cl[1].MappingU[outvert] = m_cl[0].MappingU[invert] + 240 | (m_cl[0].MappingU[nextvert] - m_cl[0].MappingU[invert]) * scale; 241 | m_cl[1].MappingV[outvert] = m_cl[0].MappingV[invert] + 242 | (m_cl[0].MappingV[nextvert] - m_cl[0].MappingV[invert]) * scale; 243 | m_cl[1].eMappingU[outvert] = m_cl[0].eMappingU[invert] + 244 | (m_cl[0].eMappingU[nextvert] - m_cl[0].eMappingU[invert]) * scale; 245 | m_cl[1].eMappingV[outvert] = m_cl[0].eMappingV[invert] + 246 | (m_cl[0].eMappingV[nextvert] - m_cl[0].eMappingV[invert]) * scale; 247 | outvert++; 248 | } 249 | curdot = nextdot; 250 | curin = nextin; 251 | invert++; 252 | } 253 | return outvert; 254 | } 255 | -------------------------------------------------------------------------------- /source/light.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Plush Version 1.2 3 | light.c 4 | Light Control 5 | Copyright (c) 1996-2000, Justin Frankel 6 | ******************************************************************************/ 7 | 8 | #include 9 | 10 | pl_Light *plLightSet(pl_Light *light, pl_uChar mode, pl_Float x, pl_Float y, 11 | pl_Float z, pl_Float intensity, pl_Float halfDist) { 12 | pl_Float m[16], m2[16]; 13 | light->Type = mode; 14 | light->Intensity = intensity; 15 | light->HalfDistSquared = halfDist*halfDist; 16 | switch (mode) { 17 | case PL_LIGHT_VECTOR: 18 | plMatrixRotate(m,1,x); 19 | plMatrixRotate(m2,2,y); 20 | plMatrixMultiply(m,m2); 21 | plMatrixRotate(m2,3,z); 22 | plMatrixMultiply(m,m2); 23 | plMatrixApply(m,0.0,0.0,-1.0,&light->Xp, &light->Yp, &light->Zp); 24 | break; 25 | case PL_LIGHT_POINT_ANGLE: 26 | case PL_LIGHT_POINT_DISTANCE: 27 | case PL_LIGHT_POINT: 28 | light->Xp = x; 29 | light->Yp = y; 30 | light->Zp = z; 31 | break; 32 | } 33 | return light; 34 | } 35 | 36 | pl_Light *plLightCreate() { 37 | pl_Light *l; 38 | l = (pl_Light *)malloc(sizeof(pl_Light)); 39 | if (!l) return 0; 40 | memset(l,0,sizeof(pl_Light)); 41 | return (l); 42 | } 43 | 44 | void plLightDelete(pl_Light *l) { 45 | if (l) free(l); 46 | } 47 | -------------------------------------------------------------------------------- /source/make.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Plush Version 1.2 3 | make.c 4 | Object Primitives 5 | Copyright (c) 1996-2000, Justin Frankel 6 | ******************************************************************************* 7 | Notes: 8 | Most of these routines are highly unoptimized. 9 | They could all use some work, such as more capable divisions (Box is 10 | most notable), etc... The mapping coordinates are all set up nicely, 11 | though. 12 | ******************************************************************************/ 13 | 14 | #include 15 | 16 | pl_Obj *plMakeTorus(pl_Float r1, pl_Float r2, pl_uInt divrot, pl_uInt divrad, 17 | pl_Mat *m) { 18 | pl_Obj *o; 19 | pl_Vertex *v; 20 | pl_Face *f; 21 | pl_uInt x, y; 22 | double ravg, rt, a, da, al, dal; 23 | pl_sInt32 U,V,dU,dV; 24 | if (divrot < 3) divrot = 3; 25 | if (divrad < 3) divrad = 3; 26 | ravg = (r1+r2)*0.5; 27 | rt = (r2-r1)*0.5; 28 | o = plObjCreate(divrad*divrot,divrad*divrot*2); 29 | if (!o) return 0; 30 | v = o->Vertices; 31 | a = 0.0; 32 | da = 2*PL_PI/divrot; 33 | for (y = 0; y < divrot; y ++) { 34 | al = 0.0; 35 | dal = 2*PL_PI/divrad; 36 | for (x = 0; x < divrad; x ++) { 37 | v->x = (pl_Float) (cos((double) a)*(ravg + cos((double) al)*rt)); 38 | v->z = (pl_Float) (sin((double) a)*(ravg + cos((double) al)*rt)); 39 | v->y = (pl_Float) (sin((double) al)*rt); 40 | v++; 41 | al += dal; 42 | } 43 | a += da; 44 | } 45 | v = o->Vertices; 46 | f = o->Faces; 47 | dV = 65535/divrad; 48 | dU = 65535/divrot; 49 | U = 0; 50 | for (y = 0; y < divrot; y ++) { 51 | V = -32768; 52 | for (x = 0; x < divrad; x ++) { 53 | f->Vertices[0] = v+x+y*divrad; 54 | f->MappingU[0] = U; 55 | f->MappingV[0] = V; 56 | f->Vertices[1] = v+(x+1==divrad?0:x+1)+y*divrad; 57 | f->MappingU[1] = U; 58 | f->MappingV[1] = V+dV; 59 | f->Vertices[2] = v+x+(y+1==divrot?0:(y+1)*divrad); 60 | f->MappingU[2] = U+dU; 61 | f->MappingV[2] = V; 62 | f->Material = m; 63 | f++; 64 | f->Vertices[0] = v+x+(y+1==divrot?0:(y+1)*divrad); 65 | f->MappingU[0] = U+dU; 66 | f->MappingV[0] = V; 67 | f->Vertices[1] = v+(x+1==divrad?0:x+1)+y*divrad; 68 | f->MappingU[1] = U; 69 | f->MappingV[1] = V+dV; 70 | f->Vertices[2] = v+(x+1==divrad?0:x+1)+(y+1==divrot?0:(y+1)*divrad); 71 | f->MappingU[2] = U+dU; 72 | f->MappingV[2] = V+dV; 73 | f->Material = m; 74 | f++; 75 | V += dV; 76 | } 77 | U += dU; 78 | } 79 | plObjCalcNormals(o); 80 | return (o); 81 | } 82 | 83 | pl_Obj *plMakeSphere(pl_Float r, pl_uInt divr, pl_uInt divh, pl_Mat *m) { 84 | pl_Obj *o; 85 | pl_Vertex *v; 86 | pl_Face *f; 87 | pl_uInt x, y; 88 | double a, da, yp, ya, yda, yf; 89 | pl_sInt32 U,V,dU,dV; 90 | if (divh < 3) divh = 3; 91 | if (divr < 3) divr = 3; 92 | o = plObjCreate(2+(divh-2)*(divr),2*divr+(divh-3)*divr*2); 93 | if (!o) return 0; 94 | v = o->Vertices; 95 | v->x = v->z = 0.0; v->y = r; v++; 96 | v->x = v->z = 0.0; v->y = -r; v++; 97 | ya = 0.0; 98 | yda = PL_PI/(divh-1); 99 | da = (PL_PI*2.0)/divr; 100 | for (y = 0; y < divh - 2; y ++) { 101 | ya += yda; 102 | yp = cos((double) ya)*r; 103 | yf = sin((double) ya)*r; 104 | a = 0.0; 105 | for (x = 0; x < divr; x ++) { 106 | v->y = (pl_Float) yp; 107 | v->x = (pl_Float) (cos((double) a)*yf); 108 | v->z = (pl_Float) (sin((double) a)*yf); 109 | v++; 110 | a += da; 111 | } 112 | } 113 | f = o->Faces; 114 | v = o->Vertices + 2; 115 | a = 0.0; 116 | U = 0; 117 | dU = 65535/divr; 118 | dV = V = 65535/divh; 119 | for (x = 0; x < divr; x ++) { 120 | f->Vertices[0] = o->Vertices; 121 | f->Vertices[1] = v + (x+1==divr ? 0 : x+1); 122 | f->Vertices[2] = v + x; 123 | f->MappingU[0] = U; 124 | f->MappingV[0] = 0; 125 | f->MappingU[1] = U+dU; 126 | f->MappingV[1] = V; 127 | f->MappingU[2] = U; 128 | f->MappingV[2] = V; 129 | f->Material = m; 130 | f++; 131 | U += dU; 132 | } 133 | da = 1.0/(divr+1); 134 | v = o->Vertices + 2; 135 | for (x = 0; x < (divh-3); x ++) { 136 | U = 0; 137 | for (y = 0; y < divr; y ++) { 138 | f->Vertices[0] = v+y; 139 | f->Vertices[1] = v+divr+(y+1==divr?0:y+1); 140 | f->Vertices[2] = v+y+divr; 141 | f->MappingU[0] = U; 142 | f->MappingV[0] = V; 143 | f->MappingU[1] = U+dU; 144 | f->MappingV[1] = V+dV; 145 | f->MappingU[2] = U; 146 | f->MappingV[2] = V+dV; 147 | f->Material = m; f++; 148 | f->Vertices[0] = v+y; 149 | f->Vertices[1] = v+(y+1==divr?0:y+1); 150 | f->Vertices[2] = v+(y+1==divr?0:y+1)+divr; 151 | f->MappingU[0] = U; 152 | f->MappingV[0] = V; 153 | f->MappingU[1] = U+dU; 154 | f->MappingV[1] = V; 155 | f->MappingU[2] = U+dU; 156 | f->MappingV[2] = V+dV; 157 | f->Material = m; f++; 158 | U += dU; 159 | } 160 | V += dV; 161 | v += divr; 162 | } 163 | v = o->Vertices + o->NumVertices - divr; 164 | U = 0; 165 | for (x = 0; x < divr; x ++) { 166 | f->Vertices[0] = o->Vertices + 1; 167 | f->Vertices[1] = v + x; 168 | f->Vertices[2] = v + (x+1==divr ? 0 : x+1); 169 | f->MappingU[0] = U; 170 | f->MappingV[0] = 65535; 171 | f->MappingU[1] = U; 172 | f->MappingV[1] = V; 173 | f->MappingU[2] = U+dU; 174 | f->MappingV[2] = V; 175 | f->Material = m; 176 | f++; 177 | U += dU; 178 | } 179 | plObjCalcNormals(o); 180 | return (o); 181 | } 182 | 183 | pl_Obj *plMakeCylinder(pl_Float r, pl_Float h, pl_uInt divr, pl_Bool captop, 184 | pl_Bool capbottom, pl_Mat *m) { 185 | pl_Obj *o; 186 | pl_Vertex *v, *topverts, *bottomverts, *topcapvert=0, *bottomcapvert=0; 187 | pl_Face *f; 188 | pl_uInt32 i; 189 | double a, da; 190 | if (divr < 3) divr = 3; 191 | o = plObjCreate(divr*2+((divr==3)?0:(captop?1:0)+(capbottom?1:0)), 192 | divr*2+(divr==3 ? (captop ? 1 : 0) + (capbottom ? 1 : 0) : 193 | (captop ? divr : 0) + (capbottom ? divr : 0))); 194 | if (!o) return 0; 195 | a = 0.0; 196 | da = (2.0*PL_PI)/divr; 197 | v = o->Vertices; 198 | topverts = v; 199 | for (i = 0; i < divr; i ++) { 200 | v->y = h/2.0f; 201 | v->x = (pl_Float) (r*cos((double) a)); 202 | v->z = (pl_Float)(r*sin(a)); 203 | v->xformedx = (pl_Float) (32768.0 + (32768.0*cos((double) a))); // temp 204 | v->xformedy = (pl_Float) (32768.0 + (32768.0*sin((double) a))); // use xf 205 | v++; 206 | a += da; 207 | } 208 | bottomverts = v; 209 | a = 0.0; 210 | for (i = 0; i < divr; i ++) { 211 | v->y = -h/2.0f; 212 | v->x = (pl_Float) (r*cos((double) a)); 213 | v->z = (pl_Float) (r*sin(a)); 214 | v->xformedx = (pl_Float) (32768.0 + (32768.0*cos((double) a))); 215 | v->xformedy = (pl_Float) (32768.0 + (32768.0*sin((double) a))); 216 | v++; a += da; 217 | } 218 | if (captop && divr != 3) { 219 | topcapvert = v; 220 | v->y = h / 2.0f; 221 | v->x = v->z = 0.0f; 222 | v++; 223 | } 224 | if (capbottom && divr != 3) { 225 | bottomcapvert = v; 226 | v->y = -h / 2.0f; 227 | v->x = v->z = 0.0f; 228 | v++; 229 | } 230 | f = o->Faces; 231 | for (i = 0; i < divr; i ++) { 232 | f->Vertices[0] = bottomverts + i; 233 | f->Vertices[1] = topverts + i; 234 | f->Vertices[2] = bottomverts + (i == divr-1 ? 0 : i+1); 235 | f->MappingV[0] = f->MappingV[2] = 65535; f->MappingV[1] = 0; 236 | f->MappingU[0] = f->MappingU[1] = (i<<16)/divr; 237 | f->MappingU[2] = ((i+1)<<16)/divr; 238 | f->Material = m; f++; 239 | f->Vertices[0] = bottomverts + (i == divr-1 ? 0 : i+1); 240 | f->Vertices[1] = topverts + i; 241 | f->Vertices[2] = topverts + (i == divr-1 ? 0 : i+1); 242 | f->MappingV[1] = f->MappingV[2] = 0; f->MappingV[0] = 65535; 243 | f->MappingU[0] = f->MappingU[2] = ((i+1)<<16)/divr; 244 | f->MappingU[1] = (i<<16)/divr; 245 | f->Material = m; f++; 246 | } 247 | if (captop) { 248 | if (divr == 3) { 249 | f->Vertices[0] = topverts + 0; 250 | f->Vertices[1] = topverts + 2; 251 | f->Vertices[2] = topverts + 1; 252 | f->MappingU[0] = (pl_sInt32) topverts[0].xformedx; 253 | f->MappingV[0] = (pl_sInt32) topverts[0].xformedy; 254 | f->MappingU[1] = (pl_sInt32) topverts[1].xformedx; 255 | f->MappingV[1] = (pl_sInt32) topverts[1].xformedy; 256 | f->MappingU[2] = (pl_sInt32) topverts[2].xformedx; 257 | f->MappingV[2] = (pl_sInt32) topverts[2].xformedy; 258 | f->Material = m; f++; 259 | } else { 260 | for (i = 0; i < divr; i ++) { 261 | f->Vertices[0] = topverts + (i == divr-1 ? 0 : i + 1); 262 | f->Vertices[1] = topverts + i; 263 | f->Vertices[2] = topcapvert; 264 | f->MappingU[0] = (pl_sInt32) topverts[(i==divr-1?0:i+1)].xformedx; 265 | f->MappingV[0] = (pl_sInt32) topverts[(i==divr-1?0:i+1)].xformedy; 266 | f->MappingU[1] = (pl_sInt32) topverts[i].xformedx; 267 | f->MappingV[1] = (pl_sInt32) topverts[i].xformedy; 268 | f->MappingU[2] = f->MappingV[2] = 32768; 269 | f->Material = m; f++; 270 | } 271 | } 272 | } 273 | if (capbottom) { 274 | if (divr == 3) { 275 | f->Vertices[0] = bottomverts + 0; 276 | f->Vertices[1] = bottomverts + 1; 277 | f->Vertices[2] = bottomverts + 2; 278 | f->MappingU[0] = (pl_sInt32) bottomverts[0].xformedx; 279 | f->MappingV[0] = (pl_sInt32) bottomverts[0].xformedy; 280 | f->MappingU[1] = (pl_sInt32) bottomverts[1].xformedx; 281 | f->MappingV[1] = (pl_sInt32) bottomverts[1].xformedy; 282 | f->MappingU[2] = (pl_sInt32) bottomverts[2].xformedx; 283 | f->MappingV[2] = (pl_sInt32) bottomverts[2].xformedy; 284 | f->Material = m; f++; 285 | } else { 286 | for (i = 0; i < divr; i ++) { 287 | f->Vertices[0] = bottomverts + i; 288 | f->Vertices[1] = bottomverts + (i == divr-1 ? 0 : i + 1); 289 | f->Vertices[2] = bottomcapvert; 290 | f->MappingU[0] = (pl_sInt32) bottomverts[i].xformedx; 291 | f->MappingV[0] = (pl_sInt32) bottomverts[i].xformedy; 292 | f->MappingU[1] = (pl_sInt32) bottomverts[(i==divr-1?0:i+1)].xformedx; 293 | f->MappingV[1] = (pl_sInt32) bottomverts[(i==divr-1?0:i+1)].xformedy; 294 | f->MappingU[2] = f->MappingV[2] = 32768; 295 | f->Material = m; f++; 296 | } 297 | } 298 | } 299 | plObjCalcNormals(o); 300 | return (o); 301 | } 302 | 303 | pl_Obj *plMakeCone(pl_Float r, pl_Float h, pl_uInt div, 304 | pl_Bool cap, pl_Mat *m) { 305 | pl_Obj *o; 306 | pl_Vertex *v; 307 | pl_Face *f; 308 | pl_uInt32 i; 309 | double a, da; 310 | if (div < 3) div = 3; 311 | o = plObjCreate(div + (div == 3 ? 1 : (cap ? 2 : 1)), 312 | div + (div == 3 ? 1 : (cap ? div : 0))); 313 | if (!o) return 0; 314 | v = o->Vertices; 315 | v->x = v->z = 0; v->y = h/2; 316 | v->xformedx = 1<<15; 317 | v->xformedy = 1<<15; 318 | v++; 319 | a = 0.0; 320 | da = (2.0*PL_PI)/div; 321 | for (i = 1; i <= div; i ++) { 322 | v->y = h/-2.0f; 323 | v->x = (pl_Float) (r*cos((double) a)); 324 | v->z = (pl_Float) (r*sin((double) a)); 325 | v->xformedx = (pl_Float) (32768.0 + (cos((double) a)*32768.0)); 326 | v->xformedy = (pl_Float) (32768.0 + (sin((double) a)*32768.0)); 327 | a += da; 328 | v++; 329 | } 330 | if (cap && div != 3) { 331 | v->y = h / -2.0f; 332 | v->x = v->z = 0.0f; 333 | v->xformedx = (pl_Float) (1<<15); 334 | v->xformedy = (pl_Float) (1<<15); 335 | v++; 336 | } 337 | f = o->Faces; 338 | for (i = 1; i <= div; i ++) { 339 | f->Vertices[0] = o->Vertices; 340 | f->Vertices[1] = o->Vertices + (i == div ? 1 : i + 1); 341 | f->Vertices[2] = o->Vertices + i; 342 | f->MappingU[0] = (pl_sInt32) o->Vertices[0].xformedx; 343 | f->MappingV[0] = (pl_sInt32) o->Vertices[0].xformedy; 344 | f->MappingU[1] = (pl_sInt32) o->Vertices[(i==div?1:i+1)].xformedx; 345 | f->MappingV[1] = (pl_sInt32) o->Vertices[(i==div?1:i+1)].xformedy; 346 | f->MappingU[2] = (pl_sInt32) o->Vertices[i].xformedx; 347 | f->MappingV[2] = (pl_sInt32) o->Vertices[i].xformedy; 348 | f->Material = m; 349 | f++; 350 | } 351 | if (cap) { 352 | if (div == 3) { 353 | f->Vertices[0] = o->Vertices + 1; 354 | f->Vertices[1] = o->Vertices + 2; 355 | f->Vertices[2] = o->Vertices + 3; 356 | f->MappingU[0] = (pl_sInt32) o->Vertices[1].xformedx; 357 | f->MappingV[0] = (pl_sInt32) o->Vertices[1].xformedy; 358 | f->MappingU[1] = (pl_sInt32) o->Vertices[2].xformedx; 359 | f->MappingV[1] = (pl_sInt32) o->Vertices[2].xformedy; 360 | f->MappingU[2] = (pl_sInt32) o->Vertices[3].xformedx; 361 | f->MappingV[2] = (pl_sInt32) o->Vertices[3].xformedy; 362 | f->Material = m; 363 | f++; 364 | } else { 365 | for (i = 1; i <= div; i ++) { 366 | f->Vertices[0] = o->Vertices + div + 1; 367 | f->Vertices[1] = o->Vertices + i; 368 | f->Vertices[2] = o->Vertices + (i==div ? 1 : i+1); 369 | f->MappingU[0] = (pl_sInt32) o->Vertices[div+1].xformedx; 370 | f->MappingV[0] = (pl_sInt32) o->Vertices[div+1].xformedy; 371 | f->MappingU[1] = (pl_sInt32) o->Vertices[i].xformedx; 372 | f->MappingV[1] = (pl_sInt32) o->Vertices[i].xformedy; 373 | f->MappingU[2] = (pl_sInt32) o->Vertices[i==div?1:i+1].xformedx; 374 | f->MappingV[2] = (pl_sInt32) o->Vertices[i==div?1:i+1].xformedy; 375 | f->Material = m; 376 | f++; 377 | } 378 | } 379 | } 380 | plObjCalcNormals(o); 381 | return (o); 382 | } 383 | 384 | static pl_uChar verts[6*6] = { 385 | 0,4,1, 1,4,5, 0,1,2, 3,2,1, 2,3,6, 3,7,6, 386 | 6,7,4, 4,7,5, 1,7,3, 7,1,5, 2,6,0, 4,0,6 387 | }; 388 | static pl_uChar map[24*2*3] = { 389 | 1,0, 1,1, 0,0, 0,0, 1,1, 0,1, 390 | 0,0, 1,0, 0,1, 1,1, 0,1, 1,0, 391 | 0,0, 1,0, 0,1, 1,0, 1,1, 0,1, 392 | 0,0, 1,0, 0,1, 0,1, 1,0, 1,1, 393 | 1,0, 0,1, 0,0, 0,1, 1,0, 1,1, 394 | 1,0, 1,1, 0,0, 0,1, 0,0, 1,1 395 | }; 396 | 397 | 398 | pl_Obj *plMakeBox(pl_Float w, pl_Float d, pl_Float h, pl_Mat *m) { 399 | pl_uChar *mm = map; 400 | pl_uChar *vv = verts; 401 | pl_Obj *o; 402 | pl_Vertex *v; 403 | pl_Face *f; 404 | pl_uInt x; 405 | o = plObjCreate(8,12); 406 | if (!o) return 0; 407 | v = o->Vertices; 408 | v->x = -w/2; v->y = h/2; v->z = d/2; v++; 409 | v->x = w/2; v->y = h/2; v->z = d/2; v++; 410 | v->x = -w/2; v->y = h/2; v->z = -d/2; v++; 411 | v->x = w/2; v->y = h/2; v->z = -d/2; v++; 412 | v->x = -w/2; v->y = -h/2; v->z = d/2; v++; 413 | v->x = w/2; v->y = -h/2; v->z = d/2; v++; 414 | v->x = -w/2; v->y = -h/2; v->z = -d/2; v++; 415 | v->x = w/2; v->y = -h/2; v->z = -d/2; v++; 416 | f = o->Faces; 417 | for (x = 0; x < 12; x ++) { 418 | f->Vertices[0] = o->Vertices + *vv++; 419 | f->Vertices[1] = o->Vertices + *vv++; 420 | f->Vertices[2] = o->Vertices + *vv++; 421 | f->MappingU[0] = (pl_sInt32) ((double)*mm++ * 65535.0); 422 | f->MappingV[0] = (pl_sInt32) ((double)*mm++ * 65535.0); 423 | f->MappingU[1] = (pl_sInt32) ((double)*mm++ * 65535.0); 424 | f->MappingV[1] = (pl_sInt32) ((double)*mm++ * 65535.0); 425 | f->MappingU[2] = (pl_sInt32) ((double)*mm++ * 65535.0); 426 | f->MappingV[2] = (pl_sInt32) ((double)*mm++ * 65535.0); 427 | f->Material = m; 428 | f++; 429 | } 430 | 431 | plObjCalcNormals(o); 432 | return (o); 433 | } 434 | 435 | pl_Obj *plMakePlane(pl_Float w, pl_Float d, pl_uInt res, pl_Mat *m) { 436 | pl_Obj *o; 437 | pl_Vertex *v; 438 | pl_Face *f; 439 | pl_uInt x, y; 440 | o = plObjCreate((res+1)*(res+1),res*res*2); 441 | if (!o) return 0; 442 | v = o->Vertices; 443 | for (y = 0; y <= res; y ++) { 444 | for (x = 0; x <= res; x ++) { 445 | v->y = 0; 446 | v->x = ((x*w)/res) - w/2; 447 | v->z = ((y*d)/res) - d/2; 448 | v++; 449 | } 450 | } 451 | f = o->Faces; 452 | for (y = 0; y < res; y ++) { 453 | for (x = 0; x < res; x ++) { 454 | f->Vertices[0] = o->Vertices + x+(y*(res+1)); 455 | f->MappingU[0] = (x<<16)/res; 456 | f->MappingV[0] = (y<<16)/res; 457 | f->Vertices[2] = o->Vertices + x+1+(y*(res+1)); 458 | f->MappingU[2] = ((x+1)<<16)/res; 459 | f->MappingV[2] = (y<<16)/res; 460 | f->Vertices[1] = o->Vertices + x+((y+1)*(res+1)); 461 | f->MappingU[1] = (x<<16)/res; 462 | f->MappingV[1] = ((y+1)<<16)/res; 463 | f->Material = m; 464 | f++; 465 | f->Vertices[0] = o->Vertices + x+((y+1)*(res+1)); 466 | f->MappingU[0] = (x<<16)/res; 467 | f->MappingV[0] = ((y+1)<<16)/res; 468 | f->Vertices[2] = o->Vertices + x+1+(y*(res+1)); 469 | f->MappingU[2] = ((x+1)<<16)/res; 470 | f->MappingV[2] = (y<<16)/res; 471 | f->Vertices[1] = o->Vertices + x+1+((y+1)*(res+1)); 472 | f->MappingU[1] = ((x+1)<<16)/res; 473 | f->MappingV[1] = ((y+1)<<16)/res; 474 | f->Material = m; 475 | f++; 476 | } 477 | } 478 | plObjCalcNormals(o); 479 | return (o); 480 | } 481 | -------------------------------------------------------------------------------- /source/mat.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Plush Version 1.2 3 | mat.c 4 | Material Control 5 | Copyright (c) 1996-2000, Justin Frankel 6 | ******************************************************************************/ 7 | 8 | #include 9 | 10 | static void _plGenerateSinglePalette(pl_Mat *); 11 | static void _plGeneratePhongPalette(pl_Mat *); 12 | static void _plGenerateTextureEnvPalette(pl_Mat *); 13 | static void _plGenerateTexturePalette(pl_Mat *, pl_Texture *); 14 | static void _plGeneratePhongTexturePalette(pl_Mat *, pl_Texture *); 15 | static void _plGeneratePhongTransparentPalette(pl_Mat *m); 16 | static void _plGenerateTransparentPalette(pl_Mat *); 17 | static void _plSetMaterialPutFace(pl_Mat *m); 18 | static void _plMatSetupTransparent(pl_Mat *m, pl_uChar *pal); 19 | 20 | pl_Mat *plMatCreate() { 21 | pl_Mat *m; 22 | m = (pl_Mat *) malloc(sizeof(pl_Mat)); 23 | if (!m) return 0; 24 | memset(m,0,sizeof(pl_Mat)); 25 | m->EnvScaling = 1.0f; 26 | m->TexScaling = 1.0f; 27 | m->Ambient[0] = m->Ambient[1] = m->Ambient[2] = 0; 28 | m->Diffuse[0] = m->Diffuse[1] = m->Diffuse[2] = 128; 29 | m->Specular[0] = m->Specular[1] = m->Specular[2] = 128; 30 | m->Shininess = 4; 31 | m->NumGradients = 32; 32 | m->FadeDist = 1000.0; 33 | m->zBufferable = 1; 34 | return m; 35 | } 36 | 37 | void plMatDelete(pl_Mat *m) { 38 | if (m) { 39 | if (m->_ReMapTable) free(m->_ReMapTable); 40 | if (m->_RequestedColors) free(m->_RequestedColors); 41 | if (m->_AddTable) free(m->_AddTable); 42 | free(m); 43 | } 44 | } 45 | 46 | void plMatInit(pl_Mat *m) { 47 | if (m->Shininess < 1) m->Shininess = 1; 48 | m->_ft = ((m->Environment ? PL_FILL_ENVIRONMENT : 0) | 49 | (m->Texture ? PL_FILL_TEXTURE : 0)); 50 | m->_st = m->ShadeType; 51 | 52 | if (m->Transparent) m->_ft = PL_FILL_TRANSPARENT; 53 | 54 | if (m->_ft == (PL_FILL_TEXTURE|PL_FILL_ENVIRONMENT)) 55 | m->_st = PL_SHADE_NONE; 56 | 57 | if (m->_ft == PL_FILL_SOLID) { 58 | if (m->_st == PL_SHADE_NONE) _plGenerateSinglePalette(m); 59 | else _plGeneratePhongPalette(m); 60 | } else if (m->_ft == PL_FILL_TEXTURE) { 61 | if (m->_st == PL_SHADE_NONE) 62 | _plGenerateTexturePalette(m,m->Texture); 63 | else _plGeneratePhongTexturePalette(m,m->Texture); 64 | } else if (m->_ft == PL_FILL_ENVIRONMENT) { 65 | if (m->_st == PL_SHADE_NONE) 66 | _plGenerateTexturePalette(m,m->Environment); 67 | else _plGeneratePhongTexturePalette(m,m->Environment); 68 | } else if (m->_ft == (PL_FILL_ENVIRONMENT|PL_FILL_TEXTURE)) 69 | _plGenerateTextureEnvPalette(m); 70 | else if (m->_ft == PL_FILL_TRANSPARENT) { 71 | if (m->_st == PL_SHADE_NONE) _plGenerateTransparentPalette(m); 72 | else _plGeneratePhongTransparentPalette(m); 73 | } 74 | _plSetMaterialPutFace(m); 75 | } 76 | 77 | static void _plMatSetupTransparent(pl_Mat *m, pl_uChar *pal) { 78 | pl_uInt x, intensity; 79 | if (m->Transparent) 80 | { 81 | if (m->_AddTable) free(m->_AddTable); 82 | m->_AddTable = (pl_uInt16 *) malloc(256*sizeof(pl_uInt16)); 83 | for (x = 0; x < 256; x ++) { 84 | intensity = *pal++; 85 | intensity += *pal++; 86 | intensity += *pal++; 87 | m->_AddTable[x] = ((intensity*(m->_ColorsUsed-m->_tsfact))/768); 88 | } 89 | } 90 | } 91 | 92 | void plMatMapToPal(pl_Mat *m, pl_uChar *pal, pl_sInt pstart, pl_sInt pend) { 93 | pl_sInt32 j, r, g, b, bestdiff, r2, g2, b2; 94 | pl_sInt bestpos,k; 95 | pl_uInt32 i; 96 | pl_uChar *p; 97 | if (!m->_RequestedColors) plMatInit(m); 98 | if (!m->_RequestedColors) return; 99 | if (m->_ReMapTable) free(m->_ReMapTable); 100 | m->_ReMapTable = (pl_uChar *) malloc(m->_ColorsUsed); 101 | for (i = 0; i < m->_ColorsUsed; i ++) { 102 | bestdiff = 1000000000; 103 | bestpos = pstart; 104 | r = m->_RequestedColors[i*3]; 105 | g = m->_RequestedColors[i*3+1]; 106 | b = m->_RequestedColors[i*3+2]; 107 | p = pal + pstart*3; 108 | for (k = pstart; k <= (pl_sInt)pend; k ++) { 109 | r2 = p[0] - r; 110 | g2 = p[1] - g; 111 | b2 = p[2] - b; 112 | p += 3; 113 | j = r2*r2+g2*g2+b2*b2; 114 | if (j < bestdiff) { 115 | bestdiff = j; 116 | bestpos = k; 117 | } 118 | } 119 | m->_ReMapTable[i] = bestpos; 120 | } 121 | _plMatSetupTransparent(m,pal); 122 | } 123 | 124 | static void _plGenerateSinglePalette(pl_Mat *m) { 125 | m->_ColorsUsed = 1; 126 | if (m->_RequestedColors) free(m->_RequestedColors); 127 | m->_RequestedColors = (pl_uChar *) malloc(3); 128 | m->_RequestedColors[0] = plMin(plMax(m->Ambient[0],0),255); 129 | m->_RequestedColors[1] = plMin(plMax(m->Ambient[1],0),255); 130 | m->_RequestedColors[2] = plMin(plMax(m->Ambient[2],0),255); 131 | } 132 | 133 | static void _plGeneratePhongPalette(pl_Mat *m) { 134 | pl_uInt i = m->NumGradients, x; 135 | pl_sInt c; 136 | pl_uChar *pal; 137 | double a, da, ca, cb; 138 | m->_ColorsUsed = m->NumGradients; 139 | if (m->_RequestedColors) free(m->_RequestedColors); 140 | pal = m->_RequestedColors = (pl_uChar *) malloc(m->_ColorsUsed*3); 141 | a = PL_PI/2.0; 142 | 143 | if (m->NumGradients > 1) da = -PL_PI/((m->NumGradients-1)<<1); 144 | else da=0.0; 145 | 146 | do { 147 | if (m->NumGradients == 1) ca = 1; 148 | else { 149 | ca = cos((double) a); 150 | a += da; 151 | } 152 | cb = pow((double) ca, (double) m->Shininess); 153 | for (x = 0; x < 3; x ++) { 154 | c = (pl_sInt) ((cb*m->Specular[x])+(ca*m->Diffuse[x])+m->Ambient[x]); 155 | *(pal++) = plMax(0,plMin(c,255)); 156 | } 157 | } while (--i); 158 | } 159 | 160 | static void _plGenerateTextureEnvPalette(pl_Mat *m) { 161 | pl_sInt c; 162 | pl_uInt whichlevel,whichindex; 163 | pl_uChar *texpal, *envpal, *pal; 164 | m->_ColorsUsed = m->Texture->NumColors*m->Environment->NumColors; 165 | if (m->_RequestedColors) free(m->_RequestedColors); 166 | pal = m->_RequestedColors = (pl_uChar *) malloc(m->_ColorsUsed*3); 167 | envpal = m->Environment->PaletteData; 168 | if (m->_AddTable) free(m->_AddTable); 169 | m->_AddTable = (pl_uInt16 *) malloc(m->Environment->NumColors*sizeof(pl_uInt16)); 170 | for (whichlevel = 0; whichlevel < m->Environment->NumColors; whichlevel++) { 171 | texpal = m->Texture->PaletteData; 172 | switch (m->TexEnvMode) 173 | { 174 | case PL_TEXENV_MUL: // multiply 175 | for (whichindex = 0; whichindex < m->Texture->NumColors; whichindex++) { 176 | *pal++ = (pl_uChar) (((pl_sInt) (*texpal++) * (pl_sInt) envpal[0])>>8); 177 | *pal++ = (pl_uChar) (((pl_sInt) (*texpal++) * (pl_sInt) envpal[1])>>8); 178 | *pal++ = (pl_uChar) (((pl_sInt) (*texpal++) * (pl_sInt) envpal[2])>>8); 179 | } 180 | break; 181 | case PL_TEXENV_AVG: // average 182 | for (whichindex = 0; whichindex < m->Texture->NumColors; whichindex++) { 183 | *pal++ = (pl_uChar) (((pl_sInt) (*texpal++) + (pl_sInt) envpal[0])>>1); 184 | *pal++ = (pl_uChar) (((pl_sInt) (*texpal++) + (pl_sInt) envpal[1])>>1); 185 | *pal++ = (pl_uChar) (((pl_sInt) (*texpal++) + (pl_sInt) envpal[2])>>1); 186 | } 187 | break; 188 | case PL_TEXENV_TEXMINUSENV: // tex-env 189 | for (whichindex = 0; whichindex < m->Texture->NumColors; whichindex++) { 190 | c = (pl_sInt) (*texpal++) - (pl_sInt) envpal[0]; *pal++ = plMax(0,plMin(255,c)); 191 | c = (pl_sInt) (*texpal++) - (pl_sInt) envpal[1]; *pal++ = plMax(0,plMin(255,c)); 192 | c = (pl_sInt) (*texpal++) - (pl_sInt) envpal[2]; *pal++ = plMax(0,plMin(255,c)); 193 | } 194 | break; 195 | case PL_TEXENV_ENVMINUSTEX: // env-tex 196 | for (whichindex = 0; whichindex < m->Texture->NumColors; whichindex++) { 197 | c = -(pl_sInt) (*texpal++) - (pl_sInt) envpal[0]; *pal++ = plMax(0,plMin(255,c)); 198 | c = -(pl_sInt) (*texpal++) - (pl_sInt) envpal[1]; *pal++ = plMax(0,plMin(255,c)); 199 | c = -(pl_sInt) (*texpal++) - (pl_sInt) envpal[2]; *pal++ = plMax(0,plMin(255,c)); 200 | } 201 | break; 202 | case PL_TEXENV_MIN: 203 | for (whichindex = 0; whichindex < m->Texture->NumColors; whichindex++) { 204 | *pal++ = plMin(texpal[0],envpal[0]); 205 | *pal++ = plMin(texpal[1],envpal[1]); 206 | *pal++ = plMin(texpal[2],envpal[2]); 207 | texpal+=3; 208 | } 209 | break; 210 | case PL_TEXENV_MAX: 211 | for (whichindex = 0; whichindex < m->Texture->NumColors; whichindex++) { 212 | *pal++ = plMax(texpal[0],envpal[0]); 213 | *pal++ = plMax(texpal[1],envpal[1]); 214 | *pal++ = plMax(texpal[2],envpal[2]); 215 | texpal+=3; 216 | } 217 | break; 218 | default: // add 219 | for (whichindex = 0; whichindex < m->Texture->NumColors; whichindex++) { 220 | c = (pl_sInt) (*texpal++) + (pl_sInt) envpal[0]; *pal++ = plMax(0,plMin(255,c)); 221 | c = (pl_sInt) (*texpal++) + (pl_sInt) envpal[1]; *pal++ = plMax(0,plMin(255,c)); 222 | c = (pl_sInt) (*texpal++) + (pl_sInt) envpal[2]; *pal++ = plMax(0,plMin(255,c)); 223 | } 224 | break; 225 | } 226 | envpal += 3; 227 | m->_AddTable[whichlevel] = whichlevel*m->Texture->NumColors; 228 | } 229 | } 230 | 231 | static void _plGenerateTexturePalette(pl_Mat *m, pl_Texture *t) { 232 | pl_uChar *ppal, *pal; 233 | pl_sInt c, i, x; 234 | m->_ColorsUsed = t->NumColors; 235 | if (m->_RequestedColors) free(m->_RequestedColors); 236 | pal = m->_RequestedColors = (pl_uChar *) malloc(m->_ColorsUsed*3); 237 | ppal = t->PaletteData; 238 | i = t->NumColors; 239 | do { 240 | for (x = 0; x < 3; x ++) { 241 | c = m->Ambient[x] + *ppal++; 242 | *(pal++) = plMax(0,plMin(c,255)); 243 | } 244 | } while (--i); 245 | } 246 | 247 | static void _plGeneratePhongTexturePalette(pl_Mat *m, pl_Texture *t) { 248 | double a, ca, da, cb; 249 | pl_uInt16 *addtable; 250 | pl_uChar *ppal, *pal; 251 | pl_sInt c, i, i2, x; 252 | pl_uInt num_shades; 253 | 254 | if (t->NumColors) num_shades = (m->NumGradients / t->NumColors); 255 | else num_shades=1; 256 | 257 | if (!num_shades) num_shades = 1; 258 | m->_ColorsUsed = num_shades*t->NumColors; 259 | if (m->_RequestedColors) free(m->_RequestedColors); 260 | pal = m->_RequestedColors = (pl_uChar *) malloc(m->_ColorsUsed*3); 261 | a = PL_PI/2.0; 262 | if (num_shades>1) da = (-PL_PI/2.0)/(num_shades-1); 263 | else da=0.0; 264 | i2 = num_shades; 265 | do { 266 | ppal = t->PaletteData; 267 | ca = cos((double) a); 268 | a += da; 269 | cb = pow(ca, (double) m->Shininess); 270 | i = t->NumColors; 271 | do { 272 | for (x = 0; x < 3; x ++) { 273 | c = (pl_sInt) ((cb*m->Specular[x])+(ca*m->Diffuse[x])+m->Ambient[x] + *ppal++); 274 | *(pal++) = plMax(0,plMin(c,255)); 275 | } 276 | } while (--i); 277 | } while (--i2); 278 | ca = 0; 279 | if (m->_AddTable) free(m->_AddTable); 280 | m->_AddTable = (pl_uInt16 *) malloc(256*sizeof(pl_uInt16)); 281 | addtable = m->_AddTable; 282 | i = 256; 283 | do { 284 | a = sin(ca) * num_shades; 285 | ca += PL_PI/512.0; 286 | *addtable++ = ((pl_sInt) a)*t->NumColors; 287 | } while (--i); 288 | } 289 | 290 | static void _plGeneratePhongTransparentPalette(pl_Mat *m) { 291 | m->_tsfact = (pl_sInt) (m->NumGradients*(1.0/(1+m->Transparent))); 292 | _plGeneratePhongPalette(m); 293 | } 294 | 295 | static void _plGenerateTransparentPalette(pl_Mat *m) { 296 | m->_tsfact = 0; 297 | _plGeneratePhongPalette(m); 298 | } 299 | 300 | static void _plSetMaterialPutFace(pl_Mat *m) { 301 | m->_PutFace = 0; 302 | switch (m->_ft) { 303 | case PL_FILL_TRANSPARENT: switch(m->_st) { 304 | case PL_SHADE_NONE: case PL_SHADE_FLAT: 305 | case PL_SHADE_FLAT_DISTANCE: case PL_SHADE_FLAT_DISTANCE|PL_SHADE_FLAT: 306 | m->_PutFace = plPF_TransF; 307 | break; 308 | case PL_SHADE_GOURAUD: case PL_SHADE_GOURAUD_DISTANCE: 309 | case PL_SHADE_GOURAUD|PL_SHADE_GOURAUD_DISTANCE: 310 | m->_PutFace = plPF_TransG; 311 | break; 312 | } 313 | break; 314 | case PL_FILL_SOLID: switch(m->_st) { 315 | case PL_SHADE_NONE: case PL_SHADE_FLAT: 316 | case PL_SHADE_FLAT_DISTANCE: case PL_SHADE_FLAT_DISTANCE|PL_SHADE_FLAT: 317 | m->_PutFace = plPF_SolidF; 318 | break; 319 | case PL_SHADE_GOURAUD: case PL_SHADE_GOURAUD_DISTANCE: 320 | case PL_SHADE_GOURAUD|PL_SHADE_GOURAUD_DISTANCE: 321 | m->_PutFace = plPF_SolidG; 322 | break; 323 | } 324 | break; 325 | case PL_FILL_ENVIRONMENT: 326 | case PL_FILL_TEXTURE: 327 | if (m->PerspectiveCorrect) switch (m->_st) { 328 | case PL_SHADE_NONE: case PL_SHADE_FLAT: 329 | case PL_SHADE_FLAT_DISTANCE: case PL_SHADE_FLAT_DISTANCE|PL_SHADE_FLAT: 330 | m->_PutFace = plPF_PTexF; 331 | break; 332 | case PL_SHADE_GOURAUD: case PL_SHADE_GOURAUD_DISTANCE: 333 | case PL_SHADE_GOURAUD|PL_SHADE_GOURAUD_DISTANCE: 334 | m->_PutFace = plPF_PTexG; 335 | break; 336 | } 337 | else switch (m->_st) { 338 | case PL_SHADE_NONE: case PL_SHADE_FLAT: 339 | case PL_SHADE_FLAT_DISTANCE: case PL_SHADE_FLAT_DISTANCE|PL_SHADE_FLAT: 340 | m->_PutFace = plPF_TexF; 341 | break; 342 | case PL_SHADE_GOURAUD: case PL_SHADE_GOURAUD_DISTANCE: 343 | case PL_SHADE_GOURAUD|PL_SHADE_GOURAUD_DISTANCE: 344 | m->_PutFace = plPF_TexG; 345 | break; 346 | } 347 | break; 348 | case PL_FILL_TEXTURE|PL_FILL_ENVIRONMENT: 349 | m->_PutFace = plPF_TexEnv; 350 | break; 351 | } 352 | } 353 | 354 | typedef struct __ct { 355 | pl_uChar r,g,b; 356 | pl_Bool visited; 357 | struct __ct *next; 358 | } _ct; 359 | 360 | static int mdist(_ct *a, _ct *b) { 361 | return ((a->r-b->r)*(a->r-b->r)+(a->g-b->g)*(a->g-b->g)+(a->b-b->b)*(a->b-b->b)); 362 | } 363 | 364 | void plMatMakeOptPal(pl_uChar *p, pl_sInt pstart, 365 | pl_sInt pend, pl_Mat **materials, pl_sInt nmats) { 366 | pl_uChar *allColors = 0; 367 | pl_sInt numColors = 0, nc, x; 368 | pl_sInt len = pend + 1 - pstart; 369 | pl_sInt32 current, newnext, bestdist, thisdist; 370 | _ct *colorBlock, *best, *cp; 371 | 372 | for (x = 0; x < nmats; x ++) { 373 | if (materials[x]) { 374 | if (!materials[x]->_RequestedColors) plMatInit(materials[x]); 375 | if (materials[x]->_RequestedColors) numColors+=materials[x]->_ColorsUsed; 376 | } 377 | } 378 | if (!numColors) return; 379 | 380 | allColors=(pl_uChar*)malloc(numColors*3); 381 | numColors=0; 382 | 383 | for (x = 0; x < nmats; x ++) { 384 | if (materials[x]) { 385 | if (materials[x]->_RequestedColors) 386 | memcpy(allColors + (numColors*3), materials[x]->_RequestedColors, 387 | materials[x]->_ColorsUsed*3); 388 | numColors += materials[x]->_ColorsUsed; 389 | } 390 | } 391 | 392 | if (numColors <= len) { 393 | memcpy(p+pstart*3,allColors,numColors*3); 394 | free(allColors); 395 | return; 396 | } 397 | 398 | colorBlock = (_ct *) malloc(sizeof(_ct)*numColors); 399 | for (x = 0; x < numColors; x++) { 400 | colorBlock[x].r = allColors[x*3]; 401 | colorBlock[x].g = allColors[x*3+1]; 402 | colorBlock[x].b = allColors[x*3+2]; 403 | colorBlock[x].visited = 0; 404 | colorBlock[x].next = 0; 405 | } 406 | free(allColors); 407 | 408 | /* Build a list, starting at color 0 */ 409 | current = 0; 410 | nc = numColors; 411 | do { 412 | newnext = -1; 413 | bestdist = 300000000; 414 | colorBlock[current].visited = 1; 415 | for (x = 0; x < nc; x ++) { 416 | if (!colorBlock[x].visited) { 417 | thisdist = mdist(colorBlock + x, colorBlock + current); 418 | if (thisdist < 5) { colorBlock[x].visited = 1; numColors--; } 419 | else if (thisdist < bestdist) { bestdist = thisdist; newnext = x; } 420 | } 421 | } 422 | if (newnext != -1) { 423 | colorBlock[current].next = colorBlock + newnext; 424 | current = newnext; 425 | } 426 | } while (newnext != -1); 427 | colorBlock[current].next = 0; /* terminate the list */ 428 | 429 | /* we now have a linked list starting at colorBlock, which is each one and 430 | it's closest neighbor */ 431 | 432 | while (numColors > len) { 433 | bestdist = mdist(colorBlock,colorBlock->next); 434 | for (best = cp = colorBlock; cp->next; cp = cp->next) { 435 | if (bestdist > (thisdist = mdist(cp,cp->next))) { 436 | best = cp; 437 | bestdist = thisdist; 438 | } 439 | } 440 | best->r = ((int) best->r + (int) best->next->r)>>1; 441 | best->g = ((int) best->g + (int) best->next->g)>>1; 442 | best->b = ((int) best->b + (int) best->next->b)>>1; 443 | best->next = best->next->next; 444 | numColors--; 445 | } 446 | x = pstart*3; 447 | for (cp = colorBlock; cp; cp = cp->next) { 448 | p[x++] = cp->r; 449 | p[x++] = cp->g; 450 | p[x++] = cp->b; 451 | } 452 | free(colorBlock); 453 | } 454 | -------------------------------------------------------------------------------- /source/math.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Plush Version 1.2 3 | math.c 4 | Math and Matrix Control 5 | Copyright (c) 1996-2000, Justin Frankel 6 | ******************************************************************************/ 7 | 8 | #include 9 | 10 | void plMatrixRotate(pl_Float matrix[], pl_uChar m, pl_Float Deg) { 11 | pl_uChar m1, m2; 12 | double c,s; 13 | double d= Deg * PL_PI / 180.0; 14 | memset(matrix,0,sizeof(pl_Float)*16); 15 | matrix[((m-1)<<2)+m-1] = matrix[15] = 1.0; 16 | m1 = (m % 3); 17 | m2 = ((m1+1) % 3); 18 | c = cos(d); s = sin(d); 19 | matrix[(m1<<2)+m1]=(pl_Float)c; matrix[(m1<<2)+m2]=(pl_Float)s; 20 | matrix[(m2<<2)+m2]=(pl_Float)c; matrix[(m2<<2)+m1]=(pl_Float)-s; 21 | } 22 | 23 | void plMatrixTranslate(pl_Float m[], pl_Float x, pl_Float y, pl_Float z) { 24 | memset(m,0,sizeof(pl_Float)*16); 25 | m[0] = m[4+1] = m[8+2] = m[12+3] = 1.0; 26 | m[0+3] = x; m[4+3] = y; m[8+3] = z; 27 | } 28 | 29 | void plMatrixMultiply(pl_Float *dest, pl_Float src[]) { 30 | pl_Float temp[16]; 31 | pl_uInt i; 32 | memcpy(temp,dest,sizeof(pl_Float)*16); 33 | for (i = 0; i < 16; i += 4) { 34 | *dest++ = src[i+0]*temp[(0<<2)+0]+src[i+1]*temp[(1<<2)+0]+ 35 | src[i+2]*temp[(2<<2)+0]+src[i+3]*temp[(3<<2)+0]; 36 | *dest++ = src[i+0]*temp[(0<<2)+1]+src[i+1]*temp[(1<<2)+1]+ 37 | src[i+2]*temp[(2<<2)+1]+src[i+3]*temp[(3<<2)+1]; 38 | *dest++ = src[i+0]*temp[(0<<2)+2]+src[i+1]*temp[(1<<2)+2]+ 39 | src[i+2]*temp[(2<<2)+2]+src[i+3]*temp[(3<<2)+2]; 40 | *dest++ = src[i+0]*temp[(0<<2)+3]+src[i+1]*temp[(1<<2)+3]+ 41 | src[i+2]*temp[(2<<2)+3]+src[i+3]*temp[(3<<2)+3]; 42 | } 43 | } 44 | 45 | void plMatrixApply(pl_Float *m, pl_Float x, pl_Float y, pl_Float z, 46 | pl_Float *outx, pl_Float *outy, pl_Float *outz) { 47 | *outx = x*m[0] + y*m[1] + z*m[2] + m[3]; 48 | *outy = x*m[4] + y*m[5] + z*m[6] + m[7]; 49 | *outz = x*m[8] + y*m[9] + z*m[10] + m[11]; 50 | } 51 | 52 | pl_Float plDotProduct(pl_Float x1, pl_Float y1, pl_Float z1, 53 | pl_Float x2, pl_Float y2, pl_Float z2) { 54 | return ((x1*x2)+(y1*y2)+(z1*z2)); 55 | } 56 | 57 | void plNormalizeVector(pl_Float *x, pl_Float *y, pl_Float *z) { 58 | double length; 59 | length = (*x)*(*x)+(*y)*(*y)+(*z)*(*z); 60 | if (length > 0.0000000001) { 61 | pl_Float t = (pl_Float)sqrt(length); 62 | *x /= t; 63 | *y /= t; 64 | *z /= t; 65 | } else *x = *y = *z = 0.0; 66 | } 67 | 68 | -------------------------------------------------------------------------------- /source/obj.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Plush Version 1.2 3 | obj.c 4 | Object control 5 | Copyright (c) 1996-2000, Justin Frankel 6 | ******************************************************************************/ 7 | 8 | #include 9 | 10 | pl_Obj *plObjScale(pl_Obj *o, pl_Float s) { 11 | pl_uInt32 i = o->NumVertices; 12 | pl_Vertex *v = o->Vertices; 13 | while (i--) { 14 | v->x *= s; v->y *= s; v->z *= s; v++; 15 | } 16 | for (i = 0; i < PL_MAX_CHILDREN; i ++) 17 | if (o->Children[i]) plObjScale(o->Children[i],s); 18 | return o; 19 | } 20 | 21 | pl_Obj *plObjStretch(pl_Obj *o, pl_Float x, pl_Float y, pl_Float z) { 22 | pl_uInt32 i = o->NumVertices; 23 | pl_Vertex *v = o->Vertices; 24 | while (i--) { 25 | v->x *= x; v->y *= y; v->z *= z; v++; 26 | } 27 | for (i = 0; i < PL_MAX_CHILDREN; i ++) 28 | if (o->Children[i]) plObjStretch(o->Children[i],x,y,z); 29 | return o; 30 | } 31 | 32 | pl_Obj *plObjTranslate(pl_Obj *o, pl_Float x, pl_Float y, pl_Float z) { 33 | pl_uInt32 i = o->NumVertices; 34 | pl_Vertex *v = o->Vertices; 35 | while (i--) { 36 | v->x += x; v->y += y; v->z += z; v++; 37 | } 38 | return o; 39 | } 40 | 41 | pl_Obj *plObjFlipNormals(pl_Obj *o) { 42 | pl_uInt32 i = o->NumVertices; 43 | pl_Vertex *v = o->Vertices; 44 | pl_Face *f = o->Faces; 45 | while (i--) { 46 | v->nx = - v->nx; v->ny = - v->ny; v->nz = - v->nz; v++; 47 | } 48 | i = o->NumFaces; 49 | while (i--) { 50 | f->nx = - f->nx; f->ny = - f->ny; f->nz = - f->nz; 51 | f++; 52 | } 53 | for (i = 0; i < PL_MAX_CHILDREN; i ++) 54 | if (o->Children[i]) plObjFlipNormals(o->Children[i]); 55 | return o; 56 | } 57 | 58 | void plObjDelete(pl_Obj *o) { 59 | pl_uInt i; 60 | if (o) { 61 | for (i = 0; i < PL_MAX_CHILDREN; i ++) 62 | if (o->Children[i]) plObjDelete(o->Children[i]); 63 | if (o->Vertices) free(o->Vertices); 64 | if (o->Faces) free(o->Faces); 65 | free(o); 66 | } 67 | } 68 | 69 | pl_Obj *plObjCreate(pl_uInt32 nv, pl_uInt32 nf) { 70 | pl_Obj *o; 71 | if (!(o = (pl_Obj *) malloc(sizeof(pl_Obj)))) return 0; 72 | memset(o,0,sizeof(pl_Obj)); 73 | o->GenMatrix = 1; 74 | o->BackfaceCull = 1; 75 | o->NumVertices = nv; 76 | o->NumFaces = nf; 77 | if (nv && !(o->Vertices=(pl_Vertex *) malloc(sizeof(pl_Vertex)*nv))) { 78 | free(o); 79 | return 0; 80 | } 81 | if (nf && !(o->Faces = (pl_Face *) malloc(sizeof(pl_Face)*nf))) { 82 | free(o->Vertices); 83 | free(o); 84 | return 0; 85 | } 86 | memset(o->Vertices,0,sizeof(pl_Vertex)*nv); 87 | memset(o->Faces,0,sizeof(pl_Face)*nf); 88 | return o; 89 | } 90 | 91 | pl_Obj *plObjClone(pl_Obj *o) { 92 | pl_Face *iff, *of; 93 | pl_uInt32 i; 94 | pl_Obj *out; 95 | if (!(out = plObjCreate(o->NumVertices,o->NumFaces))) return 0; 96 | for (i = 0; i < PL_MAX_CHILDREN; i ++) 97 | if (o->Children[i]) out->Children[i] = plObjClone(o->Children[i]); 98 | out->Xa = o->Xa; out->Ya = o->Ya; out->Za = o->Za; 99 | out->Xp = o->Xp; out->Yp = o->Yp; out->Zp = o->Zp; 100 | out->BackfaceCull = o->BackfaceCull; 101 | out->BackfaceIllumination = o->BackfaceIllumination; 102 | out->GenMatrix = o->GenMatrix; 103 | memcpy(out->Vertices, o->Vertices, sizeof(pl_Vertex) * o->NumVertices); 104 | iff = o->Faces; 105 | of = out->Faces; 106 | i = out->NumFaces; 107 | while (i--) { 108 | of->Vertices[0] = (pl_Vertex *) 109 | out->Vertices + (iff->Vertices[0] - o->Vertices); 110 | of->Vertices[1] = (pl_Vertex *) 111 | out->Vertices + (iff->Vertices[1] - o->Vertices); 112 | of->Vertices[2] = (pl_Vertex *) 113 | out->Vertices + (iff->Vertices[2] - o->Vertices); 114 | of->MappingU[0] = iff->MappingU[0]; 115 | of->MappingV[0] = iff->MappingV[0]; 116 | of->MappingU[1] = iff->MappingU[1]; 117 | of->MappingV[1] = iff->MappingV[1]; 118 | of->MappingU[2] = iff->MappingU[2]; 119 | of->MappingV[2] = iff->MappingV[2]; 120 | of->nx = iff->nx; 121 | of->ny = iff->ny; 122 | of->nz = iff->nz; 123 | of->Material = iff->Material; 124 | of++; 125 | iff++; 126 | } 127 | return out; 128 | } 129 | 130 | void plObjSetMat(pl_Obj *o, pl_Mat *m, pl_Bool th) { 131 | pl_sInt32 i = o->NumFaces; 132 | pl_Face *f = o->Faces; 133 | while (i--) (f++)->Material = m; 134 | if (th) for (i = 0; i < PL_MAX_CHILDREN; i++) 135 | if (o->Children[i]) plObjSetMat(o->Children[i],m,th); 136 | } 137 | 138 | void plObjCalcNormals(pl_Obj *obj) { 139 | pl_uInt32 i; 140 | pl_Vertex *v = obj->Vertices; 141 | pl_Face *f = obj->Faces; 142 | double x1, x2, y1, y2, z1, z2; 143 | i = obj->NumVertices; 144 | while (i--) { 145 | v->nx = 0.0; v->ny = 0.0; v->nz = 0.0; 146 | v++; 147 | } 148 | i = obj->NumFaces; 149 | while (i--) { 150 | x1 = f->Vertices[0]->x-f->Vertices[1]->x; 151 | x2 = f->Vertices[0]->x-f->Vertices[2]->x; 152 | y1 = f->Vertices[0]->y-f->Vertices[1]->y; 153 | y2 = f->Vertices[0]->y-f->Vertices[2]->y; 154 | z1 = f->Vertices[0]->z-f->Vertices[1]->z; 155 | z2 = f->Vertices[0]->z-f->Vertices[2]->z; 156 | f->nx = (pl_Float) (y1*z2 - z1*y2); 157 | f->ny = (pl_Float) (z1*x2 - x1*z2); 158 | f->nz = (pl_Float) (x1*y2 - y1*x2); 159 | plNormalizeVector(&f->nx, &f->ny, &f->nz); 160 | f->Vertices[0]->nx += f->nx; 161 | f->Vertices[0]->ny += f->ny; 162 | f->Vertices[0]->nz += f->nz; 163 | f->Vertices[1]->nx += f->nx; 164 | f->Vertices[1]->ny += f->ny; 165 | f->Vertices[1]->nz += f->nz; 166 | f->Vertices[2]->nx += f->nx; 167 | f->Vertices[2]->ny += f->ny; 168 | f->Vertices[2]->nz += f->nz; 169 | f++; 170 | } 171 | v = obj->Vertices; 172 | i = obj->NumVertices; 173 | do { 174 | plNormalizeVector(&v->nx, &v->ny, &v->nz); 175 | v++; 176 | } while (--i); 177 | for (i = 0; i < PL_MAX_CHILDREN; i ++) 178 | if (obj->Children[i]) plObjCalcNormals(obj->Children[i]); 179 | } 180 | -------------------------------------------------------------------------------- /source/pf_ptex.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Plush Version 1.2 3 | pf_ptex.c 4 | Perspective Correct Texture Mapping Rasterizers 5 | Copyright (c) 1996-2000, Justin Frankel 6 | ******************************************************************************/ 7 | 8 | #include 9 | #include "putface.h" 10 | 11 | void plPF_PTexF(pl_Cam *cam, pl_Face *TriFace) { 12 | pl_uChar i0, i1, i2; 13 | pl_uChar *gmem = cam->frameBuffer; 14 | pl_uChar *remap = TriFace->Material->_ReMapTable; 15 | pl_ZBuffer *zbuf = cam->zBuffer; 16 | pl_Float MappingU1, MappingU2, MappingU3; 17 | pl_Float MappingV1, MappingV2, MappingV3; 18 | pl_sInt32 MappingU_AND, MappingV_AND; 19 | pl_uChar *texture; 20 | pl_uChar vshift; 21 | pl_uInt16 bc; 22 | pl_Texture *Texture; 23 | pl_sInt32 iShade; 24 | 25 | pl_uChar nm, nmb; 26 | pl_sInt n; 27 | pl_Float U1,V1,U2,V2,dU1=0,dU2=0,dV1=0,dV2=0,dUL=0,dVL=0,UL,VL; 28 | pl_sInt32 iUL, iVL, idUL=0, idVL=0, iULnext, iVLnext; 29 | 30 | pl_sInt32 scrwidth = cam->ScreenWidth; 31 | pl_sInt32 X1, X2, dX1=0, dX2=0, XL1, Xlen; 32 | pl_ZBuffer Z1, dZ1=0, dZ2=0, Z2, dZL=0, ZL, pZL, pdZL; 33 | pl_sInt32 Y1, Y2, Y0, dY; 34 | pl_uChar stat; 35 | 36 | pl_Bool zb = (zbuf&&TriFace->Material->zBufferable) ? 1 : 0; 37 | 38 | if (TriFace->Material->Environment) Texture = TriFace->Material->Environment; 39 | else Texture = TriFace->Material->Texture; 40 | 41 | if (!Texture) return; 42 | texture = Texture->Data; 43 | iShade = (pl_sInt32)(TriFace->fShade*256.0); 44 | if (iShade < 0) iShade=0; 45 | if (iShade > 255) iShade=255; 46 | 47 | if (!TriFace->Material->_AddTable) bc=0; 48 | else bc = TriFace->Material->_AddTable[iShade]; 49 | nm = TriFace->Material->PerspectiveCorrect; 50 | nmb = 0; while (nm) { nmb++; nm >>= 1; } 51 | nmb = plMin(6,nmb); 52 | nm = 1<Height)-1)<Width; 54 | MappingU_AND = (1<Width)-1; 55 | vshift = 16 - Texture->Width; 56 | 57 | if (TriFace->Material->Environment) { 58 | PUTFACE_SORT_ENV(); 59 | } else { 60 | PUTFACE_SORT_TEX(); 61 | } 62 | 63 | MappingU1 *= TriFace->Scrz[i0]/65536.0f; 64 | MappingV1 *= TriFace->Scrz[i0]/65536.0f; 65 | MappingU2 *= TriFace->Scrz[i1]/65536.0f; 66 | MappingV2 *= TriFace->Scrz[i1]/65536.0f; 67 | MappingU3 *= TriFace->Scrz[i2]/65536.0f; 68 | MappingV3 *= TriFace->Scrz[i2]/65536.0f; 69 | 70 | U1 = U2 = MappingU1; 71 | V1 = V2 = MappingV1; 72 | X2 = X1 = TriFace->Scrx[i0]; 73 | Z2 = Z1 = TriFace->Scrz[i0]; 74 | Y0 = (TriFace->Scry[i0]+(1<<19))>>20; 75 | Y1 = (TriFace->Scry[i1]+(1<<19))>>20; 76 | Y2 = (TriFace->Scry[i2]+(1<<19))>>20; 77 | 78 | dY = Y2-Y0; 79 | if (dY) { 80 | dX2 = (TriFace->Scrx[i2] - X1) / dY; 81 | dZ2 = (TriFace->Scrz[i2] - Z1) / dY; 82 | dU2 = (MappingU3 - U1) / dY; 83 | dV2 = (MappingV3 - V1) / dY; 84 | } 85 | dY = Y1-Y0; 86 | if (dY) { 87 | dX1 = (TriFace->Scrx[i1] - X1) / dY; 88 | dZ1 = (TriFace->Scrz[i1] - Z1) / dY; 89 | dU1 = (MappingU2 - U1) / dY; 90 | dV1 = (MappingV2 - V1) / dY; 91 | if (dX2 < dX1) { 92 | XL1 = dX2; dX2 = dX1; dX1 = XL1; 93 | dUL = dU1; dU1 = dU2; dU2 = dUL; 94 | dVL = dV1; dV1 = dV2; dV2 = dVL; 95 | dZL = dZ1; dZ1 = dZ2; dZ2 = dZL; 96 | stat = 2; 97 | } else stat = 1; 98 | } else { 99 | if (TriFace->Scrx[i1] > X1) { 100 | X2 = TriFace->Scrx[i1]; 101 | Z2 = TriFace->Scrz[i1]; 102 | U2 = MappingU2; 103 | V2 = MappingV2; 104 | stat = 2|4; 105 | } else { 106 | X1 = TriFace->Scrx[i1]; 107 | Z1 = TriFace->Scrz[i1]; 108 | U1 = MappingU2; 109 | V1 = MappingV2; 110 | stat = 1|8; 111 | } 112 | } 113 | 114 | gmem += (Y0 * cam->ScreenWidth); 115 | zbuf += (Y0 * cam->ScreenWidth); 116 | 117 | XL1 = ((dX1-dX2)*dY+(1<<19))>>20; 118 | if (XL1) { 119 | dUL = ((dU1-dU2)*dY)/XL1; 120 | dVL = ((dV1-dV2)*dY)/XL1; 121 | dZL = ((dZ1-dZ2)*dY)/XL1; 122 | } else { 123 | XL1 = ((X2-X1+(1<<19))>>20); 124 | if (XL1) { 125 | dUL = (U2-U1)/XL1; 126 | dVL = (V2-V1)/XL1; 127 | dZL = (Z2-Z1)/XL1; 128 | } 129 | } 130 | 131 | pdZL = dZL * nm; 132 | dUL *= nm; 133 | dVL *= nm; 134 | 135 | while (Y0 < Y2) { 136 | if (Y0 == Y1) { 137 | dY = Y2-((TriFace->Scry[i1]+(1<<19))>>20); 138 | if (dY) { 139 | if (stat & 1) { 140 | X1 = TriFace->Scrx[i1]; 141 | dX1 = (TriFace->Scrx[i2]-TriFace->Scrx[i1])/dY; 142 | } 143 | if (stat & 2) { 144 | X2 = TriFace->Scrx[i1]; 145 | dX2 = (TriFace->Scrx[i2]-TriFace->Scrx[i1])/dY; 146 | } 147 | if (stat & 4) { 148 | X1 = TriFace->Scrx[i0]; 149 | dX1 = (TriFace->Scrx[i2]-TriFace->Scrx[i0])/dY; 150 | } 151 | if (stat & 8) { 152 | X2 = TriFace->Scrx[i0]; 153 | dX2 = (TriFace->Scrx[i2]-TriFace->Scrx[i0])/dY; 154 | } 155 | dZ1 = (TriFace->Scrz[i2]-Z1)/dY; 156 | dV1 = (MappingV3 - V1) / dY; 157 | dU1 = (MappingU3 - U1) / dY; 158 | } 159 | } 160 | XL1 = (X1+(1<<19))>>20; 161 | Xlen = ((X2+(1<<19))>>20) - XL1; 162 | if (Xlen > 0) { 163 | pl_Float t; 164 | pZL = ZL = Z1; 165 | UL = U1; 166 | VL = V1; 167 | gmem += XL1; 168 | zbuf += XL1; 169 | XL1 += Xlen-scrwidth; 170 | t = 65536.0f/ZL; 171 | iUL = iULnext = ((pl_sInt32) (UL*t)); 172 | iVL = iVLnext = ((pl_sInt32) (VL*t)); 173 | do { 174 | UL += dUL; 175 | VL += dVL; 176 | iUL = iULnext; 177 | iVL = iVLnext; 178 | pZL += pdZL; 179 | t = 65536.0f/pZL; 180 | iULnext = ((pl_sInt32) (UL*t)); 181 | iVLnext = ((pl_sInt32) (VL*t)); 182 | idUL = (iULnext - iUL)>>nmb; 183 | idVL = (iVLnext - iVL)>>nmb; 184 | n = nm; 185 | Xlen -= n; 186 | if (Xlen < 0) n += Xlen; 187 | if (zb) do { 188 | if (*zbuf < ZL) { 189 | *zbuf = ZL; 190 | *gmem = remap[bc + texture[((iUL>>16)&MappingU_AND) + 191 | ((iVL>>vshift)&MappingV_AND)]]; 192 | } 193 | zbuf++; 194 | gmem++; 195 | ZL += dZL; 196 | iUL += idUL; 197 | iVL += idVL; 198 | } while (--n); 199 | else do { 200 | *gmem++ = remap[bc + texture[((iUL>>16)&MappingU_AND) + 201 | ((iVL>>vshift)&MappingV_AND)]]; 202 | iUL += idUL; 203 | iVL += idVL; 204 | } while (--n); 205 | } while (Xlen > 0); 206 | gmem -= XL1; 207 | zbuf -= XL1; 208 | } else { 209 | zbuf += cam->ScreenWidth; 210 | gmem += cam->ScreenWidth; 211 | } 212 | Z1 += dZ1; 213 | U1 += dU1; 214 | V1 += dV1; 215 | X1 += dX1; 216 | X2 += dX2; 217 | Y0++; 218 | } 219 | } 220 | 221 | void plPF_PTexG(pl_Cam *cam, pl_Face *TriFace) { 222 | pl_uChar i0, i1, i2; 223 | pl_Float MappingU1, MappingU2, MappingU3; 224 | pl_Float MappingV1, MappingV2, MappingV3; 225 | 226 | pl_Texture *Texture; 227 | pl_Bool zb = (cam->zBuffer&&TriFace->Material->zBufferable) ? 1 : 0; 228 | 229 | pl_uChar nm, nmb; 230 | pl_uInt n; 231 | pl_sInt32 MappingU_AND, MappingV_AND; 232 | pl_uChar vshift; 233 | pl_uChar *texture; 234 | pl_uInt16 *addtable; 235 | pl_uChar *remap = TriFace->Material->_ReMapTable; 236 | pl_sInt32 iUL, iVL, idUL, idVL, iULnext, iVLnext; 237 | pl_Float U2,V2,dU2=0,dV2=0,dUL=0,dVL=0,UL,VL; 238 | pl_sInt32 XL1, Xlen; 239 | pl_sInt32 C2, dC2=0, CL, dCL=0; 240 | pl_Float ZL, Z2, dZ2=0, dZL=0, pdZL, pZL; 241 | 242 | pl_sInt32 Y2, dY; 243 | pl_uChar stat; 244 | 245 | /* Cache line */ 246 | pl_sInt32 Y0,Y1; 247 | pl_sInt32 C1, dC1=0, X2, dX2=0, X1, dX1=0; 248 | 249 | /* Cache line */ 250 | pl_Float dU1=0, U1, dZ1=0, Z1, V1, dV1=0; 251 | pl_sInt32 scrwidth = cam->ScreenWidth; 252 | pl_uChar *gmem = cam->frameBuffer; 253 | pl_ZBuffer *zbuf = cam->zBuffer; 254 | 255 | if (TriFace->Material->Environment) Texture = TriFace->Material->Environment; 256 | else Texture = TriFace->Material->Texture; 257 | 258 | if (!Texture) return; 259 | texture = Texture->Data; 260 | addtable = TriFace->Material->_AddTable; 261 | if (!addtable) return; 262 | 263 | nm = TriFace->Material->PerspectiveCorrect; 264 | nmb = 0; while (nm) { nmb++; nm >>= 1; } 265 | nmb = plMin(6,nmb); 266 | nm = 1<Height)-1)<Width; 268 | MappingU_AND = (1<Width)-1; 269 | vshift = 16 - Texture->Width; 270 | 271 | if (TriFace->Material->Environment) { 272 | PUTFACE_SORT_ENV(); 273 | } else { 274 | PUTFACE_SORT_TEX(); 275 | } 276 | 277 | MappingU1 *= TriFace->Scrz[i0]/65536.0f; 278 | MappingV1 *= TriFace->Scrz[i0]/65536.0f; 279 | MappingU2 *= TriFace->Scrz[i1]/65536.0f; 280 | MappingV2 *= TriFace->Scrz[i1]/65536.0f; 281 | MappingU3 *= TriFace->Scrz[i2]/65536.0f; 282 | MappingV3 *= TriFace->Scrz[i2]/65536.0f; 283 | TriFace->Shades[0] *= 65536.0f; 284 | TriFace->Shades[1] *= 65536.0f; 285 | TriFace->Shades[2] *= 65536.0f; 286 | 287 | C1 = C2 = (pl_sInt32) TriFace->Shades[i0]; 288 | U1 = U2 = MappingU1; 289 | V1 = V2 = MappingV1; 290 | X2 = X1 = TriFace->Scrx[i0]; 291 | Z2 = Z1 = TriFace->Scrz[i0]; 292 | Y0 = (TriFace->Scry[i0]+(1<<19))>>20; 293 | Y1 = (TriFace->Scry[i1]+(1<<19))>>20; 294 | Y2 = (TriFace->Scry[i2]+(1<<19))>>20; 295 | 296 | dY = Y2-Y0; 297 | if (dY) { 298 | dX2 = (TriFace->Scrx[i2] - X1) / dY; 299 | dZ2 = (TriFace->Scrz[i2] - Z1) / dY; 300 | dC2 = (pl_sInt32) ((TriFace->Shades[i2] - C1) / dY); 301 | dU2 = (MappingU3 - U1) / dY; 302 | dV2 = (MappingV3 - V1) / dY; 303 | } 304 | dY = Y1-Y0; 305 | if (dY) { 306 | dX1 = (TriFace->Scrx[i1] - X1) / dY; 307 | dZ1 = (TriFace->Scrz[i1] - Z1) / dY; 308 | dC1 = (pl_sInt32) ((TriFace->Shades[i1] - C1) / dY); 309 | dU1 = (MappingU2 - U1) / dY; 310 | dV1 = (MappingV2 - V1) / dY; 311 | if (dX2 < dX1) { 312 | dX2 ^= dX1; dX1 ^= dX2; dX2 ^= dX1; 313 | dUL = dU1; dU1 = dU2; dU2 = dUL; 314 | dVL = dV1; dV1 = dV2; dV2 = dVL; 315 | dZL = dZ1; dZ1 = dZ2; dZ2 = dZL; 316 | dCL = dC1; dC1 = dC2; dC2 = dCL; 317 | stat = 2; 318 | } else stat = 1; 319 | } else { 320 | if (TriFace->Scrx[i1] > X1) { 321 | X2 = TriFace->Scrx[i1]; 322 | Z2 = TriFace->Scrz[i1]; 323 | C2 = (pl_sInt32)TriFace->Shades[i1]; 324 | U2 = MappingU2; 325 | V2 = MappingV2; 326 | stat = 2|4; 327 | } else { 328 | X1 = TriFace->Scrx[i1]; 329 | Z1 = TriFace->Scrz[i1]; 330 | C1 = (pl_sInt32)TriFace->Shades[i1]; 331 | U1 = MappingU2; 332 | V1 = MappingV2; 333 | stat = 1|8; 334 | } 335 | } 336 | 337 | gmem += (Y0 * scrwidth); 338 | zbuf += (Y0 * scrwidth); 339 | 340 | XL1 = (((dX1-dX2)*dY+(1<<19))>>20); 341 | if (XL1) { 342 | dUL = ((dU1-dU2)*dY)/XL1; 343 | dVL = ((dV1-dV2)*dY)/XL1; 344 | dZL = ((dZ1-dZ2)*dY)/XL1; 345 | dCL = ((dC1-dC2)*dY)/XL1; 346 | } else { 347 | XL1 = ((X2-X1+(1<<19))>>20); 348 | if (XL1) { 349 | dUL = (U2-U1)/XL1; 350 | dVL = (V2-V1)/XL1; 351 | dZL = (Z2-Z1)/XL1; 352 | dCL = (C2-C1)/XL1; 353 | } 354 | } 355 | 356 | pdZL = dZL * nm; 357 | dUL *= nm; 358 | dVL *= nm; 359 | Y1 -= Y0; 360 | Y0 = Y2-Y0; 361 | while (Y0--) { 362 | if (!Y1--) { 363 | dY = Y2-((TriFace->Scry[i1]+(1<<19))>>20); 364 | if (dY) { 365 | if (stat & 1) { 366 | X1 = TriFace->Scrx[i1]; 367 | dX1 = (TriFace->Scrx[i2]-TriFace->Scrx[i1])/dY; 368 | } 369 | if (stat & 2) { 370 | X2 = TriFace->Scrx[i1]; 371 | dX2 = (TriFace->Scrx[i2]-TriFace->Scrx[i1])/dY; 372 | } 373 | if (stat & 4) { 374 | X1 = TriFace->Scrx[i0]; 375 | dX1 = (TriFace->Scrx[i2]-TriFace->Scrx[i0])/dY; 376 | } 377 | if (stat & 8) { 378 | X2 = TriFace->Scrx[i0]; 379 | dX2 = (TriFace->Scrx[i2]-TriFace->Scrx[i0])/dY; 380 | } 381 | dZ1 = (TriFace->Scrz[i2]-Z1)/dY; 382 | dC1 = (pl_sInt32)((TriFace->Shades[i2]-C1)/dY); 383 | dV1 = (MappingV3 - V1) / dY; 384 | dU1 = (MappingU3 - U1) / dY; 385 | } 386 | } 387 | XL1 = (X1+(1<<19))>>20; 388 | Xlen = ((X2+(1<<19))>>20) - XL1; 389 | if (Xlen > 0) { 390 | pl_Float t; 391 | CL = C1; 392 | pZL = ZL = Z1; 393 | UL = U1; 394 | VL = V1; 395 | gmem += XL1; 396 | zbuf += XL1; 397 | XL1 += Xlen-scrwidth; 398 | t = 65536.0f / ZL; 399 | iUL = iULnext = ((pl_sInt32) (UL*t)); 400 | iVL = iVLnext = ((pl_sInt32) (VL*t)); 401 | do { 402 | UL += dUL; 403 | VL += dVL; 404 | iUL = iULnext; 405 | iVL = iVLnext; 406 | pZL += pdZL; 407 | t = 65536.0f/pZL; 408 | iULnext = ((pl_sInt32) (UL*t)); 409 | iVLnext = ((pl_sInt32) (VL*t)); 410 | idUL = (iULnext - iUL)>>nmb; 411 | idVL = (iVLnext - iVL)>>nmb; 412 | n = nm; 413 | Xlen -= n; 414 | if (Xlen < 0) n += Xlen; 415 | if (zb) do { 416 | if (*zbuf < ZL) { 417 | int av; 418 | if (CL < 0) av=addtable[0]; 419 | else if (CL > (255<<8)) av=addtable[255]; 420 | else av=addtable[CL>>8]; 421 | *zbuf = ZL; 422 | *gmem = remap[av + 423 | texture[((iUL>>16)&MappingU_AND) + 424 | ((iVL>>vshift)&MappingV_AND)]]; 425 | } 426 | zbuf++; 427 | gmem++; 428 | ZL += dZL; 429 | CL += dCL; 430 | iUL += idUL; 431 | iVL += idVL; 432 | } while (--n); 433 | else do { 434 | int av; 435 | if (CL < 0) av=addtable[0]; 436 | else if (CL > (255<<8)) av=addtable[255]; 437 | else av=addtable[CL>>8]; 438 | *gmem++ = remap[av + 439 | texture[((iUL>>16)&MappingU_AND) + 440 | ((iVL>>vshift)&MappingV_AND)]]; 441 | CL += dCL; 442 | iUL += idUL; 443 | iVL += idVL; 444 | } while (--n); 445 | } while (Xlen > 0); 446 | gmem -= XL1; 447 | zbuf -= XL1; 448 | } else { 449 | zbuf += scrwidth; 450 | gmem += scrwidth; 451 | } 452 | Z1 += dZ1; 453 | U1 += dU1; 454 | V1 += dV1; 455 | X1 += dX1; 456 | X2 += dX2; 457 | C1 += dC1; 458 | } 459 | } 460 | -------------------------------------------------------------------------------- /source/pf_solid.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Plush Version 1.2 3 | pf_solid.c 4 | Solid Rasterizers 5 | Copyright (c) 1996-2000, Justin Frankel 6 | ******************************************************************************/ 7 | 8 | #include 9 | #include "putface.h" 10 | 11 | void plPF_SolidF(pl_Cam *cam, pl_Face *TriFace) { 12 | pl_uChar i0, i1, i2; 13 | 14 | pl_uChar *gmem = cam->frameBuffer; 15 | pl_ZBuffer *zbuf = cam->zBuffer; 16 | 17 | pl_sInt32 X1, X2, dX1=0, dX2=0, XL1, XL2; 18 | pl_ZBuffer dZL=0, dZ1=0, dZ2=0, Z1, ZL, Z2, Z3; 19 | pl_sInt32 Y1, Y2, Y0, dY; 20 | pl_uChar stat; 21 | pl_Bool zb = (zbuf&&TriFace->Material->zBufferable) ? 1 : 0; 22 | pl_uChar bc; 23 | pl_sInt32 shade; 24 | 25 | PUTFACE_SORT(); 26 | 27 | shade=(pl_sInt32) (TriFace->fShade*(TriFace->Material->_ColorsUsed-1)); 28 | if (shade < 0) shade=0; 29 | if (shade > (pl_sInt32) TriFace->Material->_ColorsUsed-1) shade=TriFace->Material->_ColorsUsed-1; 30 | bc=TriFace->Material->_ReMapTable[shade]; 31 | 32 | X2 = X1 = TriFace->Scrx[i0]; 33 | Z1 = TriFace->Scrz[i0]; 34 | Z2 = TriFace->Scrz[i1]; 35 | Z3 = TriFace->Scrz[i2]; 36 | Y0 = (TriFace->Scry[i0]+(1<<19)) >> 20; 37 | Y1 = (TriFace->Scry[i1]+(1<<19)) >> 20; 38 | Y2 = (TriFace->Scry[i2]+(1<<19)) >> 20; 39 | 40 | dY = Y2-Y0; 41 | if (dY) { 42 | dX2 = (TriFace->Scrx[i2] - X1) / dY; 43 | dZ2 = (Z3 - Z1) / dY; 44 | } 45 | dY = Y1-Y0; 46 | if (dY) { 47 | dX1 = (TriFace->Scrx[i1] - X1) / dY; 48 | dZ1 = (Z2 - Z1) / dY; 49 | if (dX2 < dX1) { 50 | dX2 ^= dX1; dX1 ^= dX2; dX2 ^= dX1; 51 | dZL = dZ1; dZ1 = dZ2; dZ2 = dZL; 52 | stat = 2; 53 | } else stat = 1; 54 | Z2 = Z1; 55 | } else { 56 | if (TriFace->Scrx[i1] > X1) { 57 | X2 = TriFace->Scrx[i1]; 58 | stat = 2|4; 59 | } else { 60 | X1 = TriFace->Scrx[i1]; 61 | ZL = Z1; Z1 = Z2; Z2 = ZL; 62 | stat = 1|8; 63 | } 64 | } 65 | 66 | if (zb) { 67 | XL1 = ((dX1-dX2)*dY+(1<<19))>>20; 68 | if (XL1) dZL = ((dZ1-dZ2)*dY)/XL1; 69 | else { 70 | XL1 = (X2-X1+(1<<19))>>20; 71 | if (zb && XL1) dZL = (Z2-Z1)/XL1; 72 | else dZL = 0.0; 73 | } 74 | } 75 | 76 | gmem += (Y0 * cam->ScreenWidth); 77 | zbuf += (Y0 * cam->ScreenWidth); 78 | 79 | while (Y0 < Y2) { 80 | if (Y0 == Y1) { 81 | dY = Y2 - ((TriFace->Scry[i1]+(1<<19))>>20); 82 | if (dY) { 83 | if (stat & 1) { 84 | X1 = TriFace->Scrx[i1]; 85 | dX1 = (TriFace->Scrx[i2]-TriFace->Scrx[i1])/dY; 86 | } 87 | if (stat & 2) { 88 | X2 = TriFace->Scrx[i1]; 89 | dX2 = (TriFace->Scrx[i2]-TriFace->Scrx[i1])/dY; 90 | } 91 | if (stat & 4) { 92 | X1 = TriFace->Scrx[i0]; 93 | dX1 = (TriFace->Scrx[i2]-TriFace->Scrx[i0])/dY; 94 | } 95 | if (stat & 8) { 96 | X2 = TriFace->Scrx[i0]; 97 | dX2 = (TriFace->Scrx[i2]-TriFace->Scrx[i0])/dY; 98 | } 99 | dZ1 = (Z3-Z1)/dY; 100 | } 101 | } 102 | XL1 = (X1+(1<<19))>>20; 103 | XL2 = (X2+(1<<19))>>20; 104 | ZL = Z1; 105 | XL2 -= XL1; 106 | if (XL2 > 0) { 107 | zbuf += XL1; 108 | gmem += XL1; 109 | XL1 += XL2; 110 | if (zb) do { 111 | if (*zbuf < ZL) { 112 | *zbuf = ZL; 113 | *gmem = bc; 114 | } 115 | gmem++; 116 | zbuf++; 117 | ZL += dZL; 118 | } while (--XL2); 119 | else do *gmem++ = bc; while (--XL2); 120 | gmem -= XL1; 121 | zbuf -= XL1; 122 | } 123 | gmem += cam->ScreenWidth; 124 | zbuf += cam->ScreenWidth; 125 | Z1 += dZ1; 126 | X1 += dX1; 127 | X2 += dX2; 128 | Y0++; 129 | } 130 | } 131 | 132 | void plPF_SolidG(pl_Cam *cam, pl_Face *TriFace) { 133 | pl_uChar i0, i1, i2; 134 | pl_uChar *gmem = cam->frameBuffer; 135 | pl_uChar *remap = TriFace->Material->_ReMapTable; 136 | pl_ZBuffer *zbuf = cam->zBuffer; 137 | pl_ZBuffer dZL=0, dZ1=0, dZ2=0, Z1, Z2, ZL, Z3; 138 | pl_sInt32 dX1=0, dX2=0, X1, X2, XL1, XL2; 139 | pl_sInt32 C1, C2, dC1=0, dC2=0, dCL=0, CL, C3; 140 | pl_sInt32 Y1, Y2, Y0, dY; 141 | pl_uChar stat; 142 | pl_Bool zb = (zbuf&&TriFace->Material->zBufferable) ? 1 : 0; 143 | 144 | pl_Float nc = (TriFace->Material->_ColorsUsed-1)*65536.0f; 145 | pl_sInt32 maxColor=((TriFace->Material->_ColorsUsed-1)<<16); 146 | pl_sInt32 maxColorNonShift=TriFace->Material->_ColorsUsed-1; 147 | 148 | PUTFACE_SORT(); 149 | 150 | 151 | C1 = (pl_sInt32) (TriFace->Shades[i0]*nc); 152 | C2 = (pl_sInt32) (TriFace->Shades[i1]*nc); 153 | C3 = (pl_sInt32) (TriFace->Shades[i2]*nc); 154 | X2 = X1 = TriFace->Scrx[i0]; 155 | Z1 = TriFace->Scrz[i0]; 156 | Z2 = TriFace->Scrz[i1]; 157 | Z3 = TriFace->Scrz[i2]; 158 | 159 | Y0 = (TriFace->Scry[i0]+(1<<19))>>20; 160 | Y1 = (TriFace->Scry[i1]+(1<<19))>>20; 161 | Y2 = (TriFace->Scry[i2]+(1<<19))>>20; 162 | 163 | dY = Y2 - Y0; 164 | if (dY) { 165 | dX2 = (TriFace->Scrx[i2] - X1) / dY; 166 | dC2 = (C3 - C1) / dY; 167 | dZ2 = (Z3 - Z1) / dY; 168 | } 169 | dY = Y1 - Y0; 170 | if (dY) { 171 | dX1 = (TriFace->Scrx[i1] - X1) / dY; 172 | dC1 = (C2 - C1) / dY; 173 | dZ1 = (Z2 - Z1) / dY; 174 | if (dX2 < dX1) { 175 | dX2 ^= dX1; dX1 ^= dX2; dX2 ^= dX1; 176 | dC2 ^= dC1; dC1 ^= dC2; dC2 ^= dC1; 177 | dZL = dZ1; dZ1 = dZ2; dZ2 = dZL; 178 | stat = 2; 179 | } else stat = 1; 180 | Z2 = Z1; 181 | C2 = C1; 182 | } else { 183 | if (TriFace->Scrx[i1] > X1) { 184 | X2 = TriFace->Scrx[i1]; 185 | stat = 2|4; 186 | } else { 187 | X1 = C1; C1 = C2; C2 = X1; 188 | ZL = Z1; Z1 = Z2; Z2 = ZL; 189 | X1 = TriFace->Scrx[i1]; 190 | stat = 1|8; 191 | } 192 | } 193 | 194 | gmem += (Y0 * cam->ScreenWidth); 195 | zbuf += (Y0 * cam->ScreenWidth); 196 | 197 | XL1 = (((dX1-dX2)*dY+(1<<19))>>20); 198 | if (XL1) { 199 | dCL = ((dC1-dC2)*dY)/XL1; 200 | dZL = ((dZ1-dZ2)*dY)/XL1; 201 | } else { 202 | XL1 = ((X2-X1+(1<<19))>>20); 203 | if (XL1) { 204 | dCL = (C2-C1)/XL1; 205 | dZL = (Z2-Z1)/XL1; 206 | } 207 | } 208 | 209 | while (Y0 < Y2) { 210 | if (Y0 == Y1) { 211 | dY = Y2 - ((TriFace->Scry[i1]+(1<<19))>>20); 212 | if (dY) { 213 | dZ1 = (Z3-Z1)/dY; 214 | dC1 = (C3-C1) / dY; 215 | if (stat & 1) { 216 | X1 = TriFace->Scrx[i1]; 217 | dX1 = (TriFace->Scrx[i2]-TriFace->Scrx[i1])/dY; 218 | } 219 | if (stat & 2) { 220 | X2 = TriFace->Scrx[i1]; 221 | dX2 = (TriFace->Scrx[i2]-TriFace->Scrx[i1])/dY; 222 | } 223 | if (stat & 4) { 224 | X1 = TriFace->Scrx[i0]; 225 | dX1 = (TriFace->Scrx[i2]-TriFace->Scrx[i0])/dY; 226 | } 227 | if (stat & 8) { 228 | X2 = TriFace->Scrx[i0]; 229 | dX2 = (TriFace->Scrx[i2]-TriFace->Scrx[i0])/dY; 230 | } 231 | } 232 | } 233 | CL = C1; 234 | XL1 = (X1+(1<<19))>>20; 235 | XL2 = (X2+(1<<19))>>20; 236 | ZL = Z1; 237 | XL2 -= XL1; 238 | if (XL2 > 0) { 239 | gmem += XL1; 240 | zbuf += XL1; 241 | XL1 += XL2; 242 | if (zb) do { 243 | if (*zbuf < ZL) { 244 | *zbuf = ZL; 245 | if (CL >= maxColor) *gmem=remap[maxColorNonShift]; 246 | else if (CL > 0) *gmem = remap[CL>>16]; 247 | else *gmem = remap[0]; 248 | } 249 | gmem++; 250 | zbuf++; 251 | ZL += dZL; 252 | CL += dCL; 253 | } while (--XL2); 254 | else do { 255 | if (CL >= maxColor) *gmem++=remap[maxColorNonShift]; 256 | else if (CL > 0) *gmem++ = remap[CL>>16]; 257 | else *gmem++ = remap[0]; 258 | CL += dCL; 259 | } while (--XL2); 260 | gmem -= XL1; 261 | zbuf -= XL1; 262 | } 263 | gmem += cam->ScreenWidth; 264 | zbuf += cam->ScreenWidth; 265 | X1 += dX1; 266 | X2 += dX2; 267 | C1 += dC1; 268 | Z1 += dZ1; 269 | Y0++; 270 | } 271 | } 272 | -------------------------------------------------------------------------------- /source/pf_trans.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Plush Version 1.2 3 | pf_trans.c 4 | Solid Translucent Rasterizers 5 | Copyright (c) 1996-2000, Justin Frankel 6 | ******************************************************************************/ 7 | 8 | #include 9 | #include "putface.h" 10 | 11 | void plPF_TransF(pl_Cam *cam, pl_Face *TriFace) { 12 | pl_uChar i0, i1, i2; 13 | pl_uChar *gmem = cam->frameBuffer; 14 | pl_uChar *remap = TriFace->Material->_ReMapTable; 15 | pl_ZBuffer *zbuf = cam->zBuffer; 16 | pl_sInt32 X1, X2, dX1=0, dX2=0, XL1, XL2; 17 | pl_ZBuffer Z1, ZL, dZ1=0, dZL=0, dZ2=0, Z2; 18 | pl_sInt32 Y1, Y2, Y0, dY; 19 | pl_uInt16 *lookuptable = TriFace->Material->_AddTable; 20 | pl_uChar stat; 21 | pl_sInt32 bc = (pl_sInt32) TriFace->fShade*TriFace->Material->_tsfact; 22 | pl_Bool zb = (zbuf&&TriFace->Material->zBufferable) ? 1 : 0; 23 | 24 | PUTFACE_SORT(); 25 | 26 | if (bc < 0) bc=0; 27 | if (bc > (pl_sInt32) TriFace->Material->_tsfact-1) bc=TriFace->Material->_tsfact-1; 28 | remap+=bc; 29 | 30 | X2 = X1 = TriFace->Scrx[i0]; 31 | Z2 = Z1 = TriFace->Scrz[i0]; 32 | Y0 = (TriFace->Scry[i0]+(1<<19))>>20; 33 | Y1 = (TriFace->Scry[i1]+(1<<19))>>20; 34 | Y2 = (TriFace->Scry[i2]+(1<<19))>>20; 35 | 36 | dY = Y2 - Y0; 37 | if (dY) { 38 | dX2 = (TriFace->Scrx[i2] - X1) / dY; 39 | dZ2 = (TriFace->Scrz[i2] - Z1) / dY; 40 | } 41 | dY = Y1-Y0; 42 | if (dY) { 43 | dX1 = (TriFace->Scrx[i1] - X1) / dY; 44 | dZ1 = (TriFace->Scrz[i1] - Z1) / dY; 45 | if (dX2 < dX1) { 46 | dX2 ^= dX1; dX1 ^= dX2; dX2 ^= dX1; 47 | dZL = dZ1; dZ1 = dZ2; dZ2 = dZL; 48 | stat = 2; 49 | } else stat = 1; 50 | } else { 51 | if (TriFace->Scrx[i1] > X1) { 52 | X2 = TriFace->Scrx[i1]; 53 | Z2 = TriFace->Scrz[i1]; 54 | stat= 2|4; 55 | } else { 56 | X1 = TriFace->Scrx[i1]; 57 | Z1 = TriFace->Scrz[i1]; 58 | stat= 1|8; 59 | } 60 | } 61 | 62 | gmem += (Y0 * cam->ScreenWidth); 63 | zbuf += (Y0 * cam->ScreenWidth); 64 | if (zb) { 65 | XL1 = (((dX1-dX2)*dY+(1<<19))>>20); 66 | if (XL1) dZL = ((dZ1-dZ2)*dY)/XL1; 67 | else { 68 | XL1 = ((X2-X1+(1<<19))>>20); 69 | if (XL1) dZL = (Z2-Z1)/XL1; 70 | } 71 | } 72 | 73 | while (Y0 < Y2) { 74 | if (Y0 == Y1) { 75 | dY = Y2 - ((TriFace->Scry[i1]+(1<<19))>>20); 76 | if (dY) { 77 | if (stat & 1) { 78 | X1 = TriFace->Scrx[i1]; 79 | dX1 = (TriFace->Scrx[i2]-TriFace->Scrx[i1])/dY; 80 | } 81 | if (stat & 2) { 82 | X2 = TriFace->Scrx[i1]; 83 | dX2 = (TriFace->Scrx[i2]-TriFace->Scrx[i1])/dY; 84 | } 85 | if (stat & 4) { 86 | X1 = TriFace->Scrx[i0]; 87 | dX1 = (TriFace->Scrx[i2]-TriFace->Scrx[i0])/dY; 88 | } 89 | if (stat & 8) { 90 | X2 = TriFace->Scrx[i0]; 91 | dX2 = (TriFace->Scrx[i2]-TriFace->Scrx[i0])/dY; 92 | } 93 | dZ1 = (TriFace->Scrz[i2]- Z1)/dY; 94 | } 95 | } 96 | XL1 = (X1+(1<<19))>>20; 97 | XL2 = (X2+(1<<19))>>20; 98 | ZL = Z1; 99 | if ((XL2-XL1) > 0) { 100 | XL2 -= XL1; 101 | zbuf += XL1; 102 | gmem += XL1; 103 | XL1 += XL2; 104 | if (zb) do { 105 | if (*zbuf < ZL) { 106 | *zbuf = ZL; 107 | *gmem = remap[lookuptable[*gmem]]; 108 | } 109 | gmem++; 110 | zbuf++; 111 | ZL += dZL; 112 | } while (--XL2); 113 | else do *gmem++ = remap[lookuptable[*gmem]]; while (--XL2); 114 | gmem -= XL1; 115 | zbuf -= XL1; 116 | } 117 | gmem += cam->ScreenWidth; 118 | zbuf += cam->ScreenWidth; 119 | Z1 += dZ1; 120 | X1 += dX1; 121 | X2 += dX2; 122 | Y0 ++; 123 | } 124 | } 125 | 126 | void plPF_TransG(pl_Cam *cam, pl_Face *TriFace) { 127 | pl_uChar i0, i1, i2; 128 | pl_uChar *gmem = cam->frameBuffer; 129 | pl_uChar *remap = TriFace->Material->_ReMapTable; 130 | pl_ZBuffer *zbuf = cam->zBuffer; 131 | pl_sInt32 X1, X2, dX1=0, dX2=0, XL1, XL2; 132 | pl_ZBuffer Z1, ZL, dZ1=0, dZL=0, dZ2=0, Z2; 133 | pl_sInt32 dC1=0, dCL=0, CL, C1, C2, dC2=0; 134 | pl_sInt32 Y1, Y2, Y0, dY; 135 | pl_Float nc = (TriFace->Material->_tsfact*65536.0f); 136 | pl_uInt16 *lookuptable = TriFace->Material->_AddTable; 137 | pl_Bool zb = (zbuf&&TriFace->Material->zBufferable) ? 1 : 0; 138 | pl_uChar stat; 139 | 140 | pl_sInt32 maxColor=((TriFace->Material->_tsfact-1)<<16); 141 | pl_sInt32 maxColorNonShift=TriFace->Material->_tsfact-1; 142 | 143 | PUTFACE_SORT(); 144 | 145 | C1 = C2 = (pl_sInt32) (TriFace->Shades[i0]*nc); 146 | X2 = X1 = TriFace->Scrx[i0]; 147 | Z2 = Z1 = TriFace->Scrz[i0]; 148 | Y0 = (TriFace->Scry[i0]+(1<<19))>>20; 149 | Y1 = (TriFace->Scry[i1]+(1<<19))>>20; 150 | Y2 = (TriFace->Scry[i2]+(1<<19))>>20; 151 | 152 | dY = Y2 - Y0; 153 | if (dY) { 154 | dX2 = (TriFace->Scrx[i2] - X1) / dY; 155 | dC2 = (pl_sInt32) ((TriFace->Shades[i2]*nc - C1) / dY); 156 | dZ2 = (TriFace->Scrz[i2] - Z1) / dY; 157 | } 158 | dY = Y1-Y0; 159 | if (dY) { 160 | dX1 = (TriFace->Scrx[i1] - X1) / dY; 161 | dZ1 = (TriFace->Scrz[i1] - Z1) / dY; 162 | dC1 = (pl_sInt32) ((TriFace->Shades[i1]*nc - C1) / dY); 163 | if (dX2 < dX1) { 164 | dX2 ^= dX1; dX1 ^= dX2; dX2 ^= dX1; 165 | dC2 ^= dC1; dC1 ^= dC2; dC2 ^= dC1; 166 | dZL = dZ1; dZ1 = dZ2; dZ2 = dZL; 167 | stat = 2; 168 | } else stat = 1; 169 | } else { 170 | if (TriFace->Scrx[i1] > X1) { 171 | X2 = TriFace->Scrx[i1]; 172 | Z2 = TriFace->Scrz[i1]; 173 | C2 = (pl_sInt32) (TriFace->Shades[i1]*nc); 174 | stat = 2|4; 175 | } else { 176 | X1 = TriFace->Scrx[i1]; 177 | Z1 = TriFace->Scrz[i1]; 178 | C1 = (pl_sInt32) (TriFace->Shades[i1]*nc); 179 | stat = 1|8; 180 | } 181 | } 182 | 183 | gmem += (Y0 * cam->ScreenWidth); 184 | zbuf += (Y0 * cam->ScreenWidth); 185 | XL1 = (((dX1-dX2)*dY+(1<<19))>>20); 186 | if (XL1) { 187 | dCL = ((dC1-dC2)*dY)/XL1; 188 | dZL = ((dZ1-dZ2)*dY)/XL1; 189 | } else { 190 | XL1 = ((X2-X1+(1<<19))>>20); 191 | if (XL1) { 192 | dCL = (C2-C1)/XL1; 193 | dZL = (Z2-Z1)/XL1; 194 | } 195 | } 196 | 197 | while (Y0 < Y2) { 198 | if (Y0 == Y1) { 199 | dY = Y2 - ((TriFace->Scry[i1]+(1<<19))>>20); 200 | if (dY) { 201 | if (stat & 1) { 202 | X1 = TriFace->Scrx[i1]; 203 | dX1 = (TriFace->Scrx[i2]-TriFace->Scrx[i1])/dY; 204 | } 205 | if (stat & 2) { 206 | X2 = TriFace->Scrx[i1]; 207 | dX2 = (TriFace->Scrx[i2]-TriFace->Scrx[i1])/dY; 208 | } 209 | if (stat & 4) { 210 | X1 = TriFace->Scrx[i0]; 211 | dX1 = (TriFace->Scrx[i2]-TriFace->Scrx[i0])/dY; 212 | } 213 | if (stat & 8) { 214 | X2 = TriFace->Scrx[i0]; 215 | dX2 = (TriFace->Scrx[i2]-TriFace->Scrx[i0])/dY; 216 | } 217 | dZ1 = (TriFace->Scrz[i2]-Z1)/dY; 218 | dC1 = (pl_sInt32) ((TriFace->Shades[i2]*nc - C1) / dY); 219 | } 220 | } 221 | CL = C1; 222 | XL1 = (X1+(1<<19))>>20; 223 | XL2 = (X2+(1<<19))>>20; 224 | ZL = Z1; 225 | if ((XL2-XL1) > 0) { 226 | XL2 -= XL1; 227 | zbuf += XL1; 228 | gmem += XL1; 229 | XL1 += XL2; 230 | if (zb) do { 231 | if (*zbuf < ZL) { 232 | int av; 233 | if (CL >= maxColor) av=maxColorNonShift; 234 | else if (CL > 0) av=CL>>16; 235 | else av=0; 236 | *zbuf = ZL; 237 | *gmem = remap[av + lookuptable[*gmem]]; 238 | } 239 | gmem++; 240 | CL += dCL; 241 | zbuf++; 242 | ZL += dZL; 243 | } while (--XL2); 244 | else do { 245 | int av; 246 | if (CL >= maxColor) av=maxColorNonShift; 247 | else if (CL > 0) av=CL>>16; 248 | else av=0; 249 | *gmem++ = remap[av + lookuptable[*gmem]]; 250 | CL += dCL; 251 | } while (--XL2); 252 | gmem -= XL1; 253 | zbuf -= XL1; 254 | } 255 | gmem += cam->ScreenWidth; 256 | zbuf += cam->ScreenWidth; 257 | Z1 += dZ1; 258 | X1 += dX1; 259 | X2 += dX2; 260 | C1 += dC1; 261 | Y0++; 262 | } 263 | } 264 | -------------------------------------------------------------------------------- /source/plush.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Plush Version 1.2 3 | plush.c 4 | Misc code and data 5 | Copyright (c) 1996-2000, Justin Frankel 6 | ******************************************************************************/ 7 | 8 | #include 9 | 10 | char plVersionString[] = "Plush 3D Version 1.2.0"; 11 | char plCopyrightString[] = 12 | "Copyright (C) 1996-2000, Justin Frankel and Nullsoft, Inc."; 13 | 14 | pl_uChar plText_DefaultFont[256*16] = { 15 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16 | 0, 0, 60, 66, 129, 231, 165, 153, 129, 153, 66, 60, 0, 0, 0, 0, 17 | 0, 0, 60, 126, 255, 153, 219, 231, 255, 231, 126, 60, 0, 0, 0, 0, 18 | 0, 0, 0, 0, 102, 255, 255, 255, 255, 126, 60, 24, 0, 0, 0, 0, 19 | 0, 0, 0, 0, 24, 60, 126, 255, 126, 60, 24, 0, 0, 0, 0, 0, 20 | 0, 0, 0, 24, 60, 60, 90, 255, 255, 90, 24, 60, 0, 0, 0, 0, 21 | 0, 0, 0, 24, 60, 126, 255, 255, 255, 90, 24, 60, 0, 0, 0, 0, 22 | 0, 0, 0, 0, 0, 0, 24, 60, 60, 24, 0, 0, 0, 0, 0, 0, 23 | 255,255,255, 255, 255, 255, 231, 195, 195, 231, 255, 255, 255, 255, 255, 255, 24 | 0, 0, 0, 0, 0, 60, 102, 66, 66, 102, 60, 0, 0, 0, 0, 0, 25 | 255,255,255, 255, 255, 195, 153, 189, 189, 153, 195, 255, 255, 255, 255, 255, 26 | 0, 0, 15, 7, 13, 24, 62, 99, 195, 195, 198, 124, 0, 0, 0, 0, 27 | 0, 0, 126, 195, 195, 195, 126, 24, 24, 30, 120, 24, 0, 0, 0, 0, 28 | 0, 0, 8, 12, 14, 11, 8, 8, 8, 120, 248, 112, 0, 0, 0, 0, 29 | 0, 16, 24, 28, 22, 26, 22, 18, 114, 242, 98, 14, 30, 12, 0, 0, 30 | 0, 0, 24, 24, 219, 126, 60, 255, 60, 126, 219, 24, 24, 0, 0, 0, 31 | 0, 0, 96, 112, 120, 124, 126, 126, 124, 120, 112, 96, 0, 0, 0, 0, 32 | 0, 0, 6, 14, 30, 62, 126, 126, 62, 30, 14, 6, 0, 0, 0, 0, 33 | 0, 0, 16, 56, 124, 254, 56, 56, 56, 56, 254, 124, 56, 16, 0, 0, 34 | 0, 0, 102, 102, 102, 102, 102, 102, 102, 0, 102, 102, 0, 0, 0, 0, 35 | 0, 0, 63, 123, 219, 219, 219, 127, 59, 27, 27, 27, 0, 0, 0, 0, 36 | 0, 31, 48, 120, 220, 206, 231, 115, 59, 30, 12, 24, 48, 224, 0, 0, 37 | 0, 0, 0, 0, 0, 0, 0, 0, 126, 126, 126, 126, 0, 0, 0, 0, 38 | 0, 0, 16, 56, 124, 254, 56, 56, 56, 254, 124, 56, 16, 0, 254, 0, 39 | 0, 0, 16, 56, 124, 254, 56, 56, 56, 56, 56, 56, 56, 56, 0, 0, 40 | 0, 0, 56, 56, 56, 56, 56, 56, 56, 56, 254, 124, 56, 16, 0, 0, 41 | 0, 0, 0, 0, 0, 8, 12, 254, 255, 254, 12, 8, 0, 0, 0, 0, 42 | 0, 0, 0, 0, 0, 16, 48, 127, 255, 127, 48, 16, 0, 0, 0, 0, 43 | 0, 0, 204, 102, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44 | 0, 0, 0, 0, 0, 36, 102, 255, 255, 102, 36, 0, 0, 0, 0, 0, 45 | 0, 0, 0, 0, 24, 60, 60, 126, 126, 255, 255, 0, 0, 0, 0, 0, 46 | 0, 0, 0, 0, 255, 255, 126, 126, 60, 60, 24, 0, 0, 0, 0, 0, 47 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48 | 0, 0, 24, 24, 24, 24, 24, 24, 24, 0, 24, 24, 0, 0, 0, 0, 49 | 0, 0, 51, 102, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50 | 0, 0, 51, 51, 255, 102, 102, 102, 102, 255, 204, 204, 0, 0, 0, 0, 51 | 0, 24, 126, 219, 216, 120, 28, 30, 27, 219, 219, 126, 24, 0, 0, 0, 52 | 0, 0, 96, 209, 179, 102, 12, 24, 54, 109, 203, 6, 0, 0, 0, 0, 53 | 0, 0, 28, 54, 102, 60, 56, 108, 199, 198, 110, 59, 0, 0, 0, 0, 54 | 0, 0, 12, 24, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55 | 0, 12, 24, 48, 48, 96, 96, 96, 96, 48, 48, 24, 12, 0, 0, 0, 56 | 0, 48, 24, 12, 12, 6, 6, 6, 6, 12, 12, 24, 48, 0, 0, 0, 57 | 0, 0, 102, 60, 255, 60, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58 | 0, 0, 0, 0, 0, 24, 24, 126, 24, 24, 0, 0, 0, 0, 0, 0, 59 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 24, 48, 0, 0, 0, 60 | 0, 0, 0, 0, 0, 0, 0, 126, 0, 0, 0, 0, 0, 0, 0, 0, 61 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 62 | 0, 0, 6, 4, 12, 8, 24, 16, 48, 32, 96, 64, 192, 0, 0, 0, 63 | 0, 0, 62, 99, 195, 195, 195, 207, 219, 243, 198, 124, 0, 0, 0, 0, 64 | 0, 0, 12, 28, 60, 108, 12, 12, 12, 12, 12, 12, 0, 0, 0, 0, 65 | 0, 0, 62, 99, 195, 3, 6, 12, 24, 48, 99, 255, 0, 0, 0, 0, 66 | 0, 0, 255, 198, 12, 24, 62, 3, 3, 195, 198, 124, 0, 0, 0, 0, 67 | 0, 0, 6, 14, 30, 54, 102, 199, 222, 246, 6, 6, 0, 0, 0, 0, 68 | 0, 0, 31, 240, 192, 220, 246, 3, 3, 195, 198, 124, 0, 0, 0, 0, 69 | 0, 0, 60, 102, 198, 192, 220, 246, 198, 198, 204, 120, 0, 0, 0, 0, 70 | 0, 0, 255, 195, 6, 12, 12, 24, 24, 48, 48, 48, 0, 0, 0, 0, 71 | 0, 0, 60, 102, 198, 108, 62, 99, 195, 195, 198, 124, 0, 0, 0, 0, 72 | 0, 0, 60, 102, 198, 198, 222, 118, 6, 198, 204, 120, 0, 0, 0, 0, 73 | 0, 0, 0, 0, 24, 24, 0, 0, 0, 24, 24, 0, 0, 0, 0, 0, 74 | 0, 0, 0, 0, 24, 24, 0, 0, 0, 24, 24, 48, 0, 0, 0, 0, 75 | 0, 0, 6, 12, 24, 48, 96, 96, 48, 24, 12, 6, 0, 0, 0, 0, 76 | 0, 0, 0, 0, 0, 255, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 77 | 0, 0, 96, 48, 24, 12, 6, 6, 12, 24, 48, 96, 0, 0, 0, 0, 78 | 0, 0, 62, 99, 198, 12, 24, 48, 48, 0, 48, 48, 0, 0, 0, 0, 79 | 0, 0, 30, 51, 111, 219, 219, 219, 222, 216, 198, 220, 112, 0, 0, 0, 80 | 0, 0, 24, 24, 60, 36, 102, 110, 122, 227, 195, 195, 0, 0, 0, 0, 81 | 0, 0, 30, 51, 227, 198, 220, 247, 195, 198, 220, 240, 0, 0, 0, 0, 82 | 0, 0, 30, 51, 96, 192, 192, 192, 192, 192, 99, 62, 0, 0, 0, 0, 83 | 0, 0, 252, 198, 195, 195, 195, 195, 195, 198, 220, 240, 0, 0, 0, 0, 84 | 0, 0, 30, 240, 192, 192, 220, 240, 192, 192, 222, 240, 0, 0, 0, 0, 85 | 0, 0, 30, 240, 192, 192, 220, 240, 192, 192, 192, 192, 0, 0, 0, 0, 86 | 0, 0, 62, 99, 192, 192, 192, 207, 195, 195, 102, 60, 0, 0, 0, 0, 87 | 0, 0, 195, 195, 195, 195, 207, 251, 195, 195, 195, 195, 0, 0, 0, 0, 88 | 0, 0, 28, 56, 24, 24, 24, 24, 24, 24, 28, 56, 0, 0, 0, 0, 89 | 0, 0, 3, 3, 3, 3, 3, 3, 195, 195, 99, 62, 0, 0, 0, 0, 90 | 0, 0, 195, 198, 220, 240, 224, 240, 216, 204, 198, 195, 0, 0, 0, 0, 91 | 0, 0, 192, 192, 192, 192, 192, 192, 192, 192, 222, 240, 0, 0, 0, 0, 92 | 0, 0, 195, 195, 231, 239, 251, 211, 195, 195, 195, 195, 0, 0, 0, 0, 93 | 0, 0, 195, 195, 227, 243, 211, 219, 207, 199, 195, 195, 0, 0, 0, 0, 94 | 0, 0, 62, 99, 195, 195, 195, 195, 195, 195, 198, 124, 0, 0, 0, 0, 95 | 0, 0, 30, 51, 227, 195, 198, 220, 240, 192, 192, 192, 0, 0, 0, 0, 96 | 0, 0, 62, 99, 195, 195, 195, 195, 243, 222, 204, 124, 6, 3, 0, 0, 97 | 0, 0, 30, 51, 227, 195, 198, 252, 216, 204, 198, 195, 0, 0, 0, 0, 98 | 0, 0, 126, 195, 192, 112, 28, 6, 3, 195, 195, 126, 0, 0, 0, 0, 99 | 0, 0, 15, 248, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 100 | 0, 0, 195, 195, 195, 195, 195, 195, 198, 198, 204, 120, 0, 0, 0, 0, 101 | 0, 0, 195, 195, 195, 195, 102, 102, 124, 56, 48, 48, 0, 0, 0, 0, 102 | 0, 0, 195, 195, 195, 195, 219, 219, 219, 255, 231, 195, 0, 0, 0, 0, 103 | 0, 0, 195, 195, 102, 102, 60, 60, 102, 102, 195, 195, 0, 0, 0, 0, 104 | 0, 0, 195, 195, 102, 102, 60, 24, 24, 24, 24, 24, 0, 0, 0, 0, 105 | 0, 0, 31, 246, 4, 12, 24, 16, 48, 32, 111, 248, 0, 0, 0, 0, 106 | 0, 62, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 62, 0, 0, 0, 107 | 0, 0, 192, 64, 96, 32, 48, 16, 24, 8, 12, 4, 6, 0, 0, 0, 108 | 0, 124, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 124, 0, 0, 0, 109 | 0, 24, 60, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 111 | 0, 0, 48, 24, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112 | 0, 0, 0, 0, 0, 62, 99, 31, 115, 195, 207, 123, 0, 0, 0, 0, 113 | 0, 0, 192, 192, 192, 220, 246, 195, 195, 198, 220, 240, 0, 0, 0, 0, 114 | 0, 0, 0, 0, 0, 30, 51, 96, 192, 192, 195, 126, 0, 0, 0, 0, 115 | 0, 0, 3, 3, 3, 31, 115, 195, 199, 207, 219, 115, 0, 0, 0, 0, 116 | 0, 0, 0, 0, 0, 62, 99, 206, 248, 192, 195, 126, 0, 0, 0, 0, 117 | 0, 0, 30, 51, 48, 48, 60, 240, 48, 48, 48, 48, 0, 0, 0, 0, 118 | 0, 0, 0, 0, 0, 63, 99, 195, 199, 207, 219, 115, 3, 195, 126, 0, 119 | 0, 0, 192, 192, 192, 206, 219, 243, 227, 195, 195, 195, 0, 0, 0, 0, 120 | 0, 0, 24, 24, 0, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 121 | 0, 0, 12, 12, 0, 12, 12, 12, 12, 12, 12, 12, 204, 204, 120, 0, 122 | 0, 0, 192, 192, 192, 198, 204, 216, 248, 236, 198, 195, 0, 0, 0, 0, 123 | 0, 0, 56, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 124 | 0, 0, 0, 0, 0, 230, 219, 219, 219, 195, 195, 195, 0, 0, 0, 0, 125 | 0, 0, 0, 0, 0, 206, 219, 243, 227, 195, 195, 195, 0, 0, 0, 0, 126 | 0, 0, 0, 0, 0, 62, 99, 195, 195, 195, 198, 124, 0, 0, 0, 0, 127 | 0, 0, 0, 0, 0, 206, 219, 243, 227, 195, 198, 252, 192, 192, 192, 0, 128 | 0, 0, 0, 0, 0, 115, 219, 207, 199, 195, 99, 63, 3, 3, 3, 0, 129 | 0, 0, 0, 0, 0, 206, 219, 243, 224, 192, 192, 192, 0, 0, 0, 0, 130 | 0, 0, 0, 0, 0, 126, 195, 112, 30, 3, 195, 126, 0, 0, 0, 0, 131 | 0, 0, 16, 48, 48, 60, 240, 48, 48, 54, 60, 24, 0, 0, 0, 0, 132 | 0, 0, 0, 0, 0, 195, 195, 195, 199, 207, 219, 115, 0, 0, 0, 0, 133 | 0, 0, 0, 0, 0, 195, 195, 195, 102, 108, 56, 24, 0, 0, 0, 0, 134 | 0, 0, 0, 0, 0, 195, 195, 195, 219, 219, 255, 195, 0, 0, 0, 0, 135 | 0, 0, 0, 0, 0, 195, 102, 60, 24, 60, 102, 195, 0, 0, 0, 0, 136 | 0, 0, 0, 0, 0, 195, 195, 195, 195, 195, 102, 62, 12, 216, 112, 0, 137 | 0, 0, 0, 0, 0, 255, 6, 12, 24, 48, 96, 255, 0, 0, 0, 0, 138 | 0, 14, 24, 24, 24, 24, 112, 112, 24, 24, 24, 24, 14, 0, 0, 0, 139 | 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 140 | 0, 112, 24, 24, 24, 24, 14, 14, 24, 24, 24, 24, 112, 0, 0, 0, 141 | 0, 0, 0, 0, 0, 0, 118, 220, 0, 0, 0, 0, 0, 0, 0, 0, 142 | 0, 0, 0, 0, 16, 56, 108, 198, 198, 198, 254, 0, 0, 0, 0, 0, 143 | 0, 0, 30, 51, 96, 192, 192, 192, 192, 192, 99, 62, 12, 24, 240, 0, 144 | 0, 0, 102, 102, 0, 195, 195, 195, 199, 207, 219, 115, 0, 0, 0, 0, 145 | 0, 6, 12, 24, 0, 62, 99, 206, 248, 192, 195, 126, 0, 0, 0, 0, 146 | 12, 30, 51, 96, 0, 62, 99, 31, 115, 195, 207, 123, 0, 0, 0, 0, 147 | 0, 0, 54, 54, 0, 62, 99, 31, 115, 195, 207, 123, 0, 0, 0, 0, 148 | 0, 48, 24, 12, 0, 62, 99, 31, 115, 195, 207, 123, 0, 0, 0, 0, 149 | 28, 54, 54, 28, 0, 62, 99, 31, 115, 195, 207, 123, 0, 0, 0, 0, 150 | 0, 0, 0, 0, 0, 30, 51, 96, 192, 192, 195, 126, 12, 24, 240, 0, 151 | 24, 60, 102, 192, 0, 62, 99, 206, 248, 192, 195, 126, 0, 0, 0, 0, 152 | 0, 0, 102, 102, 0, 62, 99, 206, 248, 192, 195, 126, 0, 0, 0, 0, 153 | 0, 96, 48, 24, 0, 62, 99, 206, 248, 192, 195, 126, 0, 0, 0, 0, 154 | 0, 0, 102, 102, 0, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 155 | 24, 60, 102, 192, 0, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 156 | 0, 96, 48, 24, 0, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 157 | 102, 102, 24, 24, 60, 36, 102, 102, 126, 195, 195, 195, 0, 0, 0, 0, 158 | 24, 36, 36, 24, 60, 36, 102, 102, 126, 195, 195, 195, 0, 0, 0, 0, 159 | 24, 48, 96, 30, 240, 192, 222, 240, 192, 192, 222, 240, 0, 0, 0, 0, 160 | 0, 0, 0, 0, 0, 126, 219, 59, 126, 220, 219, 110, 0, 0, 0, 0, 161 | 0, 0, 63, 62, 60, 108, 111, 110, 124, 204, 207, 206, 0, 0, 0, 0, 162 | 24, 60, 102, 192, 0, 62, 99, 195, 195, 195, 198, 124, 0, 0, 0, 0, 163 | 0, 0, 102, 102, 0, 62, 99, 195, 195, 195, 198, 124, 0, 0, 0, 0, 164 | 0, 96, 48, 24, 0, 62, 99, 195, 195, 195, 198, 124, 0, 0, 0, 0, 165 | 24, 60, 102, 192, 0, 195, 195, 195, 199, 207, 219, 115, 0, 0, 0, 0, 166 | 0, 96, 48, 24, 0, 195, 195, 195, 199, 207, 219, 115, 0, 0, 0, 0, 167 | 0, 0, 102, 102, 0, 195, 195, 195, 195, 195, 102, 62, 12, 216, 112, 0, 168 | 102, 0, 62, 99, 195, 195, 195, 195, 195, 195, 198, 124, 0, 0, 0, 0, 169 | 102, 0, 195, 195, 195, 195, 195, 195, 198, 198, 204, 120, 0, 0, 0, 0, 170 | 0, 0, 0, 8, 8, 30, 59, 104, 200, 200, 203, 126, 8, 8, 0, 0, 171 | 0, 0, 60, 102, 96, 248, 96, 248, 96, 96, 99, 126, 0, 0, 0, 0, 172 | 0, 0, 195, 195, 102, 102, 60, 24, 126, 24, 126, 24, 24, 0, 0, 0, 173 | 0, 0, 30, 51, 227, 195, 198, 220, 248, 204, 222, 204, 15, 14, 4, 0, 174 | 0, 0, 30, 51, 48, 48, 60, 240, 48, 48, 48, 48, 224, 0, 0, 0, 175 | 0, 6, 12, 24, 0, 62, 99, 31, 115, 195, 207, 123, 0, 0, 0, 0, 176 | 0, 6, 12, 24, 0, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 177 | 0, 6, 12, 24, 0, 62, 99, 195, 195, 195, 198, 124, 0, 0, 0, 0, 178 | 0, 12, 24, 48, 0, 195, 195, 195, 199, 207, 219, 115, 0, 0, 0, 0, 179 | 0, 3, 118, 220, 0, 206, 219, 243, 227, 195, 195, 195, 0, 0, 0, 0, 180 | 3, 118, 220, 0, 195, 227, 243, 211, 219, 207, 199, 195, 0, 0, 0, 0, 181 | 0, 0, 62, 99, 31, 115, 195, 207, 123, 0, 0, 255, 0, 0, 0, 0, 182 | 0, 0, 62, 99, 195, 195, 195, 198, 124, 0, 0, 255, 0, 0, 0, 0, 183 | 0, 0, 12, 12, 0, 12, 12, 24, 48, 99, 198, 124, 0, 0, 0, 0, 184 | 0, 0, 0, 0, 0, 0, 254, 192, 192, 192, 0, 0, 0, 0, 0, 0, 185 | 0, 0, 0, 0, 0, 0, 254, 6, 6, 6, 0, 0, 0, 0, 0, 0, 186 | 0, 96, 225, 99, 102, 108, 24, 48, 96, 206, 155, 6, 13, 31, 0, 0, 187 | 0, 96, 225, 99, 102, 108, 24, 48, 102, 206, 151, 62, 6, 6, 0, 0, 188 | 0, 0, 24, 24, 0, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 189 | 0, 0, 0, 0, 3, 54, 108, 216, 216, 108, 54, 0, 0, 0, 0, 0, 190 | 0, 0, 0, 0, 0, 108, 54, 27, 27, 54, 108, 192, 0, 0, 0, 0, 191 | 130, 16, 130, 16, 130, 16, 130, 16, 130, 16, 130, 16, 130, 16, 130, 16, 192 | 0, 149, 0, 169, 0, 149, 0, 169, 0, 149, 0, 169, 0, 149, 0, 169, 193 | 146, 73, 146, 73, 146, 73, 146, 73, 146, 73, 146, 73, 146, 73, 146, 73, 194 | 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 195 | 24, 24, 24, 24, 24, 24, 24, 24, 248, 24, 24, 24, 24, 24, 24, 24, 196 | 24, 24, 24, 24, 24, 24, 248, 248, 248, 24, 24, 24, 24, 24, 24, 24, 197 | 60, 60, 60, 60, 60, 60, 60, 60, 252, 60, 60, 60, 60, 60, 60, 60, 198 | 0, 0, 0, 0, 0, 0, 0, 0, 252, 60, 60, 60, 60, 60, 60, 60, 199 | 0, 0, 0, 0, 0, 0, 248, 248, 248, 24, 24, 24, 24, 24, 24, 24, 200 | 60, 60, 60, 60, 60, 60, 252, 252, 252, 60, 60, 60, 60, 60, 60, 60, 201 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 202 | 0, 0, 0, 0, 0, 0, 252, 252, 252, 60, 60, 60, 60, 60, 60, 60, 203 | 60, 60, 60, 60, 60, 60, 252, 252, 252, 0, 0, 0, 0, 0, 0, 0, 204 | 60, 60, 60, 60, 60, 60, 60, 60, 252, 0, 0, 0, 0, 0, 0, 0, 205 | 24, 24, 24, 24, 24, 24, 248, 248, 248, 0, 0, 0, 0, 0, 0, 0, 206 | 0, 0, 0, 0, 0, 0, 0, 0, 248, 24, 24, 24, 24, 24, 24, 24, 207 | 24, 24, 24, 24, 24, 24, 24, 24, 31, 0, 0, 0, 0, 0, 0, 0, 208 | 24, 24, 24, 24, 24, 24, 24, 24, 255, 0, 0, 0, 0, 0, 0, 0, 209 | 0, 0, 0, 0, 0, 0, 0, 0, 255, 24, 24, 24, 24, 24, 24, 24, 210 | 24, 24, 24, 24, 24, 24, 24, 24, 31, 24, 24, 24, 24, 24, 24, 24, 211 | 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 212 | 24, 24, 24, 24, 24, 24, 24, 24, 255, 24, 24, 24, 24, 24, 24, 24, 213 | 24, 24, 24, 24, 24, 24, 31, 31, 31, 24, 24, 24, 24, 24, 24, 24, 214 | 60, 60, 60, 60, 60, 60, 60, 60, 63, 60, 60, 60, 60, 60, 60, 60, 215 | 60, 60, 60, 60, 60, 60, 63, 63, 63, 0, 0, 0, 0, 0, 0, 0, 216 | 0, 0, 0, 0, 0, 0, 63, 63, 63, 60, 60, 60, 60, 60, 60, 60, 217 | 60, 60, 60, 60, 60, 60, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 218 | 0, 0, 0, 0, 0, 0, 255, 255, 255, 60, 60, 60, 60, 60, 60, 60, 219 | 60, 60, 60, 60, 60, 60, 63, 63, 63, 60, 60, 60, 60, 60, 60, 60, 220 | 0, 0, 0, 0, 0, 0, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 221 | 60, 60, 60, 60, 60, 60, 255, 255, 255, 60, 60, 60, 60, 60, 60, 60, 222 | 24, 24, 24, 24, 24, 24, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 223 | 60, 60, 60, 60, 60, 60, 60, 60, 255, 0, 0, 0, 0, 0, 0, 0, 224 | 0, 0, 0, 0, 0, 0, 255, 255, 255, 24, 24, 24, 24, 24, 24, 24, 225 | 0, 0, 0, 0, 0, 0, 0, 0, 255, 60, 60, 60, 60, 60, 60, 60, 226 | 60, 60, 60, 60, 60, 60, 60, 60, 63, 0, 0, 0, 0, 0, 0, 0, 227 | 24, 24, 24, 24, 24, 24, 31, 31, 31, 0, 0, 0, 0, 0, 0, 0, 228 | 0, 0, 0, 0, 0, 0, 31, 31, 31, 24, 24, 24, 24, 24, 24, 24, 229 | 0, 0, 0, 0, 0, 0, 0, 0, 63, 60, 60, 60, 60, 60, 60, 60, 230 | 60, 60, 60, 60, 60, 60, 60, 60, 255, 60, 60, 60, 60, 60, 60, 60, 231 | 24, 24, 24, 24, 24, 24, 255, 255, 255, 24, 24, 24, 24, 24, 24, 24, 232 | 24, 24, 24, 24, 24, 24, 24, 24, 248, 0, 0, 0, 0, 0, 0, 0, 233 | 0, 0, 0, 0, 0, 0, 0, 0, 31, 24, 24, 24, 24, 24, 24, 24, 234 | 255, 255, 255,255,255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 235 | 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 236 | 240, 240, 240, 240,240,240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 237 | 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 238 | 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 239 | 0, 0, 0, 0, 0, 3, 118, 204, 204, 204, 222, 115, 0, 0, 0, 0, 240 | 0, 0, 30, 51, 227, 194, 204, 194, 195, 195, 206, 216, 192, 192, 0, 0, 241 | 0, 0, 31, 243, 195, 192, 192, 192, 192, 192, 192, 192, 0, 0, 0, 0, 242 | 0, 0, 0, 0, 3, 126, 230, 102, 102, 102, 102, 68, 0, 0, 0, 0, 243 | 0, 0, 31, 240, 96, 48, 24, 48, 96, 192, 223, 240, 0, 0, 0, 0, 244 | 0, 0, 0, 0, 0, 127, 240, 216, 216, 216, 216, 112, 0, 0, 0, 0, 245 | 0, 0, 0, 0, 0, 99, 99, 99, 99, 103, 111, 123, 96, 96, 192, 0, 246 | 0, 0, 0, 0, 111, 184, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 247 | 0, 0, 24, 24, 126, 219, 219, 219, 219, 126, 24, 24, 0, 0, 0, 0, 248 | 0, 0, 0, 60, 102, 195, 195, 255, 195, 195, 102, 60, 0, 0, 0, 0, 249 | 0, 0, 60, 102, 195, 195, 195, 195, 102, 36, 165, 231, 0, 0, 0, 0, 250 | 0, 7, 28, 48, 24, 12, 62, 102, 198, 198, 204, 120, 0, 0, 0, 0, 251 | 0, 0, 0, 0, 0, 110, 219, 219, 219, 118, 0, 0, 0, 0, 0, 0, 252 | 0, 0, 0, 2, 4, 124, 206, 214, 230, 124, 64, 128, 0, 0, 0, 0, 253 | 0, 0, 30, 48, 96, 96, 126, 96, 96, 96, 48, 30, 0, 0, 0, 0, 254 | 0, 0, 0, 126, 195, 195, 195, 195, 195, 195, 195, 195, 0, 0, 0, 0, 255 | 0, 0, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 0, 0, 0, 256 | 0, 0, 0, 0, 24, 24, 126, 24, 24, 0, 0, 126, 0, 0, 0, 0, 257 | 0, 0, 0, 48, 24, 12, 6, 12, 24, 48, 0, 126, 0, 0, 0, 0, 258 | 0, 0, 0, 12, 24, 48, 96, 48, 24, 12, 0, 126, 0, 0, 0, 0, 259 | 0, 0, 0, 14, 27, 27, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 260 | 24, 24, 24, 24, 24, 24, 24, 24, 24, 216, 216, 112, 0, 0, 0, 0, 261 | 0, 0, 0, 0, 24, 24, 0, 255, 0, 24, 24, 0, 0, 0, 0, 0, 262 | 0, 0, 0, 0, 0, 118, 220, 0, 118, 220, 0, 0, 0, 0, 0, 0, 263 | 0, 0, 60, 102, 102, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 264 | 0, 0, 0, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 0, 0, 0, 265 | 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 266 | 0, 0, 3, 2, 6, 4, 12, 8, 216, 80, 112, 32, 0, 0, 0, 0, 267 | 0, 0, 220, 246, 230, 198, 198, 198, 0, 0, 0, 0, 0, 0, 0, 0, 268 | 0, 0, 120, 204, 24, 48, 100, 252, 0, 0, 0, 0, 0, 0, 0, 0, 269 | 0, 0, 0, 0, 126, 126, 126, 126, 126, 126, 126, 0, 0, 0, 0, 0, 270 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 271 | }; 272 | -------------------------------------------------------------------------------- /source/putface.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Plush Version 1.2 3 | putface.h 4 | Triangle Vertex Sorting Code for pf_*.c 5 | Copyright (c) 1996-2000, Justin Frankel 6 | ******************************************************************************/ 7 | 8 | #ifndef _PUTFACE_H_ 9 | #define _PUTFACE_H_ 10 | 11 | #define PUTFACE_SORT() \ 12 | i0 = 0; i1 = 1; i2 = 2; \ 13 | if (TriFace->Scry[0] > TriFace->Scry[1]) { \ 14 | i0 = 1; i1 = 0; \ 15 | } \ 16 | if (TriFace->Scry[i0] > TriFace->Scry[2]) { \ 17 | i2 ^= i0; i0 ^= i2; i2 ^= i0; \ 18 | } \ 19 | if (TriFace->Scry[i1] > TriFace->Scry[i2]) { \ 20 | i2 ^= i1; i1 ^= i2; i2 ^= i1; \ 21 | } 22 | 23 | 24 | #define PUTFACE_SORT_ENV() \ 25 | PUTFACE_SORT(); \ 26 | MappingU1=TriFace->eMappingU[i0]*Texture->uScale*\ 27 | TriFace->Material->EnvScaling;\ 28 | MappingV1=TriFace->eMappingV[i0]*Texture->vScale*\ 29 | TriFace->Material->EnvScaling;\ 30 | MappingU2=TriFace->eMappingU[i1]*Texture->uScale*\ 31 | TriFace->Material->EnvScaling;\ 32 | MappingV2=TriFace->eMappingV[i1]*Texture->vScale*\ 33 | TriFace->Material->EnvScaling;\ 34 | MappingU3=TriFace->eMappingU[i2]*Texture->uScale*\ 35 | TriFace->Material->EnvScaling;\ 36 | MappingV3=TriFace->eMappingV[i2]*Texture->vScale*\ 37 | TriFace->Material->EnvScaling; 38 | 39 | #define PUTFACE_SORT_TEX() \ 40 | PUTFACE_SORT(); \ 41 | MappingU1=TriFace->MappingU[i0]*Texture->uScale*\ 42 | TriFace->Material->TexScaling;\ 43 | MappingV1=TriFace->MappingV[i0]*Texture->vScale*\ 44 | TriFace->Material->TexScaling;\ 45 | MappingU2=TriFace->MappingU[i1]*Texture->uScale*\ 46 | TriFace->Material->TexScaling;\ 47 | MappingV2=TriFace->MappingV[i1]*Texture->vScale*\ 48 | TriFace->Material->TexScaling;\ 49 | MappingU3=TriFace->MappingU[i2]*Texture->uScale*\ 50 | TriFace->Material->TexScaling;\ 51 | MappingV3=TriFace->MappingV[i2]*Texture->vScale*\ 52 | TriFace->Material->TexScaling; 53 | 54 | #endif /* !_PUTFACE_H_ */ 55 | -------------------------------------------------------------------------------- /source/read_3ds.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Plush Version 1.2 3 | read_3ds.c 4 | 3DS Object Reader 5 | Copyright (c) 1996-2000, Justin Frankel 6 | ******************************************************************************/ 7 | 8 | #include 9 | 10 | typedef struct { 11 | pl_uInt16 id; 12 | void (*func)(FILE *f, pl_uInt32 p); 13 | } _pl_3DSChunk; 14 | 15 | static pl_Obj *obj; 16 | static pl_Obj *bobj; 17 | static pl_Obj *lobj; 18 | static pl_sInt16 currentobj; 19 | static pl_Mat *_m; 20 | 21 | static pl_Float _pl3DSReadFloat(FILE *f); 22 | static pl_uInt32 _pl3DSReadDWord(FILE *f); 23 | static pl_uInt16 _pl3DSReadWord(FILE *f); 24 | static void _pl3DSChunkReader(FILE *f, pl_uInt32 p); 25 | static void _pl3DSRGBFReader(FILE *f, pl_uInt32 p); 26 | static void _pl3DSRGBBReader(FILE *f, pl_uInt32 p); 27 | static void _pl3DSASCIIZReader(FILE *f, pl_uInt32 p, char *as); 28 | static void _pl3DSObjBlockReader(FILE *f, pl_uInt32 p); 29 | static void _pl3DSTriMeshReader(FILE *f, pl_uInt32 p); 30 | static void _pl3DSVertListReader(FILE *f, pl_uInt32 p); 31 | static void _pl3DSFaceListReader(FILE *f, pl_uInt32 p); 32 | static void _pl3DSFaceMatReader(FILE *f, pl_uInt32 p); 33 | static void MapListReader(FILE *f, pl_uInt32 p); 34 | static pl_sInt16 _pl3DSFindChunk(pl_uInt16 id); 35 | 36 | static _pl_3DSChunk _pl3DSChunkNames[] = { 37 | {0x4D4D,NULL}, /* Main */ 38 | {0x3D3D,NULL}, /* Object Mesh */ 39 | {0x4000,_pl3DSObjBlockReader}, 40 | {0x4100,_pl3DSTriMeshReader}, 41 | {0x4110,_pl3DSVertListReader}, 42 | {0x4120,_pl3DSFaceListReader}, 43 | {0x4130,_pl3DSFaceMatReader}, 44 | {0x4140,MapListReader}, 45 | {0xAFFF,NULL}, /* Material */ 46 | {0xA010,NULL}, /* Ambient */ 47 | {0xA020,NULL}, /* Diff */ 48 | {0xA030,NULL}, /* Specular */ 49 | {0xA200,NULL}, /* Texture */ 50 | {0x0010,_pl3DSRGBFReader}, 51 | {0x0011,_pl3DSRGBBReader}, 52 | }; 53 | 54 | pl_Obj *plRead3DSObj(const char *fn, pl_Mat *m) { 55 | FILE *f; 56 | pl_uInt32 p; 57 | _m = m; 58 | obj = bobj = lobj = 0; 59 | currentobj = 0; 60 | f = fopen(fn, "rb"); 61 | if (!f) return 0; 62 | fseek(f, 0, 2); 63 | p = ftell(f); 64 | rewind(f); 65 | _pl3DSChunkReader(f, p); 66 | fclose(f); 67 | return bobj; 68 | } 69 | 70 | static pl_Float _pl3DSReadFloat(FILE *f) { 71 | pl_uInt32 *i; 72 | pl_Float c; 73 | i = (pl_uInt32 *) &c; 74 | *i = _pl3DSReadDWord(f); 75 | return ((pl_Float) c); 76 | } 77 | 78 | static pl_uInt32 _pl3DSReadDWord(FILE *f) { 79 | pl_uInt32 r; 80 | r = fgetc(f); 81 | r |= fgetc(f)<<8; 82 | r |= fgetc(f)<<16; 83 | r |= fgetc(f)<<24; 84 | return r; 85 | } 86 | 87 | static pl_uInt16 _pl3DSReadWord(FILE *f) { 88 | pl_uInt16 r; 89 | r = fgetc(f); 90 | r |= fgetc(f)<<8; 91 | return r; 92 | } 93 | 94 | static void _pl3DSRGBFReader(FILE *f, pl_uInt32 p) { 95 | pl_Float c[3]; 96 | c[0] = _pl3DSReadFloat(f); 97 | c[1] = _pl3DSReadFloat(f); 98 | c[2] = _pl3DSReadFloat(f); 99 | } 100 | 101 | static void _pl3DSRGBBReader(FILE *f, pl_uInt32 p) { 102 | unsigned char c[3]; 103 | if (fread(&c, sizeof(c), 1, f) != 1) return; 104 | } 105 | 106 | static void _pl3DSASCIIZReader(FILE *f, pl_uInt32 p, char *as) { 107 | char c; 108 | if (!as) while ((c = fgetc(f)) != EOF && c != '\0'); 109 | else { 110 | while ((c = fgetc(f)) != EOF && c != '\0') *as++ = c; 111 | *as = 0; 112 | } 113 | } 114 | 115 | static void _pl3DSObjBlockReader(FILE *f, pl_uInt32 p) { 116 | _pl3DSASCIIZReader(f,p,0); 117 | _pl3DSChunkReader(f, p); 118 | } 119 | 120 | static void _pl3DSTriMeshReader(FILE *f, pl_uInt32 p) { 121 | pl_uInt32 i; 122 | pl_Face *face; 123 | obj = plObjCreate(0,0); 124 | _pl3DSChunkReader(f, p); 125 | i = obj->NumFaces; 126 | face = obj->Faces; 127 | while (i--) { 128 | face->Vertices[0] = obj->Vertices + (ptrdiff_t) face->Vertices[0]; 129 | face->Vertices[1] = obj->Vertices + (ptrdiff_t) face->Vertices[1]; 130 | face->Vertices[2] = obj->Vertices + (ptrdiff_t) face->Vertices[2]; 131 | face->MappingU[0] = face->Vertices[0]->xformedx; 132 | face->MappingV[0] = face->Vertices[0]->xformedy; 133 | face->MappingU[1] = face->Vertices[1]->xformedx; 134 | face->MappingV[1] = face->Vertices[1]->xformedy; 135 | face->MappingU[2] = face->Vertices[2]->xformedx; 136 | face->MappingV[2] = face->Vertices[2]->xformedy; 137 | face++; 138 | } 139 | plObjCalcNormals(obj); 140 | if (currentobj == 0) { 141 | currentobj = 1; 142 | lobj = bobj = obj; 143 | } else { 144 | lobj->Children[0] = obj; 145 | lobj = obj; 146 | } 147 | } 148 | 149 | static void _pl3DSVertListReader(FILE *f, pl_uInt32 p) { 150 | pl_uInt16 nv; 151 | pl_Vertex *v; 152 | nv = _pl3DSReadWord(f); 153 | obj->NumVertices = nv; 154 | v = obj->Vertices = (pl_Vertex *) calloc(sizeof(pl_Vertex)*nv,1); 155 | while (nv--) { 156 | v->x = _pl3DSReadFloat(f); 157 | v->y = _pl3DSReadFloat(f); 158 | v->z = _pl3DSReadFloat(f); 159 | if (feof(f)) return; 160 | v++; 161 | } 162 | } 163 | 164 | static void _pl3DSFaceListReader(FILE *f, pl_uInt32 p) { 165 | pl_uInt16 nv; 166 | pl_uInt16 c[3]; 167 | pl_uInt16 flags; 168 | pl_Face *face; 169 | 170 | nv = _pl3DSReadWord(f); 171 | obj->NumFaces = nv; 172 | face = obj->Faces = (pl_Face *) calloc(sizeof(pl_Face)*nv,1); 173 | while (nv--) { 174 | c[0] = _pl3DSReadWord(f); 175 | c[1] = _pl3DSReadWord(f); 176 | c[2] = _pl3DSReadWord(f); 177 | flags = _pl3DSReadWord(f); 178 | if (feof(f)) return; 179 | face->Vertices[0] = (pl_Vertex *) ((ptrdiff_t)c[0]); 180 | face->Vertices[1] = (pl_Vertex *) ((ptrdiff_t)c[1]); 181 | face->Vertices[2] = (pl_Vertex *) ((ptrdiff_t)c[2]); 182 | face->Material = _m; 183 | face++; 184 | } 185 | _pl3DSChunkReader(f, p); 186 | } 187 | 188 | static void _pl3DSFaceMatReader(FILE *f, pl_uInt32 p) { 189 | pl_uInt16 n, nf; 190 | 191 | _pl3DSASCIIZReader(f, p,0); 192 | 193 | n = _pl3DSReadWord(f); 194 | while (n--) { 195 | nf = _pl3DSReadWord(f); 196 | } 197 | } 198 | 199 | static void MapListReader(FILE *f, pl_uInt32 p) { 200 | pl_uInt16 nv; 201 | pl_Float c[2]; 202 | pl_Vertex *v; 203 | nv = _pl3DSReadWord(f); 204 | v = obj->Vertices; 205 | if (nv == obj->NumVertices) while (nv--) { 206 | c[0] = _pl3DSReadFloat(f); 207 | c[1] = _pl3DSReadFloat(f); 208 | if (feof(f)) return; 209 | v->xformedx = (pl_sInt32) (c[0]*65536.0); 210 | v->xformedy = (pl_sInt32) (c[1]*65536.0); 211 | v++; 212 | } 213 | } 214 | 215 | static pl_sInt16 _pl3DSFindChunk(pl_uInt16 id) { 216 | pl_sInt16 i; 217 | for (i = 0; i < sizeof(_pl3DSChunkNames)/sizeof(_pl3DSChunkNames[0]); i++) 218 | if (id == _pl3DSChunkNames[i].id) return i; 219 | return -1; 220 | } 221 | 222 | static void _pl3DSChunkReader(FILE *f, pl_uInt32 p) { 223 | pl_uInt32 hlen; 224 | pl_uInt16 hid; 225 | pl_sInt16 n; 226 | pl_uInt32 pc; 227 | 228 | while (ftell(f) < (int)p) { 229 | pc = ftell(f); 230 | hid = _pl3DSReadWord(f); if (feof(f)) return; 231 | hlen = _pl3DSReadDWord(f); if (feof(f)) return; 232 | if (hlen == 0) return; 233 | n = _pl3DSFindChunk(hid); 234 | if (n < 0) fseek(f, pc + hlen, 0); 235 | else { 236 | pc += hlen; 237 | if (_pl3DSChunkNames[n].func != NULL) _pl3DSChunkNames[n].func(f, pc); 238 | else _pl3DSChunkReader(f, pc); 239 | fseek(f, pc, 0); 240 | } 241 | if (ferror(f)) break; 242 | } 243 | } 244 | 245 | -------------------------------------------------------------------------------- /source/read_cob.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Plush Version 1.2 3 | read_cob.c 4 | ASCII COB Object Reader 5 | Copyright (c) 1996-2000, Justin Frankel 6 | ******************************************************************************/ 7 | 8 | #include 9 | 10 | #define PL_COB_MAX_LINELENGTH 1024 11 | 12 | pl_Obj *plReadCOBObj(const char *fn, pl_Mat *mat) { 13 | FILE *fp = fopen(fn,"rt"); 14 | long int p1,m1,p2,m2,p3,m3; 15 | char temp_string[PL_COB_MAX_LINELENGTH]; 16 | float TransMatrix[4][4]; 17 | pl_Obj *obj; 18 | pl_sInt32 x,i2; 19 | long int numVertices, numMappingVertices, numFaces, i; 20 | pl_sInt32 *MappingVertices = 0; 21 | if (!fp) return 0; 22 | 23 | fgets(temp_string,PL_COB_MAX_LINELENGTH,fp); 24 | if (memcmp("Caligari",temp_string,8)) { fclose(fp); return 0; } 25 | 26 | do { 27 | fgets(temp_string,PL_COB_MAX_LINELENGTH,fp); 28 | } while (!feof(fp) && memcmp("Transform",temp_string,9)); 29 | if (feof(fp)) { fclose(fp); return 0; } 30 | fgets(temp_string,PL_COB_MAX_LINELENGTH,fp); 31 | sscanf(temp_string,"%f %f %f %f", 32 | &TransMatrix[0][0],&TransMatrix[0][1],&TransMatrix[0][2],&TransMatrix[0][3]); 33 | fgets(temp_string,PL_COB_MAX_LINELENGTH,fp); 34 | sscanf(temp_string,"%f %f %f %f", 35 | &TransMatrix[1][0],&TransMatrix[1][1],&TransMatrix[1][2],&TransMatrix[1][3]); 36 | fgets(temp_string,PL_COB_MAX_LINELENGTH,fp); 37 | sscanf(temp_string,"%f %f %f %f", 38 | &TransMatrix[2][0],&TransMatrix[2][1],&TransMatrix[2][2],&TransMatrix[2][3]); 39 | fgets(temp_string,PL_COB_MAX_LINELENGTH,fp); 40 | sscanf(temp_string,"%f %f %f %f", 41 | &TransMatrix[3][0],&TransMatrix[3][1],&TransMatrix[3][2],&TransMatrix[3][3]); 42 | 43 | do { 44 | fgets(temp_string,PL_COB_MAX_LINELENGTH,fp); 45 | } while (!feof(fp) && memcmp("World Vertices",temp_string,12)); 46 | if (feof(fp) || sscanf(temp_string,"World Vertices %ld",&numVertices) != 1) 47 | { fclose(fp); return 0; } 48 | 49 | rewind(fp); 50 | do { 51 | fgets(temp_string,PL_COB_MAX_LINELENGTH,fp); 52 | } while (!feof(fp) && memcmp("Texture Vertices",temp_string,16)); 53 | if (feof(fp) || 54 | sscanf(temp_string,"Texture Vertices %ld",&numMappingVertices) != 1) { 55 | fclose(fp); return 0; 56 | } 57 | 58 | rewind(fp); 59 | do { 60 | fgets(temp_string,PL_COB_MAX_LINELENGTH,fp); 61 | } while (!feof(fp) && memcmp("Faces",temp_string,5)); 62 | if (feof(fp) || sscanf(temp_string,"Faces %ld",&numFaces) != 1) { 63 | fclose(fp); return 0; 64 | } 65 | for (x = numFaces; x; x--) { 66 | fgets(temp_string,PL_COB_MAX_LINELENGTH,fp); 67 | if (feof(fp) || sscanf(temp_string+4," verts %ld",&i) != 1 || i < 3) { 68 | fclose(fp); 69 | return 0; 70 | } 71 | numFaces += i-3; 72 | fgets(temp_string,PL_COB_MAX_LINELENGTH,fp); 73 | } 74 | obj = plObjCreate(numVertices,numFaces); 75 | if (!obj) { fclose(fp); return 0; } 76 | rewind(fp); 77 | do { 78 | fgets(temp_string,PL_COB_MAX_LINELENGTH,fp); 79 | } while (!feof(fp) && memcmp("World Vertices",temp_string,12)); 80 | if (feof(fp)) { plObjDelete(obj); fclose(fp); return 0; } 81 | for (x = 0; x < numVertices; x ++) { 82 | float xp, yp, zp; 83 | fgets(temp_string,PL_COB_MAX_LINELENGTH,fp); 84 | if (feof(fp) || 85 | sscanf(temp_string,"%f %f %f", &xp, &yp, &zp) != 3) { 86 | plObjDelete(obj); fclose(fp); return 0; 87 | } 88 | obj->Vertices[x].x = (TransMatrix[0][0]*xp+TransMatrix[0][1]*yp+ 89 | TransMatrix[0][2]*zp+TransMatrix[0][3]); 90 | obj->Vertices[x].y = (TransMatrix[1][0]*xp+TransMatrix[1][1]*yp+ 91 | TransMatrix[1][2]*zp+TransMatrix[1][3]); 92 | obj->Vertices[x].z = (TransMatrix[2][0]*xp+TransMatrix[2][1]*yp+ 93 | TransMatrix[2][2]*zp+TransMatrix[2][3]); 94 | } 95 | rewind(fp); 96 | do { 97 | fgets(temp_string,PL_COB_MAX_LINELENGTH,fp); 98 | } while (!feof(fp) && memcmp("Texture Vertices",temp_string,16)); 99 | if (!feof(fp)) { 100 | MappingVertices = (pl_sInt32 *) 101 | malloc(sizeof(pl_sInt32) * numMappingVertices * 2); 102 | if (MappingVertices) { 103 | for (x = 0; x < numMappingVertices; x ++) { 104 | float p1, p2; 105 | fgets(temp_string,PL_COB_MAX_LINELENGTH,fp); 106 | if (feof(fp) || sscanf(temp_string,"%f %f", &p1, &p2) != 2) { 107 | free(MappingVertices); plObjDelete(obj); fclose(fp); return 0; 108 | } 109 | MappingVertices[x*2] = (pl_sInt32) (p1*65536.0); 110 | MappingVertices[x*2+1] = (pl_sInt32) (p2*65536.0); 111 | } 112 | } 113 | } 114 | rewind(fp); 115 | do { 116 | fgets(temp_string,PL_COB_MAX_LINELENGTH,fp); 117 | } while (!feof(fp) && memcmp("Faces",temp_string,5)); 118 | if (feof(fp)) { 119 | if (MappingVertices) free(MappingVertices); 120 | plObjDelete(obj); fclose(fp); return 0; 121 | } 122 | for (x = 0; x < numFaces; x ++) { 123 | fgets(temp_string,PL_COB_MAX_LINELENGTH,fp); 124 | sscanf(temp_string+4," verts %ld",&i); 125 | fgets(temp_string,PL_COB_MAX_LINELENGTH,fp); 126 | if (i == 3) { 127 | if (feof(fp) || sscanf(temp_string,"<%ld,%ld> <%ld,%ld> <%ld,%ld>", 128 | &p3,&m3,&p2,&m2,&p1,&m1) != 6) { 129 | if (MappingVertices) free(MappingVertices); 130 | plObjDelete(obj); fclose(fp); return 0; 131 | } 132 | obj->Faces[x].Vertices[0] = obj->Vertices + p1; 133 | obj->Faces[x].Vertices[1] = obj->Vertices + p2; 134 | obj->Faces[x].Vertices[2] = obj->Vertices + p3; 135 | if (MappingVertices) { 136 | obj->Faces[x].MappingU[0] = MappingVertices[m1*2]; 137 | obj->Faces[x].MappingV[0] = MappingVertices[m1*2+1]; 138 | obj->Faces[x].MappingU[1] = MappingVertices[m2*2]; 139 | obj->Faces[x].MappingV[1] = MappingVertices[m2*2+1]; 140 | obj->Faces[x].MappingU[2] = MappingVertices[m3*2]; 141 | obj->Faces[x].MappingV[2] = MappingVertices[m3*2+1]; 142 | } 143 | obj->Faces[x].Material = mat; 144 | } else { 145 | long int p[16],m[16]; 146 | if (feof(fp)) { 147 | if (MappingVertices) free(MappingVertices); 148 | plObjDelete(obj); fclose(fp); return 0; 149 | } 150 | sscanf(temp_string, 151 | "<%ld,%ld> <%ld,%ld> <%ld,%ld> <%ld,%ld> " 152 | "<%ld,%ld> <%ld,%ld> <%ld,%ld> <%ld,%ld> " 153 | "<%ld,%ld> <%ld,%ld> <%ld,%ld> <%ld,%ld> " 154 | "<%ld,%ld> <%ld,%ld> <%ld,%ld> <%ld,%ld> ", 155 | p+0,m+0,p+1,m+1,p+2,m+2,p+3,m+3, 156 | p+4,m+4,p+5,m+5,p+6,m+6,p+7,m+7, 157 | p+8,m+8,p+9,m+9,p+10,m+10,p+11,m+11, 158 | p+12,m+12,p+13,m+13,p+14,m+14,p+15,m+15); 159 | for (i2 = 1; i2 < (i-1); i2 ++) { 160 | obj->Faces[x].Vertices[0] = obj->Vertices + p[0]; 161 | obj->Faces[x].Vertices[1] = obj->Vertices + p[i2+1]; 162 | obj->Faces[x].Vertices[2] = obj->Vertices + p[i2]; 163 | if (MappingVertices) { 164 | obj->Faces[x].MappingU[0] = MappingVertices[m[0]*2]; 165 | obj->Faces[x].MappingV[0] = MappingVertices[m[0]*2+1]; 166 | obj->Faces[x].MappingU[1] = MappingVertices[m[i2+1]*2]; 167 | obj->Faces[x].MappingV[1] = MappingVertices[m[i2+1]*2+1]; 168 | obj->Faces[x].MappingU[2] = MappingVertices[m[i2]*2]; 169 | obj->Faces[x].MappingV[2] = MappingVertices[m[i2]*2+1]; 170 | } 171 | obj->Faces[x].Material = mat; 172 | x++; 173 | } 174 | x--; 175 | } 176 | } 177 | obj->BackfaceCull = 1; 178 | if (MappingVertices) free(MappingVertices); 179 | plObjCalcNormals(obj); 180 | fclose(fp); 181 | return obj; 182 | } 183 | -------------------------------------------------------------------------------- /source/read_jaw.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Plush Version 1.2 3 | read_jaw.c 4 | Jaw3D Object Reader 5 | Copyright (c) 1996-2000, Justin Frankel 6 | ******************************************************************************* 7 | Notes on .JAW files: 8 | This is a file format created by Jawed Karim for Jaw3D 9 | (http://jaw3d.home.ml.org). 10 | -- updated 11/6/00 - www.jawed.com 11 | It is very simple, and lets one easily create ones own models using only 12 | a text editor. The format is pretty simple: 13 | The first line must be "Light: (x,y,z)" where x,y, and z are the x y and 14 | z components of the lightsource vector (I think ;) 15 | A series of lines, numbered 0 to n, in the format of 16 | "i: x y z", where i is the vertex number (which should be listed in 17 | order, and x y and z are the coordinates of that vertex. 18 | A series of lines, having the format "tri a, b, c" where a b and c are 19 | the vertices that the face uses. It is unclear at this time which 20 | way the vertices are listed (ccw or cw), so just make em consistent 21 | and you can always use plFlipObjectNormals() on the loaded object. 22 | That is it! (I told ya it was simple). 23 | ******************************************************************************/ 24 | 25 | #include 26 | 27 | pl_Obj *plReadJAWObj(const char *filename, pl_Mat *m) { 28 | FILE *jawfile; 29 | pl_Obj *obj; 30 | pl_uInt32 i; 31 | pl_sInt crap; 32 | char line[256]; 33 | pl_uInt32 total_points = 0, total_polys = 0; 34 | if ((jawfile = fopen(filename, "r")) == NULL) return 0; 35 | fgets(line, 256, jawfile); /* Ignores lightsource info */ 36 | while (fgets(line, 256, jawfile) != NULL) 37 | if (strstr(line, ":") != NULL) total_points++; 38 | 39 | rewind(jawfile); fgets(line, 256, jawfile); 40 | while (fgets(line, 256, jawfile) != NULL) 41 | if (strstr(line, "tri") != NULL) total_polys++; 42 | 43 | rewind(jawfile); fgets(line, 256, jawfile); 44 | obj = plObjCreate(total_points,total_polys); 45 | 46 | i = 0; 47 | while (fgets(line, 256, jawfile) != NULL) if (strstr(line, ":") != NULL) { 48 | float x, y, z; 49 | sscanf(line, "%d: %f %f %f",&crap,&x,&y,&z); 50 | obj->Vertices[i].x = (pl_Float) x; 51 | obj->Vertices[i].y = (pl_Float) y; 52 | obj->Vertices[i].z = (pl_Float) z; 53 | i++; 54 | } 55 | rewind(jawfile); fgets(line, 256, jawfile); 56 | i = 0; 57 | while (fgets(line, 256, jawfile) != NULL) if (strstr(line, "tri") != NULL) { 58 | pl_uInt32 a,b,c; 59 | sscanf(line, "tri %ld, %ld, %ld", &a, &b, &c); 60 | obj->Faces[i].Vertices[0] = obj->Vertices + a; 61 | obj->Faces[i].Vertices[1] = obj->Vertices + c; 62 | obj->Faces[i].Vertices[2] = obj->Vertices + b; 63 | obj->Faces[i].Material = m; 64 | i++; 65 | } 66 | fclose(jawfile); 67 | plObjCalcNormals(obj); 68 | return obj; 69 | } 70 | -------------------------------------------------------------------------------- /source/read_pcx.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Plush Version 1.2 3 | read_pcx.c 4 | PCX Texture Reader 5 | Copyright (c) 1996-2000, Justin Frankel 6 | ******************************************************************************/ 7 | 8 | #include 9 | 10 | /* texture.c */ 11 | pl_uInt _plHiBit(pl_uInt16 x); 12 | pl_uInt _plOptimizeImage(pl_uChar *pal, pl_uChar *data, pl_uInt32 len); 13 | void _plRescaleImage(pl_uChar *in, pl_uChar *out, pl_uInt inx, 14 | pl_uInt iny, pl_uInt outx, pl_uInt outy); 15 | 16 | /* read_pcx.c */ 17 | static pl_sInt _plReadPCX(const char *filename, pl_uInt16 *width, pl_uInt16 *height, 18 | pl_uChar **pal, pl_uChar **data); 19 | 20 | pl_Texture *plReadPCXTex(const char *fn, pl_Bool rescale, pl_Bool optimize) { 21 | pl_uChar *data, *pal; 22 | pl_uInt16 x, y; 23 | pl_Texture *t; 24 | if (_plReadPCX(fn,&x,&y,&pal,&data) < 0) return 0; 25 | t = (pl_Texture *) malloc(sizeof(pl_Texture)); 26 | if (!t) return 0; 27 | t->Width = _plHiBit(x); 28 | t->Height = _plHiBit(y); 29 | if (rescale && (1 << t->Width != x || 1 << t->Height != y)) { 30 | pl_uChar nx, ny, *newdata; 31 | nx = t->Width; 32 | if ((1 << t->Width) != x) nx++; 33 | ny = t->Height; 34 | if ((1 << t->Height) != y) ny++; 35 | newdata = (pl_uChar *) malloc((1<Width = nx; 46 | t->Height = ny; 47 | x = 1<iWidth = x; 50 | t->iHeight = y; 51 | t->uScale = (pl_Float) (1<Width); 52 | t->vScale = (pl_Float) (1<Height); 53 | if (optimize) t->NumColors = _plOptimizeImage(pal, data,x*y); 54 | else t->NumColors = 256; 55 | t->Data = data; 56 | t->PaletteData = pal; 57 | return t; 58 | } 59 | 60 | static pl_sInt _plReadPCX(const char *filename, pl_uInt16 *width, pl_uInt16 *height, 61 | pl_uChar **pal, pl_uChar **data) { 62 | pl_uInt16 sx, sy, ex, ey; 63 | FILE *fp = fopen(filename,"rb"); 64 | pl_uChar *data2; 65 | if (!fp) return -1; 66 | fgetc(fp); 67 | if (fgetc(fp) != 5) { fclose(fp); return -2; } 68 | if (fgetc(fp) != 1) { fclose(fp); return -2; } 69 | if (fgetc(fp) != 8) { fclose(fp); return -3; } 70 | sx = fgetc(fp); sx |= fgetc(fp)<<8; 71 | sy = fgetc(fp); sy |= fgetc(fp)<<8; 72 | ex = fgetc(fp); ex |= fgetc(fp)<<8; 73 | ey = fgetc(fp); ey |= fgetc(fp)<<8; 74 | *width = ex - sx + 1; 75 | *height = ey - sy + 1; 76 | fseek(fp,128,SEEK_SET); 77 | if (feof(fp)) { fclose(fp); return -4; } 78 | *data = (pl_uChar *) malloc((*width) * (*height)); 79 | if (!*data) { fclose(fp); return -128; } 80 | sx = *height; 81 | data2 = *data; 82 | do { 83 | int xpos = 0; 84 | do { 85 | char c = fgetc(fp); 86 | if ((c & 192) == 192) { 87 | char oc = fgetc(fp); 88 | c &= ~192; 89 | do { 90 | *(data2++) = oc; 91 | xpos++; 92 | } while (--c && xpos < *width); 93 | } else { 94 | *(data2++) = c; 95 | xpos++; 96 | } 97 | } while (xpos < *width); 98 | } while (--sx); 99 | if (feof(fp)) { fclose(fp); free(*data); return -5; } 100 | fseek(fp,-769,SEEK_END); 101 | if (fgetc(fp) != 12) { fclose(fp); free(*data); return -6; } 102 | *pal = (pl_uChar *) malloc(768); 103 | if (!*pal) { fclose(fp); free(*data); return -7; } 104 | fread(*pal,3,256,fp); 105 | fclose(fp); 106 | return 0; 107 | } 108 | -------------------------------------------------------------------------------- /source/render.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Plush Version 1.2 3 | render.c 4 | Rendering code: this includes transformation, lighting, etc 5 | Copyright (c) 1996-2000, Justin Frankel 6 | ******************************************************************************/ 7 | 8 | #include 9 | 10 | typedef struct { 11 | pl_Float zd; 12 | pl_Face *face; 13 | } _faceInfo; 14 | 15 | typedef struct { 16 | pl_Light *light; 17 | pl_Float l[3]; 18 | } _lightInfo; 19 | 20 | #define MACRO_plMatrixApply(m,x,y,z,outx,outy,outz) \ 21 | ( outx ) = ( x )*( m )[0] + ( y )*( m )[1] + ( z )*( m )[2] + ( m )[3];\ 22 | ( outy ) = ( x )*( m )[4] + ( y )*( m )[5] + ( z )*( m )[6] + ( m )[7];\ 23 | ( outz ) = ( x )*( m )[8] + ( y )*( m )[9] + ( z )*( m )[10] + ( m )[11] 24 | 25 | #define MACRO_plDotProduct(x1,y1,z1,x2,y2,z2) \ 26 | ((( x1 )*( x2 ))+(( y1 )*( y2 ))+(( z1 )*( z2 ))) 27 | 28 | #define MACRO_plNormalizeVector(x,y,z) { \ 29 | double length; \ 30 | length = ( x )*( x )+( y )*( y )+( z )*( z ); \ 31 | if (length > 0.0000000001) { \ 32 | pl_Float l = (pl_Float) sqrt(length); \ 33 | ( x ) /= l; \ 34 | ( y ) /= l; \ 35 | ( z ) /= l; \ 36 | } \ 37 | } 38 | 39 | pl_uInt32 plRender_TriStats[4]; 40 | 41 | static pl_uInt32 _numfaces; 42 | static _faceInfo _faces[PL_MAX_TRIANGLES]; 43 | 44 | static pl_Float _cMatrix[16]; 45 | static pl_uInt32 _numlights; 46 | static _lightInfo _lights[PL_MAX_LIGHTS]; 47 | static pl_Cam *_cam; 48 | static void _RenderObj(pl_Obj *, pl_Float *, pl_Float *); 49 | static void _sift_down(int L, int U, int dir); 50 | static void _hsort(_faceInfo *base, int nel, int dir); 51 | 52 | void plRenderBegin(pl_Cam *Camera) { 53 | pl_Float tempMatrix[16]; 54 | memset(plRender_TriStats,0,sizeof(plRender_TriStats)); 55 | _cam = Camera; 56 | _numlights = 0; 57 | _numfaces = 0; 58 | plMatrixRotate(_cMatrix,2,-Camera->Pan); 59 | plMatrixRotate(tempMatrix,1,-Camera->Pitch); 60 | plMatrixMultiply(_cMatrix,tempMatrix); 61 | plMatrixRotate(tempMatrix,3,-Camera->Roll); 62 | plMatrixMultiply(_cMatrix,tempMatrix); 63 | plClipSetFrustum(_cam); 64 | } 65 | 66 | void plRenderLight(pl_Light *light) { 67 | pl_Float *pl, xp, yp, zp; 68 | if (light->Type == PL_LIGHT_NONE || _numlights >= PL_MAX_LIGHTS) return; 69 | pl = _lights[_numlights].l; 70 | if (light->Type == PL_LIGHT_VECTOR) { 71 | xp = light->Xp; 72 | yp = light->Yp; 73 | zp = light->Zp; 74 | MACRO_plMatrixApply(_cMatrix,xp,yp,zp,pl[0],pl[1],pl[2]); 75 | } else if (light->Type & PL_LIGHT_POINT) { 76 | xp = light->Xp-_cam->X; 77 | yp = light->Yp-_cam->Y; 78 | zp = light->Zp-_cam->Z; 79 | MACRO_plMatrixApply(_cMatrix,xp,yp,zp,pl[0],pl[1],pl[2]); 80 | } 81 | _lights[_numlights++].light = light; 82 | } 83 | 84 | static void _RenderObj(pl_Obj *obj, pl_Float *bmatrix, pl_Float *bnmatrix) { 85 | pl_uInt32 i, x, facepos; 86 | pl_Float nx = 0.0, ny = 0.0, nz = 0.0; 87 | double tmp, tmp2; 88 | pl_Float oMatrix[16], nMatrix[16], tempMatrix[16]; 89 | 90 | pl_Vertex *vertex; 91 | pl_Face *face; 92 | pl_Light *light; 93 | 94 | if (obj->GenMatrix) { 95 | plMatrixRotate(nMatrix,1,obj->Xa); 96 | plMatrixRotate(tempMatrix,2,obj->Ya); 97 | plMatrixMultiply(nMatrix,tempMatrix); 98 | plMatrixRotate(tempMatrix,3,obj->Za); 99 | plMatrixMultiply(nMatrix,tempMatrix); 100 | memcpy(oMatrix,nMatrix,sizeof(pl_Float)*16); 101 | } else memcpy(nMatrix,obj->RotMatrix,sizeof(pl_Float)*16); 102 | 103 | if (bnmatrix) plMatrixMultiply(nMatrix,bnmatrix); 104 | 105 | if (obj->GenMatrix) { 106 | plMatrixTranslate(tempMatrix, obj->Xp, obj->Yp, obj->Zp); 107 | plMatrixMultiply(oMatrix,tempMatrix); 108 | } else memcpy(oMatrix,obj->Matrix,sizeof(pl_Float)*16); 109 | if (bmatrix) plMatrixMultiply(oMatrix,bmatrix); 110 | 111 | for (i = 0; i < PL_MAX_CHILDREN; i ++) 112 | if (obj->Children[i]) _RenderObj(obj->Children[i],oMatrix,nMatrix); 113 | if (!obj->NumFaces || !obj->NumVertices) return; 114 | 115 | plMatrixTranslate(tempMatrix, -_cam->X, -_cam->Y, -_cam->Z); 116 | plMatrixMultiply(oMatrix,tempMatrix); 117 | plMatrixMultiply(oMatrix,_cMatrix); 118 | plMatrixMultiply(nMatrix,_cMatrix); 119 | 120 | x = obj->NumVertices; 121 | vertex = obj->Vertices; 122 | 123 | do { 124 | MACRO_plMatrixApply(oMatrix,vertex->x,vertex->y,vertex->z, 125 | vertex->xformedx, vertex->xformedy, vertex->xformedz); 126 | MACRO_plMatrixApply(nMatrix,vertex->nx,vertex->ny,vertex->nz, 127 | vertex->xformednx,vertex->xformedny,vertex->xformednz); 128 | vertex++; 129 | } while (--x); 130 | 131 | face = obj->Faces; 132 | facepos = _numfaces; 133 | 134 | if (_numfaces + obj->NumFaces >= PL_MAX_TRIANGLES) // exceeded maximum face coutn 135 | { 136 | return; 137 | } 138 | 139 | plRender_TriStats[0] += obj->NumFaces; 140 | _numfaces += obj->NumFaces; 141 | x = obj->NumFaces; 142 | 143 | do { 144 | if (obj->BackfaceCull || face->Material->_st & PL_SHADE_FLAT) 145 | { 146 | MACRO_plMatrixApply(nMatrix,face->nx,face->ny,face->nz,nx,ny,nz); 147 | } 148 | if (!obj->BackfaceCull || (MACRO_plDotProduct(nx,ny,nz, 149 | face->Vertices[0]->xformedx, face->Vertices[0]->xformedy, 150 | face->Vertices[0]->xformedz) < 0.0000001)) { 151 | if (plClipNeeded(face)) { 152 | if (face->Material->_st & (PL_SHADE_FLAT|PL_SHADE_FLAT_DISTANCE)) { 153 | tmp = face->sLighting; 154 | if (face->Material->_st & PL_SHADE_FLAT) { 155 | for (i = 0; i < _numlights; i ++) { 156 | tmp2 = 0.0; 157 | light = _lights[i].light; 158 | if (light->Type & PL_LIGHT_POINT_ANGLE) { 159 | double nx2 = _lights[i].l[0] - face->Vertices[0]->xformedx; 160 | double ny2 = _lights[i].l[1] - face->Vertices[0]->xformedy; 161 | double nz2 = _lights[i].l[2] - face->Vertices[0]->xformedz; 162 | MACRO_plNormalizeVector(nx2,ny2,nz2); 163 | tmp2 = MACRO_plDotProduct(nx,ny,nz,nx2,ny2,nz2)*light->Intensity; 164 | } 165 | if (light->Type & PL_LIGHT_POINT_DISTANCE) { 166 | double nx2 = _lights[i].l[0] - face->Vertices[0]->xformedx; 167 | double ny2 = _lights[i].l[1] - face->Vertices[0]->xformedy; 168 | double nz2 = _lights[i].l[2] - face->Vertices[0]->xformedz; 169 | if (light->Type & PL_LIGHT_POINT_ANGLE) { 170 | nx2 = (1.0 - 0.5*((nx2*nx2+ny2*ny2+nz2*nz2)/ 171 | light->HalfDistSquared)); 172 | tmp2 *= plMax(0,plMin(1.0,nx2))*light->Intensity; 173 | } else { 174 | tmp2 = (1.0 - 0.5*((nx2*nx2+ny2*ny2+nz2*nz2)/ 175 | light->HalfDistSquared)); 176 | tmp2 = plMax(0,plMin(1.0,tmp2))*light->Intensity; 177 | } 178 | } 179 | if (light->Type == PL_LIGHT_VECTOR) 180 | tmp2 = MACRO_plDotProduct(nx,ny,nz,_lights[i].l[0],_lights[i].l[1],_lights[i].l[2]) 181 | * light->Intensity; 182 | if (tmp2 > 0.0) tmp += tmp2; 183 | else if (obj->BackfaceIllumination) tmp -= tmp2; 184 | } /* End of light loop */ 185 | } /* End of flat shading if */ 186 | if (face->Material->_st & PL_SHADE_FLAT_DISTANCE) 187 | tmp += 1.0-(face->Vertices[0]->xformedz+face->Vertices[1]->xformedz+ 188 | face->Vertices[2]->xformedz) / 189 | (face->Material->FadeDist*3.0); 190 | face->fShade = (pl_Float) tmp; 191 | } else face->fShade = 0.0; /* End of flatmask lighting if */ 192 | if (face->Material->_ft & PL_FILL_ENVIRONMENT) { 193 | face->eMappingU[0] = 32768 + (pl_sInt32) (face->Vertices[0]->xformednx*32768.0); 194 | face->eMappingV[0] = 32768 - (pl_sInt32) (face->Vertices[0]->xformedny*32768.0); 195 | face->eMappingU[1] = 32768 + (pl_sInt32) (face->Vertices[1]->xformednx*32768.0); 196 | face->eMappingV[1] = 32768 - (pl_sInt32) (face->Vertices[1]->xformedny*32768.0); 197 | face->eMappingU[2] = 32768 + (pl_sInt32) (face->Vertices[2]->xformednx*32768.0); 198 | face->eMappingV[2] = 32768 - (pl_sInt32) (face->Vertices[2]->xformedny*32768.0); 199 | } 200 | if (face->Material->_st &(PL_SHADE_GOURAUD|PL_SHADE_GOURAUD_DISTANCE)) { 201 | pl_uChar a; 202 | for (a = 0; a < 3; a ++) { 203 | tmp = face->vsLighting[a]; 204 | if (face->Material->_st & PL_SHADE_GOURAUD) { 205 | for (i = 0; i < _numlights ; i++) { 206 | tmp2 = 0.0; 207 | light = _lights[i].light; 208 | if (light->Type & PL_LIGHT_POINT_ANGLE) { 209 | nx = _lights[i].l[0] - face->Vertices[a]->xformedx; 210 | ny = _lights[i].l[1] - face->Vertices[a]->xformedy; 211 | nz = _lights[i].l[2] - face->Vertices[a]->xformedz; 212 | MACRO_plNormalizeVector(nx,ny,nz); 213 | tmp2 = MACRO_plDotProduct(face->Vertices[a]->xformednx, 214 | face->Vertices[a]->xformedny, 215 | face->Vertices[a]->xformednz, 216 | nx,ny,nz) * light->Intensity; 217 | } 218 | if (light->Type & PL_LIGHT_POINT_DISTANCE) { 219 | double nx2 = _lights[i].l[0] - face->Vertices[a]->xformedx; 220 | double ny2 = _lights[i].l[1] - face->Vertices[a]->xformedy; 221 | double nz2 = _lights[i].l[2] - face->Vertices[a]->xformedz; 222 | if (light->Type & PL_LIGHT_POINT_ANGLE) { 223 | double t= (1.0 - 0.5*((nx2*nx2+ny2*ny2+nz2*nz2)/light->HalfDistSquared)); 224 | tmp2 *= plMax(0,plMin(1.0,t))*light->Intensity; 225 | } else { 226 | tmp2 = (1.0 - 0.5*((nx2*nx2+ny2*ny2+nz2*nz2)/light->HalfDistSquared)); 227 | tmp2 = plMax(0,plMin(1.0,tmp2))*light->Intensity; 228 | } 229 | } 230 | if (light->Type == PL_LIGHT_VECTOR) 231 | tmp2 = MACRO_plDotProduct(face->Vertices[a]->xformednx, 232 | face->Vertices[a]->xformedny, 233 | face->Vertices[a]->xformednz, 234 | _lights[i].l[0],_lights[i].l[1],_lights[i].l[2]) 235 | * light->Intensity; 236 | if (tmp2 > 0.0) tmp += tmp2; 237 | else if (obj->BackfaceIllumination) tmp -= tmp2; 238 | } /* End of light loop */ 239 | } /* End of gouraud shading if */ 240 | if (face->Material->_st & PL_SHADE_GOURAUD_DISTANCE) 241 | tmp += 1.0-face->Vertices[a]->xformedz/face->Material->FadeDist; 242 | face->Shades[a] = (pl_Float) tmp; 243 | } /* End of vertex loop for */ 244 | } /* End of gouraud shading mask if */ 245 | _faces[facepos].zd = face->Vertices[0]->xformedz+ 246 | face->Vertices[1]->xformedz+face->Vertices[2]->xformedz; 247 | _faces[facepos++].face = face; 248 | plRender_TriStats[1] ++; 249 | } /* Is it in our area Check */ 250 | } /* Backface Check */ 251 | _numfaces = facepos; 252 | face++; 253 | } while (--x); /* Face loop */ 254 | } 255 | 256 | void plRenderObj(pl_Obj *obj) { 257 | _RenderObj(obj,0,0); 258 | } 259 | 260 | void plRenderEnd() { 261 | _faceInfo *f; 262 | if (_cam->Sort > 0) _hsort(_faces,_numfaces,0); 263 | else if (_cam->Sort < 0) _hsort(_faces,_numfaces,1); 264 | f = _faces; 265 | while (_numfaces--) { 266 | if (f->face->Material && f->face->Material->_PutFace) 267 | { 268 | plClipRenderFace(f->face); 269 | } 270 | f++; 271 | } 272 | _numfaces=0; 273 | _numlights = 0; 274 | } 275 | 276 | static _faceInfo *Base, tmp; 277 | 278 | static void _hsort(_faceInfo *base, int nel, int dir) { 279 | static int i; 280 | Base=base-1; 281 | for (i=nel/2; i>0; i--) _sift_down(i,nel,dir); 282 | for (i=nel; i>1; ) { 283 | tmp = base[0]; base[0] = Base[i]; Base[i] = tmp; 284 | _sift_down(1,i-=1,dir); 285 | } 286 | } 287 | 288 | #define Comp(x,y) (( x ).zd < ( y ).zd ? 1 : 0) 289 | 290 | static void _sift_down(int L, int U, int dir) { 291 | static int c; 292 | while (1) { 293 | c=L+L; 294 | if (c>U) break; 295 | if ( (c < U) && dir^Comp(Base[c+1],Base[c])) c++; 296 | if (dir^Comp(Base[L],Base[c])) return; 297 | tmp = Base[L]; Base[L] = Base[c]; Base[c] = tmp; 298 | L=c; 299 | } 300 | } 301 | #undef Comp 302 | -------------------------------------------------------------------------------- /source/spline.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Plush Version 1.2 3 | spline.c 4 | n-th Dimensional Spline Interpolator 5 | Copyright (c) 1996-2000, Justin Frankel 6 | ******************************************************************************/ 7 | 8 | #include 9 | 10 | void plSplineGetPoint(pl_Spline *s, pl_Float frame, pl_Float *out) { 11 | pl_sInt32 i, i_1, i0, i1, i2; 12 | pl_Float time1,time2,time3; 13 | pl_Float t1,t2,t3,t4,u1,u2,u3,u4,v1,v2,v3; 14 | pl_Float a,b,c,d; 15 | 16 | pl_Float *keys = s->keys; 17 | 18 | a = (1-s->tens)*(1+s->cont)*(1+s->bias); 19 | b = (1-s->tens)*(1-s->cont)*(1-s->bias); 20 | c = (1-s->tens)*(1-s->cont)*(1+s->bias); 21 | d = (1-s->tens)*(1+s->cont)*(1-s->bias); 22 | v1 = t1 = -a / 2.0; u1 = a; 23 | u2 = (-6-2*a+2*b+c)/2.0; v2 = (a-b)/2.0; t2 = (4+a-b-c) / 2.0; 24 | t3 = (-4+b+c-d) / 2.0; 25 | u3 = (6-2*b-c+d)/2.0; 26 | v3 = b/2.0; 27 | t4 = d/2.0; u4 = -t4; 28 | 29 | i0 = (pl_uInt) frame; 30 | i_1 = i0 - 1; 31 | while (i_1 < 0) i_1 += s->numKeys; 32 | i1 = i0 + 1; 33 | while (i1 >= s->numKeys) i1 -= s->numKeys; 34 | i2 = i0 + 2; 35 | while (i2 >= s->numKeys) i2 -= s->numKeys; 36 | time1 = frame - (pl_Float) ((pl_uInt) frame); 37 | time2 = time1*time1; 38 | time3 = time2*time1; 39 | i0 *= s->keyWidth; 40 | i1 *= s->keyWidth; 41 | i2 *= s->keyWidth; 42 | i_1 *= s->keyWidth; 43 | for (i = 0; i < s->keyWidth; i ++) { 44 | a = t1*keys[i+i_1]+t2*keys[i+i0]+t3*keys[i+i1]+t4*keys[i+i2]; 45 | b = u1*keys[i+i_1]+u2*keys[i+i0]+u3*keys[i+i1]+u4*keys[i+i2]; 46 | c = v1*keys[i+i_1]+v2*keys[i+i0]+v3*keys[i+i1]; 47 | *out++ = a*time3 + b*time2 + c*time1 + keys[i+i0]; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /source/text.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Plush Version 1.1 3 | text.c 4 | Text code and data (8xX bitmapped) 5 | Copyright (c) 1996-2000, Justin Frankel 6 | ******************************************************************************/ 7 | 8 | #include 9 | #include 10 | 11 | static pl_uChar font_height = 16; 12 | 13 | static pl_uChar *current_font = plText_DefaultFont; 14 | 15 | void plTextSetFont(pl_uChar *font, pl_uChar height) { 16 | current_font = font; 17 | font_height = height; 18 | } 19 | 20 | void plTextPutChar(pl_Cam *cam, pl_sInt x, pl_sInt y, pl_Float z, 21 | pl_uChar color, pl_uChar c) { 22 | pl_uChar *font = current_font + (c*font_height); 23 | pl_sInt offset = x+(y*cam->ScreenWidth); 24 | pl_ZBuffer zz = (pl_ZBuffer) (1.0/z); 25 | pl_sInt xx = x, a; 26 | pl_uChar len = font_height; 27 | pl_uChar ch; 28 | pl_uChar *outmem; 29 | pl_ZBuffer *zbuffer; 30 | if (y+font_height < cam->ClipTop || y >= cam->ClipBottom) return; 31 | if (y < cam->ClipTop) { 32 | font += (cam->ClipTop-y); 33 | offset += (cam->ClipTop-y)*cam->ScreenWidth; 34 | len -= (cam->ClipTop-y); 35 | y = cam->ClipTop; 36 | } 37 | if (y+font_height >= cam->ClipBottom) { 38 | len = cam->ClipBottom-y; 39 | } 40 | if (len > 0) { 41 | if (cam->zBuffer && z != 0.0) do { 42 | outmem = cam->frameBuffer + offset; 43 | zbuffer = cam->zBuffer + offset; 44 | offset += cam->ScreenWidth; 45 | xx = x; 46 | ch = *font++; 47 | a = 128; 48 | while (a) { 49 | if (xx >= cam->ClipRight) break; 50 | if (xx++ >= cam->ClipLeft) 51 | if (ch & a) 52 | if (zz > *zbuffer) { 53 | *zbuffer = zz; 54 | *outmem = color; 55 | } 56 | zbuffer++; 57 | outmem++; 58 | a >>= 1; 59 | } 60 | if (a) break; 61 | } while (--len); 62 | else do { 63 | outmem = cam->frameBuffer + offset; 64 | offset += cam->ScreenWidth; 65 | xx = x; 66 | ch = *font++; 67 | a = 128; 68 | while (a) { 69 | if (xx >= cam->ClipRight) break; 70 | if (xx++ >= cam->ClipLeft) if (ch & a) *outmem = color; 71 | outmem++; 72 | a >>= 1; 73 | } 74 | if (a) break; 75 | } while (--len); 76 | } 77 | } 78 | 79 | void plTextPutStr(pl_Cam *cam, pl_sInt x, pl_sInt y, pl_Float z, 80 | pl_uChar color, const char *string) { 81 | pl_sInt xx = x; 82 | while (*string) { 83 | switch (*string) { 84 | case '\n': y += font_height; xx = x; break; 85 | case ' ': xx += 8; break; 86 | case '\r': break; 87 | case '\t': xx += 8*5; break; 88 | default: 89 | plTextPutChar(cam,xx,y,z,color,(pl_uChar) *string); 90 | xx += 8; 91 | break; 92 | } 93 | string++; 94 | } 95 | } 96 | 97 | void plTextPrintf(pl_Cam *cam, pl_sInt x, pl_sInt y, pl_Float z, 98 | pl_uChar color, const char *format, ...) { 99 | va_list arglist; 100 | char str[256]; 101 | va_start(arglist, format); 102 | vsprintf((char *)str, (char *) format,arglist); 103 | va_end(arglist); 104 | plTextPutStr(cam,x,y,z,color,str); 105 | } 106 | -------------------------------------------------------------------------------- /source/texture.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Plush Version 1.2 3 | texture.c 4 | Texture routines 5 | Copyright (c) 2024, erysdren (it/she/they) 6 | ******************************************************************************/ 7 | 8 | #include 9 | 10 | pl_uInt _plHiBit(pl_uInt16 x) { 11 | pl_uInt i = 16, mask = 1<<15; 12 | while (mask) { 13 | if (x & mask) return i; 14 | mask >>= 1; i--; 15 | } 16 | return 0; 17 | } 18 | 19 | pl_uInt _plOptimizeImage(pl_uChar *pal, pl_uChar *data, pl_uInt32 len) { 20 | pl_uChar colors[256], *dd = data; 21 | pl_uChar remap[256]; 22 | pl_sInt32 lastused, firstunused; 23 | pl_uInt32 x; 24 | memset(colors,0,256); 25 | for (x = 0; x < len; x ++) colors[(pl_uInt) *dd++] = 1; 26 | lastused = -1; 27 | for (x = 0; x < 256; x ++) remap[x] = (pl_uChar)x; 28 | lastused = 255; 29 | firstunused = 0; 30 | for (;;) { 31 | while (firstunused < 256 && colors[firstunused]) firstunused++; 32 | if (firstunused > 255) break; 33 | while (lastused >= 0 && !colors[lastused]) lastused--; 34 | if (lastused < 0) break; 35 | if (lastused <= firstunused) break; 36 | pal[firstunused*3] = pal[lastused*3]; 37 | pal[firstunused*3+1] = pal[lastused*3+1]; 38 | pal[firstunused*3+2] = pal[lastused*3+2]; 39 | colors[lastused] = 0; 40 | colors[firstunused] = 1; 41 | remap[lastused] = (pl_uChar) firstunused; 42 | } 43 | x = len; 44 | while (x--) *data++ = remap[(pl_uInt) *data]; 45 | return (lastused+1); 46 | } 47 | 48 | void _plRescaleImage(pl_uChar *in, pl_uChar *out, pl_uInt inw, 49 | pl_uInt inh, pl_uInt outx, pl_uInt outy) { 50 | pl_uInt x; 51 | pl_uInt32 X, dX, dY, Y; 52 | dX = (inw<<16) / outx; 53 | dY = (inh<<16) / outy; 54 | Y = 0; 55 | do { 56 | pl_uChar *ptr = in + inw*(Y>>16); 57 | X = 0; 58 | Y += dY; 59 | x = outx; 60 | do { 61 | *out++ = ptr[X>>16]; 62 | X += dX; 63 | } while (--x); 64 | } while (--outy); 65 | } 66 | 67 | pl_Texture *plTexCreate(pl_uInt w, pl_uInt h, pl_uChar *p, pl_uInt nc, pl_uChar *c) 68 | { 69 | pl_Texture *t = (pl_Texture *)malloc(sizeof(pl_Texture)); 70 | 71 | /* create copy of palette data */ 72 | t->PaletteData = (pl_uChar *)malloc(nc * 3); 73 | memcpy(t->PaletteData, c, nc * 3); 74 | 75 | /* rescale image */ 76 | t->Width = _plHiBit(w); 77 | t->Height = _plHiBit(h); 78 | if (1 << t->Width != w || 1 << t->Height != h) 79 | { 80 | pl_uChar nw, nh; 81 | 82 | nw = t->Width; 83 | if ((1 << t->Width) != w) nw++; 84 | 85 | nh = t->Height; 86 | if ((1 << t->Height) != h) nh++; 87 | 88 | t->Data = (pl_uChar *)malloc((1 << nw) * (1 << nh)); 89 | 90 | _plRescaleImage(p, t->Data, w, h, 1 << nw, 1 << nh); 91 | 92 | t->Width = nw; 93 | t->Height = nh; 94 | w = 1 << nw; 95 | h = 1 << nh; 96 | } 97 | else 98 | { 99 | /* create copy of pixel data */ 100 | t->Data = (pl_uChar *)malloc(w * h); 101 | memcpy(t->Data, p, w * h); 102 | } 103 | 104 | /* setup fields */ 105 | t->iWidth = w; 106 | t->iHeight = h; 107 | t->uScale = (pl_Float)(1 << t->Width); 108 | t->vScale = (pl_Float)(1 << t->Height); 109 | t->NumColors = nc; 110 | 111 | return t; 112 | } 113 | 114 | void plTexDelete(pl_Texture *t) { 115 | if (t) { 116 | if (t->Data) free(t->Data); 117 | if (t->PaletteData) free(t->PaletteData); 118 | free(t); 119 | } 120 | } 121 | --------------------------------------------------------------------------------