From 065d2c64aa06f049ac78b9b051d2c4ff5d17543a Mon Sep 17 00:00:00 2001 From: Toby Jaffey Date: Sun, 14 Dec 2025 14:45:10 +0000 Subject: [PATCH] TinyGL example --- README.md | 1 + apps/Makefile | 2 + apps/tinygl/Makefile | 18 + apps/tinygl/build.zig | 87 + apps/tinygl/build.zig.zon | 40 + apps/tinygl/src/SDL_scancode.h | 436 ++++ apps/tinygl/src/TinyGL/BeOS/GLView.cpp | 205 ++ apps/tinygl/src/TinyGL/BeOS/GLView.h | 72 + apps/tinygl/src/TinyGL/BeOS/Makefile | 16 + apps/tinygl/src/TinyGL/Changelog | 44 + apps/tinygl/src/TinyGL/INSTALL | 10 + apps/tinygl/src/TinyGL/LICENSE | 21 + apps/tinygl/src/TinyGL/LIMITATIONS | 206 ++ apps/tinygl/src/TinyGL/Makefile | 15 + apps/tinygl/src/TinyGL/README | 150 ++ apps/tinygl/src/TinyGL/README.BEOS | 20 + apps/tinygl/src/TinyGL/config.mk | 82 + apps/tinygl/src/TinyGL/examples/Makefile | 29 + apps/tinygl/src/TinyGL/examples/gears.c | 300 +++ apps/tinygl/src/TinyGL/examples/glu.c | 261 +++ apps/tinygl/src/TinyGL/examples/glu.h | 23 + apps/tinygl/src/TinyGL/examples/mech.c | 1753 +++++++++++++++++ apps/tinygl/src/TinyGL/examples/nanox.c | 113 ++ apps/tinygl/src/TinyGL/examples/spin.c | 161 ++ apps/tinygl/src/TinyGL/examples/texobj.c | 193 ++ apps/tinygl/src/TinyGL/examples/ui.h | 17 + apps/tinygl/src/TinyGL/examples/x11.c | 139 ++ apps/tinygl/src/TinyGL/include/GL/gl.h | 838 ++++++++ apps/tinygl/src/TinyGL/include/GL/glx.h | 144 ++ apps/tinygl/src/TinyGL/include/GL/nglx.h | 27 + apps/tinygl/src/TinyGL/include/GL/oscontext.h | 37 + apps/tinygl/src/TinyGL/include/GLView.h | 72 + apps/tinygl/src/TinyGL/src/Makefile | 43 + apps/tinygl/src/TinyGL/src/api.c | 668 +++++++ apps/tinygl/src/TinyGL/src/arrays.c | 207 ++ apps/tinygl/src/TinyGL/src/clear.c | 30 + apps/tinygl/src/TinyGL/src/clip.c | 445 +++++ apps/tinygl/src/TinyGL/src/error.c | 17 + apps/tinygl/src/TinyGL/src/get.c | 73 + apps/tinygl/src/TinyGL/src/glx.c | 413 ++++ apps/tinygl/src/TinyGL/src/image_util.c | 136 ++ apps/tinygl/src/TinyGL/src/init.c | 189 ++ apps/tinygl/src/TinyGL/src/light.c | 304 +++ apps/tinygl/src/TinyGL/src/list.c | 260 +++ apps/tinygl/src/TinyGL/src/matrix.c | 244 +++ apps/tinygl/src/TinyGL/src/memory.c | 21 + apps/tinygl/src/TinyGL/src/misc.c | 147 ++ apps/tinygl/src/TinyGL/src/msghandling.c | 52 + apps/tinygl/src/TinyGL/src/msghandling.h | 8 + apps/tinygl/src/TinyGL/src/nglx.c | 128 ++ apps/tinygl/src/TinyGL/src/opinfo.h | 71 + apps/tinygl/src/TinyGL/src/oscontext.c | 85 + apps/tinygl/src/TinyGL/src/select.c | 114 ++ apps/tinygl/src/TinyGL/src/specbuf.c | 52 + apps/tinygl/src/TinyGL/src/specbuf.h | 22 + apps/tinygl/src/TinyGL/src/texture.c | 229 +++ apps/tinygl/src/TinyGL/src/vertex.c | 364 ++++ apps/tinygl/src/TinyGL/src/zbuffer.c | 518 +++++ apps/tinygl/src/TinyGL/src/zbuffer.h | 162 ++ apps/tinygl/src/TinyGL/src/zdither.c | 163 ++ apps/tinygl/src/TinyGL/src/zfeatures.h | 43 + apps/tinygl/src/TinyGL/src/zgl.h | 385 ++++ apps/tinygl/src/TinyGL/src/zline.c | 84 + apps/tinygl/src/TinyGL/src/zline.h | 121 ++ apps/tinygl/src/TinyGL/src/zmath.c | 276 +++ apps/tinygl/src/TinyGL/src/zmath.h | 53 + apps/tinygl/src/TinyGL/src/ztriangle.c | 394 ++++ apps/tinygl/src/TinyGL/src/ztriangle.h | 363 ++++ apps/tinygl/src/console.zig | 49 + apps/tinygl/src/main.zig | 416 ++++ apps/tinygl/src/uvm.zig | 84 + precompiled/tinygl.bin | Bin 0 -> 99024 bytes 72 files changed, 12965 insertions(+) create mode 100644 apps/tinygl/Makefile create mode 100644 apps/tinygl/build.zig create mode 100644 apps/tinygl/build.zig.zon create mode 100644 apps/tinygl/src/SDL_scancode.h create mode 100644 apps/tinygl/src/TinyGL/BeOS/GLView.cpp create mode 100644 apps/tinygl/src/TinyGL/BeOS/GLView.h create mode 100644 apps/tinygl/src/TinyGL/BeOS/Makefile create mode 100644 apps/tinygl/src/TinyGL/Changelog create mode 100644 apps/tinygl/src/TinyGL/INSTALL create mode 100644 apps/tinygl/src/TinyGL/LICENSE create mode 100644 apps/tinygl/src/TinyGL/LIMITATIONS create mode 100644 apps/tinygl/src/TinyGL/Makefile create mode 100644 apps/tinygl/src/TinyGL/README create mode 100644 apps/tinygl/src/TinyGL/README.BEOS create mode 100644 apps/tinygl/src/TinyGL/config.mk create mode 100644 apps/tinygl/src/TinyGL/examples/Makefile create mode 100644 apps/tinygl/src/TinyGL/examples/gears.c create mode 100644 apps/tinygl/src/TinyGL/examples/glu.c create mode 100644 apps/tinygl/src/TinyGL/examples/glu.h create mode 100644 apps/tinygl/src/TinyGL/examples/mech.c create mode 100644 apps/tinygl/src/TinyGL/examples/nanox.c create mode 100644 apps/tinygl/src/TinyGL/examples/spin.c create mode 100644 apps/tinygl/src/TinyGL/examples/texobj.c create mode 100644 apps/tinygl/src/TinyGL/examples/ui.h create mode 100644 apps/tinygl/src/TinyGL/examples/x11.c create mode 100644 apps/tinygl/src/TinyGL/include/GL/gl.h create mode 100644 apps/tinygl/src/TinyGL/include/GL/glx.h create mode 100644 apps/tinygl/src/TinyGL/include/GL/nglx.h create mode 100644 apps/tinygl/src/TinyGL/include/GL/oscontext.h create mode 100644 apps/tinygl/src/TinyGL/include/GLView.h create mode 100644 apps/tinygl/src/TinyGL/src/Makefile create mode 100644 apps/tinygl/src/TinyGL/src/api.c create mode 100644 apps/tinygl/src/TinyGL/src/arrays.c create mode 100644 apps/tinygl/src/TinyGL/src/clear.c create mode 100644 apps/tinygl/src/TinyGL/src/clip.c create mode 100644 apps/tinygl/src/TinyGL/src/error.c create mode 100644 apps/tinygl/src/TinyGL/src/get.c create mode 100644 apps/tinygl/src/TinyGL/src/glx.c create mode 100644 apps/tinygl/src/TinyGL/src/image_util.c create mode 100644 apps/tinygl/src/TinyGL/src/init.c create mode 100644 apps/tinygl/src/TinyGL/src/light.c create mode 100644 apps/tinygl/src/TinyGL/src/list.c create mode 100644 apps/tinygl/src/TinyGL/src/matrix.c create mode 100644 apps/tinygl/src/TinyGL/src/memory.c create mode 100644 apps/tinygl/src/TinyGL/src/misc.c create mode 100644 apps/tinygl/src/TinyGL/src/msghandling.c create mode 100644 apps/tinygl/src/TinyGL/src/msghandling.h create mode 100644 apps/tinygl/src/TinyGL/src/nglx.c create mode 100644 apps/tinygl/src/TinyGL/src/opinfo.h create mode 100644 apps/tinygl/src/TinyGL/src/oscontext.c create mode 100644 apps/tinygl/src/TinyGL/src/select.c create mode 100644 apps/tinygl/src/TinyGL/src/specbuf.c create mode 100644 apps/tinygl/src/TinyGL/src/specbuf.h create mode 100644 apps/tinygl/src/TinyGL/src/texture.c create mode 100644 apps/tinygl/src/TinyGL/src/vertex.c create mode 100644 apps/tinygl/src/TinyGL/src/zbuffer.c create mode 100644 apps/tinygl/src/TinyGL/src/zbuffer.h create mode 100644 apps/tinygl/src/TinyGL/src/zdither.c create mode 100644 apps/tinygl/src/TinyGL/src/zfeatures.h create mode 100644 apps/tinygl/src/TinyGL/src/zgl.h create mode 100644 apps/tinygl/src/TinyGL/src/zline.c create mode 100644 apps/tinygl/src/TinyGL/src/zline.h create mode 100644 apps/tinygl/src/TinyGL/src/zmath.c create mode 100644 apps/tinygl/src/TinyGL/src/zmath.h create mode 100644 apps/tinygl/src/TinyGL/src/ztriangle.c create mode 100644 apps/tinygl/src/TinyGL/src/ztriangle.h create mode 100644 apps/tinygl/src/console.zig create mode 100644 apps/tinygl/src/main.zig create mode 100644 apps/tinygl/src/uvm.zig create mode 100755 precompiled/tinygl.bin diff --git a/README.md b/README.md index d39970e..c3d4f12 100644 --- a/README.md +++ b/README.md @@ -138,6 +138,7 @@ int main(int argc, char *argv[]) { * [apps/zigtris](apps/zigtris) Zig Tetris (https://github.com/ringtailsoftware/zigtris) * [apps/zigalloc](apps/zigalloc) Demonstration of using extram with zig allocator * [apps/zigdoom](apps/zigdoom) Port of PureDOOM (making use of Zig to provide an allocator and libc like functions) + * [apps/tinygl](apps/tinygl) TinyGL gears (softfp stress test) * Assembly sample apps * [apps/hello-asm](apps/hello-asm) Minimal hello world assembly * VM host as an app diff --git a/apps/Makefile b/apps/Makefile index 4616512..47a4daf 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -15,6 +15,7 @@ all: (cd zigalloc && make) (cd gfx && make) (cd zigdoom && make) + (cd tinygl && make) clean: (cd sketch && make clean) @@ -33,4 +34,5 @@ clean: (cd zigalloc && make clean) (cd gfx && make clean) (cd zigdoom && make clean) + (cd tinygl && make clean) diff --git a/apps/tinygl/Makefile b/apps/tinygl/Makefile new file mode 100644 index 0000000..3829dc4 --- /dev/null +++ b/apps/tinygl/Makefile @@ -0,0 +1,18 @@ +PROJECT=tinygl +TOPDIR=../.. + +HEAP_SIZE=$(shell echo "1024 * 1024 * 8" | bc) +HOST_EXTRA=-e ${HEAP_SIZE} -i 9999999 + +all: + @# zig's objcopy is broken, so use external tool + @# https://ziggit.dev/t/addobjcopy-producing-zero-padding-at-start-of-binary/13384 + zig build -Dheapsize=${HEAP_SIZE} && ${PREFIX}objcopy zig-out/bin/${PROJECT} -O binary ${PROJECT}.bin + +clean: clean_common + rm -rf zig-out .zig-cache + +test: all + ${TOPDIR}/hosts/host-sdl/host-sdl ${HOST_EXTRA} ${PROJECT}.bin + +include ${TOPDIR}/apps/common/makefile.common diff --git a/apps/tinygl/build.zig b/apps/tinygl/build.zig new file mode 100644 index 0000000..a86e2af --- /dev/null +++ b/apps/tinygl/build.zig @@ -0,0 +1,87 @@ +const std = @import("std"); +const CrossTarget = @import("std").zig.CrossTarget; +const Target = @import("std").Target; +const Feature = @import("std").Target.Cpu.Feature; + +pub fn build(b: *std.Build) void { + var options = b.addOptions(); + const heapsize = b.option(u32, "heapsize", "heap size in bytes") orelse 0; // -Dheapsize=u32 + options.addOption(u32, "heapsize", heapsize); + + const features = Target.riscv.Feature; + var disabled_features = Feature.Set.empty; + var enabled_features = Feature.Set.empty; + + // disable all CPU extensions + disabled_features.addFeature(@intFromEnum(features.a)); + disabled_features.addFeature(@intFromEnum(features.c)); + disabled_features.addFeature(@intFromEnum(features.d)); + disabled_features.addFeature(@intFromEnum(features.e)); + disabled_features.addFeature(@intFromEnum(features.f)); + // except multiply + enabled_features.addFeature(@intFromEnum(features.m)); + + const target = b.resolveTargetQuery(.{ .cpu_arch = Target.Cpu.Arch.riscv32, .os_tag = Target.Os.Tag.freestanding, .abi = Target.Abi.none, .cpu_model = .{ .explicit = &std.Target.riscv.cpu.generic_rv32 }, .cpu_features_sub = disabled_features, .cpu_features_add = enabled_features }); + + const exe = b.addExecutable(.{ + .name = "tinygl", + .root_module = b.createModule(.{ + .root_source_file = b.path("src/main.zig"), + .target = target, + .optimize = .ReleaseSmall, + }), + }); + exe.root_module.addOptions("buildopts", options); + + // add zeptolibc + const zeptolibc_dep = b.dependency("zeptolibc", .{ + .target = target, + .optimize = .ReleaseSmall, + }); + exe.root_module.addImport("zeptolibc", zeptolibc_dep.module("zeptolibc")); + exe.root_module.addIncludePath(zeptolibc_dep.path("include")); + exe.root_module.addIncludePath(zeptolibc_dep.path("include/zeptolibc")); + + exe.addCSourceFiles(.{ .files = &.{ + "src/TinyGL/src/api.c", + "src/TinyGL/src/specbuf.c", + "src/TinyGL/src/zmath.c", + "src/TinyGL/src/arrays.c", + "src/TinyGL/src/image_util.c", + "src/TinyGL/src/misc.c", + "src/TinyGL/src/texture.c", + "src/TinyGL/src/ztriangle.c", + "src/TinyGL/src/clear.c", + "src/TinyGL/src/init.c", + "src/TinyGL/src/msghandling.c", + "src/TinyGL/src/vertex.c", + "src/TinyGL/src/clip.c", + "src/TinyGL/src/light.c", + "src/TinyGL/src/zbuffer.c", + "src/TinyGL/src/error.c", + "src/TinyGL/src/list.c", + "src/TinyGL/src/zdither.c", + "src/TinyGL/src/get.c", + "src/TinyGL/src/matrix.c", + "src/TinyGL/src/select.c", + "src/TinyGL/src/zline.c", + }, .flags = &.{ "-Wall", "-fno-sanitize=undefined" } }); + exe.addIncludePath(b.path("src/")); + exe.addIncludePath(b.path("src/TinyGL/include")); + exe.addIncludePath(b.path("src/TinyGL/src")); + + b.installArtifact(exe); + + exe.addAssemblyFile(b.path("../common/crt0.S")); + exe.setLinkerScript(b.path("../common/linker.ld")); + exe.addIncludePath(b.path("../../common")); + exe.addIncludePath(b.path("../common")); + + const bin = b.addObjCopy(exe.getEmittedBin(), .{ + .format = .bin, + }); + bin.step.dependOn(&exe.step); + + const copy_bin = b.addInstallBinFile(bin.getOutput(), "tinygl.bin"); + b.default_step.dependOn(©_bin.step); +} diff --git a/apps/tinygl/build.zig.zon b/apps/tinygl/build.zig.zon new file mode 100644 index 0000000..1f5273d --- /dev/null +++ b/apps/tinygl/build.zig.zon @@ -0,0 +1,40 @@ +.{ + // This is the default name used by packages depending on this one. For + // example, when a user runs `zig fetch --save `, this field is used + // as the key in the `dependencies` table. Although the user can choose a + // different name, most users will stick with this provided value. + // + // It is redundant to include "zig" in this name because it is already + // within the Zig package namespace. + .name = .zigdoom, + .fingerprint = 0xf734231076ec3b9f, + + // This is a [Semantic Version](https://semver.org/). + // In a future version of Zig it will be used for package deduplication. + .version = "0.0.1", + + // This field is optional. + // This is currently advisory only; Zig does not yet do anything + // with this value. + //.minimum_zig_version = "0.11.0", + + // This field is optional. + // Each dependency must either provide a `url` and `hash`, or a `path`. + // `zig build --fetch` can be used to fetch all dependencies of a package, recursively. + // Once all dependencies are fetched, `zig build` no longer requires + // internet connectivity. + .dependencies = .{ + .zeptolibc = .{ + .url = "git+https://github.com/ringtailsoftware/zeptolibc.git#d787abfdd597bee5616a439f12393e11fb370822", + .hash = "zeptolibc-0.0.1-T3flJ4M4AAAEx1K1DS-SmkmuXvJJ3JqnNHIw4Aqo0PfD", + }, + }, + .paths = .{ + "build.zig", + "build.zig.zon", + "src", + // For example... + //"LICENSE", + //"README.md", + }, +} diff --git a/apps/tinygl/src/SDL_scancode.h b/apps/tinygl/src/SDL_scancode.h new file mode 100644 index 0000000..3c9ad77 --- /dev/null +++ b/apps/tinygl/src/SDL_scancode.h @@ -0,0 +1,436 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + + 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. + + 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: + + 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. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/** + * \file SDL_scancode.h + * + * \brief Defines keyboard scancodes. + */ + +#ifndef SDL_scancode_h_ +#define SDL_scancode_h_ + +//#include + +/** + * \brief The SDL keyboard scancode representation. + * + * Values of this type are used to represent keyboard keys, among other places + * in the \link SDL_Keysym::scancode key.keysym.scancode \endlink field of the + * SDL_Event structure. + * + * The values in this enumeration are based on the USB usage page standard: + * https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf + */ +typedef enum +{ + SDL_SCANCODE_UNKNOWN = 0, + + /** + * \name Usage page 0x07 + * + * These values are from usage page 0x07 (USB keyboard page). + */ + /* @{ */ + + SDL_SCANCODE_A = 4, + SDL_SCANCODE_B = 5, + SDL_SCANCODE_C = 6, + SDL_SCANCODE_D = 7, + SDL_SCANCODE_E = 8, + SDL_SCANCODE_F = 9, + SDL_SCANCODE_G = 10, + SDL_SCANCODE_H = 11, + SDL_SCANCODE_I = 12, + SDL_SCANCODE_J = 13, + SDL_SCANCODE_K = 14, + SDL_SCANCODE_L = 15, + SDL_SCANCODE_M = 16, + SDL_SCANCODE_N = 17, + SDL_SCANCODE_O = 18, + SDL_SCANCODE_P = 19, + SDL_SCANCODE_Q = 20, + SDL_SCANCODE_R = 21, + SDL_SCANCODE_S = 22, + SDL_SCANCODE_T = 23, + SDL_SCANCODE_U = 24, + SDL_SCANCODE_V = 25, + SDL_SCANCODE_W = 26, + SDL_SCANCODE_X = 27, + SDL_SCANCODE_Y = 28, + SDL_SCANCODE_Z = 29, + + SDL_SCANCODE_1 = 30, + SDL_SCANCODE_2 = 31, + SDL_SCANCODE_3 = 32, + SDL_SCANCODE_4 = 33, + SDL_SCANCODE_5 = 34, + SDL_SCANCODE_6 = 35, + SDL_SCANCODE_7 = 36, + SDL_SCANCODE_8 = 37, + SDL_SCANCODE_9 = 38, + SDL_SCANCODE_0 = 39, + + SDL_SCANCODE_RETURN = 40, + SDL_SCANCODE_ESCAPE = 41, + SDL_SCANCODE_BACKSPACE = 42, + SDL_SCANCODE_TAB = 43, + SDL_SCANCODE_SPACE = 44, + + SDL_SCANCODE_MINUS = 45, + SDL_SCANCODE_EQUALS = 46, + SDL_SCANCODE_LEFTBRACKET = 47, + SDL_SCANCODE_RIGHTBRACKET = 48, + SDL_SCANCODE_BACKSLASH = 49, /**< Located at the lower left of the return + * key on ISO keyboards and at the right end + * of the QWERTY row on ANSI keyboards. + * Produces REVERSE SOLIDUS (backslash) and + * VERTICAL LINE in a US layout, REVERSE + * SOLIDUS and VERTICAL LINE in a UK Mac + * layout, NUMBER SIGN and TILDE in a UK + * Windows layout, DOLLAR SIGN and POUND SIGN + * in a Swiss German layout, NUMBER SIGN and + * APOSTROPHE in a German layout, GRAVE + * ACCENT and POUND SIGN in a French Mac + * layout, and ASTERISK and MICRO SIGN in a + * French Windows layout. + */ + SDL_SCANCODE_NONUSHASH = 50, /**< ISO USB keyboards actually use this code + * instead of 49 for the same key, but all + * OSes I've seen treat the two codes + * identically. So, as an implementor, unless + * your keyboard generates both of those + * codes and your OS treats them differently, + * you should generate SDL_SCANCODE_BACKSLASH + * instead of this code. As a user, you + * should not rely on this code because SDL + * will never generate it with most (all?) + * keyboards. + */ + SDL_SCANCODE_SEMICOLON = 51, + SDL_SCANCODE_APOSTROPHE = 52, + SDL_SCANCODE_GRAVE = 53, /**< Located in the top left corner (on both ANSI + * and ISO keyboards). Produces GRAVE ACCENT and + * TILDE in a US Windows layout and in US and UK + * Mac layouts on ANSI keyboards, GRAVE ACCENT + * and NOT SIGN in a UK Windows layout, SECTION + * SIGN and PLUS-MINUS SIGN in US and UK Mac + * layouts on ISO keyboards, SECTION SIGN and + * DEGREE SIGN in a Swiss German layout (Mac: + * only on ISO keyboards), CIRCUMFLEX ACCENT and + * DEGREE SIGN in a German layout (Mac: only on + * ISO keyboards), SUPERSCRIPT TWO and TILDE in a + * French Windows layout, COMMERCIAL AT and + * NUMBER SIGN in a French Mac layout on ISO + * keyboards, and LESS-THAN SIGN and GREATER-THAN + * SIGN in a Swiss German, German, or French Mac + * layout on ANSI keyboards. + */ + SDL_SCANCODE_COMMA = 54, + SDL_SCANCODE_PERIOD = 55, + SDL_SCANCODE_SLASH = 56, + + SDL_SCANCODE_CAPSLOCK = 57, + + SDL_SCANCODE_F1 = 58, + SDL_SCANCODE_F2 = 59, + SDL_SCANCODE_F3 = 60, + SDL_SCANCODE_F4 = 61, + SDL_SCANCODE_F5 = 62, + SDL_SCANCODE_F6 = 63, + SDL_SCANCODE_F7 = 64, + SDL_SCANCODE_F8 = 65, + SDL_SCANCODE_F9 = 66, + SDL_SCANCODE_F10 = 67, + SDL_SCANCODE_F11 = 68, + SDL_SCANCODE_F12 = 69, + + SDL_SCANCODE_PRINTSCREEN = 70, + SDL_SCANCODE_SCROLLLOCK = 71, + SDL_SCANCODE_PAUSE = 72, + SDL_SCANCODE_INSERT = 73, /**< insert on PC, help on some Mac keyboards (but + does send code 73, not 117) */ + SDL_SCANCODE_HOME = 74, + SDL_SCANCODE_PAGEUP = 75, + SDL_SCANCODE_DELETE = 76, + SDL_SCANCODE_END = 77, + SDL_SCANCODE_PAGEDOWN = 78, + SDL_SCANCODE_RIGHT = 79, + SDL_SCANCODE_LEFT = 80, + SDL_SCANCODE_DOWN = 81, + SDL_SCANCODE_UP = 82, + + SDL_SCANCODE_NUMLOCKCLEAR = 83, /**< num lock on PC, clear on Mac keyboards + */ + SDL_SCANCODE_KP_DIVIDE = 84, + SDL_SCANCODE_KP_MULTIPLY = 85, + SDL_SCANCODE_KP_MINUS = 86, + SDL_SCANCODE_KP_PLUS = 87, + SDL_SCANCODE_KP_ENTER = 88, + SDL_SCANCODE_KP_1 = 89, + SDL_SCANCODE_KP_2 = 90, + SDL_SCANCODE_KP_3 = 91, + SDL_SCANCODE_KP_4 = 92, + SDL_SCANCODE_KP_5 = 93, + SDL_SCANCODE_KP_6 = 94, + SDL_SCANCODE_KP_7 = 95, + SDL_SCANCODE_KP_8 = 96, + SDL_SCANCODE_KP_9 = 97, + SDL_SCANCODE_KP_0 = 98, + SDL_SCANCODE_KP_PERIOD = 99, + + SDL_SCANCODE_NONUSBACKSLASH = 100, /**< This is the additional key that ISO + * keyboards have over ANSI ones, + * located between left shift and Y. + * Produces GRAVE ACCENT and TILDE in a + * US or UK Mac layout, REVERSE SOLIDUS + * (backslash) and VERTICAL LINE in a + * US or UK Windows layout, and + * LESS-THAN SIGN and GREATER-THAN SIGN + * in a Swiss German, German, or French + * layout. */ + SDL_SCANCODE_APPLICATION = 101, /**< windows contextual menu, compose */ + SDL_SCANCODE_POWER = 102, /**< The USB document says this is a status flag, + * not a physical key - but some Mac keyboards + * do have a power key. */ + SDL_SCANCODE_KP_EQUALS = 103, + SDL_SCANCODE_F13 = 104, + SDL_SCANCODE_F14 = 105, + SDL_SCANCODE_F15 = 106, + SDL_SCANCODE_F16 = 107, + SDL_SCANCODE_F17 = 108, + SDL_SCANCODE_F18 = 109, + SDL_SCANCODE_F19 = 110, + SDL_SCANCODE_F20 = 111, + SDL_SCANCODE_F21 = 112, + SDL_SCANCODE_F22 = 113, + SDL_SCANCODE_F23 = 114, + SDL_SCANCODE_F24 = 115, + SDL_SCANCODE_EXECUTE = 116, + SDL_SCANCODE_HELP = 117, /**< AL Integrated Help Center */ + SDL_SCANCODE_MENU = 118, /**< Menu (show menu) */ + SDL_SCANCODE_SELECT = 119, + SDL_SCANCODE_STOP = 120, /**< AC Stop */ + SDL_SCANCODE_AGAIN = 121, /**< AC Redo/Repeat */ + SDL_SCANCODE_UNDO = 122, /**< AC Undo */ + SDL_SCANCODE_CUT = 123, /**< AC Cut */ + SDL_SCANCODE_COPY = 124, /**< AC Copy */ + SDL_SCANCODE_PASTE = 125, /**< AC Paste */ + SDL_SCANCODE_FIND = 126, /**< AC Find */ + SDL_SCANCODE_MUTE = 127, + SDL_SCANCODE_VOLUMEUP = 128, + SDL_SCANCODE_VOLUMEDOWN = 129, +/* not sure whether there's a reason to enable these */ +/* SDL_SCANCODE_LOCKINGCAPSLOCK = 130, */ +/* SDL_SCANCODE_LOCKINGNUMLOCK = 131, */ +/* SDL_SCANCODE_LOCKINGSCROLLLOCK = 132, */ + SDL_SCANCODE_KP_COMMA = 133, + SDL_SCANCODE_KP_EQUALSAS400 = 134, + + SDL_SCANCODE_INTERNATIONAL1 = 135, /**< used on Asian keyboards, see + footnotes in USB doc */ + SDL_SCANCODE_INTERNATIONAL2 = 136, + SDL_SCANCODE_INTERNATIONAL3 = 137, /**< Yen */ + SDL_SCANCODE_INTERNATIONAL4 = 138, + SDL_SCANCODE_INTERNATIONAL5 = 139, + SDL_SCANCODE_INTERNATIONAL6 = 140, + SDL_SCANCODE_INTERNATIONAL7 = 141, + SDL_SCANCODE_INTERNATIONAL8 = 142, + SDL_SCANCODE_INTERNATIONAL9 = 143, + SDL_SCANCODE_LANG1 = 144, /**< Hangul/English toggle */ + SDL_SCANCODE_LANG2 = 145, /**< Hanja conversion */ + SDL_SCANCODE_LANG3 = 146, /**< Katakana */ + SDL_SCANCODE_LANG4 = 147, /**< Hiragana */ + SDL_SCANCODE_LANG5 = 148, /**< Zenkaku/Hankaku */ + SDL_SCANCODE_LANG6 = 149, /**< reserved */ + SDL_SCANCODE_LANG7 = 150, /**< reserved */ + SDL_SCANCODE_LANG8 = 151, /**< reserved */ + SDL_SCANCODE_LANG9 = 152, /**< reserved */ + + SDL_SCANCODE_ALTERASE = 153, /**< Erase-Eaze */ + SDL_SCANCODE_SYSREQ = 154, + SDL_SCANCODE_CANCEL = 155, /**< AC Cancel */ + SDL_SCANCODE_CLEAR = 156, + SDL_SCANCODE_PRIOR = 157, + SDL_SCANCODE_RETURN2 = 158, + SDL_SCANCODE_SEPARATOR = 159, + SDL_SCANCODE_OUT = 160, + SDL_SCANCODE_OPER = 161, + SDL_SCANCODE_CLEARAGAIN = 162, + SDL_SCANCODE_CRSEL = 163, + SDL_SCANCODE_EXSEL = 164, + + SDL_SCANCODE_KP_00 = 176, + SDL_SCANCODE_KP_000 = 177, + SDL_SCANCODE_THOUSANDSSEPARATOR = 178, + SDL_SCANCODE_DECIMALSEPARATOR = 179, + SDL_SCANCODE_CURRENCYUNIT = 180, + SDL_SCANCODE_CURRENCYSUBUNIT = 181, + SDL_SCANCODE_KP_LEFTPAREN = 182, + SDL_SCANCODE_KP_RIGHTPAREN = 183, + SDL_SCANCODE_KP_LEFTBRACE = 184, + SDL_SCANCODE_KP_RIGHTBRACE = 185, + SDL_SCANCODE_KP_TAB = 186, + SDL_SCANCODE_KP_BACKSPACE = 187, + SDL_SCANCODE_KP_A = 188, + SDL_SCANCODE_KP_B = 189, + SDL_SCANCODE_KP_C = 190, + SDL_SCANCODE_KP_D = 191, + SDL_SCANCODE_KP_E = 192, + SDL_SCANCODE_KP_F = 193, + SDL_SCANCODE_KP_XOR = 194, + SDL_SCANCODE_KP_POWER = 195, + SDL_SCANCODE_KP_PERCENT = 196, + SDL_SCANCODE_KP_LESS = 197, + SDL_SCANCODE_KP_GREATER = 198, + SDL_SCANCODE_KP_AMPERSAND = 199, + SDL_SCANCODE_KP_DBLAMPERSAND = 200, + SDL_SCANCODE_KP_VERTICALBAR = 201, + SDL_SCANCODE_KP_DBLVERTICALBAR = 202, + SDL_SCANCODE_KP_COLON = 203, + SDL_SCANCODE_KP_HASH = 204, + SDL_SCANCODE_KP_SPACE = 205, + SDL_SCANCODE_KP_AT = 206, + SDL_SCANCODE_KP_EXCLAM = 207, + SDL_SCANCODE_KP_MEMSTORE = 208, + SDL_SCANCODE_KP_MEMRECALL = 209, + SDL_SCANCODE_KP_MEMCLEAR = 210, + SDL_SCANCODE_KP_MEMADD = 211, + SDL_SCANCODE_KP_MEMSUBTRACT = 212, + SDL_SCANCODE_KP_MEMMULTIPLY = 213, + SDL_SCANCODE_KP_MEMDIVIDE = 214, + SDL_SCANCODE_KP_PLUSMINUS = 215, + SDL_SCANCODE_KP_CLEAR = 216, + SDL_SCANCODE_KP_CLEARENTRY = 217, + SDL_SCANCODE_KP_BINARY = 218, + SDL_SCANCODE_KP_OCTAL = 219, + SDL_SCANCODE_KP_DECIMAL = 220, + SDL_SCANCODE_KP_HEXADECIMAL = 221, + + SDL_SCANCODE_LCTRL = 224, + SDL_SCANCODE_LSHIFT = 225, + SDL_SCANCODE_LALT = 226, /**< alt, option */ + SDL_SCANCODE_LGUI = 227, /**< windows, command (apple), meta */ + SDL_SCANCODE_RCTRL = 228, + SDL_SCANCODE_RSHIFT = 229, + SDL_SCANCODE_RALT = 230, /**< alt gr, option */ + SDL_SCANCODE_RGUI = 231, /**< windows, command (apple), meta */ + + SDL_SCANCODE_MODE = 257, /**< I'm not sure if this is really not covered + * by any of the above, but since there's a + * special SDL_KMOD_MODE for it I'm adding it here + */ + + /* @} *//* Usage page 0x07 */ + + /** + * \name Usage page 0x0C + * + * These values are mapped from usage page 0x0C (USB consumer page). + * See https://usb.org/sites/default/files/hut1_2.pdf + * + * There are way more keys in the spec than we can represent in the + * current scancode range, so pick the ones that commonly come up in + * real world usage. + */ + /* @{ */ + + SDL_SCANCODE_AUDIONEXT = 258, + SDL_SCANCODE_AUDIOPREV = 259, + SDL_SCANCODE_AUDIOSTOP = 260, + SDL_SCANCODE_AUDIOPLAY = 261, + SDL_SCANCODE_AUDIOMUTE = 262, + SDL_SCANCODE_MEDIASELECT = 263, + SDL_SCANCODE_WWW = 264, /**< AL Internet Browser */ + SDL_SCANCODE_MAIL = 265, + SDL_SCANCODE_CALCULATOR = 266, /**< AL Calculator */ + SDL_SCANCODE_COMPUTER = 267, + SDL_SCANCODE_AC_SEARCH = 268, /**< AC Search */ + SDL_SCANCODE_AC_HOME = 269, /**< AC Home */ + SDL_SCANCODE_AC_BACK = 270, /**< AC Back */ + SDL_SCANCODE_AC_FORWARD = 271, /**< AC Forward */ + SDL_SCANCODE_AC_STOP = 272, /**< AC Stop */ + SDL_SCANCODE_AC_REFRESH = 273, /**< AC Refresh */ + SDL_SCANCODE_AC_BOOKMARKS = 274, /**< AC Bookmarks */ + + /* @} *//* Usage page 0x0C */ + + /** + * \name Walther keys + * + * These are values that Christian Walther added (for mac keyboard?). + */ + /* @{ */ + + SDL_SCANCODE_BRIGHTNESSDOWN = 275, + SDL_SCANCODE_BRIGHTNESSUP = 276, + SDL_SCANCODE_DISPLAYSWITCH = 277, /**< display mirroring/dual display + switch, video mode switch */ + SDL_SCANCODE_KBDILLUMTOGGLE = 278, + SDL_SCANCODE_KBDILLUMDOWN = 279, + SDL_SCANCODE_KBDILLUMUP = 280, + SDL_SCANCODE_EJECT = 281, + SDL_SCANCODE_SLEEP = 282, /**< SC System Sleep */ + + SDL_SCANCODE_APP1 = 283, + SDL_SCANCODE_APP2 = 284, + + /* @} *//* Walther keys */ + + /** + * \name Usage page 0x0C (additional media keys) + * + * These values are mapped from usage page 0x0C (USB consumer page). + */ + /* @{ */ + + SDL_SCANCODE_AUDIOREWIND = 285, + SDL_SCANCODE_AUDIOFASTFORWARD = 286, + + /* @} *//* Usage page 0x0C (additional media keys) */ + + /** + * \name Mobile keys + * + * These are values that are often used on mobile phones. + */ + /* @{ */ + + SDL_SCANCODE_SOFTLEFT = 287, /**< Usually situated below the display on phones and + used as a multi-function feature key for selecting + a software defined function shown on the bottom left + of the display. */ + SDL_SCANCODE_SOFTRIGHT = 288, /**< Usually situated below the display on phones and + used as a multi-function feature key for selecting + a software defined function shown on the bottom right + of the display. */ + SDL_SCANCODE_CALL = 289, /**< Used for accepting phone calls. */ + SDL_SCANCODE_ENDCALL = 290, /**< Used for rejecting phone calls. */ + + /* @} *//* Mobile keys */ + + /* Add any other keys here. */ + + SDL_NUM_SCANCODES = 512 /**< not a key, just marks the number of scancodes + for array bounds */ +} SDL_Scancode; + +#endif /* SDL_scancode_h_ */ diff --git a/apps/tinygl/src/TinyGL/BeOS/GLView.cpp b/apps/tinygl/src/TinyGL/BeOS/GLView.cpp new file mode 100644 index 0000000..778107e --- /dev/null +++ b/apps/tinygl/src/TinyGL/BeOS/GLView.cpp @@ -0,0 +1,205 @@ +#include "GLView.h" +#include +#include + +BLocker BGLView::locker; + +BGLView::BGLView(BRect rect, char *name, + ulong resizingMode, ulong mode, + ulong options) + : BView(rect, name, resizingMode, mode|B_FRAME_EVENTS|B_WILL_DRAW) +{ +#ifdef __INTEL__ + color_space cs = B_RGB16_LITTLE; +#else + color_space cs = B_RGB16_BIG; +#endif + this->bitmaps[0] = new BBitmap(rect, cs, false, true); + this->bitmaps[1] = new BBitmap(rect, cs, false, true); + + this->currBitmap = 0; + int w = this->bitmaps[0]->BytesPerRow() / 2; + int h = rect.Height() + 1; + void *buffers[2]; + buffers[0] = this->bitmaps[0]->Bits(); + buffers[1] = this->bitmaps[1]->Bits(); + this->context = ostgl_create_context(w, h, 16, buffers, 2); + ostgl_make_current(this->context, 0); +} + +BGLView::~BGLView() +{ + ostgl_delete_context(this->context); + delete this->bitmaps[0]; + delete this->bitmaps[1]; +} + +void +BGLView::LockGL() +{ + BGLView::locker.Lock(); + ostgl_make_current(this->context, this->currBitmap); +} + +void +BGLView::UnlockGL() +{ + BGLView::locker.Unlock(); +} + +void +BGLView::SwapBuffers() +{ + if (Window()->Lock()) { + DrawBitmap(this->bitmaps[this->currBitmap]); + Window()->Unlock(); + this->currBitmap ^= 1; + } +} + +/* +BView * +BGLView::EmbeddedView() +{ + return NULL; +} + +status_t +BGLView::CopyPixelsOut(BPoint source, BBitmap *dest) +{ + assert(0); + return 0; +} + +status_t +BGLView::CopyPixelsIn(BBitmap *source, BPoint dest) +{ + assert(0); + return 0; +} +*/ + +void +BGLView::ErrorCallback(GLenum /*errorCode*/) +{ +} + +void +BGLView::Draw(BRect rect) +{ + //fprintf(stderr, "GLView::Draw()"); + DrawBitmap(this->bitmaps[this->currBitmap^1], rect, rect); +} + +void +BGLView::AttachedToWindow() +{ +} + +void +BGLView::AllAttached() +{ +} + +void +BGLView::DetachedFromWindow() +{ +} + +void +BGLView::AllDetached() +{ +} + +void +BGLView::FrameResized(float w, float h) +{ + delete this->bitmaps[0]; + delete this->bitmaps[1]; +#ifdef __INTEL__ + color_space cs = B_RGB16_LITTLE; +#else + color_space cs = B_RGB16_BIG; +#endif + this->bitmaps[0] = new BBitmap(BRect(0,0, w-1, h-1), + cs, false, true); + this->bitmaps[1] = new BBitmap(BRect(0,0, w-1, h-1), + cs, false, true); + int w2 = this->bitmaps[0]->BytesPerRow() / 2; + void *buffers[2]; + buffers[0] = this->bitmaps[0]->Bits(); + buffers[1] = this->bitmaps[1]->Bits(); + ostgl_resize(this->context, w2, h, buffers); +} + +/* +status_t +BGLView::Perform(perform_code d, void *arg) +{ + +} +*/ + +// +// the rest are pass-through functions +// + +status_t +BGLView::Archive(BMessage *data, bool deep) const +{ + return BView::Archive(data, deep); +} + +void +BGLView::MessageReceived(BMessage *msg) +{ + BView::MessageReceived(msg); +} + +void +BGLView::SetResizingMode(uint32 mode) +{ + BView::SetResizingMode(mode); +} + +void +BGLView::Show() +{ + BView::Show(); +} + +void +BGLView::Hide() +{ + BView::Hide(); +} + +BHandler * +BGLView::ResolveSpecifier(BMessage *msg, int32 index, + BMessage *specifier, int32 form, + const char *property) +{ + return BView::ResolveSpecifier(msg, index, specifier, form, property); +} + +status_t +BGLView::GetSupportedSuites(BMessage *data) +{ + return BView::GetSupportedSuites(data); +} + +/* +void +BGLView::DirectConnected( direct_buffer_info *info ) +{ + BView::DirectConnected(info); +} +*/ + +/* +void +BGLView::EnableDirectMode( bool enabled ) +{ + BView::EnableDirectMode(enabled); +} +*/ diff --git a/apps/tinygl/src/TinyGL/BeOS/GLView.h b/apps/tinygl/src/TinyGL/BeOS/GLView.h new file mode 100644 index 0000000..6791e5a --- /dev/null +++ b/apps/tinygl/src/TinyGL/BeOS/GLView.h @@ -0,0 +1,72 @@ +#ifndef _glview_h_ +#define _glview_h_ + +#define BGL_RGB 0 +#define BGL_INDEX 1 +#define BGL_SINGLE 0 +#define BGL_DOUBLE 2 +#define BGL_DIRECT 0 +#define BGL_INDIRECT 4 +#define BGL_ACCUM 8 +#define BGL_ALPHA 16 +#define BGL_DEPTH 32 +#define BGL_OVERLAY 64 +#define BGL_UNDERLAY 128 +#define BGL_STENCIL 512 + +#include +#include +#include +#include +#include +#include + +class BGLView : public BView { +public: + BGLView(BRect rect, char *name, + ulong resizingMode, ulong mode, + ulong options); + virtual ~BGLView(); + + void LockGL(); + void UnlockGL(); + void SwapBuffers(); +// BView *EmbeddedView(); +// status_t CopyPixelsOut(BPoint source, BBitmap *dest); +// status_t CopyPixelsIn(BBitmap *source, BPoint dest); + + virtual void ErrorCallback(GLenum errorCode); + virtual void Draw(BRect updateRect); + virtual void AttachedToWindow(); + virtual void AllAttached(); + virtual void DetachedFromWindow(); + virtual void AllDetached(); + virtual void FrameResized(float width, float height); +// virtual status_t Perform(perform_code d, void *arg); + + // + // Methods below are pass-throughs to BView for the moment. + // + + virtual status_t Archive(BMessage *data, bool deep = true) const; + virtual void MessageReceived(BMessage *msg); + virtual void SetResizingMode(uint32 mode); + + virtual void Show(); + virtual void Hide(); + + virtual BHandler *ResolveSpecifier(BMessage *msg, int32 index, + BMessage *specifier, int32 form, + const char *property); + virtual status_t GetSupportedSuites(BMessage *data); + //void DirectConnected( direct_buffer_info *info ); + //void EnableDirectMode( bool enabled ); + +private: + ostgl_context *context; + BBitmap *bitmaps[2]; + int currBitmap; + static BLocker locker; +}; + +#endif // _glview_h_ diff --git a/apps/tinygl/src/TinyGL/BeOS/Makefile b/apps/tinygl/src/TinyGL/BeOS/Makefile new file mode 100644 index 0000000..0113b3f --- /dev/null +++ b/apps/tinygl/src/TinyGL/BeOS/Makefile @@ -0,0 +1,16 @@ +OBJS=GLView.o +INCLUDES = -I../include +LIB = libGLView.a + +all: $(LIB) + +$(LIB): $(OBJS) + rm -f $(LIB) + ar rcs $(LIB) $(OBJS) + cp $(LIB) ../lib + +clean: + rm -f *~ *.o *.a + +GLView.o: GLView.cpp GLView.h + $(CC) $(CFLAGS) $(INCLUDES) -c GLView.cpp diff --git a/apps/tinygl/src/TinyGL/Changelog b/apps/tinygl/src/TinyGL/Changelog new file mode 100644 index 0000000..53811d3 --- /dev/null +++ b/apps/tinygl/src/TinyGL/Changelog @@ -0,0 +1,44 @@ +version 0.4.1: + - changed license to MIT + - fixed compilation errors + - fixed lighting bug + - fixed color conversions + +version 0.4: + - added 24/32 bit rendering support (Olivier Landemarre - F. Bellard) + - fixed GL_TRIANGLE_STRIP (Olivier Landemarre) + - added gl_malloc, gl_free, gl_zalloc wrappers (Olivier Landemarre) + +version 0.3: + - added NanoX API (nglx) (F. Bellard) + - added gears example and unified GUI in examples (F. Bellard) + - added TGL_FEATURE_RENDER_BITS so that it will be possible to render + natively in 15/16/24 or 32 bits. (F. Bellard) + - interpolated lines (Olivier Landemarre) + - fast no shading case (Olivier Landemarre) + - fast no projection case (Olivier Landemarre) + +version 0.2: Fabrice Bellard + - added 24/32 bpp support. Added some features.h ifdefs. + - fixed some error reporting cases in the examples + - endianness is deduced from the glibc (BYTE_ORDER macro) + +version 0.19: Peder Blekken + - new files BeOS/* src/msghandling.*, src/arrays.*, src/oscontext.c + include/GL/oscontext.h src/features.h + - added support for BeOS, see README.BEOS + - added support for drawing convex polygons with unlimited # of vertices + - added support for GL_LIGHT_MODEL_TWO_SIDE + - added generic rotation code for glopRotate + - added support for opengl 1.1 arrays + - added support for glPolygonOffset, not implemented. + - added glGetFloatv, limited support. + - added some pnames for glGetIntegerv + - added some empty functions in include/GL/gl.h to compile VRMLView + - added GL_VERSION_1_1 define in include/GL/gl.h + - fixed "bug" when context->gl_resize_viewport is not set. + - fixed bug in glBindTexture (didn't accept texture object 0) + +version 0.1: + - Initial revision, Fabrice Bellard + diff --git a/apps/tinygl/src/TinyGL/INSTALL b/apps/tinygl/src/TinyGL/INSTALL new file mode 100644 index 0000000..2a9d7f1 --- /dev/null +++ b/apps/tinygl/src/TinyGL/INSTALL @@ -0,0 +1,10 @@ +Installation: + +- Edit config.mk and change what is needed. You can also look at +src/zfeatures.h to change very specific details (only useful to tune +TinyGL to your needs). You can link the examples with either OpenGL, +Mesa or TinyGL. + +- Type 'make'. The library 'libTinyGL.a' is copied into './lib'. The +examples are build in './examples'. Only the directories './lib' and +'./include' are needed to use TinyGL from another program. diff --git a/apps/tinygl/src/TinyGL/LICENSE b/apps/tinygl/src/TinyGL/LICENSE new file mode 100644 index 0000000..cd1bc3d --- /dev/null +++ b/apps/tinygl/src/TinyGL/LICENSE @@ -0,0 +1,21 @@ +TinyGL + +Copyright (c) 1997-2022 Fabrice Bellard + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/apps/tinygl/src/TinyGL/LIMITATIONS b/apps/tinygl/src/TinyGL/LIMITATIONS new file mode 100644 index 0000000..a20a863 --- /dev/null +++ b/apps/tinygl/src/TinyGL/LIMITATIONS @@ -0,0 +1,206 @@ + +Here are listed the functions that TinyGL understands with the known +limitations. The non mentionned functions are *not* implemented and +must not be used. + + +************ glEnable / glDisable + +- The following flags are handled: + +GL_CULL_FACE, GL_LIGHTING, GL_COLOR_MATERIAL, GL_TEXTURE_2D, GL_NORMALIZE, +GL_LIGHTx, GL_POLYGON_OFFSET_FILL, GL_POLYGON_OFFSET_POINT, +GL_POLYGON_OFFSET_LINE + + +- GL_DEPTH_TEST is accepted, but it is only used for lines. For all + other primitives, Z buffer use is assumed. The DepthMode is + hardcoded as GL_LESS (OpenGL default). + +************ glShadeModel + +OK. + +************ glCullFace + +OK. + +************ glPolygonMode + +OK. + +************ glBegin + +No tests are performed to prevent some functions of being executed +between glBegin/glEnd. + +************ glEnd + +OK. + +************ glVertex + +Some prototypes are not implemented. + + +************ glColor + +Some prototypes are not implemented. + +************ glNormal + +Some prototypes are not implemented. + +************ glTexCoord + +- Some prototypes are not implemented. + +- The Matrix transformation is not applied yet. + +************ glEdgeFlag + +OK. The edge handling has to be tested, although it is not much useful +in TinyGL. + +************ glMatrixMode / glLoadMatrixf / glLoadIdentity / glMultMatrixf / + glPushMatrix / glPopMatrix / glRotatef / glTranslatef / glScalef / + glFrustum + +- The prototypes with doubles are not implemented. + +************ glViewport + +GlViewport calls a function pointers to tell glx (or another display +system) to resize the Z buffer and the ximage. Made optional in +version 0.2. + +************ glGenLists / glIsList / glNewList / glEndList / glCallList + +OK. + +************ glClear / glClearColor / glClearDepth + +The whole zbuffer and the colors are cleared in any case. The clear color +can be redefined, by *not* the initial z value. + +************ glRenderMode + +Only the modes GL_RENDER and GL_SELECT are implemented. + +************ glSelectBuffer / glInitNames / glPushName / glPopName / glLoadName + +OK. + +************ glGenTextures / glDeleteTextures / glBindTexture + +OK. These functions should be used to get the maximum performance with +TinyGL. + +************ glTexImage2D + +The function accepts only RGB UNSIGNED_BYTES bitmaps. They are +internally resized to 256x256 so you'd better use that size. No +mipmapping is implemented although it will come if asked. No borders +are implemented. + +************ glTexEnvi + +The only supported mode is GL_DECAL, although others are planned if +asked. + + +************ glTexParameteri + +The other prototypes are not implemented. Only the follwing mode are +implemented: + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + +************ glPixelStorei + +The pixels are alware byte aligned. + +************ glMaterialfv / glMaterialf / glColorMaterial + +OK. + + +************ glLightfv / glLightf / glLightModeli / glLightModelfv + +OK. The OpenGL lightening is implemented but not optimized. + + +************ glFlush + +Ignored. + +************ glHint + +Ignored. + +************ glGetIntegerv + +- only GL_VIEWPORT, GL_MAX_MODELVIEW_STACK_DEPTH, +GL_MAX_PROJECTION_STACK_DEPTH, GL_MAX_LIGHTS, GL_MAX_TEXTURE_SIZE, +GL_MAX_TEXTURE_STACK_DEPTH + +************ glGetIntegerv + +- only GL_TEXTURE_MATRIX, GL_PROJECTION_MATRIX, GL_MODELVIEW_MATRIX, +GL_LINE_WIDTH, GL_LINE_WIDTH_RANGE, GL_POINT_SIZE, GL_POINT_SIZE_RANGE + +************ glPolygonOffset + +- only API implemented. + +************ glEnableClientState, glDisableClientState, + +- No support for GL_INDEX_ARRAY_POINTER or GL_EDGE_FLAG_ARRAY_POINTER + +************ glVertexPointer, glNormalPointer, + glColorPointer, glTexureCoordPointer + +- OK + +------------------------------------------------------------------------------ + +TinyGL GLX emulation: + + +************ glXQueryExtension + +Returns always True + +************ glXChooseVisual + +Only 8 bit Pseudocolor or 16 bit Truecolor Visual are accepted. The +attribute list is ignored. + +************ glXCreateContext + +The sharing is not implemented although the code could handle it. + +************ glXDestroyContext + +OK. + +************ glXMakeCurrent + +Not all the syntax is supported yet, in particular with the 'NULL' or +'None' parameters. + + +************ glXSwapBuffers + +OK. + +************ glXWaitGL / glXWaitX + +Ignored. + + +See README.BEOS for BeOS limitations. + diff --git a/apps/tinygl/src/TinyGL/Makefile b/apps/tinygl/src/TinyGL/Makefile new file mode 100644 index 0000000..ff3f0a0 --- /dev/null +++ b/apps/tinygl/src/TinyGL/Makefile @@ -0,0 +1,15 @@ +include config.mk + +all: + ( for f in $(DIRS); do ( cd $$f ; make all ) || exit 1 ; done ) + +clean: + rm -f *~ lib/libTinyGL.a include/GL/*~ TAGS + ( for f in $(DIRS); do ( cd $$f ; make clean ; ) done ) + +install: + ( for f in $(DIRS); do ( cd $$f ; make install ; ) done ) + + +tar: + ( cd .. ; tar zcvf /tmp/TinyGL-0.4.1.tar.gz TinyGL --exclude .svn --exclude TAGS ) diff --git a/apps/tinygl/src/TinyGL/README b/apps/tinygl/src/TinyGL/README new file mode 100644 index 0000000..29f4e30 --- /dev/null +++ b/apps/tinygl/src/TinyGL/README @@ -0,0 +1,150 @@ +TinyGL 0.4 (c) 1997-2002 Fabrice Bellard. + +General Description: +-------------------- + +TinyGL is intended to be a very small implementation of a subset of +OpenGL* for embedded systems or games. It is a software only +implementation. Only the main OpenGL calls are implemented. All the +calls I considered not important are simply *not implemented*. + +The main strength of TinyGL is that it is fast and simple because it +has not to be exactly compatible with OpenGL. In particular, the +texture mapping and the geometrical transformations are very fast. + +The main features of TinyGL are: + +- Header compatible with OpenGL (the headers are adapted from the very good +Mesa by Brian Paul et al.) + +- MIT license for easy integration in commercial designs (read +the LICENSE file). + +- Subset of GLX for easy testing with X Window. + +- GLX like API (NGLX) to use it with NanoX in MicroWindows/NanoX. + +- Subset of BGLView under BeOS. + +- OpenGL like lightening. + +- Complete OpenGL selection mode handling for object picking. + +- 16 bit Z buffer. 16/24/32 bit RGB rendering. High speed dithering to +paletted 8 bits if needed. High speed conversion to 24 bit packed +pixel or 32 bit RGBA if needed. + +- Fast Gouraud shadding optimized for 16 bit RGB. + +- Fast texture mapping capabilities, with perspective correction and +texture objects. + +- 32 bit float only arithmetic. + +- Very small: compiled code size of about 40 kB on x86. The file + src/zfeatures.h can be used to remove some unused features from + TinyGL. + +- C sources for GCC on 32/64 bit architectures. It has been tested +succesfully on x86-Linux and sparc-Solaris. + +Examples: +--------- + +I took three simple examples from the Mesa package to test the main +functions of TinyGL. You can link them to either TinyGL, Mesa or any +other OpenGL/GLX implementation. You can also compile them with +Microwindows. + +- texobj illustrates the use of texture objects. Its shows the speed +of TinyGL in this case. + +- glutmech comes from the GLUT packages. It is much bigger and slower +because it uses the lightening. I have just included some GLU +functions and suppressed the GLUT related code to make it work. It +shows the display list handling of TinyGL in particular. You can look +at the source code to learn the keys to move the robot. The key 't' +toggles between shaded rendering and wire frame. + +- You can download and compile the VReng project to see that TinyGL +has been successfully used in a big project +(http://www-inf.enst.fr/vreng). + +Architecture: +------------- + +TinyGL is made up four main modules: + +- Mathematical routines (zmath). + +- OpenGL-like emulation (zgl). + +- Z buffer and rasterisation (zbuffer). + +- GLX interface (zglx). + +To use TinyGL in an embedded system, you should look at the GLX layer +and modify it to suit your need. Adding a more user friendly +developper layer (as in Mesa) may be useful. + +Notes - limitations: +-------------------- + +- See the file 'LIMITATIONS' to see the current functions supported by the API. + +- The multithreading could be easily implemented since no global state +is maintainted. The library gets the current context with a function +which can be modified. + +- The lightening is not very fast. I supposed that in most games the +lightening is computed by the 3D engine. + +- Some changes are needed for 64 bit pointers for the handling of +arrays of float with the GLParam union. + +- List sharing is partialy supported in the source, but not by the +current TinyGLX implementation (is it really useful ?). + +- No user clipping planes are supported. + +- No color index mode (no longer useful !) + +- The mipmapping is not implemented. + +- The perspecture correction in the mapping code does not use W but +1/Z. In any 'normal scene' it should work. + +- The resizing of the viewport in TinyGLX ensures that the width and +the height are multiples of 4. This is not optimal because some pixels +of the window may not be refreshed. + +Why ? +----- + +TinyGL was developped as a student project for a Virtual Reality +network system called VReng (see the VReng home page at +http://www-inf.enst.fr/vreng). + +At that time (January 1997), my initial project was to write my own 3D +rasterizer based on some old sources I wrote. But I realized that it +would be better to use OpenGL to work on any platform. My problem was +that I wanted to use texture mapping which was (and is still) quite +slower on many software OpenGL implementation. I could have modified +Mesa to suit my needs, but I really wanted to use my old sources for +that project. + +I finally decided to use the same syntax as OpenGL but with my own +libraries, thinking that later it could ease the porting of VReng to +OpenGL. + +Now VReng is at last compatible with OpenGL, and I managed to patch +TinyGL so that VReng can still work with it without any modifications. + +Since TinyGL may be useful for some people, especially in the world of +embedded designs, I decided to release it 'as is', otherwise, it would +have been lost on my hard disk ! + +------------------------------------------------------------------------------ +* OpenGL(R) is a registered trademark of Silicon Graphics, Inc. +------------------------------------------------------------------------------ +Fabrice Bellard. diff --git a/apps/tinygl/src/TinyGL/README.BEOS b/apps/tinygl/src/TinyGL/README.BEOS new file mode 100644 index 0000000..a146f5f --- /dev/null +++ b/apps/tinygl/src/TinyGL/README.BEOS @@ -0,0 +1,20 @@ +BeOS support for TinyGL, 1998 Peder Blekken + +I implemented (a limited version of) the BGLView class. There is +no DirectWindow support, and some other funtions are missing too, +but it should work ok for most uses. Feel free to use and modify +GLView.cpp and GLView.h in any way you desire. + +You will need to take a look in Makefile to compile the library +under BeOS. For those of you not familiar with using makefiles: too bad :) + +Also, you will probably need to remove /boot/develop/headers/be/opengl +from the BEINCLUDES environment variable. Unfortunately, this means +editing the /boot/beos/system/boot/SetupEnvironment. It might be possible +to just make sure the TinyGL path is before Be's OpenGL in the include-paths +though. But I prefer to remove /boot/develop/headers/be/opengl, since I +often use Mesa as well. It is a better to add the OpenGL include path in your +makefile; or BeIDE project if that is what you use. + +Contact me for any reason: + diff --git a/apps/tinygl/src/TinyGL/config.mk b/apps/tinygl/src/TinyGL/config.mk new file mode 100644 index 0000000..5ec62ba --- /dev/null +++ b/apps/tinygl/src/TinyGL/config.mk @@ -0,0 +1,82 @@ +##################################################################### +# C compiler + +# linux +CC= gcc +CFLAGS= -g -Wall -O2 +LFLAGS= + +# for BeOS PPC +#CC= mwcc +#CFLAGS= -I. -i- +#LFLAGS= + +##################################################################### +# TinyGL configuration + +##################################################################### +# Select window API for TinyGL: + +# standard X11 GLX like API +TINYGL_USE_GLX=y + +# BEOS API +#TINYGL_USE_BEOS=y + +# Micro Windows NanoX API +#TINYGL_USE_NANOX=y + +##################################################################### +# X11 configuration (for the examples only) + +ifdef TINYGL_USE_GLX +# Linux +UI_LIBS= -L/usr/X11R6/lib -lX11 -lXext +UI_INCLUDES= +# Solaris +#UI_LIBS= -L/usr/X11/lib -lX11 -lXext -lsocket -lnsl +#UI_INCLUDES= + +UI_OBJS=x11.o +endif + +##################################################################### +# Micro windowX11 configuration (for the examples only) + +ifdef TINYGL_USE_NANOX +UI_LIBS= -lnano-X -lmwengine -lmwdrivers -lmwfonts +UI_INCLUDES= + +# X11 target for nanoX +UI_LIBS+= -L/usr/X11R6/lib -lX11 -lXext + +UI_OBJS=nanox.o +endif + +##################################################################### +# OpenGL configuration (for the examples only) + +# use TinyGL +GL_LIBS= -L../lib -lTinyGL +GL_INCLUDES= -I../include +GL_DEPS= ../lib/libTinyGL.a + +# use Mesa +#GL_LIBS= -lMesaGL +#GL_INCLUDES= +#GL_DEPS= + +# use OpenGL +#GL_LIBS= -lGL +#GL_INCLUDES= +#GL_DEPS= + +#################################################################### +# Compile and link control + +# UNIX systems +DIRS= src examples + +# BeOS +# DIRS= src BeOS + diff --git a/apps/tinygl/src/TinyGL/examples/Makefile b/apps/tinygl/src/TinyGL/examples/Makefile new file mode 100644 index 0000000..912243b --- /dev/null +++ b/apps/tinygl/src/TinyGL/examples/Makefile @@ -0,0 +1,29 @@ +include ../config.mk + +PROGS = mech texobj gears spin + +all: $(PROGS) + +clean: + rm -f core *.o *~ $(PROGS) + +mech: mech.o glu.o $(UI_OBJS) $(GL_DEPS) + $(CC) $(LFLAGS) $^ -o $@ $(GL_LIBS) $(UI_LIBS) -lm + +texobj: texobj.o $(UI_OBJS) $(GL_DEPS) + $(CC) $(LFLAGS) $^ -o $@ $(GL_LIBS) $(UI_LIBS) -lm + +gears: gears.o $(UI_OBJS) $(GL_DEPS) + $(CC) $(LFLAGS) $^ -o $@ $(GL_LIBS) $(UI_LIBS) -lm + +spin: spin.o $(UI_OBJS) $(GL_DEPS) + $(CC) $(LFLAGS) $^ -o $@ $(GL_LIBS) $(UI_LIBS) -lm + +.c.o: + $(CC) $(CFLAGS) $(GL_INCLUDES) $(UI_INCLUDES) -c $*.c + +mech.o: glu.h + +glu.o: glu.h + +ui.o: ui.h diff --git a/apps/tinygl/src/TinyGL/examples/gears.c b/apps/tinygl/src/TinyGL/examples/gears.c new file mode 100644 index 0000000..7ccf5bf --- /dev/null +++ b/apps/tinygl/src/TinyGL/examples/gears.c @@ -0,0 +1,300 @@ +/* gears.c */ + +/* + * 3-D gear wheels. This program is in the public domain. + * + * Brian Paul + */ + + +#include +#include +#include +#include + +#include +#include +#include "ui.h" + +#ifndef M_PI +# define M_PI 3.14159265 +#endif + + +/* + * Draw a gear wheel. You'll probably want to call this function when + * building a display list since we do a lot of trig here. + * + * Input: inner_radius - radius of hole at center + * outer_radius - radius at center of teeth + * width - width of gear + * teeth - number of teeth + * tooth_depth - depth of tooth + */ +static void gear( GLfloat inner_radius, GLfloat outer_radius, GLfloat width, + GLint teeth, GLfloat tooth_depth ) +{ + GLint i; + GLfloat r0, r1, r2; + GLfloat angle, da; + GLfloat u, v, len; + + r0 = inner_radius; + r1 = outer_radius - tooth_depth/2.0; + r2 = outer_radius + tooth_depth/2.0; + + da = 2.0*M_PI / teeth / 4.0; + + glShadeModel( GL_FLAT ); + + glNormal3f( 0.0, 0.0, 1.0 ); + + /* draw front face */ + glBegin( GL_QUAD_STRIP ); + for (i=0;i<=teeth;i++) { + angle = i * 2.0*M_PI / teeth; + glVertex3f( r0*cos(angle), r0*sin(angle), width*0.5 ); + glVertex3f( r1*cos(angle), r1*sin(angle), width*0.5 ); + glVertex3f( r0*cos(angle), r0*sin(angle), width*0.5 ); + glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), width*0.5 ); + } + glEnd(); + + /* draw front sides of teeth */ + glBegin( GL_QUADS ); + da = 2.0*M_PI / teeth / 4.0; + for (i=0;i1) { + /* do 'n' frames then exit */ + limit = atoi( argv[1] ) + 1; + } + else { + limit = 0; + } + + return ui_loop(argc, argv, "gears"); +} + + diff --git a/apps/tinygl/src/TinyGL/examples/glu.c b/apps/tinygl/src/TinyGL/examples/glu.c new file mode 100644 index 0000000..38561e7 --- /dev/null +++ b/apps/tinygl/src/TinyGL/examples/glu.c @@ -0,0 +1,261 @@ +#include +#include +#include +#include "glu.h" + + +void drawTorus(float rc, int numc, float rt, int numt) +{ + int i, j, k; + double s, t; + double x, y, z; + double pi, twopi; + + pi = 3.14159265358979323846; + twopi = 2 * pi; + + for (i = 0; i < numc; i++) { + glBegin(GL_QUAD_STRIP); + for (j = 0; j <= numt; j++) { + for (k = 1; k >= 0; k--) { + s = (i + k) % numc + 0.5; + t = j % numt; + + x = cos(t*twopi/numt) * cos(s*twopi/numc); + y = sin(t*twopi/numt) * cos(s*twopi/numc); + z = sin(s*twopi/numc); + glNormal3f(x, y, z); + + x = (rt + rc * cos(s*twopi/numc)) * cos(t*twopi/numt); + y = (rt + rc * cos(s*twopi/numc)) * sin(t*twopi/numt); + z = rc * sin(s*twopi/numc); + glVertex3f(x, y, z); + } + } + glEnd(); + } +} + +static void normal3f( GLfloat x, GLfloat y, GLfloat z ) +{ + GLdouble mag; + + mag = sqrt( x*x + y*y + z*z ); + if (mag>0.00001F) { + x /= mag; + y /= mag; + z /= mag; + } + glNormal3f( x, y, z ); +} + +void gluPerspective( GLdouble fovy, GLdouble aspect, + GLdouble zNear, GLdouble zFar ) +{ + GLdouble xmin, xmax, ymin, ymax; + + ymax = zNear * tan( fovy * M_PI / 360.0 ); + ymin = -ymax; + + xmin = ymin * aspect; + xmax = ymax * aspect; + + glFrustum( xmin, xmax, ymin, ymax, zNear, zFar ); +} + +GLUquadricObj *gluNewQuadric(void) +{ + return NULL; +} + +void gluQuadricDrawStyle(GLUquadricObj *obj, int style) +{ +} + +void gluCylinder( GLUquadricObj *qobj, + GLdouble baseRadius, GLdouble topRadius, GLdouble height, + GLint slices, GLint stacks ) +{ + GLdouble da, r, dr, dz; + GLfloat z, nz, nsign; + GLint i, j; + GLfloat du = 1.0 / slices; + GLfloat dv = 1.0 / stacks; + GLfloat tcx = 0.0, tcy = 0.0; + + nsign = 1.0; + + da = 2.0*M_PI / slices; + dr = (topRadius-baseRadius) / stacks; + dz = height / stacks; + nz = (baseRadius-topRadius) / height; /* Z component of normal vectors */ + + for (i=0;i=0;j--) { + theta = (j==slices) ? 0.0 : j * dtheta; + x = -sin(theta) * sin(rho); + y = cos(theta) * sin(rho); + z = nsign * cos(rho); + if (normals) glNormal3f( x*nsign, y*nsign, z*nsign ); + glTexCoord2f(s,1-t); + s -= ds; + glVertex3f( x*radius, y*radius, z*radius ); + } + glEnd(); +} diff --git a/apps/tinygl/src/TinyGL/examples/glu.h b/apps/tinygl/src/TinyGL/examples/glu.h new file mode 100644 index 0000000..8e4bbdf --- /dev/null +++ b/apps/tinygl/src/TinyGL/examples/glu.h @@ -0,0 +1,23 @@ + +void gluPerspective( GLdouble fovy, GLdouble aspect, + GLdouble zNear, GLdouble zFar ); + +typedef struct { + int draw_style; +} GLUquadricObj; + +#define GLU_LINE 0 + +GLUquadricObj *gluNewQuadric(void); +void gluQuadricDrawStyle(GLUquadricObj *obj, int style); + +void gluSphere(GLUquadricObj *qobj, + float radius,int slices,int stacks); +void gluCylinder( GLUquadricObj *qobj, + GLdouble baseRadius, GLdouble topRadius, GLdouble height, + GLint slices, GLint stacks ); +void gluDisk( GLUquadricObj *qobj, + GLdouble innerRadius, GLdouble outerRadius, + GLint slices, GLint loops ); + +void drawTorus(float rc, int numc, float rt, int numt); diff --git a/apps/tinygl/src/TinyGL/examples/mech.c b/apps/tinygl/src/TinyGL/examples/mech.c new file mode 100644 index 0000000..f071ee3 --- /dev/null +++ b/apps/tinygl/src/TinyGL/examples/mech.c @@ -0,0 +1,1753 @@ +/** +* program : glutmech V1.1 +* author : Simon Parkinson-Bates. +* E-mail : sapb@yallara.cs.rmit.edu.au +* Copyright Simon Parkinson-Bates. +* "source if freely avaliable to anyone to copy as long as they +* acknowledge me in their work." +* +* Funtional features +* ------------------ +* * online menu system avaliable by pressing left mouse button +* * online cascading help system avaliable, providing information on +* the several key strokes and what they do. +* * animation sequence coded which makes the mech walk through an +* environment. Shadows will soon be added to make it look +* more realistic. +* * menu control to view mech in wireframe or sold mode. +* * various key strokes avaliable to control idependently the mechs +* many joints. +* * various key strokes avaliable to view mech and environment from +* different angles +* * various key strokes avaliable to alter positioning of the single +* light source. +* +* +* Program features +* ---------------- +* * uses double buffering +* * uses display lists +* * uses glut to manage windows, callbacks, and online menu. +* * uses glpolygonfill() to maintain colors in wireframe and solid +* mode. +* +**/ + +/* start of compilation conditions */ +#define SPHERE +#define COLOR +#define LIGHT +#define TORSO +#define HIP +#define SHOULDER +#define UPPER_ARM +#define LOWER_ARM +#define ROCKET_POD +#define UPPER_LEG +#define LOWER_LEG +#define NO_NORM +#define ANIMATION +#define DRAW_MECH +#define DRAW_ENVIRO +#define MOVE_LIGHT +/* end of compilation conditions */ + +/* start various header files needed */ +#include +#include +#include + +#define GLUT +#define GLUT_KEY +#define GLUT_SPEC +#include +#include +#include "glu.h" +#include "ui.h" + +/* end of header files */ + +/* start of display list definitions */ +#define SOLID_MECH_TORSO 1 +#define SOLID_MECH_HIP 2 +#define SOLID_MECH_SHOULDER 3 +#define SOLID_MECH_UPPER_ARM 4 +#define SOLID_MECH_FOREARM 5 +#define SOLID_MECH_UPPER_LEG 6 +#define SOLID_MECH_FOOT 7 +#define SOLID_MECH_ROCKET 8 +#define SOLID_MECH_VULCAN 9 +#define SOLID_ENVIRO 10 +/* end of display list definitions */ + +/* start of motion rate variables */ +#define ANKLE_RATE 3 +#define HEEL_RATE 3 +#define ROTATE_RATE 10 +#define TILT_RATE 10 +#define ELBOW_RATE 2 +#define SHOULDER_RATE 5 +#define LAT_RATE 5 +#define CANNON_RATE 40 +#define UPPER_LEG_RATE 3 +#define UPPER_LEG_RATE_GROIN 10 +#define LIGHT_TURN_RATE 10 +#define VIEW_TURN_RATE 10 +/* end of motion rate variables */ + +/* start of motion variables */ +#ifndef PI +#define PI 3.141592654 +#endif + +char leg = 0; + +int shoulder1 = 0, shoulder2 = 0, shoulder3 = 0, shoulder4 = 0, lat1 = 20, lat2 = 20, + elbow1 = 0, elbow2 = 0, pivot = 0, tilt = 10, ankle1 = 0, ankle2 = 0, heel1 = 0, + heel2 = 0, hip11 = 0, hip12 = 10, hip21 = 0, hip22 = 10, fire = 0, solid_part = 0, + anim = 0, turn = 0, turn1 = 0, lightturn = 0, lightturn1 = 0; + +float elevation = 0.0, distance = 0.0, frame = 3.0 + /* foot1v[] = {} foot2v[] = {} */ ; + +/* end of motion variables */ + +/* start of material definitions */ +#ifdef LIGHT +GLfloat mat_specular[] = +{0.628281, 0.555802, 0.366065, 1.0}; +GLfloat mat_ambient[] = +{0.24725, 0.1995, 0.0745, 1.0}; +GLfloat mat_diffuse[] = +{0.75164, 0.60648, 0.22648, 1.0}; +GLfloat mat_shininess[] = +{128.0 * 0.4}; + +GLfloat mat_specular2[] = +{0.508273, 0.508273, 0.508373, 1.0}; +GLfloat mat_ambient2[] = +{0.19225, 0.19225, 0.19225, 1.0}; +GLfloat mat_diffuse2[] = +{0.50754, 0.50754, 0.50754, 1.0}; +GLfloat mat_shininess2[] = +{128.0 * 0.6}; + +GLfloat mat_specular3[] = +{0.296648, 0.296648, 0.296648, 1.0}; +GLfloat mat_ambient3[] = +{0.25, 0.20725, 0.20725, 1.0}; +GLfloat mat_diffuse3[] = +{1, 0.829, 0.829, 1.0}; +GLfloat mat_shininess3[] = +{128.0 * 0.088}; + +GLfloat mat_specular4[] = +{0.633, 0.727811, 0.633, 1.0}; +GLfloat mat_ambient4[] = +{0.0215, 0.1745, 0.0215, 1.0}; +GLfloat mat_diffuse4[] = +{0.07568, 0.61424, 0.07568, 1.0}; +GLfloat mat_shininess4[] = +{128 * 0.6}; + +GLfloat mat_specular5[] = +{0.60, 0.60, 0.50, 1.0}; +GLfloat mat_ambient5[] = +{0.0, 0.0, 0.0, 1.0}; +GLfloat mat_diffuse5[] = +{0.5, 0.5, 0.0, 1.0}; +GLfloat mat_shininess5[] = +{128.0 * 0.25}; + +#endif +/* end of material definitions */ + +/* start of the body motion functions */ +void +Heel1Add(void) +{ + heel1 = (heel1 + HEEL_RATE) % 360; +} + +void +Heel1Subtract(void) +{ + heel1 = (heel1 - HEEL_RATE) % 360; +} + +void +Heel2Add(void) +{ + heel2 = (heel2 + HEEL_RATE) % 360; +} + +void +Heel2Subtract(void) +{ + heel2 = (heel2 - HEEL_RATE) % 360; +} + +void +Ankle1Add(void) +{ + ankle1 = (ankle1 + ANKLE_RATE) % 360; +} + +void +Ankle1Subtract(void) +{ + ankle1 = (ankle1 - ANKLE_RATE) % 360; +} + +void +Ankle2Add(void) +{ + ankle2 = (ankle2 + ANKLE_RATE) % 360; +} + +void +Ankle2Subtract(void) +{ + ankle2 = (ankle2 - ANKLE_RATE) % 360; +} + +void +RotateAdd(void) +{ + pivot = (pivot + ROTATE_RATE) % 360; +} + +void +RotateSubtract(void) +{ + pivot = (pivot - ROTATE_RATE) % 360; +} + +void +MechTiltSubtract(void) +{ + tilt = (tilt - TILT_RATE) % 360; +} + +void +MechTiltAdd(void) +{ + tilt = (tilt + TILT_RATE) % 360; +} + +void +elbow1Add(void) +{ + elbow1 = (elbow1 + ELBOW_RATE) % 360; +} + +void +elbow1Subtract(void) +{ + elbow1 = (elbow1 - ELBOW_RATE) % 360; +} + +void +elbow2Add(void) +{ + elbow2 = (elbow2 + ELBOW_RATE) % 360; +} + +void +elbow2Subtract(void) +{ + elbow2 = (elbow2 - ELBOW_RATE) % 360; +} + +void +shoulder1Add(void) +{ + shoulder1 = (shoulder1 + SHOULDER_RATE) % 360; +} + +void +shoulder1Subtract(void) +{ + shoulder1 = (shoulder1 - SHOULDER_RATE) % 360; +} + +void +shoulder2Add(void) +{ + shoulder2 = (shoulder2 + SHOULDER_RATE) % 360; +} + +void +shoulder2Subtract(void) +{ + shoulder2 = (shoulder2 - SHOULDER_RATE) % 360; +} + +void +shoulder3Add(void) +{ + shoulder3 = (shoulder3 + SHOULDER_RATE) % 360; +} + +void +shoulder3Subtract(void) +{ + shoulder3 = (shoulder3 - SHOULDER_RATE) % 360; +} + +void +shoulder4Add(void) +{ + shoulder4 = (shoulder4 + SHOULDER_RATE) % 360; +} + +void +shoulder4Subtract(void) +{ + shoulder4 = (shoulder4 - SHOULDER_RATE) % 360; +} + +void +lat1Raise(void) +{ + lat1 = (lat1 + LAT_RATE) % 360; +} + +void +lat1Lower(void) +{ + lat1 = (lat1 - LAT_RATE) % 360; +} + +void +lat2Raise(void) +{ + lat2 = (lat2 + LAT_RATE) % 360; +} + +void +lat2Lower(void) +{ + lat2 = (lat2 - LAT_RATE) % 360; +} + +void +FireCannon(void) +{ + fire = (fire + CANNON_RATE) % 360; +} + +void +RaiseLeg1Forward(void) +{ + hip11 = (hip11 + UPPER_LEG_RATE) % 360; +} + +void +LowerLeg1Backwards(void) +{ + hip11 = (hip11 - UPPER_LEG_RATE) % 360; +} + +void +RaiseLeg1Outwards(void) +{ + hip12 = (hip12 + UPPER_LEG_RATE_GROIN) % 360; +} + +void +LowerLeg1Inwards(void) +{ + hip12 = (hip12 - UPPER_LEG_RATE_GROIN) % 360; +} + +void +RaiseLeg2Forward(void) +{ + hip21 = (hip21 + UPPER_LEG_RATE) % 360; +} + +void +LowerLeg2Backwards(void) +{ + hip21 = (hip21 - UPPER_LEG_RATE) % 360; +} + +void +RaiseLeg2Outwards(void) +{ + hip22 = (hip22 + UPPER_LEG_RATE_GROIN) % 360; +} + +void +LowerLeg2Inwards(void) +{ + hip22 = (hip22 - UPPER_LEG_RATE_GROIN) % 360; +} + +/* end of body motion functions */ + +/* start of light source position functions */ +void +TurnRight(void) +{ + turn = (turn - VIEW_TURN_RATE) % 360; +} + +void +TurnLeft(void) +{ + turn = (turn + VIEW_TURN_RATE) % 360; +} + +void +TurnForwards(void) +{ + turn1 = (turn1 - VIEW_TURN_RATE) % 360; +} + +void +TurnBackwards(void) +{ + turn1 = (turn1 + VIEW_TURN_RATE) % 360; +} + +void +LightTurnRight(void) +{ + lightturn = (lightturn + LIGHT_TURN_RATE) % 360; +} + +void +LightTurnLeft(void) +{ + lightturn = (lightturn - LIGHT_TURN_RATE) % 360; +} + +void +LightForwards(void) +{ + lightturn1 = (lightturn1 + LIGHT_TURN_RATE) % 360; +} + +void +LightBackwards(void) +{ + lightturn1 = (lightturn1 - LIGHT_TURN_RATE) % 360; +} + +/* end of light source position functions */ + +/* start of geometric shape functions */ +void +Box(float width, float height, float depth, char solid) +{ + char i, j = 0; + float x = width / 2.0, y = height / 2.0, z = depth / 2.0; + + for (i = 0; i < 4; i++) { + glRotatef(90.0, 0.0, 0.0, 1.0); + if (j) { + if (!solid) + glBegin(GL_LINE_LOOP); + else + glBegin(GL_QUADS); + glNormal3f(-1.0, 0.0, 0.0); + glVertex3f(-x, y, z); + glVertex3f(-x, -y, z); + glVertex3f(-x, -y, -z); + glVertex3f(-x, y, -z); + glEnd(); + if (solid) { + glBegin(GL_TRIANGLES); + glNormal3f(0.0, 0.0, 1.0); + glVertex3f(0.0, 0.0, z); + glVertex3f(-x, y, z); + glVertex3f(-x, -y, z); + glNormal3f(0.0, 0.0, -1.0); + glVertex3f(0.0, 0.0, -z); + glVertex3f(-x, -y, -z); + glVertex3f(-x, y, -z); + glEnd(); + } + j = 0; + } else { + if (!solid) + glBegin(GL_LINE_LOOP); + else + glBegin(GL_QUADS); + glNormal3f(-1.0, 0.0, 0.0); + glVertex3f(-y, x, z); + glVertex3f(-y, -x, z); + glVertex3f(-y, -x, -z); + glVertex3f(-y, x, -z); + glEnd(); + if (solid) { + glBegin(GL_TRIANGLES); + glNormal3f(0.0, 0.0, 1.0); + glVertex3f(0.0, 0.0, z); + glVertex3f(-y, x, z); + glVertex3f(-y, -x, z); + glNormal3f(0.0, 0.0, -1.0); + glVertex3f(0.0, 0.0, -z); + glVertex3f(-y, -x, -z); + glVertex3f(-y, x, -z); + glEnd(); + } + j = 1; + } + } +} + +void +Octagon(float side, float height, char solid) +{ + char j; + float x = sin(0.785398163) * side, y = side / 2.0, z = height / 2.0, c; + + c = x + y; + for (j = 0; j < 8; j++) { + glTranslatef(-c, 0.0, 0.0); + if (!solid) + glBegin(GL_LINE_LOOP); + else + glBegin(GL_QUADS); + glNormal3f(-1.0, 0.0, 0.0); + glVertex3f(0.0, -y, z); + glVertex3f(0.0, y, z); + glVertex3f(0.0, y, -z); + glVertex3f(0.0, -y, -z); + glEnd(); + glTranslatef(c, 0.0, 0.0); + if (solid) { + glBegin(GL_TRIANGLES); + glNormal3f(0.0, 0.0, 1.0); + glVertex3f(0.0, 0.0, z); + glVertex3f(-c, -y, z); + glVertex3f(-c, y, z); + glNormal3f(0.0, 0.0, -1.0); + glVertex3f(0.0, 0.0, -z); + glVertex3f(-c, y, -z); + glVertex3f(-c, -y, -z); + glEnd(); + } + glRotatef(45.0, 0.0, 0.0, 1.0); + } +} + +/* end of geometric shape functions */ +#ifdef NORM +void +Normalize(float v[3]) +{ + GLfloat d = sqrt(v[1] * v[1] + v[2] * v[2] + v[3] * v[3]); + + if (d == 0.0) { + printf("zero length vector"); + return; + } + v[1] /= d; + v[2] /= d; + v[3] /= d; +} + +void +NormXprod(float v1[3], float v2[3], float v[3], float out[3]) +{ + GLint i, j; + GLfloat length; + + out[0] = v1[1] * v2[2] - v1[2] * v2[1]; + out[1] = v1[2] * v2[0] - v1[0] * v2[2]; + out[2] = v1[0] * v2[1] - v1[1] * v2[0]; + Normalize(out); +} + +#endif + +void +SetMaterial(GLfloat spec[], GLfloat amb[], GLfloat diff[], GLfloat shin[]) +{ + + glMaterialfv(GL_FRONT, GL_SPECULAR, spec); + glMaterialfv(GL_FRONT, GL_SHININESS, shin); + glMaterialfv(GL_FRONT, GL_AMBIENT, amb); + glMaterialfv(GL_FRONT, GL_DIFFUSE, diff); +} + +void +MechTorso(char solid) +{ + glNewList(SOLID_MECH_TORSO, GL_COMPILE); +#ifdef LIGHT + SetMaterial(mat_specular, mat_ambient, mat_diffuse, mat_shininess); +#endif + glColor3f(1.0, 1.0, 0.0); + Box(1.0, 1.0, 3.0, solid); + glTranslatef(0.75, 0.0, 0.0); +#ifdef LIGHT + SetMaterial(mat_specular2, mat_ambient2, mat_diffuse2, mat_shininess2); +#endif + glColor3f(0.5, 0.5, 0.5); + Box(0.5, 0.6, 2.0, solid); + glTranslatef(-1.5, 0.0, 0.0); + Box(0.5, 0.6, 2.0, solid); + glTranslatef(0.75, 0.0, 0.0); + glEndList(); +} + +void +MechHip(char solid) +{ + int i; + GLUquadricObj *hip[2]; + + glNewList(SOLID_MECH_HIP, GL_COMPILE); +#ifdef LIGHT + SetMaterial(mat_specular, mat_ambient, mat_diffuse, mat_shininess); +#endif + glColor3f(1.0, 1.0, 0.0); + Octagon(0.7, 0.5, solid); +#ifdef SPHERE + for (i = 0; i < 2; i++) { + if (i) + glScalef(-1.0, 1.0, 1.0); + glTranslatef(1.0, 0.0, 0.0); + hip[i] = gluNewQuadric(); +#ifdef LIGHT + SetMaterial(mat_specular2, mat_ambient2, mat_diffuse2, mat_shininess2); +#endif + glColor3f(0.5, 0.5, 0.5); + if (!solid) + gluQuadricDrawStyle(hip[i], GLU_LINE); + gluSphere(hip[0], 0.2, 16, 16); + glTranslatef(-1.0, 0.0, 0.0); + } + glScalef(-1.0, 1.0, 1.0); +#endif + glEndList(); +} + +void +Shoulder(char solid) +{ + GLUquadricObj *deltoid = gluNewQuadric(); + + glNewList(SOLID_MECH_SHOULDER, GL_COMPILE); +#ifdef LIGHT + SetMaterial(mat_specular, mat_ambient, mat_diffuse, mat_shininess); +#endif + glColor3f(1.0, 1.0, 0.0); + Box(1.0, 0.5, 0.5, solid); + glTranslatef(0.9, 0.0, 0.0); +#ifdef LIGHT + SetMaterial(mat_specular2, mat_ambient2, mat_diffuse2, mat_shininess2); +#endif + glColor3f(0.5, 0.5, 0.5); +#ifdef SPHERE + if (!solid) + gluQuadricDrawStyle(deltoid, GLU_LINE); + gluSphere(deltoid, 0.6, 16, 16); +#endif + glTranslatef(-0.9, 0.0, 0.0); + glEndList(); +} + +void +UpperArm(char solid) +{ + GLUquadricObj *upper = gluNewQuadric(); + GLUquadricObj *joint[2]; + GLUquadricObj *joint1[2]; + int i; + + glNewList(SOLID_MECH_UPPER_ARM, GL_COMPILE); +#ifdef LIGHT + SetMaterial(mat_specular, mat_ambient, mat_diffuse, mat_shininess); +#endif + glColor3f(1.0, 1.0, 0.0); + Box(1.0, 2.0, 1.0, solid); + glTranslatef(0.0, -0.95, 0.0); + glRotatef(90.0, 1.0, 0.0, 0.0); +#ifdef LIGHT + SetMaterial(mat_specular2, mat_ambient2, mat_diffuse2, mat_shininess2); +#endif + glColor3f(0.5, 0.5, 0.5); + if (!solid) + gluQuadricDrawStyle(upper, GLU_LINE); + gluCylinder(upper, 0.4, 0.4, 1.5, 16, 10); +#ifdef LIGHT + SetMaterial(mat_specular, mat_ambient, mat_diffuse, mat_shininess); +#endif + glColor3f(1.0, 1.0, 0.0); + glRotatef(-90.0, 1.0, 0.0, 0.0); + glTranslatef(-0.4, -1.85, 0.0); + glRotatef(90.0, 0.0, 1.0, 0.0); + for (i = 0; i < 2; i++) { + joint[i] = gluNewQuadric(); + if (!solid) + gluQuadricDrawStyle(joint[i], GLU_LINE); + if (i) + gluCylinder(joint[i], 0.5, 0.5, 0.8, 16, 10); + else + gluCylinder(joint[i], 0.2, 0.2, 0.8, 16, 10); + } + for (i = 0; i < 2; i++) { + if (i) + glScalef(-1.0, 1.0, 1.0); + joint1[i] = gluNewQuadric(); + if (!solid) + gluQuadricDrawStyle(joint1[i], GLU_LINE); + if (i) + glTranslatef(0.0, 0.0, 0.8); + gluDisk(joint1[i], 0.2, 0.5, 16, 10); + if (i) + glTranslatef(0.0, 0.0, -0.8); + } + glScalef(-1.0, 1.0, 1.0); + glRotatef(-90.0, 0.0, 1.0, 0.0); + glTranslatef(0.4, 2.9, 0.0); + glEndList(); +} + +void +VulcanGun(char solid) +{ + int i; + GLUquadricObj *Barrel[5]; + GLUquadricObj *BarrelFace[5]; + GLUquadricObj *Barrel2[5]; + GLUquadricObj *Barrel3[5]; + GLUquadricObj *BarrelFace2[5]; + GLUquadricObj *Mount = gluNewQuadric(); + GLUquadricObj *Mount_face = gluNewQuadric(); + + glNewList(SOLID_MECH_VULCAN, GL_COMPILE); + +#ifdef LIGHT + SetMaterial(mat_specular2, mat_ambient2, mat_diffuse2, mat_shininess2); +#endif + glColor3f(0.5, 0.5, 0.5); + + if (!solid) { + gluQuadricDrawStyle(Mount, GLU_LINE); + gluQuadricDrawStyle(Mount_face, GLU_LINE); + } + gluCylinder(Mount, 0.5, 0.5, 0.5, 16, 10); + glTranslatef(0.0, 0.0, 0.5); + gluDisk(Mount_face, 0.0, 0.5, 16, 10); + + for (i = 0; i < 5; i++) { + Barrel[i] = gluNewQuadric(); + BarrelFace[i] = gluNewQuadric(); + BarrelFace2[i] = gluNewQuadric(); + Barrel2[i] = gluNewQuadric(); + Barrel3[i] = gluNewQuadric(); + glRotatef(72.0, 0.0, 0.0, 1.0); + glTranslatef(0.0, 0.3, 0.0); + if (!solid) { + gluQuadricDrawStyle(Barrel[i], GLU_LINE); + gluQuadricDrawStyle(BarrelFace[i], GLU_LINE); + gluQuadricDrawStyle(BarrelFace2[i], GLU_LINE); + gluQuadricDrawStyle(Barrel2[i], GLU_LINE); + gluQuadricDrawStyle(Barrel3[i], GLU_LINE); + } + gluCylinder(Barrel[i], 0.15, 0.15, 2.0, 16, 10); + gluCylinder(Barrel3[i], 0.06, 0.06, 2.0, 16, 10); + glTranslatef(0.0, 0.0, 2.0); + gluDisk(BarrelFace[i], 0.1, 0.15, 16, 10); + gluCylinder(Barrel2[i], 0.1, 0.1, 0.1, 16, 5); + glTranslatef(0.0, 0.0, 0.1); + gluDisk(BarrelFace2[i], 0.06, 0.1, 16, 5); + glTranslatef(0.0, -0.3, -2.1); + } + glEndList(); +} + +void +ForeArm(char solid) +{ + char i; + + glNewList(SOLID_MECH_FOREARM, GL_COMPILE); +#ifdef LIGHT + SetMaterial(mat_specular, mat_ambient, mat_diffuse, mat_shininess); +#endif + glColor3f(1.0, 1.0, 0.0); + for (i = 0; i < 5; i++) { + glTranslatef(0.0, -0.1, -0.15); + Box(0.6, 0.8, 0.2, solid); + glTranslatef(0.0, 0.1, -0.15); + Box(0.4, 0.6, 0.1, solid); + } + glTranslatef(0.0, 0.0, 2.45); + Box(1.0, 1.0, 2.0, solid); + glTranslatef(0.0, 0.0, -1.0); + glEndList(); +} + +void +UpperLeg(char solid) +{ + int i; + GLUquadricObj *Hamstring = gluNewQuadric(); + GLUquadricObj *Knee = gluNewQuadric(); + GLUquadricObj *joint[2]; + + glNewList(SOLID_MECH_UPPER_LEG, GL_COMPILE); +#ifdef LIGHT + SetMaterial(mat_specular, mat_ambient, mat_diffuse, mat_shininess); +#endif + glColor3f(1.0, 1.0, 0.0); + if (!solid) { + gluQuadricDrawStyle(Hamstring, GLU_LINE); + gluQuadricDrawStyle(Knee, GLU_LINE); + } + glTranslatef(0.0, -1.0, 0.0); + Box(0.4, 1.0, 0.7, solid); + glTranslatef(0.0, -0.65, 0.0); + for (i = 0; i < 5; i++) { + Box(1.2, 0.3, 1.2, solid); + glTranslatef(0.0, -0.2, 0.0); + Box(1.0, 0.1, 1.0, solid); + glTranslatef(0.0, -0.2, 0.0); + } + glTranslatef(0.0, -0.15, -0.4); + Box(2.0, 0.5, 2.0, solid); + glTranslatef(0.0, -0.3, -0.2); + glRotatef(90.0, 1.0, 0.0, 0.0); +#ifdef LIGHT + SetMaterial(mat_specular2, mat_ambient2, mat_diffuse2, mat_shininess2); +#endif + glColor3f(0.5, 0.5, 0.5); + gluCylinder(Hamstring, 0.6, 0.6, 3.0, 16, 10); +#ifdef LIGHT + SetMaterial(mat_specular, mat_ambient, mat_diffuse, mat_shininess); +#endif + glColor3f(1.0, 1.0, 0.0); + glRotatef(-90.0, 1.0, 0.0, 0.0); + glTranslatef(0.0, -1.5, 1.0); + Box(1.5, 3.0, 0.5, solid); + glTranslatef(0.0, -1.75, -0.8); + Box(2.0, 0.5, 2.0, solid); + glTranslatef(0.0, -0.9, -0.85); +#ifdef LIGHT + SetMaterial(mat_specular2, mat_ambient2, mat_diffuse2, mat_shininess2); +#endif + glColor3f(0.5, 0.5, 0.5); + gluCylinder(Knee, 0.8, 0.8, 1.8, 16, 10); + for (i = 0; i < 2; i++) { + if (i) + glScalef(-1.0, 1.0, 1.0); + joint[i] = gluNewQuadric(); + if (!solid) + gluQuadricDrawStyle(joint[i], GLU_LINE); + if (i) + glTranslatef(0.0, 0.0, 1.8); + gluDisk(joint[i], 0.0, 0.8, 16, 10); + if (i) + glTranslatef(0.0, 0.0, -1.8); + } + glScalef(-1.0, 1.0, 1.0); + glEndList(); +} + +void +Foot(char solid) +{ + + glNewList(SOLID_MECH_FOOT, GL_COMPILE); +#ifdef LIGHT + SetMaterial(mat_specular2, mat_ambient2, mat_diffuse2, mat_shininess2); +#endif + glColor3f(0.5, 0.5, 0.5); + glRotatef(90.0, 1.0, 0.0, 0.0); + Octagon(1.5, 0.6, solid); + glRotatef(-90.0, 1.0, 0.0, 0.0); + glEndList(); +} + +void +LowerLeg(char solid) +{ + float k, l; + GLUquadricObj *ankle = gluNewQuadric(); + GLUquadricObj *ankle_face[2],*joints; + +#ifdef LIGHT + SetMaterial(mat_specular, mat_ambient, mat_diffuse, mat_shininess); +#endif + glColor3f(1.0, 1.0, 0.0); + for (k = 0.0; k < 2.0; k++) { + for (l = 0.0; l < 2.0; l++) { + glPushMatrix(); + glTranslatef(k, 0.0, l); +#ifdef LIGHT + SetMaterial(mat_specular, mat_ambient, mat_diffuse, mat_shininess); +#endif + glColor3f(1.0, 1.0, 0.0); + Box(1.0, 0.5, 1.0, solid); + glTranslatef(0.0, -0.45, 0.0); +#ifdef LIGHT + SetMaterial(mat_specular2, mat_ambient2, mat_diffuse2, mat_shininess2); +#endif + glColor3f(0.5, 0.5, 0.5); +#ifdef SPHERE + joints = gluNewQuadric(); + if(!solid)gluQuadricDrawStyle(joints, GLU_LINE); + gluSphere(joints,0.2, 16, 16); + free(joints); +#endif + if (leg) + glRotatef((GLfloat) heel1, 1.0, 0.0, 0.0); + else + glRotatef((GLfloat) heel2, 1.0, 0.0, 0.0); + /* glTranslatef(0.0, -0.2, 0.0); */ + glTranslatef(0.0, -1.7, 0.0); +#ifdef LIGHT + SetMaterial(mat_specular, mat_ambient, mat_diffuse, mat_shininess); +#endif + glColor3f(1.0, 1.0, 0.0); + Box(0.25, 3.0, 0.25, solid); + glTranslatef(0.0, -1.7, 0.0); +#ifdef LIGHT + SetMaterial(mat_specular2, mat_ambient2, mat_diffuse2, mat_shininess2); +#endif + glColor3f(0.5, 0.5, 0.5); +#ifdef SPHERE + joints = gluNewQuadric(); + if(!solid)gluQuadricDrawStyle(joints, GLU_LINE); + gluSphere(joints, 0.2, 16, 16); +#endif + if (leg) + glRotatef((GLfloat) - heel1, 1.0, 0.0, 0.0); + else + glRotatef((GLfloat) - heel2, 1.0, 0.0, 0.0); + glTranslatef(0.0, -0.45, 0.0); +#ifdef LIGHT + SetMaterial(mat_specular, mat_ambient, mat_diffuse, mat_shininess); +#endif + glColor3f(1.0, 1.0, 0.0); + Box(1.0, 0.5, 1.0, solid); + if (!k && !l) { + int j; + + glTranslatef(-0.4, -0.8, 0.5); + if (leg) + glRotatef((GLfloat) ankle1, 1.0, 0.0, 0.0); + else + glRotatef((GLfloat) ankle2, 1.0, 0.0, 0.0); + glRotatef(90.0, 0.0, 1.0, 0.0); + if (!solid) + gluQuadricDrawStyle(ankle, GLU_LINE); + gluCylinder(ankle, 0.8, 0.8, 1.8, 16, 10); + for (j = 0; j < 2; j++) { + ankle_face[j] = gluNewQuadric(); + if (!solid) + gluQuadricDrawStyle(ankle_face[j], GLU_LINE); + if (j) { + glScalef(-1.0, 1.0, 1.0); + glTranslatef(0.0, 0.0, 1.8); + } + gluDisk(ankle_face[j], 0.0, 0.8, 16, 10); + if (j) + glTranslatef(0.0, 0.0, -1.8); + } + glScalef(-1.0, 1.0, 1.0); + glRotatef(-90.0, 0.0, 1.0, 0.0); + glTranslatef(0.95, -0.8, 0.0); + glCallList(SOLID_MECH_FOOT); + } + glPopMatrix(); + } + } +} + +void +RocketPod(char solid) +{ + + int i, j, k = 0; + GLUquadricObj *rocket[6]; + GLUquadricObj *rocket1[6]; + + glNewList(SOLID_MECH_ROCKET, GL_COMPILE); +#ifdef LIGHT + SetMaterial(mat_specular2, mat_ambient2, mat_diffuse2, mat_shininess2); +#endif + glColor3f(0.5, 0.5, 0.5); + glScalef(0.4, 0.4, 0.4); + glRotatef(45.0, 0.0, 0.0, 1.0); + glTranslatef(1.0, 0.0, 0.0); + Box(2.0, 0.5, 3.0, solid); + glTranslatef(1.0, 0.0, 0.0); + glRotatef(45.0, 0.0, 0.0, 1.0); + glTranslatef(0.5, 0.0, 0.0); + Box(1.2, 0.5, 3.0, solid); + glTranslatef(2.1, 0.0, 0.0); + glRotatef(-90.0, 0.0, 0.0, 1.0); +#ifdef LIGHT + SetMaterial(mat_specular, mat_ambient, mat_diffuse, mat_shininess); +#endif + glColor3f(1.0, 1.0, 0.0); + Box(2.0, 3.0, 4.0, solid); + glTranslatef(-0.5, -1.0, 1.3); + for (i = 0; i < 2; i++) { + for (j = 0; j < 3; j++) { + rocket[k] = gluNewQuadric(); + rocket1[k] = gluNewQuadric(); + if (!solid) { + gluQuadricDrawStyle(rocket[k], GLU_LINE); + gluQuadricDrawStyle(rocket1[k], GLU_LINE); + } + glTranslatef(i, j, 0.6); +#ifdef LIGHT + SetMaterial(mat_specular3, mat_ambient3, mat_diffuse3, mat_shininess3); +#endif + glColor3f(1.0, 1.0, 1.0); + gluCylinder(rocket[k], 0.4, 0.4, 0.3, 16, 10); + glTranslatef(0.0, 0.0, 0.3); +#ifdef LIGHT + SetMaterial(mat_specular4, mat_ambient4, mat_diffuse4, mat_shininess4); +#endif + glColor3f(0.0, 1.0, 0.0); + gluCylinder(rocket1[k], 0.4, 0.0, 0.5, 16, 10); + k++; + glTranslatef(-i, -j, -0.9); + } + } + glEndList(); +} + +void +Enviro(char solid) +{ + + int i, j; + + glNewList(SOLID_ENVIRO, GL_COMPILE); + SetMaterial(mat_specular4, mat_ambient4, mat_diffuse4, mat_shininess4); + glColor3f(0.0, 1.0, 0.0); + Box(20.0, 0.5, 30.0, solid); + + SetMaterial(mat_specular4, mat_ambient3, mat_diffuse2, mat_shininess); + glColor3f(0.6, 0.6, 0.6); + glTranslatef(0.0, 0.0, -10.0); + for (j = 0; j < 6; j++) { + for (i = 0; i < 2; i++) { + if (i) + glScalef(-1.0, 1.0, 1.0); + glTranslatef(10.0, 4.0, 0.0); + Box(4.0, 8.0, 2.0, solid); + glTranslatef(0.0, -1.0, -3.0); + Box(4.0, 6.0, 2.0, solid); + glTranslatef(-10.0, -3.0, 3.0); + } + glScalef(-1.0, 1.0, 1.0); + glTranslatef(0.0, 0.0, 5.0); + } + + glEndList(); +} + +void +Toggle(void) +{ + if (solid_part) + solid_part = 0; + else + solid_part = 1; +} + +void +disable(void) +{ + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + glDisable(GL_NORMALIZE); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); +} + +void +lighting(void) +{ + + GLfloat position[] = + {0.0, 0.0, 2.0, 1.0}; + +#ifdef MOVE_LIGHT + glRotatef((GLfloat) lightturn1, 1.0, 0.0, 0.0); + glRotatef((GLfloat) lightturn, 0.0, 1.0, 0.0); + glRotatef(0.0, 1.0, 0.0, 0.0); +#endif + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_NORMALIZE); + /* glEnable(GL_FLAT); */ + /* glDepthFunc(GL_LESS); */ + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + glLightfv(GL_LIGHT0, GL_POSITION, position); + glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 80.0); + + glTranslatef(0.0, 0.0, 2.0); + glDisable(GL_LIGHTING); + Box(0.1, 0.1, 0.1, 0); + glEnable(GL_LIGHTING); + /* glEnable(GL_CULL_FACE); */ +} + +void +DrawMech(void) +{ + int i, j; + + glScalef(0.5, 0.5, 0.5); + glPushMatrix(); + glTranslatef(0.0, -0.75, 0.0); + glRotatef((GLfloat) tilt, 1.0, 0.0, 0.0); + + glRotatef(90.0, 1.0, 0.0, 0.0); +#ifdef HIP + glCallList(SOLID_MECH_HIP); +#endif + glRotatef(-90.0, 1.0, 0.0, 0.0); + + glTranslatef(0.0, 0.75, 0.0); + glPushMatrix(); + glRotatef((GLfloat) pivot, 0.0, 1.0, 0.0); + glPushMatrix(); +#ifdef TORSO + glCallList(SOLID_MECH_TORSO); +#endif + glPopMatrix(); + glPushMatrix(); + glTranslatef(0.5, 0.5, 0.0); +#ifdef ROCKET_POD + glCallList(SOLID_MECH_ROCKET); +#endif + glPopMatrix(); + for (i = 0; i < 2; i++) { + glPushMatrix(); + if (i) + glScalef(-1.0, 1.0, 1.0); + glTranslatef(1.5, 0.0, 0.0); +#ifdef SHOULDER + glCallList(SOLID_MECH_SHOULDER); +#endif + glTranslatef(0.9, 0.0, 0.0); + if (i) { + glRotatef((GLfloat) lat1, 0.0, 0.0, 1.0); + glRotatef((GLfloat) shoulder1, 1.0, 0.0, 0.0); + glRotatef((GLfloat) shoulder3, 0.0, 1.0, 0.0); + } else { + glRotatef((GLfloat) lat2, 0.0, 0.0, 1.0); + glRotatef((GLfloat) shoulder2, 1.0, 0.0, 0.0); + glRotatef((GLfloat) shoulder4, 0.0, 1.0, 0.0); + } + glTranslatef(0.0, -1.4, 0.0); +#ifdef UPPER_ARM + glCallList(SOLID_MECH_UPPER_ARM); +#endif + glTranslatef(0.0, -2.9, 0.0); + if (i) + glRotatef((GLfloat) elbow1, 1.0, 0.0, 0.0); + else + glRotatef((GLfloat) elbow2, 1.0, 0.0, 0.0); + glTranslatef(0.0, -0.9, -0.2); +#ifdef LOWER_ARM + glCallList(SOLID_MECH_FOREARM); + glPushMatrix(); + glTranslatef(0.0, 0.0, 2.0); + glRotatef((GLfloat) fire, 0.0, 0.0, 1.0); + glCallList(SOLID_MECH_VULCAN); + glPopMatrix(); +#endif + glPopMatrix(); + } + glPopMatrix(); + + glPopMatrix(); + + for (j = 0; j < 2; j++) { + glPushMatrix(); + if (j) { + glScalef(-0.5, 0.5, 0.5); + leg = 1; + } else { + glScalef(0.5, 0.5, 0.5); + leg = 0; + } + glTranslatef(2.0, -1.5, 0.0); + if (j) { + glRotatef((GLfloat) hip11, 1.0, 0.0, 0.0); + glRotatef((GLfloat) hip12, 0.0, 0.0, 1.0); + } else { + glRotatef((GLfloat) hip21, 1.0, 0.0, 0.0); + glRotatef((GLfloat) hip22, 0.0, 0.0, 1.0); + } + glTranslatef(0.0, 0.3, 0.0); +#ifdef UPPER_LEG + glPushMatrix(); + glCallList(SOLID_MECH_UPPER_LEG); + glPopMatrix(); +#endif + glTranslatef(0.0, -8.3, -0.4); + if (j) + glRotatef((GLfloat) - hip12, 0.0, 0.0, 1.0); + else + glRotatef((GLfloat) - hip22, 0.0, 0.0, 1.0); + glTranslatef(-0.5, -0.85, -0.5); +#ifdef LOWER_LEG + LowerLeg(1); +#endif + glPopMatrix(); + } +} + +void +display(void) +{ + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glEnable(GL_DEPTH_TEST); + + glPushMatrix(); + glRotatef((GLfloat) turn, 0.0, 1.0, 0.0); + glRotatef((GLfloat) turn1, 1.0, 0.0, 0.0); +#ifdef LIGHT + if (solid_part) { + glPushMatrix(); + lighting(); + glPopMatrix(); + } else + disable(); +#endif +#ifdef DRAW_MECH + glPushMatrix(); + glTranslatef(0.0, elevation, 0.0); + DrawMech(); + glPopMatrix(); +#endif +#ifdef DRAW_ENVIRO + glPushMatrix(); + if (distance >= 20.136) + distance = 0.0; + glTranslatef(0.0, -5.0, -distance); + glCallList(SOLID_ENVIRO); + glTranslatef(0.0, 0.0, 10.0); + glCallList(SOLID_ENVIRO); + glPopMatrix(); +#endif + glPopMatrix(); + glFlush(); + tkSwapBuffers(); +} + +void +init(void) +{ + char i = 1; + +#ifdef LIGHT + SetMaterial(mat_specular2, mat_ambient2, mat_diffuse2, mat_shininess2); +#endif + glEnable(GL_DEPTH_TEST); + MechTorso(i); + MechHip(i); + Shoulder(i); + RocketPod(i); + UpperArm(i); + ForeArm(i); + UpperLeg(i); + Foot(i); + VulcanGun(i); + Enviro(i); +} + +void +reshape(int w, int h) +{ + glViewport(0, 0, w, h); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(65.0, (GLfloat) w / (GLfloat) h, 1.0, 20.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.0, 1.2, -5.5); /* viewing transform */ +} + +#ifdef ANIMATION +void +animation_walk(void) +{ + float angle; + static int step; + + if (step == 0 || step == 2) { + /* for(frame=3.0; frame<=21.0; frame=frame+3.0){ */ + if (frame >= 0.0 && frame <= 21.0) { + if (frame == 0.0) + frame = 3.0; + angle = (180 / PI) * (acos(((cos((PI / 180) * frame) * 2.043) + 1.1625) / 3.2059)); + if (frame > 0) { + elevation = -(3.2055 - (cos((PI / 180) * angle) * 3.2055)); + } else + elevation = 0.0; + if (step == 0) { + hip11 = -(frame * 1.7); + if (1.7 * frame > 15) + heel1 = frame * 1.7; + heel2 = 0; + ankle1 = frame * 1.7; + if (frame > 0) + hip21 = angle; + else + hip21 = 0; + ankle2 = -hip21; + shoulder1 = frame * 1.5; + shoulder2 = -frame * 1.5; + elbow1 = frame; + elbow2 = -frame; + } else { + hip21 = -(frame * 1.7); + if (1.7 * frame > 15) + heel2 = frame * 1.7; + heel1 = 0; + ankle2 = frame * 1.7; + if (frame > 0) + hip11 = angle; + else + hip11 = 0; + ankle1 = -hip11; + shoulder1 = -frame * 1.5; + shoulder2 = frame * 1.5; + elbow1 = -frame; + elbow2 = frame; + } + if (frame == 21) + step++; + if (frame < 21) + frame = frame + 3.0; + } + } + if (step == 1 || step == 3) { + /* for(x=21.0; x>=0.0; x=x-3.0){ */ + if (frame <= 21.0 && frame >= 0.0) { + angle = (180 / PI) * (acos(((cos((PI / 180) * frame) * 2.043) + 1.1625) / 3.2029)); + if (frame > 0) + elevation = -(3.2055 - (cos((PI / 180) * angle) * 3.2055)); + else + elevation = 0.0; + if (step == 1) { + elbow2 = hip11 = -frame; + elbow1 = heel1 = frame; + heel2 = 15; + ankle1 = frame; + if (frame > 0) + hip21 = angle; + else + hip21 = 0; + ankle2 = -hip21; + shoulder1 = 1.5 * frame; + shoulder2 = -frame * 1.5; + } else { + elbow1 = hip21 = -frame; + elbow2 = heel2 = frame; + heel1 = 15; + ankle2 = frame; + if (frame > 0) + hip11 = angle; + else + hip11 = 0; + ankle1 = -hip11; + shoulder1 = -frame * 1.5; + shoulder2 = frame * 1.5; + } + if (frame == 0.0) + step++; + if (frame > 0) + frame = frame - 3.0; + } + } + if (step == 4) + step = 0; + distance += 0.1678; +} + +void +animation(void) +{ + animation_walk(); +} + +#endif + +GLenum key(int key, GLenum mask) +{ + + int i = 0; + + switch (key) { + /* start arm control functions */ + case 'q':{ + shoulder2Subtract(); + i++; + } + break; + case 'a':{ + shoulder2Add(); + i++; + } + break; + case 'w':{ + shoulder1Subtract(); + i++; + } + break; + case 's':{ + shoulder1Add(); + i++; + } + break; + case '2':{ + shoulder3Add(); + i++; + } + break; + case '1':{ + shoulder4Add(); + i++; + } + break; + case '4':{ + shoulder3Subtract(); + i++; + } + break; + case '3':{ + shoulder4Subtract(); + i++; + } + break; + + case 'z':{ + lat2Raise(); + i++; + } + break; + case 'Z':{ + lat2Lower(); + i++; + } + break; + case 'x':{ + lat1Raise(); + i++; + } + break; + case 'X':{ + lat1Lower(); + i++; + } + break; + + case 'A':{ + elbow2Add(); + i++; + } + break; + case 'Q':{ + elbow2Subtract(); + i++; + } + break; + case 'S':{ + elbow1Add(); + i++; + } + break; + case 'W':{ + elbow1Subtract(); + i++; + } + break; + /* end of arm control functions */ + + /* start of torso control functions */ + case 'd':{ + RotateAdd(); + i++; + } + break; + case 'g':{ + RotateSubtract(); + i++; + } + break; + case 'r':{ + MechTiltAdd(); + i++; + } + break; + case 'f':{ + MechTiltSubtract(); + i++; + } + break; + /* end of torso control functions */ + + /* start of leg control functions */ + case 'h':{ + RaiseLeg2Forward(); + i++; + } + break; + case 'y':{ + LowerLeg2Backwards(); + i++; + } + break; + case 'Y':{ + RaiseLeg2Outwards(); + i++; + } + break; + case 'H':{ + LowerLeg2Inwards(); + i++; + } + break; + + case 'j':{ + RaiseLeg1Forward(); + i++; + } + break; + case 'u':{ + LowerLeg1Backwards(); + i++; + } + break; + case 'U':{ + RaiseLeg1Outwards(); + i++; + } + break; + case 'J':{ + LowerLeg1Inwards(); + i++; + } + break; + + case 'N':{ + Heel2Add(); + i++; + } + break; + case 'n':{ + Heel2Subtract(); + i++; + } + break; + case 'M':{ + Heel1Add(); + i++; + } + break; + case 'm':{ + Heel1Subtract(); + i++; + } + break; + + case 'k':{ + Ankle2Add(); + i++; + } + break; + case 'K':{ + Ankle2Subtract(); + i++; + } + break; + case 'l':{ + Ankle1Add(); + i++; + } + break; + case 'L':{ + Ankle1Subtract(); + i++; + } + break; + /* end of leg control functions */ + + /* start of light source position functions */ + case 'p':{ + LightTurnRight(); + i++; + } + break; + case 'i':{ + LightTurnLeft(); + i++; + } + break; + case 'o':{ + LightForwards(); + i++; + } + break; + case '9':{ + LightBackwards(); + i++; + } + break; + /* end of light source position functions */ + + /* start of misc functions */ + case 't': + Toggle(); + break; + + case KEY_LEFT: + TurnLeft(); + break; + case KEY_RIGHT: + TurnRight(); + break; + case KEY_UP: + TurnBackwards(); + break; + case KEY_DOWN: + TurnForwards(); + break; + + case ' ': + FireCannon(); + } + return 0; +} + +void printHelp(void) +{ + printf("at the shoulders:"); + printf("forward : q,w"); + printf("backwards : a,s"); + printf("outwards : z,x"); + printf("inwards : Z,X"); +#if 0 + glut_menu[6] = glutCreateMenu(null_select); + printf("upwards : Q,W\n"); + printf("downwards : A,S\n"); + printf("outwards : 1,2\n"); + printf("inwards : 3,4\n"); + + glut_menu[1] = glutCreateMenu(null_select); + printf(" : Page_up\n"); + + glut_menu[8] = glutCreateMenu(null_select); + printf("forward : y,u\n"); + printf("backwards : h.j\n"); + printf("outwards : Y,U\n"); + printf("inwards : H,J\n"); + + glut_menu[9] = glutCreateMenu(null_select); + printf("forward : n,m\n"); + printf("backwards : N,M\n"); + + glut_menu[9] = glutCreateMenu(null_select); + printf("forward : n,m\n"); + printf("backwards : N,M\n"); + + glut_menu[10] = glutCreateMenu(null_select); + printf("toes up : K,L\n"); + printf("toes down : k,l\n"); + + glut_menu[11] = glutCreateMenu(null_select); + printf("right : right arrow\n"); + printf("left : left arrow\n"); + printf("down : up arrow\n"); + printf("up : down arrow\n"); + + glut_menu[12] = glutCreateMenu(null_select); + printf("right : p\n"); + printf("left : i\n"); + printf("up : 9\n"); + printf("down : o\n"); + + glut_menu[4] = glutCreateMenu(NULL); + glutAddSubMenu("at the elbows?", glut_menu[6]); + + glut_menu[7] = glutCreateMenu(NULL); + glutAddSubMenu("at the hip? ", glut_menu[8]); + glutAddSubMenu("at the knees?", glut_menu[9]); + glutAddSubMenu("at the ankles? ", glut_menu[10]); + + printf("turn left : d\n"); + printf("turn right : g\n"); + + glut_menu[3] = glutCreateMenu(null_select); + printf("tilt backwards : f\n"); + printf("tilt forwards : r\n"); + + glut_menu[0] = glutCreateMenu(NULL); + glutAddSubMenu("move the arms.. ", glut_menu[4]); + glutAddSubMenu("fire the vulcan guns?", glut_menu[1]); + glutAddSubMenu("move the legs.. ", glut_menu[7]); + glutAddSubMenu("move the torso?", glut_menu[2]); + glutAddSubMenu("move the hip?", glut_menu[3]); + glutAddSubMenu("rotate the scene..", glut_menu[11]); +#ifdef MOVE_LIGHT + glutAddSubMenu("rotate the light source..", glut_menu[12]); +#endif + + glutCreateMenu(menu_select); +#ifdef ANIMATION + printf("Start Walk", 1); + printf("Stop Walk", 2); +#endif + printf("Toggle Wireframe", 3); + glutAddSubMenu("How do I ..", glut_menu[0]); + printfy("Quit", 4); + glutAttachMenu(GLUT_LEFT_BUTTON); + glutAttachMenu(GLUT_RIGHT_BUTTON); +#endif +} + +void idle( void ) +{ + /* animate the mech */ + + animation(); + + /* draw the Mech */ + + display(); +} + +/* #define PROFILE */ + +#ifdef PROFILE +extern int count_triangles; +#endif + +// #define LINUX_TEST_FLOAT + +#ifdef LINUX_TEST_FLOAT +#include +#endif + +int +main(int argc, char **argv) +{ +#ifdef LINUX_TEST_FLOAT + /* for debuging floating point errors under Linux */ + __setfpucw ( 0x1372 ); +#endif + + Toggle(); + + return ui_loop(argc, argv, "mech"); +} diff --git a/apps/tinygl/src/TinyGL/examples/nanox.c b/apps/tinygl/src/TinyGL/examples/nanox.c new file mode 100644 index 0000000..14e5d4f --- /dev/null +++ b/apps/tinygl/src/TinyGL/examples/nanox.c @@ -0,0 +1,113 @@ +/* + * Demonstration program for Nano-X graphics. + */ +#include +#include +#include +#define MWINCLUDECOLORS +#include +#include +#include +#include "ui.h" + +static GR_WINDOW_ID w1; /* id for large window */ +static GR_GC_ID gc1; /* graphics context for text */ + +void errorcatcher(); /* routine to handle errors */ + +void tkSwapBuffers(void) +{ + nglXSwapBuffers(w1); +} + +int +ui_loop(int argc,char **argv, const char *name) +{ + GR_EVENT event; /* current event */ + GR_IMAGE_ID id = 0; + NGLXContext cx; + int width, height, k; + + if (GrOpen() < 0) { + fprintf(stderr, "cannot open graphics\n"); + exit(1); + } + + width = 400; + height = 300; + + GrSetErrorHandler(errorcatcher); + + w1 = GrNewWindow(GR_ROOT_WINDOW_ID, 10, 10, width, height, 4, BLACK, WHITE); + + GrSelectEvents(w1, GR_EVENT_MASK_CLOSE_REQ|GR_EVENT_MASK_EXPOSURE|GR_EVENT_MASK_KEY_DOWN); + + GrMapWindow(w1); + + gc1 = GrNewGC(); + + GrSetGCForeground(gc1, WHITE); + + cx = nglXCreateContext(NULL, 0); + nglXMakeCurrent(w1, cx); + + init(); + reshape(width, height); + + while (1) { + GrCheckNextEvent(&event); + switch(event.type) { + case GR_EVENT_TYPE_CLOSE_REQ: + GrFreeImage(id); + GrClose(); + exit(0); + case GR_EVENT_TYPE_EXPOSURE: + break; + case GR_EVENT_TYPE_KEY_DOWN: + { + GR_EVENT_KEYSTROKE *kp = &event.keystroke; + /* XXX: nanoX special keys are totally bugged ! */ + switch(kp->ch) { + case 81: + k = KEY_LEFT; + break; + case 83: + k = KEY_RIGHT; + break; + case 82: + k = KEY_UP; + break; + case 84: + k = KEY_DOWN; + break; + default: + k = kp->ch; + break; + } + key(k, 0); + } + break; + default: + idle(); + break; + } + } + + return 0; +} + + +/* + * Here on an unrecoverable error. + */ +void +errorcatcher(code, name, id) + GR_ERROR code; /* error code */ + GR_FUNC_NAME name; /* function name which failed */ + GR_ID id; /* resource id */ +{ + GrClose(); + fprintf(stderr, "DEMO ERROR: code %d, function %s, resource id %d\n", + code, name, id); + exit(1); +} diff --git a/apps/tinygl/src/TinyGL/examples/spin.c b/apps/tinygl/src/TinyGL/examples/spin.c new file mode 100644 index 0000000..be4e4ef --- /dev/null +++ b/apps/tinygl/src/TinyGL/examples/spin.c @@ -0,0 +1,161 @@ +/* spin.c */ + + +/* + * Spinning box. This program is in the public domain. + * + * Brian Paul + */ + + +#include +#include +#include + +#include +#include +#include "ui.h" + + + + +static GLfloat Xrot, Xstep; +static GLfloat Yrot, Ystep; +static GLfloat Zrot, Zstep; +static GLfloat Step = 5.0; +static GLfloat Scale = 1.0; +static GLuint Object; + + + + +static GLuint make_object( void ) +{ + GLuint list; + + list = glGenLists( 1 ); + + glNewList( list, GL_COMPILE ); + + glBegin( GL_LINE_LOOP ); + glColor3f( 1.0, 1.0, 1.0 ); + glVertex3f( 1.0, 0.5, -0.4 ); + glColor3f( 1.0, 0.0, 0.0 ); + glVertex3f( 1.0, -0.5, -0.4 ); + glColor3f( 0.0, 1.0, 0.0 ); + glVertex3f( -1.0, -0.5, -0.4 ); + glColor3f( 0.0, 0.0, 1.0 ); + glVertex3f( -1.0, 0.5, -0.4 ); + glEnd(); + + glColor3f( 1.0, 1.0, 1.0 ); + + glBegin( GL_LINE_LOOP ); + glVertex3f( 1.0, 0.5, 0.4 ); + glVertex3f( 1.0, -0.5, 0.4 ); + glVertex3f( -1.0, -0.5, 0.4 ); + glVertex3f( -1.0, 0.5, 0.4 ); + glEnd(); + + glBegin( GL_LINES ); + glVertex3f( 1.0, 0.5, -0.4 ); glVertex3f( 1.0, 0.5, 0.4 ); + glVertex3f( 1.0, -0.5, -0.4 ); glVertex3f( 1.0, -0.5, 0.4 ); + glVertex3f( -1.0, -0.5, -0.4 ); glVertex3f( -1.0, -0.5, 0.4 ); + glVertex3f( -1.0, 0.5, -0.4 ); glVertex3f( -1.0, 0.5, 0.4 ); + glEnd(); + + + glEndList(); + + return list; +} + + + +void reshape( int width, int height ) +{ + glViewport(0, 0, (GLint)width, (GLint)height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 15.0 ); + glMatrixMode(GL_MODELVIEW); +} + + +GLenum key(int k, GLenum mask) +{ + switch (k) { + case KEY_ESCAPE: + exit(0); + } + return GL_FALSE; +} + + +void draw( void ) +{ + glClear( GL_COLOR_BUFFER_BIT ); + + glPushMatrix(); + + glTranslatef( 0.0, 0.0, -10.0 ); + glScalef( Scale, Scale, Scale ); + if (Xstep) { + glRotatef( Xrot, 1.0, 0.0, 0.0 ); + } + else if (Ystep) { + glRotatef( Yrot, 0.0, 1.0, 0.0 ); + } + else { + glRotatef( Zrot, 0.0, 0.0, 1.0 ); + } + + glCallList( Object ); + + glPopMatrix(); + + glFlush(); + tkSwapBuffers(); +} + + +void idle( void ) +{ + Xrot += Xstep; + Yrot += Ystep; + Zrot += Zstep; + + if (Xrot>=360.0) { + Xrot = Xstep = 0.0; + Ystep = Step; + } + else if (Yrot>=360.0) { + Yrot = Ystep = 0.0; + Zstep = Step; + } + else if (Zrot>=360.0) { + Zrot = Zstep = 0.0; + Xstep = Step; + } + draw(); +} + +void init(void) +{ + Object = make_object(); + glCullFace( GL_BACK ); +/* glEnable( GL_CULL_FACE );*/ + glDisable( GL_DITHER ); + glShadeModel( GL_FLAT ); +/* glEnable( GL_DEPTH_TEST ); */ + + Xrot = Yrot = Zrot = 0.0; + Xstep = Step; + Ystep = Zstep = 0.0; +} + + +int main( int argc, char *argv[] ) +{ + return ui_loop(argc, argv, "spin"); +} diff --git a/apps/tinygl/src/TinyGL/examples/texobj.c b/apps/tinygl/src/TinyGL/examples/texobj.c new file mode 100644 index 0000000..913d35a --- /dev/null +++ b/apps/tinygl/src/TinyGL/examples/texobj.c @@ -0,0 +1,193 @@ +/* + * Example of using the 1.1 texture object functions. + * Also, this demo utilizes Mesa's fast texture map path. + * + * Brian Paul June 1996 + */ + +#include +#include +#include +#include + +#include +#include +#include "ui.h" + +static GLuint TexObj[2]; +static GLfloat Angle = 0.0f; + +static int cnt=0,v=0; + +void +draw(void) +{ + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + + glColor3f(1.0, 1.0, 1.0); + + /* draw first polygon */ + glPushMatrix(); + glTranslatef(-1.0, 0.0, 0.0); + glRotatef(Angle, 0.0, 0.0, 1.0); + glBindTexture(GL_TEXTURE_2D, TexObj[v]); + + glEnable(GL_TEXTURE_2D); + glBegin(GL_QUADS); + glTexCoord2f(0.0, 0.0); + glVertex2f(-1.0, -1.0); + glTexCoord2f(1.0, 0.0); + glVertex2f(1.0, -1.0); + glTexCoord2f(1.0, 1.0); + glVertex2f(1.0, 1.0); + glTexCoord2f(0.0, 1.0); + glVertex2f(-1.0, 1.0); + glEnd(); + glDisable(GL_TEXTURE_2D); + glPopMatrix(); + + /* draw second polygon */ + glPushMatrix(); + glTranslatef(1.0, 0.0, 0.0); + glRotatef(Angle - 90.0, 0.0, 1.0, 0.0); + + glBindTexture(GL_TEXTURE_2D, TexObj[1-v]); + + glEnable(GL_TEXTURE_2D); + glBegin(GL_QUADS); + glTexCoord2f(0.0, 0.0); + glVertex2f(-1.0, -1.0); + glTexCoord2f(1.0, 0.0); + glVertex2f(1.0, -1.0); + glTexCoord2f(1.0, 1.0); + glVertex2f(1.0, 1.0); + glTexCoord2f(0.0, 1.0); + glVertex2f(-1.0, 1.0); + glEnd(); + glDisable(GL_TEXTURE_2D); + + glPopMatrix(); + + tkSwapBuffers(); +} + + +/* new window size or exposure */ +void +reshape(int width, int height) +{ + glViewport(0, 0, (GLint) width, (GLint) height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + /* glOrtho( -3.0, 3.0, -3.0, 3.0, -10.0, 10.0 ); */ + glFrustum(-2.0, 2.0, -2.0, 2.0, 6.0, 20.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.0, 0.0, -8.0); +} + + +void bind_texture(int texobj,int image) +{ + static int width = 8, height = 8; + static int color[2][3]={ + {255,0,0}, + {0,255,0}, + }; + GLubyte tex[64][3]; + static GLubyte texchar[2][8*8] = { + { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2, 2, 0, 0, 0, + 0, 0, 2, 0, 0, 2, 0, 0, + 0, 0, 0, 0, 0, 2, 0, 0, + 0, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 0, 2, 0, 0, 0, 0, + 0, 0, 2, 2, 2, 2, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}}; + + int i,j; + + glBindTexture(GL_TEXTURE_2D, texobj); + + /* red on white */ + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) { + int p = i * width + j; + if (texchar[image][(height - i - 1) * width + j]) { + tex[p][0] = color[image][0]; + tex[p][1] = color[image][1]; + tex[p][2] = color[image][2]; + } else { + tex[p][0] = 255; + tex[p][1] = 255; + tex[p][2] = 255; + } + } + } + glTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0, + GL_RGB, GL_UNSIGNED_BYTE, tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + /* end of texture object */ +} + + + +void +init(void) +{ + glEnable(GL_DEPTH_TEST); + + /* Setup texturing */ + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); + + /* generate texture object IDs */ + glGenTextures(2, TexObj); + bind_texture(TexObj[0],0); + bind_texture(TexObj[1],1); + +} + +void +idle(void) +{ + + Angle += 2.0; + + if (++cnt==5) { + cnt=0; + v=!v; + } + draw(); +} + +/* change view angle, exit upon ESC */ +GLenum key(int k, GLenum mask) +{ + switch (k) { + case 'q': + case KEY_ESCAPE: + exit(0); + } + return GL_FALSE; +} + +int main(int argc, char **argv) +{ + return ui_loop(argc, argv, "texobj"); +} + + diff --git a/apps/tinygl/src/TinyGL/examples/ui.h b/apps/tinygl/src/TinyGL/examples/ui.h new file mode 100644 index 0000000..8814566 --- /dev/null +++ b/apps/tinygl/src/TinyGL/examples/ui.h @@ -0,0 +1,17 @@ +/* + * tk like ui + */ +void draw( void ); +void idle( void ); +GLenum key(int k, GLenum mask); +void reshape( int width, int height ); +void init( void ); +int ui_loop(int argc, char **argv, const char *name); +void tkSwapBuffers(void); + +#define KEY_UP 0xe000 +#define KEY_DOWN 0xe001 +#define KEY_LEFT 0xe002 +#define KEY_RIGHT 0xe003 +#define KEY_ESCAPE 0xe004 + diff --git a/apps/tinygl/src/TinyGL/examples/x11.c b/apps/tinygl/src/TinyGL/examples/x11.c new file mode 100644 index 0000000..13913f5 --- /dev/null +++ b/apps/tinygl/src/TinyGL/examples/x11.c @@ -0,0 +1,139 @@ +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include "ui.h" + + +#ifndef M_PI +# define M_PI 3.14159265 +#endif + +static int attributeList[] = { GLX_RGBA, GLX_DOUBLEBUFFER, None }; + +static Bool WaitForNotify(Display *d, XEvent *e, char *arg) +{ + return (e->type == MapNotify) && (e->xmap.window == (Window)arg); +} + +Display *dpy; +Window win; + +void tkSwapBuffers(void) +{ + glXSwapBuffers(dpy,win); +} + +int ui_loop(int argc, char **argv, const char *name) +{ + XVisualInfo *vi; + Colormap cmap; + XSetWindowAttributes swa; + XSizeHints hint; + GLXContext cx; + XEvent event; + int k, width, height; + char buf[80]; + XEvent xev; + KeySym keysym; + XComposeStatus status; + + /* get a connection */ + dpy = XOpenDisplay(NULL); + if (dpy == NULL) { + fprintf(stderr,"Could not open X display\n"); + exit(1); + } + + /* get an appropriate visual */ + vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList); + if (vi == NULL) { + fprintf(stderr, "No suitable visual for glx\n"); + exit(1); + } + + /* create a GLX context */ + cx = glXCreateContext(dpy, vi, 0, GL_TRUE); + + /* create a color map */ + cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), + vi->visual, AllocNone); + + /* create a window */ + width = 400; + height = 300; + hint.x = 0; + hint.y = 0; + hint.width = width; + hint.height = height; + hint.flags = PPosition | PSize; + swa.colormap = cmap; + swa.border_pixel = 0; + swa.event_mask = StructureNotifyMask; + win = XCreateWindow(dpy, RootWindow(dpy, vi->screen), 0, 0, width, height, + 0, vi->depth, InputOutput, vi->visual, + CWBorderPixel|CWColormap|CWEventMask, &swa); + XSetStandardProperties (dpy, win, name, name, None, NULL, 0, &hint); + + XMapWindow(dpy, win); + XIfEvent(dpy, &event, WaitForNotify, (char*)win); + XSelectInput(dpy, win, KeyPressMask | StructureNotifyMask | ExposureMask); + + /* connect the context to the window */ + glXMakeCurrent(dpy, win, cx); + + init(); + reshape(width, height); + + while (1) { + if (XPending(dpy) > 0) { + XNextEvent(dpy,&xev); + switch(xev.type) { + case KeyPress: + XLookupString((XKeyEvent *)&xev,buf,80,&keysym,&status); + switch(keysym) { + case XK_Up: + k = KEY_UP; + break; + case XK_Down: + k = KEY_DOWN; + break; + case XK_Left: + k = KEY_LEFT; + break; + case XK_Right: + k = KEY_RIGHT; + break; + case XK_Escape: + k = KEY_ESCAPE; + break; + default: + k = keysym; + } + key(k, 0); + break; + case ConfigureNotify: + { + int width,height; + width = xev.xconfigure.width; + height = xev.xconfigure.height; + glXWaitX(); + reshape(width, height); + } + break; + } + } else { + idle(); + } + } + return 0; +} + + diff --git a/apps/tinygl/src/TinyGL/include/GL/gl.h b/apps/tinygl/src/TinyGL/include/GL/gl.h new file mode 100644 index 0000000..2403504 --- /dev/null +++ b/apps/tinygl/src/TinyGL/include/GL/gl.h @@ -0,0 +1,838 @@ +/* + * The following constants come from Mesa + */ +#ifndef GL_H +#define GL_H + +#define GL_VERSION_1_1 1 + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + /* Boolean values */ + GL_FALSE = 0, + GL_TRUE = 1, + + /* Data types */ + GL_BYTE = 0x1400, + GL_UNSIGNED_BYTE = 0x1401, + GL_SHORT = 0x1402, + GL_UNSIGNED_SHORT = 0x1403, + GL_INT = 0x1404, + GL_UNSIGNED_INT = 0x1405, + GL_FLOAT = 0x1406, + GL_DOUBLE = 0x140A, + GL_2_BYTES = 0x1407, + GL_3_BYTES = 0x1408, + GL_4_BYTES = 0x1409, + + /* Primitives */ + GL_LINES = 0x0001, + GL_POINTS = 0x0000, + GL_LINE_STRIP = 0x0003, + GL_LINE_LOOP = 0x0002, + GL_TRIANGLES = 0x0004, + GL_TRIANGLE_STRIP = 0x0005, + GL_TRIANGLE_FAN = 0x0006, + GL_QUADS = 0x0007, + GL_QUAD_STRIP = 0x0008, + GL_POLYGON = 0x0009, + GL_EDGE_FLAG = 0x0B43, + + /* Vertex Arrays */ + GL_VERTEX_ARRAY = 0x8074, + GL_NORMAL_ARRAY = 0x8075, + GL_COLOR_ARRAY = 0x8076, + GL_INDEX_ARRAY = 0x8077, + GL_TEXTURE_COORD_ARRAY = 0x8078, + GL_EDGE_FLAG_ARRAY = 0x8079, + GL_VERTEX_ARRAY_SIZE = 0x807A, + GL_VERTEX_ARRAY_TYPE = 0x807B, + GL_VERTEX_ARRAY_STRIDE = 0x807C, + GL_VERTEX_ARRAY_COUNT = 0x807D, + GL_NORMAL_ARRAY_TYPE = 0x807E, + GL_NORMAL_ARRAY_STRIDE = 0x807F, + GL_NORMAL_ARRAY_COUNT = 0x8080, + GL_COLOR_ARRAY_SIZE = 0x8081, + GL_COLOR_ARRAY_TYPE = 0x8082, + GL_COLOR_ARRAY_STRIDE = 0x8083, + GL_COLOR_ARRAY_COUNT = 0x8084, + GL_INDEX_ARRAY_TYPE = 0x8085, + GL_INDEX_ARRAY_STRIDE = 0x8086, + GL_INDEX_ARRAY_COUNT = 0x8087, + GL_TEXTURE_COORD_ARRAY_SIZE = 0x8088, + GL_TEXTURE_COORD_ARRAY_TYPE = 0x8089, + GL_TEXTURE_COORD_ARRAY_STRIDE = 0x808A, + GL_TEXTURE_COORD_ARRAY_COUNT = 0x808B, + GL_EDGE_FLAG_ARRAY_STRIDE = 0x808C, + GL_EDGE_FLAG_ARRAY_COUNT = 0x808D, + GL_VERTEX_ARRAY_POINTER = 0x808E, + GL_NORMAL_ARRAY_POINTER = 0x808F, + GL_COLOR_ARRAY_POINTER = 0x8090, + GL_INDEX_ARRAY_POINTER = 0x8091, + GL_TEXTURE_COORD_ARRAY_POINTER = 0x8092, + GL_EDGE_FLAG_ARRAY_POINTER = 0x8093, + GL_V2F = 0x2A20, + GL_V3F = 0x2A21, + GL_C4UB_V2F = 0x2A22, + GL_C4UB_V3F = 0x2A23, + GL_C3F_V3F = 0x2A24, + GL_N3F_V3F = 0x2A25, + GL_C4F_N3F_V3F = 0x2A26, + GL_T2F_V3F = 0x2A27, + GL_T4F_V4F = 0x2A28, + GL_T2F_C4UB_V3F = 0x2A29, + GL_T2F_C3F_V3F = 0x2A2A, + GL_T2F_N3F_V3F = 0x2A2B, + GL_T2F_C4F_N3F_V3F = 0x2A2C, + GL_T4F_C4F_N3F_V4F = 0x2A2D, + + /* Matrix Mode */ + GL_MATRIX_MODE = 0x0BA0, + GL_MODELVIEW = 0x1700, + GL_PROJECTION = 0x1701, + GL_TEXTURE = 0x1702, + + /* Points */ + GL_POINT_SMOOTH = 0x0B10, + GL_POINT_SIZE = 0x0B11, + GL_POINT_SIZE_GRANULARITY = 0x0B13, + GL_POINT_SIZE_RANGE = 0x0B12, + + /* Lines */ + GL_LINE_SMOOTH = 0x0B20, + GL_LINE_STIPPLE = 0x0B24, + GL_LINE_STIPPLE_PATTERN = 0x0B25, + GL_LINE_STIPPLE_REPEAT = 0x0B26, + GL_LINE_WIDTH = 0x0B21, + GL_LINE_WIDTH_GRANULARITY = 0x0B23, + GL_LINE_WIDTH_RANGE = 0x0B22, + + /* Polygons */ + GL_POINT = 0x1B00, + GL_LINE = 0x1B01, + GL_FILL = 0x1B02, + GL_CCW = 0x0901, + GL_CW = 0x0900, + GL_FRONT = 0x0404, + GL_BACK = 0x0405, + GL_CULL_FACE = 0x0B44, + GL_CULL_FACE_MODE = 0x0B45, + GL_POLYGON_SMOOTH = 0x0B41, + GL_POLYGON_STIPPLE = 0x0B42, + GL_FRONT_FACE = 0x0B46, + GL_POLYGON_MODE = 0x0B40, + GL_POLYGON_OFFSET_FACTOR = 0x3038, + GL_POLYGON_OFFSET_UNITS = 0x2A00, + GL_POLYGON_OFFSET_POINT = 0x2A01, + GL_POLYGON_OFFSET_LINE = 0x2A02, + GL_POLYGON_OFFSET_FILL = 0x8037, + + /* Display Lists */ + GL_COMPILE = 0x1300, + GL_COMPILE_AND_EXECUTE = 0x1301, + GL_LIST_BASE = 0x0B32, + GL_LIST_INDEX = 0x0B33, + GL_LIST_MODE = 0x0B30, + + /* Depth buffer */ + GL_NEVER = 0x0200, + GL_LESS = 0x0201, + GL_GEQUAL = 0x0206, + GL_LEQUAL = 0x0203, + GL_GREATER = 0x0204, + GL_NOTEQUAL = 0x0205, + GL_EQUAL = 0x0202, + GL_ALWAYS = 0x0207, + GL_DEPTH_TEST = 0x0B71, + GL_DEPTH_BITS = 0x0D56, + GL_DEPTH_CLEAR_VALUE = 0x0B73, + GL_DEPTH_FUNC = 0x0B74, + GL_DEPTH_RANGE = 0x0B70, + GL_DEPTH_WRITEMASK = 0x0B72, + GL_DEPTH_COMPONENT = 0x1902, + + /* Lighting */ + GL_LIGHTING = 0x0B50, + GL_LIGHT0 = 0x4000, + GL_LIGHT1 = 0x4001, + GL_LIGHT2 = 0x4002, + GL_LIGHT3 = 0x4003, + GL_LIGHT4 = 0x4004, + GL_LIGHT5 = 0x4005, + GL_LIGHT6 = 0x4006, + GL_LIGHT7 = 0x4007, + GL_SPOT_EXPONENT = 0x1205, + GL_SPOT_CUTOFF = 0x1206, + GL_CONSTANT_ATTENUATION = 0x1207, + GL_LINEAR_ATTENUATION = 0x1208, + GL_QUADRATIC_ATTENUATION = 0x1209, + GL_AMBIENT = 0x1200, + GL_DIFFUSE = 0x1201, + GL_SPECULAR = 0x1202, + GL_SHININESS = 0x1601, + GL_EMISSION = 0x1600, + GL_POSITION = 0x1203, + GL_SPOT_DIRECTION = 0x1204, + GL_AMBIENT_AND_DIFFUSE = 0x1602, + GL_COLOR_INDEXES = 0x1603, + GL_LIGHT_MODEL_TWO_SIDE = 0x0B52, + GL_LIGHT_MODEL_LOCAL_VIEWER = 0x0B51, + GL_LIGHT_MODEL_AMBIENT = 0x0B53, + GL_FRONT_AND_BACK = 0x0408, + GL_SHADE_MODEL = 0x0B54, + GL_FLAT = 0x1D00, + GL_SMOOTH = 0x1D01, + GL_COLOR_MATERIAL = 0x0B57, + GL_COLOR_MATERIAL_FACE = 0x0B55, + GL_COLOR_MATERIAL_PARAMETER = 0x0B56, + GL_NORMALIZE = 0x0BA1, + + /* User clipping planes */ + GL_CLIP_PLANE0 = 0x3000, + GL_CLIP_PLANE1 = 0x3001, + GL_CLIP_PLANE2 = 0x3002, + GL_CLIP_PLANE3 = 0x3003, + GL_CLIP_PLANE4 = 0x3004, + GL_CLIP_PLANE5 = 0x3005, + + /* Accumulation buffer */ + GL_ACCUM_RED_BITS = 0x0D58, + GL_ACCUM_GREEN_BITS = 0x0D59, + GL_ACCUM_BLUE_BITS = 0x0D5A, + GL_ACCUM_ALPHA_BITS = 0x0D5B, + GL_ACCUM_CLEAR_VALUE = 0x0B80, + GL_ACCUM = 0x0100, + GL_ADD = 0x0104, + GL_LOAD = 0x0101, + GL_MULT = 0x0103, + GL_RETURN = 0x0102, + + /* Alpha testing */ + GL_ALPHA_TEST = 0x0BC0, + GL_ALPHA_TEST_REF = 0x0BC2, + GL_ALPHA_TEST_FUNC = 0x0BC1, + + /* Blending */ + GL_BLEND = 0x0BE2, + GL_BLEND_SRC = 0x0BE1, + GL_BLEND_DST = 0x0BE0, + GL_ZERO = 0, + GL_ONE = 1, + GL_SRC_COLOR = 0x0300, + GL_ONE_MINUS_SRC_COLOR = 0x0301, + GL_DST_COLOR = 0x0306, + GL_ONE_MINUS_DST_COLOR = 0x0307, + GL_SRC_ALPHA = 0x0302, + GL_ONE_MINUS_SRC_ALPHA = 0x0303, + GL_DST_ALPHA = 0x0304, + GL_ONE_MINUS_DST_ALPHA = 0x0305, + GL_SRC_ALPHA_SATURATE = 0x0308, + GL_CONSTANT_COLOR = 0x8001, + GL_ONE_MINUS_CONSTANT_COLOR = 0x8002, + GL_CONSTANT_ALPHA = 0x8003, + GL_ONE_MINUS_CONSTANT_ALPHA = 0x8004, + + /* Render Mode */ + GL_FEEDBACK = 0x1C01, + GL_RENDER = 0x1C00, + GL_SELECT = 0x1C02, + + /* Feedback */ + GL_2D = 0x0600, + GL_3D = 0x0601, + GL_3D_COLOR = 0x0602, + GL_3D_COLOR_TEXTURE = 0x0603, + GL_4D_COLOR_TEXTURE = 0x0604, + GL_POINT_TOKEN = 0x0701, + GL_LINE_TOKEN = 0x0702, + GL_LINE_RESET_TOKEN = 0x0707, + GL_POLYGON_TOKEN = 0x0703, + GL_BITMAP_TOKEN = 0x0704, + GL_DRAW_PIXEL_TOKEN = 0x0705, + GL_COPY_PIXEL_TOKEN = 0x0706, + GL_PASS_THROUGH_TOKEN = 0x0700, + + /* Fog */ + GL_FOG = 0x0B60, + GL_FOG_MODE = 0x0B65, + GL_FOG_DENSITY = 0x0B62, + GL_FOG_COLOR = 0x0B66, + GL_FOG_INDEX = 0x0B61, + GL_FOG_START = 0x0B63, + GL_FOG_END = 0x0B64, + GL_LINEAR = 0x2601, + GL_EXP = 0x0800, + GL_EXP2 = 0x0801, + + /* Logic Ops */ + GL_LOGIC_OP = 0x0BF1, + GL_LOGIC_OP_MODE = 0x0BF0, + GL_CLEAR = 0x1500, + GL_SET = 0x150F, + GL_COPY = 0x1503, + GL_COPY_INVERTED = 0x150C, + GL_NOOP = 0x1505, + GL_INVERT = 0x150A, + GL_AND = 0x1501, + GL_NAND = 0x150E, + GL_OR = 0x1507, + GL_NOR = 0x1508, + GL_XOR = 0x1506, + GL_EQUIV = 0x1509, + GL_AND_REVERSE = 0x1502, + GL_AND_INVERTED = 0x1504, + GL_OR_REVERSE = 0x150B, + GL_OR_INVERTED = 0x150D, + + /* Stencil */ + GL_STENCIL_TEST = 0x0B90, + GL_STENCIL_WRITEMASK = 0x0B98, + GL_STENCIL_BITS = 0x0D57, + GL_STENCIL_FUNC = 0x0B92, + GL_STENCIL_VALUE_MASK = 0x0B93, + GL_STENCIL_REF = 0x0B97, + GL_STENCIL_FAIL = 0x0B94, + GL_STENCIL_PASS_DEPTH_PASS = 0x0B96, + GL_STENCIL_PASS_DEPTH_FAIL = 0x0B95, + GL_STENCIL_CLEAR_VALUE = 0x0B91, + GL_STENCIL_INDEX = 0x1901, + GL_KEEP = 0x1E00, + GL_REPLACE = 0x1E01, + GL_INCR = 0x1E02, + GL_DECR = 0x1E03, + + /* Buffers, Pixel Drawing/Reading */ + GL_NONE = 0, + GL_LEFT = 0x0406, + GL_RIGHT = 0x0407, + /*GL_FRONT = 0x0404, */ + /*GL_BACK = 0x0405, */ + /*GL_FRONT_AND_BACK = 0x0408, */ + GL_FRONT_LEFT = 0x0400, + GL_FRONT_RIGHT = 0x0401, + GL_BACK_LEFT = 0x0402, + GL_BACK_RIGHT = 0x0403, + GL_AUX0 = 0x0409, + GL_AUX1 = 0x040A, + GL_AUX2 = 0x040B, + GL_AUX3 = 0x040C, + GL_COLOR_INDEX = 0x1900, + GL_RED = 0x1903, + GL_GREEN = 0x1904, + GL_BLUE = 0x1905, + GL_ALPHA = 0x1906, + GL_LUMINANCE = 0x1909, + GL_LUMINANCE_ALPHA = 0x190A, + GL_ALPHA_BITS = 0x0D55, + GL_RED_BITS = 0x0D52, + GL_GREEN_BITS = 0x0D53, + GL_BLUE_BITS = 0x0D54, + GL_INDEX_BITS = 0x0D51, + GL_SUBPIXEL_BITS = 0x0D50, + GL_AUX_BUFFERS = 0x0C00, + GL_READ_BUFFER = 0x0C02, + GL_DRAW_BUFFER = 0x0C01, + GL_DOUBLEBUFFER = 0x0C32, + GL_STEREO = 0x0C33, + GL_BITMAP = 0x1A00, + GL_COLOR = 0x1800, + GL_DEPTH = 0x1801, + GL_STENCIL = 0x1802, + GL_DITHER = 0x0BD0, + GL_RGB = 0x1907, + GL_RGBA = 0x1908, + + /* Implementation limits */ + GL_MAX_LIST_NESTING = 0x0B31, + GL_MAX_ATTRIB_STACK_DEPTH = 0x0D35, + GL_MAX_MODELVIEW_STACK_DEPTH = 0x0D36, + GL_MAX_NAME_STACK_DEPTH = 0x0D37, + GL_MAX_PROJECTION_STACK_DEPTH = 0x0D38, + GL_MAX_TEXTURE_STACK_DEPTH = 0x0D39, + GL_MAX_EVAL_ORDER = 0x0D30, + GL_MAX_LIGHTS = 0x0D31, + GL_MAX_CLIP_PLANES = 0x0D32, + GL_MAX_TEXTURE_SIZE = 0x0D33, + GL_MAX_PIXEL_MAP_TABLE = 0x0D34, + GL_MAX_VIEWPORT_DIMS = 0x0D3A, + GL_MAX_CLIENT_ATTRIB_STACK_DEPTH= 0x0D3B, + + /* Gets */ + GL_ATTRIB_STACK_DEPTH = 0x0BB0, + GL_COLOR_CLEAR_VALUE = 0x0C22, + GL_COLOR_WRITEMASK = 0x0C23, + GL_CURRENT_INDEX = 0x0B01, + GL_CURRENT_COLOR = 0x0B00, + GL_CURRENT_NORMAL = 0x0B02, + GL_CURRENT_RASTER_COLOR = 0x0B04, + GL_CURRENT_RASTER_DISTANCE = 0x0B09, + GL_CURRENT_RASTER_INDEX = 0x0B05, + GL_CURRENT_RASTER_POSITION = 0x0B07, + GL_CURRENT_RASTER_TEXTURE_COORDS = 0x0B06, + GL_CURRENT_RASTER_POSITION_VALID = 0x0B08, + GL_CURRENT_TEXTURE_COORDS = 0x0B03, + GL_INDEX_CLEAR_VALUE = 0x0C20, + GL_INDEX_MODE = 0x0C30, + GL_INDEX_WRITEMASK = 0x0C21, + GL_MODELVIEW_MATRIX = 0x0BA6, + GL_MODELVIEW_STACK_DEPTH = 0x0BA3, + GL_NAME_STACK_DEPTH = 0x0D70, + GL_PROJECTION_MATRIX = 0x0BA7, + GL_PROJECTION_STACK_DEPTH = 0x0BA4, + GL_RENDER_MODE = 0x0C40, + GL_RGBA_MODE = 0x0C31, + GL_TEXTURE_MATRIX = 0x0BA8, + GL_TEXTURE_STACK_DEPTH = 0x0BA5, + GL_VIEWPORT = 0x0BA2, + + + /* Evaluators */ + GL_AUTO_NORMAL = 0x0D80, + GL_MAP1_COLOR_4 = 0x0D90, + GL_MAP1_GRID_DOMAIN = 0x0DD0, + GL_MAP1_GRID_SEGMENTS = 0x0DD1, + GL_MAP1_INDEX = 0x0D91, + GL_MAP1_NORMAL = 0x0D92, + GL_MAP1_TEXTURE_COORD_1 = 0x0D93, + GL_MAP1_TEXTURE_COORD_2 = 0x0D94, + GL_MAP1_TEXTURE_COORD_3 = 0x0D95, + GL_MAP1_TEXTURE_COORD_4 = 0x0D96, + GL_MAP1_VERTEX_3 = 0x0D97, + GL_MAP1_VERTEX_4 = 0x0D98, + GL_MAP2_COLOR_4 = 0x0DB0, + GL_MAP2_GRID_DOMAIN = 0x0DD2, + GL_MAP2_GRID_SEGMENTS = 0x0DD3, + GL_MAP2_INDEX = 0x0DB1, + GL_MAP2_NORMAL = 0x0DB2, + GL_MAP2_TEXTURE_COORD_1 = 0x0DB3, + GL_MAP2_TEXTURE_COORD_2 = 0x0DB4, + GL_MAP2_TEXTURE_COORD_3 = 0x0DB5, + GL_MAP2_TEXTURE_COORD_4 = 0x0DB6, + GL_MAP2_VERTEX_3 = 0x0DB7, + GL_MAP2_VERTEX_4 = 0x0DB8, + GL_COEFF = 0x0A00, + GL_DOMAIN = 0x0A02, + GL_ORDER = 0x0A01, + + /* Hints */ + GL_FOG_HINT = 0x0C54, + GL_LINE_SMOOTH_HINT = 0x0C52, + GL_PERSPECTIVE_CORRECTION_HINT = 0x0C50, + GL_POINT_SMOOTH_HINT = 0x0C51, + GL_POLYGON_SMOOTH_HINT = 0x0C53, + GL_DONT_CARE = 0x1100, + GL_FASTEST = 0x1101, + GL_NICEST = 0x1102, + + /* Scissor box */ + GL_SCISSOR_TEST = 0x0C11, + GL_SCISSOR_BOX = 0x0C10, + + /* Pixel Mode / Transfer */ + GL_MAP_COLOR = 0x0D10, + GL_MAP_STENCIL = 0x0D11, + GL_INDEX_SHIFT = 0x0D12, + GL_INDEX_OFFSET = 0x0D13, + GL_RED_SCALE = 0x0D14, + GL_RED_BIAS = 0x0D15, + GL_GREEN_SCALE = 0x0D18, + GL_GREEN_BIAS = 0x0D19, + GL_BLUE_SCALE = 0x0D1A, + GL_BLUE_BIAS = 0x0D1B, + GL_ALPHA_SCALE = 0x0D1C, + GL_ALPHA_BIAS = 0x0D1D, + GL_DEPTH_SCALE = 0x0D1E, + GL_DEPTH_BIAS = 0x0D1F, + GL_PIXEL_MAP_S_TO_S_SIZE = 0x0CB1, + GL_PIXEL_MAP_I_TO_I_SIZE = 0x0CB0, + GL_PIXEL_MAP_I_TO_R_SIZE = 0x0CB2, + GL_PIXEL_MAP_I_TO_G_SIZE = 0x0CB3, + GL_PIXEL_MAP_I_TO_B_SIZE = 0x0CB4, + GL_PIXEL_MAP_I_TO_A_SIZE = 0x0CB5, + GL_PIXEL_MAP_R_TO_R_SIZE = 0x0CB6, + GL_PIXEL_MAP_G_TO_G_SIZE = 0x0CB7, + GL_PIXEL_MAP_B_TO_B_SIZE = 0x0CB8, + GL_PIXEL_MAP_A_TO_A_SIZE = 0x0CB9, + GL_PIXEL_MAP_S_TO_S = 0x0C71, + GL_PIXEL_MAP_I_TO_I = 0x0C70, + GL_PIXEL_MAP_I_TO_R = 0x0C72, + GL_PIXEL_MAP_I_TO_G = 0x0C73, + GL_PIXEL_MAP_I_TO_B = 0x0C74, + GL_PIXEL_MAP_I_TO_A = 0x0C75, + GL_PIXEL_MAP_R_TO_R = 0x0C76, + GL_PIXEL_MAP_G_TO_G = 0x0C77, + GL_PIXEL_MAP_B_TO_B = 0x0C78, + GL_PIXEL_MAP_A_TO_A = 0x0C79, + GL_PACK_ALIGNMENT = 0x0D05, + GL_PACK_LSB_FIRST = 0x0D01, + GL_PACK_ROW_LENGTH = 0x0D02, + GL_PACK_SKIP_PIXELS = 0x0D04, + GL_PACK_SKIP_ROWS = 0x0D03, + GL_PACK_SWAP_BYTES = 0x0D00, + GL_UNPACK_ALIGNMENT = 0x0CF5, + GL_UNPACK_LSB_FIRST = 0x0CF1, + GL_UNPACK_ROW_LENGTH = 0x0CF2, + GL_UNPACK_SKIP_PIXELS = 0x0CF4, + GL_UNPACK_SKIP_ROWS = 0x0CF3, + GL_UNPACK_SWAP_BYTES = 0x0CF0, + GL_ZOOM_X = 0x0D16, + GL_ZOOM_Y = 0x0D17, + + /* Texture mapping */ + GL_TEXTURE_ENV = 0x2300, + GL_TEXTURE_ENV_MODE = 0x2200, + GL_TEXTURE_1D = 0x0DE0, + GL_TEXTURE_2D = 0x0DE1, + GL_TEXTURE_WRAP_S = 0x2802, + GL_TEXTURE_WRAP_T = 0x2803, + GL_TEXTURE_MAG_FILTER = 0x2800, + GL_TEXTURE_MIN_FILTER = 0x2801, + GL_TEXTURE_ENV_COLOR = 0x2201, + GL_TEXTURE_GEN_S = 0x0C60, + GL_TEXTURE_GEN_T = 0x0C61, + GL_TEXTURE_GEN_MODE = 0x2500, + GL_TEXTURE_BORDER_COLOR = 0x1004, + GL_TEXTURE_WIDTH = 0x1000, + GL_TEXTURE_HEIGHT = 0x1001, + GL_TEXTURE_BORDER = 0x1005, + GL_TEXTURE_COMPONENTS = 0x1003, + GL_NEAREST_MIPMAP_NEAREST = 0x2700, + GL_NEAREST_MIPMAP_LINEAR = 0x2702, + GL_LINEAR_MIPMAP_NEAREST = 0x2701, + GL_LINEAR_MIPMAP_LINEAR = 0x2703, + GL_OBJECT_LINEAR = 0x2401, + GL_OBJECT_PLANE = 0x2501, + GL_EYE_LINEAR = 0x2400, + GL_EYE_PLANE = 0x2502, + GL_SPHERE_MAP = 0x2402, + GL_DECAL = 0x2101, + GL_MODULATE = 0x2100, + GL_NEAREST = 0x2600, + GL_REPEAT = 0x2901, + GL_CLAMP = 0x2900, + GL_S = 0x2000, + GL_T = 0x2001, + GL_R = 0x2002, + GL_Q = 0x2003, + GL_TEXTURE_GEN_R = 0x0C62, + GL_TEXTURE_GEN_Q = 0x0C63, + + GL_PROXY_TEXTURE_1D = 0x8063, + GL_PROXY_TEXTURE_2D = 0x8064, + GL_TEXTURE_PRIORITY = 0x8066, + GL_TEXTURE_RESIDENT = 0x8067, + GL_TEXTURE_1D_BINDING = 0x8068, + GL_TEXTURE_2D_BINDING = 0x8069, + + /* Internal texture formats */ + GL_ALPHA4 = 0x803B, + GL_ALPHA8 = 0x803C, + GL_ALPHA12 = 0x803D, + GL_ALPHA16 = 0x803E, + GL_LUMINANCE4 = 0x803F, + GL_LUMINANCE8 = 0x8040, + GL_LUMINANCE12 = 0x8041, + GL_LUMINANCE16 = 0x8042, + GL_LUMINANCE4_ALPHA4 = 0x8043, + GL_LUMINANCE6_ALPHA2 = 0x8044, + GL_LUMINANCE8_ALPHA8 = 0x8045, + GL_LUMINANCE12_ALPHA4 = 0x8046, + GL_LUMINANCE12_ALPHA12 = 0x8047, + GL_LUMINANCE16_ALPHA16 = 0x8048, + GL_INTENSITY = 0x8049, + GL_INTENSITY4 = 0x804A, + GL_INTENSITY8 = 0x804B, + GL_INTENSITY12 = 0x804C, + GL_INTENSITY16 = 0x804D, + GL_R3_G3_B2 = 0x2A10, + GL_RGB4 = 0x804F, + GL_RGB5 = 0x8050, + GL_RGB8 = 0x8051, + GL_RGB10 = 0x8052, + GL_RGB12 = 0x8053, + GL_RGB16 = 0x8054, + GL_RGBA2 = 0x8055, + GL_RGBA4 = 0x8056, + GL_RGB5_A1 = 0x8057, + GL_RGBA8 = 0x8058, + GL_RGB10_A2 = 0x8059, + GL_RGBA12 = 0x805A, + GL_RGBA16 = 0x805B, + + /* Utility */ + GL_VENDOR = 0x1F00, + GL_RENDERER = 0x1F01, + GL_VERSION = 0x1F02, + GL_EXTENSIONS = 0x1F03, + + /* Errors */ + GL_INVALID_VALUE = 0x0501, + GL_INVALID_ENUM = 0x0500, + GL_INVALID_OPERATION = 0x0502, + GL_STACK_OVERFLOW = 0x0503, + GL_STACK_UNDERFLOW = 0x0504, + GL_OUT_OF_MEMORY = 0x0505, + + /* + * 1.0 Extensions + */ + /* GL_EXT_blend_minmax and GL_EXT_blend_color */ + GL_CONSTANT_COLOR_EXT = 0x8001, + GL_ONE_MINUS_CONSTANT_COLOR_EXT = 0x8002, + GL_CONSTANT_ALPHA_EXT = 0x8003, + GL_ONE_MINUS_CONSTANT_ALPHA_EXT = 0x8004, + GL_BLEND_EQUATION_EXT = 0x8009, + GL_MIN_EXT = 0x8007, + GL_MAX_EXT = 0x8008, + GL_FUNC_ADD_EXT = 0x8006, + GL_FUNC_SUBTRACT_EXT = 0x800A, + GL_FUNC_REVERSE_SUBTRACT_EXT = 0x800B, + GL_BLEND_COLOR_EXT = 0x8005, + + /* GL_EXT_polygon_offset */ + GL_POLYGON_OFFSET_EXT = 0x8037, + GL_POLYGON_OFFSET_FACTOR_EXT = 0x8038, + GL_POLYGON_OFFSET_BIAS_EXT = 0x8039, + + /* GL_EXT_vertex_array */ + GL_VERTEX_ARRAY_EXT = 0x8074, + GL_NORMAL_ARRAY_EXT = 0x8075, + GL_COLOR_ARRAY_EXT = 0x8076, + GL_INDEX_ARRAY_EXT = 0x8077, + GL_TEXTURE_COORD_ARRAY_EXT = 0x8078, + GL_EDGE_FLAG_ARRAY_EXT = 0x8079, + GL_VERTEX_ARRAY_SIZE_EXT = 0x807A, + GL_VERTEX_ARRAY_TYPE_EXT = 0x807B, + GL_VERTEX_ARRAY_STRIDE_EXT = 0x807C, + GL_VERTEX_ARRAY_COUNT_EXT = 0x807D, + GL_NORMAL_ARRAY_TYPE_EXT = 0x807E, + GL_NORMAL_ARRAY_STRIDE_EXT = 0x807F, + GL_NORMAL_ARRAY_COUNT_EXT = 0x8080, + GL_COLOR_ARRAY_SIZE_EXT = 0x8081, + GL_COLOR_ARRAY_TYPE_EXT = 0x8082, + GL_COLOR_ARRAY_STRIDE_EXT = 0x8083, + GL_COLOR_ARRAY_COUNT_EXT = 0x8084, + GL_INDEX_ARRAY_TYPE_EXT = 0x8085, + GL_INDEX_ARRAY_STRIDE_EXT = 0x8086, + GL_INDEX_ARRAY_COUNT_EXT = 0x8087, + GL_TEXTURE_COORD_ARRAY_SIZE_EXT = 0x8088, + GL_TEXTURE_COORD_ARRAY_TYPE_EXT = 0x8089, + GL_TEXTURE_COORD_ARRAY_STRIDE_EXT= 0x808A, + GL_TEXTURE_COORD_ARRAY_COUNT_EXT= 0x808B, + GL_EDGE_FLAG_ARRAY_STRIDE_EXT = 0x808C, + GL_EDGE_FLAG_ARRAY_COUNT_EXT = 0x808D, + GL_VERTEX_ARRAY_POINTER_EXT = 0x808E, + GL_NORMAL_ARRAY_POINTER_EXT = 0x808F, + GL_COLOR_ARRAY_POINTER_EXT = 0x8090, + GL_INDEX_ARRAY_POINTER_EXT = 0x8091, + GL_TEXTURE_COORD_ARRAY_POINTER_EXT= 0x8092, + GL_EDGE_FLAG_ARRAY_POINTER_EXT = 0x8093 + +}; + +enum { + GL_CURRENT_BIT = 0x00000001, + GL_POINT_BIT = 0x00000002, + GL_LINE_BIT = 0x00000004, + GL_POLYGON_BIT = 0x00000008, + GL_POLYGON_STIPPLE_BIT = 0x00000010, + GL_PIXEL_MODE_BIT = 0x00000020, + GL_LIGHTING_BIT = 0x00000040, + GL_FOG_BIT = 0x00000080, + GL_DEPTH_BUFFER_BIT = 0x00000100, + GL_ACCUM_BUFFER_BIT = 0x00000200, + GL_STENCIL_BUFFER_BIT = 0x00000400, + GL_VIEWPORT_BIT = 0x00000800, + GL_TRANSFORM_BIT = 0x00001000, + GL_ENABLE_BIT = 0x00002000, + GL_COLOR_BUFFER_BIT = 0x00004000, + GL_HINT_BIT = 0x00008000, + GL_EVAL_BIT = 0x00010000, + GL_LIST_BIT = 0x00020000, + GL_TEXTURE_BIT = 0x00040000, + GL_SCISSOR_BIT = 0x00080000, + GL_ALL_ATTRIB_BITS = 0x000fffff +}; + +/* some types */ + +typedef int GLenum; +typedef void GLvoid; +typedef unsigned char GLboolean; +typedef signed char GLbyte; /* 1-byte signed */ +typedef short GLshort; /* 2-byte signed */ +typedef int GLint; /* 4-byte signed */ +typedef unsigned char GLubyte; /* 1-byte unsigned */ +typedef unsigned short GLushort; /* 2-byte unsigned */ +typedef unsigned int GLuint; /* 4-byte unsigned */ +typedef float GLfloat; /* single precision float */ +typedef double GLdouble; /* double precision float */ +typedef int GLsizei; + +/* functions */ + +void glEnable(int code); +void glDisable(int code); + +void glShadeModel(int mode); +void glCullFace(int mode); +void glPolygonMode(int face,int mode); + +void glBegin(int type); +void glEnd(void); + +#define PROTO_GL1(name) \ +void gl ## name ## 1f(float); \ +void gl ## name ## 1d(double); \ +void gl ## name ## 1fv(float *); \ +void gl ## name ## 1dv(double *); + +#define PROTO_GL2(name) \ +void gl ## name ## 2f(float ,float); \ +void gl ## name ## 2d(double ,double); \ +void gl ## name ## 2fv(float *); \ +void gl ## name ## 2dv(double *); + +#define PROTO_GL3(name) \ +void gl ## name ## 3f(float ,float ,float); \ +void gl ## name ## 3d(double ,double ,double); \ +void gl ## name ## 3fv(float *); \ +void gl ## name ## 3dv(double *); + +#define PROTO_GL4(name) \ +void gl ## name ## 4f(float ,float ,float, float ); \ +void gl ## name ## 4d(double ,double ,double, double ); \ +void gl ## name ## 4fv(float *); \ +void gl ## name ## 4dv(double *); + +PROTO_GL2(Vertex) +PROTO_GL3(Vertex) +PROTO_GL4(Vertex) + +PROTO_GL3(Color) +PROTO_GL4(Color) + +PROTO_GL3(Normal) + +PROTO_GL1(TexCoord) +PROTO_GL2(TexCoord) +PROTO_GL3(TexCoord) +PROTO_GL4(TexCoord) + +void glEdgeFlag(int flag); + +/* matrix */ +void glMatrixMode(int mode); +void glLoadMatrixf(const float *m); +void glLoadIdentity(void); +void glMultMatrixf(const float *m); +void glPushMatrix(void); +void glPopMatrix(void); +void glRotatef(float angle,float x,float y,float z); +void glTranslatef(float x,float y,float z); +void glScalef(float x,float y,float z); + +void glViewport(int x,int y,int width,int height); +void glFrustum(double left,double right,double bottom,double top, + double near,double far); + +/* lists */ +unsigned int glGenLists(int range); +int glIsList(unsigned int list); +void glNewList(unsigned int list,int mode); +void glEndList(void); +void glCallList(unsigned int list); + +/* clear */ +void glClear(int mask); +void glClearColor(float r,float g,float b,float a); +void glClearDepth(double depth); + +/* selection */ +int glRenderMode(int mode); +void glSelectBuffer(int size,unsigned int *buf); + +void glInitNames(void); +void glPushName(unsigned int name); +void glPopName(void); +void glLoadName(unsigned int name); + +/* textures */ +void glGenTextures(int n, unsigned int *textures); +void glDeleteTextures(int n, const unsigned int *textures); +void glBindTexture(int target,int texture); +void glTexImage2D( int target, int level, int components, + int width, int height, int border, + int format, int type, void *pixels); +void glTexEnvi(int target,int pname,int param); +void glTexParameteri(int target,int pname,int param); +void glPixelStorei(int pname,int param); + +/* lighting */ + +void glMaterialfv(int mode,int type,float *v); +void glMaterialf(int mode,int type,float v); +void glColorMaterial(int mode,int type); + +void glLightfv(int light,int type,float *v); +void glLightf(int light,int type,float v); +void glLightModeli(int pname,int param); +void glLightModelfv(int pname,float *param); + +/* misc */ + +void glFlush(void); +void glHint(int target,int mode); +void glGetIntegerv(int pname,int *params); +void glGetFloatv(int pname, float *v); +void glFrontFace(int mode); + +/* opengl 1.2 arrays */ +void glEnableClientState(GLenum array); +void glDisableClientState(GLenum array); +void glArrayElement(GLint i); +void glVertexPointer(GLint size, GLenum type, GLsizei stride, + const GLvoid *pointer); +void glColorPointer(GLint size, GLenum type, GLsizei stride, + const GLvoid *pointer); +void glNormalPointer(GLenum type, GLsizei stride, + const GLvoid *pointer); +void glTexCoordPointer(GLint size, GLenum type, GLsizei stride, + const GLvoid *pointer); + +/* opengl 1.2 polygon offset */ +void glPolygonOffset(GLfloat factor, GLfloat units); + +/* not implemented, just added to compile */ + /* +inline void glPointSize(float) {} +inline void glLineWidth(float) {} +inline void glDeleteLists(int, int) {} +inline void glDepthFunc(int) {} +inline void glBlendFunc(int, int) {} +inline void glTexEnvf(int, int, int) {} +inline void glOrtho(float,float,float,float,float,float){} +inline void glVertex2i(int,int) {} +inline void glDepthMask(int) {} +inline void glFogi(int, int) {} +inline void glFogfv(int, const float*) {} +inline void glFogf(int, float) {} +inline void glRasterPos2f(float, float) {} +inline void glPolygonStipple(void*) {} +inline void glTexParameterf(int, int, int) {}; + */ +/* non compatible functions */ + +void glDebug(int mode); + +void glInit(void *zbuffer); +void glClose(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/apps/tinygl/src/TinyGL/include/GL/glx.h b/apps/tinygl/src/TinyGL/include/GL/glx.h new file mode 100644 index 0000000..67fd68a --- /dev/null +++ b/apps/tinygl/src/TinyGL/include/GL/glx.h @@ -0,0 +1,144 @@ +#ifndef GLX_H +#define GLX_H + +#include +#include +#include + + +/* the following comes from Mesa */ + +#ifdef __cplusplus +extern "C" { +#endif + + +#define GLX_VERSION_1_1 1 + + +/* + * Tokens for glXChooseVisual and glXGetConfig: + */ +enum _GLX_CONFIGS { + GLX_USE_GL = 1, + GLX_BUFFER_SIZE = 2, + GLX_LEVEL = 3, + GLX_RGBA = 4, + GLX_DOUBLEBUFFER = 5, + GLX_STEREO = 6, + GLX_AUX_BUFFERS = 7, + GLX_RED_SIZE = 8, + GLX_GREEN_SIZE = 9, + GLX_BLUE_SIZE = 10, + GLX_ALPHA_SIZE = 11, + GLX_DEPTH_SIZE = 12, + GLX_STENCIL_SIZE = 13, + GLX_ACCUM_RED_SIZE = 14, + GLX_ACCUM_GREEN_SIZE = 15, + GLX_ACCUM_BLUE_SIZE = 16, + GLX_ACCUM_ALPHA_SIZE = 17, + + /* GLX_EXT_visual_info extension */ + GLX_X_VISUAL_TYPE_EXT = 0x22, + GLX_TRANSPARENT_TYPE_EXT = 0x23, + GLX_TRANSPARENT_INDEX_VALUE_EXT = 0x24, + GLX_TRANSPARENT_RED_VALUE_EXT = 0x25, + GLX_TRANSPARENT_GREEN_VALUE_EXT = 0x26, + GLX_TRANSPARENT_BLUE_VALUE_EXT = 0x27, + GLX_TRANSPARENT_ALPHA_VALUE_EXT = 0x28 +}; + + +/* + * Error codes returned by glXGetConfig: + */ +#define GLX_BAD_SCREEN 1 +#define GLX_BAD_ATTRIBUTE 2 +#define GLX_NO_EXTENSION 3 +#define GLX_BAD_VISUAL 4 +#define GLX_BAD_CONTEXT 5 +#define GLX_BAD_VALUE 6 +#define GLX_BAD_ENUM 7 + + +/* + * GLX 1.1 and later: + */ +#define GLX_VENDOR 1 +#define GLX_VERSION 2 +#define GLX_EXTENSIONS 3 + + +/* + * GLX_visual_info extension + */ +#define GLX_TRUE_COLOR_EXT 0x8002 +#define GLX_DIRECT_COLOR_EXT 0x8003 +#define GLX_PSEUDO_COLOR_EXT 0x8004 +#define GLX_STATIC_COLOR_EXT 0x8005 +#define GLX_GRAY_SCALE_EXT 0x8006 +#define GLX_STATIC_GRAY_EXT 0x8007 +#define GLX_NONE_EXT 0x8000 +#define GLX_TRANSPARENT_RGB_EXT 0x8008 +#define GLX_TRANSPARENT_INDEX_EXT 0x8009 + + +typedef void *GLXContext; +typedef Pixmap GLXPixmap; +typedef Drawable GLXDrawable; +typedef XID GLXContextID; + + +extern XVisualInfo* glXChooseVisual( Display *dpy, int screen, + int *attribList ); + +extern GLXContext glXCreateContext( Display *dpy, XVisualInfo *vis, + GLXContext shareList, Bool direct ); + +extern void glXDestroyContext( Display *dpy, GLXContext ctx ); + +extern Bool glXMakeCurrent( Display *dpy, GLXDrawable drawable, + GLXContext ctx); + +extern void glXCopyContext( Display *dpy, GLXContext src, GLXContext dst, + GLuint mask ); + +extern void glXSwapBuffers( Display *dpy, GLXDrawable drawable ); + +extern GLXPixmap glXCreateGLXPixmap( Display *dpy, XVisualInfo *visual, + Pixmap pixmap ); + +extern void glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap ); + +extern Bool glXQueryExtension( Display *dpy, int *errorb, int *event ); + +extern Bool glXQueryVersion( Display *dpy, int *maj, int *min ); + +extern Bool glXIsDirect( Display *dpy, GLXContext ctx ); + +extern int glXGetConfig( Display *dpy, XVisualInfo *visual, + int attrib, int *value ); + +extern GLXContext glXGetCurrentContext( void ); + +extern GLXDrawable glXGetCurrentDrawable( void ); + +extern void glXWaitGL( void ); + +extern void glXWaitX( void ); + +extern void glXUseXFont( Font font, int first, int count, int list ); + + +/* GLX 1.1 and later */ +extern const char *glXQueryExtensionsString( Display *dpy, int screen ); + +extern const char *glXQueryServerString( Display *dpy, int screen, int name ); + +extern const char *glXGetClientString( Display *dpy, int name ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/apps/tinygl/src/TinyGL/include/GL/nglx.h b/apps/tinygl/src/TinyGL/include/GL/nglx.h new file mode 100644 index 0000000..d2f6114 --- /dev/null +++ b/apps/tinygl/src/TinyGL/include/GL/nglx.h @@ -0,0 +1,27 @@ +#ifndef NGLX_H +#define NGLX_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void *NGLXContext; +typedef GR_DRAW_ID NGLXDrawable; + +extern NGLXContext nglXCreateContext( NGLXContext shareList, int flags ); + +extern void nglXDestroyContext( NGLXContext ctx ); + +extern int nglXMakeCurrent( NGLXDrawable drawable, + NGLXContext ctx); + +extern void nglXSwapBuffers( NGLXDrawable drawable ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/apps/tinygl/src/TinyGL/include/GL/oscontext.h b/apps/tinygl/src/TinyGL/include/GL/oscontext.h new file mode 100644 index 0000000..a044f22 --- /dev/null +++ b/apps/tinygl/src/TinyGL/include/GL/oscontext.h @@ -0,0 +1,37 @@ +#ifndef _tgl_osbuffer_h_ +#define _tgl_osbuffer_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + void **zbs; + void **framebuffers; + int numbuffers; + int xsize, ysize; +} ostgl_context; + +ostgl_context * +ostgl_create_context(const int xsize, + const int ysize, + const int depth, + void **framebuffers, + const int numbuffers); +void +ostgl_delete_context(ostgl_context *context); + +void +ostgl_make_current(ostgl_context *context, const int index); + +void +ostgl_resize(ostgl_context * context, + const int xsize, + const int ysize, + void **framebuffers); + +#ifdef __cplusplus +} +#endif + +#endif /* _tgl_osbuffer_h_ */ diff --git a/apps/tinygl/src/TinyGL/include/GLView.h b/apps/tinygl/src/TinyGL/include/GLView.h new file mode 100644 index 0000000..6791e5a --- /dev/null +++ b/apps/tinygl/src/TinyGL/include/GLView.h @@ -0,0 +1,72 @@ +#ifndef _glview_h_ +#define _glview_h_ + +#define BGL_RGB 0 +#define BGL_INDEX 1 +#define BGL_SINGLE 0 +#define BGL_DOUBLE 2 +#define BGL_DIRECT 0 +#define BGL_INDIRECT 4 +#define BGL_ACCUM 8 +#define BGL_ALPHA 16 +#define BGL_DEPTH 32 +#define BGL_OVERLAY 64 +#define BGL_UNDERLAY 128 +#define BGL_STENCIL 512 + +#include +#include +#include +#include +#include +#include + +class BGLView : public BView { +public: + BGLView(BRect rect, char *name, + ulong resizingMode, ulong mode, + ulong options); + virtual ~BGLView(); + + void LockGL(); + void UnlockGL(); + void SwapBuffers(); +// BView *EmbeddedView(); +// status_t CopyPixelsOut(BPoint source, BBitmap *dest); +// status_t CopyPixelsIn(BBitmap *source, BPoint dest); + + virtual void ErrorCallback(GLenum errorCode); + virtual void Draw(BRect updateRect); + virtual void AttachedToWindow(); + virtual void AllAttached(); + virtual void DetachedFromWindow(); + virtual void AllDetached(); + virtual void FrameResized(float width, float height); +// virtual status_t Perform(perform_code d, void *arg); + + // + // Methods below are pass-throughs to BView for the moment. + // + + virtual status_t Archive(BMessage *data, bool deep = true) const; + virtual void MessageReceived(BMessage *msg); + virtual void SetResizingMode(uint32 mode); + + virtual void Show(); + virtual void Hide(); + + virtual BHandler *ResolveSpecifier(BMessage *msg, int32 index, + BMessage *specifier, int32 form, + const char *property); + virtual status_t GetSupportedSuites(BMessage *data); + //void DirectConnected( direct_buffer_info *info ); + //void EnableDirectMode( bool enabled ); + +private: + ostgl_context *context; + BBitmap *bitmaps[2]; + int currBitmap; + static BLocker locker; +}; + +#endif // _glview_h_ diff --git a/apps/tinygl/src/TinyGL/src/Makefile b/apps/tinygl/src/TinyGL/src/Makefile new file mode 100644 index 0000000..829d3bf --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/Makefile @@ -0,0 +1,43 @@ +include ../config.mk + +OBJS= api.o list.o vertex.o init.o matrix.o texture.o \ + misc.o clear.o light.o clip.o select.o get.o error.o \ + zbuffer.o zline.o zdither.o ztriangle.o \ + zmath.o image_util.o oscontext.o msghandling.o \ + arrays.o specbuf.o memory.o +ifdef TINYGL_USE_GLX +OBJS += glx.o +endif +ifdef TINYGL_USE_NANOX +OBJS += nglx.o +endif + +INCLUDES = -I../include +LIB = libTinyGL.a + +all: $(LIB) + +$(LIB): $(OBJS) + rm -f $(LIB) + ar rcs $(LIB) $(OBJS) + cp $(LIB) ../lib + +clean: + rm -f *~ *.o *.a + +.c.o: + $(CC) $(CFLAGS) $(INCLUDES) -c $*.c + +clip.o: zgl.h zfeatures.h +vertex.o: zgl.h zfeatures.h +light.o: zgl.h zfeatures.h +matrix.o: zgl.h zfeatures.h +list.o: zgl.h opinfo.h zfeatures.h +arrays.c: zgl.h zfeatures.h +specbuf.o: zgl.h zfeatures.h +glx.o: zgl.h zfeatures.h +nglx.o: zgl.h zfeatures.h +zline.o: zgl.h zfeatures.h zline.h + +ztriangle.o: ztriangle.c ztriangle.h zgl.h zfeatures.h + $(CC) $(CFLAGS) -Wno-uninitialized $(INCLUDES) -c $*.c diff --git a/apps/tinygl/src/TinyGL/src/api.c b/apps/tinygl/src/TinyGL/src/api.c new file mode 100644 index 0000000..91b920f --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/api.c @@ -0,0 +1,668 @@ +#include "zgl.h" +//#include +/* glVertex */ + +void glVertex4f(float x,float y,float z,float w) +{ + GLParam p[5]; + + p[0].op=OP_Vertex; + p[1].f=x; + p[2].f=y; + p[3].f=z; + p[4].f=w; + + gl_add_op(p); +} + +void glVertex2f(float x,float y) +{ + glVertex4f(x,y,0,1); +} + +void glVertex3f(float x,float y,float z) +{ + glVertex4f(x,y,z,1); +} + +void glVertex3fv(float *v) +{ + glVertex4f(v[0],v[1],v[2],1); +} + +/* glNormal */ + +void glNormal3f(float x,float y,float z) +{ + GLParam p[4]; + + p[0].op=OP_Normal; + p[1].f=x; + p[2].f=y; + p[3].f=z; + + gl_add_op(p); +} + +void glNormal3fv(float *v) +{ + glNormal3f(v[0],v[1],v[2]); +} + +/* glColor */ + +void glColor4f(float r,float g,float b,float a) +{ + GLParam p[8]; + + p[0].op=OP_Color; + p[1].f=r; + p[2].f=g; + p[3].f=b; + p[4].f=a; + /* direct convertion to integer to go faster if no shading */ + p[5].ui = (unsigned int) (r * (ZB_POINT_RED_MAX - ZB_POINT_RED_MIN) + + ZB_POINT_RED_MIN); + p[6].ui = (unsigned int) (g * (ZB_POINT_GREEN_MAX - ZB_POINT_GREEN_MIN) + + ZB_POINT_GREEN_MIN); + p[7].ui = (unsigned int) (b * (ZB_POINT_BLUE_MAX - ZB_POINT_BLUE_MIN) + + ZB_POINT_BLUE_MIN); + gl_add_op(p); +} + +void glColor4fv(float *v) +{ + GLParam p[8]; + + p[0].op=OP_Color; + p[1].f=v[0]; + p[2].f=v[1]; + p[3].f=v[2]; + p[4].f=v[3]; + /* direct convertion to integer to go faster if no shading */ + p[5].ui = (unsigned int) (v[0] * (ZB_POINT_RED_MAX - ZB_POINT_RED_MIN) + + ZB_POINT_RED_MIN); + p[6].ui = (unsigned int) (v[1] * (ZB_POINT_GREEN_MAX - ZB_POINT_GREEN_MIN) + + ZB_POINT_GREEN_MIN); + p[7].ui = (unsigned int) (v[2] * (ZB_POINT_BLUE_MAX - ZB_POINT_BLUE_MIN) + + ZB_POINT_BLUE_MIN); + gl_add_op(p); +} + +void glColor3f(float x,float y,float z) +{ + glColor4f(x,y,z,1); +} + +void glColor3fv(float *v) +{ + glColor4f(v[0],v[1],v[2],1); +} + + +/* TexCoord */ + +void glTexCoord4f(float s,float t,float r,float q) +{ + GLParam p[5]; + + p[0].op=OP_TexCoord; + p[1].f=s; + p[2].f=t; + p[3].f=r; + p[4].f=q; + + gl_add_op(p); +} + +void glTexCoord2f(float s,float t) +{ + glTexCoord4f(s,t,0,1); +} + +void glTexCoord2fv(float *v) +{ + glTexCoord4f(v[0],v[1],0,1); +} + +void glEdgeFlag(int flag) +{ + GLParam p[2]; + + p[0].op=OP_EdgeFlag; + p[1].i=flag; + + gl_add_op(p); +} + +/* misc */ + +void glShadeModel(int mode) +{ + GLParam p[2]; + + assert(mode == GL_FLAT || mode == GL_SMOOTH); + + p[0].op=OP_ShadeModel; + p[1].i=mode; + + gl_add_op(p); +} + +void glCullFace(int mode) +{ + GLParam p[2]; + + assert(mode == GL_BACK || + mode == GL_FRONT || + mode == GL_FRONT_AND_BACK); + + p[0].op=OP_CullFace; + p[1].i=mode; + + gl_add_op(p); +} + +void glFrontFace(int mode) +{ + GLParam p[2]; + + assert(mode == GL_CCW || mode == GL_CW); + + mode = (mode != GL_CCW); + + p[0].op=OP_FrontFace; + p[1].i=mode; + + gl_add_op(p); +} + +void glPolygonMode(int face,int mode) +{ + GLParam p[3]; + + assert(face == GL_BACK || + face == GL_FRONT || + face == GL_FRONT_AND_BACK); + assert(mode == GL_POINT || mode == GL_LINE || mode==GL_FILL); + + p[0].op=OP_PolygonMode; + p[1].i=face; + p[2].i=mode; + + gl_add_op(p); +} + + +/* glEnable / glDisable */ + +void glEnable(int cap) +{ + GLParam p[3]; + + p[0].op=OP_EnableDisable; + p[1].i=cap; + p[2].i=1; + + gl_add_op(p); +} + +void glDisable(int cap) +{ + GLParam p[3]; + + p[0].op=OP_EnableDisable; + p[1].i=cap; + p[2].i=0; + + gl_add_op(p); +} + +/* glBegin / glEnd */ + +void glBegin(int mode) +{ + GLParam p[2]; + + p[0].op=OP_Begin; + p[1].i=mode; + + gl_add_op(p); +} + +void glEnd(void) +{ + GLParam p[1]; + + p[0].op=OP_End; + + gl_add_op(p); +} + +/* matrix */ + +void glMatrixMode(int mode) +{ + GLParam p[2]; + + p[0].op=OP_MatrixMode; + p[1].i=mode; + + gl_add_op(p); +} + +void glLoadMatrixf(const float *m) +{ + GLParam p[17]; + int i; + + p[0].op=OP_LoadMatrix; + for(i=0;i<16;i++) p[i+1].f=m[i]; + + gl_add_op(p); +} + +void glLoadIdentity(void) +{ + GLParam p[1]; + + p[0].op=OP_LoadIdentity; + + gl_add_op(p); +} + +void glMultMatrixf(const float *m) +{ + GLParam p[17]; + int i; + + p[0].op=OP_MultMatrix; + for(i=0;i<16;i++) p[i+1].f=m[i]; + + gl_add_op(p); +} + +void glPushMatrix(void) +{ + GLParam p[1]; + + p[0].op=OP_PushMatrix; + + gl_add_op(p); +} + +void glPopMatrix(void) +{ + GLParam p[1]; + + p[0].op=OP_PopMatrix; + + gl_add_op(p); +} + +void glRotatef(float angle,float x,float y,float z) +{ + GLParam p[5]; + + p[0].op=OP_Rotate; + p[1].f=angle; + p[2].f=x; + p[3].f=y; + p[4].f=z; + + gl_add_op(p); +} + +void glTranslatef(float x,float y,float z) +{ + GLParam p[4]; + + p[0].op=OP_Translate; + p[1].f=x; + p[2].f=y; + p[3].f=z; + + gl_add_op(p); +} + +void glScalef(float x,float y,float z) +{ + GLParam p[4]; + + p[0].op=OP_Scale; + p[1].f=x; + p[2].f=y; + p[3].f=z; + + gl_add_op(p); +} + + +void glViewport(int x,int y,int width,int height) +{ + GLParam p[5]; + + p[0].op=OP_Viewport; + p[1].i=x; + p[2].i=y; + p[3].i=width; + p[4].i=height; + + gl_add_op(p); +} + +void glFrustum(double left,double right,double bottom,double top, + double near,double farv) +{ + GLParam p[7]; + + p[0].op=OP_Frustum; + p[1].f=left; + p[2].f=right; + p[3].f=bottom; + p[4].f=top; + p[5].f=near; + p[6].f=farv; + + gl_add_op(p); +} + +/* lightening */ + +void glMaterialfv(int mode,int type,float *v) +{ + GLParam p[7]; + int i,n; + + assert(mode == GL_FRONT || mode == GL_BACK || mode==GL_FRONT_AND_BACK); + + p[0].op=OP_Material; + p[1].i=mode; + p[2].i=type; + n=4; + if (type == GL_SHININESS) n=1; + for(i=0;i<4;i++) p[3+i].f=v[i]; + for(i=n;i<4;i++) p[3+i].f=0; + + gl_add_op(p); +} + +void glMaterialf(int mode,int type,float v) +{ + GLParam p[7]; + int i; + + p[0].op=OP_Material; + p[1].i=mode; + p[2].i=type; + p[3].f=v; + for(i=0;i<3;i++) p[4+i].f=0; + + gl_add_op(p); +} + +void glColorMaterial(int mode,int type) +{ + GLParam p[3]; + + p[0].op=OP_ColorMaterial; + p[1].i=mode; + p[2].i=type; + + gl_add_op(p); +} + +void glLightfv(int light,int type,float *v) +{ + GLParam p[7]; + int i; + + p[0].op=OP_Light; + p[1].i=light; + p[2].i=type; + /* TODO: 3 composants ? */ + for(i=0;i<4;i++) p[3+i].f=v[i]; + + gl_add_op(p); +} + + +void glLightf(int light,int type,float v) +{ + GLParam p[7]; + int i; + + p[0].op=OP_Light; + p[1].i=light; + p[2].i=type; + p[3].f=v; + for(i=0;i<3;i++) p[4+i].f=0; + + gl_add_op(p); +} + +void glLightModeli(int pname,int param) +{ + GLParam p[6]; + int i; + + p[0].op=OP_LightModel; + p[1].i=pname; + p[2].f=(float)param; + for(i=0;i<3;i++) p[3+i].f=0; + + gl_add_op(p); +} + +void glLightModelfv(int pname,float *param) +{ + GLParam p[6]; + int i; + + p[0].op=OP_LightModel; + p[1].i=pname; + for(i=0;i<4;i++) p[2+i].f=param[i]; + + gl_add_op(p); +} + +/* clear */ + +void glClear(int mask) +{ + GLParam p[2]; + + p[0].op=OP_Clear; + p[1].i=mask; + + gl_add_op(p); +} + +void glClearColor(float r,float g,float b,float a) +{ + GLParam p[5]; + + p[0].op=OP_ClearColor; + p[1].f=r; + p[2].f=g; + p[3].f=b; + p[4].f=a; + + gl_add_op(p); +} + +void glClearDepth(double depth) +{ + GLParam p[2]; + + p[0].op=OP_ClearDepth; + p[1].f=depth; + + gl_add_op(p); +} + + +/* textures */ + +void glTexImage2D( int target, int level, int components, + int width, int height, int border, + int format, int type, void *pixels) +{ + GLParam p[10]; + + p[0].op=OP_TexImage2D; + p[1].i=target; + p[2].i=level; + p[3].i=components; + p[4].i=width; + p[5].i=height; + p[6].i=border; + p[7].i=format; + p[8].i=type; + p[9].p=pixels; + + gl_add_op(p); +} + + +void glBindTexture(int target,int texture) +{ + GLParam p[3]; + + p[0].op=OP_BindTexture; + p[1].i=target; + p[2].i=texture; + + gl_add_op(p); +} + +void glTexEnvi(int target,int pname,int param) +{ + GLParam p[8]; + + p[0].op=OP_TexEnv; + p[1].i=target; + p[2].i=pname; + p[3].i=param; + p[4].f=0; + p[5].f=0; + p[6].f=0; + p[7].f=0; + + gl_add_op(p); +} + +void glTexParameteri(int target,int pname,int param) +{ + GLParam p[8]; + + p[0].op=OP_TexParameter; + p[1].i=target; + p[2].i=pname; + p[3].i=param; + p[4].f=0; + p[5].f=0; + p[6].f=0; + p[7].f=0; + + gl_add_op(p); +} + +void glPixelStorei(int pname,int param) +{ + GLParam p[3]; + + p[0].op=OP_PixelStore; + p[1].i=pname; + p[2].i=param; + + gl_add_op(p); +} + +/* selection */ + +void glInitNames(void) +{ + GLParam p[1]; + + p[0].op=OP_InitNames; + + gl_add_op(p); +} + +void glPushName(unsigned int name) +{ + GLParam p[2]; + + p[0].op=OP_PushName; + p[1].i=name; + + gl_add_op(p); +} + +void glPopName(void) +{ + GLParam p[1]; + + p[0].op=OP_PopName; + + gl_add_op(p); +} + +void glLoadName(unsigned int name) +{ + GLParam p[2]; + + p[0].op=OP_LoadName; + p[1].i=name; + + gl_add_op(p); +} + +void +glPolygonOffset(GLfloat factor, GLfloat units) +{ + GLParam p[3]; + p[0].op = OP_PolygonOffset; + p[1].f = factor; + p[2].f = units; + + gl_add_op(p); +} + +/* Special Functions */ + +void glCallList(unsigned int list) +{ + GLParam p[2]; + + p[0].op=OP_CallList; + p[1].i=list; + + gl_add_op(p); +} + +void glFlush(void) +{ + /* nothing to do */ +} + +void glHint(int target,int mode) +{ + GLParam p[3]; + + p[0].op=OP_Hint; + p[1].i=target; + p[2].i=mode; + + gl_add_op(p); +} + +/* Non standard functions */ + +void glDebug(int mode) +{ + GLContext *c=gl_get_context(); + c->print_flag=mode; +} + diff --git a/apps/tinygl/src/TinyGL/src/arrays.c b/apps/tinygl/src/TinyGL/src/arrays.c new file mode 100644 index 0000000..b79adc8 --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/arrays.c @@ -0,0 +1,207 @@ +#include "zgl.h" +//#include + +#define VERTEX_ARRAY 0x0001 +#define COLOR_ARRAY 0x0002 +#define NORMAL_ARRAY 0x0004 +#define TEXCOORD_ARRAY 0x0008 + +void +glopArrayElement(GLContext *c, GLParam *param) +{ + int i; + int states = c->client_states; + int idx = param[1].i; + + if (states & COLOR_ARRAY) { + GLParam p[5]; + int size = c->color_array_size; + i = idx * (size + c->color_array_stride); + p[1].f = c->color_array[i]; + p[2].f = c->color_array[i+1]; + p[3].f = c->color_array[i+2]; + p[4].f = size > 3 ? c->color_array[i+3] : 1.0f; + glopColor(c, p); + } + if (states & NORMAL_ARRAY) { + i = idx * (3 + c->normal_array_stride); + c->current_normal.X = c->normal_array[i]; + c->current_normal.Y = c->normal_array[i+1]; + c->current_normal.Z = c->normal_array[i+2]; + c->current_normal.Z = 0.0f; + } + if (states & TEXCOORD_ARRAY) { + int size = c->texcoord_array_size; + i = idx * (size + c->texcoord_array_stride); + c->current_tex_coord.X = c->texcoord_array[i]; + c->current_tex_coord.Y = c->texcoord_array[i+1]; + c->current_tex_coord.Z = size > 2 ? c->texcoord_array[i+2] : 0.0f; + c->current_tex_coord.W = size > 3 ? c->texcoord_array[i+3] : 1.0f; + } + if (states & VERTEX_ARRAY) { + GLParam p[5]; + int size = c->vertex_array_size; + i = idx * (size + c->vertex_array_stride); + p[1].f = c->vertex_array[i]; + p[2].f = c->vertex_array[i+1]; + p[3].f = size > 2 ? c->vertex_array[i+2] : 0.0f; + p[4].f = size > 3 ? c->vertex_array[i+3] : 1.0f; + glopVertex(c, p); + } +} + +void +glArrayElement(GLint i) +{ + GLParam p[2]; + p[0].op = OP_ArrayElement; + p[1].i = i; + gl_add_op(p); +} + + +void +glopEnableClientState(GLContext *c, GLParam *p) +{ + c->client_states |= p[1].i; +} + +void +glEnableClientState(GLenum array) +{ + GLParam p[2]; + p[0].op = OP_EnableClientState; + + switch(array) { + case GL_VERTEX_ARRAY: + p[1].i = VERTEX_ARRAY; + break; + case GL_NORMAL_ARRAY: + p[1].i = NORMAL_ARRAY; + break; + case GL_COLOR_ARRAY: + p[1].i = COLOR_ARRAY; + break; + case GL_TEXTURE_COORD_ARRAY: + p[1].i = TEXCOORD_ARRAY; + break; + default: + assert(0); + break; + } + gl_add_op(p); +} + +void +glopDisableClientState(GLContext *c, GLParam *p) +{ + c->client_states &= p[1].i; +} + +void +glDisableClientState(GLenum array) +{ + GLParam p[2]; + p[0].op = OP_DisableClientState; + + switch(array) { + case GL_VERTEX_ARRAY: + p[1].i = ~VERTEX_ARRAY; + break; + case GL_NORMAL_ARRAY: + p[1].i = ~NORMAL_ARRAY; + break; + case GL_COLOR_ARRAY: + p[1].i = ~COLOR_ARRAY; + break; + case GL_TEXTURE_COORD_ARRAY: + p[1].i = ~TEXCOORD_ARRAY; + break; + default: + assert(0); + break; + } + gl_add_op(p); +} + +void +glopVertexPointer(GLContext *c, GLParam *p) +{ + c->vertex_array_size = p[1].i; + c->vertex_array_stride = p[2].i; + c->vertex_array = p[3].p; +} + +void +glVertexPointer(GLint size, GLenum type, GLsizei stride, + const GLvoid *pointer) +{ + GLParam p[4]; + assert(type == GL_FLOAT); + p[0].op = OP_VertexPointer; + p[1].i = size; + p[2].i = stride; + p[3].p = (void*)pointer; + gl_add_op(p); +} + +void +glopColorPointer(GLContext *c, GLParam *p) +{ + c->color_array_size = p[1].i; + c->color_array_stride = p[2].i; + c->color_array = p[3].p; +} + +void +glColorPointer(GLint size, GLenum type, GLsizei stride, + const GLvoid *pointer) +{ + GLParam p[4]; + assert(type == GL_FLOAT); + p[0].op = OP_ColorPointer; + p[1].i = size; + p[2].i = stride; + p[3].p = (void*)pointer; + gl_add_op(p); +} + +void +glopNormalPointer(GLContext *c, GLParam *p) +{ + c->normal_array_stride = p[1].i; + c->normal_array = p[2].p; +} + +void +glNormalPointer(GLenum type, GLsizei stride, + const GLvoid *pointer) +{ + GLParam p[3]; + assert(type == GL_FLOAT); + p[0].op = OP_NormalPointer; + p[1].i = stride; + p[2].p = (void*)pointer; + gl_add_op(p); +} + +void +glopTexCoordPointer(GLContext *c, GLParam *p) +{ + c->texcoord_array_size = p[1].i; + c->texcoord_array_stride = p[2].i; + c->texcoord_array = p[3].p; +} + +void +glTexCoordPointer(GLint size, GLenum type, GLsizei stride, + const GLvoid *pointer) +{ + GLParam p[4]; + assert(type == GL_FLOAT); + p[0].op = OP_TexCoordPointer; + p[1].i = size; + p[2].i = stride; + p[3].p = (void*)pointer; + gl_add_op(p); +} diff --git a/apps/tinygl/src/TinyGL/src/clear.c b/apps/tinygl/src/TinyGL/src/clear.c new file mode 100644 index 0000000..f5b7558 --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/clear.c @@ -0,0 +1,30 @@ +#include "zgl.h" + + +void glopClearColor(GLContext *c,GLParam *p) +{ + c->clear_color.v[0]=p[1].f; + c->clear_color.v[1]=p[2].f; + c->clear_color.v[2]=p[3].f; + c->clear_color.v[3]=p[4].f; +} +void glopClearDepth(GLContext *c,GLParam *p) +{ + c->clear_depth=p[1].f; +} + + +void glopClear(GLContext *c,GLParam *p) +{ + int mask=p[1].i; + int z=0; + int r=(int)(c->clear_color.v[0]*65535); + int g=(int)(c->clear_color.v[1]*65535); + int b=(int)(c->clear_color.v[2]*65535); + + /* TODO : correct value of Z */ + + ZB_clear(c->zb,mask & GL_DEPTH_BUFFER_BIT,z, + mask & GL_COLOR_BUFFER_BIT,r,g,b); +} + diff --git a/apps/tinygl/src/TinyGL/src/clip.c b/apps/tinygl/src/TinyGL/src/clip.c new file mode 100644 index 0000000..85a1602 --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/clip.c @@ -0,0 +1,445 @@ +#include "zgl.h" + +/* fill triangle profile */ +/* #define PROFILE */ + +#define CLIP_XMIN (1<<0) +#define CLIP_XMAX (1<<1) +#define CLIP_YMIN (1<<2) +#define CLIP_YMAX (1<<3) +#define CLIP_ZMIN (1<<4) +#define CLIP_ZMAX (1<<5) + +void gl_transform_to_viewport(GLContext *c,GLVertex *v) +{ + float winv; + + /* coordinates */ + winv=1.0/v->pc.W; + v->zp.x= (int) ( v->pc.X * winv * c->viewport.scale.X + + c->viewport.trans.X ); + v->zp.y= (int) ( v->pc.Y * winv * c->viewport.scale.Y + + c->viewport.trans.Y ); + v->zp.z= (int) ( v->pc.Z * winv * c->viewport.scale.Z + + c->viewport.trans.Z ); + /* color */ + if (c->lighting_enabled) { + v->zp.r=(int)(v->color.v[0] * (ZB_POINT_RED_MAX - ZB_POINT_RED_MIN) + + ZB_POINT_RED_MIN); + v->zp.g=(int)(v->color.v[1] * (ZB_POINT_GREEN_MAX - ZB_POINT_GREEN_MIN) + + ZB_POINT_GREEN_MIN); + v->zp.b=(int)(v->color.v[2] * (ZB_POINT_BLUE_MAX - ZB_POINT_BLUE_MIN) + + ZB_POINT_BLUE_MIN); + } else { + /* no need to convert to integer if no lighting : take current color */ + v->zp.r = c->longcurrent_color[0]; + v->zp.g = c->longcurrent_color[1]; + v->zp.b = c->longcurrent_color[2]; + } + + /* texture */ + + if (c->texture_2d_enabled) { + v->zp.s=(int)(v->tex_coord.X * (ZB_POINT_S_MAX - ZB_POINT_S_MIN) + + ZB_POINT_S_MIN); + v->zp.t=(int)(v->tex_coord.Y * (ZB_POINT_T_MAX - ZB_POINT_T_MIN) + + ZB_POINT_T_MIN); + } +} + + +static void gl_add_select1(GLContext *c,int z1,int z2,int z3) +{ + unsigned int min,max; + min=max=z1; + if (z2max) max=z2; + if (z3>max) max=z3; + + gl_add_select(c,0xffffffff-min,0xffffffff-max); +} + +/* point */ + +void gl_draw_point(GLContext *c,GLVertex *p0) +{ + if (p0->clip_code == 0) { + if (c->render_mode == GL_SELECT) { + gl_add_select(c,p0->zp.z,p0->zp.z); + } else { + ZB_plot(c->zb,&p0->zp); + } + } +} + +/* line */ + +static inline void interpolate(GLVertex *q,GLVertex *p0,GLVertex *p1,float t) +{ + q->pc.X=p0->pc.X+(p1->pc.X-p0->pc.X)*t; + q->pc.Y=p0->pc.Y+(p1->pc.Y-p0->pc.Y)*t; + q->pc.Z=p0->pc.Z+(p1->pc.Z-p0->pc.Z)*t; + q->pc.W=p0->pc.W+(p1->pc.W-p0->pc.W)*t; + + q->color.v[0]=p0->color.v[0] + (p1->color.v[0]-p0->color.v[0])*t; + q->color.v[1]=p0->color.v[1] + (p1->color.v[1]-p0->color.v[1])*t; + q->color.v[2]=p0->color.v[2] + (p1->color.v[2]-p0->color.v[2])*t; +} + +/* + * Line Clipping + */ + +/* Line Clipping algorithm from 'Computer Graphics', Principles and + Practice */ +static inline int ClipLine1(float denom,float num,float *tmin,float *tmax) +{ + float t; + + if (denom>0) { + t=num/denom; + if (t>*tmax) return 0; + if (t>*tmin) *tmin=t; + } else if (denom<0) { + t=num/denom; + if (t<*tmin) return 0; + if (t<*tmax) *tmax=t; + } else if (num>0) return 0; + return 1; +} + +void gl_draw_line(GLContext *c,GLVertex *p1,GLVertex *p2) +{ + float dx,dy,dz,dw,x1,y1,z1,w1; + float tmin,tmax; + GLVertex q1,q2; + int cc1,cc2; + + cc1=p1->clip_code; + cc2=p2->clip_code; + + if ( (cc1 | cc2) == 0) { + if (c->render_mode == GL_SELECT) { + gl_add_select1(c,p1->zp.z,p2->zp.z,p2->zp.z); + } else { + if (c->depth_test) + ZB_line_z(c->zb,&p1->zp,&p2->zp); + else + ZB_line(c->zb,&p1->zp,&p2->zp); + } + } else if ( (cc1&cc2) != 0 ) { + return; + } else { + dx=p2->pc.X-p1->pc.X; + dy=p2->pc.Y-p1->pc.Y; + dz=p2->pc.Z-p1->pc.Z; + dw=p2->pc.W-p1->pc.W; + x1=p1->pc.X; + y1=p1->pc.Y; + z1=p1->pc.Z; + w1=p1->pc.W; + + tmin=0; + tmax=1; + if (ClipLine1(dx+dw,-x1-w1,&tmin,&tmax) && + ClipLine1(-dx+dw,x1-w1,&tmin,&tmax) && + ClipLine1(dy+dw,-y1-w1,&tmin,&tmax) && + ClipLine1(-dy+dw,y1-w1,&tmin,&tmax) && + ClipLine1(dz+dw,-z1-w1,&tmin,&tmax) && + ClipLine1(-dz+dw,z1-w1,&tmin,&tmax)) { + + interpolate(&q1,p1,p2,tmin); + interpolate(&q2,p1,p2,tmax); + gl_transform_to_viewport(c,&q1); + gl_transform_to_viewport(c,&q2); + + if (c->depth_test) + ZB_line_z(c->zb,&q1.zp,&q2.zp); + else + ZB_line(c->zb,&q1.zp,&q2.zp); + } + } +} + + +/* triangle */ + +/* + * Clipping + */ + +/* We clip the segment [a,b] against the 6 planes of the normal volume. + * We compute the point 'c' of intersection and the value of the parameter 't' + * of the intersection if x=a+t(b-a). + */ + +#define clip_func(name,sign,dir,dir1,dir2) \ +static float name(V4 *c,V4 *a,V4 *b) \ +{\ + float t,dX,dY,dZ,dW,den;\ + dX = (b->X - a->X);\ + dY = (b->Y - a->Y);\ + dZ = (b->Z - a->Z);\ + dW = (b->W - a->W);\ + den = -(sign d ## dir) + dW;\ + if (den == 0) t=0;\ + else t = ( sign a->dir - a->W) / den;\ + c->dir1 = a->dir1 + t * d ## dir1;\ + c->dir2 = a->dir2 + t * d ## dir2;\ + c->W = a->W + t * dW;\ + c->dir = sign c->W;\ + return t;\ +} + + +clip_func(clip_xmin,-,X,Y,Z) + +clip_func(clip_xmax,+,X,Y,Z) + +clip_func(clip_ymin,-,Y,X,Z) + +clip_func(clip_ymax,+,Y,X,Z) + +clip_func(clip_zmin,-,Z,X,Y) + +clip_func(clip_zmax,+,Z,X,Y) + + +float (*clip_proc[6])(V4 *,V4 *,V4 *)= { + clip_xmin,clip_xmax, + clip_ymin,clip_ymax, + clip_zmin,clip_zmax +}; + +static inline void updateTmp(GLContext *c, + GLVertex *q,GLVertex *p0,GLVertex *p1,float t) +{ + if (c->current_shade_model == GL_SMOOTH) { + q->color.v[0]=p0->color.v[0] + (p1->color.v[0]-p0->color.v[0])*t; + q->color.v[1]=p0->color.v[1] + (p1->color.v[1]-p0->color.v[1])*t; + q->color.v[2]=p0->color.v[2] + (p1->color.v[2]-p0->color.v[2])*t; + } else { + q->color.v[0]=p0->color.v[0]; + q->color.v[1]=p0->color.v[1]; + q->color.v[2]=p0->color.v[2]; + } + + if (c->texture_2d_enabled) { + q->tex_coord.X=p0->tex_coord.X + (p1->tex_coord.X-p0->tex_coord.X)*t; + q->tex_coord.Y=p0->tex_coord.Y + (p1->tex_coord.Y-p0->tex_coord.Y)*t; + } + + q->clip_code=gl_clipcode(q->pc.X,q->pc.Y,q->pc.Z,q->pc.W); + if (q->clip_code==0) + gl_transform_to_viewport(c,q); +} + +static void gl_draw_triangle_clip(GLContext *c, + GLVertex *p0,GLVertex *p1,GLVertex *p2,int clip_bit); + +void gl_draw_triangle(GLContext *c, + GLVertex *p0,GLVertex *p1,GLVertex *p2) +{ + int co,c_and,cc[3],front; + float norm; + + cc[0]=p0->clip_code; + cc[1]=p1->clip_code; + cc[2]=p2->clip_code; + + co=cc[0] | cc[1] | cc[2]; + + /* we handle the non clipped case here to go faster */ + if (co==0) { + + norm=(float)(p1->zp.x-p0->zp.x)*(float)(p2->zp.y-p0->zp.y)- + (float)(p2->zp.x-p0->zp.x)*(float)(p1->zp.y-p0->zp.y); + + if (norm == 0) return; + + front = norm < 0.0; + front = front ^ c->current_front_face; + + /* back face culling */ + if (c->cull_face_enabled) { + /* most used case first */ + if (c->current_cull_face == GL_BACK) { + if (front == 0) return; + c->draw_triangle_front(c,p0,p1,p2); + } else if (c->current_cull_face == GL_FRONT) { + if (front != 0) return; + c->draw_triangle_back(c,p0,p1,p2); + } else { + return; + } + } else { + /* no culling */ + if (front) { + c->draw_triangle_front(c,p0,p1,p2); + } else { + c->draw_triangle_back(c,p0,p1,p2); + } + } + } else { + c_and=cc[0] & cc[1] & cc[2]; + if (c_and==0) { + gl_draw_triangle_clip(c,p0,p1,p2,0); + } + } +} + +static void gl_draw_triangle_clip(GLContext *c, + GLVertex *p0,GLVertex *p1,GLVertex *p2,int clip_bit) +{ + int co,c_and,co1,cc[3],edge_flag_tmp,clip_mask; + GLVertex tmp1,tmp2,*q[3]; + float tt; + + cc[0]=p0->clip_code; + cc[1]=p1->clip_code; + cc[2]=p2->clip_code; + + co=cc[0] | cc[1] | cc[2]; + if (co == 0) { + gl_draw_triangle(c,p0,p1,p2); + } else { + c_and=cc[0] & cc[1] & cc[2]; + /* the triangle is completely outside */ + if (c_and!=0) return; + + /* find the next direction to clip */ + while (clip_bit < 6 && (co & (1 << clip_bit)) == 0) { + clip_bit++; + } + + /* this test can be true only in case of rounding errors */ + if (clip_bit == 6) { +#if 0 + printf("Error:\n"); + printf("%f %f %f %f\n",p0->pc.X,p0->pc.Y,p0->pc.Z,p0->pc.W); + printf("%f %f %f %f\n",p1->pc.X,p1->pc.Y,p1->pc.Z,p1->pc.W); + printf("%f %f %f %f\n",p2->pc.X,p2->pc.Y,p2->pc.Z,p2->pc.W); +#endif + return; + } + + clip_mask = 1 << clip_bit; + co1=(cc[0] ^ cc[1] ^ cc[2]) & clip_mask; + + if (co1) { + /* one point outside */ + + if (cc[0] & clip_mask) { q[0]=p0; q[1]=p1; q[2]=p2; } + else if (cc[1] & clip_mask) { q[0]=p1; q[1]=p2; q[2]=p0; } + else { q[0]=p2; q[1]=p0; q[2]=p1; } + + tt=clip_proc[clip_bit](&tmp1.pc,&q[0]->pc,&q[1]->pc); + updateTmp(c,&tmp1,q[0],q[1],tt); + + tt=clip_proc[clip_bit](&tmp2.pc,&q[0]->pc,&q[2]->pc); + updateTmp(c,&tmp2,q[0],q[2],tt); + + tmp1.edge_flag=q[0]->edge_flag; + edge_flag_tmp=q[2]->edge_flag; + q[2]->edge_flag=0; + gl_draw_triangle_clip(c,&tmp1,q[1],q[2],clip_bit+1); + + tmp2.edge_flag=1; + tmp1.edge_flag=0; + q[2]->edge_flag=edge_flag_tmp; + gl_draw_triangle_clip(c,&tmp2,&tmp1,q[2],clip_bit+1); + } else { + /* two points outside */ + + if ((cc[0] & clip_mask)==0) { q[0]=p0; q[1]=p1; q[2]=p2; } + else if ((cc[1] & clip_mask)==0) { q[0]=p1; q[1]=p2; q[2]=p0; } + else { q[0]=p2; q[1]=p0; q[2]=p1; } + + tt=clip_proc[clip_bit](&tmp1.pc,&q[0]->pc,&q[1]->pc); + updateTmp(c,&tmp1,q[0],q[1],tt); + + tt=clip_proc[clip_bit](&tmp2.pc,&q[0]->pc,&q[2]->pc); + updateTmp(c,&tmp2,q[0],q[2],tt); + + tmp1.edge_flag=1; + tmp2.edge_flag=q[2]->edge_flag; + gl_draw_triangle_clip(c,q[0],&tmp1,&tmp2,clip_bit+1); + } + } +} + + +void gl_draw_triangle_select(GLContext *c, + GLVertex *p0,GLVertex *p1,GLVertex *p2) +{ + gl_add_select1(c,p0->zp.z,p1->zp.z,p2->zp.z); +} + +#ifdef PROFILE +int count_triangles,count_triangles_textured,count_pixels; +#endif + +void gl_draw_triangle_fill(GLContext *c, + GLVertex *p0,GLVertex *p1,GLVertex *p2) +{ +#ifdef PROFILE + { + int norm; + assert(p0->zp.x >= 0 && p0->zp.x < c->zb->xsize); + assert(p0->zp.y >= 0 && p0->zp.y < c->zb->ysize); + assert(p1->zp.x >= 0 && p1->zp.x < c->zb->xsize); + assert(p1->zp.y >= 0 && p1->zp.y < c->zb->ysize); + assert(p2->zp.x >= 0 && p2->zp.x < c->zb->xsize); + assert(p2->zp.y >= 0 && p2->zp.y < c->zb->ysize); + + norm=(p1->zp.x-p0->zp.x)*(p2->zp.y-p0->zp.y)- + (p2->zp.x-p0->zp.x)*(p1->zp.y-p0->zp.y); + count_pixels+=abs(norm)/2; + count_triangles++; + } +#endif + + if (c->texture_2d_enabled) { +#ifdef PROFILE + count_triangles_textured++; +#endif + ZB_setTexture(c->zb,c->current_texture->images[0].pixmap); + ZB_fillTriangleMappingPerspective(c->zb,&p0->zp,&p1->zp,&p2->zp); + } else if (c->current_shade_model == GL_SMOOTH) { + ZB_fillTriangleSmooth(c->zb,&p0->zp,&p1->zp,&p2->zp); + } else { + ZB_fillTriangleFlat(c->zb,&p0->zp,&p1->zp,&p2->zp); + } +} + +/* Render a clipped triangle in line mode */ + +void gl_draw_triangle_line(GLContext *c, + GLVertex *p0,GLVertex *p1,GLVertex *p2) +{ + if (c->depth_test) { + if (p0->edge_flag) ZB_line_z(c->zb,&p0->zp,&p1->zp); + if (p1->edge_flag) ZB_line_z(c->zb,&p1->zp,&p2->zp); + if (p2->edge_flag) ZB_line_z(c->zb,&p2->zp,&p0->zp); + } else { + if (p0->edge_flag) ZB_line(c->zb,&p0->zp,&p1->zp); + if (p1->edge_flag) ZB_line(c->zb,&p1->zp,&p2->zp); + if (p2->edge_flag) ZB_line(c->zb,&p2->zp,&p0->zp); + } +} + + + +/* Render a clipped triangle in point mode */ +void gl_draw_triangle_point(GLContext *c, + GLVertex *p0,GLVertex *p1,GLVertex *p2) +{ + if (p0->edge_flag) ZB_plot(c->zb,&p0->zp); + if (p1->edge_flag) ZB_plot(c->zb,&p1->zp); + if (p2->edge_flag) ZB_plot(c->zb,&p2->zp); +} + + + + diff --git a/apps/tinygl/src/TinyGL/src/error.c b/apps/tinygl/src/TinyGL/src/error.c new file mode 100644 index 0000000..9b1bccb --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/error.c @@ -0,0 +1,17 @@ +#include +#include "zgl.h" + +void gl_fatal_error(char *format, ...) +{ +// FIXME +// va_list ap; +// +// va_start(ap,format); +// +// fprintf(stderr,"TinyGL: fatal error: "); +// vfprintf(stderr,format,ap); +// fprintf(stderr,"\n"); +// exit(1); +// +// va_end(ap); +} diff --git a/apps/tinygl/src/TinyGL/src/get.c b/apps/tinygl/src/TinyGL/src/get.c new file mode 100644 index 0000000..f7803c2 --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/get.c @@ -0,0 +1,73 @@ +#include "zgl.h" + +void glGetIntegerv(int pname,int *params) +{ + GLContext *c=gl_get_context(); + + switch(pname) { + case GL_VIEWPORT: + params[0]=c->viewport.xmin; + params[1]=c->viewport.ymin; + params[2]=c->viewport.xsize; + params[3]=c->viewport.ysize; + break; + case GL_MAX_MODELVIEW_STACK_DEPTH: + *params = MAX_MODELVIEW_STACK_DEPTH; + break; + case GL_MAX_PROJECTION_STACK_DEPTH: + *params = MAX_PROJECTION_STACK_DEPTH; + break; + case GL_MAX_LIGHTS: + *params = MAX_LIGHTS; + break; + case GL_MAX_TEXTURE_SIZE: + *params = 256; /* not completely true, but... */ + break; + case GL_MAX_TEXTURE_STACK_DEPTH: + *params = MAX_TEXTURE_STACK_DEPTH; + break; + default: + gl_fatal_error("glGet: option not implemented"); + break; + } +} + +void glGetFloatv(int pname, float *v) +{ + int i; + int mnr = 0; /* just a trick to return the correct matrix */ + GLContext *c = gl_get_context(); + switch (pname) { + case GL_TEXTURE_MATRIX: + mnr++; + case GL_PROJECTION_MATRIX: + mnr++; + case GL_MODELVIEW_MATRIX: + { + float *p = &c->matrix_stack_ptr[mnr]->m[0][0];; + for (i = 0; i < 4; i++) { + *v++ = p[0]; + *v++ = p[4]; + *v++ = p[8]; + *v++ = p[12]; + p++; + } + } + break; + case GL_LINE_WIDTH: + *v = 1.0f; + break; + case GL_LINE_WIDTH_RANGE: + v[0] = v[1] = 1.0f; + break; + case GL_POINT_SIZE: + *v = 1.0f; + break; + case GL_POINT_SIZE_RANGE: + v[0] = v[1] = 1.0f; + default: + //fprintf(stderr,"warning: unknown pname in glGetFloatv()\n"); + // FIXME + break; + } +} diff --git a/apps/tinygl/src/TinyGL/src/glx.c b/apps/tinygl/src/TinyGL/src/glx.c new file mode 100644 index 0000000..b4888f4 --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/glx.c @@ -0,0 +1,413 @@ +/* simple glx driver for TinyGL */ +#include +#include +#include +#include +#include "zgl.h" + +typedef struct { + GLContext *gl_context; + Display *display; + XVisualInfo visual_info; + int xsize,ysize; + XImage *ximage; + GC gc; + Colormap cmap; + Drawable drawable; + int do_convert; /* true if must do convertion to X11 format */ + /* shared memory */ + int shm_use; + XShmSegmentInfo *shm_info; + int CompletionType; +} TinyGLXContext; + +Bool glXQueryExtension( Display *dpy, int *errorb, int *event ) +{ + return True; +} + + +XVisualInfo* glXChooseVisual( Display *dpy, int screen, + int *attribList ) +{ + XVisualInfo vinfo; + int n; + + /* the attribList is ignored : we consider only RGBA rendering (no + direct color) */ + + if (XMatchVisualInfo (dpy, screen, 16, TrueColor, &vinfo)) { + /* 16 bit visual (fastest with TinyGL) */ + } else if (XMatchVisualInfo (dpy, screen, 24, TrueColor, &vinfo)) { + /* 24 bit visual */ + } else if (XMatchVisualInfo (dpy, screen, 32, TrueColor, &vinfo)) { + /* 32 bit visual */ + } else if (XMatchVisualInfo (dpy, screen, 8, PseudoColor, &vinfo)) { + /* 8 bit visual */ + } else { + /* no suitable visual */ + return NULL; + } + + return XGetVisualInfo(dpy,VisualAllMask,&vinfo,&n); +} + + + +GLXContext glXCreateContext( Display *dpy, XVisualInfo *vis, + GLXContext shareList, Bool direct ) +{ + TinyGLXContext *ctx; + + if (shareList != NULL) { + gl_fatal_error("No sharing available in TinyGL"); + } + ctx=gl_malloc(sizeof(TinyGLXContext)); + ctx->gl_context=NULL; + ctx->visual_info=*vis; + return (GLXContext) ctx; +} + + +void glXDestroyContext( Display *dpy, GLXContext ctx1 ) +{ + TinyGLXContext *ctx = (TinyGLXContext *) ctx1; + if (ctx->gl_context != NULL) { + glClose(); + } + gl_free(ctx); +} + + +static int glxXErrorFlag=0; + +static int glxHandleXError(Display *dpy,XErrorEvent *event) +{ + glxXErrorFlag=1; + return 0; +} + +static int bits_per_pixel(Display *dpy, XVisualInfo *visinfo) +{ + XImage *img; + int bpp; + char *data; + + data = gl_malloc(8); + if (data == NULL) + return visinfo->depth; + + img = XCreateImage(dpy, visinfo->visual, visinfo->depth, + ZPixmap, 0, data, 1, 1, 32, 0); + if (img == NULL) { + gl_free(data); + return visinfo->depth; + } + bpp = img->bits_per_pixel; + gl_free(data); + img->data = NULL; + XDestroyImage(img); + return bpp; +} + +static int create_ximage(TinyGLXContext *ctx, + int xsize,int ysize,int depth) +{ + int major,minor; + Bool pixmaps; + unsigned char *framebuffer; + int (*old_handler)(Display *,XErrorEvent *); + + if (XShmQueryVersion(ctx->display,&major,&minor,&pixmaps)) + ctx->shm_use=1; + else + ctx->shm_use=0; + + if (!ctx->shm_use) goto no_shm; + + ctx->shm_info=gl_malloc(sizeof(XShmSegmentInfo)); + ctx->ximage=XShmCreateImage(ctx->display,None,depth,ZPixmap,NULL, + ctx->shm_info,xsize,ysize); + if (ctx->ximage == NULL) { + fprintf(stderr,"XShm: error: XShmCreateImage\n"); + ctx->shm_use=0; + gl_free(ctx->shm_info); + goto no_shm; + } + ctx->shm_info->shmid=shmget(IPC_PRIVATE, + ctx->ysize*ctx->ximage->bytes_per_line, + IPC_CREAT | 0777); + if (ctx->shm_info->shmid < 0) { + fprintf(stderr,"XShm: error: shmget\n"); + no_shm1: + ctx->shm_use=0; + XDestroyImage(ctx->ximage); + goto no_shm; + } + ctx->ximage->data=shmat(ctx->shm_info->shmid,0,0); + if (ctx->ximage->data == (char *) -1) { + fprintf(stderr,"XShm: error: shmat\n"); + no_shm2: + shmctl(ctx->shm_info->shmid,IPC_RMID,0); + goto no_shm1; + } + ctx->shm_info->shmaddr=ctx->ximage->data; + + ctx->shm_info->readOnly=False; + + /* attach & test X errors */ + + glxXErrorFlag=0; + old_handler=XSetErrorHandler(glxHandleXError); + XShmAttach(ctx->display,ctx->shm_info); + XSync(ctx->display, False); + + if (glxXErrorFlag) { + XFlush(ctx->display); + shmdt(ctx->shm_info->shmaddr); + XSetErrorHandler(old_handler); + goto no_shm2; + } + + /* the shared memory will be automatically deleted */ + shmctl(ctx->shm_info->shmid,IPC_RMID,0); + + /* test with a dummy XShmPutImage */ + XShmPutImage(ctx->display,ctx->drawable,ctx->gc, + ctx->ximage,0,0,0,0,1,1, + False); + + XSync(ctx->display, False); + XSetErrorHandler(old_handler); + + if (glxXErrorFlag) { + fprintf(stderr,"XShm: error: XShmPutImage\n"); + XFlush(ctx->display); + shmdt(ctx->shm_info->shmaddr); + goto no_shm2; + } + + ctx->CompletionType=XShmGetEventBase(ctx->display) + ShmCompletion; + /* shared memory is OK !! */ + + return 0; + + no_shm: + ctx->ximage=XCreateImage(ctx->display, None, depth, ZPixmap, 0, + NULL,xsize,ysize, 8, 0); + framebuffer=gl_malloc(ysize * ctx->ximage->bytes_per_line); + ctx->ximage->data = (char *)framebuffer; + return 0; +} + +static void free_ximage(TinyGLXContext *ctx) +{ + if (ctx->shm_use) + { + XShmDetach(ctx->display, ctx->shm_info); + XDestroyImage(ctx->ximage); + shmdt(ctx->shm_info->shmaddr); + gl_free(ctx->shm_info); + } else { + gl_free(ctx->ximage->data); + XDestroyImage(ctx->ximage); + } +} + +/* resize the glx viewport : we try to use the xsize and ysize + given. We return the effective size which is guaranted to be smaller */ + +int glX_resize_viewport(GLContext *c,int *xsize_ptr,int *ysize_ptr) +{ + TinyGLXContext *ctx; + int xsize,ysize; + + ctx=(TinyGLXContext *)c->opaque; + + xsize=*xsize_ptr; + ysize=*ysize_ptr; + + /* we ensure that xsize and ysize are multiples of 2 for the zbuffer. + TODO: find a better solution */ + xsize&=~3; + ysize&=~3; + + if (xsize == 0 || ysize == 0) return -1; + + *xsize_ptr=xsize; + *ysize_ptr=ysize; + + if (ctx->ximage != NULL) free_ximage(ctx); + + ctx->xsize=xsize; + ctx->ysize=ysize; + + if (create_ximage(ctx,ctx->xsize,ctx->ysize,ctx->visual_info.depth) != 0) + return -1; + + /* resize the Z buffer */ + if (ctx->do_convert) { + ZB_resize(c->zb,NULL,xsize,ysize); + } else { + ZB_resize(c->zb,ctx->ximage->data,xsize,ysize); + } + return 0; +} + +/* we assume here that drawable is a window */ +Bool glXMakeCurrent( Display *dpy, GLXDrawable drawable, + GLXContext ctx1) +{ + TinyGLXContext *ctx = (TinyGLXContext *) ctx1; + XWindowAttributes attr; + int i,xsize,ysize; + int palette[ZB_NB_COLORS]; + unsigned char color_indexes[ZB_NB_COLORS]; + ZBuffer *zb; + XColor xcolor; + unsigned long pixel[ZB_NB_COLORS],tmp_plane; + + if (ctx->gl_context == NULL) { + /* create the TinyGL context */ + + ctx->display=dpy; + ctx->drawable=drawable; + + XGetWindowAttributes(ctx->display,drawable,&attr); + + xsize=attr.width; + ysize=attr.height; + + if (attr.depth != ctx->visual_info.depth) return False; + + /* ximage structure */ + ctx->ximage=NULL; + ctx->shm_use=1; /* use shm */ + + if (attr.depth == 8) { + /* get the colormap from the window */ + ctx->cmap = attr.colormap; + + if ( XAllocColorCells(ctx->display,ctx->cmap,True,&tmp_plane,0, + pixel,ZB_NB_COLORS) == 0) { + /* private cmap */ + ctx->cmap = XCreateColormap(ctx->display, drawable, + ctx->visual_info.visual, AllocAll); + XSetWindowColormap(ctx->display, drawable, ctx->cmap); + for(i=0;i>8) & 0xFF00; + xcolor.green = (palette[i] & 0xFF00); + xcolor.blue = (palette[i] << 8) & 0xFF00; + xcolor.pixel = pixel[i]; + XStoreColor(ctx->display,ctx->cmap,&xcolor); + } + ctx->do_convert = 1; + } else { + int mode,bpp; + /* RGB 16/24/32 */ + bpp = bits_per_pixel(ctx->display,&ctx->visual_info); + switch(bpp) { + case 24: + mode = ZB_MODE_RGB24; + ctx->do_convert = (TGL_FEATURE_RENDER_BITS != 24); + break; + case 32: + mode = ZB_MODE_RGBA; + ctx->do_convert = (TGL_FEATURE_RENDER_BITS != 32); + break; + default: + mode = ZB_MODE_5R6G5B; + ctx->do_convert = (TGL_FEATURE_RENDER_BITS != 16); + break; + } + zb=ZB_open(xsize,ysize,mode,0,NULL,NULL,NULL); + if (zb == NULL) { + fprintf(stderr, "Error while initializing Z buffer\n"); + exit(1); + } + } + + /* create a gc */ + ctx->gc = XCreateGC(ctx->display, drawable, 0, 0); + + /* initialisation of the TinyGL interpreter */ + glInit(zb); + ctx->gl_context=gl_get_context(); + ctx->gl_context->opaque=(void *) ctx; + ctx->gl_context->gl_resize_viewport=glX_resize_viewport; + + /* set the viewport : we force a call to glX_resize_viewport */ + ctx->gl_context->viewport.xsize=-1; + ctx->gl_context->viewport.ysize=-1; + + glViewport(0, 0, xsize, ysize); + } + + return True; +} + +static Bool WaitForShmCompletion(Display *dpy, XEvent *event, char *arg) +{ + TinyGLXContext *ctx=(TinyGLXContext *) arg; + + return (event->type == ctx->CompletionType) && + ( ((XShmCompletionEvent *)event)->drawable == (Window)ctx->drawable); +} + +void glXSwapBuffers( Display *dpy, GLXDrawable drawable ) +{ + GLContext *gl_context; + TinyGLXContext *ctx; + + /* retrieve the current GLXContext */ + gl_context=gl_get_context(); + ctx=(TinyGLXContext *)gl_context->opaque; + + /* for non 16 bits visuals, a conversion is required */ + + + if (ctx->do_convert) { + ZB_copyFrameBuffer(ctx->gl_context->zb, + ctx->ximage->data, + ctx->ximage->bytes_per_line); + + } + + /* draw the ximage */ + if (ctx->shm_use) { + XEvent event; + + XShmPutImage(dpy,drawable,ctx->gc, + ctx->ximage,0,0,0,0,ctx->ximage->width, ctx->ximage->height, + True); + XIfEvent(dpy, &event, WaitForShmCompletion, (char*)ctx); + } else { + XPutImage(dpy, drawable, ctx->gc, + ctx->ximage, 0, 0, 0, 0, ctx->ximage->width, ctx->ximage->height); + } + XFlush(dpy); +} + + +void glXWaitGL( void ) +{ +} + +void glXWaitX( void ) +{ +} diff --git a/apps/tinygl/src/TinyGL/src/image_util.c b/apps/tinygl/src/TinyGL/src/image_util.c new file mode 100644 index 0000000..cb04382 --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/image_util.c @@ -0,0 +1,136 @@ +#include "zgl.h" + +/* + * image conversion + */ + +void gl_convertRGB_to_5R6G5B(unsigned short *pixmap,unsigned char *rgb, + int xsize,int ysize) +{ + int i,n; + unsigned char *p; + + p=rgb; + n=xsize*ysize; + for(i=0;i>3); + p+=3; + } +} + +void gl_convertRGB_to_8A8R8G8B(unsigned int *pixmap, unsigned char *rgb, + int xsize, int ysize) +{ + int i,n; + unsigned char *p; + + p=rgb; + n=xsize*ysize; + for(i=0;i> INTERP_NORM_BITS); +} + + +/* + * TODO: more accurate resampling + */ + +void gl_resizeImage(unsigned char *dest,int xsize_dest,int ysize_dest, + unsigned char *src,int xsize_src,int ysize_src) +{ + unsigned char *pix,*pix_src; + float x1,y1,x1inc,y1inc; + int xi,yi,j,xf,yf,x,y; + + pix=dest; + pix_src=src; + + x1inc=(float) (xsize_src - 1) / (float) (xsize_dest - 1); + y1inc=(float) (ysize_src - 1) / (float) (ysize_dest - 1); + + y1=0; + for(y=0;y> FRAC_BITS; + yi=y1 >> FRAC_BITS; + pix1=pix_src+(yi*xsize_src+xi)*3; + + pix[0]=pix1[0]; + pix[1]=pix1[1]; + pix[2]=pix1[2]; + + pix+=3; + x1+=x1inc; + } + y1+=y1inc; + } +} + diff --git a/apps/tinygl/src/TinyGL/src/init.c b/apps/tinygl/src/TinyGL/src/init.c new file mode 100644 index 0000000..edc7a4c --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/init.c @@ -0,0 +1,189 @@ +#include "zgl.h" + +GLContext *gl_ctx; + + +void initSharedState(GLContext *c) +{ + GLSharedState *s=&c->shared_state; + s->lists=gl_zalloc(sizeof(GLList *) * MAX_DISPLAY_LISTS); + s->texture_hash_table= + gl_zalloc(sizeof(GLTexture *) * TEXTURE_HASH_TABLE_SIZE); + + alloc_texture(c,0); +} + +void endSharedState(GLContext *c) +{ + GLSharedState *s=&c->shared_state; + int i; + + for(i=0;ilists); + + gl_free(s->texture_hash_table); +} + + +void glInit(void *zbuffer1) +{ + ZBuffer *zbuffer=(ZBuffer *)zbuffer1; + GLContext *c; + GLViewport *v; + int i; + + c=gl_zalloc(sizeof(GLContext)); + gl_ctx=c; + + c->zb=zbuffer; + + /* allocate GLVertex array */ + c->vertex_max = POLYGON_MAX_VERTEX; + c->vertex = gl_malloc(POLYGON_MAX_VERTEX*sizeof(GLVertex)); + + /* viewport */ + v=&c->viewport; + v->xmin=0; + v->ymin=0; + v->xsize=zbuffer->xsize; + v->ysize=zbuffer->ysize; + v->updated=1; + + /* shared state */ + initSharedState(c); + + /* lists */ + + c->exec_flag=1; + c->compile_flag=0; + c->print_flag=0; + + c->in_begin=0; + + /* lights */ + for(i=0;ilights[i]; + l->ambient=gl_V4_New(0,0,0,1); + l->diffuse=gl_V4_New(1,1,1,1); + l->specular=gl_V4_New(1,1,1,1); + l->position=gl_V4_New(0,0,1,0); + l->norm_position=gl_V3_New(0,0,1); + l->spot_direction=gl_V3_New(0,0,-1); + l->norm_spot_direction=gl_V3_New(0,0,-1); + l->spot_exponent=0; + l->spot_cutoff=180; + l->attenuation[0]=1; + l->attenuation[1]=0; + l->attenuation[2]=0; + l->enabled=0; + } + c->first_light=NULL; + c->ambient_light_model=gl_V4_New(0.2,0.2,0.2,1); + c->local_light_model=0; + c->lighting_enabled=0; + c->light_model_two_side = 0; + + /* default materials */ + for(i=0;i<2;i++) { + GLMaterial *m=&c->materials[i]; + m->emission=gl_V4_New(0,0,0,1); + m->ambient=gl_V4_New(0.2,0.2,0.2,1); + m->diffuse=gl_V4_New(0.8,0.8,0.8,1); + m->specular=gl_V4_New(0,0,0,1); + m->shininess=0; + } + c->current_color_material_mode=GL_FRONT_AND_BACK; + c->current_color_material_type=GL_AMBIENT_AND_DIFFUSE; + c->color_material_enabled=0; + + /* textures */ + glInitTextures(c); + + /* default state */ + c->current_color.X=1.0; + c->current_color.Y=1.0; + c->current_color.Z=1.0; + c->current_color.W=1.0; + c->longcurrent_color[0] = 65535; + c->longcurrent_color[1] = 65535; + c->longcurrent_color[2] = 65535; + + c->current_normal.X=1.0; + c->current_normal.Y=0.0; + c->current_normal.Z=0.0; + c->current_normal.W=0.0; + + c->current_edge_flag=1; + + c->current_tex_coord.X=0; + c->current_tex_coord.Y=0; + c->current_tex_coord.Z=0; + c->current_tex_coord.W=1; + + c->polygon_mode_front=GL_FILL; + c->polygon_mode_back=GL_FILL; + + c->current_front_face=0; /* 0 = GL_CCW 1 = GL_CW */ + c->current_cull_face=GL_BACK; + c->current_shade_model=GL_SMOOTH; + c->cull_face_enabled=0; + + /* clear */ + c->clear_color.v[0]=0; + c->clear_color.v[1]=0; + c->clear_color.v[2]=0; + c->clear_color.v[3]=0; + c->clear_depth=0; + + /* selection */ + c->render_mode=GL_RENDER; + c->select_buffer=NULL; + c->name_stack_size=0; + + /* matrix */ + c->matrix_mode=0; + + c->matrix_stack_depth_max[0]=MAX_MODELVIEW_STACK_DEPTH; + c->matrix_stack_depth_max[1]=MAX_PROJECTION_STACK_DEPTH; + c->matrix_stack_depth_max[2]=MAX_TEXTURE_STACK_DEPTH; + + for(i=0;i<3;i++) { + c->matrix_stack[i]=gl_zalloc(c->matrix_stack_depth_max[i] * sizeof(M4)); + c->matrix_stack_ptr[i]=c->matrix_stack[i]; + } + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + c->matrix_model_projection_updated=1; + + /* opengl 1.1 arrays */ + c->client_states = 0; + + /* opengl 1.1 polygon offset */ + c->offset_states = 0; + + /* clear the resize callback function pointer */ + c->gl_resize_viewport = NULL; + + /* specular buffer */ + c->specbuf_first = NULL; + c->specbuf_used_counter = 0; + c->specbuf_num_buffers = 0; + + /* depth test */ + c->depth_test = 0; +} + +void glClose(void) +{ + GLContext *c=gl_get_context(); + endSharedState(c); + gl_free(c); +} diff --git a/apps/tinygl/src/TinyGL/src/light.c b/apps/tinygl/src/TinyGL/src/light.c new file mode 100644 index 0000000..e092543 --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/light.c @@ -0,0 +1,304 @@ +#include "zgl.h" +#include "msghandling.h" + +void glopMaterial(GLContext *c,GLParam *p) +{ + int mode=p[1].i; + int type=p[2].i; + int i; + GLMaterial *m; + + if (mode == GL_FRONT_AND_BACK) { + p[1].i=GL_FRONT; + glopMaterial(c,p); + mode=GL_BACK; + } + if (mode == GL_FRONT) m=&c->materials[0]; + else m=&c->materials[1]; + + switch(type) { + case GL_EMISSION: + for(i=0;i<4;i++) + m->emission.v[i]=p[3 + i].f; + break; + case GL_AMBIENT: + for(i=0;i<4;i++) + m->ambient.v[i]=p[3 + i].f; + break; + case GL_DIFFUSE: + for(i=0;i<4;i++) + m->diffuse.v[i]=p[3 + i].f; + break; + case GL_SPECULAR: + for(i=0;i<4;i++) + m->specular.v[i]=p[3 + i].f; + break; + case GL_SHININESS: + m->shininess=p[3].f; + m->shininess_i = (m->shininess/128.0f)*SPECULAR_BUFFER_RESOLUTION; + break; + case GL_AMBIENT_AND_DIFFUSE: + for(i=0;i<4;i++) + m->diffuse.v[i]=p[3 + i].f; + for(i=0;i<4;i++) + m->ambient.v[i]=p[3 + i].f; + break; + default: + assert(0); + } +} + +void glopColorMaterial(GLContext *c,GLParam *p) +{ + int mode=p[1].i; + int type=p[2].i; + + c->current_color_material_mode=mode; + c->current_color_material_type=type; +} + +void glopLight(GLContext *c,GLParam *p) +{ + int light=p[1].i; + int type=p[2].i; + V4 v; + GLLight *l; + int i; + + assert(light >= GL_LIGHT0 && light < GL_LIGHT0+MAX_LIGHTS ); + + l=&c->lights[light-GL_LIGHT0]; + + for(i=0;i<4;i++) v.v[i]=p[3+i].f; + + switch(type) { + case GL_AMBIENT: + l->ambient=v; + break; + case GL_DIFFUSE: + l->diffuse=v; + break; + case GL_SPECULAR: + l->specular=v; + break; + case GL_POSITION: + { + V4 pos; + gl_M4_MulV4(&pos,c->matrix_stack_ptr[0],&v); + + l->position=pos; + + if (l->position.v[3] == 0) { + l->norm_position.X=pos.X; + l->norm_position.Y=pos.Y; + l->norm_position.Z=pos.Z; + + gl_V3_Norm(&l->norm_position); + } + } + break; + case GL_SPOT_DIRECTION: + for(i=0;i<3;i++) { + l->spot_direction.v[i]=v.v[i]; + l->norm_spot_direction.v[i]=v.v[i]; + } + gl_V3_Norm(&l->norm_spot_direction); + break; + case GL_SPOT_EXPONENT: + l->spot_exponent=v.v[0]; + break; + case GL_SPOT_CUTOFF: + { + float a=v.v[0]; + assert(a == 180 || (a>=0 && a<=90)); + l->spot_cutoff=a; + if (a != 180) l->cos_spot_cutoff=zcos(a * M_PI / 180.0); + } + break; + case GL_CONSTANT_ATTENUATION: + l->attenuation[0]=v.v[0]; + break; + case GL_LINEAR_ATTENUATION: + l->attenuation[1]=v.v[0]; + break; + case GL_QUADRATIC_ATTENUATION: + l->attenuation[2]=v.v[0]; + break; + default: + assert(0); + } +} + + +void glopLightModel(GLContext *c,GLParam *p) +{ + int pname=p[1].i; + int i; + + switch(pname) { + case GL_LIGHT_MODEL_AMBIENT: + for(i=0;i<4;i++) + c->ambient_light_model.v[i]=p[2 + i].f; + break; + case GL_LIGHT_MODEL_LOCAL_VIEWER: + c->local_light_model=(int)p[2].f; + break; + case GL_LIGHT_MODEL_TWO_SIDE: + c->light_model_two_side = (int)p[2].f; + break; + default: + tgl_warning("glopLightModel: illegal pname: 0x%x\n", pname); + //assert(0); + break; + } +} + + +static inline float clampf(float a,float min,float max) +{ + if (amax) return max; + else return a; +} + +void gl_enable_disable_light(GLContext *c,int light,int v) +{ + GLLight *l=&c->lights[light]; + if (v && !l->enabled) { + l->enabled=1; + l->next=c->first_light; + c->first_light=l; + l->prev=NULL; + } else if (!v && l->enabled) { + l->enabled=0; + if (l->prev == NULL) c->first_light=l->next; + else l->prev->next=l->next; + if (l->next != NULL) l->next->prev=l->prev; + } +} + +/* non optimized lightening model */ +void gl_shade_vertex(GLContext *c,GLVertex *v) +{ + float R,G,B,A; + GLMaterial *m; + GLLight *l; + V3 n,s,d; + float dist,tmp,att,dot,dot_spot,dot_spec; + int twoside = c->light_model_two_side; + + m=&c->materials[0]; + + n.X=v->normal.X; + n.Y=v->normal.Y; + n.Z=v->normal.Z; + + R=m->emission.v[0]+m->ambient.v[0]*c->ambient_light_model.v[0]; + G=m->emission.v[1]+m->ambient.v[1]*c->ambient_light_model.v[1]; + B=m->emission.v[2]+m->ambient.v[2]*c->ambient_light_model.v[2]; + A=clampf(m->diffuse.v[3],0,1); + + for(l=c->first_light;l!=NULL;l=l->next) { + float lR,lB,lG; + + /* ambient */ + lR=l->ambient.v[0] * m->ambient.v[0]; + lG=l->ambient.v[1] * m->ambient.v[1]; + lB=l->ambient.v[2] * m->ambient.v[2]; + + if (l->position.v[3] == 0) { + /* light at infinity */ + d.X=l->norm_position.v[0]; + d.Y=l->norm_position.v[1]; + d.Z=l->norm_position.v[2]; + att=1; + } else { + /* distance attenuation */ + d.X=l->position.v[0]-v->ec.v[0]; + d.Y=l->position.v[1]-v->ec.v[1]; + d.Z=l->position.v[2]-v->ec.v[2]; + dist=zsqrt(d.X*d.X+d.Y*d.Y+d.Z*d.Z); + if (dist>1E-10f) { + tmp=1/dist; + d.X*=tmp; + d.Y*=tmp; + d.Z*=tmp; + } + att=1.0f/(l->attenuation[0]+dist*(l->attenuation[1]+ + dist*l->attenuation[2])); + } + dot=d.X*n.X+d.Y*n.Y+d.Z*n.Z; + if (twoside && dot < 0) dot = -dot; + if (dot>0) { + /* diffuse light */ + lR+=dot * l->diffuse.v[0] * m->diffuse.v[0]; + lG+=dot * l->diffuse.v[1] * m->diffuse.v[1]; + lB+=dot * l->diffuse.v[2] * m->diffuse.v[2]; + + /* spot light */ + if (l->spot_cutoff != 180) { + dot_spot=-(d.X*l->norm_spot_direction.v[0]+ + d.Y*l->norm_spot_direction.v[1]+ + d.Z*l->norm_spot_direction.v[2]); + if (twoside && dot_spot < 0) dot_spot = -dot_spot; + if (dot_spot < l->cos_spot_cutoff) { + /* no contribution */ + continue; + } else { + /* TODO: optimize */ + if (l->spot_exponent > 0) { + att=att*zpow(dot_spot,l->spot_exponent); + } + } + } + + /* specular light */ + + if (c->local_light_model) { + V3 vcoord; + vcoord.X=v->ec.X; + vcoord.Y=v->ec.Y; + vcoord.Z=v->ec.Z; + gl_V3_Norm(&vcoord); + s.X=d.X-vcoord.X; + s.Y=d.Y-vcoord.X; + s.Z=d.Z-vcoord.X; + } else { + s.X=d.X; + s.Y=d.Y; + s.Z=d.Z+1.0; + } + dot_spec=n.X*s.X+n.Y*s.Y+n.Z*s.Z; + if (twoside && dot_spec < 0) dot_spec = -dot_spec; + if (dot_spec>0) { + GLSpecBuf *specbuf; + int idx; + tmp=zsqrt(s.X*s.X+s.Y*s.Y+s.Z*s.Z); + if (tmp > 1E-3) { + dot_spec=dot_spec / tmp; + } + + /* TODO: optimize */ + /* testing specular buffer code */ + /* dot_spec= zpow(dot_spec,m->shininess);*/ + specbuf = specbuf_get_buffer(c, m->shininess_i, m->shininess); + idx = (int)(dot_spec*SPECULAR_BUFFER_SIZE); + if (idx > SPECULAR_BUFFER_SIZE) idx = SPECULAR_BUFFER_SIZE; + dot_spec = specbuf->buf[idx]; + lR+=dot_spec * l->specular.v[0] * m->specular.v[0]; + lG+=dot_spec * l->specular.v[1] * m->specular.v[1]; + lB+=dot_spec * l->specular.v[2] * m->specular.v[2]; + } + } + + R+=att * lR; + G+=att * lG; + B+=att * lB; + } + + v->color.v[0]=clampf(R,0,1); + v->color.v[1]=clampf(G,0,1); + v->color.v[2]=clampf(B,0,1); + v->color.v[3]=A; +} + diff --git a/apps/tinygl/src/TinyGL/src/list.c b/apps/tinygl/src/TinyGL/src/list.c new file mode 100644 index 0000000..90a5039 --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/list.c @@ -0,0 +1,260 @@ +#include "zgl.h" + +static char *op_table_str[]= +{ +#define ADD_OP(a,b,c) "gl" #a " " #c, + +#include "opinfo.h" +}; + +static void (*op_table_func[])(GLContext *,GLParam *)= +{ +#define ADD_OP(a,b,c) glop ## a , + +#include "opinfo.h" +}; + +static int op_table_size[]= +{ +#define ADD_OP(a,b,c) b + 1 , + +#include "opinfo.h" +}; + + +GLContext *gl_get_context(void) +{ + return gl_ctx; +} + +static GLList *find_list(GLContext *c,unsigned int list) +{ + return c->shared_state.lists[list]; +} + +static void delete_list(GLContext *c,int list) +{ + GLParamBuffer *pb,*pb1; + GLList *l; + + l=find_list(c,list); + assert(l != NULL); + + /* free param buffer */ + pb=l->first_op_buffer; + while (pb!=NULL) { + pb1=pb->next; + gl_free(pb); + pb=pb1; + } + + gl_free(l); + c->shared_state.lists[list]=NULL; +} + +static GLList *alloc_list(GLContext *c,int list) +{ + GLList *l; + GLParamBuffer *ob; + + l=gl_zalloc(sizeof(GLList)); + ob=gl_zalloc(sizeof(GLParamBuffer)); + + ob->next=NULL; + l->first_op_buffer=ob; + + ob->ops[0].op=OP_EndList; + + c->shared_state.lists[list]=l; + return l; +} + + + +/* +void gl_print_op(FILE *f,GLParam *p) +{ +// FIXME + int op; + char *s; + + op=p[0].op; + p++; + s=op_table_str[op]; + while (*s != 0) { + if (*s == '%') { + s++; + switch (*s++) { + case 'f': + fprintf(f,"%g",p[0].f); + break; + default: + fprintf(f,"%d",p[0].i); + break; + } + p++; + } else { + fputc(*s,f); + s++; + } + } + fprintf(f,"\n"); +} +*/ + + +void gl_compile_op(GLContext *c,GLParam *p) +{ + int op,op_size; + GLParamBuffer *ob,*ob1; + int index,i; + + op=p[0].op; + op_size=op_table_size[op]; + index=c->current_op_buffer_index; + ob=c->current_op_buffer; + + /* we should be able to add a NextBuffer opcode */ + if ((index + op_size) > (OP_BUFFER_MAX_SIZE-2)) { + + ob1=gl_zalloc(sizeof(GLParamBuffer)); + ob1->next=NULL; + + ob->next=ob1; + ob->ops[index].op=OP_NextBuffer; + ob->ops[index+1].p=(void *)ob1; + + c->current_op_buffer=ob1; + ob=ob1; + index=0; + } + + for(i=0;iops[index]=p[i]; + index++; + } + c->current_op_buffer_index=index; +} + +void gl_add_op(GLParam *p) +{ + GLContext *c=gl_get_context(); + int op; + + op=p[0].op; + if (c->exec_flag) { + op_table_func[op](c,p); + } + if (c->compile_flag) { + gl_compile_op(c,p); + } + if (c->print_flag) { + //gl_print_op(stderr,p); + // FIXME + } +} + +/* this opcode is never called directly */ +void glopEndList(GLContext *c,GLParam *p) +{ + assert(0); +} + +/* this opcode is never called directly */ +void glopNextBuffer(GLContext *c,GLParam *p) +{ + assert(0); +} + + +void glopCallList(GLContext *c,GLParam *p) +{ + GLList *l; + int list,op; + + list=p[1].ui; + l=find_list(c,list); + if (l == NULL) gl_fatal_error("list %d not defined",list); + p=l->first_op_buffer->ops; + + while (1) { + op=p[0].op; + if (op == OP_EndList) break; + if (op == OP_NextBuffer) { + p=(GLParam *)p[1].p; + } else { + op_table_func[op](c,p); + p+=op_table_size[op]; + } + } +} + + + +void glNewList(unsigned int list,int mode) +{ + GLList *l; + GLContext *c=gl_get_context(); + + assert(mode == GL_COMPILE || mode == GL_COMPILE_AND_EXECUTE); + assert(c->compile_flag == 0); + + l=find_list(c,list); + if (l!=NULL) delete_list(c,list); + l=alloc_list(c,list); + + c->current_op_buffer=l->first_op_buffer; + c->current_op_buffer_index=0; + + c->compile_flag=1; + c->exec_flag=(mode == GL_COMPILE_AND_EXECUTE); +} + +void glEndList(void) +{ + GLContext *c=gl_get_context(); + GLParam p[1]; + + assert(c->compile_flag == 1); + + /* end of list */ + p[0].op=OP_EndList; + gl_compile_op(c,p); + + c->compile_flag=0; + c->exec_flag=1; +} + +int glIsList(unsigned int list) +{ + GLContext *c=gl_get_context(); + GLList *l; + l=find_list(c,list); + return (l != NULL); +} + +unsigned int glGenLists(int range) +{ + GLContext *c=gl_get_context(); + int count,i,list; + GLList **lists; + + lists=c->shared_state.lists; + count=0; + for(i=0;imatrix_model_projection_updated=(c->matrix_mode<=1); +} + + +void glopMatrixMode(GLContext *c,GLParam *p) +{ + int mode=p[1].i; + switch(mode) { + case GL_MODELVIEW: + c->matrix_mode=0; + break; + case GL_PROJECTION: + c->matrix_mode=1; + break; + case GL_TEXTURE: + c->matrix_mode=2; + break; + default: + assert(0); + } +} + +void glopLoadMatrix(GLContext *c,GLParam *p) +{ + M4 *m; + int i; + + GLParam *q; + + m=c->matrix_stack_ptr[c->matrix_mode]; + q=p+1; + + for(i=0;i<4;i++) { + m->m[0][i]=q[0].f; + m->m[1][i]=q[1].f; + m->m[2][i]=q[2].f; + m->m[3][i]=q[3].f; + q+=4; + } + + gl_matrix_update(c); +} + +void glopLoadIdentity(GLContext *c,GLParam *p) +{ + + gl_M4_Id(c->matrix_stack_ptr[c->matrix_mode]); + + gl_matrix_update(c); +} + +void glopMultMatrix(GLContext *c,GLParam *p) +{ + M4 m; + int i; + + GLParam *q; + q=p+1; + + for(i=0;i<4;i++) { + m.m[0][i]=q[0].f; + m.m[1][i]=q[1].f; + m.m[2][i]=q[2].f; + m.m[3][i]=q[3].f; + q+=4; + } + + gl_M4_MulLeft(c->matrix_stack_ptr[c->matrix_mode],&m); + + gl_matrix_update(c); +} + + +void glopPushMatrix(GLContext *c,GLParam *p) +{ + int n=c->matrix_mode; + M4 *m; + + assert( (c->matrix_stack_ptr[n] - c->matrix_stack[n] + 1 ) + < c->matrix_stack_depth_max[n] ); + + m=++c->matrix_stack_ptr[n]; + + gl_M4_Move(&m[0],&m[-1]); + + gl_matrix_update(c); +} + +void glopPopMatrix(GLContext *c,GLParam *p) +{ + int n=c->matrix_mode; + + assert( c->matrix_stack_ptr[n] > c->matrix_stack[n] ); + c->matrix_stack_ptr[n]--; + gl_matrix_update(c); +} + + +void glopRotate(GLContext *c,GLParam *p) +{ + M4 m; + float u[3]; + float angle; + int dir_code; + + angle = p[1].f * M_PI / 180.0; + u[0]=p[2].f; + u[1]=p[3].f; + u[2]=p[4].f; + + /* simple case detection */ + dir_code = ((u[0] != 0)<<2) | ((u[1] != 0)<<1) | (u[2] != 0); + + switch(dir_code) { + case 0: + gl_M4_Id(&m); + break; + case 4: + if (u[0] < 0) angle=-angle; + gl_M4_Rotate(&m,angle,0); + break; + case 2: + if (u[1] < 0) angle=-angle; + gl_M4_Rotate(&m,angle,1); + break; + case 1: + if (u[2] < 0) angle=-angle; + gl_M4_Rotate(&m,angle,2); + break; + default: + { + float cost, sint; + + /* normalize vector */ + float len = u[0]*u[0]+u[1]*u[1]+u[2]*u[2]; + if (len == 0.0f) return; + len = 1.0f / zsqrt(len); + u[0] *= len; + u[1] *= len; + u[2] *= len; + + /* store cos and sin values */ + cost=zcos(angle); + sint=zsin(angle); + + /* fill in the values */ + m.m[3][0]=m.m[3][1]=m.m[3][2]= + m.m[0][3]=m.m[1][3]=m.m[2][3]=0.0f; + m.m[3][3]=1.0f; + + /* do the math */ + m.m[0][0]=u[0]*u[0]+cost*(1-u[0]*u[0]); + m.m[1][0]=u[0]*u[1]*(1-cost)-u[2]*sint; + m.m[2][0]=u[2]*u[0]*(1-cost)+u[1]*sint; + m.m[0][1]=u[0]*u[1]*(1-cost)+u[2]*sint; + m.m[1][1]=u[1]*u[1]+cost*(1-u[1]*u[1]); + m.m[2][1]=u[1]*u[2]*(1-cost)-u[0]*sint; + m.m[0][2]=u[2]*u[0]*(1-cost)-u[1]*sint; + m.m[1][2]=u[1]*u[2]*(1-cost)+u[0]*sint; + m.m[2][2]=u[2]*u[2]+cost*(1-u[2]*u[2]); + } + } + + gl_M4_MulLeft(c->matrix_stack_ptr[c->matrix_mode],&m); + + gl_matrix_update(c); +} + +void glopScale(GLContext *c,GLParam *p) +{ + float *m; + float x=p[1].f,y=p[2].f,z=p[3].f; + + m=&c->matrix_stack_ptr[c->matrix_mode]->m[0][0]; + + m[0] *= x; m[1] *= y; m[2] *= z; + m[4] *= x; m[5] *= y; m[6] *= z; + m[8] *= x; m[9] *= y; m[10] *= z; + m[12] *= x; m[13] *= y; m[14] *= z; + gl_matrix_update(c); +} + +void glopTranslate(GLContext *c,GLParam *p) +{ + float *m; + float x=p[1].f,y=p[2].f,z=p[3].f; + + m=&c->matrix_stack_ptr[c->matrix_mode]->m[0][0]; + + m[3] = m[0] * x + m[1] * y + m[2] * z + m[3]; + m[7] = m[4] * x + m[5] * y + m[6] * z + m[7]; + m[11] = m[8] * x + m[9] * y + m[10] * z + m[11]; + m[15] = m[12] * x + m[13] * y + m[14] * z + m[15]; + + gl_matrix_update(c); +} + + +void glopFrustum(GLContext *c,GLParam *p) +{ + float *r; + M4 m; + float left=p[1].f; + float right=p[2].f; + float bottom=p[3].f; + float top=p[4].f; + float near=p[5].f; + float farp=p[6].f; + float x,y,A,B,C,D; + + x = (2.0*near) / (right-left); + y = (2.0*near) / (top-bottom); + A = (right+left) / (right-left); + B = (top+bottom) / (top-bottom); + C = -(farp+near) / ( farp-near); + D = -(2.0*farp*near) / (farp-near); + + r=&m.m[0][0]; + r[0]= x; r[1]=0; r[2]=A; r[3]=0; + r[4]= 0; r[5]=y; r[6]=B; r[7]=0; + r[8]= 0; r[9]=0; r[10]=C; r[11]=D; + r[12]= 0; r[13]=0; r[14]=-1; r[15]=0; + + gl_M4_MulLeft(c->matrix_stack_ptr[c->matrix_mode],&m); + + gl_matrix_update(c); +} + diff --git a/apps/tinygl/src/TinyGL/src/memory.c b/apps/tinygl/src/TinyGL/src/memory.c new file mode 100644 index 0000000..e1dc3cb --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/memory.c @@ -0,0 +1,21 @@ +/* + * Memory allocator for TinyGL + */ +#include "zgl.h" + +/* modify these functions so that they suit your needs */ + +void gl_free(void *p) +{ + free(p); +} + +void *gl_malloc(int size) +{ + return malloc(size); +} + +void *gl_zalloc(int size) +{ + return calloc(1, size); +} diff --git a/apps/tinygl/src/TinyGL/src/misc.c b/apps/tinygl/src/TinyGL/src/misc.c new file mode 100644 index 0000000..6b82771 --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/misc.c @@ -0,0 +1,147 @@ +#include "zgl.h" +#include "msghandling.h" + +void glopViewport(GLContext *c,GLParam *p) +{ + int xsize,ysize,xmin,ymin,xsize_req,ysize_req; + + xmin=p[1].i; + ymin=p[2].i; + xsize=p[3].i; + ysize=p[4].i; + + /* we may need to resize the zbuffer */ + + if (c->viewport.xmin != xmin || + c->viewport.ymin != ymin || + c->viewport.xsize != xsize || + c->viewport.ysize != ysize) { + + xsize_req=xmin+xsize; + ysize_req=ymin+ysize; + + if (c->gl_resize_viewport && + c->gl_resize_viewport(c,&xsize_req,&ysize_req) != 0) { + gl_fatal_error("glViewport: error while resizing display"); + } + + xsize=xsize_req-xmin; + ysize=ysize_req-ymin; + if (xsize <= 0 || ysize <= 0) { + gl_fatal_error("glViewport: size too small"); + } + + tgl_trace("glViewport: %d %d %d %d\n", + xmin, ymin, xsize, ysize); + c->viewport.xmin=xmin; + c->viewport.ymin=ymin; + c->viewport.xsize=xsize; + c->viewport.ysize=ysize; + + c->viewport.updated=1; + } +} + +void glopEnableDisable(GLContext *c,GLParam *p) +{ + int code=p[1].i; + int v=p[2].i; + + switch(code) { + case GL_CULL_FACE: + c->cull_face_enabled=v; + break; + case GL_LIGHTING: + c->lighting_enabled=v; + break; + case GL_COLOR_MATERIAL: + c->color_material_enabled=v; + break; + case GL_TEXTURE_2D: + c->texture_2d_enabled=v; + break; + case GL_NORMALIZE: + c->normalize_enabled=v; + break; + case GL_DEPTH_TEST: + c->depth_test = v; + break; + case GL_POLYGON_OFFSET_FILL: + if (v) c->offset_states |= TGL_OFFSET_FILL; + else c->offset_states &= ~TGL_OFFSET_FILL; + break; + case GL_POLYGON_OFFSET_POINT: + if (v) c->offset_states |= TGL_OFFSET_POINT; + else c->offset_states &= ~TGL_OFFSET_POINT; + break; + case GL_POLYGON_OFFSET_LINE: + if (v) c->offset_states |= TGL_OFFSET_LINE; + else c->offset_states &= ~TGL_OFFSET_LINE; + break; + default: + if (code>=GL_LIGHT0 && codecurrent_shade_model=code; +} + +void glopCullFace(GLContext *c,GLParam *p) +{ + int code=p[1].i; + c->current_cull_face=code; +} + +void glopFrontFace(GLContext *c,GLParam *p) +{ + int code=p[1].i; + c->current_front_face=code; +} + +void glopPolygonMode(GLContext *c,GLParam *p) +{ + int face=p[1].i; + int mode=p[2].i; + + switch(face) { + case GL_BACK: + c->polygon_mode_back=mode; + break; + case GL_FRONT: + c->polygon_mode_front=mode; + break; + case GL_FRONT_AND_BACK: + c->polygon_mode_front=mode; + c->polygon_mode_back=mode; + break; + default: + assert(0); + } +} + +void glopHint(GLContext *c,GLParam *p) +{ +#if 0 + int target=p[1].i; + int mode=p[2].i; + + /* do nothing */ +#endif +} + +void +glopPolygonOffset(GLContext *c, GLParam *p) +{ + c->offset_factor = p[1].f; + c->offset_units = p[2].f; +} diff --git a/apps/tinygl/src/TinyGL/src/msghandling.c b/apps/tinygl/src/TinyGL/src/msghandling.c new file mode 100644 index 0000000..0748a88 --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/msghandling.c @@ -0,0 +1,52 @@ +//#include +//#include + +#define NDEBUG + +#ifdef NDEBUG +#define NO_DEBUG_OUTPUT +#endif + +/* Use this function to output messages when something unexpected + happens (which might be an indication of an error). *Don't* use it + when there's internal errors in the code - these should be handled + by asserts. */ +void +tgl_warning(const char *format, ...) +{ +#ifndef NO_DEBUG_OUTPUT + va_list args; + va_start(args, format); + fprintf(stderr, "*WARNING* "); + vfprintf(stderr, format, args); + va_end(args); +#endif /* !NO_DEBUG_OUTPUT */ +} + +/* This function should be used for debug output only. */ +void +tgl_trace(const char *format, ...) +{ +#ifndef NO_DEBUG_OUTPUT + va_list args; + va_start(args, format); + fprintf(stderr, "*DEBUG* "); + vfprintf(stderr, format, args); + va_end(args); +#endif /* !NO_DEBUG_OUTPUT */ +} + +/* Use this function to output info about things in the code which + should be fixed (missing handling of special cases, important + features not implemented, known bugs/buglets, ...). */ +void +tgl_fixme(const char *format, ...) +{ +#ifndef NO_DEBUG_OUTPUT + va_list args; + va_start(args, format); + fprintf(stderr, "*FIXME* "); + vfprintf(stderr, format, args); + va_end(args); +#endif /* !NO_DEBUG_OUTPUT */ +} diff --git a/apps/tinygl/src/TinyGL/src/msghandling.h b/apps/tinygl/src/TinyGL/src/msghandling.h new file mode 100644 index 0000000..ebe4548 --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/msghandling.h @@ -0,0 +1,8 @@ +#ifndef _msghandling_h_ +#define _msghandling_h_ + +extern void tgl_warning(const char *text, ...); +extern void tgl_trace(const char *text, ...); +extern void tgl_fixme(const char *text, ...); + +#endif /* _msghandling_h_ */ diff --git a/apps/tinygl/src/TinyGL/src/nglx.c b/apps/tinygl/src/TinyGL/src/nglx.c new file mode 100644 index 0000000..26f356c --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/nglx.c @@ -0,0 +1,128 @@ +/* simple glx like driver for TinyGL and Nano X */ +#include +#include +#include +#include "zgl.h" + +typedef struct { + GLContext *gl_context; + int xsize,ysize; + GR_DRAW_ID drawable; + GR_GC_ID gc; + int pixtype; /* pixel type in TinyGL */ +} TinyNGLXContext; + +NGLXContext nglXCreateContext(NGLXContext shareList, int flags) +{ + TinyNGLXContext *ctx; + + if (shareList != NULL) { + gl_fatal_error("No sharing available in TinyGL"); + } + ctx=gl_malloc(sizeof(TinyNGLXContext)); + if (!ctx) + return NULL; + ctx->gl_context=NULL; + return (NGLXContext) ctx; +} + +void glXDestroyContext( NGLXContext ctx1 ) +{ + TinyNGLXContext *ctx = (TinyNGLXContext *) ctx1; + if (ctx->gl_context != NULL) { + glClose(); + } + gl_free(ctx); +} + + +/* resize the glx viewport : we try to use the xsize and ysize + given. We return the effective size which is guaranted to be smaller */ + +static int glX_resize_viewport(GLContext *c,int *xsize_ptr,int *ysize_ptr) +{ + TinyNGLXContext *ctx; + int xsize,ysize; + + ctx=(TinyNGLXContext *)c->opaque; + + xsize=*xsize_ptr; + ysize=*ysize_ptr; + + /* we ensure that xsize and ysize are multiples of 2 for the zbuffer. + TODO: find a better solution */ + xsize&=~3; + ysize&=~3; + + if (xsize == 0 || ysize == 0) return -1; + + *xsize_ptr=xsize; + *ysize_ptr=ysize; + + ctx->xsize=xsize; + ctx->ysize=ysize; + + /* resize the Z buffer */ + ZB_resize(c->zb,NULL,xsize,ysize); + return 0; +} + +/* we assume here that drawable is a window */ +int nglXMakeCurrent( NGLXDrawable drawable, + NGLXContext ctx1) +{ + TinyNGLXContext *ctx = (TinyNGLXContext *) ctx1; + int mode, xsize, ysize; + ZBuffer *zb; + GR_WINDOW_INFO win_info; + + if (ctx->gl_context == NULL) { + /* create the TinyGL context */ + GrGetWindowInfo(drawable, &win_info); + + xsize = win_info.width; + ysize = win_info.height; + + /* currently, we only support 16 bit rendering */ + mode = ZB_MODE_5R6G5B; + zb=ZB_open(xsize,ysize,mode,0,NULL,NULL,NULL); + if (zb == NULL) { + fprintf(stderr, "Error while initializing Z buffer\n"); + exit(1); + } + + ctx->pixtype = MWPF_TRUECOLOR565; + + /* create a gc */ + ctx->gc = GrNewGC(); + + /* initialisation of the TinyGL interpreter */ + glInit(zb); + ctx->gl_context=gl_get_context(); + ctx->gl_context->opaque=(void *) ctx; + ctx->gl_context->gl_resize_viewport=glX_resize_viewport; + + /* set the viewport : we force a call to glX_resize_viewport */ + ctx->gl_context->viewport.xsize=-1; + ctx->gl_context->viewport.ysize=-1; + + glViewport(0, 0, xsize, ysize); + } + + return 1; +} + +void nglXSwapBuffers( NGLXDrawable drawable ) +{ + GLContext *gl_context; + TinyNGLXContext *ctx; + + /* retrieve the current NGLXContext */ + gl_context=gl_get_context(); + ctx=(TinyNGLXContext *)gl_context->opaque; + + GrArea(drawable, ctx->gc, 0, 0, ctx->xsize, + ctx->ysize, ctx->gl_context->zb->pbuf, ctx->pixtype); +} + + diff --git a/apps/tinygl/src/TinyGL/src/opinfo.h b/apps/tinygl/src/TinyGL/src/opinfo.h new file mode 100644 index 0000000..e57344e --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/opinfo.h @@ -0,0 +1,71 @@ + + +ADD_OP(Color,7,"%f %f %f %f %d %d %d") +ADD_OP(TexCoord,4,"%f %f %f %f") +ADD_OP(EdgeFlag,1,"%d") +ADD_OP(Normal,3,"%f %f %f") + +ADD_OP(Begin,1,"%C") +ADD_OP(Vertex,4,"%f %f %f %f") +ADD_OP(End,0,"") + +ADD_OP(EnableDisable,2,"%C %d") + +ADD_OP(MatrixMode,1,"%C") +ADD_OP(LoadMatrix,16,"") +ADD_OP(LoadIdentity,0,"") +ADD_OP(MultMatrix,16,"") +ADD_OP(PushMatrix,0,"") +ADD_OP(PopMatrix,0,"") +ADD_OP(Rotate,4,"%f %f %f %f") +ADD_OP(Translate,3,"%f %f %f") +ADD_OP(Scale,3,"%f %f %f") + +ADD_OP(Viewport,4,"%d %d %d %d") +ADD_OP(Frustum,6,"%f %f %f %f %f %f") + +ADD_OP(Material,6,"%C %C %f %f %f %f") +ADD_OP(ColorMaterial,2,"%C %C") +ADD_OP(Light,6,"%C %C %f %f %f %f") +ADD_OP(LightModel,5,"%C %f %f %f %f") + +ADD_OP(Clear,1,"%d") +ADD_OP(ClearColor,4,"%f %f %f %f") +ADD_OP(ClearDepth,1,"%f") + +ADD_OP(InitNames,0,"") +ADD_OP(PushName,1,"%d") +ADD_OP(PopName,0,"") +ADD_OP(LoadName,1,"%d") + +ADD_OP(TexImage2D,9,"%d %d %d %d %d %d %d %d %d") +ADD_OP(BindTexture,2,"%C %d") +ADD_OP(TexEnv,7,"%C %C %C %f %f %f %f") +ADD_OP(TexParameter,7,"%C %C %C %f %f %f %f") +ADD_OP(PixelStore,2,"%C %C") + +ADD_OP(ShadeModel,1,"%C") +ADD_OP(CullFace,1,"%C") +ADD_OP(FrontFace,1,"%C") +ADD_OP(PolygonMode,2,"%C %C") + +ADD_OP(CallList,1,"%d") +ADD_OP(Hint,2,"%C %C") + +/* special opcodes */ +ADD_OP(EndList,0,"") +ADD_OP(NextBuffer,1,"%p") + +/* opengl 1.1 arrays */ +ADD_OP(ArrayElement, 1, "%d") +ADD_OP(EnableClientState, 1, "%C") +ADD_OP(DisableClientState, 1, "%C") +ADD_OP(VertexPointer, 4, "%d %C %d %p") +ADD_OP(ColorPointer, 4, "%d %C %d %p") +ADD_OP(NormalPointer, 3, "%C %d %p") +ADD_OP(TexCoordPointer, 4, "%d %C %d %p") + +/* opengl 1.1 polygon offset */ +ADD_OP(PolygonOffset, 2, "%f %f") + +#undef ADD_OP diff --git a/apps/tinygl/src/TinyGL/src/oscontext.c b/apps/tinygl/src/TinyGL/src/oscontext.c new file mode 100644 index 0000000..a16eecb --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/oscontext.c @@ -0,0 +1,85 @@ +#include +#include "zbuffer.h" +#include "zgl.h" +#include +//#include +//#include + +static int buffercnt = 0; + +ostgl_context * +ostgl_create_context(const int xsize, + const int ysize, + const int depth, + void **framebuffers, + const int numbuffers) +{ + ostgl_context *context; + int i; + ZBuffer *zb; + + assert(depth == 16); /* support for other depths must include bpp + convertion */ + assert(numbuffers >= 1); + + context = gl_malloc(sizeof(ostgl_context)); + assert(context); + context->zbs = gl_malloc(sizeof(void*)*numbuffers); + context->framebuffers = gl_malloc(sizeof(void*)*numbuffers); + + assert(context->zbs != NULL && context->framebuffers != NULL); + + for (i = 0; i < numbuffers; i++) { + context->framebuffers[i] = framebuffers[i]; + zb = ZB_open(xsize, ysize, ZB_MODE_5R6G5B, 0, NULL, NULL, framebuffers[i]); + if (zb == NULL) { + //fprintf(stderr, "Error while initializing Z buffer\n"); + //exit(1); + //FIXME + } + context->zbs[i] = zb; + } + if (++buffercnt == 1) { + glInit(context->zbs[0]); + } + context->xsize = xsize; + context->ysize = ysize; + context->numbuffers = numbuffers; + return context; +} + +void +ostgl_delete_context(ostgl_context *context) +{ + int i; + for (i = 0; i < context->numbuffers; i++) { + ZB_close(context->zbs[i]); + } + gl_free(context->zbs); + gl_free(context->framebuffers); + gl_free(context); + + if (--buffercnt == 0) { + glClose(); + } +} + +void +ostgl_make_current(ostgl_context *oscontext, const int idx) +{ + GLContext *context = gl_get_context(); + assert(idx < oscontext->numbuffers); + context->zb = oscontext->zbs[idx]; +} + +void +ostgl_resize(ostgl_context *context, + const int xsize, + const int ysize, + void **framebuffers) +{ + int i; + for (i = 0; i < context->numbuffers; i++) { + ZB_resize(context->zbs[i], framebuffers[i], xsize, ysize); + } +} diff --git a/apps/tinygl/src/TinyGL/src/select.c b/apps/tinygl/src/TinyGL/src/select.c new file mode 100644 index 0000000..bf416ee --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/select.c @@ -0,0 +1,114 @@ +#include "zgl.h" + +int glRenderMode(int mode) +{ + GLContext *c=gl_get_context(); + int result=0; + + switch(c->render_mode) { + case GL_RENDER: + break; + case GL_SELECT: + if (c->select_overflow) { + result=-c->select_hits; + } else { + result=c->select_hits; + } + c->select_overflow=0; + c->select_ptr=c->select_buffer; + c->name_stack_size=0; + break; + default: + assert(0); + } + switch(mode) { + case GL_RENDER: + c->render_mode=GL_RENDER; + break; + case GL_SELECT: + c->render_mode=GL_SELECT; + assert( c->select_buffer != NULL); + c->select_ptr=c->select_buffer; + c->select_hits=0; + c->select_overflow=0; + c->select_hit=NULL; + break; + default: + assert(0); + } + return result; +} + +void glSelectBuffer(int size,unsigned int *buf) +{ + GLContext *c=gl_get_context(); + + assert(c->render_mode != GL_SELECT); + + c->select_buffer=buf; + c->select_size=size; +} + + +void glopInitNames(GLContext *c,GLParam *p) +{ + if (c->render_mode == GL_SELECT) { + c->name_stack_size=0; + c->select_hit=NULL; + } +} + +void glopPushName(GLContext *c,GLParam *p) +{ + if (c->render_mode == GL_SELECT) { + assert(c->name_stack_sizename_stack[c->name_stack_size++]=p[1].i; + c->select_hit=NULL; + } +} + +void glopPopName(GLContext *c,GLParam *p) +{ + if (c->render_mode == GL_SELECT) { + assert(c->name_stack_size>0); + c->name_stack_size--; + c->select_hit=NULL; + } +} + +void glopLoadName(GLContext *c,GLParam *p) +{ + if (c->render_mode == GL_SELECT) { + assert(c->name_stack_size>0); + c->name_stack[c->name_stack_size-1]=p[1].i; + c->select_hit=NULL; + } +} + +void gl_add_select(GLContext *c,unsigned int zmin,unsigned int zmax) +{ + unsigned int *ptr; + int n,i; + + if (!c->select_overflow) { + if (c->select_hit==NULL) { + n=c->name_stack_size; + if ((c->select_ptr-c->select_buffer+3+n) > + c->select_size) { + c->select_overflow=1; + } else { + ptr=c->select_ptr; + c->select_hit=ptr; + *ptr++=c->name_stack_size; + *ptr++=zmin; + *ptr++=zmax; + for(i=0;iname_stack[i]; + c->select_ptr=ptr; + c->select_hits++; + } + } else { + if (zminselect_hit[1]) c->select_hit[1]=zmin; + if (zmax>c->select_hit[2]) c->select_hit[2]=zmax; + } + } +} diff --git a/apps/tinygl/src/TinyGL/src/specbuf.c b/apps/tinygl/src/TinyGL/src/specbuf.c new file mode 100644 index 0000000..b168065 --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/specbuf.c @@ -0,0 +1,52 @@ +#include "zgl.h" +#include "msghandling.h" +//#include +//#include + +static void calc_buf(GLSpecBuf *buf, const float shininess) +{ + int i; + float val, inc; + val = 0.0f; + inc = 1.0f/SPECULAR_BUFFER_SIZE; + for (i = 0; i <= SPECULAR_BUFFER_SIZE; i++) { + buf->buf[i] = zpow(val, shininess); + val += inc; + } +} + +GLSpecBuf * +specbuf_get_buffer(GLContext *c, const int shininess_i, + const float shininess) +{ + GLSpecBuf *found, *oldest; + found = oldest = c->specbuf_first; + while (found && found->shininess_i != shininess_i) { + if (found->last_used < oldest->last_used) { + oldest = found; + } + found = found->next; + } + if (found) { /* hey, found one! */ + found->last_used = c->specbuf_used_counter++; + return found; + } + if (oldest == NULL || c->specbuf_num_buffers < MAX_SPECULAR_BUFFERS) { + /* create new buffer */ + GLSpecBuf *buf = gl_malloc(sizeof(GLSpecBuf)); + if (!buf) gl_fatal_error("could not allocate specular buffer"); + c->specbuf_num_buffers++; + buf->next = c->specbuf_first; + c->specbuf_first = buf; + buf->last_used = c->specbuf_used_counter++; + buf->shininess_i = shininess_i; + calc_buf(buf, shininess); + return buf; + } + /* overwrite the lru buffer */ + /*tgl_trace("overwriting spec buffer :(\n");*/ + oldest->shininess_i = shininess_i; + oldest->last_used = c->specbuf_used_counter++; + calc_buf(oldest, shininess); + return oldest; +} diff --git a/apps/tinygl/src/TinyGL/src/specbuf.h b/apps/tinygl/src/TinyGL/src/specbuf.h new file mode 100644 index 0000000..ed1bacf --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/specbuf.h @@ -0,0 +1,22 @@ +#ifndef _tgl_specbuf_h_ +#define _tgl_specbuf_h_ + +/* Max # of specular light pow buffers */ +#define MAX_SPECULAR_BUFFERS 8 +/* # of entries in specular buffer */ +#define SPECULAR_BUFFER_SIZE 1024 +/* specular buffer granularity */ +#define SPECULAR_BUFFER_RESOLUTION 1024 + +typedef struct GLSpecBuf { + int shininess_i; + int last_used; + float buf[SPECULAR_BUFFER_SIZE+1]; + struct GLSpecBuf *next; +} GLSpecBuf; + +GLSpecBuf *specbuf_get_buffer(GLContext *c, const int shininess_i, + const float shininess); +void specbuf_cleanup(GLContext *c); /* free all memory used */ + +#endif /* _tgl_specbuf_h_ */ diff --git a/apps/tinygl/src/TinyGL/src/texture.c b/apps/tinygl/src/TinyGL/src/texture.c new file mode 100644 index 0000000..bec9ac5 --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/texture.c @@ -0,0 +1,229 @@ +/* + * Texture Manager + */ + +#include "zgl.h" + +static GLTexture *find_texture(GLContext *c,int h) +{ + GLTexture *t; + + t=c->shared_state.texture_hash_table[h % TEXTURE_HASH_TABLE_SIZE]; + while (t!=NULL) { + if (t->handle == h) return t; + t=t->next; + } + return NULL; +} + +static void free_texture(GLContext *c,int h) +{ + GLTexture *t,**ht; + GLImage *im; + int i; + + t=find_texture(c,h); + if (t->prev==NULL) { + ht=&c->shared_state.texture_hash_table + [t->handle % TEXTURE_HASH_TABLE_SIZE]; + *ht=t->next; + } else { + t->prev->next=t->next; + } + if (t->next!=NULL) t->next->prev=t->prev; + + for(i=0;iimages[i]; + if (im->pixmap != NULL) gl_free(im->pixmap); + } + + gl_free(t); +} + +GLTexture *alloc_texture(GLContext *c,int h) +{ + GLTexture *t,**ht; + + t=gl_zalloc(sizeof(GLTexture)); + + ht=&c->shared_state.texture_hash_table[h % TEXTURE_HASH_TABLE_SIZE]; + + t->next=*ht; + t->prev=NULL; + if (t->next != NULL) t->next->prev=t; + *ht=t; + + t->handle=h; + + return t; +} + + +void glInitTextures(GLContext *c) +{ + /* textures */ + + c->texture_2d_enabled=0; + c->current_texture=find_texture(c,0); +} + +void glGenTextures(int n, unsigned int *textures) +{ + GLContext *c=gl_get_context(); + int max,i; + GLTexture *t; + + max=0; + for(i=0;ishared_state.texture_hash_table[i]; + while (t!=NULL) { + if (t->handle>max) max=t->handle; + t=t->next; + } + + } + for(i=0;icurrent_texture) { + glBindTexture(GL_TEXTURE_2D,0); + } + free_texture(c,textures[i]); + } + } +} + + +void glopBindTexture(GLContext *c,GLParam *p) +{ + int target=p[1].i; + int texture=p[2].i; + GLTexture *t; + + assert(target == GL_TEXTURE_2D && texture >= 0); + + t=find_texture(c,texture); + if (t==NULL) { + t=alloc_texture(c,texture); + } + c->current_texture=t; +} + +void glopTexImage2D(GLContext *c,GLParam *p) +{ + int target=p[1].i; + int level=p[2].i; + int components=p[3].i; + int width=p[4].i; + int height=p[5].i; + int border=p[6].i; + int format=p[7].i; + int type=p[8].i; + void *pixels=p[9].p; + GLImage *im; + unsigned char *pixels1; + int do_free; + + if (!(target == GL_TEXTURE_2D && level == 0 && components == 3 && + border == 0 && format == GL_RGB && + type == GL_UNSIGNED_BYTE)) { + gl_fatal_error("glTexImage2D: combinaison of parameters not handled"); + } + + do_free=0; + if (width != 256 || height != 256) { + pixels1 = gl_malloc(256 * 256 * 3); + /* no interpolation is done here to respect the original image aliasing ! */ + gl_resizeImageNoInterpolate(pixels1,256,256,pixels,width,height); + do_free=1; + width=256; + height=256; + } else { + pixels1=pixels; + } + + im=&c->current_texture->images[level]; + im->xsize=width; + im->ysize=height; + if (im->pixmap!=NULL) gl_free(im->pixmap); +#if TGL_FEATURE_RENDER_BITS == 24 + im->pixmap=gl_malloc(width*height*3); + if(im->pixmap) { + memcpy(im->pixmap,pixels1,width*height*3); + } +#elif TGL_FEATURE_RENDER_BITS == 32 + im->pixmap=gl_malloc(width*height*4); + if(im->pixmap) { + gl_convertRGB_to_8A8R8G8B(im->pixmap,pixels1,width,height); + } +#elif TGL_FEATURE_RENDER_BITS == 16 + im->pixmap=gl_malloc(width*height*2); + if(im->pixmap) { + gl_convertRGB_to_5R6G5B(im->pixmap,pixels1,width,height); + } +#else +#error TODO +#endif + if (do_free) gl_free(pixels1); +} + + +/* TODO: not all tests are done */ +void glopTexEnv(GLContext *c,GLParam *p) +{ + int target=p[1].i; + int pname=p[2].i; + int param=p[3].i; + + if (target != GL_TEXTURE_ENV) { + error: + gl_fatal_error("glTexParameter: unsupported option"); + } + + if (pname != GL_TEXTURE_ENV_MODE) goto error; + + if (param != GL_DECAL) goto error; +} + +/* TODO: not all tests are done */ +void glopTexParameter(GLContext *c,GLParam *p) +{ + int target=p[1].i; + int pname=p[2].i; + int param=p[3].i; + + if (target != GL_TEXTURE_2D) { + error: + gl_fatal_error("glTexParameter: unsupported option"); + } + + switch(pname) { + case GL_TEXTURE_WRAP_S: + case GL_TEXTURE_WRAP_T: + if (param != GL_REPEAT) goto error; + break; + } +} + +void glopPixelStore(GLContext *c,GLParam *p) +{ + int pname=p[1].i; + int param=p[2].i; + + if (pname != GL_UNPACK_ALIGNMENT || + param != 1) { + gl_fatal_error("glPixelStore: unsupported option"); + } +} diff --git a/apps/tinygl/src/TinyGL/src/vertex.c b/apps/tinygl/src/TinyGL/src/vertex.c new file mode 100644 index 0000000..b194e97 --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/vertex.c @@ -0,0 +1,364 @@ +#include "zgl.h" + +void glopNormal(GLContext * c, GLParam * p) +{ + V3 v; + + v.X = p[1].f; + v.Y = p[2].f; + v.Z = p[3].f; + + c->current_normal.X = v.X; + c->current_normal.Y = v.Y; + c->current_normal.Z = v.Z; + c->current_normal.W = 0; +} + +void glopTexCoord(GLContext * c, GLParam * p) +{ + c->current_tex_coord.X = p[1].f; + c->current_tex_coord.Y = p[2].f; + c->current_tex_coord.Z = p[3].f; + c->current_tex_coord.W = p[4].f; +} + +void glopEdgeFlag(GLContext * c, GLParam * p) +{ + c->current_edge_flag = p[1].i; +} + +void glopColor(GLContext * c, GLParam * p) +{ + + c->current_color.X = p[1].f; + c->current_color.Y = p[2].f; + c->current_color.Z = p[3].f; + c->current_color.W = p[4].f; + c->longcurrent_color[0] = p[5].ui; + c->longcurrent_color[1] = p[6].ui; + c->longcurrent_color[2] = p[7].ui; + + if (c->color_material_enabled) { + GLParam q[7]; + q[0].op = OP_Material; + q[1].i = c->current_color_material_mode; + q[2].i = c->current_color_material_type; + q[3].f = p[1].f; + q[4].f = p[2].f; + q[5].f = p[3].f; + q[6].f = p[4].f; + glopMaterial(c, q); + } +} + + +void gl_eval_viewport(GLContext * c) +{ + GLViewport *v; + float zsize = (1 << (ZB_Z_BITS + ZB_POINT_Z_FRAC_BITS)); + + v = &c->viewport; + + v->trans.X = ((v->xsize - 0.5) / 2.0) + v->xmin; + v->trans.Y = ((v->ysize - 0.5) / 2.0) + v->ymin; + v->trans.Z = ((zsize - 0.5) / 2.0) + ((1 << ZB_POINT_Z_FRAC_BITS)) / 2; + + v->scale.X = (v->xsize - 0.5) / 2.0; + v->scale.Y = -(v->ysize - 0.5) / 2.0; + v->scale.Z = -((zsize - 0.5) / 2.0); +} + +void glopBegin(GLContext * c, GLParam * p) +{ + int type; + M4 tmp; + + assert(c->in_begin == 0); + + type = p[1].i; + c->begin_type = type; + c->in_begin = 1; + c->vertex_n = 0; + c->vertex_cnt = 0; + + if (c->matrix_model_projection_updated) { + + if (c->lighting_enabled) { + /* precompute inverse modelview */ + gl_M4_Inv(&tmp, c->matrix_stack_ptr[0]); + gl_M4_Transpose(&c->matrix_model_view_inv, &tmp); + } else { + float *m = &c->matrix_model_projection.m[0][0]; + /* precompute projection matrix */ + gl_M4_Mul(&c->matrix_model_projection, + c->matrix_stack_ptr[1], + c->matrix_stack_ptr[0]); + /* test to accelerate computation */ + c->matrix_model_projection_no_w_transform = 0; + if (m[12] == 0.0 && m[13] == 0.0 && m[14] == 0.0) + c->matrix_model_projection_no_w_transform = 1; + } + + /* test if the texture matrix is not Identity */ + c->apply_texture_matrix = !gl_M4_IsId(c->matrix_stack_ptr[2]); + + c->matrix_model_projection_updated = 0; + } + /* viewport */ + if (c->viewport.updated) { + gl_eval_viewport(c); + c->viewport.updated = 0; + } + /* triangle drawing functions */ + if (c->render_mode == GL_SELECT) { + c->draw_triangle_front = gl_draw_triangle_select; + c->draw_triangle_back = gl_draw_triangle_select; + } else { + switch (c->polygon_mode_front) { + case GL_POINT: + c->draw_triangle_front = gl_draw_triangle_point; + break; + case GL_LINE: + c->draw_triangle_front = gl_draw_triangle_line; + break; + default: + c->draw_triangle_front = gl_draw_triangle_fill; + break; + } + + switch (c->polygon_mode_back) { + case GL_POINT: + c->draw_triangle_back = gl_draw_triangle_point; + break; + case GL_LINE: + c->draw_triangle_back = gl_draw_triangle_line; + break; + default: + c->draw_triangle_back = gl_draw_triangle_fill; + break; + } + } +} + +/* coords, tranformation , clip code and projection */ +/* TODO : handle all cases */ +static inline void gl_vertex_transform(GLContext * c, GLVertex * v) +{ + float *m; + V4 *n; + + if (c->lighting_enabled) { + /* eye coordinates needed for lighting */ + + m = &c->matrix_stack_ptr[0]->m[0][0]; + v->ec.X = (v->coord.X * m[0] + v->coord.Y * m[1] + + v->coord.Z * m[2] + m[3]); + v->ec.Y = (v->coord.X * m[4] + v->coord.Y * m[5] + + v->coord.Z * m[6] + m[7]); + v->ec.Z = (v->coord.X * m[8] + v->coord.Y * m[9] + + v->coord.Z * m[10] + m[11]); + v->ec.W = (v->coord.X * m[12] + v->coord.Y * m[13] + + v->coord.Z * m[14] + m[15]); + + /* projection coordinates */ + m = &c->matrix_stack_ptr[1]->m[0][0]; + v->pc.X = (v->ec.X * m[0] + v->ec.Y * m[1] + + v->ec.Z * m[2] + v->ec.W * m[3]); + v->pc.Y = (v->ec.X * m[4] + v->ec.Y * m[5] + + v->ec.Z * m[6] + v->ec.W * m[7]); + v->pc.Z = (v->ec.X * m[8] + v->ec.Y * m[9] + + v->ec.Z * m[10] + v->ec.W * m[11]); + v->pc.W = (v->ec.X * m[12] + v->ec.Y * m[13] + + v->ec.Z * m[14] + v->ec.W * m[15]); + + m = &c->matrix_model_view_inv.m[0][0]; + n = &c->current_normal; + + v->normal.X = (n->X * m[0] + n->Y * m[1] + n->Z * m[2]); + v->normal.Y = (n->X * m[4] + n->Y * m[5] + n->Z * m[6]); + v->normal.Z = (n->X * m[8] + n->Y * m[9] + n->Z * m[10]); + + if (c->normalize_enabled) { + gl_V3_Norm(&v->normal); + } + } else { + /* no eye coordinates needed, no normal */ + /* NOTE: W = 1 is assumed */ + m = &c->matrix_model_projection.m[0][0]; + + v->pc.X = (v->coord.X * m[0] + v->coord.Y * m[1] + + v->coord.Z * m[2] + m[3]); + v->pc.Y = (v->coord.X * m[4] + v->coord.Y * m[5] + + v->coord.Z * m[6] + m[7]); + v->pc.Z = (v->coord.X * m[8] + v->coord.Y * m[9] + + v->coord.Z * m[10] + m[11]); + if (c->matrix_model_projection_no_w_transform) { + v->pc.W = m[15]; + } else { + v->pc.W = (v->coord.X * m[12] + v->coord.Y * m[13] + + v->coord.Z * m[14] + m[15]); + } + } + + v->clip_code = gl_clipcode(v->pc.X, v->pc.Y, v->pc.Z, v->pc.W); +} + +void glopVertex(GLContext * c, GLParam * p) +{ + GLVertex *v; + int n, i, cnt; + + assert(c->in_begin != 0); + + n = c->vertex_n; + cnt = c->vertex_cnt; + cnt++; + c->vertex_cnt = cnt; + + /* quick fix to avoid crashes on large polygons */ + if (n >= c->vertex_max) { + GLVertex *newarray; + c->vertex_max <<= 1; /* just double size */ + newarray = gl_malloc(sizeof(GLVertex) * c->vertex_max); + if (!newarray) { + gl_fatal_error("unable to allocate GLVertex array.\n"); + } + memcpy(newarray, c->vertex, n * sizeof(GLVertex)); + gl_free(c->vertex); + c->vertex = newarray; + } + /* new vertex entry */ + v = &c->vertex[n]; + n++; + + v->coord.X = p[1].f; + v->coord.Y = p[2].f; + v->coord.Z = p[3].f; + v->coord.W = p[4].f; + + gl_vertex_transform(c, v); + + /* color */ + + if (c->lighting_enabled) { + gl_shade_vertex(c, v); + } else { + v->color = c->current_color; + } + + /* tex coords */ + + if (c->texture_2d_enabled) { + if (c->apply_texture_matrix) { + gl_M4_MulV4(&v->tex_coord, c->matrix_stack_ptr[2], &c->current_tex_coord); + } else { + v->tex_coord = c->current_tex_coord; + } + } + /* precompute the mapping to the viewport */ + if (v->clip_code == 0) + gl_transform_to_viewport(c, v); + + /* edge flag */ + + v->edge_flag = c->current_edge_flag; + + switch (c->begin_type) { + case GL_POINTS: + gl_draw_point(c, &c->vertex[0]); + n = 0; + break; + + case GL_LINES: + if (n == 2) { + gl_draw_line(c, &c->vertex[0], &c->vertex[1]); + n = 0; + } + break; + case GL_LINE_STRIP: + case GL_LINE_LOOP: + if (n == 1) { + c->vertex[2] = c->vertex[0]; + } else if (n == 2) { + gl_draw_line(c, &c->vertex[0], &c->vertex[1]); + c->vertex[0] = c->vertex[1]; + n = 1; + } + break; + + case GL_TRIANGLES: + if (n == 3) { + gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]); + n = 0; + } + break; + case GL_TRIANGLE_STRIP: + if (cnt >= 3) { + if (n == 3) + n = 0; + /* needed to respect triangle orientation */ + switch(cnt & 1) { + case 0: + gl_draw_triangle(c,&c->vertex[2],&c->vertex[1],&c->vertex[0]); + break; + default: + case 1: + gl_draw_triangle(c,&c->vertex[0],&c->vertex[1],&c->vertex[2]); + break; + } + } + break; + case GL_TRIANGLE_FAN: + if (n == 3) { + gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]); + c->vertex[1] = c->vertex[2]; + n = 2; + } + break; + + case GL_QUADS: + if (n == 4) { + c->vertex[2].edge_flag = 0; + gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]); + c->vertex[2].edge_flag = 1; + c->vertex[0].edge_flag = 0; + gl_draw_triangle(c, &c->vertex[0], &c->vertex[2], &c->vertex[3]); + n = 0; + } + break; + + case GL_QUAD_STRIP: + if (n == 4) { + gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]); + gl_draw_triangle(c, &c->vertex[1], &c->vertex[3], &c->vertex[2]); + for (i = 0; i < 2; i++) + c->vertex[i] = c->vertex[i + 2]; + n = 2; + } + break; + case GL_POLYGON: + break; + default: + gl_fatal_error("glBegin: type %x not handled\n", c->begin_type); + } + + c->vertex_n = n; +} + +void glopEnd(GLContext * c, GLParam * param) +{ + assert(c->in_begin == 1); + + if (c->begin_type == GL_LINE_LOOP) { + if (c->vertex_cnt >= 3) { + gl_draw_line(c, &c->vertex[0], &c->vertex[2]); + } + } else if (c->begin_type == GL_POLYGON) { + int i = c->vertex_cnt; + while (i >= 3) { + i--; + gl_draw_triangle(c, &c->vertex[i], &c->vertex[0], &c->vertex[i - 1]); + } + } + c->in_begin = 0; +} diff --git a/apps/tinygl/src/TinyGL/src/zbuffer.c b/apps/tinygl/src/TinyGL/src/zbuffer.c new file mode 100644 index 0000000..8d7aefd --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/zbuffer.c @@ -0,0 +1,518 @@ +/* + + * Z buffer: 16 bits Z / 16 bits color + * + */ +//#include +//#include +//#include +//#include +#include "zgl.h" +#include "zbuffer.h" + +ZBuffer *ZB_open(int xsize, int ysize, int mode, + int nb_colors, + unsigned char *color_indexes, + int *color_table, + void *frame_buffer) +{ + ZBuffer *zb; + int size; + + zb = gl_malloc(sizeof(ZBuffer)); + if (zb == NULL) + return NULL; + + zb->xsize = xsize; + zb->ysize = ysize; + zb->mode = mode; + zb->linesize = (xsize * PSZB + 3) & ~3; + + switch (mode) { +#ifdef TGL_FEATURE_8_BITS + case ZB_MODE_INDEX: + ZB_initDither(zb, nb_colors, color_indexes, color_table); + break; +#endif +#ifdef TGL_FEATURE_32_BITS + case ZB_MODE_RGBA: +#endif +#ifdef TGL_FEATURE_24_BITS + case ZB_MODE_RGB24: +#endif + case ZB_MODE_5R6G5B: + zb->nb_colors = 0; + break; + default: + goto error; + } + + size = zb->xsize * zb->ysize * sizeof(unsigned short); + + zb->zbuf = gl_malloc(size); + if (zb->zbuf == NULL) + goto error; + + if (frame_buffer == NULL) { + zb->pbuf = gl_malloc(zb->ysize * zb->linesize); + if (zb->pbuf == NULL) { + gl_free(zb->zbuf); + goto error; + } + zb->frame_buffer_allocated = 1; + } else { + zb->frame_buffer_allocated = 0; + zb->pbuf = frame_buffer; + } + + zb->current_texture = NULL; + + return zb; + error: + gl_free(zb); + return NULL; +} + +void ZB_close(ZBuffer * zb) +{ +#ifdef TGL_FEATURE_8_BITS + if (zb->mode == ZB_MODE_INDEX) + ZB_closeDither(zb); +#endif + + if (zb->frame_buffer_allocated) + gl_free(zb->pbuf); + + gl_free(zb->zbuf); + gl_free(zb); +} + +void ZB_resize(ZBuffer * zb, void *frame_buffer, int xsize, int ysize) +{ + int size; + + /* xsize must be a multiple of 4 */ + xsize = xsize & ~3; + + zb->xsize = xsize; + zb->ysize = ysize; + zb->linesize = (xsize * PSZB + 3) & ~3; + + size = zb->xsize * zb->ysize * sizeof(unsigned short); + + gl_free(zb->zbuf); + zb->zbuf = gl_malloc(size); + + if (zb->frame_buffer_allocated) + gl_free(zb->pbuf); + + if (frame_buffer == NULL) { + zb->pbuf = gl_malloc(zb->ysize * zb->linesize); + zb->frame_buffer_allocated = 1; + } else { + zb->pbuf = frame_buffer; + zb->frame_buffer_allocated = 0; + } +} + +static void ZB_copyBuffer(ZBuffer * zb, + void *buf, + int linesize) +{ + unsigned char *p1; + PIXEL *q; + int y, n; + + q = zb->pbuf; + p1 = buf; + n = zb->xsize * PSZB; + for (y = 0; y < zb->ysize; y++) { + memcpy(p1, q, n); + p1 += linesize; + q = (PIXEL *) ((char *) q + zb->linesize); + } +} + +#if TGL_FEATURE_RENDER_BITS == 16 + +/* 32 bpp copy */ + +#ifdef TGL_FEATURE_32_BITS + +#define RGB16_TO_RGB32(p0,p1,v)\ +{\ + unsigned int g,b,gb;\ + g = (v & 0x07E007E0) << 5;\ + b = (v & 0x001F001F) << 3;\ + gb = g | b;\ + p0 = (gb & 0x0000FFFF) | ((v & 0x0000F800) << 8);\ + p1 = (gb >> 16) | ((v & 0xF8000000) >> 8);\ +} +static void ZB_copyFrameBufferRGB32(ZBuffer * zb, + void *buf, + int linesize) +{ + unsigned short *q; + unsigned int *p, *p1, v, w0, w1; + int y, n; + + q = zb->pbuf; + p1 = (unsigned int *) buf; + + for (y = 0; y < zb->ysize; y++) { + p = p1; + n = zb->xsize >> 2; + do { + v = *(unsigned int *) q; +#if BYTE_ORDER == BIG_ENDIAN + RGB16_TO_RGB32(w1, w0, v); +#else + RGB16_TO_RGB32(w0, w1, v); +#endif + p[0] = w0; + p[1] = w1; + + v = *(unsigned int *) (q + 2); +#if BYTE_ORDER == BIG_ENDIAN + RGB16_TO_RGB32(w1, w0, v); +#else + RGB16_TO_RGB32(w0, w1, v); +#endif + p[2] = w0; + p[3] = w1; + + q += 4; + p += 4; + } while (--n > 0); + + p1 = (unsigned int *)((char *)p1 + linesize); + } +} + +#endif + +/* 24 bit packed pixel handling */ + +#ifdef TGL_FEATURE_24_BITS + +/* order: RGBR GBRG BRGB */ + +/* XXX: packed pixel 24 bit support not tested */ +/* XXX: big endian case not optimised */ + +#if BYTE_ORDER == BIG_ENDIAN + +#define RGB16_TO_RGB24(p0,p1,p2,v1,v2)\ +{\ + unsigned int r1,g1,b1,gb1,g2,b2,gb2;\ + v1 = (v1 << 16) | (v1 >> 16);\ + v2 = (v2 << 16) | (v2 >> 16);\ + r1 = (v1 & 0xF800F800);\ + g1 = (v1 & 0x07E007E0) << 5;\ + b1 = (v1 & 0x001F001F) << 3;\ + gb1 = g1 | b1;\ + p0 = ((gb1 & 0x0000FFFF) << 8) | (r1 << 16) | (r1 >> 24);\ + g2 = (v2 & 0x07E007E0) << 5;\ + b2 = (v2 & 0x001F001F) << 3;\ + gb2 = g2 | b2;\ + p1 = (gb1 & 0xFFFF0000) | (v2 & 0xF800) | ((gb2 >> 8) & 0xff);\ + p2 = (gb2 << 24) | ((v2 & 0xF8000000) >> 8) | (gb2 >> 16);\ +} + +#else + +#define RGB16_TO_RGB24(p0,p1,p2,v1,v2)\ +{\ + unsigned int r1,g1,b1,gb1,g2,b2,gb2;\ + r1 = (v1 & 0xF800F800);\ + g1 = (v1 & 0x07E007E0) << 5;\ + b1 = (v1 & 0x001F001F) << 3;\ + gb1 = g1 | b1;\ + p0 = ((gb1 & 0x0000FFFF) << 8) | (r1 << 16) | (r1 >> 24);\ + g2 = (v2 & 0x07E007E0) << 5;\ + b2 = (v2 & 0x001F001F) << 3;\ + gb2 = g2 | b2;\ + p1 = (gb1 & 0xFFFF0000) | (v2 & 0xF800) | ((gb2 >> 8) & 0xff);\ + p2 = (gb2 << 24) | ((v2 & 0xF8000000) >> 8) | (gb2 >> 16);\ +} + +#endif + +static void ZB_copyFrameBufferRGB24(ZBuffer * zb, + void *buf, + int linesize) +{ + unsigned short *q; + unsigned int *p, *p1, w0, w1, w2, v0, v1; + int y, n; + + q = zb->pbuf; + p1 = (unsigned int *) buf; + linesize = linesize * 3; + + for (y = 0; y < zb->ysize; y++) { + p = p1; + n = zb->xsize >> 2; + do { + v0 = *(unsigned int *) q; + v1 = *(unsigned int *) (q + 2); + RGB16_TO_RGB24(w0, w1, w2, v0, v1); + p[0] = w0; + p[1] = w1; + p[2] = w2; + + q += 4; + p += 3; + } while (--n > 0); + + p1 = (unsigned int *)((char *)p1 + linesize); + } +} + +#endif + +void ZB_copyFrameBuffer(ZBuffer * zb, void *buf, + int linesize) +{ + switch (zb->mode) { +#ifdef TGL_FEATURE_8_BITS + case ZB_MODE_INDEX: + ZB_ditherFrameBuffer(zb, buf, linesize >> 1); + break; +#endif +#ifdef TGL_FEATURE_16_BITS + case ZB_MODE_5R6G5B: + ZB_copyBuffer(zb, buf, linesize); + break; +#endif +#ifdef TGL_FEATURE_32_BITS + case ZB_MODE_RGBA: + ZB_copyFrameBufferRGB32(zb, buf, linesize); + break; +#endif +#ifdef TGL_FEATURE_24_BITS + case ZB_MODE_RGB24: + ZB_copyFrameBufferRGB24(zb, buf, linesize); + break; +#endif + default: + assert(0); + } +} + +#endif /* TGL_FEATURE_RENDER_BITS == 16 */ + +#if TGL_FEATURE_RENDER_BITS == 24 + +#define RGB24_TO_RGB16(r, g, b) \ + ((((r) >> 3) << 11) | (((g) >> 2) << 5) | ((b) >> 3)) + +/* XXX: not optimized */ +static void ZB_copyFrameBuffer5R6G5B(ZBuffer * zb, + void *buf, int linesize) +{ + PIXEL *q; + unsigned short *p, *p1; + int y, n; + + q = zb->pbuf; + p1 = (unsigned short *) buf; + + for (y = 0; y < zb->ysize; y++) { + p = p1; + n = zb->xsize >> 2; + do { + p[0] = RGB24_TO_RGB16(q[0], q[1], q[2]); + p[1] = RGB24_TO_RGB16(q[3], q[4], q[5]); + p[2] = RGB24_TO_RGB16(q[6], q[7], q[8]); + p[3] = RGB24_TO_RGB16(q[9], q[10], q[11]); + q = (PIXEL *)((char *)q + 4 * PSZB); + p += 4; + } while (--n > 0); + p1 = (unsigned short *)((char *)p1 + linesize); + } +} + +void ZB_copyFrameBuffer(ZBuffer * zb, void *buf, + int linesize) +{ + switch (zb->mode) { +#ifdef TGL_FEATURE_16_BITS + case ZB_MODE_5R6G5B: + ZB_copyFrameBuffer5R6G5B(zb, buf, linesize); + break; +#endif +#ifdef TGL_FEATURE_24_BITS + case ZB_MODE_RGB24: + ZB_copyBuffer(zb, buf, linesize); + break; +#endif + default: + assert(0); + } +} + +#endif /* TGL_FEATURE_RENDER_BITS == 24 */ + +#if TGL_FEATURE_RENDER_BITS == 32 + +#define RGB32_TO_RGB16(v) \ + (((v >> 8) & 0xf800) | (((v) >> 5) & 0x07e0) | (((v) & 0xff) >> 3)) + +/* XXX: not optimized */ +static void ZB_copyFrameBuffer5R6G5B(ZBuffer * zb, + void *buf, int linesize) +{ + PIXEL *q; + unsigned short *p, *p1; + int y, n; + + q = zb->pbuf; + p1 = (unsigned short *) buf; + + for (y = 0; y < zb->ysize; y++) { + p = p1; + n = zb->xsize >> 2; + do { + p[0] = RGB32_TO_RGB16(q[0]); + p[1] = RGB32_TO_RGB16(q[1]); + p[2] = RGB32_TO_RGB16(q[2]); + p[3] = RGB32_TO_RGB16(q[3]); + q += 4; + p += 4; + } while (--n > 0); + p1 = (unsigned short *)((char *)p1 + linesize); + } +} + +void ZB_copyFrameBuffer(ZBuffer * zb, void *buf, + int linesize) +{ + switch (zb->mode) { +#ifdef TGL_FEATURE_16_BITS + case ZB_MODE_5R6G5B: + ZB_copyFrameBuffer5R6G5B(zb, buf, linesize); + break; +#endif +#ifdef TGL_FEATURE_32_BITS + case ZB_MODE_RGBA: + ZB_copyBuffer(zb, buf, linesize); + break; +#endif + default: + assert(0); + } +} + +#endif /* TGL_FEATURE_RENDER_BITS == 32 */ + + +/* + * adr must be aligned on an 'int' + */ +void memset_s(void *adr, int val, int count) +{ + int i, n, v; + unsigned int *p; + unsigned short *q; + + p = adr; + v = val | (val << 16); + + n = count >> 3; + for (i = 0; i < n; i++) { + p[0] = v; + p[1] = v; + p[2] = v; + p[3] = v; + p += 4; + } + + q = (unsigned short *) p; + n = count & 7; + for (i = 0; i < n; i++) + *q++ = val; +} + +void memset_l(void *adr, int val, int count) +{ + int i, n, v; + unsigned int *p; + + p = adr; + v = val; + n = count >> 2; + for (i = 0; i < n; i++) { + p[0] = v; + p[1] = v; + p[2] = v; + p[3] = v; + p += 4; + } + + n = count & 3; + for (i = 0; i < n; i++) + *p++ = val; +} + +/* count must be a multiple of 4 and >= 4 */ +void memset_RGB24(void *adr,int r, int v, int b,long count) +{ + long i, n; + register long v1,v2,v3,*pt=(long *)(adr); + unsigned char *p,R=(unsigned char)r,V=(unsigned char)v,B=(unsigned char)b; + + p=(unsigned char *)adr; + *p++=R; + *p++=V; + *p++=B; + *p++=R; + *p++=V; + *p++=B; + *p++=R; + *p++=V; + *p++=B; + *p++=R; + *p++=V; + *p++=B; + v1=*pt++; + v2=*pt++; + v3=*pt++; + n = count >> 2; + for(i=1;izbuf, z, zb->xsize * zb->ysize); + } + if (clear_color) { + pp = zb->pbuf; + for (y = 0; y < zb->ysize; y++) { +#if TGL_FEATURE_RENDER_BITS == 15 || TGL_FEATURE_RENDER_BITS == 16 + color = RGB_TO_PIXEL(r, g, b); + memset_s(pp, color, zb->xsize); +#elif TGL_FEATURE_RENDER_BITS == 32 + color = RGB_TO_PIXEL(r, g, b); + memset_l(pp, color, zb->xsize); +#elif TGL_FEATURE_RENDER_BITS == 24 + memset_RGB24(pp,r>>8,g>>8,b>>8,zb->xsize); +#else +#error TODO +#endif + pp = (PIXEL *) ((char *) pp + zb->linesize); + } + } +} diff --git a/apps/tinygl/src/TinyGL/src/zbuffer.h b/apps/tinygl/src/TinyGL/src/zbuffer.h new file mode 100644 index 0000000..35d3734 --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/zbuffer.h @@ -0,0 +1,162 @@ +#ifndef _tgl_zbuffer_h_ +#define _tgl_zbuffer_h_ + +/* + * Z buffer + */ + +#include + +#include "zfeatures.h" + +#define ZB_Z_BITS 16 + +#define ZB_POINT_Z_FRAC_BITS 14 + +#define ZB_POINT_S_MIN ( (1<<13) ) +#define ZB_POINT_S_MAX ( (1<<22)-(1<<13) ) +#define ZB_POINT_T_MIN ( (1<<21) ) +#define ZB_POINT_T_MAX ( (1<<30)-(1<<21) ) + +#define ZB_POINT_RED_MIN ( (1<<10) ) +#define ZB_POINT_RED_MAX ( (1<<16)-(1<<10) ) +#define ZB_POINT_GREEN_MIN ( (1<<9) ) +#define ZB_POINT_GREEN_MAX ( (1<<16)-(1<<9) ) +#define ZB_POINT_BLUE_MIN ( (1<<10) ) +#define ZB_POINT_BLUE_MAX ( (1<<16)-(1<<10) ) + +/* display modes */ +#define ZB_MODE_5R6G5B 1 /* true color 16 bits */ +#define ZB_MODE_INDEX 2 /* color index 8 bits */ +#define ZB_MODE_RGBA 3 /* 32 bit rgba mode */ +#define ZB_MODE_RGB24 4 /* 24 bit rgb mode */ +#define ZB_NB_COLORS 225 /* number of colors for 8 bit display */ + +#if TGL_FEATURE_RENDER_BITS == 15 + +#define RGB_TO_PIXEL(r,g,b) \ + ((((r) >> 1) & 0x7c00) | (((g) >> 6) & 0x03e0) | ((b) >> 11)) +typedef unsigned short PIXEL; +/* bytes per pixel */ +#define PSZB 2 +/* bits per pixel = (1 << PSZH) */ +#define PSZSH 4 + +#elif TGL_FEATURE_RENDER_BITS == 16 + +/* 16 bit mode */ +#define RGB_TO_PIXEL(r,g,b) \ + (((r) & 0xF800) | (((g) >> 5) & 0x07E0) | ((b) >> 11)) +typedef unsigned short PIXEL; +#define PSZB 2 +#define PSZSH 4 + +#elif TGL_FEATURE_RENDER_BITS == 24 + +#define RGB_TO_PIXEL(r,g,b) \ + ((((r) << 8) & 0xff0000) | ((g) & 0xff00) | ((b) >> 8)) +typedef unsigned char PIXEL; +#define PSZB 3 +#define PSZSH 5 + +#elif TGL_FEATURE_RENDER_BITS == 32 + +#define RGB_TO_PIXEL(r,g,b) \ + (((((r) << 8) & 0xff0000) | ((g) & 0xff00) | ((b) >> 8)) | 0xff000000) +typedef unsigned int PIXEL; +#define PSZB 4 +#define PSZSH 5 + +#else + +#error Incorrect number of bits per pixel + +#endif + +typedef struct { + int xsize,ysize; + int linesize; /* line size, in bytes */ + int mode; + + unsigned short *zbuf; + PIXEL *pbuf; + int frame_buffer_allocated; + + int nb_colors; + unsigned char *dctable; + int *ctable; + PIXEL *current_texture; +} ZBuffer; + +typedef struct { + int x,y,z; /* integer coordinates in the zbuffer */ + int s,t; /* coordinates for the mapping */ + int r,g,b; /* color indexes */ + + float sz,tz; /* temporary coordinates for mapping */ +} ZBufferPoint; + +/* zbuffer.c */ + +ZBuffer *ZB_open(int xsize,int ysize,int mode, + int nb_colors, + unsigned char *color_indexes, + int *color_table, + void *frame_buffer); + + +void ZB_close(ZBuffer *zb); + +void ZB_resize(ZBuffer *zb,void *frame_buffer,int xsize,int ysize); +void ZB_clear(ZBuffer *zb,int clear_z,int z, + int clear_color,int r,int g,int b); +/* linesize is in BYTES */ +void ZB_copyFrameBuffer(ZBuffer *zb,void *buf,int linesize); + +/* zdither.c */ + +void ZB_initDither(ZBuffer *zb,int nb_colors, + unsigned char *color_indexes,int *color_table); +void ZB_closeDither(ZBuffer *zb); +void ZB_ditherFrameBuffer(ZBuffer *zb,unsigned char *dest, + int linesize); + +/* zline.c */ + +void ZB_plot(ZBuffer *zb,ZBufferPoint *p); +void ZB_line(ZBuffer *zb,ZBufferPoint *p1,ZBufferPoint *p2); +void ZB_line_z(ZBuffer * zb, ZBufferPoint * p1, ZBufferPoint * p2); + +/* ztriangle.c */ + +void ZB_setTexture(ZBuffer *zb, PIXEL *texture); + +void ZB_fillTriangleFlat(ZBuffer *zb, + ZBufferPoint *p1,ZBufferPoint *p2,ZBufferPoint *p3); + +void ZB_fillTriangleSmooth(ZBuffer *zb, + ZBufferPoint *p1,ZBufferPoint *p2,ZBufferPoint *p3); + +void ZB_fillTriangleMapping(ZBuffer *zb, + ZBufferPoint *p1,ZBufferPoint *p2,ZBufferPoint *p3); + +void ZB_fillTriangleMappingPerspective(ZBuffer *zb, + ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2); + + +typedef void (*ZB_fillTriangleFunc)(ZBuffer *, + ZBufferPoint *,ZBufferPoint *,ZBufferPoint *); + +/* memory.c */ +//void gl_free(void *p); +//void *gl_malloc(int size); +//void *gl_zalloc(int size); +//void *gl_memcpy(void *dst, const void *src, int n); + +#define gl_memcpy memcpy +#define gl_malloc malloc +#define gl_free free +#define gl_calloc calloc +#define gl_zalloc(n) calloc(n, 1) + +#endif /* _tgl_zbuffer_h_ */ diff --git a/apps/tinygl/src/TinyGL/src/zdither.c b/apps/tinygl/src/TinyGL/src/zdither.c new file mode 100644 index 0000000..cdddb0b --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/zdither.c @@ -0,0 +1,163 @@ +/* + * Highly optimised dithering 16 bits -> 8 bits. + * The formulas were taken in Mesa (Bob Mercier mercier@hollywood.cinenet.net). + */ + +//#include +//#include +#include "zgl.h" +#include "zbuffer.h" +//#include + +#if defined(TGL_FEATURE_8_BITS) + +#if TGL_FEATURE_RENDER_BITS != 16 +#error TGL_FEATURE_8_BITS is not supported for this value of TGL_FEATURE_RENDER_BITS +#endif + +#define _R 5 +#define _G 9 +#define _B 5 +#define _DX 4 +#define _DY 4 +#define _D (_DX*_DY) +#define _MIX(r,g,b) ( ((g)<<6) | ((b)<<3) | (r) ) + +#define DITHER_TABLE_SIZE (1 << 15) + +#define DITHER_INDEX(r,g,b) ((b) + (g) * _B + (r) * (_B * _G)) + +#define MAXC 256 +static int kernel8[_DY*_DX] = { + 0 * MAXC, 8 * MAXC, 2 * MAXC, 10 * MAXC, + 12 * MAXC, 4 * MAXC, 14 * MAXC, 6 * MAXC, + 3 * MAXC, 11 * MAXC, 1 * MAXC, 9 * MAXC, + 15 * MAXC, 7 * MAXC, 13 * MAXC, 5 * MAXC, +}; + +/* we build the color table and the lookup table */ + +void ZB_initDither(ZBuffer *zb,int nb_colors, + unsigned char *color_indexes,int *color_table) +{ + int c,r,g,b,i,index,r1,g1,b1; + + if (nb_colors < (_R * _G * _B)) { + // FIXME + } + + for(i=0;inb_colors=nb_colors; + zb->ctable=gl_malloc(nb_colors * sizeof(int)); + + for (r = 0; r < _R; r++) { + for (g = 0; g < _G; g++) { + for (b = 0; b < _B; b++) { + r1=(r*255) / (_R - 1); + g1=(g*255) / (_G - 1); + b1=(b*255) / (_B - 1); + index=DITHER_INDEX(r,g,b); + c=(r1 << 16) | (g1 << 8) | b1; + zb->ctable[index]=c; + color_table[index]=c; + } + } + } + + zb->dctable=gl_malloc( DITHER_TABLE_SIZE ); + + for(i=0;i> 12) & 0x7; + g=(i >> 8) & 0xF; + b=(i >> 3) & 0x7; + index=DITHER_INDEX(r,g,b); + zb->dctable[i]=color_indexes[index]; + } +} + +void ZB_closeDither(ZBuffer *zb) +{ + gl_free(zb->ctable); + gl_free(zb->dctable); +} + +#if 0 +int ZDither_lookupColor(int r,int g,int b) +{ + unsigned char *ctable=zdither_color_table; + return ctable[_MIX(_DITH0(_R, r), _DITH0(_G, g),_DITH0(_B, b))]; +} +#endif + + +#define DITHER_PIXEL2(a) \ +{ \ + register int v,t,r,g,c; \ + v=*(unsigned int *)(pp+(a)); \ + g=(v & 0x07DF07DF) + g_d; \ + r=(((v & 0xF800F800) >> 2) + r_d) & 0x70007000; \ + t=r | g; \ + c=ctable[t & 0xFFFF] | (ctable[t >> 16] << 8); \ + *(unsigned short *)(dest+(a))=c; \ +} + +/* NOTE: all the memory access are 16 bit aligned, so if buf or + linesize are not multiple of 2, it cannot work efficiently (or + hang!) */ + +void ZB_ditherFrameBuffer(ZBuffer *zb,unsigned char *buf, + int linesize) +{ + int xk,yk,x,y,c1,c2; + unsigned char *dest1; + unsigned short *pp1; + int r_d,g_d,b_d; + unsigned char *ctable=zb->dctable; + register unsigned char *dest; + register unsigned short *pp; + + assert( ((long)buf & 1) == 0 && (linesize & 1) == 0); + + for(yk=0;yk<4;yk++) { + for(xk=0;xk<4;xk+=2) { +#if BYTE_ORDER == BIG_ENDIAN + c1=kernel8[yk*4+xk+1]; + c2=kernel8[yk*4+xk]; +#else + c1=kernel8[yk*4+xk]; + c2=kernel8[yk*4+xk+1]; +#endif + r_d=((c1 << 2) & 0xF800) >> 2; + g_d=(c1 >> 4) & 0x07C0; + b_d=(c1 >> 9) & 0x001F; + + r_d|=(((c2 << 2) & 0xF800) >> 2) << 16; + g_d|=((c2 >> 4) & 0x07C0) << 16; + b_d|=((c2 >> 9) & 0x001F) << 16; + g_d=b_d | g_d; + + dest1=buf + (yk * linesize) + xk; + pp1=zb->pbuf + (yk * zb->xsize) + xk; + + for(y=yk;yysize;y+=4) { + dest=dest1; + pp=pp1; + for(x=xk;xxsize;x+=16) { + + DITHER_PIXEL2(0); + DITHER_PIXEL2(1*4); + DITHER_PIXEL2(2*4); + DITHER_PIXEL2(3*4); + + pp+=16; + dest+=16; + } + dest1+=linesize*4; + pp1+=zb->xsize*4; + } + } + } +} + +#endif /* TGL_FEATURE_8_BITS */ diff --git a/apps/tinygl/src/TinyGL/src/zfeatures.h b/apps/tinygl/src/TinyGL/src/zfeatures.h new file mode 100644 index 0000000..c9dfa64 --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/zfeatures.h @@ -0,0 +1,43 @@ +#ifndef _tgl_features_h_ +#define _tgl_features_h_ + +/* It is possible to enable/disable (compile time) features in this + header file. */ + +#define TGL_FEATURE_ARRAYS 1 +#define TGL_FEATURE_DISPLAYLISTS 1 +#define TGL_FEATURE_POLYGON_OFFSET 1 + +/* + * Matrix of internal and external pixel formats supported. 'Y' means + * supported. + * + * External 8 16 24 32 + * Internal + * 15 . . . . + * 16 Y Y Y Y + * 24 . Y Y . + * 32 . Y . Y + * + * + * 15 bpp does not work yet (although it is easy to add it - ask me if + * you need it). + * + * Internal pixel format: see TGL_FEATURE_RENDER_BITS + * External pixel format: see TGL_FEATURE_xxx_BITS + */ + +/* enable various convertion code from internal pixel format (usually + 16 bits per pixel) to any external format */ +//#define TGL_FEATURE_16_BITS 1 +//#define TGL_FEATURE_8_BITS 1 +//#define TGL_FEATURE_24_BITS 1 +#define TGL_FEATURE_32_BITS 1 + + +//#define TGL_FEATURE_RENDER_BITS 15 +//#define TGL_FEATURE_RENDER_BITS 16 +//#define TGL_FEATURE_RENDER_BITS 24 +#define TGL_FEATURE_RENDER_BITS 32 + +#endif /* _tgl_features_h_ */ diff --git a/apps/tinygl/src/TinyGL/src/zgl.h b/apps/tinygl/src/TinyGL/src/zgl.h new file mode 100644 index 0000000..96d5089 --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/zgl.h @@ -0,0 +1,385 @@ +#ifndef _tgl_zgl_h_ +#define _tgl_zgl_h_ + +#define NULL ((void *)0) +#define M_PI 3.14159265358979323846264338328 + +#define assert(X) // FIXME + +#define zsin sin +#define zfloor floor +#define zcos cos +#define zfabs fabs +#define zsqrt sqrt +#define zpow pow + +#include +#include +//#include +//#include +#include +#include +#include "zbuffer.h" +#include "zmath.h" +#include "zfeatures.h" + +#define DEBUG +/* #define NDEBUG */ + +enum { + +#define ADD_OP(a,b,c) OP_ ## a , + +#include "opinfo.h" + +}; + +/* initially # of allocated GLVertexes (will grow when necessary) */ +#define POLYGON_MAX_VERTEX 16 + +/* Max # of specular light pow buffers */ +#define MAX_SPECULAR_BUFFERS 8 +/* # of entries in specular buffer */ +#define SPECULAR_BUFFER_SIZE 1024 +/* specular buffer granularity */ +#define SPECULAR_BUFFER_RESOLUTION 1024 + + +#define MAX_MODELVIEW_STACK_DEPTH 32 +#define MAX_PROJECTION_STACK_DEPTH 8 +#define MAX_TEXTURE_STACK_DEPTH 8 +#define MAX_NAME_STACK_DEPTH 64 +#define MAX_TEXTURE_LEVELS 11 +#define MAX_LIGHTS 16 + +#define VERTEX_HASH_SIZE 1031 + +#define MAX_DISPLAY_LISTS 1024 +#define OP_BUFFER_MAX_SIZE 512 + +#define TGL_OFFSET_FILL 0x1 +#define TGL_OFFSET_LINE 0x2 +#define TGL_OFFSET_POINT 0x4 + +typedef struct GLSpecBuf { + int shininess_i; + int last_used; + float buf[SPECULAR_BUFFER_SIZE+1]; + struct GLSpecBuf *next; +} GLSpecBuf; + +typedef struct GLLight { + V4 ambient; + V4 diffuse; + V4 specular; + V4 position; + V3 spot_direction; + float spot_exponent; + float spot_cutoff; + float attenuation[3]; + /* precomputed values */ + float cos_spot_cutoff; + V3 norm_spot_direction; + V3 norm_position; + /* we use a linked list to know which are the enabled lights */ + int enabled; + struct GLLight *next,*prev; +} GLLight; + +typedef struct GLMaterial { + V4 emission; + V4 ambient; + V4 diffuse; + V4 specular; + float shininess; + + /* computed values */ + int shininess_i; + int do_specular; +} GLMaterial; + + +typedef struct GLViewport { + int xmin,ymin,xsize,ysize; + V3 scale; + V3 trans; + int updated; +} GLViewport; + +typedef union { + int op; + float f; + int i; + unsigned int ui; + void *p; +} GLParam; + +typedef struct GLParamBuffer { + GLParam ops[OP_BUFFER_MAX_SIZE]; + struct GLParamBuffer *next; +} GLParamBuffer; + +typedef struct GLList { + GLParamBuffer *first_op_buffer; + /* TODO: extensions for an hash table or a better allocating scheme */ +} GLList; + +typedef struct GLVertex { + int edge_flag; + V3 normal; + V4 coord; + V4 tex_coord; + V4 color; + + /* computed values */ + V4 ec; /* eye coordinates */ + V4 pc; /* coordinates in the normalized volume */ + int clip_code; /* clip code */ + ZBufferPoint zp; /* integer coordinates for the rasterization */ +} GLVertex; + +typedef struct GLImage { + void *pixmap; + int xsize,ysize; +} GLImage; + +/* textures */ + +#define TEXTURE_HASH_TABLE_SIZE 256 + +typedef struct GLTexture { + GLImage images[MAX_TEXTURE_LEVELS]; + int handle; + struct GLTexture *next,*prev; +} GLTexture; + + +/* shared state */ + +typedef struct GLSharedState { + GLList **lists; + GLTexture **texture_hash_table; +} GLSharedState; + +struct GLContext; + +typedef void (*gl_draw_triangle_func)(struct GLContext *c, + GLVertex *p0,GLVertex *p1,GLVertex *p2); + +/* display context */ + +typedef struct GLContext { + /* Z buffer */ + ZBuffer *zb; + + /* lights */ + GLLight lights[MAX_LIGHTS]; + GLLight *first_light; + V4 ambient_light_model; + int local_light_model; + int lighting_enabled; + int light_model_two_side; + + /* materials */ + GLMaterial materials[2]; + int color_material_enabled; + int current_color_material_mode; + int current_color_material_type; + + /* textures */ + GLTexture *current_texture; + int texture_2d_enabled; + + /* shared state */ + GLSharedState shared_state; + + /* current list */ + GLParamBuffer *current_op_buffer; + int current_op_buffer_index; + int exec_flag,compile_flag,print_flag; + + /* matrix */ + + int matrix_mode; + M4 *matrix_stack[3]; + M4 *matrix_stack_ptr[3]; + int matrix_stack_depth_max[3]; + + M4 matrix_model_view_inv; + M4 matrix_model_projection; + int matrix_model_projection_updated; + int matrix_model_projection_no_w_transform; + int apply_texture_matrix; + + /* viewport */ + GLViewport viewport; + + /* current state */ + int polygon_mode_back; + int polygon_mode_front; + + int current_front_face; + int current_shade_model; + int current_cull_face; + int cull_face_enabled; + int normalize_enabled; + gl_draw_triangle_func draw_triangle_front,draw_triangle_back; + + /* selection */ + int render_mode; + unsigned int *select_buffer; + int select_size; + unsigned int *select_ptr,*select_hit; + int select_overflow; + int select_hits; + + /* names */ + unsigned int name_stack[MAX_NAME_STACK_DEPTH]; + int name_stack_size; + + /* clear */ + float clear_depth; + V4 clear_color; + + /* current vertex state */ + V4 current_color; + unsigned int longcurrent_color[3]; /* precomputed integer color */ + V4 current_normal; + V4 current_tex_coord; + int current_edge_flag; + + /* glBegin / glEnd */ + int in_begin; + int begin_type; + int vertex_n,vertex_cnt; + int vertex_max; + GLVertex *vertex; + + /* opengl 1.1 arrays */ + float *vertex_array; + int vertex_array_size; + int vertex_array_stride; + float *normal_array; + int normal_array_stride; + float *color_array; + int color_array_size; + int color_array_stride; + float *texcoord_array; + int texcoord_array_size; + int texcoord_array_stride; + int client_states; + + /* opengl 1.1 polygon offset */ + float offset_factor; + float offset_units; + int offset_states; + + /* specular buffer. could probably be shared between contexts, + but that wouldn't be 100% thread safe */ + GLSpecBuf *specbuf_first; + int specbuf_used_counter; + int specbuf_num_buffers; + + /* opaque structure for user's use */ + void *opaque; + /* resize viewport function */ + int (*gl_resize_viewport)(struct GLContext *c,int *xsize,int *ysize); + + /* depth test */ + int depth_test; +} GLContext; + +extern GLContext *gl_ctx; + +void gl_add_op(GLParam *p); + +/* clip.c */ +void gl_transform_to_viewport(GLContext *c,GLVertex *v); +void gl_draw_triangle(GLContext *c,GLVertex *p0,GLVertex *p1,GLVertex *p2); +void gl_draw_line(GLContext *c,GLVertex *p0,GLVertex *p1); +void gl_draw_point(GLContext *c,GLVertex *p0); + +void gl_draw_triangle_point(GLContext *c, + GLVertex *p0,GLVertex *p1,GLVertex *p2); +void gl_draw_triangle_line(GLContext *c, + GLVertex *p0,GLVertex *p1,GLVertex *p2); +void gl_draw_triangle_fill(GLContext *c, + GLVertex *p0,GLVertex *p1,GLVertex *p2); +void gl_draw_triangle_select(GLContext *c, + GLVertex *p0,GLVertex *p1,GLVertex *p2); + +/* matrix.c */ +void gl_print_matrix(const float *m); +/* +void glopLoadIdentity(GLContext *c,GLParam *p); +void glopTranslate(GLContext *c,GLParam *p);*/ + +/* light.c */ +void gl_add_select(GLContext *c,unsigned int zmin,unsigned int zmax); +void gl_enable_disable_light(GLContext *c,int light,int v); +void gl_shade_vertex(GLContext *c,GLVertex *v); + +void glInitTextures(GLContext *c); +void glEndTextures(GLContext *c); +GLTexture *alloc_texture(GLContext *c,int h); + +/* image_util.c */ +void gl_convertRGB_to_5R6G5B(unsigned short *pixmap,unsigned char *rgb, + int xsize,int ysize); +void gl_convertRGB_to_8A8R8G8B(unsigned int *pixmap, unsigned char *rgb, + int xsize, int ysize); +void gl_resizeImage(unsigned char *dest,int xsize_dest,int ysize_dest, + unsigned char *src,int xsize_src,int ysize_src); +void gl_resizeImageNoInterpolate(unsigned char *dest,int xsize_dest,int ysize_dest, + unsigned char *src,int xsize_src,int ysize_src); + +GLContext *gl_get_context(void); + +void gl_fatal_error(char *format, ...); + + +/* specular buffer "api" */ +GLSpecBuf *specbuf_get_buffer(GLContext *c, const int shininess_i, + const float shininess); + +#ifdef __BEOS__ +void dprintf(const char *, ...); + +#else /* !BEOS */ + +#ifdef DEBUG + +#define dprintf(format, args...) \ + fprintf(stderr,"In '%s': " format "\n",__FUNCTION__, ##args); + +#else + +#define dprintf(format, args...) + +#endif +#endif /* !BEOS */ + +/* glopXXX functions */ + +#define ADD_OP(a,b,c) void glop ## a (GLContext *,GLParam *); +#include "opinfo.h" + +/* this clip epsilon is needed to avoid some rounding errors after + several clipping stages */ + +#define CLIP_EPSILON (1E-5) + +static inline int gl_clipcode(float x,float y,float z,float w1) +{ + float w; + + w=w1 * (1.0 + CLIP_EPSILON); + return (x<-w) | + ((x>w)<<1) | + ((y<-w)<<2) | + ((y>w)<<3) | + ((z<-w)<<4) | + ((z>w)<<5) ; +} + +#endif /* _tgl_zgl_h_ */ diff --git a/apps/tinygl/src/TinyGL/src/zline.c b/apps/tinygl/src/TinyGL/src/zline.c new file mode 100644 index 0000000..75f8941 --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/zline.c @@ -0,0 +1,84 @@ +//#include +#include "zbuffer.h" + +#define ZCMP(z,zpix) ((z) >= (zpix)) + +void ZB_plot(ZBuffer * zb, ZBufferPoint * p) +{ + unsigned short *pz; + PIXEL *pp; + int zz; + + pz = zb->zbuf + (p->y * zb->xsize + p->x); + pp = (PIXEL *) ((char *) zb->pbuf + zb->linesize * p->y + p->x * PSZB); + zz = p->z >> ZB_POINT_Z_FRAC_BITS; + if (ZCMP(zz, *pz)) { +#if TGL_FEATURE_RENDER_BITS == 24 + pp[0]=p->r>>8; + pp[1]=p->g>>8; + pp[2]=p->b>>8; +#else + *pp = RGB_TO_PIXEL(p->r, p->g, p->b); +#endif + *pz = zz; + } +} + +#define INTERP_Z +static void ZB_line_flat_z(ZBuffer * zb, ZBufferPoint * p1, ZBufferPoint * p2, + int color) +{ +#include "zline.h" +} + +/* line with color interpolation */ +#define INTERP_Z +#define INTERP_RGB +static void ZB_line_interp_z(ZBuffer * zb, ZBufferPoint * p1, ZBufferPoint * p2) +{ +#include "zline.h" +} + +/* no Z interpolation */ + +static void ZB_line_flat(ZBuffer * zb, ZBufferPoint * p1, ZBufferPoint * p2, + int color) +{ +#include "zline.h" +} + +#define INTERP_RGB +static void ZB_line_interp(ZBuffer * zb, ZBufferPoint * p1, ZBufferPoint * p2) +{ +#include "zline.h" +} + +void ZB_line_z(ZBuffer * zb, ZBufferPoint * p1, ZBufferPoint * p2) +{ + int color1, color2; + + color1 = RGB_TO_PIXEL(p1->r, p1->g, p1->b); + color2 = RGB_TO_PIXEL(p2->r, p2->g, p2->b); + + /* choose if the line should have its color interpolated or not */ + if (color1 == color2) { + ZB_line_flat_z(zb, p1, p2, color1); + } else { + ZB_line_interp_z(zb, p1, p2); + } +} + +void ZB_line(ZBuffer * zb, ZBufferPoint * p1, ZBufferPoint * p2) +{ + int color1, color2; + + color1 = RGB_TO_PIXEL(p1->r, p1->g, p1->b); + color2 = RGB_TO_PIXEL(p2->r, p2->g, p2->b); + + /* choose if the line should have its color interpolated or not */ + if (color1 == color2) { + ZB_line_flat(zb, p1, p2, color1); + } else { + ZB_line_interp(zb, p1, p2); + } +} diff --git a/apps/tinygl/src/TinyGL/src/zline.h b/apps/tinygl/src/TinyGL/src/zline.h new file mode 100644 index 0000000..982b355 --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/zline.h @@ -0,0 +1,121 @@ +{ + int n, dx, dy, sx, pp_inc_1, pp_inc_2; + register int a; + register PIXEL *pp; +#if defined(INTERP_RGB) || TGL_FEATURE_RENDER_BITS == 24 + register unsigned int r, g, b; +#endif +#ifdef INTERP_RGB + register unsigned int rinc, ginc, binc; +#endif +#ifdef INTERP_Z + register unsigned short *pz; + int zinc; + register int z, zz; +#endif + + if (p1->y > p2->y || (p1->y == p2->y && p1->x > p2->x)) { + ZBufferPoint *tmp; + tmp = p1; + p1 = p2; + p2 = tmp; + } + sx = zb->xsize; + pp = (PIXEL *) ((char *) zb->pbuf + zb->linesize * p1->y + p1->x * PSZB); +#ifdef INTERP_Z + pz = zb->zbuf + (p1->y * sx + p1->x); + z = p1->z; +#endif + + dx = p2->x - p1->x; + dy = p2->y - p1->y; +#ifdef INTERP_RGB + r = p2->r << 8; + g = p2->g << 8; + b = p2->b << 8; +#elif TGL_FEATURE_RENDER_BITS == 24 + /* for 24 bits, we store the colors in different variables */ + r = p2->r >> 8; + g = p2->g >> 8; + b = p2->b >> 8; +#endif + +#ifdef INTERP_RGB +#define RGB(x) x +#if TGL_FEATURE_RENDER_BITS == 24 +#define RGBPIXEL pp[0] = r >> 16, pp[1] = g >> 16, pp[2] = b >> 16 +#else +#define RGBPIXEL *pp = RGB_TO_PIXEL(r >> 8,g >> 8,b >> 8) +#endif +#else /* INTERP_RGB */ +#define RGB(x) +#if TGL_FEATURE_RENDER_BITS == 24 +#define RGBPIXEL pp[0] = r, pp[1] = g, pp[2] = b +#else +#define RGBPIXEL *pp = color +#endif +#endif /* INTERP_RGB */ + +#ifdef INTERP_Z +#define ZZ(x) x +#define PUTPIXEL() \ + { \ + zz=z >> ZB_POINT_Z_FRAC_BITS; \ + if (ZCMP(zz,*pz)) { \ + RGBPIXEL; \ + *pz=zz; \ + } \ + } +#else /* INTERP_Z */ +#define ZZ(x) +#define PUTPIXEL() RGBPIXEL +#endif /* INTERP_Z */ + +#define DRAWLINE(dx,dy,inc_1,inc_2) \ + n=dx;\ + ZZ(zinc=(p2->z-p1->z)/n);\ + RGB(rinc=((p2->r-p1->r) << 8)/n;\ + ginc=((p2->g-p1->g) << 8)/n;\ + binc=((p2->b-p1->b) << 8)/n);\ + a=2*dy-dx;\ + dy=2*dy;\ + dx=2*dx-dy;\ + pp_inc_1 = (inc_1) * PSZB;\ + pp_inc_2 = (inc_2) * PSZB;\ + do {\ + PUTPIXEL();\ + ZZ(z+=zinc);\ + RGB(r+=rinc;g+=ginc;b+=binc);\ + if (a>0) { pp=(PIXEL *)((char *)pp + pp_inc_1); ZZ(pz+=(inc_1)); a-=dx; }\ + else { pp=(PIXEL *)((char *)pp + pp_inc_2); ZZ(pz+=(inc_2)); a+=dy; }\ + } while (--n >= 0); + +/* fin macro */ + + if (dx == 0 && dy == 0) { + PUTPIXEL(); + } else if (dx > 0) { + if (dx >= dy) { + DRAWLINE(dx, dy, sx + 1, 1); + } else { + DRAWLINE(dy, dx, sx + 1, sx); + } + } else { + dx = -dx; + if (dx >= dy) { + DRAWLINE(dx, dy, sx - 1, -1); + } else { + DRAWLINE(dy, dx, sx - 1, sx); + } + } +} + +#undef INTERP_Z +#undef INTERP_RGB + +/* internal defines */ +#undef DRAWLINE +#undef PUTPIXEL +#undef ZZ +#undef RGB +#undef RGBPIXEL diff --git a/apps/tinygl/src/TinyGL/src/zmath.c b/apps/tinygl/src/TinyGL/src/zmath.c new file mode 100644 index 0000000..0686159 --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/zmath.c @@ -0,0 +1,276 @@ +/* Some simple mathematical functions. Don't look for some logic in + the function names :-) */ + +//#include +//#include +//#include +#include "zgl.h" +#include "zmath.h" + + +/* ******* Gestion des matrices 4x4 ****** */ + +void gl_M4_Id(M4 *a) +{ + int i,j; + for(i=0;i<4;i++) + for(j=0;j<4;j++) + if (i==j) a->m[i][j]=1.0; else a->m[i][j]=0.0; +} + +int gl_M4_IsId(M4 *a) +{ + int i,j; + for(i=0;i<4;i++) + for(j=0;j<4;j++) { + if (i==j) { + if (a->m[i][j] != 1.0) return 0; + } else if (a->m[i][j] != 0.0) return 0; + } + return 1; +} + +void gl_M4_Mul(M4 *c,M4 *a,M4 *b) +{ + int i,j,k; + float s; + for(i=0;i<4;i++) + for(j=0;j<4;j++) { + s=0.0; + for(k=0;k<4;k++) s+=a->m[i][k]*b->m[k][j]; + c->m[i][j]=s; + } +} + +/* c=c*a */ +void gl_M4_MulLeft(M4 *c,M4 *b) +{ + int i,j,k; + float s; + M4 a; + + /*memcpy(&a, c, 16*sizeof(float)); + */ + a=*c; + + for(i=0;i<4;i++) + for(j=0;j<4;j++) { + s=0.0; + for(k=0;k<4;k++) s+=a.m[i][k]*b->m[k][j]; + c->m[i][j]=s; + } +} + +void gl_M4_Move(M4 *a,M4 *b) +{ + memcpy(a,b,sizeof(M4)); +} + +void gl_MoveV3(V3 *a,V3 *b) +{ + memcpy(a,b,sizeof(V3)); +} + + +void gl_MulM4V3(V3 *a,M4 *b,V3 *c) +{ + a->X=b->m[0][0]*c->X+b->m[0][1]*c->Y+b->m[0][2]*c->Z+b->m[0][3]; + a->Y=b->m[1][0]*c->X+b->m[1][1]*c->Y+b->m[1][2]*c->Z+b->m[1][3]; + a->Z=b->m[2][0]*c->X+b->m[2][1]*c->Y+b->m[2][2]*c->Z+b->m[2][3]; +} + +void gl_MulM3V3(V3 *a,M4 *b,V3 *c) +{ + a->X=b->m[0][0]*c->X+b->m[0][1]*c->Y+b->m[0][2]*c->Z; + a->Y=b->m[1][0]*c->X+b->m[1][1]*c->Y+b->m[1][2]*c->Z; + a->Z=b->m[2][0]*c->X+b->m[2][1]*c->Y+b->m[2][2]*c->Z; +} + +void gl_M4_MulV4(V4 *a,M4 *b,V4 *c) +{ + a->X=b->m[0][0]*c->X+b->m[0][1]*c->Y+b->m[0][2]*c->Z+b->m[0][3]*c->W; + a->Y=b->m[1][0]*c->X+b->m[1][1]*c->Y+b->m[1][2]*c->Z+b->m[1][3]*c->W; + a->Z=b->m[2][0]*c->X+b->m[2][1]*c->Y+b->m[2][2]*c->Z+b->m[2][3]*c->W; + a->W=b->m[3][0]*c->X+b->m[3][1]*c->Y+b->m[3][2]*c->Z+b->m[3][3]*c->W; +} + +/* transposition of a 4x4 matrix */ +void gl_M4_Transpose(M4 *a,M4 *b) +{ + a->m[0][0]=b->m[0][0]; + a->m[0][1]=b->m[1][0]; + a->m[0][2]=b->m[2][0]; + a->m[0][3]=b->m[3][0]; + + a->m[1][0]=b->m[0][1]; + a->m[1][1]=b->m[1][1]; + a->m[1][2]=b->m[2][1]; + a->m[1][3]=b->m[3][1]; + + a->m[2][0]=b->m[0][2]; + a->m[2][1]=b->m[1][2]; + a->m[2][2]=b->m[2][2]; + a->m[2][3]=b->m[3][2]; + + a->m[3][0]=b->m[0][3]; + a->m[3][1]=b->m[1][3]; + a->m[3][2]=b->m[2][3]; + a->m[3][3]=b->m[3][3]; +} + +/* inversion of an orthogonal matrix of type Y=M.X+P */ +void gl_M4_InvOrtho(M4 *a,M4 b) +{ + int i,j; + float s; + for(i=0;i<3;i++) + for(j=0;j<3;j++) a->m[i][j]=b.m[j][i]; + a->m[3][0]=0.0; a->m[3][1]=0.0; a->m[3][2]=0.0; a->m[3][3]=1.0; + for(i=0;i<3;i++) { + s=0; + for(j=0;j<3;j++) s-=b.m[j][i]*b.m[j][3]; + a->m[i][3]=s; + } +} + +/* Inversion of a general nxn matrix. + Note : m is destroyed */ + +int Matrix_Inv(float *r,float *m,int n) +{ + int i,j,k,l; + float max,tmp,t; + + /* identitée dans r */ + for(i=0;izfabs(max)) { + k=i; + max=m[i*n+j]; + } + + /* non intersible matrix */ + if (max==0) return 1; + + + /* permutation des lignes j et k */ + if (k!=j) { + for(i=0;im[0][0],&tmp.m[0][0],4); +} + +void gl_M4_Rotate(M4 *a,float t,int u) +{ + float s,c; + int v,w; + if ((v=u+1)>2) v=0; + if ((w=v+1)>2) w=0; + s=zsin(t); + c=zcos(t); + gl_M4_Id(a); + a->m[v][v]=c; a->m[v][w]=-s; + a->m[w][v]=s; a->m[w][w]=c; +} + + +/* inverse of a 3x3 matrix */ +void gl_M3_Inv(M3 *a,M3 *m) +{ + float det; + + det = m->m[0][0]*m->m[1][1]*m->m[2][2]-m->m[0][0]*m->m[1][2]*m->m[2][1]- + m->m[1][0]*m->m[0][1]*m->m[2][2]+m->m[1][0]*m->m[0][2]*m->m[2][1]+ + m->m[2][0]*m->m[0][1]*m->m[1][2]-m->m[2][0]*m->m[0][2]*m->m[1][1]; + + a->m[0][0] = (m->m[1][1]*m->m[2][2]-m->m[1][2]*m->m[2][1])/det; + a->m[0][1] = -(m->m[0][1]*m->m[2][2]-m->m[0][2]*m->m[2][1])/det; + a->m[0][2] = -(-m->m[0][1]*m->m[1][2]+m->m[0][2]*m->m[1][1])/det; + + a->m[1][0] = -(m->m[1][0]*m->m[2][2]-m->m[1][2]*m->m[2][0])/det; + a->m[1][1] = (m->m[0][0]*m->m[2][2]-m->m[0][2]*m->m[2][0])/det; + a->m[1][2] = -(m->m[0][0]*m->m[1][2]-m->m[0][2]*m->m[1][0])/det; + + a->m[2][0] = (m->m[1][0]*m->m[2][1]-m->m[1][1]*m->m[2][0])/det; + a->m[2][1] = -(m->m[0][0]*m->m[2][1]-m->m[0][1]*m->m[2][0])/det; + a->m[2][2] = (m->m[0][0]*m->m[1][1]-m->m[0][1]*m->m[1][0])/det; +} + + +/* vector arithmetic */ + +int gl_V3_Norm(V3 *a) +{ + float n; + n=zsqrt(a->X*a->X+a->Y*a->Y+a->Z*a->Z); + if (n==0) return 1; + a->X/=n; + a->Y/=n; + a->Z/=n; + return 0; +} + +V3 gl_V3_New(float x,float y,float z) +{ + V3 a; + a.X=x; + a.Y=y; + a.Z=z; + return a; +} + +V4 gl_V4_New(float x,float y,float z,float w) +{ + V4 a; + a.X=x; + a.Y=y; + a.Z=z; + a.W=w; + return a; +} + + diff --git a/apps/tinygl/src/TinyGL/src/zmath.h b/apps/tinygl/src/TinyGL/src/zmath.h new file mode 100644 index 0000000..3bbb1d6 --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/zmath.h @@ -0,0 +1,53 @@ +#ifndef __ZMATH__ +#define __ZMATH__ + +/* Matrix & Vertex */ + +typedef struct { + float m[4][4]; +} M4; + +typedef struct { + float m[3][3]; +} M3; + +typedef struct { + float m[3][4]; +} M34; + + +#define X v[0] +#define Y v[1] +#define Z v[2] +#define W v[3] + +typedef struct { + float v[3]; +} V3; + +typedef struct { + float v[4]; +} V4; + +void gl_M4_Id(M4 *a); +int gl_M4_IsId(M4 *a); +void gl_M4_Move(M4 *a,M4 *b); +void gl_MoveV3(V3 *a,V3 *b); +void gl_MulM4V3(V3 *a,M4 *b,V3 *c); +void gl_MulM3V3(V3 *a,M4 *b,V3 *c); + +void gl_M4_MulV4(V4 * a,M4 *b,V4 * c); +void gl_M4_InvOrtho(M4 *a,M4 b); +void gl_M4_Inv(M4 *a,M4 *b); +void gl_M4_Mul(M4 *c,M4 *a,M4 *b); +void gl_M4_MulLeft(M4 *c,M4 *a); +void gl_M4_Transpose(M4 *a,M4 *b); +void gl_M4_Rotate(M4 *c,float t,int u); +int gl_V3_Norm(V3 *a); + +V3 gl_V3_New(float x,float y,float z); +V4 gl_V4_New(float x,float y,float z,float w); + +int gl_Matrix_Inv(float *r,float *m,int n); + +#endif /* __ZMATH__ */ diff --git a/apps/tinygl/src/TinyGL/src/ztriangle.c b/apps/tinygl/src/TinyGL/src/ztriangle.c new file mode 100644 index 0000000..a907903 --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/ztriangle.c @@ -0,0 +1,394 @@ +//#include +#include "zbuffer.h" + +#define ZCMP(z,zpix) ((z) >= (zpix)) + +void ZB_fillTriangleFlat(ZBuffer *zb, + ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2) +{ +#if TGL_FEATURE_RENDER_BITS == 24 + unsigned char colorR, colorG, colorB; +#else + int color; +#endif + +#define INTERP_Z + +#if TGL_FEATURE_RENDER_BITS == 24 + +#define DRAW_INIT() \ +{ \ + colorR=p2->r>>8; \ + colorG=p2->g>>8; \ + colorB=p2->b>>8; \ +} + +#define PUT_PIXEL(_a) \ +{ \ + zz=z >> ZB_POINT_Z_FRAC_BITS; \ + if (ZCMP(zz,pz[_a])) { \ + pp[3 * _a]=colorR;\ + pp[3 * _a + 1]=colorG;\ + pp[3 * _a + 2]=colorB;\ + pz[_a]=zz; \ + }\ + z+=dzdx; \ +} + +#else + +#define DRAW_INIT() \ +{ \ + color=RGB_TO_PIXEL(p2->r,p2->g,p2->b); \ +} + +#define PUT_PIXEL(_a) \ +{ \ + zz=z >> ZB_POINT_Z_FRAC_BITS; \ + if (ZCMP(zz,pz[_a])) { \ + pp[_a]=color; \ + pz[_a]=zz; \ + } \ + z+=dzdx; \ +} +#endif /* TGL_FEATURE_RENDER_BITS == 24 */ + +#include "ztriangle.h" +} + +/* + * Smooth filled triangle. + * The code below is very tricky :) + */ + +void ZB_fillTriangleSmooth(ZBuffer *zb, + ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2) +{ +#if TGL_FEATURE_RENDER_BITS == 16 + int _drgbdx; +#endif + +#define INTERP_Z +#define INTERP_RGB + +#define SAR_RND_TO_ZERO(v,n) (v / (1<> ZB_POINT_Z_FRAC_BITS; \ + if (ZCMP(zz,pz[_a])) { \ + pp[3 * _a]=or1 >> 8;\ + pp[3 * _a + 1]=og1 >> 8;\ + pp[3 * _a + 2]=ob1 >> 8;\ + pz[_a]=zz; \ + }\ + z+=dzdx; \ + og1+=dgdx; \ + or1+=drdx; \ + ob1+=dbdx; \ +} + +#elif TGL_FEATURE_RENDER_BITS == 16 + +#define DRAW_INIT() \ +{ \ + _drgbdx=(SAR_RND_TO_ZERO(drdx,6) << 22) & 0xFFC00000; \ + _drgbdx|=SAR_RND_TO_ZERO(dgdx,5) & 0x000007FF; \ + _drgbdx|=(SAR_RND_TO_ZERO(dbdx,7) << 12) & 0x001FF000; \ +} + + +#define PUT_PIXEL(_a) \ +{ \ + zz=z >> ZB_POINT_Z_FRAC_BITS; \ + if (ZCMP(zz,pz[_a])) { \ + tmp=rgb & 0xF81F07E0; \ + pp[_a]=tmp | (tmp >> 16); \ + pz[_a]=zz; \ + } \ + z+=dzdx; \ + rgb=(rgb+drgbdx) & ( ~ 0x00200800); \ +} + +#define DRAW_LINE() \ +{ \ + register unsigned short *pz; \ + register PIXEL *pp; \ + register unsigned int tmp,z,zz,rgb,drgbdx; \ + register int n; \ + n=(x2 >> 16) - x1; \ + pp=pp1+x1; \ + pz=pz1+x1; \ + z=z1; \ + rgb=(r1 << 16) & 0xFFC00000; \ + rgb|=(g1 >> 5) & 0x000007FF; \ + rgb|=(b1 << 5) & 0x001FF000; \ + drgbdx=_drgbdx; \ + while (n>=3) { \ + PUT_PIXEL(0); \ + PUT_PIXEL(1); \ + PUT_PIXEL(2); \ + PUT_PIXEL(3); \ + pz+=4; \ + pp+=4; \ + n-=4; \ + } \ + while (n>=0) { \ + PUT_PIXEL(0); \ + pz+=1; \ + pp+=1; \ + n-=1; \ + } \ +} + +#else + +#define DRAW_INIT() \ +{ \ +} + +#define PUT_PIXEL(_a) \ +{ \ + zz=z >> ZB_POINT_Z_FRAC_BITS; \ + if (ZCMP(zz,pz[_a])) { \ + pp[_a] = RGB_TO_PIXEL(or1, og1, ob1);\ + pz[_a]=zz; \ + }\ + z+=dzdx; \ + og1+=dgdx; \ + or1+=drdx; \ + ob1+=dbdx; \ +} + +#endif /* TGL_FEATURE_RENDER_BITS */ + +#include "ztriangle.h" +} + +void ZB_setTexture(ZBuffer *zb,PIXEL *texture) +{ + zb->current_texture=texture; +} + +void ZB_fillTriangleMapping(ZBuffer *zb, + ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2) +{ + PIXEL *texture; + +#define INTERP_Z +#define INTERP_ST + +#define DRAW_INIT() \ +{ \ + texture=zb->current_texture; \ +} + +#if TGL_FEATURE_RENDER_BITS == 24 + +#define PUT_PIXEL(_a) \ +{ \ + unsigned char *ptr;\ + zz=z >> ZB_POINT_Z_FRAC_BITS; \ + if (ZCMP(zz,pz[_a])) { \ + ptr = texture + (((t & 0x3FC00000) | s) >> 14) * 3; \ + pp[3 * _a]= ptr[0];\ + pp[3 * _a + 1]= ptr[1];\ + pp[3 * _a + 2]= ptr[2];\ + pz[_a]=zz; \ + } \ + z+=dzdx; \ + s+=dsdx; \ + t+=dtdx; \ +} + +#else + +#define PUT_PIXEL(_a) \ +{ \ + zz=z >> ZB_POINT_Z_FRAC_BITS; \ + if (ZCMP(zz,pz[_a])) { \ + pp[_a]=texture[((t & 0x3FC00000) | s) >> 14]; \ + pz[_a]=zz; \ + } \ + z+=dzdx; \ + s+=dsdx; \ + t+=dtdx; \ +} + +#endif + +#include "ztriangle.h" +} + +/* + * Texture mapping with perspective correction. + * We use the gradient method to make less divisions. + * TODO: pipeline the division + */ +#if 1 + +void ZB_fillTriangleMappingPerspective(ZBuffer *zb, + ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2) +{ + PIXEL *texture; + float fdzdx,fndzdx,ndszdx,ndtzdx; + +#define INTERP_Z +#define INTERP_STZ + +#define NB_INTERP 8 + +#define DRAW_INIT() \ +{ \ + texture=zb->current_texture;\ + fdzdx=(float)dzdx;\ + fndzdx=NB_INTERP * fdzdx;\ + ndszdx=NB_INTERP * dszdx;\ + ndtzdx=NB_INTERP * dtzdx;\ +} + + +#if TGL_FEATURE_RENDER_BITS == 24 + +#define PUT_PIXEL(_a) \ +{ \ + unsigned char *ptr;\ + zz=z >> ZB_POINT_Z_FRAC_BITS; \ + if (ZCMP(zz,pz[_a])) { \ + ptr = texture + (((t & 0x3FC00000) | (s & 0x003FC000)) >> 14) * 3;\ + pp[3 * _a]= ptr[0];\ + pp[3 * _a + 1]= ptr[1];\ + pp[3 * _a + 2]= ptr[2];\ + pz[_a]=zz; \ + } \ + z+=dzdx; \ + s+=dsdx; \ + t+=dtdx; \ +} + +#else + +#define PUT_PIXEL(_a) \ +{ \ + zz=z >> ZB_POINT_Z_FRAC_BITS; \ + if (ZCMP(zz,pz[_a])) { \ + pp[_a]=*(PIXEL *)((char *)texture+ \ + (((t & 0x3FC00000) | (s & 0x003FC000)) >> (17 - PSZSH)));\ + pz[_a]=zz; \ + } \ + z+=dzdx; \ + s+=dsdx; \ + t+=dtdx; \ +} + +#endif + +#define DRAW_LINE() \ +{ \ + register unsigned short *pz; \ + register PIXEL *pp; \ + register unsigned int s,t,z,zz; \ + register int n,dsdx,dtdx; \ + float sz,tz,fz,zinv; \ + n=(x2>>16)-x1; \ + fz=(float)z1;\ + zinv=1.0 / fz;\ + pp=(PIXEL *)((char *)pp1 + x1 * PSZB); \ + pz=pz1+x1; \ + z=z1; \ + sz=sz1;\ + tz=tz1;\ + while (n>=(NB_INTERP-1)) { \ + {\ + float ss,tt;\ + ss=(sz * zinv);\ + tt=(tz * zinv);\ + s=(int) ss;\ + t=(int) tt;\ + dsdx= (int)( (dszdx - ss*fdzdx)*zinv );\ + dtdx= (int)( (dtzdx - tt*fdzdx)*zinv );\ + fz+=fndzdx;\ + zinv=1.0 / fz;\ + }\ + PUT_PIXEL(0); \ + PUT_PIXEL(1); \ + PUT_PIXEL(2); \ + PUT_PIXEL(3); \ + PUT_PIXEL(4); \ + PUT_PIXEL(5); \ + PUT_PIXEL(6); \ + PUT_PIXEL(7); \ + pz+=NB_INTERP; \ + pp=(PIXEL *)((char *)pp + NB_INTERP * PSZB);\ + n-=NB_INTERP; \ + sz+=ndszdx;\ + tz+=ndtzdx;\ + } \ + {\ + float ss,tt;\ + ss=(sz * zinv);\ + tt=(tz * zinv);\ + s=(int) ss;\ + t=(int) tt;\ + dsdx= (int)( (dszdx - ss*fdzdx)*zinv );\ + dtdx= (int)( (dtzdx - tt*fdzdx)*zinv );\ + }\ + while (n>=0) { \ + PUT_PIXEL(0); \ + pz+=1; \ + pp=(PIXEL *)((char *)pp + PSZB);\ + n-=1; \ + } \ +} + +#include "ztriangle.h" +} + +#endif + +#if 0 + +/* slow but exact version (only there for reference, incorrect for 24 + bits) */ + +void ZB_fillTriangleMappingPerspective(ZBuffer *zb, + ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2) +{ + PIXEL *texture; + +#define INTERP_Z +#define INTERP_STZ + +#define DRAW_INIT() \ +{ \ + texture=zb->current_texture; \ +} + +#define PUT_PIXEL(_a) \ +{ \ + float zinv; \ + int s,t; \ + zz=z >> ZB_POINT_Z_FRAC_BITS; \ + if (ZCMP(zz,pz[_a])) { \ + zinv= 1.0 / (float) z; \ + s= (int) (sz * zinv); \ + t= (int) (tz * zinv); \ + pp[_a]=texture[((t & 0x3FC00000) | s) >> 14]; \ + pz[_a]=zz; \ + } \ + z+=dzdx; \ + sz+=dszdx; \ + tz+=dtzdx; \ +} + +#include "ztriangle.h" +} + + +#endif diff --git a/apps/tinygl/src/TinyGL/src/ztriangle.h b/apps/tinygl/src/TinyGL/src/ztriangle.h new file mode 100644 index 0000000..b614264 --- /dev/null +++ b/apps/tinygl/src/TinyGL/src/ztriangle.h @@ -0,0 +1,363 @@ +/* + * We draw a triangle with various interpolations + */ + +{ + ZBufferPoint *t,*pr1,*pr2,*l1,*l2; + float fdx1, fdx2, fdy1, fdy2, fz, d1, d2; + unsigned short *pz1; + PIXEL *pp1; + int part,update_left,update_right; + + int nb_lines,dx1,dy1,tmp,dx2,dy2; + + int error,derror; + int x1,dxdy_min,dxdy_max; +/* warning: x2 is multiplied by 2^16 */ + int x2,dx2dy2; + +#ifdef INTERP_Z + int z1,dzdx,dzdy,dzdl_min,dzdl_max; +#endif +#ifdef INTERP_RGB + int r1,drdx,drdy,drdl_min,drdl_max; + int g1,dgdx,dgdy,dgdl_min,dgdl_max; + int b1,dbdx,dbdy,dbdl_min,dbdl_max; +#endif +#ifdef INTERP_ST + int s1,dsdx,dsdy,dsdl_min,dsdl_max; + int t1,dtdx,dtdy,dtdl_min,dtdl_max; +#endif +#ifdef INTERP_STZ + float sz1,dszdx,dszdy,dszdl_min,dszdl_max; + float tz1,dtzdx,dtzdy,dtzdl_min,dtzdl_max; +#endif + + /* we sort the vertex with increasing y */ + if (p1->y < p0->y) { + t = p0; + p0 = p1; + p1 = t; + } + if (p2->y < p0->y) { + t = p2; + p2 = p1; + p1 = p0; + p0 = t; + } else if (p2->y < p1->y) { + t = p1; + p1 = p2; + p2 = t; + } + + /* we compute dXdx and dXdy for all interpolated values */ + + fdx1 = p1->x - p0->x; + fdy1 = p1->y - p0->y; + + fdx2 = p2->x - p0->x; + fdy2 = p2->y - p0->y; + + fz = fdx1 * fdy2 - fdx2 * fdy1; + if (fz == 0) + return; + fz = 1.0 / fz; + + fdx1 *= fz; + fdy1 *= fz; + fdx2 *= fz; + fdy2 *= fz; + +#ifdef INTERP_Z + d1 = p1->z - p0->z; + d2 = p2->z - p0->z; + dzdx = (int) (fdy2 * d1 - fdy1 * d2); + dzdy = (int) (fdx1 * d2 - fdx2 * d1); +#endif + +#ifdef INTERP_RGB + d1 = p1->r - p0->r; + d2 = p2->r - p0->r; + drdx = (int) (fdy2 * d1 - fdy1 * d2); + drdy = (int) (fdx1 * d2 - fdx2 * d1); + + d1 = p1->g - p0->g; + d2 = p2->g - p0->g; + dgdx = (int) (fdy2 * d1 - fdy1 * d2); + dgdy = (int) (fdx1 * d2 - fdx2 * d1); + + d1 = p1->b - p0->b; + d2 = p2->b - p0->b; + dbdx = (int) (fdy2 * d1 - fdy1 * d2); + dbdy = (int) (fdx1 * d2 - fdx2 * d1); + +#endif + +#ifdef INTERP_ST + d1 = p1->s - p0->s; + d2 = p2->s - p0->s; + dsdx = (int) (fdy2 * d1 - fdy1 * d2); + dsdy = (int) (fdx1 * d2 - fdx2 * d1); + + d1 = p1->t - p0->t; + d2 = p2->t - p0->t; + dtdx = (int) (fdy2 * d1 - fdy1 * d2); + dtdy = (int) (fdx1 * d2 - fdx2 * d1); +#endif + +#ifdef INTERP_STZ + { + float zz; + zz=(float) p0->z; + p0->sz= (float) p0->s * zz; + p0->tz= (float) p0->t * zz; + zz=(float) p1->z; + p1->sz= (float) p1->s * zz; + p1->tz= (float) p1->t * zz; + zz=(float) p2->z; + p2->sz= (float) p2->s * zz; + p2->tz= (float) p2->t * zz; + + d1 = p1->sz - p0->sz; + d2 = p2->sz - p0->sz; + dszdx = (fdy2 * d1 - fdy1 * d2); + dszdy = (fdx1 * d2 - fdx2 * d1); + + d1 = p1->tz - p0->tz; + d2 = p2->tz - p0->tz; + dtzdx = (fdy2 * d1 - fdy1 * d2); + dtzdy = (fdx1 * d2 - fdx2 * d1); + } +#endif + + /* screen coordinates */ + + pp1 = (PIXEL *) ((char *) zb->pbuf + zb->linesize * p0->y); + pz1 = zb->zbuf + p0->y * zb->xsize; + + DRAW_INIT(); + + for(part=0;part<2;part++) { + if (part == 0) { + if (fz > 0) { + update_left=1; + update_right=1; + l1=p0; + l2=p2; + pr1=p0; + pr2=p1; + } else { + update_left=1; + update_right=1; + l1=p0; + l2=p1; + pr1=p0; + pr2=p2; + } + nb_lines = p1->y - p0->y; + } else { + /* second part */ + if (fz > 0) { + update_left=0; + update_right=1; + pr1=p1; + pr2=p2; + } else { + update_left=1; + update_right=0; + l1=p1; + l2=p2; + } + nb_lines = p2->y - p1->y + 1; + } + + /* compute the values for the left edge */ + + if (update_left) { + dy1 = l2->y - l1->y; + dx1 = l2->x - l1->x; + if (dy1 > 0) + tmp = (dx1 << 16) / dy1; + else + tmp = 0; + x1 = l1->x; + error = 0; + derror = tmp & 0x0000ffff; + dxdy_min = tmp >> 16; + dxdy_max = dxdy_min + 1; + +#ifdef INTERP_Z + z1=l1->z; + dzdl_min=(dzdy + dzdx * dxdy_min); + dzdl_max=dzdl_min + dzdx; +#endif +#ifdef INTERP_RGB + r1=l1->r; + drdl_min=(drdy + drdx * dxdy_min); + drdl_max=drdl_min + drdx; + + g1=l1->g; + dgdl_min=(dgdy + dgdx * dxdy_min); + dgdl_max=dgdl_min + dgdx; + + b1=l1->b; + dbdl_min=(dbdy + dbdx * dxdy_min); + dbdl_max=dbdl_min + dbdx; +#endif +#ifdef INTERP_ST + s1=l1->s; + dsdl_min=(dsdy + dsdx * dxdy_min); + dsdl_max=dsdl_min + dsdx; + + t1=l1->t; + dtdl_min=(dtdy + dtdx * dxdy_min); + dtdl_max=dtdl_min + dtdx; +#endif +#ifdef INTERP_STZ + sz1=l1->sz; + dszdl_min=(dszdy + dszdx * dxdy_min); + dszdl_max=dszdl_min + dszdx; + + tz1=l1->tz; + dtzdl_min=(dtzdy + dtzdx * dxdy_min); + dtzdl_max=dtzdl_min + dtzdx; +#endif + } + + /* compute values for the right edge */ + + if (update_right) { + dx2 = (pr2->x - pr1->x); + dy2 = (pr2->y - pr1->y); + if (dy2>0) + dx2dy2 = ( dx2 << 16) / dy2; + else + dx2dy2 = 0; + x2 = pr1->x << 16; + } + + /* we draw all the scan line of the part */ + + while (nb_lines>0) { + nb_lines--; +#ifndef DRAW_LINE + /* generic draw line */ + { + register PIXEL *pp; + register int n; +#ifdef INTERP_Z + register unsigned short *pz; + register unsigned int z,zz; +#endif +#ifdef INTERP_RGB + register unsigned int or1,og1,ob1; +#endif +#ifdef INTERP_ST + register unsigned int s,t; +#endif +#ifdef INTERP_STZ + float sz,tz; +#endif + + n=(x2 >> 16) - x1; + pp=(PIXEL *)((char *)pp1 + x1 * PSZB); +#ifdef INTERP_Z + pz=pz1+x1; + z=z1; +#endif +#ifdef INTERP_RGB + or1 = r1; + og1 = g1; + ob1 = b1; +#endif +#ifdef INTERP_ST + s=s1; + t=t1; +#endif +#ifdef INTERP_STZ + sz=sz1; + tz=tz1; +#endif + while (n>=3) { + PUT_PIXEL(0); + PUT_PIXEL(1); + PUT_PIXEL(2); + PUT_PIXEL(3); +#ifdef INTERP_Z + pz+=4; +#endif + pp=(PIXEL *)((char *)pp + 4 * PSZB); + n-=4; + } + while (n>=0) { + PUT_PIXEL(0); +#ifdef INTERP_Z + pz+=1; +#endif + pp=(PIXEL *)((char *)pp + PSZB); + n-=1; + } + } +#else + DRAW_LINE(); +#endif + + /* left edge */ + error+=derror; + if (error > 0) { + error-=0x10000; + x1+=dxdy_max; +#ifdef INTERP_Z + z1+=dzdl_max; +#endif +#ifdef INTERP_RGB + r1+=drdl_max; + g1+=dgdl_max; + b1+=dbdl_max; +#endif +#ifdef INTERP_ST + s1+=dsdl_max; + t1+=dtdl_max; +#endif +#ifdef INTERP_STZ + sz1+=dszdl_max; + tz1+=dtzdl_max; +#endif + } else { + x1+=dxdy_min; +#ifdef INTERP_Z + z1+=dzdl_min; +#endif +#ifdef INTERP_RGB + r1+=drdl_min; + g1+=dgdl_min; + b1+=dbdl_min; +#endif +#ifdef INTERP_ST + s1+=dsdl_min; + t1+=dtdl_min; +#endif +#ifdef INTERP_STZ + sz1+=dszdl_min; + tz1+=dtzdl_min; +#endif + } + + /* right edge */ + x2+=dx2dy2; + + /* screen coordinates */ + pp1=(PIXEL *)((char *)pp1 + zb->linesize); + pz1+=zb->xsize; + } + } +} + +#undef INTERP_Z +#undef INTERP_RGB +#undef INTERP_ST +#undef INTERP_STZ + +#undef DRAW_INIT +#undef DRAW_LINE +#undef PUT_PIXEL diff --git a/apps/tinygl/src/console.zig b/apps/tinygl/src/console.zig new file mode 100644 index 0000000..c5ae395 --- /dev/null +++ b/apps/tinygl/src/console.zig @@ -0,0 +1,49 @@ +const std = @import("std"); +extern fn console_write(data: [*]const u8, len: usize) void; +var wbuf:[4096]u8 = undefined; +var cw = ConsoleWriter.init(&wbuf); +const uvm = @import("uvm.zig"); + +pub const WriteError = error{ Unsupported, NotConnected }; + +pub const ConsoleWriter = struct { + interface: std.Io.Writer, + err: ?WriteError = null, + + fn drain(w: *std.Io.Writer, data: []const []const u8, splat: usize) std.Io.Writer.Error!usize { + var ret: usize = 0; + + const b = w.buffered(); + uvm.print(b); + _ = w.consume(b.len); + + for (data) |d| { + uvm.print(d); + ret += d.len; + } + + const pattern = data[data.len - 1]; + for (0..splat) |_| { + uvm.print(pattern); + ret += pattern.len; + } + + return ret; + } + + pub fn init(buf: []u8) ConsoleWriter { + return ConsoleWriter{ + .interface = .{ + .buffer = buf, + .vtable = &.{ + .drain = drain, + }, + }, + }; + } +}; + +pub fn getWriter() *std.Io.Writer { + return &cw.interface; +} + diff --git a/apps/tinygl/src/main.zig b/apps/tinygl/src/main.zig new file mode 100644 index 0000000..db44a1e --- /dev/null +++ b/apps/tinygl/src/main.zig @@ -0,0 +1,416 @@ +const uvm = @import("uvm.zig"); +const zeptolibc = @import("zeptolibc"); +const std = @import("std"); + +const console = @import("console.zig").getWriter(); +const tgl = @cImport({ + @cInclude("GL/gl.h"); + @cInclude("zgl.h"); +}); +const sdlkeys = @cImport({ + @cInclude("SDL_scancode.h"); +}); + +const WIDTH = 320; +const HEIGHT = 200; + +var leftPressed: bool = false; +var rightPressed: bool = false; +var upPressed: bool = false; +var downPressed: bool = false; + +fn checkKeys() void { + var pressed:bool = undefined; + var scancode:u16 = undefined; + if (uvm.getkey(&scancode, &pressed)) { + if (pressed) { + switch(scancode) { + sdlkeys.SDL_SCANCODE_RIGHT => rightPressed = true, + sdlkeys.SDL_SCANCODE_LEFT => leftPressed = true, + sdlkeys.SDL_SCANCODE_UP => upPressed = true, + sdlkeys.SDL_SCANCODE_DOWN => downPressed = true, + else => {}, + } + } else { + switch(scancode) { + sdlkeys.SDL_SCANCODE_RIGHT => rightPressed = false, + sdlkeys.SDL_SCANCODE_LEFT => leftPressed = false, + sdlkeys.SDL_SCANCODE_UP => upPressed = false, + sdlkeys.SDL_SCANCODE_DOWN => downPressed = false, + else => {}, + } + } + } +} + +var view_rotx: tgl.GLfloat = 20.0; +var view_roty: tgl.GLfloat = 30.0; +var view_rotz: tgl.GLfloat = 0.0; +var gear1: tgl.GLuint = undefined; +var gear2: tgl.GLuint = undefined; +var gear3: tgl.GLuint = undefined; +var angle: tgl.GLfloat = 0.0; +var pos: [4]tgl.GLfloat = .{ 5.0, 5.0, 10.0, 0.0 }; +var red: [4]tgl.GLfloat = .{ 0.8, 0.1, 0.0, 1.0 }; +var green: [4]tgl.GLfloat = .{ 0.0, 0.8, 0.2, 1.0 }; +var blue: [4]tgl.GLfloat = .{ 0.2, 0.2, 1.0, 1.0 }; + +var gfxFramebuffer: [WIDTH * HEIGHT]u32 = undefined; + +fn gear(inner_radius: tgl.GLfloat, outer_radius: tgl.GLfloat, width: tgl.GLfloat, teeth: tgl.GLint, tooth_depth: tgl.GLfloat) void { + var i: tgl.GLint = undefined; + var r0: tgl.GLfloat = undefined; + var r1: tgl.GLfloat = undefined; + var r2: tgl.GLfloat = undefined; + var ang: tgl.GLfloat = undefined; + var da: tgl.GLfloat = undefined; + var u: tgl.GLfloat = undefined; + var v: tgl.GLfloat = undefined; + var len: tgl.GLfloat = undefined; + + r0 = inner_radius; + r1 = outer_radius - tooth_depth / 2.0; + r2 = outer_radius + tooth_depth / 2.0; + + da = 2.0 * std.math.pi / @as(tgl.GLfloat, @floatFromInt(teeth)) / 4.0; + + tgl.glShadeModel(tgl.GL_FLAT); + + tgl.glNormal3f(0.0, 0.0, 1.0); + + // draw front face + tgl.glBegin(tgl.GL_QUAD_STRIP); + + i = 0; + while (i <= teeth) : (i += 1) { + ang = @as(tgl.GLfloat, @floatFromInt(i)) * 2.0 * std.math.pi / @as(tgl.GLfloat, @floatFromInt(teeth)); + tgl.glVertex3f(r0 * @cos(ang), r0 * @sin(ang), width * 0.5); + tgl.glVertex3f(r1 * @cos(ang), r1 * @sin(ang), width * 0.5); + tgl.glVertex3f(r0 * @cos(ang), r0 * @sin(ang), width * 0.5); + tgl.glVertex3f(r1 * @cos(ang + 3 * da), r1 * @sin(ang + 3 * da), width * 0.5); + } + tgl.glEnd(); + + // draw front sides of teeth + tgl.glBegin(tgl.GL_QUADS); + da = 2.0 * std.math.pi / @as(tgl.GLfloat, @floatFromInt(teeth)) / 4.0; + i = 0; + while (i < teeth) : (i += 1) { + ang = @as(tgl.GLfloat, @floatFromInt(i)) * 2.0 * std.math.pi / @as(tgl.GLfloat, @floatFromInt(teeth)); + + tgl.glVertex3f(r1 * @cos(ang), r1 * @sin(ang), width * 0.5); + tgl.glVertex3f(r2 * @cos(ang + da), r2 * @sin(ang + da), width * 0.5); + tgl.glVertex3f(r2 * @cos(ang + 2 * da), r2 * @sin(ang + 2 * da), width * 0.5); + tgl.glVertex3f(r1 * @cos(ang + 3 * da), r1 * @sin(ang + 3 * da), width * 0.5); + } + tgl.glEnd(); + + tgl.glNormal3f(0.0, 0.0, -1.0); + + // draw back face + tgl.glBegin(tgl.GL_QUAD_STRIP); + i = 0; + while (i <= teeth) : (i += 1) { + ang = @as(tgl.GLfloat, @floatFromInt(i)) * 2.0 * std.math.pi / @as(tgl.GLfloat, @floatFromInt(teeth)); + tgl.glVertex3f(r1 * @cos(ang), r1 * @sin(ang), -width * 0.5); + tgl.glVertex3f(r0 * @cos(ang), r0 * @sin(ang), -width * 0.5); + tgl.glVertex3f(r1 * @cos(ang + 3 * da), r1 * @sin(ang + 3 * da), -width * 0.5); + tgl.glVertex3f(r0 * @cos(ang), r0 * @sin(ang), -width * 0.5); + } + tgl.glEnd(); + + // draw back sides of teeth + tgl.glBegin(tgl.GL_QUADS); + da = 2.0 * std.math.pi / @as(tgl.GLfloat, @floatFromInt(teeth)) / 4.0; + i = 0; + while (i < teeth) : (i += 1) { + ang = @as(tgl.GLfloat, @floatFromInt(i)) * 2.0 * std.math.pi / @as(tgl.GLfloat, @floatFromInt(teeth)); + + tgl.glVertex3f(r1 * @cos(ang + 3 * da), r1 * @sin(ang + 3 * da), -width * 0.5); + tgl.glVertex3f(r2 * @cos(ang + 2 * da), r2 * @sin(ang + 2 * da), -width * 0.5); + tgl.glVertex3f(r2 * @cos(ang + da), r2 * @sin(ang + da), -width * 0.5); + tgl.glVertex3f(r1 * @cos(ang), r1 * @sin(ang), -width * 0.5); + } + tgl.glEnd(); + + // draw outward faces of teeth + tgl.glBegin(tgl.GL_QUAD_STRIP); + i = 0; + while (i <= teeth) : (i += 1) { + ang = @as(tgl.GLfloat, @floatFromInt(i)) * 2.0 * std.math.pi / @as(tgl.GLfloat, @floatFromInt(teeth)); + + tgl.glVertex3f(r1 * @cos(ang), r1 * @sin(ang), width * 0.5); + tgl.glVertex3f(r1 * @cos(ang), r1 * @sin(ang), -width * 0.5); + u = r2 * @cos(ang + da) - r1 * @cos(ang); + v = r2 * @sin(ang + da) - r1 * @sin(ang); + len = std.math.sqrt(u * u + v * v); + u /= len; + v /= len; + tgl.glNormal3f(v, -u, 0.0); + tgl.glVertex3f(r2 * @cos(ang + da), r2 * @sin(ang + da), width * 0.5); + tgl.glVertex3f(r2 * @cos(ang + da), r2 * @sin(ang + da), -width * 0.5); + tgl.glNormal3f(@cos(ang), @sin(ang), 0.0); + tgl.glVertex3f(r2 * @cos(ang + 2 * da), r2 * @sin(ang + 2 * da), width * 0.5); + tgl.glVertex3f(r2 * @cos(ang + 2 * da), r2 * @sin(ang + 2 * da), -width * 0.5); + u = r1 * @cos(ang + 3 * da) - r2 * @cos(ang + 2 * da); + v = r1 * @sin(ang + 3 * da) - r2 * @sin(ang + 2 * da); + tgl.glNormal3f(v, -u, 0.0); + tgl.glVertex3f(r1 * @cos(ang + 3 * da), r1 * @sin(ang + 3 * da), width * 0.5); + tgl.glVertex3f(r1 * @cos(ang + 3 * da), r1 * @sin(ang + 3 * da), -width * 0.5); + tgl.glNormal3f(@cos(ang), @sin(ang), 0.0); + } + + tgl.glVertex3f(r1 * @cos(0.0), r1 * @sin(0.0), width * 0.5); + tgl.glVertex3f(r1 * @cos(0.0), r1 * @sin(0.0), -width * 0.5); + + tgl.glEnd(); + + tgl.glShadeModel(tgl.GL_SMOOTH); + + // draw inside radius cylinder + tgl.glBegin(tgl.GL_QUAD_STRIP); + i = 0; + while (i <= teeth) : (i += 1) { + ang = @as(tgl.GLfloat, @floatFromInt(i)) * 2.0 * std.math.pi / @as(tgl.GLfloat, @floatFromInt(teeth)); + tgl.glNormal3f(-@cos(ang), -@sin(ang), 0.0); + tgl.glVertex3f(r0 * @cos(ang), r0 * @sin(ang), -width * 0.5); + tgl.glVertex3f(r0 * @cos(ang), r0 * @sin(ang), width * 0.5); + } + tgl.glEnd(); +} + +fn make_object() tgl.GLuint { + var list: tgl.GLuint = undefined; + + list = tgl.glGenLists(1); + + tgl.glNewList(list, tgl.GL_COMPILE); + + tgl.glBegin(tgl.GL_LINE_LOOP); + tgl.glColor3f(1.0, 1.0, 1.0); + tgl.glVertex3f(1.0, 0.5, -0.4); + tgl.glColor3f(1.0, 0.0, 0.0); + tgl.glVertex3f(1.0, -0.5, -0.4); + tgl.glColor3f(0.0, 1.0, 0.0); + tgl.glVertex3f(-1.0, -0.5, -0.4); + tgl.glColor3f(0.0, 0.0, 1.0); + tgl.glVertex3f(-1.0, 0.5, -0.4); + tgl.glEnd(); + + tgl.glColor3f(1.0, 1.0, 1.0); + + tgl.glBegin(tgl.GL_LINE_LOOP); + tgl.glVertex3f(1.0, 0.5, 0.4); + tgl.glVertex3f(1.0, -0.5, 0.4); + tgl.glVertex3f(-1.0, -0.5, 0.4); + tgl.glVertex3f(-1.0, 0.5, 0.4); + tgl.glEnd(); + + tgl.glBegin(tgl.GL_LINES); + tgl.glVertex3f(1.0, 0.5, -0.4); + tgl.glVertex3f(1.0, 0.5, 0.4); + tgl.glVertex3f(1.0, -0.5, -0.4); + tgl.glVertex3f(1.0, -0.5, 0.4); + tgl.glVertex3f(-1.0, -0.5, -0.4); + tgl.glVertex3f(-1.0, -0.5, 0.4); + tgl.glVertex3f(-1.0, 0.5, -0.4); + tgl.glVertex3f(-1.0, 0.5, 0.4); + tgl.glEnd(); + + tgl.glEndList(); + + return list; +} + +fn reshape(width: c_int, height: c_int) void { + const h: tgl.GLfloat = @as(tgl.GLfloat, @floatFromInt(height)) / @as(tgl.GLfloat, @floatFromInt(width)); + + tgl.glViewport(0, 0, @intCast(width), @intCast(height)); + tgl.glMatrixMode(tgl.GL_PROJECTION); + tgl.glLoadIdentity(); + tgl.glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0); + tgl.glMatrixMode(tgl.GL_MODELVIEW); + tgl.glLoadIdentity(); + tgl.glTranslatef(0.0, 0.0, -40.0); + tgl.glClear(tgl.GL_COLOR_BUFFER_BIT | tgl.GL_DEPTH_BUFFER_BIT); +} + +fn consoleWriteFn(data:[]const u8) void { + _ = console.print("{s}", .{data}) catch 0; + _ = console.flush() catch 0; +} + + +//fn scancode_to_doom_key(scancode:u16) pd.doom_key_t { +// return switch(scancode) { +// sdlkeys.SDL_SCANCODE_TAB => pd.DOOM_KEY_TAB, +// sdlkeys.SDL_SCANCODE_RETURN => pd.DOOM_KEY_ENTER, +// sdlkeys.SDL_SCANCODE_ESCAPE => pd.DOOM_KEY_ESCAPE, +// sdlkeys.SDL_SCANCODE_SPACE => pd.DOOM_KEY_SPACE, +// sdlkeys.SDL_SCANCODE_APOSTROPHE => pd.DOOM_KEY_APOSTROPHE, +// sdlkeys.SDL_SCANCODE_KP_MULTIPLY => pd.DOOM_KEY_MULTIPLY, +// sdlkeys.SDL_SCANCODE_COMMA => pd.DOOM_KEY_COMMA, +// sdlkeys.SDL_SCANCODE_MINUS => pd.DOOM_KEY_MINUS, +// sdlkeys.SDL_SCANCODE_PERIOD => pd.DOOM_KEY_PERIOD, +// sdlkeys.SDL_SCANCODE_SLASH => pd.DOOM_KEY_SLASH, +// sdlkeys.SDL_SCANCODE_0 => pd.DOOM_KEY_0, +// sdlkeys.SDL_SCANCODE_1 => pd.DOOM_KEY_1, +// sdlkeys.SDL_SCANCODE_2 => pd.DOOM_KEY_2, +// sdlkeys.SDL_SCANCODE_3 => pd.DOOM_KEY_3, +// sdlkeys.SDL_SCANCODE_4 => pd.DOOM_KEY_4, +// sdlkeys.SDL_SCANCODE_5 => pd.DOOM_KEY_5, +// sdlkeys.SDL_SCANCODE_6 => pd.DOOM_KEY_6, +// sdlkeys.SDL_SCANCODE_7 => pd.DOOM_KEY_7, +// sdlkeys.SDL_SCANCODE_8 => pd.DOOM_KEY_8, +// sdlkeys.SDL_SCANCODE_9 => pd.DOOM_KEY_9, +// sdlkeys.SDL_SCANCODE_SEMICOLON => pd.DOOM_KEY_SEMICOLON, +// sdlkeys.SDL_SCANCODE_EQUALS => pd.DOOM_KEY_EQUALS, +// sdlkeys.SDL_SCANCODE_LEFTBRACKET => pd.DOOM_KEY_LEFT_BRACKET, +// sdlkeys.SDL_SCANCODE_RIGHTBRACKET => pd.DOOM_KEY_RIGHT_BRACKET, +// sdlkeys.SDL_SCANCODE_A => pd.DOOM_KEY_A, +// sdlkeys.SDL_SCANCODE_B => pd.DOOM_KEY_B, +// sdlkeys.SDL_SCANCODE_C => pd.DOOM_KEY_C, +// sdlkeys.SDL_SCANCODE_D => pd.DOOM_KEY_D, +// sdlkeys.SDL_SCANCODE_E => pd.DOOM_KEY_E, +// sdlkeys.SDL_SCANCODE_F => pd.DOOM_KEY_F, +// sdlkeys.SDL_SCANCODE_G => pd.DOOM_KEY_G, +// sdlkeys.SDL_SCANCODE_H => pd.DOOM_KEY_H, +// sdlkeys.SDL_SCANCODE_I => pd.DOOM_KEY_I, +// sdlkeys.SDL_SCANCODE_J => pd.DOOM_KEY_J, +// sdlkeys.SDL_SCANCODE_K => pd.DOOM_KEY_K, +// sdlkeys.SDL_SCANCODE_L => pd.DOOM_KEY_L, +// sdlkeys.SDL_SCANCODE_M => pd.DOOM_KEY_M, +// sdlkeys.SDL_SCANCODE_N => pd.DOOM_KEY_N, +// sdlkeys.SDL_SCANCODE_O => pd.DOOM_KEY_O, +// sdlkeys.SDL_SCANCODE_P => pd.DOOM_KEY_P, +// sdlkeys.SDL_SCANCODE_Q => pd.DOOM_KEY_Q, +// sdlkeys.SDL_SCANCODE_R => pd.DOOM_KEY_R, +// sdlkeys.SDL_SCANCODE_S => pd.DOOM_KEY_S, +// sdlkeys.SDL_SCANCODE_T => pd.DOOM_KEY_T, +// sdlkeys.SDL_SCANCODE_U => pd.DOOM_KEY_U, +// sdlkeys.SDL_SCANCODE_V => pd.DOOM_KEY_V, +// sdlkeys.SDL_SCANCODE_W => pd.DOOM_KEY_W, +// sdlkeys.SDL_SCANCODE_X => pd.DOOM_KEY_X, +// sdlkeys.SDL_SCANCODE_Y => pd.DOOM_KEY_Y, +// sdlkeys.SDL_SCANCODE_Z => pd.DOOM_KEY_Z, +// sdlkeys.SDL_SCANCODE_BACKSPACE => pd.DOOM_KEY_BACKSPACE, +// sdlkeys.SDL_SCANCODE_LCTRL => pd.DOOM_KEY_CTRL, +// sdlkeys.SDL_SCANCODE_RCTRL => pd.DOOM_KEY_CTRL, +// sdlkeys.SDL_SCANCODE_LEFT => pd.DOOM_KEY_LEFT_ARROW, +// sdlkeys.SDL_SCANCODE_UP => pd.DOOM_KEY_UP_ARROW, +// sdlkeys.SDL_SCANCODE_RIGHT => pd.DOOM_KEY_RIGHT_ARROW, +// sdlkeys.SDL_SCANCODE_DOWN => pd.DOOM_KEY_DOWN_ARROW, +// sdlkeys.SDL_SCANCODE_RSHIFT => pd.DOOM_KEY_SHIFT, +// sdlkeys.SDL_SCANCODE_LSHIFT => pd.DOOM_KEY_SHIFT, +// sdlkeys.SDL_SCANCODE_LALT => pd.DOOM_KEY_ALT, +// sdlkeys.SDL_SCANCODE_RALT => pd.DOOM_KEY_ALT, +// sdlkeys.SDL_SCANCODE_F1 => pd.DOOM_KEY_F1, +// sdlkeys.SDL_SCANCODE_F2 => pd.DOOM_KEY_F2, +// sdlkeys.SDL_SCANCODE_F3 => pd.DOOM_KEY_F3, +// sdlkeys.SDL_SCANCODE_F4 => pd.DOOM_KEY_F4, +// sdlkeys.SDL_SCANCODE_F5 => pd.DOOM_KEY_F5, +// sdlkeys.SDL_SCANCODE_F6 => pd.DOOM_KEY_F6, +// sdlkeys.SDL_SCANCODE_F7 => pd.DOOM_KEY_F7, +// sdlkeys.SDL_SCANCODE_F8 => pd.DOOM_KEY_F8, +// sdlkeys.SDL_SCANCODE_F9 => pd.DOOM_KEY_F9, +// sdlkeys.SDL_SCANCODE_F10 => pd.DOOM_KEY_F10, +// sdlkeys.SDL_SCANCODE_F11 => pd.DOOM_KEY_F11, +// sdlkeys.SDL_SCANCODE_F12 => pd.DOOM_KEY_F12, +// sdlkeys.SDL_SCANCODE_PAUSE => pd.DOOM_KEY_PAUSE, +// else => pd.DOOM_KEY_UNKNOWN, +// }; +//} + +fn submain() !void { + // init zepto with a memory allocator and console writer + zeptolibc.init(uvm.allocator(), consoleWriteFn); + + const zb: *tgl.ZBuffer = tgl.ZB_open(WIDTH, HEIGHT, tgl.ZB_MODE_RGBA, 0, 0, 0, &gfxFramebuffer); + tgl.glInit(zb); + + const glCtx: *tgl.GLContext = tgl.gl_get_context(); + glCtx.zb = zb; + + reshape(WIDTH, HEIGHT); + + tgl.glLightfv(tgl.GL_LIGHT0, tgl.GL_POSITION, &pos); + tgl.glEnable(tgl.GL_CULL_FACE); + tgl.glEnable(tgl.GL_LIGHTING); + tgl.glEnable(tgl.GL_LIGHT0); + tgl.glEnable(tgl.GL_DEPTH_TEST); + + // make the gears + gear1 = tgl.glGenLists(1); + tgl.glNewList(gear1, tgl.GL_COMPILE); + tgl.glMaterialfv(tgl.GL_FRONT, tgl.GL_AMBIENT_AND_DIFFUSE, &red); + gear(1.0, 4.0, 1.0, 20, 0.7); + tgl.glEndList(); + + gear2 = tgl.glGenLists(1); + tgl.glNewList(gear2, tgl.GL_COMPILE); + tgl.glMaterialfv(tgl.GL_FRONT, tgl.GL_AMBIENT_AND_DIFFUSE, &green); + gear(0.5, 2.0, 2.0, 10, 0.7); + tgl.glEndList(); + + gear3 = tgl.glGenLists(1); + tgl.glNewList(gear3, tgl.GL_COMPILE); + tgl.glMaterialfv(tgl.GL_FRONT, tgl.GL_AMBIENT_AND_DIFFUSE, &blue); + gear(1.3, 2.0, 0.5, 10, 0.7); + tgl.glEndList(); + + tgl.glEnable(tgl.GL_NORMALIZE); + + while(true) { + checkKeys(); + + if (leftPressed) { + view_roty += 5.0; + } + if (rightPressed) { + view_roty -= 5.0; + } + if (upPressed) { + view_rotx += 5.0; + } + if (downPressed) { + view_rotx -= 5.0; + } + + angle += 2.0; + + tgl.glClear(tgl.GL_COLOR_BUFFER_BIT | tgl.GL_DEPTH_BUFFER_BIT); + + tgl.glPushMatrix(); + tgl.glRotatef(view_rotx, 1.0, 0.0, 0.0); + tgl.glRotatef(view_roty, 0.0, 1.0, 0.0); + tgl.glRotatef(view_rotz, 0.0, 0.0, 1.0); + + tgl.glPushMatrix(); + tgl.glTranslatef(-3.0, -2.0, 0.0); + tgl.glRotatef(angle, 0.0, 0.0, 1.0); + tgl.glCallList(gear1); + tgl.glPopMatrix(); + + tgl.glPushMatrix(); + tgl.glTranslatef(3.1, -2.0, 0.0); + tgl.glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0); + tgl.glCallList(gear2); + tgl.glPopMatrix(); + + tgl.glPushMatrix(); + tgl.glTranslatef(-3.1, 4.2, 0.0); + tgl.glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0); + tgl.glCallList(gear3); + tgl.glPopMatrix(); + + tgl.glPopMatrix(); + + uvm.render(@ptrCast(&gfxFramebuffer), WIDTH * HEIGHT * 4); + } +} + +export fn main() void { + _ = submain() catch { + uvm.println("Caught err"); + }; +} diff --git a/apps/tinygl/src/uvm.zig b/apps/tinygl/src/uvm.zig new file mode 100644 index 0000000..1a1d4e2 --- /dev/null +++ b/apps/tinygl/src/uvm.zig @@ -0,0 +1,84 @@ +const uvm32 = @cImport({ + @cDefine("USE_MAIN", "1"); + @cInclude("uvm32_target.h"); +}); +const buildopts = @import("buildopts"); +const std = @import("std"); + +const extram:[*]u8 = @ptrFromInt(uvm32.UVM32_EXTRAM_BASE); +const extram_len = buildopts.heapsize; + +var fba:std.heap.FixedBufferAllocator = .init(extram[0..extram_len]); + +pub fn allocator() std.mem.Allocator { + return fba.allocator(); +} + +pub inline fn syscall(id: u32, param1: u32, param2: u32) u32 { + var val: u32 = undefined; + asm volatile ("ecall" + : [val] "={a2}" (val), + : [param1] "{a0}" (param1), [param2] "{a1}" (param2), + [id] "{a7}" (id), + : .{ .memory = true }); + return val; +} + +pub inline fn render(fb: [*]const u8, len:u32) void { + _ = syscall(uvm32.UVM32_SYSCALL_RENDER, @intFromPtr(fb), len); +} + +pub inline fn getc() ?u8 { + const key = syscall(uvm32.UVM32_SYSCALL_GETC, 0, 0); + if (key == 0xFFFFFFFF) { + return null; + } else { + return @truncate(key); + } +} + +pub inline fn getkey(code: *u16, pressed:*bool) bool { + const k = syscall(uvm32.UVM32_SYSCALL_GETKEY, 0, 0); + if (k == 0xFFFFFFFF) { + return false; + } else { + code.* = @truncate(k & 0xFFFF); + pressed.* = (k & 0x80000000) != 0; + return true; + } +} + +pub inline fn millis() u32 { + return syscall(uvm32.UVM32_SYSCALL_MILLIS, 0, 0); +} + +// dupeZ would be better, but want to avoid using an allocator +// this is of course, unsafe... +var termination_buf:[512]u8 = undefined; + +pub inline fn print(m: []const u8) void { + @memcpy(termination_buf[0..m.len], m); + termination_buf[m.len] = 0; + const s = termination_buf[0..m.len :0]; + _ = syscall(uvm32.UVM32_SYSCALL_PRINT, @intFromPtr(s.ptr), 0); +} + +pub inline fn println(m: []const u8) void { + @memcpy(termination_buf[0..m.len], m); + termination_buf[m.len] = 0; + const s = termination_buf[0..m.len :0]; + _ = syscall(uvm32.UVM32_SYSCALL_PRINTLN, @intFromPtr(s.ptr), 0); +} + +pub inline fn yield() void { + _ = syscall(uvm32.UVM32_SYSCALL_YIELD, 0, 0); +} + +pub inline fn halt() void { + _ = syscall(uvm32.UVM32_SYSCALL_HALT, 0, 0); +} + +pub inline fn putc(c:u8) void { + _ = syscall(uvm32.UVM32_SYSCALL_PUTC, c, 0); +} + diff --git a/precompiled/tinygl.bin b/precompiled/tinygl.bin new file mode 100755 index 0000000000000000000000000000000000000000..b0f826716f33b93067a6e5bfad16effb9331cfeb GIT binary patch literal 99024 zcmdSCdwf*Yxi`M{?90sL0+F4Bi>NU>GlUQ*I%29t*`o;vS`RATt71pg+FJE(QF}RM z$DIiVkfNK5Qt?elCXj#}=ooX<({@J*>Zxt@)L?5{D@{dvYCYHrYK!FkK5Okgmt55L zJ-_#Set+aMnZ4KLSeK!b>s9Ywu&F{KzTeubTJ@Vs=zn&h__W?OYTHoe+Y9uh!bCaq%e^Y|%30@o<^R)| zMdj{ZpsRj4_vW1T7JBWyX;icYbT#gcn>B;(fDAhAs(1i0mpz&1(Jx0KgQ^B*S0y2b zes3Io7)K-cc|Vtd=v(t>WY=f=Hshji_qUm`WN5Um&5p%ATa+_@lNn29%;2tnNSM zv^U#p@2B}=V7GpnG33glj_Brk^|A6eFWa|S?eTA4W-J*Rt%mGa+=wV=?#+xPGiG*f zPJ4#eUSIxL%%x+D#j`^tW7{Di&o7|94NTW^+n~AF1|62N zwoLTDWLO(RnA6NrE1>_VgL%y7k?8LtlqDN0dGp6BI~((Vcv<(t(aV~nlw}u;R<^f{ zF(+BJF4oWkdKL#_b6Q8C$vkhgy1KSBV1QPm5@W8~gE2^KlNfKqXyqOCcFr%O0^{Iy z$Zq;|*g0d>$(EOL%g-CVyg3^Eb4M$yt4lrJH+potXN*?PQLRzhWOc*J{tYr!bZs5@ z2%f;V=~|y+!`>OK1K=@qMQvb%5B4A9{*m*^Jr!*zkhPjCYh8s5xK8+VnX^alYxm#L z7pon;FLzj9*7RY0asAWP7l)N&(}tDv=HlxpcVL)r_Ar6aZv*v4%tc2#G`dd}`cyG` z9VU(Hhj|@#!f18$V2Shz^i3XCkINPQSAqXkjEa+0W7a9MQ5%S_^mtjKQAx_Vhkku4$C*nz$^_kYvyskZa-3Yq>x7b(G5)7)X+*Y0REBpUKtD zz*YO0QSnm778ub3tPZwCSId?f)$fu`ln5s!9!$YTN}i3B@Luxf9t#ZPd#0cKcKgPv ze{5KNp|_eT8Kc@L_BWKzwXkZ*F-xL8;g9iGC85tg zU*CT|tWQ1$M=SX|+Hik5tPPLuiZT4M`{QABi}GqKWCZF2I7*vl-)LoFGi77cxorM$wDQ0kqu?Oxsob)8epj=`;G6lcxpm;L zIp1LOnXX_?avgFzb@lLy_Nrt#m4#g$F&B*5M$EDMVZTm>-#P{SiA%JG&wTWOj5u{0YAA1(v|OSh$PH)1PO0bC?ZI4IfS18^(HS zN>%wORp9*vxlgT9eMR!>L0e6In8CP zy|(7u_F1o<(_YbCpAMfP8J*8VhaZBycmg^?{)l`JU*BuDF{a3<@1Sn`tS8SgD!bTi z%ni^pqZM_wcA*Zv>pn;LGQTd9^_DPi5B!qAFUbZ!;D;pmAqGE0{L70QjK)6)YCR&_C_rG@w9@neOq!G|`3me)Cd4hTDAK47$VVclk(N#peV>s3z6 zLbRu{!F3Bi`XpK%75yT%;b{C6K8F`WPE){B}(o7)Q#L*-^xZ0-!$toex0gfs=rns^YM}z)cm`%f_rb zfC(BUyqAD=Femn4PV_OI%Marzz}ln$W5ai+5dTkI#A0jKFukZqN*6sO$uk=ih2A7ZRB^isA#GxSo1UIw6-0gN?(u?B#TBpLJrAAuI=?M%=vNs1@G z4={cW9js3Pa^p|AzdivJPCp)LGUC9 zo&>=Y4Ls4n6Ae7kz!PBHMvig86BRt6^-YNL1ml_bbH;9B@m})jhK_1PlyxoIG1&{Q-JY6<{U%wXXaTBFtwP+)(LWF6Y8~yxuW{@ z*ypl(Vjgd&_WI?g7!@7pQ^CBcm;64x_(a{vzO2);eYxf6OB&gid0MtFs}y}n9=_3y zO5RrheL=^>_(Wgql#zY8pUL*cO3+t;`r`7;jLVvtm9<-pz5<>-D>kao*BCYza?G8> zA1fD!d{;}3T)Gv^zxrWvVUbbjH*)A#0wEZERpX)u4CksaB>%-nH5%xV8s&;a=kr@?wZTgH8b z%XfNMhW^OI^ylzM8r;8RX<#pd26+_yd^e~4mp}u`fQCFBGyf~AW7f}%=%<_4GS-1c zML%q*3hd24u{PnK@X_?y0F25%;hXs<{5b!F&!*2L)eqp4>eDCHr%$Sn&wi>;pH!bd zsXlnvkNQ16rpwzGFe*;QyHkJ%;;3^G@WA!J19t!q03TG|FJ=8A{JlCGxL3g*4t(9j z2#W<*0$&AXCkT6VFK}};;xD0)WVB8c_-fKyh`ABAoe!U?!H@MECEQR4ETk9gWyW?T zV07beC;oPI1e^l2Unu;jzF|7BR1*GHmGvTErlLY7r;6Z55Ni?pE3Y^z=}rb~EG9eb ztSRC?d2sW$fi)HaOHBsW=s=7Meic4<@PR8S{*c)(fiDffm%`5gPt?RE_)-bJl);xW z;0v zWTzPXSq<8XfJxPT0cTDbK6{v61|9+jQT)hg#e2jm2OmxyODx$v-TB^3;IZ>Lujswr zT#Pa)@bSn{I+^4DGDB0PC5Szd5U>u$c07DOUI`(&@n9<|hvW zH!{#6#ftAk+fpE=E{9)lgU^kN|10_bm^a`Lbl(R3gC#w`p>+q=nG$_+9EtS^=8lT? zR2w>vxuat4DCkGQ+)*%h6njRWjJYFY>@xb4fkP?2qj}go6VnwKvXNu$O)v7jzikfU zAUdtz)XZ9y;vqa%iZ=4%pqOJL*7USKu9*+|dMx^J+qj)*$VZt zY&<94{>?02w%(Jw>Y2S`FV>o9ie>tX>IviL(s#`$?R_DKzWw=anLp4+FJ;H*?lY>1XMQ`NEi*=Q$;futCE0e^Px5JEPa8GV7L8Bw z#^YNovALWEF`uT|5zJTLPK)bM(1?7Q zIO4q$*-oApU{v&=E^v0$0QZTx-;L-S!cR)lsP>h7o}(OIVRx-RNA7B1`r+v;F-}$F z&Lwd!z?8JH_iSM&n`_8>{DHfY3 z7(m&6ic8~}!k@M8+KWCW6J68?=vrc;k9ni@VMHMVuMY!xV!3@#{?_n5u-D0-(SGMJ zUQ8WL-yu^!SBmR3_F3}xEiB?A%gX_8|3JQbJEKmXYExz=Xlu0Yr_rHH4hEx z+P)7+mV{>v?Aax5>i~m614YAStwkmS_COPnZmWqDJE6Lg``yso2>@W13?TugTyQ;5a9}Rny zJRheIdPzA5*n1P>IUa3hau70Y)_85!dTmzsnE7oU`j|Eu?fZ;uGfHiN&Za1RBW!SEKi{k1 z?Op2z#%yn+Cg~GbX4>IxR8SkV&J=AxxBj6uEzh%P!nzi*NC#LNdW%@Z0kr-8kg(Ne zg8Z9Nd5WwjKlGllFXrP4>wH>==xXNuQtmg@_x$qL37hO=KycC!buh&d>SeGcA+h5ZlA;mmjUCEf?t`JT^uExSgBUnU%Q zh|}_&UhR-cYYopY9`X1k3mUzAk{7w{c{SUH_nfz3eKWre_g&Ej8%nDYDXl#wrSE%E zs?#KvFdx^P4dqxPyv)}M`o3d71^u1Rw`{@v5aTPu%v3B}=u9_Lr6p3UJ3to$Irr&P)v4ZyZZjvefjDkUCiW_I+d%Eac4_}pBX z*tid$uU013J|4pN`k2-XJJSdK-T=G@Uwe-RU5P_i33qA?u_kZ-z5fbf>scH026`bO zK9w}nEgQ_lk_suYXtpHw>HDwue8MB*d+IB+_by_eh;6NeJ(^AP)4Zg;VpU~(<>t!v zsv4s`dZs~Gw7sgkYAk-h-tsuC4S!00rEVf*5ez=*08=Dhd__TSKWz3U*soW#x;lC{ zu{E*kNJtM(Yfap9u%K=wY*p|sIkEm=ftC4IpV-@Man|c!FD*@5wg2xig zN6=odC-KNZt$kNN-wPD)?&?XbITFA;>rJe~yUzZ4^0(sM#3#`oy?ZV3z(ED?O6gsD zYk!n5Hrkm$-+A8wP0^P%aO~Z_wLhA9K28hh%OZGg$_KSc7fWI(WaxZ5`9wybNda%SA#6Uf&q%_%h3g)#NKD2`$0Tk z8KP%{T<7-%~@CNMp(*D3zW%~ZZan5hxE6(rce$MZh){nR}Y=IRnqTC(i z^@I}lVl5MG4pA%}x>sO#ZZ1s#lO-MqE2Qf>#qMaW`TEchc((CV_klbRxpN`p@;G7$ zEs#t2nB4h%C=t>WJJk|0svZv|njyQ?^C6=%71CEP3^}V&Csl|TxQ`#)Ezas6!?u2T zh}QK&udIhDPhzlq^P$_ADN`TRo^#oexU;_*et$nOB|#M?Dl-g-GpFA$b# zui9Jc>qJJcKOql+{3)#!?CvDRAtk%3L4uD6^kSX^lf33A$gw(ce<1O20oJ;ZJJz6y za_oPlk`m?D;F(kxg-y`zT$h;A4?e2_FaO?56!dt$p=_C$8|FN{Azb40hf88#?!kBp z19hs*Ho1J>EG8cgohSi*E8+WKLFfqigF~bv?ss&h0C@Dh6?WBzQhh@W@`8{%lk7Ir zO&#bL@d?y5wm!y;j>m+odAn?de#Y_G>j6F$-xtw7K!W0vydU&M?|2_9p3uS+zxj0j z7WF<&*@@4PO}6jkehKon!AH)spf(#mB7poz$=SFOxoiWh7rX@DOA_lv3}l3@(aKBG z{UnDHNiW~XVhvd9ECYT%t&G)uU9xng=^BpBxh*oQ2UjU$*@-+GW+2`qWBn}y8`vG7 z54m=ZI{CG%43pOg88Sn^6nRwYWHT`d@|^?Ot7Yp3AL%&i>z-W&T#^&lp>~B|xa?;_ zN0O*t!V;yzCkPzSbDi*A@(CF8Ka^+0^R~A&@Yq*k-)cGtizXQ4@%JVq)YGBKiuzQ{7V}1gc5Y7ZPG@=K9gM&OqWOu8u z%a_IlCS}uP5bsmt z7@+=m-=M{whJL0=7z6s~TtM*?(^0V&1uoG;z$=SdHMtx9=L;^z7J^J0;(D1X!S)0= zu7n?#qm5GR&VE`eDEg&p-0lYNG^`6N`mm?p7Ko{HWI5U=aV$8iEs$n&ut&sLqG`N> zzOi;(06MUSr2aL;tWxOrS{LIDVr|t4Kd4Euefz-UKHvunyp37f(Z-51I3exA6Q5l3B)%9|uTxDtA+N)B>m2X9tBO#FK&;5;~q#X=L2H(QOqK*KNI6#el2sa_rG zO+!7zlS+a^m}g3Q&A&kxFm9|<67$#LOb7OYr}fEB^2kuEdYzPB^;Z@vSU}H}n0657 zBB1lzn$Qo6$L@YhN+W+Gz4~w9!9*4-dYcWJuf3DLw;lGI0Sk@)1?=}fo(CyO?;6qL z#sSle19l&0RGd5>xi7`QoyEv~DK@IFFGlVQ^7I;u@xIuoXe%~m?J4waHrZ?4v)4SI z!?V|RM+0I{ZCc`r^{~fe!#tZE8D_I#Lv*s)LD=jlY<3gy0B}FIx3x4+V6$f-hSfzj z+P78iEV3)HWRvOHikaMIN62RTWvp7Vl}7FLuxFmlev#YT8PvA!=V%<_Ho0BrHZ(UT zWp2&dY;!8T=Qf+S;a)k2Sbe^&1|9+CGH@m;$6h}|@fh%-Ku;3R@ol#CFyCjTXSAQl zX)wPh>@1b@Z8qCX_TR2*gs*FY&F&j!v&|F5xEnFXTwCr=rLpVStIcVD1GmNS6WAvy z%+lgIS-b5P3x2Y_ye#Z!E@mQj(OwlF%YW-k0rV0KG4Xf`sJDN zLe3xZ--5>P@V>?WA9(cc;$!8!^~+ga4gk^Ww`qzT0AAO8Pt>)#4a!Tw-nY<&{u~|x zV}LF>^5dLm=24=b)0&|P`~Q58pXBKGg|#nqMbK>hN%V!h3|@|O$S;Tee?E5d-9GIu z_Wb?#?jJmUw!%&X;9G)n1aYbeFx+$vyqzzl3zCQ>Cj;c4Wnhq;IW-TqMlz!Jd%n1l za>an#u9pZKL7s=wp{t~HpoQt{;g2^QkDQRHOy4*i^Q*5w-#7z$-B)1ONV2oOhUuG; z=e2P&{0-hc+>JHID%M*(#OlIqi1N~7%4wA6U%>NzD%)`8aZdqaWyk^AgJ)le8?)L% z9SD2;nk|2(F=Wq*%eK)c%SKvBOD7Nx|?sw0~v18wt(%-pR(uue4{1m()-oEDX_AX$) z&q}e--N0X)GWaWf&&ATZ=4K_hBf*)dAc;tp59k1*EAN}HSuD3hE#0N=qr+I8;k7Pc#%9) zDzazx6=FR;p5nGfRVL5*J>=>Z7`2TB$i*!%s!uLNu5O`G6)!}dV4+cQeIaa981KV) zPiMZvu#4eOh4rf2{(G<+xrZ$&){Okz>JsruSLD#GXnh>Q^&ZPx#|Ibojw6ZnB0TFZc^@T`tOqH~>8( zjK`m`k21cOunK?X{*7=SWDnnhb@|M=WOvZ|dxM8C=wUoOcR8Kk;rIx28y8V{e}9nXEcU*EG0v?^)4?X>VMg*f3iVX zgwx%R*war0&73y(>%@2HCusinoag4(IDP=lIhf&(VjM(=&lBrE`FKQsH+cO`;pI5J zemUe6l6;dChsa=%gS;JH*Ig>=vWW)a5l$;&rNA9_hYFnJ^V0p2z)l4@&#aqC59CNZ zl*KyifW!4E7ZbU^LuZsswhDr#A;;tAU>o_aOXaAWk844lxbEs~zxj@U@6HV62$C!?08zOOL-rN?T3L zp_s-7oG%29($^!lv89GN>u0dKLU&$z%~|A2;X5yd9fV%5Qn5F)oUjqcM9$s7L{-PB zi8Y}dOcei=n8=0iZ{+g}XW(%r0I`nhi;&9#OjOkeny**HSlmZoYZdsJfNk^zU@K+V zRmHA|%l2pbfJZQ2JZv;7E;_HZK;D^)i;^Q^A9}ee5iXK}i|noYnB9)tkjsEuYWf5o zst|Z6rd^KnAO{q}L-MqEAV&K^gnKv+>XTy0PGE-vN-RkD=YWTQE&~tyfPV<{fOk>Y z$F(6~5lNH(9=ucAhjY!qJE)hqa5rK_X2htKG#!^c7(Uinyt@iK4fMtn~zV}UhmxcfR%gs_O zAxrut&oKRKCZt;>*ua~HEOnT9?-Wcnq8$m{xAAZ;Hn#nu)`>AxhT^x!j+ z^Ydqz^Ot9a((*UJXVlxeoEgUlVq1 zuItEmzX>_+mFN?(wVxyA^F`1Ko}>rmkz;E``z6$V9WcoiX#egECK)Wb{HPs?1CR6t zIUcz<2an7;K)T`Kkw)MVlD!4l)AK&n&cPytKhpMg(DfE(zjy2L2&MX9hGv>eYnoRSGaE9EDI*kh9jKPher-3mFfiVh!F$(4BQlUM) zuRyM8#F{Ez0E|%pj1dOL2-~$-m(0ZaWM*Fo7^8?V20jk~TZ{vC7zgYy&Zs_lJg~)h zV2km<7UPYI>k(H%9I3VuaV5l&s@o7(+EeUf3)nn`$C9v@N_)^eW<;^1N9V)0AohRN z7R3I@=OQ*#KrvIq{}Fpk%zqTR>(x;qo0W+72ZOMm3z&W%Vks0$B5Y9cF4oOKVEr6? z!F?4g&=I%6d8oK&yTcU6p)=_`Zo$jALGqPGHEdi2dsk}8D{E@hHjnKjef)s^F7AIR zjsw3c?D9Y7;EVU^J;xWK|2cz-I(Hbp;6Bkn-Xq`R;%%7U;O)XE^ZZ=lGwvq;XH>Qo zi8zN(gLNm30X#+A3FR|%u;t`K(Qc89^FDG7VoEdND|Qgx_@+Pp4+S2PFxDikWs6|H z{PDgo@C*4{#0xkLSpU;_c|ZO$>#I3<<1N8g_Yv4aFAnCHV_%`ZbdCr7XUP9oGynhI zlgalm7W4tXFXZu#o%#vi*U^*M8|KffKZ#r+lo9;85$Er*K6o^cEn{MzfoS#1up5l6 zcu)M{ZJ2+sBiO6wn8I(Dy_Lx&660NJM-tG7QR zbmc{A7jqlB;>8%ncrJ11`SeCS_x5-M|1QpH?*-BWyB2E-j=y~Qu*FnYFTg$<$&m0H zuWMbHt!q7pob!OZP&O^XU zgyn?(?ZbV7an$uqJt9dfp(OP&rRFM!K{MeRtVB+8g*kMslUrCECd9^X}rpYq!gmupkN56Fr1 zD^tJH##+Iv9}sgK^=mWrdCW@{xo2Y~{((_qb?J=D&a!OOcqF3z3 zex1f*!EL5KF({=QdZ};tc$e>~Q8~Q{`7Rf(gMYKGGAboaF9k2qrcwP;AaT{YE6^8W zbQ?%FfR`Kb{QjU(g*!c>jhenhiO0e>#A%Ek%@5PM#+f>UImaK*(nVXq*NejG)!&r3 zzsasmnsoAGxUUDgiaXqJH%LumFkyC`hWV=UHp93Vp(Y;E6`Z?WQ%rjjh#A0UfLA&G zWjx8jsJf^)-|tw(V%-P6?&fnXImOLYly$OG=uma*abg@Xt)3t>R ze4D^RUi~wuUz(p(m)0eRdwOaDO1S{8lM;1bcSN`k8)dKXiH<>SEljxW8rHQ_LQi0X%UUV%3MHJ6$DD1%-BxkWUt7HKYH+?_4rWe}CcWZ&>I*wdv0tbHAwT>ppxn*+0TMoObhNQP)&yzR0!l zpbh_=xG?NtT9o5+)0BPMyzha!=jM^^FVrU^e>yosa*`2dW3K4?|A2MT{y_Q&cz>5F zr4JrNF2+9O0ldQOPRPCW*O(taX6cqExQx=P7D>)(*d{usz3!=_(0$FWm4fLtJHdy( zAaWb!I>c)EcYdxquFA+GfXtCgU}A4EuGqLM63^ft8gW;o6q0KiHAnd?Vzcp(H|IMI zieX@0bGy#@Xr%~qK=)MSz42T=8GBXfmgkW-`6c-NxP~^hn6el1?+3^!DP!qX-QXS8 zPv=}sJ zV*O)dZ(W`#6$5)0Vck?h>nF^Kla{LqoNJ*qCGfw4|`Ec zd3H)a(W!?s^#76kor65%x};=L{*lviX~?KfVJ~Y7>6Bz_?>Zgz)(G0nCynl|(~Vu> zNk(gU3gtxME<1eIBWJQ}im`S22^0quIi=>?#;)nbC^yd7ioe$I>A05-``Ao#3S3n$ zv{a|iRB=y+>J*tuZ}Dm8>ILhVK4lg5M7KzEE{*QACmxdQ9Q%3}JNH1KCeCgF8y=V>A0fa@MUu)Kc1~=9ZLI+sy zzy)U$El$(G3tYaKD2{J z0d%>*RoXkA3bl9sIMlxVSE2UqKZel9JiTS$g;-&OO!?>3-{`tzo-Jew{J?dIK8bJi zNqpPE`8GP8)|o=4Ufo)+ZjD#BI;SqMysiPyM{*JC%W^V*@sVTA>{%1FMSzzqy zDll4~0CvWleUbD2J;D{el;@z8U`~fmGdl6N9e>^7)A0KcrXGCnBs`yu=d;y*N_55j=s{x~O!J zf7APZiuiQvh@a^5Owe^E#(gH}$NycEK<}A&J{M!8JJo>$8Wp=Lj&+;_T+m176@dxj zBkqre??o)4kIu*X_ow9f9C23My4d$UIFs%92zP^=TH^bQ4diQle}R7anPlNJ&UMf> z`0y^)iV}3@IOz5stc#%A{I@y|@F{rqnDN1+kj8DgXZo1v>t-(dkHbE z10KJ?!)oxb20Y~F`EfRRHsAl`=j+fOKRf2PYm9LRj!|(v;%aoR=X;eNX8A#{_WF;= z$BFOOS@=GWf9Dv{{XEHEjvQYJ%;c4EpU9p)1Uq{bI%n7kJHPl|QqpH2~ zsVdS*PM3H;tG#+hCGVf&8i)(zjBlQ3!<~UPe%fBMqq4pBsY>Ycs2C0NX!x1MJWQ0G zD-GNp;Qoe_+qXV;c6&$1+3lUm+3nkvvlBQQhkF;oiGVuJPQ5%){9X&U3%BdZC6noV z;-=mF`$?E*lf?hlgF5a8YwuPn+IMwS;7*7tI=e{Y^v=+{jyoEv>{RKrIR2BfWU$B>QzoE8AVS5%0D6ntrc}T;^ARS2eFr|1>?go1YPP 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 X!-oLJ