Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/render')
-rw-r--r--source/blender/render/Makefile37
-rw-r--r--source/blender/render/extern/include/render.h290
-rw-r--r--source/blender/render/extern/include/render_types.h256
-rw-r--r--source/blender/render/intern/Makefile37
-rw-r--r--source/blender/render/intern/include/RE_DummyShadowBuffer.h70
-rw-r--r--source/blender/render/intern/include/RE_ShadowBuffer.h61
-rw-r--r--source/blender/render/intern/include/RE_basicShadowBuffer.h94
-rw-r--r--source/blender/render/intern/include/RE_callbacks.h84
-rw-r--r--source/blender/render/intern/include/edgeRender.h63
-rw-r--r--source/blender/render/intern/include/envmap.h49
-rw-r--r--source/blender/render/intern/include/errorHandler.h69
-rw-r--r--source/blender/render/intern/include/gammaCorrectionTables.h79
-rw-r--r--source/blender/render/intern/include/initrender.h59
-rw-r--r--source/blender/render/intern/include/jitter.h50
-rw-r--r--source/blender/render/intern/include/old_zbuffer_types.h58
-rw-r--r--source/blender/render/intern/include/outerRenderLoop.h43
-rw-r--r--source/blender/render/intern/include/pixelblending.h209
-rw-r--r--source/blender/render/intern/include/pixelblending_types.h61
-rw-r--r--source/blender/render/intern/include/pixelshading.h122
-rw-r--r--source/blender/render/intern/include/renderHelp.h63
-rw-r--r--source/blender/render/intern/include/renderPreAndPost.h43
-rw-r--r--source/blender/render/intern/include/render_intern.h60
-rw-r--r--source/blender/render/intern/include/rendercore.h117
-rw-r--r--source/blender/render/intern/include/rendercore_int.h55
-rw-r--r--source/blender/render/intern/include/shadbuf.h75
-rw-r--r--source/blender/render/intern/include/shadowBuffer.h79
-rw-r--r--source/blender/render/intern/include/texture.h86
-rw-r--r--source/blender/render/intern/include/vanillaRenderPipe.h49
-rw-r--r--source/blender/render/intern/include/vanillaRenderPipe_int.h191
-rw-r--r--source/blender/render/intern/include/vanillaRenderPipe_types.h90
-rw-r--r--source/blender/render/intern/include/zbuf.h180
-rw-r--r--source/blender/render/intern/include/zbuf_int.h203
-rw-r--r--source/blender/render/intern/include/zbuf_types.h78
-rw-r--r--source/blender/render/intern/include/zbufferdatastruct.h99
-rw-r--r--source/blender/render/intern/include/zbufferdatastruct_types.h77
-rw-r--r--source/blender/render/intern/source/Makefile60
-rw-r--r--source/blender/render/intern/source/RE_DummyShadowBuffer.cpp66
-rw-r--r--source/blender/render/intern/source/RE_basicShadowBuffer.cpp734
-rw-r--r--source/blender/render/intern/source/RE_callbacks.c159
-rw-r--r--source/blender/render/intern/source/edgeRender.c952
-rw-r--r--source/blender/render/intern/source/envmap.c689
-rw-r--r--source/blender/render/intern/source/errorHandler.c99
-rw-r--r--source/blender/render/intern/source/gammaCorrectionTables.c168
-rw-r--r--source/blender/render/intern/source/initrender.c1329
-rw-r--r--source/blender/render/intern/source/jitter.c192
-rw-r--r--source/blender/render/intern/source/outerRenderLoop.c515
-rw-r--r--source/blender/render/intern/source/pixelblending.c919
-rw-r--r--source/blender/render/intern/source/pixelshading.c1917
-rw-r--r--source/blender/render/intern/source/renderHelp.c294
-rw-r--r--source/blender/render/intern/source/renderPreAndPost.c94
-rw-r--r--source/blender/render/intern/source/rendercore.c2902
-rw-r--r--source/blender/render/intern/source/renderdatabase.c248
-rw-r--r--source/blender/render/intern/source/shadbuf.c771
-rw-r--r--source/blender/render/intern/source/shadowBuffer.cpp100
-rw-r--r--source/blender/render/intern/source/vanillaRenderPipe.c1654
-rw-r--r--source/blender/render/intern/source/zbuf.c2329
-rw-r--r--source/blender/render/intern/source/zbufferdatastruct.c342
57 files changed, 19869 insertions, 0 deletions
diff --git a/source/blender/render/Makefile b/source/blender/render/Makefile
new file mode 100644
index 00000000000..5d8fbdd743f
--- /dev/null
+++ b/source/blender/render/Makefile
@@ -0,0 +1,37 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL/BL DUAL LICENSE BLOCK *****
+#
+# Bounces make to subdirectories.
+
+SOURCEDIR = source/blender/render
+DIRS = intern
+
+include nan_subdirs.mk
diff --git a/source/blender/render/extern/include/render.h b/source/blender/render/extern/include/render.h
new file mode 100644
index 00000000000..0ac9d7e61c8
--- /dev/null
+++ b/source/blender/render/extern/include/render.h
@@ -0,0 +1,290 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Interface to transform the Blender scene into renderable data.
+ */
+
+#ifndef RENDER_H
+#define RENDER_H "$Id$"
+
+/* ------------------------------------------------------------------------- */
+/* This little preamble might be moved to a separate include. It contains */
+/* some defines that should become functions, and some platform dependency */
+/* fixes. I think it is risky to always include it... */
+/* ------------------------------------------------------------------------- */
+
+/* fix for OSA and defmaterial extern */
+#include "BKE_osa_types.h"
+#include "DNA_material_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* For #undefs of stupid windows defines */
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+/* ------------------------------------------------------------------------- */
+/* Types */
+/* Both external and internal types can be placed here. Make sure there are */
+/* no dirty extras in the type files so they can be included without */
+/* problems. If possible, make a note why the include is needed. */
+/* ------------------------------------------------------------------------- */
+
+#include "render_types.h"
+
+/* ------------------------------------------------------------------------- */
+/* Global variables */
+/* These variable are global to the render module, and also externally */
+/* visible. The file where they are defined must be added. */
+/* ------------------------------------------------------------------------- */
+
+extern RE_Render R; /* rendercore.c */
+extern Osa O; /* rendercore.c */
+extern Material defmaterial; /* initrender.c */
+extern unsigned short *igamtab1; /* initrender.c */
+extern unsigned short *gamtab; /* initrender.c */
+
+struct View3D;
+
+/* ------------------------------------------------------------------------- */
+/* Function definitions */
+/* */
+/* All functions that need to be externally visible must be declared here. */
+/* Currently, this interface contains 29 functions and 11 callbacks. */
+/* ------------------------------------------------------------------------- */
+
+
+/* ------------------------------------------------------------------------- */
+/* Needed for the outside world referring to shadowbuffers */
+/* ------------------------------------------------------------------------- */
+
+#ifndef RE_SHADOWBUFFERHANDLE
+#define RE_SHADOWBUFFERHANDLE
+#define RE_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
+ RE_DECLARE_HANDLE(RE_ShadowBufferHandle);
+#endif
+
+ /**
+ * Create a new, empty shadow buffer with certain settings.
+ *
+ * @param mode 0 is a dummy buffer, 1 is the old buffer for
+ * c-based shadowing, 2 is the old buffer with c++ refit , 2 is a
+ * deep buffer
+ */
+ extern RE_ShadowBufferHandle RE_createShadowBuffer(struct LampRen *lar,
+ float mat[][4],
+ int mode);
+
+ /**
+ * Delete a shadow buffer.
+ * @param shb handle to the buffer to be released
+ */
+ extern void RE_deleteShadowBuffer(RE_ShadowBufferHandle shb);
+
+
+
+/* ------------------------------------------------------------------------- */
+/* initrender (14) */
+/* ------------------------------------------------------------------------- */
+
+struct View3D;
+
+/**
+ * Guarded call to frame renderer? Tests several limits and boundary
+ * conditions.
+ *
+ * @param ogl_render_area The View3D area to use for OpenGL rendering
+ * (can be NULL unless render R_OGL flag is set)
+ */
+void RE_initrender(struct View3D *ogl_render_view3d);
+
+/**
+ *
+ */
+void RE_setwindowclip(int mode, int jmode);
+
+/*
+ * @param ogl_render_area The View3D area to use for OpenGL rendering
+ * (can be NULL unless render R_OGL flag is set)
+ */
+void RE_animrender(struct View3D *ogl_render_view3d);
+void RE_free_render_data(void);
+void RE_free_filt_mask(void);
+void RE_holoview(void);
+void RE_init_filt_mask(void);
+void RE_init_render_data(void);
+void RE_jitterate1(float *jit1, float *jit2, int num, float rad1);
+void RE_jitterate2(float *jit1, float *jit2, int num, float rad2);
+void RE_make_existing_file(char *name);
+
+/* ------------------------------------------------------------------------- */
+/* zbuf (2) */
+/* ------------------------------------------------------------------------- */
+
+/**
+ * Converts a world coordinate into a homogenous coordinate in view
+ * coordinates. (WCS -> HCS)
+ * Also called in: shadbuf.c render.c radfactors.c
+ * initrender.c envmap.c editmesh.c
+ * @param v1 [3 floats] the world coordinate
+ * @param adr [4 floats] the homogenous view coordinate
+ */
+void RE_projectverto(float *v1,float *adr);
+
+/**
+ * Something about doing radiosity z buffering?
+ * (called in radfactors.c), hope the RadView is defined already...
+ * Also called in: radfactors.c
+ * Note: Uses globals.
+ * @param radview radiosity view definition
+ */
+ struct RadView;
+ struct RNode;
+void RE_zbufferall_radio(struct RadView *vw, struct RNode **rg_elem, int rg_totelem);
+
+
+/* ------------------------------------------------------------------------- */
+/* envmap (5) */
+/* ------------------------------------------------------------------------- */
+ struct EnvMap;
+ struct Tex;
+void RE_free_envmapdata(struct EnvMap *env);
+void RE_free_envmap(struct EnvMap *env);
+struct EnvMap *RE_add_envmap(void);
+/* these two maybe not external? yes, they are, for texture.c */
+struct EnvMap *RE_copy_envmap(struct EnvMap *env);
+/* (used in texture.c) */
+int RE_envmaptex(struct Tex *tex, float *texvec, float *dxt, float *dyt);
+
+ /* --------------------------------------------------------------------- */
+ /* rendercore (2) */
+ /* --------------------------------------------------------------------- */
+ float RE_Spec(float inp, int hard);
+
+ /* maybe not external */
+ void RE_calc_R_ref(void);
+
+ /* --------------------------------------------------------------------- */
+ /* renderdatabase (3) */
+ /* --------------------------------------------------------------------- */
+ struct VlakRen *RE_findOrAddVlak(int nr);
+ struct VertRen *RE_findOrAddVert(int nr);
+ struct HaloRen *RE_findOrAddHalo(int nr);
+ HaloRen *RE_inithalo(Material *ma,
+ float *vec,
+ float *vec1,
+ float *orco,
+ float hasize,
+ float vectsize);
+
+
+ /**
+ * callbacks (11):
+ *
+ * If the callbacks aren't set, rendering will still proceed as
+ * desired, but the concerning functionality will not be enabled.
+ *
+ * There need to be better uncoupling between the renderer and
+ * these functions still!
+ * */
+
+ void RE_set_test_break_callback(int (*f)(void));
+
+ void RE_set_timecursor_callback(void (*f)(int));
+
+ void RE_set_renderdisplay_callback(void (*f)(int, int, int, int, unsigned int *));
+ void RE_set_initrenderdisplay_callback(void (*f)(void));
+ void RE_set_clearrenderdisplay_callback(void (*f)(short));
+
+ void RE_set_printrenderinfo_callback(void (*f)(double,int));
+
+ void RE_set_getrenderdata_callback(void (*f)(void));
+ void RE_set_freerenderdata_callback(void (*f)(void));
+
+
+ /*from renderhelp, should disappear!!! */
+ /** Recalculate all normals on renderdata. */
+ void set_normalflags(void);
+ /**
+ * On loan from zbuf.h:
+ * Tests whether the first three coordinates should be clipped
+ * wrt. the fourth component. Bits 1 and 2 test on x, 3 and 4 test on
+ * y, 5 and 6 test on z:
+ * xyz > test => set first bit (01),
+ * xyz < -test => set second bit (10),
+ * xyz == test => reset both bits (00).
+ * Note: functionality is duplicated from an internal function
+ * Also called in: initrender.c, radfactors.c
+ * @param v [4 floats] a coordinate
+ * @return a vector of bitfields
+ */
+ int RE_testclip(float *v);
+
+ /* patch for the external if, to support the split for the ui */
+ void RE_addalphaAddfac(char *doel, char *bron, char addfac);
+ void RE_sky(char *col);
+ void RE_renderflare(struct HaloRen *har);
+ /**
+ * Shade the pixel at xn, yn for halo har, and write the result to col.
+ * Also called in: previewrender.c
+ * @param har The halo to be rendered on this location
+ * @param col [unsigned int 3] The destination colour vector
+ * @param zz Some kind of distance
+ * @param dist Square of the distance of this coordinate to the halo's center
+ * @param x [f] Pixel x relative to center
+ * @param y [f] Pixel y relative to center
+ * @param flarec Flare counter? Always har->flarec...
+ */
+ void RE_shadehalo(struct HaloRen *har,
+ char *col,
+ unsigned int zz,
+ float dist,
+ float x,
+ float y,
+ short flarec);
+
+/***/
+
+/* haloren->type: flags */
+
+#define HA_ONLYSKY 1
+#define HA_VECT 2
+#define HA_XALPHA 4
+#define HA_FLARECIRC 8
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RENDER_H */
diff --git a/source/blender/render/extern/include/render_types.h b/source/blender/render/extern/include/render_types.h
new file mode 100644
index 00000000000..6ed2eafba21
--- /dev/null
+++ b/source/blender/render/extern/include/render_types.h
@@ -0,0 +1,256 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef RENDER_TYPES_H
+#define RENDER_TYPES_H "$Id$"
+
+#include "DNA_scene_types.h"
+#include "DNA_world_types.h"
+/* ------------------------------------------------------------------------- */
+
+/* Definitely weird: this equals 1<<21... so wtf?*/
+#define MAXVERT (2<<20)
+#define MAXVLAK (2<<20)
+
+
+/* This is needed to not let VC choke on near and far... old
+ * proprietary MS extensions... */
+#ifdef WIN32
+#undef near
+#undef far
+#define near clipsta
+#define far clipend
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+typedef struct RE_Render
+{
+ float co[3];
+ float lo[3], gl[3], uv[3], ref[3], orn[3], winco[3], sticky[3], vcol[3];
+ float itot, i, ic, rgb, norm;
+ float vn[3], view[3], *vno, refcol[4];
+
+ float grvec[3], inprz, inprh;
+ float imat[3][3];
+
+ float viewmat[4][4], viewinv[4][4];
+ float persmat[4][4], persinv[4][4];
+ float winmat[4][4];
+
+ short flag, osatex, osa, rt;
+ /**
+ * Screen sizes and positions, in pixels
+ */
+ short xstart, xend, ystart, yend, afmx, afmy;
+ short rectx; /* Picture width - 1, normally xend - xstart. */
+ short recty; /* picture height - 1, normally yend - ystart. */
+
+ /**
+ * Distances and sizes in world coordinates nearvar, farvar were
+ * near and far, but VC in cpp mode chokes on it :( */
+ float near; /* near clip distance */
+ float far; /* far clip distance */
+ float ycor, zcor, pixsize, viewfac;
+
+
+ /* These three need to be 'handlerized'. Not an easy task... */
+/* RE_RenderDataHandle r; */
+ RenderData r;
+ World wrld;
+ ListBase parts;
+
+ int totvlak, totvert, tothalo, totlamp;
+
+ /* internal: these two are a sort of cache for the render pipe */
+ struct VlakRen *vlr;
+ int vlaknr;
+
+ /* external */
+ struct Material *mat, *matren;
+ /* internal, fortunately */
+ struct LampRen **la;
+ struct VlakRen **blovl;
+ struct VertRen **blove;
+ struct HaloRen **bloha;
+
+ unsigned int *rectaccu;
+ unsigned int *rectz; /* z buffer: distance buffer */
+ unsigned int *rectf1, *rectf2;
+ unsigned int *rectot; /* z buffer: face index buffer, recycled as colour buffer! */
+ unsigned int *rectspare; /* */
+ /* for 8 byte systems! */
+ long *rectdaps;
+
+ short win, winpos, winx, winy, winxof, winyof;
+ short winpop, displaymode, sparex, sparey;
+
+ /* Not sure what these do... But they're pointers, so good for handlerization */
+ struct Image *backbuf, *frontbuf;
+ /* backbuf is an image that drawn as background */
+
+} RE_Render;
+
+/* ------------------------------------------------------------------------- */
+
+/**
+ * Part as in part-rendering. An image rendered in parts is rendered
+ * to a list of parts, with x,y size, and a pointer to the render
+ * output stored per part. Internal!
+ */
+typedef struct Part
+{
+ struct Part *next, *prev;
+ unsigned int *rect;
+ short x, y;
+} Part;
+
+typedef struct ShadBuf {
+ short samp, shadhalostep;
+ float persmat[4][4];
+ float viewmat[4][4];
+ float winmat[4][4];
+ float *jit;
+ float d,far,pixsize,soft;
+ int co[3];
+ int size,bias;
+ unsigned long *zbuf;
+ char *cbuf;
+} ShadBuf;
+
+/* ------------------------------------------------------------------------- */
+
+typedef struct VertRen
+{
+ float co[3];
+ float n[3];
+ float ho[4];
+ float *orco;
+ float *sticky;
+ void *svert; /* smooth vert, only used during initrender */
+ short clip, texofs; /* texofs= flag */
+} VertRen;
+
+/* ------------------------------------------------------------------------- */
+
+struct halosort {
+ struct HaloRen *har;
+ unsigned int z;
+};
+
+/* ------------------------------------------------------------------------- */
+struct Material;
+struct MFace;
+struct TFace;
+
+typedef struct VlakRen
+{
+ struct VertRen *v1, *v2, *v3, *v4;
+ float n[3], len;
+ struct Material *mat;
+ struct MFace *mface;
+ struct TFace *tface;
+ unsigned int *vcol;
+ char snproj, puno;
+ char flag, ec;
+ unsigned int lay;
+} VlakRen;
+
+
+typedef struct HaloRen
+{
+ float alfa, xs, ys, rad, radsq, sin, cos, co[3], no[3];
+ unsigned int zs, zd;
+ unsigned int zBufDist;/* depth in the z-buffer coordinate system */
+ short miny, maxy;
+ short hard, b, g, r;
+ char starpoints, add, type, tex;
+ char linec, ringc, seed;
+ short flarec; /* used to be a char. why ?*/
+ float hasize;
+ int pixels;
+ unsigned int lay;
+ struct Material *mat;
+} HaloRen;
+
+struct LampRen;
+struct MTex;
+
+/**
+ * For each lamp in a scene, a LampRen is created. It determines the
+ * properties of a lightsource.
+ */
+typedef struct LampRen
+{
+ float xs, ys, dist;
+ float co[3];
+ short type, mode;
+ float r, g, b;
+ float energy, haint;
+ int lay;
+ float spotsi,spotbl;
+ float vec[3];
+ float xsp, ysp, distkw, inpr;
+ float halokw, halo;
+ float ld1,ld2;
+
+ /* copied from Lamp, to decouple more rendering stuff */
+ /** Size of the shadowbuffer */
+ short bufsize;
+ /** Number of samples for the shadows */
+ short samp;
+ /** Softness factor for shadow */
+ float soft;
+ /** shadow plus halo: detail level */
+ short shadhalostep;
+ /** Near clip of the lamp */
+ float clipsta;
+ /** Far clip of the lamp */
+ float clipend;
+ /** A small depth offset to prevent self-shadowing. */
+ float bias;
+
+ /** If the lamp casts shadows, one of these is filled. For the old
+ * renderer, shb is used, for the new pipeline the shadowBufOb,
+ * which should be a shadowbuffer handle. */
+ struct ShadBuf *shb;
+ void* shadowBufOb;
+
+ float imat[3][3];
+ float spottexfac;
+ float sh_invcampos[3], sh_zfac; /* sh_= spothalo */
+
+ struct LampRen *org;
+ struct MTex *mtex[8];
+} LampRen;
+
+#endif /* RENDER_TYPES_H */
diff --git a/source/blender/render/intern/Makefile b/source/blender/render/intern/Makefile
new file mode 100644
index 00000000000..ee9969a76c8
--- /dev/null
+++ b/source/blender/render/intern/Makefile
@@ -0,0 +1,37 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL/BL DUAL LICENSE BLOCK *****
+#
+# Bounces make to subdirectories.
+
+SOURCEDIR = source/blender/render/intern
+DIRS = source
+
+include nan_subdirs.mk
diff --git a/source/blender/render/intern/include/RE_DummyShadowBuffer.h b/source/blender/render/intern/include/RE_DummyShadowBuffer.h
new file mode 100644
index 00000000000..d5308277f6c
--- /dev/null
+++ b/source/blender/render/intern/include/RE_DummyShadowBuffer.h
@@ -0,0 +1,70 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef RE_DUMMYSHADOWBUFFER_H
+#define RE_DUMMYSHADOWBUFFER_H
+
+#include "RE_ShadowBuffer.h"
+
+struct LampRen;
+
+class RE_DummyShadowBuffer : public RE_ShadowBuffer {
+
+ public:
+ /**
+ * Make an empty shadow buffer
+ */
+ RE_DummyShadowBuffer(void);
+
+ /**
+ * Delete and clear this buffer
+ */
+ virtual ~RE_DummyShadowBuffer(void);
+
+ /**
+ * Place this scene in the buffer
+ */
+ virtual void importScene(struct LampRen* lar);
+
+ /**
+ * Always return a fixed shadow factor.
+ * @param inp ignored
+ * @param shb ignored
+ * @param shadowResult a vector of 3 floats with rgb shadow values
+ */
+ virtual void readShadowValue(struct ShadBuf *shb,
+ float inp,
+ float* shadowResult);
+
+};
+
+#endif /* RE_SHADOWBUFFER_H */
diff --git a/source/blender/render/intern/include/RE_ShadowBuffer.h b/source/blender/render/intern/include/RE_ShadowBuffer.h
new file mode 100644
index 00000000000..3b015597bb9
--- /dev/null
+++ b/source/blender/render/intern/include/RE_ShadowBuffer.h
@@ -0,0 +1,61 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef RE_SHADOWBUFFER_H
+#define RE_SHADOWBUFFER_H
+
+#include <iostream.h>
+
+struct ShadBuf;
+struct LampRen;
+
+class RE_ShadowBuffer {
+
+ public:
+
+ virtual ~RE_ShadowBuffer(void){};
+ /**
+ * Place this scene in the buffer
+ */
+ virtual void importScene(struct LampRen* lar) = 0;
+
+ /**
+ * Test the shadow factor at a location in the buffer
+ * @param shadowResult a vector of 3 floats with rgb shadow values
+ */
+ virtual void readShadowValue(struct ShadBuf *shb,
+ float inp,
+ float* shadowResult) = 0;
+
+};
+
+#endif /* RE_SHADOWBUFFER_H */
diff --git a/source/blender/render/intern/include/RE_basicShadowBuffer.h b/source/blender/render/intern/include/RE_basicShadowBuffer.h
new file mode 100644
index 00000000000..8d5e9237205
--- /dev/null
+++ b/source/blender/render/intern/include/RE_basicShadowBuffer.h
@@ -0,0 +1,94 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef RE_BASICSHADOWBUFFER_H
+#define RE_BASICSHADOWBUFFER_H
+
+#include "RE_ShadowBuffer.h"
+
+struct LampRen;
+struct Lamp;
+
+class RE_BasicShadowBuffer : public RE_ShadowBuffer {
+
+ private:
+
+ void lrectreadRectz(int x1, int y1, int x2, int y2, char *r1);
+ int sizeoflampbuf(struct ShadBuf *shb);
+ int firstreadshadbuf(struct ShadBuf *shb, int xs, int ys, int nr);
+ float readshadowbuf(struct ShadBuf *shb, int xs, int ys, int zs);
+ float readshadowbuf_halo(struct ShadBuf *shb, int xs, int ys, int zs);
+ float *give_jitter_tab(int samp);
+
+ int bias;
+
+ public:
+ /**
+ * Make a shadow buffer from these settings
+ */
+ RE_BasicShadowBuffer(struct LampRen *lar, float mat[][4]);
+
+ /**
+ * Delete and clear this buffer
+ */
+ virtual ~RE_BasicShadowBuffer(void);
+
+ /**
+ * Calculates shadowbuffers for a vector of shadow-giving lamps
+ * @param lar The vector of lamps
+ */
+ void importScene(LampRen *lar);
+
+ /**
+ * Determines the shadow factor for a face and lamp. There is some
+ * communication with global variables here.
+ * @param shadres The RGB shadow factors: 1.0 for no shadow, 0.0 for complete
+ * shadow. There must be a float[3] to write the result to.
+ * @param shb The shadowbuffer to find the shadow factor in.
+ * @param inp The inproduct between viewvector and ?
+ *
+ */
+ virtual void readShadowValue(struct ShadBuf *shb,
+ float inp,
+ float* shadowResult);
+
+ /**
+ * Determines the shadow factor for lamp <lar>, between <p1>
+ * and <p2>. (Which CS?)
+ */
+ float shadow_halo(LampRen *lar, float *p1, float *p2);
+
+};
+
+#endif /* RE_BASICSHADOWBUFFER_H */
+
+
diff --git a/source/blender/render/intern/include/RE_callbacks.h b/source/blender/render/intern/include/RE_callbacks.h
new file mode 100644
index 00000000000..30734728b4b
--- /dev/null
+++ b/source/blender/render/intern/include/RE_callbacks.h
@@ -0,0 +1,84 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Callbacks to make the renderer interact with calling modules.
+ */
+
+#ifndef RE_CALLBACKS_H
+#define RE_CALLBACKS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ /**
+ * Test whether operation should be prematurely terminated.
+ *
+ * @returns 0 to continue, any other value to break.
+ */
+ int RE_local_test_break(void);
+
+ /**
+ * Set a red square with the argument as text as cursor.
+ */
+ void RE_local_timecursor(int i);
+
+ /**
+ * Render these lines from the renderbuffer on screen (needs better spec)
+ */
+ void RE_local_render_display(int i, int j, int k, int l, unsigned int *m);
+
+ /**
+ * Initialise a render display (needs better spec)
+ */
+ void RE_local_init_render_display(void);
+
+ /**
+ * Clear/close a render display (needs better spec)
+ */
+ void RE_local_clear_render_display(short);
+
+ /**
+ * Print render statistics.
+ */
+ void RE_local_printrenderinfo(double time, int i);
+
+ /** Get the data for the scene to render. */
+ void RE_local_get_renderdata(void);
+
+ /** Release the data for the scene that was rendered. */
+ void RE_local_free_renderdata(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/render/intern/include/edgeRender.h b/source/blender/render/intern/include/edgeRender.h
new file mode 100644
index 00000000000..d6e2fcb989e
--- /dev/null
+++ b/source/blender/render/intern/include/edgeRender.h
@@ -0,0 +1,63 @@
+/*
+ * edgeRender.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef EDGERENDER_H
+#define EDGERENDER_H
+/* ------------------------------------------------------------------------- */
+
+/**
+ * Add edges to <targetbuf>, which is of size <iw> by <ih>. Use <osanr>
+ * samples, and intensity <i>. <compat> indicates an extra shift in the
+ * image, for backwards compatibility with the old renderpipe. <mode>
+ * indicates which edges should be considered. The edges will be shaded
+ * to <rgb>
+ */
+void
+addEdges(
+ char * targetbuf,
+ int iw,
+ int ih,
+ int osanr,
+ short int i,
+ short int i_red,
+ int compat,
+ int mode,
+ float r,
+ float g,
+ float b
+ );
+
+/* ------------------------------------------------------------------------- */
+
+#endif /* EDGERENDER_H */
diff --git a/source/blender/render/intern/include/envmap.h b/source/blender/render/intern/include/envmap.h
new file mode 100644
index 00000000000..62640454151
--- /dev/null
+++ b/source/blender/render/intern/include/envmap.h
@@ -0,0 +1,49 @@
+/*
+ * envmap_ext.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef ENVMAP_EXT_H
+#define ENVMAP_EXT_H
+
+/* no types!!! */
+/* #include "envmap_types.h" */
+
+/**
+ * Make environment maps for all objects in the scene that have an
+ * environment map as texture.
+ * (initrender.c)
+ */
+void make_envmaps(void);
+
+#endif /* ENVMAP_EXT_H */
+
diff --git a/source/blender/render/intern/include/errorHandler.h b/source/blender/render/intern/include/errorHandler.h
new file mode 100644
index 00000000000..190cd0c9a35
--- /dev/null
+++ b/source/blender/render/intern/include/errorHandler.h
@@ -0,0 +1,69 @@
+/*
+ * errorHandler.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef ERRORHANDLER_H
+#define ERRORHANDLER_H
+
+/* ------------------------------------------------------------------------- */
+/* error codes */
+enum RE_RENDER_ERROR {
+ RE_NO_ERROR,
+ RE_DEPTH_MISMATCH, /* 1. conflict resolution detects a bad z value */
+ RE_BAD_FACE_TYPE, /* 2. a face type switch fails */
+ RE_BAD_FACE_INDEX, /* 3. tried to do an operation with a bad index */
+ RE_BAD_DATA_POINTER,
+ RE_TRACE_COUNTER,
+ RE_TOO_MANY_FACES, /* 6. overflow on z-buffer depth */
+ RE_EDGERENDER_WRITE_OUTSIDE_BUFFER, /* 7. write value outside buffer */
+ RE_CANNOT_ALLOCATE_MEMORY, /* 8. no memory for malloc */
+ RE_WRITE_OUTSIDE_COLOUR_BUFFER, /* 9. write outside colour target buffer */
+ RE_MAX_ERROR
+};
+
+/**
+ * Reset all counters for the error trace
+ */
+void RE_errortrace_reset(void);
+
+/**
+ * Signals an error to screen. Counts repetitive errors
+ */
+void RE_error(int errType, char* fname);
+
+/**
+ * Signals an error, and prints an integer argument
+ */
+void RE_error_int(int errType, char* fname, int valye);
+
+#endif /* ERRORHANDLER_H */
diff --git a/source/blender/render/intern/include/gammaCorrectionTables.h b/source/blender/render/intern/include/gammaCorrectionTables.h
new file mode 100644
index 00000000000..14c2d2d4a68
--- /dev/null
+++ b/source/blender/render/intern/include/gammaCorrectionTables.h
@@ -0,0 +1,79 @@
+/*
+ * gammacorrectiontables.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef GAMMACORRECTIONTABLES_H
+#define GAMMACORRECTIONTABLES_H
+
+
+
+/* Default gamma. For most CRTs, gamma ranges from 2.2 to 2.5 (Foley), so */
+/* 2.35 seems appropriate enough. Experience teaches a different number */
+/* though. Old blender: 2.0. It might be nice to make this a slider */
+#define RE_DEFAULT_GAMMA 2.0
+/* This 400 is sort of based on the number of intensity levels needed for */
+/* the typical dynamic range of a medium, in this case CRTs. (Foley) */
+/* (Actually, it says the number should be between 400 and 535.) */
+#define RE_GAMMA_TABLE_SIZE 400
+
+/**
+ * Initialise the gamma lookup tables
+ */
+void makeGammaTables(float gamma);
+
+/**
+ * Returns true if the table is initialised, false otherwise
+ */
+int gammaTableIsInitialised(void);
+
+/**
+ * Apply gamma correction on col
+ */
+float gammaCorrect(float col);
+
+/**
+ * Apply inverse gamma correction on col
+ */
+float invGammaCorrect(float col);
+
+/**
+ * Tell whether or not to do gamma.
+ */
+int doGamma(void);
+
+/**
+ * Set/unset performing gamma corrections.
+ */
+void setDoGamma(int);
+
+#endif
diff --git a/source/blender/render/intern/include/initrender.h b/source/blender/render/intern/include/initrender.h
new file mode 100644
index 00000000000..06c5f032c7d
--- /dev/null
+++ b/source/blender/render/intern/include/initrender.h
@@ -0,0 +1,59 @@
+/*
+ * initrender_ext.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef INITRENDER_EXT_H
+#define INITRENDER_EXT_H
+
+/* type includes */
+
+#include "DNA_effect_types.h" /* for PartEff type */
+#include "render_types.h"
+
+/* Functions */
+
+void init_def_material(void);
+void init_render_jit(int nr);
+float calc_weight(float *weight, int i, int j);
+void defaultlamp(void);
+void schrijfplaatje(char *name);
+void initparts(void);
+short setpart(short nr); /* return 0 als geen goede part */
+void addparttorect(short nr, Part *part);
+void add_to_blurbuf(int blur);
+void oldRenderLoop(void); /* Calls the old renderer. Contains the PART and FIELD loops. */
+void render(void); /* Switch between the old and the unified renderer. */
+/* void write_screendump(char *name); not here !*/
+
+#endif /* INITRENDER_EXT_H */
+
diff --git a/source/blender/render/intern/include/jitter.h b/source/blender/render/intern/include/jitter.h
new file mode 100644
index 00000000000..eff8c7bf805
--- /dev/null
+++ b/source/blender/render/intern/include/jitter.h
@@ -0,0 +1,50 @@
+/*
+ * jitter.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef JITTER_H
+#define JITTER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern float jit[64][2];
+
+void initjit(float *jit, int num);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/render/intern/include/old_zbuffer_types.h b/source/blender/render/intern/include/old_zbuffer_types.h
new file mode 100644
index 00000000000..7eb3159f438
--- /dev/null
+++ b/source/blender/render/intern/include/old_zbuffer_types.h
@@ -0,0 +1,58 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Datatypes for old zbuffering algorithms.
+ */
+
+#ifndef OLD_ZBUFFER_TYPES_H
+#define OLD_ZBUFFER_TYPES_H "$Id$"
+
+/* ------------------------------------------------------------------------- */
+
+typedef struct PixStr
+{
+ struct PixStr *next;
+ int vlak0, vlak;
+ unsigned int z;
+ unsigned int mask;
+ short aantal, ronde;
+} PixStr;
+
+/* ------------------------------------------------------------------------- */
+
+typedef struct PixStrMain
+{
+ struct PixStr *ps;
+ struct PixStrMain *next;
+} PixStrMain;
+
+/* ------------------------------------------------------------------------- */
+
+#endif
diff --git a/source/blender/render/intern/include/outerRenderLoop.h b/source/blender/render/intern/include/outerRenderLoop.h
new file mode 100644
index 00000000000..965516c9525
--- /dev/null
+++ b/source/blender/render/intern/include/outerRenderLoop.h
@@ -0,0 +1,43 @@
+/*
+ * outerRenderLoop.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef OUTERRENDERLOOP_H
+#define OUTERRENDERLOOP_H
+
+/**
+ * Outer loop for rendering a single picture.
+ */
+void unifiedRenderingLoop(void);
+
+#endif
diff --git a/source/blender/render/intern/include/pixelblending.h b/source/blender/render/intern/include/pixelblending.h
new file mode 100644
index 00000000000..39c439505e0
--- /dev/null
+++ b/source/blender/render/intern/include/pixelblending.h
@@ -0,0 +1,209 @@
+/*
+ * pixelblending_ext.h
+ * external interface for pixelblending
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef PIXELBLENDING_EXT_H
+#define PIXELBLENDING_EXT_H
+
+/* local includes */
+#include "vanillaRenderPipe_types.h"
+
+/* own include */
+#include "pixelblending_types.h"
+
+/**
+ * Samples pixel, depending on R.osa setting
+ */
+int addtosampcol(unsigned short *sampcol, unsigned short *shortcol, int mask);
+
+/**
+ * Samples pixel, bring your own R.osa setting
+ */
+int addToSampCol(unsigned short *sampcol, unsigned short *shortcol, int mask, int osaNr);
+
+/**
+ * Halo-add pixel, bring your own R.osa setting, and add factor
+ */
+void addAddSampColF(float *s, float *d, int m, int osa, char add);
+
+/**
+ * Alpha undersamples pixel, bring your own R.osa setting
+ */
+int addUnderSampColF(float *sampcol, float *dest, int mask, int osaNr);
+
+/**
+ * Alpha oversample pixel, bring your own R.osa setting
+ */
+void addOverSampColF(float *sampcol, float *dest, int mask, int osaNr);
+
+/**
+ * Convert a series of oversampled pixels into a single pixel.
+ * (float vecs to float vec)
+ */
+void sampleFloatColV2FloatColV(float *sample, float *dest, int osaNr);
+
+/**
+ * Convert a series of oversampled pixels into a single pixel. Uses R.osa to
+ * count the length! (short vecs to short vec)
+ */
+void sampleShortColV2ShortColV(unsigned short *sample, unsigned short *dest, int osaNr);
+
+/**
+ * Take colour <bron>, and apply it to <doel> using the alpha value of
+ * <bron>.
+ * @param doel
+ * @param bron
+ */
+void addAlphaOverShort(unsigned short *doel, unsigned short *bron);
+
+/**
+ * Take colour <bron>, and apply it to <doel> using the alpha value of
+ * <doel>.
+ * @param doel
+ * @param bron
+ */
+void addAlphaUnderShort(unsigned short *doel, unsigned short *bron);
+
+/**
+ * Alpha-over blending for floats.
+ */
+void addAlphaOverFloat(float *dest, float *source);
+
+/**
+ * Alpha-under blending for floats.
+ */
+void addAlphaUnderFloat(float *dest, float *source);
+
+/**
+ * Write a 16-bit-colour colour vector to a 8-bit-colour colour vector.
+ */
+void cpShortColV2CharColV(unsigned short *source, char *dest);
+
+/**
+ * Write a 8-bit-colour colour vector to a 16-bit-colour colour vector.
+ */
+void cpCharColV2ShortColV(char *source, unsigned short *dest);
+
+/**
+ * Write a 32-bit-colour colour vector to a 8-bit-colour colour vector.
+ */
+void cpIntColV2CharColV(unsigned int *source, char *dest);
+
+/**
+ * Write a floating-point-colour colour vector to a 8-bit-colour colour
+ * vector. Clip colours to [0, 1].
+ */
+void cpFloatColV2CharColV(float *source, char *dest);
+
+/**
+ * Cpoy a 8-bit-colour vector to floating point colour vector.
+ */
+void cpCharColV2FloatColV(char *source, float *dest);
+/**
+ * Cpoy a 16-bit-colour vector to floating point colour vector.
+ */
+void cpShortColV2FloatColV(unsigned short *source, float *dest);
+
+/**
+ * Copy a float-colour colour vector.
+ */
+void cpFloatColV(float *source, float *dest);
+
+/**
+ * Copy a 16-bit-colour colour vector.
+ */
+void cpShortColV(unsigned short *source, unsigned short *dest);
+
+/**
+ * Copy an 8-bit-colour colour vector.
+ */
+void cpCharColV(char *source, char *dest);
+
+/**
+ * Add a fraction of <source> to <dest>. Result ends up in <dest>.
+ * The internal calculation is done with floats.
+ *
+ * col(dest) = (1 - alpha(source)*(1 - addfac)) * dest + source
+ * alpha(dest) = alpha(source) + alpha (dest)
+ */
+void addalphaAddfacShort(unsigned short *dest, unsigned short *source, char addfac);
+
+/**
+ * Same for floats
+ */
+void addalphaAddfacFloat(float *dest, float *source, char addfac);
+
+/**
+ * Add two halos. Result ends up in <dest>. This should be the
+ * addition of two light sources. So far, I use normal alpha-under blending here.
+ * The internal calculation is done with floats. The add-factors have to be
+ * compensated outside this routine.
+ * col(dest) = s + (1 - alpha(s))d
+ * alpha(dest) = alpha(s) + (1 - alpha(s))alpha (d)
+ */
+void addHaloToHaloShort(unsigned short *dest, unsigned short *source);
+
+/**
+ * dest = dest + source
+ */
+void addalphaAddFloat(float *dest, float *source);
+
+/** ols functions: side effects?
+void addalphaUnderFloat(char *doel, char *bron); think this already exists...
+void addalphaUnderGammaFloat(char *doel, char *bron);
+*/
+/**
+ * Blend bron under doel, while doing gamma correction
+ */
+void addalphaUnderGammaFloat(float *doel, float *bron);
+
+/**
+ * Transform an premul-alpha 32-bit colour into a key-alpha 32-bit colour.
+ */
+void applyKeyAlphaCharCol(char* target);
+
+/* Old blending functions */
+void keyalpha(char *doel); /* maakt premul 255 */
+void addalphaUnder(char *doel, char *bron);
+void addalphaUnderGamma(char *doel, char *bron);
+void addalphaOver(char *doel, char *bron);
+void addalphaAdd(char *doel, char *bron);
+void addalphaAddshort(unsigned short *doel, unsigned short *bron);
+/* void addalphaAddfac(char *doel, char *bron, char addfac); to ext, temporarily */
+void addalphaAddfacshort(unsigned short *doel,
+ unsigned short *bron,
+ short addfac);
+
+
+#endif /* PIXELBLENDING_EXT_H */
diff --git a/source/blender/render/intern/include/pixelblending_types.h b/source/blender/render/intern/include/pixelblending_types.h
new file mode 100644
index 00000000000..71e2baa994c
--- /dev/null
+++ b/source/blender/render/intern/include/pixelblending_types.h
@@ -0,0 +1,61 @@
+/*
+ * pixelblending_types.h
+ * types pixelblending
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef PIXELBLENDING_TYPES_H
+#define PIXELBLENDING_TYPES_H
+
+/* #include "blender.h" */
+
+/* Threshold for a 'full' pixel: pixels with alpha above this level are */
+/* considered opaque This is the decimal value for 0xFFF0 / 0xFFFF */
+#define RE_FULL_COLOUR_FLOAT 0.9998
+/* Threshold for an 'empty' pixel: pixels with alpha above this level are */
+/* considered completely transparent. This is the decimal value */
+/* for 0x000F / 0xFFFF */
+#define RE_EMPTY_COLOUR_FLOAT 0.0002
+/* A 100% pixel. Sometimes, seems to be too little.... Hm....... */
+#define RE_UNITY_COLOUR_FLOAT 1.0
+/* A 0% pixel. I wonder how 0 the 0.0 is... */
+#define RE_ZERO_COLOUR_FLOAT 0.0
+
+/* threshold for alpha */
+#define RE_FULL_ALPHA_FLOAT 0.9998
+
+/* Same set of defines for shorts */
+#define RE_FULL_COLOUR_SHORT 0xFFF0
+#define RE_EMPTY_COLOUR_SHORT 0x0000
+
+#endif /* PIXELBLENDING_EXT_H */
+
diff --git a/source/blender/render/intern/include/pixelshading.h b/source/blender/render/intern/include/pixelshading.h
new file mode 100644
index 00000000000..de75e96a225
--- /dev/null
+++ b/source/blender/render/intern/include/pixelshading.h
@@ -0,0 +1,122 @@
+/*
+ * pixelshading.h
+ *
+ * These functions determine what actual colour a pixel will have.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef PIXELSHADING_H
+#define PIXELSHADING_H
+
+/* ------------------------------------------------------------------------- */
+
+#include "render.h"
+#include "vanillaRenderPipe_types.h"
+/* ------------------------------------------------------------------------- */
+
+/**
+ * Render the pixel at (x,y) for object ap. Apply the jitter mask.
+ * Output is given in float collector[4]. The type vector:
+ * t[0] - min. distance
+ * t[1] - face/halo index
+ * t[2] - jitter mask
+ * t[3] - type ZB_POLY or ZB_HALO
+ * t[4] - max. distance
+ * @return pointer to the object
+ */
+void *renderPixel(float x, float y, int *t);
+
+/**
+ * Spothalos on otherwise empty pixels.
+ */
+void renderSpotHaloPixel(float x, float y, float* colbuf);
+
+/**
+ * Set the sky blending to the indicated type.
+ */
+void setSkyBlendingMode(enum RE_SkyAlphaBlendingType mode);
+
+/**
+ * Get the sky blending mode.
+ */
+enum RE_SkyAlphaBlendingType getSkyBlendingMode(void);
+/**
+ * Render the sky at pixel (x, y).
+ */
+void renderSkyPixelFloat(float x, float y);
+
+/* ------------------------------------------------------------------------- */
+/* All these are supposed to be internal. I should move these to a separate */
+/* header. */
+
+/**
+ * Determine colour for pixel at SCS x,y for face <vlaknr>. Result end up in
+ * <collector>
+ * @return pointer to this object's VlakRen
+ */
+void *renderFacePixel(float x, float y, int vlaknr);
+
+/**
+ * Render this pixel for halo haloNr. Leave result in <collector>.
+ * @return pointer to this object's HaloRen
+ */
+void *renderHaloPixel(float x, float y, int haloNr);
+
+/**
+ * Shade the halo at the given location
+ */
+void shadeHaloFloat(HaloRen *har, float *col, unsigned int zz,
+ float dist, float xn, float yn, short flarec);
+
+/**
+ * Shade a sky pixel on a certain line, into collector[4]
+ * The x-coordinate (y as well, actually) are communicated through
+ * R.view[3]
+ */
+void shadeSkyPixel(float x, float y);
+
+void shadeSpotHaloPixelFloat(float *col);
+void spotHaloFloat(struct LampRen *lar, float *view, float *intens);
+void shadeLampLusFloat(void);
+
+/* this should be replaced by shadeSpotHaloPixelFloat(), but there's */
+/* something completely fucked up here with the arith. */
+/* void renderspothaloFix(unsigned short *col); */
+void renderspothaloFix(float *col);
+
+/* used by shadeSkyPixel: */
+void shadeSkyPixelFloat(float y);
+void fillBackgroundImage(float x, float y);
+
+/* ------------------------------------------------------------------------- */
+
+#endif
diff --git a/source/blender/render/intern/include/renderHelp.h b/source/blender/render/intern/include/renderHelp.h
new file mode 100644
index 00000000000..7e192a5460e
--- /dev/null
+++ b/source/blender/render/intern/include/renderHelp.h
@@ -0,0 +1,63 @@
+/*
+ * renderhelp_ext.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef RENDERHELP_EXT_H
+#define RENDERHELP_EXT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ /* Push-pop, because this sometimes is necessary... */
+ void pushTempPanoPhi(float p);
+ void popTempPanoPhi(void);
+
+ float getPanoPhi(void);
+ float getPanovCo(void);
+ float getPanovSi(void);
+ void setPanoRot(int part);
+
+ /** Set clip flags on all data entries, using the given projection
+ * function */
+ void setzbufvlaggen( void (*projectfunc)(float *, float *) );
+
+/* external for the time being, since the converter calls it. */
+/** Recalculate all normals on renderdata. */
+/* void set_normalflags(void); */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/render/intern/include/renderPreAndPost.h b/source/blender/render/intern/include/renderPreAndPost.h
new file mode 100644
index 00000000000..74438f10df7
--- /dev/null
+++ b/source/blender/render/intern/include/renderPreAndPost.h
@@ -0,0 +1,43 @@
+/*
+ * renderpreandpost.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef RENDERPREANDPOST_H
+#define RENDERPREANDPOST_H
+
+void prepareScene(void);
+void finalizeScene(void);
+void doClipping( void (*projectfunc)(float *, float *) );
+
+
+#endif
diff --git a/source/blender/render/intern/include/render_intern.h b/source/blender/render/intern/include/render_intern.h
new file mode 100644
index 00000000000..1f058821b2b
--- /dev/null
+++ b/source/blender/render/intern/include/render_intern.h
@@ -0,0 +1,60 @@
+/*
+ * render_int.h
+ * misc internal defines for renderer
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+ /* XXX, should die, no good reason to write
+ * regular (non-file related) endian dependant
+ * code.
+ */
+#if defined(__sgi) || defined(__sparc) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
+#define RCOMP 3
+#define GCOMP 2
+#define BCOMP 1
+#define ACOMP 0
+#else
+#define RCOMP 0
+#define GCOMP 1
+#define BCOMP 2
+#define ACOMP 3
+#endif
+
+#define VECCOPY(v1,v2) {*(v1)= *(v2); *(v1+1)= *(v2+1); *(v1+2)= *(v2+2);}
+#define QUATCOPY(v1,v2) {*(v1)= *(v2); *(v1+1)= *(v2+1); *(v1+2)= *(v2+2); *(v1+3)= *(v2+3);}
+
+#define CLAMPIS(a, b, c) ((a)<(b) ? (b) : (a)>(c) ? (c) : (a))
+
+typedef struct {
+ int a, b, c, d;
+} byte16;
+#define COPY_16(a,b) (*((byte16 *)(a))= *((byte16 *)(b)))
diff --git a/source/blender/render/intern/include/rendercore.h b/source/blender/render/intern/include/rendercore.h
new file mode 100644
index 00000000000..6138fbc3e3a
--- /dev/null
+++ b/source/blender/render/intern/include/rendercore.h
@@ -0,0 +1,117 @@
+/*
+ * rendercore_ext.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef RENDERCORE_H
+#define RENDERCORE_H
+#include "render_types.h"
+
+struct HaloRen;
+
+float mistfactor(float *co); /* dist en hoogte, return alpha */
+/* void sky(char *col); */
+void renderspothalo(unsigned short *col);
+void render_lighting_halo(struct HaloRen *har, float *colf);
+unsigned int calchalo_z(struct HaloRen *har, unsigned int zz);
+float CookTorr(float *n, float *l, float *v, int hard);
+void shadelamplus(void);
+/* void renderflare(struct HaloRen *har); */
+void add_halo_flare(void);
+
+/**
+ * Apply the background (sky). Depending on the active alphamode and
+ * worldmode, different filling strategies are applied.
+ * Active alphamode = R.r.alphamode
+ * Active worldmode = R.wrld.mode
+ * <LI>
+ * <IT> R_ALPHAPREMUL - do not fill sky, but apply alpha to colours
+ * <IT> R_ALPHAKEY - do not fill sky, do not apply alpha to colours
+ * <IT> R_ADDSKY - fill skycolour in the background, blend
+ * transparent colours with the background
+ * (there's also a world dependency here?
+ * <LI>
+ * <IT> R.wrld.mode == WO_MIST
+ * <IT> R.r.bufflag == 1, R.flag == R_SEC_FIELD
+ * <IT> R.wrld.skytype == ( WO_SKYBLEND ^ WO_SKYTEX)
+ * <IT> R.wrld.skytype == WO_SKYPAPER
+ * <IT> R.r.mode == R_PANORAMA )
+ * </LI>
+ * </LI>
+ * @param rect
+ * @param y
+ */
+void scanlinesky(char *rect, int y);
+
+/**
+ * Do z buffer stuff.
+ */
+void zbufshade(void);
+
+/**
+ * Insert transparent faces into the z buffer?
+ */
+void zbufshadeDA(void); /* Delta Accum Pixel Struct */
+
+/**
+ * Also called in: zbuf.c
+ */
+void shadepixel(float x, float y, int vlaknr);
+
+/**
+ * Shade the pixel at xn, yn for halo har, and write the result to col.
+ * Also called in: previewrender.c
+ * @param har The halo to be rendered on this location
+ * @param col [unsigned int 3] The destination colour vector
+ * @param zz Some kind of distance
+ * @param dist Square of the distance of this coordinate to the halo's center
+ * @param x [f] Pixel x relative to center
+ * @param y [f] Pixel y relative to center
+ * @param flarec Flare counter? Always har->flarec...
+ */
+/* void shadehalo(struct HaloRen *har, char *col, unsigned int zz, float dist, float x, float y, short flarec); */
+
+/**
+ * A cryptic but very efficient way of counting the number of bits that
+ * is set in the unsigned short.
+ */
+int count_mask(unsigned short mask);
+
+/* These defines are only used internally :) */
+/* dirty hack: pointers are negative, indices positive */
+/* pointers should be converted to positive numbers */
+
+#define IS_A_POINTER_CODE(a) ((a)<0)
+#define POINTER_FROM_CODE(a) ((void *)(-(a)))
+#define POINTER_TO_CODE(a) (-(long)(a))
+
+#endif /* RENDER_EXT_H */
diff --git a/source/blender/render/intern/include/rendercore_int.h b/source/blender/render/intern/include/rendercore_int.h
new file mode 100644
index 00000000000..8b1fd0ed759
--- /dev/null
+++ b/source/blender/render/intern/include/rendercore_int.h
@@ -0,0 +1,55 @@
+/*
+ * render_int.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef RENDER_INT_H
+#define RENDER_INT_H
+
+#include "zbuf_types.h"
+#include "render_types.h"
+
+/* float CookTorr(float *n, float *l, float *v, int hard); */
+void do_lamphalo_tex(LampRen *lar, float *p1, float *p2, float *intens);
+void spothalo(struct LampRen *lar, float *view, float *intens);
+void add_filt_mask(unsigned int mask, unsigned short *col, unsigned int *rb1, unsigned int *rb2, unsigned int *rb3);
+void addps(long *rd, int vlak, unsigned int z, short ronde);
+PixStr *addpsmain(void);
+float count_maskf(unsigned short mask);
+void freeps(void);
+void halovert(void);
+void renderhalo(HaloRen *har); /* postprocess versie */
+void scanlinehaloPS(unsigned int *rectz, long *rectdelta, unsigned int *rectt, short ys);
+
+
+#endif /* RENDER_INT_H */
+
diff --git a/source/blender/render/intern/include/shadbuf.h b/source/blender/render/intern/include/shadbuf.h
new file mode 100644
index 00000000000..6060edfed95
--- /dev/null
+++ b/source/blender/render/intern/include/shadbuf.h
@@ -0,0 +1,75 @@
+/*
+ * shadbuf_ext.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef SHADBUF_EXT_H
+#define SHADBUF_EXT_H
+
+#include "render_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Init memory for old-style shodow buffers. */
+void initshadowbuf(struct LampRen *lar, float mat[][4]);
+
+
+/**
+ * Calculates shadowbuffers for a vector of shadow-giving lamps
+ * @param lar The vector of lamps
+ */
+void makeshadowbuf(LampRen *lar);
+
+/**
+ * Determines the shadow factor for a face and lamp. There is some
+ * communication with global variables here.
+ * @returns The shadow factors: 1.0 for no shadow, 0.0 for complete
+ * shadow.
+ * @param shb The shadowbuffer to find the shadow factor in.
+ * @param inp The inproduct between viewvector and ?
+ *
+ */
+float testshadowbuf(struct ShadBuf *shb, float inp);
+
+/**
+ * Determines the shadow factor for lamp <lar>, between <p1>
+ * and <p2>. (Which CS?)
+ */
+float shadow_halo(LampRen *lar, float *p1, float *p2);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SHADBUF_EXT_H */
diff --git a/source/blender/render/intern/include/shadowBuffer.h b/source/blender/render/intern/include/shadowBuffer.h
new file mode 100644
index 00000000000..4df95c20674
--- /dev/null
+++ b/source/blender/render/intern/include/shadowBuffer.h
@@ -0,0 +1,79 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef SHADOWBUFFER_H
+#define SHADOWBUFFER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef RE_SHADOWBUFFERHANDLE
+#define RE_SHADOWBUFFERHANDLE
+#define RE_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
+RE_DECLARE_HANDLE(RE_ShadowBufferHandle);
+#endif
+
+ struct ShadBuf;
+ struct LampRen;
+
+/**
+ * Calculates shadowbuffers for a vector of shadow-giving lamps
+ * @param lar The vector of lamps
+ * @returns a handle to the buffer
+ */
+ extern void RE_buildShadowBuffer(RE_ShadowBufferHandle dsbh,
+ struct LampRen *lar);
+
+/**
+ * Determines the shadow factor for a face and lamp. There is some
+ * communication with global variables here? Should be made explicit...
+ * @param shadres The RGB shadow factors: 1.0 for no shadow, 0.0 for complete
+ * shadow. There must be a float[3] to write the result to.
+ * @param shb The shadowbuffer to find the shadow factor in.
+ * @param inp The inproduct between viewvector and ?
+ *
+ */
+ void RE_testshadowbuf(RE_ShadowBufferHandle dsbh,
+ struct ShadBuf* shbp,
+ float inp,
+ float* shadres);
+
+/**
+ * Determines a shadow factor for halo-shadows.
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SHADOWBUFFER_H */
diff --git a/source/blender/render/intern/include/texture.h b/source/blender/render/intern/include/texture.h
new file mode 100644
index 00000000000..9d033ac26dd
--- /dev/null
+++ b/source/blender/render/intern/include/texture.h
@@ -0,0 +1,86 @@
+/*
+ * texture_ext.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef TEXTURE_EXT_H
+#define TEXTURE_EXT_H "$Id$"
+#define TEXTURE_EXT_H "Copyright (C) 2001 NaN Technologies B.V.
+
+/* no types!!! */
+/* #include "texture_types.h" */
+
+struct Tex;
+struct MTex;
+struct HaloRen;
+struct LampRen;
+/**
+ * Takes uv coordinates (R.uv[], O.dxuv, O.dyuv), find texture colour
+ * at that spot (using imagewrap()).
+ * Result is kept in R.vcol (float vector 3)
+ */
+void render_realtime_texture(void);
+
+/**
+ * Do texture mapping for materials. Communicates with R.... variables.
+ */
+void do_material_tex(void);
+
+/* unsorted */
+int blend(struct Tex *tex, float *texvec);
+int clouds(struct Tex *tex, float *texvec);
+int cubemap(struct MTex *mtex, float x, float y, float z, float *adr1, float *adr2);
+int cubemap_glob(struct MTex *mtex, float x, float y, float z, float *adr1, float *adr2);
+int cubemap_ob(struct MTex *mtex, float x, float y, float z, float *adr1, float *adr2);
+void do_2d_mapping(struct MTex *mtex, float *t, float *dxt, float *dyt);
+void do_halo_tex(struct HaloRen *har, float xn, float yn, float *colf);
+void do_lamp_tex(struct LampRen *la, float *lavec);
+void do_sky_tex(void);
+int magic(struct Tex *tex, float *texvec);
+int marble(struct Tex *tex, float *texvec);
+int multitex(struct Tex *tex, float *texvec, float *dxt, float *dyt);
+int plugintex(struct Tex *tex, float *texvec, float *dxt, float *dyt);
+int stucci(struct Tex *tex, float *texvec);
+int texnoise(struct Tex *tex);
+int wood(struct Tex *tex, float *texvec);
+
+#endif /* TEXTURE_EXT_H */
+
+
+
+
+
+
+
+
+
+
diff --git a/source/blender/render/intern/include/vanillaRenderPipe.h b/source/blender/render/intern/include/vanillaRenderPipe.h
new file mode 100644
index 00000000000..4dfaa41e91d
--- /dev/null
+++ b/source/blender/render/intern/include/vanillaRenderPipe.h
@@ -0,0 +1,49 @@
+/*
+ * vanillaRenderPipe_ext.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef VANILLARENDERPIPE_EXT_H
+#define VANILLARENDERPIPE_EXT_H
+
+#include "vanillaRenderPipe_types.h"
+
+/**
+ * Render pipeline with all kinds of extras.
+ * status-------------------------\/
+ * - integrated z buffering ok
+ * - integrated halo rendering ok
+ */
+void zBufShadeAdvanced(void);
+
+
+#endif /* VANILLARENDERPIPE_EXT_H */
diff --git a/source/blender/render/intern/include/vanillaRenderPipe_int.h b/source/blender/render/intern/include/vanillaRenderPipe_int.h
new file mode 100644
index 00000000000..024b82cc812
--- /dev/null
+++ b/source/blender/render/intern/include/vanillaRenderPipe_int.h
@@ -0,0 +1,191 @@
+/*
+ * vanillaRenderPipe_int.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef VANILLARENDERPIPE_INT_H
+#define VANILLARENDERPIPE_INT_H
+
+#include "vanillaRenderPipe_types.h"
+#include "zbufferdatastruct_types.h"
+
+/**
+ * Z buffer initializer, for new pipeline.
+ * <LI>
+ * <IT> AColourBuffer : colour buffer for one line
+ * <IT> APixbufExt : pixel data buffer for one line, depth RE_ZBUFLEN
+ * </LI>
+ */
+void initRenderBuffers(int width);
+/* void initRenderBuffers(void); */
+
+/**
+ * Z buffer destructor, frees stuff from initZBuffers().
+ */
+void freeRenderBuffers(void);
+
+/**
+ * Fill the accumulation buffer APixbufExt with face and halo indices.
+ * Note: Uses globals.
+ * @param y the line number to set
+ */
+void calcZBufLine(int y);
+
+/**
+ * Shade and render the pixels in this line, into AColourBuffer
+ * Note: Uses globals.
+ * @param y the line number to set
+ */
+void renderZBufLine(int y);
+
+/**
+ * Count and sort the list behind ap into buf. Sorts on min. distance.
+ * Low index <=> high z
+ */
+int countAndSortPixelFaces(int buf[RE_MAX_FACES_PER_PIXEL][5],
+ RE_APixstrExt *ap);
+
+/**
+ * Compose the conflict and colour stacks
+ * Note: Uses globals.
+ */
+int composeStack(int zrow[RE_MAX_FACES_PER_PIXEL][RE_PIXELFIELDSIZE],
+ struct RE_faceField* stack, int ptr,
+ int totvlak, float x, float y, int osaNr);
+/**
+ * Integrate conflicting layers.
+ * Note: Uses globals.
+ */
+int resolveConflict(struct RE_faceField* stack, int ptr, float x, float y);
+
+/**
+ * Integrate the colour stack, defer conflicts.
+ * Note: Uses globals.
+ */
+void integrateStack(struct RE_faceField* stack, int ptr,
+ float x, float y, int osaNr);
+
+/**
+ * Calculate the view depth to this object on this location, with
+ * the current view parameters in R.
+ */
+int calcDepth(float x, float y, void *data, int type);
+
+
+
+/**
+ * Fills in distances of all faces in a z buffer, for given jitter settings.
+ */
+int fillZBufDistances(void);
+
+/**
+ * Fills in distances of faces in the z buffer.
+ *
+ * Halo z buffering ----------------------------------------------
+ *
+ * A halo is treated here as a billboard: no z-extension, always
+ * oriented perpendicular to the viewer. The rest of the z-buffer
+ * stores face-numbers first, then calculates colours as the
+ * final image is rendered. We'll use the same approach here,
+ * which differs from the original method (which was add halos per
+ * scan line). This means that the z-buffer now also needs to
+ * store info about what sort of 'thing' the index refers to.
+ *
+ * Halo extension:
+ * h.maxy ---------
+ * | h.xs + h.rad
+ * | h.xs
+ * | h.xs - h.rad
+ * h.miny ---------
+ *
+ * These coordinates must be clipped to picture size.
+ * I'm not quite certain about halo numbering.
+ *
+ * Halos and jittering -------------------------------------------
+ *
+ * Halos were not jittered previously. Now they are. I wonder
+ * whether this may have some adverse effects here.
+
+ * @return 1 for succes, 0 if the operation was interrupted.
+ */
+int zBufferAllFaces(void);
+
+/**
+ * Fills in distances of halos in the z buffer.
+ * @return 1 for succes, 0 if the operation was interrupted.
+ */
+int zBufferAllHalos(void);
+
+/**
+ * New fill function for z buffer, for edge-only rendering.
+ */
+void zBufferFillEdge(float *vec1, float *vec2);
+
+/**
+ * New fill function for z buffer.
+ */
+void zBufferFillFace(float *v1, float *v2, float *v3);
+
+/**
+ * One more filler: fill in halo data in z buffer.
+ * Empty so far, but may receive content of halo loop.
+ */
+void zBufferFillHalo(void);
+
+/**
+ * Copy the colour buffer output to R.rectot, to line y.
+ */
+void transferColourBufferToOutput(int y);
+
+/**
+ * Set the colour buffer fields to zero.
+ */
+void eraseColBuf(RE_COLBUFTYPE *buf);
+
+/**
+ * Blend source over dest, and leave result in dest. 1 pixel.
+ */
+void blendOverFloat(int type, float* dest, float* source, void* data);
+
+/**
+ * Blend source over dest, and leave result in dest. 1 pixel into
+ * multiple bins.
+ */
+void blendOverFloatRow(int type, float* dest, float* source,
+ void* data, int mask, int osaNr) ;
+
+/**
+ * Do a post-process step on a finalized render image.
+ */
+void std_transFloatColV2CharColV( RE_COLBUFTYPE *buf, char *target);
+
+#endif /* VANILLARENDERPIPE_INT_H */
diff --git a/source/blender/render/intern/include/vanillaRenderPipe_types.h b/source/blender/render/intern/include/vanillaRenderPipe_types.h
new file mode 100644
index 00000000000..90828ff62c3
--- /dev/null
+++ b/source/blender/render/intern/include/vanillaRenderPipe_types.h
@@ -0,0 +1,90 @@
+/*
+ * vanillaRenderPipe_types.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef VANILLARENDERPIPE_TYPES_H
+#define VANILLARENDERPIPE_TYPES_H
+
+/* Render defines */
+#define RE_MAX_OSA_COUNT 16 /* The max. number of possible oversamples */
+#define RE_MAX_FACES_PER_PIXEL 500 /* max. nr of faces rendered behind one */
+ /* pixel */
+
+enum RE_SkyAlphaBlendingType {
+ RE_ALPHA_NODEF = 0,
+ RE_ALPHA_PREMUL,
+ RE_ALPHA_KEY,
+ RE_ALPHA_SKY,
+ RE_ALPHA_MAX
+};
+
+
+/* Render typedefs */
+typedef float RE_COLBUFTYPE; /* datatype for the colour buffer */
+
+
+/**
+ * Threshold for add-blending for faces
+ */
+#define RE_FACE_ADD_THRESHOLD 0.001
+
+/**
+ For oversampling
+
+ New stack: the old stack limits our freedom to do all kinds of
+ manipulation, so we rewrite it.
+
+ A stacked face needs:
+ - a face type
+ - a colour
+ - a conflict count
+ - a data pointer (void*)
+ - a mask
+
+ The stack starts at index 0, with the closest face, and stacks up.
+
+*/
+
+struct RE_faceField {
+ int faceType;
+ float colour[4];
+ int conflictCount;
+ void *data;
+ int mask;
+};
+
+
+
+#endif /* VANILLARENDERPIPE_TYPES_H */
+
+
diff --git a/source/blender/render/intern/include/zbuf.h b/source/blender/render/intern/include/zbuf.h
new file mode 100644
index 00000000000..fdfa5b19abe
--- /dev/null
+++ b/source/blender/render/intern/include/zbuf.h
@@ -0,0 +1,180 @@
+/*
+ * zbuf_ext.h
+ * external interface for zbuf.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef ZBUF_H
+#define ZBUF_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct LampRen;
+struct VlakRen;
+
+/*-----------------------------------------------------------*/
+/* Includes */
+/*-----------------------------------------------------------*/
+
+#include "zbuf_types.h"
+#include "render_types.h"
+#include "radio_types.h" /* for RadView */
+
+/*-----------------------------------------------------------*/
+/* Function */
+/* (11 so far ) */
+/*-----------------------------------------------------------*/
+
+/**
+ * Fill a 'rectangle' with a fixed value. The rectangle contains x by
+ * y points. The rows are assumed to be contiguous in memory, and to
+ * consist of uints. This function is used for initializing the z
+ * buffer.
+ * (why is x int and y uint? called in envmap, render, zbuf)
+ * @param rect Pointer to the data representing the rectangle.
+ * @param x The width of the rectangle
+ * @param y The height of the rectangle
+ * @param val The value used to fill the rectangle.
+ */
+void fillrect(unsigned int *rect, int x, unsigned int y, unsigned int val);
+
+/**
+ * Converts a world coordinate into a homogenous coordinate in view
+ * coordinates. The transformation matrix is only allowed to have a
+ * scaling and translation component.
+ * Also called in: shadbuf.c render.c radfactors.c
+ * initrender.c envmap.c editmesh.c
+ * @param v1 [3 floats] the world coordinate
+ * @param adr [4 floats] the homogenous view coordinate
+ */
+void projectvert(float *v1,float *adr);
+
+
+/**
+ * Do a z buffer calculation pass for shadow calculations.
+ * Also called in: shadbuf.c
+ * Note: Uses globals.
+ * @param lar lamp definition data
+ */
+void zbuffershad(struct LampRen *lar);
+
+ /* to the external interface, temp, I hope... */
+/**
+ * Tests whether the first three coordinates should be clipped
+ * wrt. the fourth component. Bits 1 and 2 test on x, 3 and 4 test on
+ * y, 5 and 6 test on z:
+ * xyz > test => set first bit (01),
+ * xyz < -test => set second bit (10),
+ * xyz == test => reset both bits (00).
+ * Note: functionality is duplicated from an internal function
+ * Also called in: initrender.c, radfactors.c
+ * @param v [4 floats] a coordinate
+ * @return a vector of bitfields
+ */
+/* int testclip(float *v); */
+
+
+/* The following are only used in zbuf.c and render.c ---------------*/
+/**
+ * Fills the entire in the alpha DA buffer. (All of it!)
+ * Note: Uses globals.
+ * Also called in: render.c
+ * @param y the line number to set
+ */
+void abufsetrow(int y);
+
+
+/**
+ * Calculate the z buffer for all faces (or edges when in wireframe
+ * mode) presently visible.
+ * Note: Uses globals.
+ * Also called in: render.c
+ */
+void zbufferall(void);
+
+
+/**
+ * Initialize accumulation buffers for alpha z buffering.
+ * The buffers are global variables. Also resets Accu buffer
+ * y bounds.
+ * <LI>
+ * <IT> Acolrow : colour buffer for one line
+ * <IT> Arectz : distance buffer for one line, depth ABUFPART
+ * <IT> APixbuf : pixel data buffer for one line, depth ABUFPART
+ * </LI>
+ * Also called in: render.c (should migrate)
+ * Note: Uses globals.
+ */
+void bgnaccumbuf(void);
+
+/**
+ * Discard accumulation buffers for alpha z buffering.
+ * The buffers are global variables. The released buffers are Acolrow,
+ * Arectz, APixBuf.
+ * Also called in: render.c (should migrate)
+ * Note: Uses globals.
+ */
+void endaccumbuf(void);
+
+/**
+ * Z face intersect?
+ */
+int vergzvlak(const void *x1, const void *x2);
+
+/**
+ * Clip and fill vertex into the z buffer. zbuffunc needs to be set
+ * before entering, to assure that there is a buffer fill function
+ * that can be called. Zvlnr must be set to the current valid face
+ * index .
+ * Note: uses globals
+ * @param f1 [4 floats] vertex 1
+ * @param f2 [4 floats] vertex 2
+ * @param f3 [4 floats] vertex 3
+ * @param c1 clip conditions?
+ * @param c2
+ * @param c3
+ */
+void zbufclip(float *f1, float *f2, float *f3, int c1, int c2, int c3);
+
+/**
+ * same, for edges
+ */
+void zbufclipwire(struct VlakRen *vlr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/source/blender/render/intern/include/zbuf_int.h b/source/blender/render/intern/include/zbuf_int.h
new file mode 100644
index 00000000000..1ea416a581f
--- /dev/null
+++ b/source/blender/render/intern/include/zbuf_int.h
@@ -0,0 +1,203 @@
+/*
+ * zbuf_int.h
+ * internal interface for zbuf.h (ie. functions that are not used
+ * anywhere else)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef ZBUF_INT_H
+#define ZBUF_INT_H
+
+#include "render_types.h"
+#include "zbuf_types.h"
+
+
+
+/**
+ * Convert a homogenous coordinate to a z buffer coordinate. The
+ * function makes use of Zmulx, Zmuly, the x and y scale factors for
+ * the screen, and Zjitx, Zjity, the pixel offset. (These are declared
+ * in render.c) The normalised z coordinate must fall on [0, 1].
+ * @param zco [3, 4 floats] pointer to the resulting z buffer coordinate
+ * @param hoco [4 floats] pointer to the homogenous coordinate of the
+ * vertex in world space.
+ */
+void hoco_to_zco(float *zco, float *hoco);
+
+/**
+ * Fill the z buffer for alpha?
+ *
+ * This is one of the z buffer fill functions called in zbufclip() and
+ * zbufwireclip().
+ *
+ * @param v1 [4 floats, world coordinates] first vertex
+ * @param v2 [4 floats, world coordinates] second vertex
+ * @param v3 [4 floats, world coordinates] third vertex
+ */
+void zbufinvulAc(float *v1, float *v2, float *v3);
+
+/**
+ * Fill the z buffer, but invert z order, and add the face index to
+ * the corresponing face buffer.
+ *
+ * This is one of the z buffer fill functions called in zbufclip() and
+ * zbufwireclip().
+ *
+ * @param v1 [4 floats, world coordinates] first vertex
+ * @param v2 [4 floats, world coordinates] second vertex
+ * @param v3 [4 floats, world coordinates] third vertex
+ */
+void zbufinvulGLinv(float *v1, float *v2, float *v3);
+
+/**
+ * Fill the z buffer, and add the face index to
+ * the corresponing face buffer. Writes into R.rectz and R.rectot. It
+ * assumes that Zvlnr is set to the face index of the face under
+ * consideration. Zvlnr is written into R.rectot. R.rectz
+ *
+ * This is one of the z buffer fill functions called in zbufclip() and
+ * zbufwireclip().
+ *
+ * @param v1 [4 floats, world coordinates] first vertex
+ * @param v2 [4 floats, world coordinates] second vertex
+ * @param v3 [4 floats, world coordinates] third vertex
+ */
+void zbufinvulGL(float *v1, float *v2, float *v3);
+
+/**
+ * Fill the z buffer. The face buffer is not operated on!
+ *
+ * This is one of the z buffer fill functions called in zbufclip() and
+ * zbufwireclip().
+ *
+ * @param v1 [4 floats, world coordinates] first vertex
+ * @param v2 [4 floats, world coordinates] second vertex
+ * @param v3 [4 floats, world coordinates] third vertex
+ */
+void zbufinvulGL_onlyZ(float *v1, float *v2, float *v3);
+
+/**
+ * Prints 3 unlabelled floating point values to stdout. Used for diagnostics.
+ * @param v1 any float
+ * @param v2 any float
+ * @param v3 any float
+ */
+void print3floats(float *v1, float *v2, float *v3);
+
+/**
+ * Checks labda and uses this to make decision about clipping the line
+ * segment from v1 to v2. labda is the factor by which the vector is
+ * cut. ( calculate s + l * ( t - s )). The result is appended to the
+ * vertex list of this face.
+ * Note: uses globals.
+ * (arguments: one int, one pointer to int... why?)
+ * @param v1 start coordinate s
+ * @param v2 target coordinate t
+ * @param b1
+ * @param b2
+ * @param clve vertex vector.
+ */
+static void maakvertpira(float *v1, float *v2, int *b1, int b2, int *clve);
+
+/**
+ * Sets labda: flag, and parametrize the clipping of vertices in
+ * viewspace coordinates. labda = -1 means no clipping, labda in [0,
+ * 1] means a clipping.
+ * Note: uses globals.
+ * @param v1 start coordinate s
+ * @param v2 target coordinate t
+ * @param b1
+ * @param b2
+ * @param b3
+ * @param a index for coordinate (x, y, or z)
+ */
+static void clipp(float *v1, float *v2, int b1, int *b2, int *b3, int a);
+
+/**
+ * Tests whether this coordinate is 'inside' or 'outside' of the view
+ * volume? By definition, this is in [0, 1].
+ * @param p vertex z difference plus coordinate difference?
+ * @param q origin z plus r minus some coordinate?
+ * @param u1 [in/out] clip fraction for ?
+ * @param u2 [in/out]
+ * @return 0 if point is outside, or 1 if the point lies on the clip
+ * boundary
+ */
+static short cliptestf(float p, float q, float *u1, float *u2);
+
+
+/* not documented yet */
+/* not sure if these should stay static... */
+
+static int clipline(float *v1, float *v2);
+
+/**
+ * Provide book-keeping for the z buffer data lists.
+ */
+APixstr *addpsmainA(void);
+void freepsA(void);
+APixstr *addpsA(void);
+
+/**
+ * Fill function for the z buffer (fills lines)
+ */
+void zbuflineAc(float *vec1, float *vec2);
+void zbufline(float *vec1, float *vec2);
+
+
+/**
+ * Copy results from the solid face z buffering to the transparent
+ * buffer.
+ */
+void copyto_abufz(int sample);
+
+/**
+ * Do accumulation z buffering.
+ */
+void zbuffer_abuf(void);
+
+/**
+ * Shade this face at this location in SCS.
+ */
+void shadetrapixel(float x, float y, int vlak);
+
+/**
+ * Determine the distance to the camera of this halo, in ZCS.
+ */
+unsigned int calcHaloDist(HaloRen *har);
+
+#endif /* ZBUF_INT_H */
+
+
+
+
+
diff --git a/source/blender/render/intern/include/zbuf_types.h b/source/blender/render/intern/include/zbuf_types.h
new file mode 100644
index 00000000000..49960541fa0
--- /dev/null
+++ b/source/blender/render/intern/include/zbuf_types.h
@@ -0,0 +1,78 @@
+/*
+ * zbuf_types.h
+ * type definitions used (and maybe exported) by zbuf.c.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef ZBUF_TYPES_H
+#define ZBUF_TYPES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ABUFPART 64
+
+/**
+ * Primitive data structure for zbuffering. One struct
+ * stores data for 4 entries.
+ */
+typedef struct APixstr {
+ unsigned short mask[4]; /* jitter mask */
+ int z[4]; /* distance */
+ int p[4]; /* index */
+ struct APixstr *next;
+} APixstr;
+
+
+typedef struct APixstrMain
+{
+ struct APixstr *ps;
+ struct APixstrMain *next;
+} APixstrMain;
+
+
+typedef struct {
+ float *vert;
+ float hoco[4];
+ int clip;
+} VertBucket;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZBUF_TYPES_H */
+
+
+
+
diff --git a/source/blender/render/intern/include/zbufferdatastruct.h b/source/blender/render/intern/include/zbufferdatastruct.h
new file mode 100644
index 00000000000..3e36066100c
--- /dev/null
+++ b/source/blender/render/intern/include/zbufferdatastruct.h
@@ -0,0 +1,99 @@
+/*
+ * zbufferdatastruct_ext.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef ZBUFFERDATASTRUCT_EXT_H
+#define ZBUFFERDATASTRUCT_EXT_H
+
+#include "zbufferdatastruct_types.h"
+
+/**
+ * Set memory and counters for a fresh z buffer
+ */
+void initZbuffer(int linewidth);
+
+/**
+ * Release memory for the current z buffer
+ */
+void freeZbuffer(void);
+
+/**
+ * Release previous buffer and initialise new buffer.
+ */
+void resetZbuffer(void);
+
+/**
+ * Make a root for a memory block (internal)
+ */
+RE_APixstrExt *addpsemainA(void);
+
+/**
+ * Release a memory chunk
+ */
+void freepseA(void);
+
+/**
+ * Add a structure
+ */
+RE_APixstrExt *addpseA(void);
+
+/**
+ * Add an object to a zbuffer entry.
+ */
+void insertObject(int teller,
+/* int opaque, */
+ int obindex,
+ int obtype,
+ int dist,
+ int mask);
+
+/**
+ * Add a flat object to a zbuffer entry.
+ */
+void insertFlatObject(RE_APixstrExt* ap,
+ int obindex,
+ int obtype,
+ int dist,
+ int mask);
+
+/**
+ * Add a flat object to a zbuffer entry, but don't do OSA entry testing.
+ */
+void insertFlatObjectNoOsa(RE_APixstrExt* ap,
+ int obindex,
+ int obtype,
+ int dist,
+ int mask);
+
+
+#endif
diff --git a/source/blender/render/intern/include/zbufferdatastruct_types.h b/source/blender/render/intern/include/zbufferdatastruct_types.h
new file mode 100644
index 00000000000..10e0db8a540
--- /dev/null
+++ b/source/blender/render/intern/include/zbufferdatastruct_types.h
@@ -0,0 +1,77 @@
+/*
+ * zbufferdatastruct_types.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef ZBUFFERDATASTRUCT_TYPES_H
+#define ZBUFFERDATASTRUCT_TYPES_H
+
+#define RE_ZBUFLEN 64 /* number of lines in the accumulation buffer */
+
+/**
+ * Primitive data structure for zbuffering. One struct
+ * stores data for 4 entries. This struct has been extended
+ * for the render pipeline overhaul.
+ */
+typedef struct RE_APixstrExt {
+ unsigned short mask[4]; /* jitter masks */
+ int zmin[4]; /* min. distance of all samples */
+ int zmax[4]; /* max. distance of all samples */
+ int p[4]; /* index */
+ int t[4]; /* entry type: ZB_POLY or ZB_HALO */
+ struct RE_APixstrExt *next;
+} RE_APixstrExt;
+
+/* For now I'll stick to the Blender convention of hand made defines */
+/* but this should definitely be done in a better way. An enum may */
+/* be some help, but masking is still a nice feature... */
+/* object types to buffer in the z buffer */
+#define RE_NONE 0
+#define RE_POLY 1
+#define RE_HALO 2
+#define RE_SKY 4
+
+/* unique indices for each field */
+#define RE_ZMIN 0
+#define RE_INDEX 1
+#define RE_MASK 2
+#define RE_TYPE 3
+#define RE_ZMAX 4
+#define RE_PIXELFIELDSIZE 5
+
+typedef struct RE_APixstrExtMain
+{
+ struct RE_APixstrExt *ps;
+ struct RE_APixstrExtMain *next;
+} RE_APixstrExtMain;
+
+#endif
diff --git a/source/blender/render/intern/source/Makefile b/source/blender/render/intern/source/Makefile
new file mode 100644
index 00000000000..5e3d1b095ad
--- /dev/null
+++ b/source/blender/render/intern/source/Makefile
@@ -0,0 +1,60 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL/BL DUAL LICENSE BLOCK *****
+#
+#
+
+LIBNAME = render
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+ CCFLAGS += -funsigned-char
+endif
+
+CFLAGS += $(LEVEL_2_C_WARNINGS)
+
+# first /include is my own includes, second is the external interface.
+# The external modules follow after. There should be a nicer way to say this.
+CPPFLAGS += -I../include
+CPPFLAGS += -I../../extern/include
+CPPFLAGS += -I../../../radiosity/extern/include
+CPPFLAGS += -I../../../misc
+CPPFLAGS += -I../../../blenlib
+CPPFLAGS += -I../../../imbuf
+CPPFLAGS += -I../../../makesdna
+CPPFLAGS += -I../../../blenkernel
+CPPFLAGS += -I../../../../kernel/gen_messaging
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+# not very neat: the rest of blender..
+CPPFLAGS += -I../../../include
+
diff --git a/source/blender/render/intern/source/RE_DummyShadowBuffer.cpp b/source/blender/render/intern/source/RE_DummyShadowBuffer.cpp
new file mode 100644
index 00000000000..e2adefc05f2
--- /dev/null
+++ b/source/blender/render/intern/source/RE_DummyShadowBuffer.cpp
@@ -0,0 +1,66 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+// #include <iostream.h>
+
+#include "render_intern.h"
+
+#include "RE_DummyShadowBuffer.h"
+struct LampRen;
+
+RE_DummyShadowBuffer::RE_DummyShadowBuffer(void)
+{
+ /* empty for now */
+// cout << "Constructing dummy SB\n";
+}
+
+RE_DummyShadowBuffer::~RE_DummyShadowBuffer(void)
+{
+ /* empty for now */
+// cout << "Deconstructing dummy SB\n";
+}
+
+void RE_DummyShadowBuffer::importScene(struct LampRen* lar)
+{
+ /* empty for now */
+// cout << "Importing scene in dummy SB\n";
+}
+
+void RE_DummyShadowBuffer::readShadowValue(struct ShadBuf *shb,
+ float inp,
+ float* shadowResult)
+{
+ /* a sort of puple-ish colour */
+ shadowResult[0] = 1.0;
+ shadowResult[1] = 0.0;
+ shadowResult[2] = 0.5;
+}
diff --git a/source/blender/render/intern/source/RE_basicShadowBuffer.cpp b/source/blender/render/intern/source/RE_basicShadowBuffer.cpp
new file mode 100644
index 00000000000..e126a755c35
--- /dev/null
+++ b/source/blender/render/intern/source/RE_basicShadowBuffer.cpp
@@ -0,0 +1,734 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <string.h>
+
+//#include <iostream.h>
+#include "MEM_guardedalloc.h"
+#include "BLI_arithb.h"
+
+#include "DNA_lamp_types.h"
+/* c stuff */
+#include "MTC_matrixops.h"
+#include "render.h"
+#include "render_intern.h"
+#include "renderHelp.h"
+#include "jitter.h"
+#include "zbuf.h"
+#include "shadbuf.h"
+
+/* own include */
+#include "RE_basicShadowBuffer.h"
+/* crud */
+#define MIN2(x,y) ( (x)<(y) ? (x) : (y) )
+/* ------------------------------------------------------------------------- */
+/* The implementation of this one is a bit of a fraud still, as it
+ * still relies on everything internally to be done in C. Memory is
+ * allocated on the fly, and deallocated elsewhere... There's not much
+ * more than a handle for the implementation here. This is an exact
+ * copy of the old code, retrofitted for integration in the unified
+ * renderer.
+ *
+ * - the shadow values are tripled to make a shadow vector out of a
+ * single shadow value
+ */
+
+RE_BasicShadowBuffer::RE_BasicShadowBuffer(struct LampRen *lar, float mat[][4])
+{
+// cout << "Constructing basic SB\n";
+ bias = 0x00500000;
+ initshadowbuf(lar, mat); /* a ref to the shb is stored in the lar */
+}
+
+RE_BasicShadowBuffer::~RE_BasicShadowBuffer(void)
+{
+ /* clean-up is done when the lar's are deleted */
+// cout << "Destroying basic SB\n";
+}
+
+void RE_BasicShadowBuffer::lrectreadRectz(int x1, int y1,
+ int x2, int y2,
+ char *r1) /* leest deel uit rectz in r1 */
+{
+ unsigned int len4, *rz;
+
+ if(x1>=R.rectx || x2>=R.rectx || y1>=R.recty || y2>=R.recty) return;
+ if(x1>x2 || y1>y2) return;
+
+ len4= 4*(x2- x1+1);
+ rz= R.rectz+R.rectx*y1+x1;
+ for(;y1<=y2;y1++) {
+ memcpy(r1,rz,len4);
+ rz+= R.rectx;
+ r1+= len4;
+ }
+}
+
+
+int RE_BasicShadowBuffer::sizeoflampbuf(struct ShadBuf *shb)
+{
+ int num,count=0;
+ char *cp;
+
+ cp= shb->cbuf;
+ num= (shb->size*shb->size)/256;
+
+ while(num--) count+= *(cp++);
+
+ return 256*count;
+}
+
+float* RE_BasicShadowBuffer::give_jitter_tab(int samp)
+{
+ /* these are all possible jitter tables, takes up some
+ * 12k, not really bad!
+ * For soft shadows, it saves memory and render time
+ */
+ static int tab[17]={1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256};
+ static float jit[1496][2];
+ static char ctab[17]= {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ int a, offset=0;
+
+ if(samp<2) samp= 2;
+ else if(samp>16) samp= 16;
+
+ for(a=0; a<samp-1; a++) offset+= tab[a];
+
+ if(ctab[samp]==0) {
+ initjit(jit[offset], samp*samp);
+ ctab[samp]= 1;
+ }
+
+ return jit[offset];
+
+}
+
+void RE_BasicShadowBuffer::importScene(LampRen *lar)
+{
+ struct ShadBuf *shb= lar->shb;
+ float panophi;
+ float temp, wsize, dist;
+ int *rz, *rz1, verg, verg1;
+ unsigned long *ztile;
+ int a, x, y, minx, miny, byt1, byt2;
+ short temprx,tempry, square;
+ char *rc, *rcline, *ctile, *zt;
+
+ panophi = getPanoPhi();
+
+ /* viewvars onthouden */
+ temprx= R.rectx; tempry= R.recty;
+ R.rectx= R.recty= shb->size;
+
+ shb->jit= give_jitter_tab(shb->samp);
+
+ /* matrices en window: in R.winmat komt transformatie
+ van obsview naar lampview, inclusief lampwinmat */
+
+ wsize= shb->pixsize*(shb->size/2.0);
+
+ i_window(-wsize, wsize, -wsize, wsize, shb->d, shb->far, shb->winmat);
+
+ MTC_Mat4MulMat4(shb->persmat, shb->viewmat, shb->winmat);
+
+ /* temp, will be restored */
+ MTC_Mat4SwapMat4(shb->persmat, R.winmat);
+
+ /* zbufferen */
+ if(R.rectz) MEM_freeN(R.rectz);
+ R.rectz= (unsigned int *)MEM_mallocN(sizeof(int)*shb->size*shb->size,"makeshadbuf");
+ rcline= (char*) MEM_mallocN(256*4+sizeof(int),"makeshadbuf2");
+
+ /* onthouden: panorama rot */
+ temp= panophi;
+ panophi= 0.0;
+ pushTempPanoPhi(0.0);
+
+ /* pano interference here? */
+ setzbufvlaggen(projectvert);
+
+ popTempPanoPhi();
+ panophi= temp;
+
+ zbuffershad(lar);
+
+ /* alle pixels 1 x ingevuld verwijderen (oneven) */
+ /* probleem hierbij kan geven dat er abrupte overgangen van zacht gebied
+ * naar geen zacht gebied is: bijv als eronder een klein vlakje zit
+ * DAAROM ER WEER UIT
+ * ook vanwege shadowhalo!
+ *
+ a= shb->size*shb->size;
+ rz= R.rectz;
+ while(a--) {
+ if(*rz & 1) *rz= 0x7FFFFFFF;
+ rz++;
+ }
+ */
+
+ square= lar->mode & LA_SQUARE;
+
+ /* Z tiles aanmaken: dit systeem is 24 bits!!! */
+
+ ztile= shb->zbuf;
+ ctile= shb->cbuf;
+ for(y=0; y<shb->size; y+=16) {
+ if(y< shb->size/2) miny= y+15-shb->size/2;
+ else miny= y-shb->size/2;
+
+ for(x=0; x<shb->size; x+=16) {
+
+ /* ligt rechthoek binnen spotbundel? */
+ a= shb->size/2;
+ if(x< a) minx= x+15-a;
+ else minx= x-a;
+
+ dist= sqrt( (float)(minx*minx+miny*miny) );
+
+ if(square==0 && dist>(float)(a+12)) { /* 12, tested with a onlyshadow lamp */
+ a= 256; verg= 0; /* 0x80000000; */ /* 0x7FFFFFFF; */
+ rz1= (&verg)+1;
+ }
+ else {
+ lrectreadRectz(x, y, MIN2(shb->size-1,x+15), MIN2(shb->size-1,y+15), rcline);
+ rz1= (int *)rcline;
+
+ verg= (*rz1 & 0xFFFFFF00);
+
+ for(a=0;a<256;a++,rz1++) {
+ if( (*rz1 & 0xFFFFFF00) != verg) break;
+ }
+ }
+ if(a==256) { /* compleet leeg vakje */
+ *ctile= 0;
+ *ztile= *(rz1-1);
+ }
+ else {
+
+ /* ACOMP enz. zijn defined L/B endian */
+
+ rc= rcline;
+ rz1= (int *)rcline;
+ verg= rc[ACOMP];
+ verg1= rc[BCOMP];
+ rc+= 4;
+ byt1= 1; byt2= 1;
+ for(a=1;a<256;a++,rc+=4) {
+ byt1 &= (verg==rc[ACOMP]);
+ byt2 &= (verg1==rc[BCOMP]);
+
+ if(byt1==0) break;
+ }
+ if(byt1 && byt2) { /* alleen byte opslaan */
+ *ctile= 1;
+ *ztile= (unsigned long)MEM_mallocN(256+4, "tile1");
+ rz= (int *)*ztile;
+ *rz= *rz1;
+
+ zt= (char *)(rz+1);
+ rc= rcline;
+ for(a=0; a<256; a++, zt++, rc+=4) *zt= rc[GCOMP];
+ }
+ else if(byt1) { /* short opslaan */
+ *ctile= 2;
+ *ztile= (unsigned long)MEM_mallocN(2*256+4,"Tile2");
+ rz= (int *)*ztile;
+ *rz= *rz1;
+
+ zt= (char *)(rz+1);
+ rc= rcline;
+ for(a=0; a<256; a++, zt+=2, rc+=4) {
+ zt[0]= rc[BCOMP];
+ zt[1]= rc[GCOMP];
+ }
+ }
+ else { /* triple opslaan */
+ *ctile= 3;
+ *ztile= (unsigned long)MEM_mallocN(3*256,"Tile3");
+
+ zt= (char *)*ztile;
+ rc= rcline;
+ for(a=0; a<256; a++, zt+=3, rc+=4) {
+ zt[0]= rc[ACOMP];
+ zt[1]= rc[BCOMP];
+ zt[2]= rc[GCOMP];
+ }
+ }
+ }
+ ztile++;
+ ctile++;
+ }
+ }
+
+ MEM_freeN(rcline);
+ MEM_freeN(R.rectz); R.rectz= 0;
+
+ R.rectx= temprx; R.recty= tempry;
+ MTC_Mat4SwapMat4(shb->persmat, R.winmat);
+
+ /* printf("lampbuf %d\n", sizeoflampbuf(shb)); */
+}
+
+int RE_BasicShadowBuffer::firstreadshadbuf(struct ShadBuf *shb, int xs, int ys, int nr)
+{
+ /* return 1 als volledig gecomprimeerde shadbuftile && z==const */
+ static int *rz;
+ int ofs;
+ char *ct;
+
+ /* always test borders of shadowbuffer */
+ if(xs<0) xs= 0; else if(xs>=shb->size) xs= shb->size-1;
+ if(ys<0) ys= 0; else if(ys>=shb->size) ys= shb->size-1;
+
+ /* z berekenen */
+ ofs= (ys>>4)*(shb->size>>4) + (xs>>4);
+ ct= shb->cbuf+ofs;
+ if(*ct==0) {
+ if(nr==0) {
+ rz= *( (int **)(shb->zbuf+ofs) );
+ return 1;
+ }
+ else if(rz!= *( (int **)(shb->zbuf+ofs) )) return 0;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+float RE_BasicShadowBuffer::readshadowbuf(struct ShadBuf *shb,
+ int xs, int ys, int zs) /* return 1.0 : volledig licht */
+{
+ float temp;
+ int *rz, ofs;
+ int zsamp;
+ char *ct, *cz;
+
+ /* simpleclip */
+ /* if(xs<0 || ys<0) return 1.0; */
+ /* if(xs>=shb->size || ys>=shb->size) return 1.0; */
+
+ /* always test borders of shadowbuffer */
+ if(xs<0) xs= 0; else if(xs>=shb->size) xs= shb->size-1;
+ if(ys<0) ys= 0; else if(ys>=shb->size) ys= shb->size-1;
+
+ /* z berekenen */
+ ofs= (ys>>4)*(shb->size>>4) + (xs>>4);
+ ct= shb->cbuf+ofs;
+ rz= *( (int **)(shb->zbuf+ofs) );
+
+ if(*ct==3) {
+ ct= ((char *)rz)+3*16*(ys & 15)+3*(xs & 15);
+ cz= (char *)&zsamp;
+ cz[ACOMP]= ct[0];
+ cz[BCOMP]= ct[1];
+ cz[GCOMP]= ct[2];
+ }
+ else if(*ct==2) {
+ ct= ((char *)rz);
+ ct+= 4+2*16*(ys & 15)+2*(xs & 15);
+ zsamp= *rz;
+
+ cz= (char *)&zsamp;
+ cz[BCOMP]= ct[0];
+ cz[GCOMP]= ct[1];
+ }
+ else if(*ct==1) {
+ ct= ((char *)rz);
+ ct+= 4+16*(ys & 15)+(xs & 15);
+ zsamp= *rz;
+
+ cz= (char *)&zsamp;
+ cz[GCOMP]= ct[0];
+
+ }
+ else {
+ /* got warning on this from alpha .... */
+ /* but it's working code! (ton) */
+ zsamp= (int) rz;
+ }
+
+ /* if(zsamp >= 0x7FFFFE00) return 1.0; */ /* geen schaduw als op oneindig wordt gesampeld*/
+
+ if(zsamp > zs) return 1.0; /* absoluut geen schaduw */
+ else if( zsamp < zs-bias) return 0.0 ; /* absoluut wel schaduw */
+ else { /* zacht gebied */
+
+ temp= ( (float)(zs- zsamp) )/(float)bias;
+ return 1.0 - temp*temp;
+
+ }
+}
+
+
+void RE_BasicShadowBuffer::readShadowValue(struct ShadBuf *shb,
+ float inp,
+ float * shadres) /* return 1.0: geen schaduw */
+{
+ float fac, co[4], dx[3], dy[3], aantal=0;
+ float xs1,ys1, siz, *j, xres, yres;
+ int xs,ys, zs;
+ short a,num;
+ float shadowfactor = 1.0;
+
+#ifdef RE_NO_SHADOWS
+ shadres[0] = shadowfactor;
+ shadres[1] = shadowfactor;
+ shadres[2] = shadowfactor;
+ return;
+#endif
+
+ /* if(inp <= 0.0) return 1.0; */
+
+ /* renderco en osaco roteren */
+ siz= 0.5*(float)shb->size;
+ VECCOPY(co, R.co);
+ co[3]= 1.0;
+
+ MTC_Mat4MulVec4fl(shb->persmat, co); /* rationele hom co */
+
+ xs1= siz*(1.0+co[0]/co[3]);
+ ys1= siz*(1.0+co[1]/co[3]);
+
+ /* Clip for z: near and far clip values of the shadow buffer. We
+ * can test for -1.0/1.0 because of the properties of the
+ * coordinate transformations. */
+ fac= (co[2]/co[3]);
+
+ if(fac>=1.0) {
+ shadres[0] = 0.0;
+ shadres[1] = 0.0;
+ shadres[2] = 0.0;
+ return;
+ } else if(fac<= -1.0) {
+ shadres[0] = 1.0;
+ shadres[1] = 1.0;
+ shadres[2] = 1.0;
+ return;
+ }
+
+ zs = (int) (((float)0x7FFFFFFF)*fac);
+
+ /* num*num samples nemen, gebied met fac vergroten */
+ num= shb->samp*shb->samp;
+ fac= shb->soft;
+
+
+ bias = (int) ((1.1-inp*inp)*shb->bias);
+
+ if(num==1) {
+ shadowfactor = readshadowbuf(shb,(int)xs1, (int)ys1, zs);
+ shadres[0] = shadowfactor;
+ shadres[1] = shadowfactor;
+ shadres[2] = shadowfactor;
+ return;
+ }
+
+ co[0]= R.co[0]+O.dxco[0];
+ co[1]= R.co[1]+O.dxco[1];
+ co[2]= R.co[2]+O.dxco[2];
+ co[3]= 1.0;
+ MTC_Mat4MulVec4fl(shb->persmat,co); /* rationele hom co */
+ dx[0]= xs1- siz*(1.0+co[0]/co[3]);
+ dx[1]= ys1- siz*(1.0+co[1]/co[3]);
+
+ co[0]= R.co[0]+O.dyco[0];
+ co[1]= R.co[1]+O.dyco[1];
+ co[2]= R.co[2]+O.dyco[2];
+ co[3]= 1.0;
+ MTC_Mat4MulVec4fl(shb->persmat,co); /* rationele hom co */
+ dy[0]= xs1- siz*(1.0+co[0]/co[3]);
+ dy[1]= ys1- siz*(1.0+co[1]/co[3]);
+
+ xres= fac*( fabs(dx[0])+fabs(dy[0]) );
+ yres= fac*( fabs(dx[1])+fabs(dy[1]) );
+
+ if(xres<fac) xres= fac;
+ if(yres<fac) yres= fac;
+
+ xs1-= (xres)/2;
+ ys1-= (yres)/2;
+
+ j= shb->jit;
+
+ if(xres<16.0 && yres<16.0) {
+ if(firstreadshadbuf(shb, (int)xs1, (int)ys1, 0)) {
+ if(firstreadshadbuf(shb, (int)(xs1+xres), (int)ys1, 1)) {
+ if(firstreadshadbuf(shb, (int)xs1, (int)(ys1+yres), 1)) {
+ if(firstreadshadbuf(shb, (int)(xs1+xres), (int)(ys1+yres), 1)) {
+ /* this return should do some renormalization, methinks */
+ shadowfactor = readshadowbuf(shb,(int)xs1, (int)ys1, zs);
+ shadres[0] = shadowfactor;
+ shadres[1] = shadowfactor;
+ shadres[2] = shadowfactor;
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ for(a=num;a>0;a--) {
+ /* i.p.v. jit ook met random geprobeerd: lelijk! */
+ xs= (int) (xs1 + xres*j[0]);
+ ys= (int) (ys1 + yres*j[1]);
+ j+=2;
+
+ aantal+= readshadowbuf(shb, xs, ys, zs);
+ }
+
+ /* Renormalizes for the sample number: */
+ shadowfactor = aantal/( (float)(num) );
+ shadres[0] = shadowfactor;
+ shadres[1] = shadowfactor;
+ shadres[2] = shadowfactor;
+ return;
+}
+
+/* different function... sampling behind clipend can be LIGHT, bias is negative! */
+/* return: light */
+float RE_BasicShadowBuffer::readshadowbuf_halo(struct ShadBuf *shb, int xs, int ys, int zs)
+{
+ float temp;
+ int *rz, ofs;
+ int zbias, zsamp;
+ char *ct, *cz;
+
+ /* simpleclip */
+ if(xs<0 || ys<0) return 0.0;
+ if(xs>=shb->size || ys>=shb->size) return 0.0;
+
+ /* z berekenen */
+ ofs= (ys>>4)*(shb->size>>4) + (xs>>4);
+ ct= shb->cbuf+ofs;
+ rz= *( (int **)(shb->zbuf+ofs) );
+
+ if(*ct==3) {
+ ct= ((char *)rz)+3*16*(ys & 15)+3*(xs & 15);
+ cz= (char *)&zsamp;
+ zsamp= 0;
+ cz[ACOMP]= ct[0];
+ cz[BCOMP]= ct[1];
+ cz[GCOMP]= ct[2];
+ }
+ else if(*ct==2) {
+ ct= ((char *)rz);
+ ct+= 4+2*16*(ys & 15)+2*(xs & 15);
+ zsamp= *rz;
+
+ cz= (char *)&zsamp;
+ cz[BCOMP]= ct[0];
+ cz[GCOMP]= ct[1];
+ }
+ else if(*ct==1) {
+ ct= ((char *)rz);
+ ct+= 4+16*(ys & 15)+(xs & 15);
+ zsamp= *rz;
+
+ cz= (char *)&zsamp;
+ cz[GCOMP]= ct[0];
+
+ }
+ else {
+ /* same as before */
+ /* still working code! (ton) */
+ zsamp= (int) rz;
+ }
+
+ /* geen schaduw als op oneindig wordt gesampeld*/
+
+ if(zsamp >= 0x7FFFFE00) return 1.0;
+
+ if(zsamp > zs) return 1.0; /* absoluut geen schaduw */
+ else {
+ /* bias is negative, so the (zs-bias) can be beyond 0x7fffffff */
+ zbias= 0x7fffffff - zs;
+ if(zbias > -bias) {
+ if( zsamp < zs-bias) return 0.0 ; /* absoluut wel schaduw */
+ }
+ else return 0.0 ; /* absoluut wel schaduw */
+ }
+
+ /* zacht gebied */
+
+ temp= ( (float)(zs- zsamp) )/(float)bias;
+ return 1.0 - temp*temp;
+}
+
+
+float RE_BasicShadowBuffer::shadow_halo(LampRen *lar, float *p1, float *p2)
+{
+ /* p1 p2 already are rotated in spot-space */
+ ShadBuf *shb= lar->shb;
+ float co[4], siz;
+ float labda, labdao, labdax, labday, ldx, ldy;
+ float zf, xf1, yf1, zf1, xf2, yf2, zf2;
+ float count, lightcount;
+ int x, y, z, xs1, ys1;
+ int dx = 0, dy = 0;
+
+ siz= 0.5*(float)shb->size;
+ /* negative! The other side is more important */
+ bias= -shb->bias;
+
+ co[0]= p1[0];
+ co[1]= p1[1];
+ co[2]= p1[2]/lar->sh_zfac;
+ co[3]= 1.0;
+ MTC_Mat4MulVec4fl(shb->winmat, co); /* rationele hom co */
+ xf1= siz*(1.0+co[0]/co[3]);
+ yf1= siz*(1.0+co[1]/co[3]);
+ zf1= (co[2]/co[3]);
+
+
+ co[0]= p2[0];
+ co[1]= p2[1];
+ co[2]= p2[2]/lar->sh_zfac;
+ co[3]= 1.0;
+ MTC_Mat4MulVec4fl(shb->winmat, co); /* rationele hom co */
+ xf2= siz*(1.0+co[0]/co[3]);
+ yf2= siz*(1.0+co[1]/co[3]);
+ zf2= (co[2]/co[3]);
+
+ /* de 2dda */
+
+ xs1= (int)xf1;
+ ys1= (int)yf1;
+
+ if(xf1 != xf2) {
+ if(xf2-xf1 > 0.0) {
+ labdax= (xf1-xs1-1.0)/(xf1-xf2);
+ ldx= -shb->shadhalostep/(xf1-xf2);
+ dx= shb->shadhalostep;
+ }
+ else {
+ labdax= (xf1-xs1)/(xf1-xf2);
+ ldx= shb->shadhalostep/(xf1-xf2);
+ dx= -shb->shadhalostep;
+ }
+ }
+ else {
+ labdax= 1.0;
+ ldx= 0.0;
+ }
+
+ if(yf1 != yf2) {
+ if(yf2-yf1 > 0.0) {
+ labday= (yf1-ys1-1.0)/(yf1-yf2);
+ ldy= -shb->shadhalostep/(yf1-yf2);
+ dy= shb->shadhalostep;
+ }
+ else {
+ labday= (yf1-ys1)/(yf1-yf2);
+ ldy= shb->shadhalostep/(yf1-yf2);
+ dy= -shb->shadhalostep;
+ }
+ }
+ else {
+ labday= 1.0;
+ ldy= 0.0;
+ }
+
+ x= xs1;
+ y= ys1;
+ labda= count= lightcount= 0.0;
+
+/* printf("start %x %x \n", (int)(0x7FFFFFFF*zf1), (int)(0x7FFFFFFF*zf2)); */
+
+ while(1) {
+ labdao= labda;
+
+ if(labdax==labday) {
+ labdax+= ldx;
+ x+= dx;
+ labday+= ldy;
+ y+= dy;
+ }
+ else {
+ if(labdax<labday) {
+ labdax+= ldx;
+ x+= dx;
+ } else {
+ labday+= ldy;
+ y+= dy;
+ }
+ }
+
+ labda= MIN2(labdax, labday);
+ if(labda==labdao || labda>=1.0) break;
+
+ zf= zf1 + labda*(zf2-zf1);
+ count+= 1.0;
+
+ if(zf<= 0.0) lightcount += 1.0; /* close to the spot */
+ else {
+
+ /* make sure, behind the clipend we extend halolines. */
+ if(zf>=1.0) z= 0x7FFFF000;
+ else z= (int)(0x7FFFF000*zf);
+
+ lightcount+= readshadowbuf_halo(shb, x, y, z);
+
+ }
+ }
+
+ if(count!=0.0) return (lightcount/count);
+ return 0.0;
+
+}
+
+
+
+
+/* sampelen met filter
+ xstart= xs-1;
+ ystart= ys-1;
+ if(xstart<0) xstart= 0;
+ if(ystart<0) ystart= 0;
+ xend= xstart+2;
+ yend= ystart+2;
+ if(xend>=shb->size) { xstart= shb->size-3; xend= shb->size-1;}
+ if(yend>=shb->size) { ystart= shb->size-3; yend= shb->size-1;}
+
+ fid= filt3;
+ for(ys=ystart;ys<=yend;ys++) {
+ rz= shb->buf+ ys*shb->size+ xstart;
+ for(xs= xstart;xs<=xend;xs++,rz++) {
+ if( *rz+0x100000<zs) aantal+= *fid;
+ fid++;
+ }
+ }
+
+
+ return 1.0-((float)aantal)/16.0;
+*/
diff --git a/source/blender/render/intern/source/RE_callbacks.c b/source/blender/render/intern/source/RE_callbacks.c
new file mode 100644
index 00000000000..6228edf1731
--- /dev/null
+++ b/source/blender/render/intern/source/RE_callbacks.c
@@ -0,0 +1,159 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Callbacks to make the renderer interact with calling modules.
+ */
+
+#include <stdlib.h> /* for NULL??? */
+#include "render.h"
+#include "render_intern.h"
+#include "RE_callbacks.h"
+
+/*
+ * The callbacks are done in three parts:
+ *
+ * - a local static pointer to the eventual function. NULL if not
+ * defined, or if the behaviour is not required.
+ *
+ * - a hook that can be called locally
+ *
+ * - a hook that can be called externally, to set an external function
+ * to provide said functionality.
+ *
+ * These might be generated from a spec such as:
+ *
+ * callback {
+ * local = <local name>
+ * external = <external name>
+ * type = <ret_type> (<args>,...)
+ * }
+ *
+ * Should generate:
+ * - a static var
+ * - an internal loop, plus decl.
+ * - an external setter, plus decl.
+ *
+ */
+
+/* Part 1: ------------------------------------------------------------- */
+
+static int (*RE_local_test_break_function)(void) = NULL;
+
+static void (*RE_local_timecursor_function)(int) = NULL;
+
+static void (*RE_local_renderdisplay_function)(int i,
+ int j,
+ int k,
+ int l,
+ unsigned int *m)
+ = NULL;
+
+static void (*RE_local_initrenderdisplay_function)(void) = NULL;
+static void (*RE_local_clearrenderdisplay_function)(short) = NULL;
+
+static void (*RE_local_printrenderinfo_function)(double,int) = NULL;
+
+static void (*RE_local_getrenderdata_function)(void) = NULL;
+static void (*RE_local_freerenderdata_function)(void) = NULL;
+
+/* Part 2: ------------------------------------------------------------- */
+
+int RE_local_test_break(void) {
+ if (RE_local_test_break_function) {
+ return RE_local_test_break_function();
+ } else {
+ /* transparant behaviour: proceed */
+ return 0;
+ }
+}
+
+void RE_local_timecursor(int i) {
+ if (RE_local_timecursor_function) RE_local_timecursor_function(i);
+}
+
+void RE_local_render_display(int i, int j, int k, int l, unsigned int* m) {
+ if (RE_local_renderdisplay_function) RE_local_renderdisplay_function(i, j, k, l, m);
+}
+void RE_local_init_render_display(void) {
+ if (RE_local_initrenderdisplay_function) RE_local_initrenderdisplay_function();
+}
+void RE_local_clear_render_display(short i) {
+ if (RE_local_clearrenderdisplay_function) RE_local_clearrenderdisplay_function(i);
+}
+
+void RE_local_printrenderinfo(double time, int i) {
+ if (RE_local_printrenderinfo_function) RE_local_printrenderinfo_function(time, i);
+}
+
+void RE_local_get_renderdata(void) {
+ if (RE_local_getrenderdata_function) RE_local_getrenderdata_function();
+}
+void RE_local_free_renderdata(void) {
+ if (RE_local_freerenderdata_function) RE_local_freerenderdata_function();
+}
+
+/* Part 3: ------------------------------------------------------------- */
+
+void RE_set_test_break_callback(int (*f)(void)) {
+ RE_local_test_break_function = f;
+}
+
+void RE_set_timecursor_callback(void (*f)(int)) {
+ RE_local_timecursor_function = f;
+}
+
+void RE_set_renderdisplay_callback(void (*f)(int i,
+ int j,
+ int k,
+ int l,
+ unsigned int *))
+{
+ RE_local_renderdisplay_function = f;
+}
+
+void RE_set_initrenderdisplay_callback(void (*f)(void)) {
+ RE_local_initrenderdisplay_function = f;
+}
+
+void RE_set_clearrenderdisplay_callback(void (*f)(short)) {
+ RE_local_clearrenderdisplay_function = f;
+}
+
+void RE_set_printrenderinfo_callback(void (*f)(double,int)) {
+ RE_local_printrenderinfo_function = f;
+}
+
+void RE_set_getrenderdata_callback(void (*f)(void)) {
+ RE_local_getrenderdata_function = f;
+}
+
+void RE_set_freerenderdata_callback(void (*f)(void)) {
+ RE_local_freerenderdata_function = f;
+}
diff --git a/source/blender/render/intern/source/edgeRender.c b/source/blender/render/intern/source/edgeRender.c
new file mode 100644
index 00000000000..d3c944efac7
--- /dev/null
+++ b/source/blender/render/intern/source/edgeRender.c
@@ -0,0 +1,952 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Add enhanced edges on a rendered image (toon shading, edge shading).
+ */
+
+/*
+ * Edge rendering: use a mask to weigh the depth of neighbouring
+ * pixels, and do a colour correction.
+ *
+ * We need:
+ * - a buffer to store the depths (ints)
+ * - a function that alters the colours in R.rectot (copy edge_enhance?)
+ * The max. z buffer depth is 0x7FFF.FFFF (7 F's)
+ *
+ * - We 'ignore' the pixels falling outside the regular buffer (we fill)
+ * these with the max depth. This causes artefacts when rendering in
+ * parts.
+ */
+
+/* ------------------------------------------------------------------------- */
+
+/* enable extra bounds checking and tracing */
+/* #define RE_EDGERENDERSAFE */
+/* disable the actual edge correction */
+/* #define RE_EDGERENDER_NO_CORRECTION */
+
+#include <stdlib.h>
+#include <math.h>
+#include <limits.h> /* INT_MIN,MAX are used here */
+#include <stdio.h>
+
+#include "MEM_guardedalloc.h"
+#include "MTC_vectorops.h"
+
+#include "RE_callbacks.h"
+#include "edgeRender.h"
+#include "render.h"
+#include "render_intern.h"
+#include "zbuf.h" /* for zbufclipwire and zbufclip */
+#include "jitter.h"
+
+#ifdef RE_EDGERENDERSAFE
+char edgeRender_h[] = EDGERENDER_H;
+char edgeRender_c[] = "$Id$";
+#include "errorHandler.h"
+#endif
+
+/* ------------------------------------------------------------------------- */
+/* the lazy way: */
+#define MIN2(x,y) ( (x)<(y) ? (x) : (y) )
+
+/* ------------------------------------------------------------------------- */
+
+ /* These function pointers are used for z buffer filling. */
+extern void (*zbuffunc)(float *, float *, float *);
+extern void (*zbuflinefunc)(float *v1, float *v2);
+extern float Zmulx, Zmuly; /* Some kind of scale? */
+extern float Zjitx,Zjity; /* The x,y values for jitter offset */
+extern unsigned int Zvlnr; /* Face rendering pointer and counter: these */
+extern VlakRen *Zvlr; /* are used for 'caching' render results. */
+
+/* ------------------------------------------------------------------------- */
+
+/* exp: */
+static Material** matBuffer; /* buffer with material indices */
+static Material* mat_cache; /* material of the face being buffered */
+
+static char* colBuffer; /* buffer with colour correction */
+static int *edgeBuffer; /* buffer with distances */
+static int bufWidth; /* x-dimension of the buffer */
+static int bufHeight; /* y-dimension of the buffer */
+static int imWidth; /* x-dimension of the image */
+static int imHeight; /* y-dimension of the image */
+static int osaCount; /* oversample count */
+static int maskBorder; /* size of the mask border */
+static short int intensity; /* edge intensity */
+static short int same_mat_redux; /* intensity reduction for boundaries with the same material */
+static int compatible_mode; /* edge positioning compatible with old rederer */
+static int selectmode; /* 0: only solid faces, 1: also transparent f's */
+
+static int Aminy; /* y value of first line in the accu buffer */
+static int Amaxy; /* y value of last line in the accu buffer */
+ /* -also used to clip when zbuffering */
+static char edgeR; /* Colour for the edges. The edges will receive */
+static char edgeG; /* this tint. The colour is fully used! */
+static char edgeB;
+/* static float edgeBlend; */ /* Indicate opaqueness of the edge colour. */
+
+/* Local functions --------------------------------------------------------- */
+/**
+ * Initialise the edge render buffer memory.
+ */
+void initEdgeRenderBuffer(void);
+/**
+ * Release buffer memory.
+ */
+void freeEdgeRenderBuffer(void);
+
+/**
+ * Set all distances in the distance buffer to the maximum distance.
+ */
+void resetDistanceBuffer(void);
+
+/**
+ * Insert this distance at these pixel coordinates.
+ */
+void insertInEdgeBuffer(int x, int y, int dist);
+
+/**
+ * Renders enhanced edges. Distances from distRect are used to
+ * determine a correction on colourRect
+ */
+void renderEdges(char * colourRect);
+
+/**
+ * Buffer an edge between these two vertices in the e.r. distance buffer.
+ */
+void fillEdgeRenderEdge(float *vec1, float *vec2);
+
+/**
+ * Buffer a face between these two vertices in the e.r. distance buffer.
+ */
+void fillEdgeRenderFace(float *v1, float *v2, float *v3);
+
+/**
+ * Compose the edge render colour buffer.
+ */
+void calcEdgeRenderColBuf(char * tarbuf);
+
+/**
+ * Loop over all objects that need to be edge rendered. This loop determines
+ * which objects get to be elected for edge rendering.
+ */
+int zBufferEdgeRenderObjects(void);
+
+/**
+ * Add edge pixels to the original image. It blends <bron> over <doel>.
+ */
+void addEdgeOver(char *doel, char *bron);
+
+/* ------------------------------------------------------------------------- */
+
+void addEdges(
+ char * targetbuf,
+ int iw, int ih,
+ int osanr,
+ short int intens, short int intens_redux,
+ int compat, int mode,
+ float r, float g, float b
+ )
+{
+ float rf, gf ,bf;
+ /* render parameters */
+ selectmode = mode;
+ imWidth = iw;
+ imHeight = ih;
+ compatible_mode = compat;
+ osaCount = osanr;
+ intensity = intens;
+ /* Reduction doesn't exceed intensity. */
+ same_mat_redux = ((intens_redux < intensity)? intens_redux : intensity);
+
+ rf = r * 255.0;
+ if (rf > 255) edgeR = 255; else edgeR = rf;
+ gf = g * 255.0;
+ if (gf > 255) edgeG = 255; else edgeG = gf;
+ bf = b * 255.0;
+ if (bf > 255) edgeB = 255; else edgeB = bf;
+
+ /* Go! */
+ initEdgeRenderBuffer();
+ calcEdgeRenderColBuf(targetbuf);
+ freeEdgeRenderBuffer();
+
+} /* end of void addEdges(char *, int, int, int, short int , int) */
+
+/* ------------------------------------------------------------------------- */
+
+void initEdgeRenderBuffer()
+{
+ char *ptr;
+ int i;
+
+ maskBorder = 1; /* for 3 by 3 mask*/
+
+ bufWidth = imWidth + (2 * maskBorder);
+ bufHeight = imHeight + (2 * maskBorder);
+
+ /* Experimental: store the material indices. */
+ if (same_mat_redux) {
+ matBuffer = MEM_callocN(sizeof(Material*)
+ * bufWidth * bufHeight, "matBuffer");
+ }
+
+ edgeBuffer = MEM_callocN(sizeof(int) * bufWidth * bufHeight, "edgeBuffer");
+ colBuffer = MEM_callocN(sizeof(char) * 4 * imWidth * imHeight, "colBuffer");
+
+
+ if ((edgeR != 0) || (edgeG != 0) || (edgeB != 0)) {
+ /* Set all colbuf pixels to the edge colour. Leave alpha channel */
+ /* cleared. Actually, we could blend in any image here... */
+ ptr = colBuffer;
+ for (i = 0; i < imWidth * imHeight; i++, ptr+=4)
+ {
+ ptr[0] = edgeR;
+ ptr[1] = edgeG;
+ ptr[2] = edgeB;
+ ptr[3] = 0;
+ }
+ }
+
+#ifdef RE_EDGERENDERSAFE
+ if (!edgeBuffer || !colBuffer) {
+ char *fname = "initEdgeRenderBuffer";
+ RE_error(RE_CANNOT_ALLOCATE_MEMORY, fname);
+ }
+#endif
+} /* end of void initEdgeRenderBuffer(void) */
+
+/* ------------------------------------------------------------------------- */
+void freeEdgeRenderBuffer(void)
+{
+ if(edgeBuffer) MEM_freeN(edgeBuffer);
+ if(colBuffer) MEM_freeN(colBuffer);
+ if(matBuffer) MEM_freeN(matBuffer);
+} /* end of void freeEdgeRenderBuffer(void) */
+
+/* ------------------------------------------------------------------------- */
+
+void resetDistanceBuffer(void)
+{
+ int i;
+ for(i = 0; i < bufWidth * bufHeight; i++) edgeBuffer[i] = 0x7FFFFFFF;
+} /* end of void resetDistanceBuffer(void) */
+
+/* ------------------------------------------------------------------------- */
+
+void insertInEdgeBuffer(int x, int y, int dist)
+{
+ int index;
+#ifdef RE_EDGERENDERSAFE
+ char *fname = "insertInEdgeBuffer";
+ if ((x < 0) || (x > imWidth ) ||
+ (y < 0) || (y > (imHeight-1) ) ) {
+ RE_error(RE_EDGERENDER_WRITE_OUTSIDE_BUFFER, fname);
+ return;
+ }
+#endif
+
+ /* +1? */
+ index = (y * bufWidth) + x + maskBorder;
+
+ /*exp: just dump a single index here. Maybe we can do more
+ * sophisticated things later on. */
+ if (same_mat_redux) {
+ matBuffer[index] = mat_cache;
+ }
+
+ if (edgeBuffer[index] >dist ) edgeBuffer[index] = dist;
+
+} /* end of void insertInEdgeBuffer(int x, int y, int dist) */
+
+/* ------------------------------------------------------------------------- */
+/* Modelled after rendercore.c/edge_enhance() */
+void renderEdges(char *colourRect)
+{
+ /* use zbuffer to define edges, add it to the image */
+ int val, y, x, col, *rz, *rz1, *rz2, *rz3;
+ char *cp;
+ int targetoffset, heightoffset;
+ int i;
+ int matdif; /* For now: just a bogus int, 0 when all materials
+ * under the mask are the same, non-0 otherwise*/
+ int *matptr_low = 0, *matptr_cent = 0, *matptr_high = 0;
+ int matdiffac = 0;
+
+#ifdef RE_EDGERENDER_NO_CORRECTION
+ return; /* no edge correction */
+#endif
+
+#ifdef RE_EDGERENDERSAFE
+ fprintf(stderr, "\n*** Activated full error trace on "
+ "edge rendering using:\n\t%s\n\t%s"
+ "\n*** Rendering edges at %d intensity",
+ edgeRender_c, edgeRender_h, intensity);
+#endif
+
+
+ /* Old renderer uses wrong positions! With the compat switch on, the po- */
+ /* sitions will be corrected to be offset in the same way. */
+ if (compatible_mode) {
+ targetoffset = 4 * (imWidth - 1);
+ heightoffset = -1;
+ } else {
+ targetoffset = 0;
+ heightoffset = 0;
+ }
+
+ /* Fill edges with some default values. We just copy what is in the edge */
+ /* This looks messy, but it appears to be ok. */
+ edgeBuffer[0] = edgeBuffer[bufWidth + 1];
+ edgeBuffer[bufWidth - 1] = edgeBuffer[(2 * bufWidth) - 2];
+ edgeBuffer[bufWidth * (bufHeight - 1)] =
+ edgeBuffer[bufWidth * (bufHeight - 2) + 1];
+ edgeBuffer[(bufWidth * bufHeight) - 1] =
+ edgeBuffer[(bufWidth * (bufHeight - 1)) - 2];
+ for (i = 1; i < bufWidth - 1; i++) { /* lieing edges */
+ edgeBuffer[i] = edgeBuffer[bufWidth + i]; /* bottom*/
+ edgeBuffer[((bufHeight - 1)*bufWidth) + i]
+ = edgeBuffer[((bufHeight - 2)*bufWidth) + i]; /* top */
+ }
+ for (i = 1; i < bufHeight - 2; i++) { /* standing edges */
+ edgeBuffer[i * bufWidth] = edgeBuffer[(i * bufWidth) + 1]; /* left */
+ edgeBuffer[((i + 1) * bufWidth) - 1] =
+ edgeBuffer[((i + 1) * bufWidth) - 2]; /* right */
+ }
+
+ /* same hack for the materials: */
+ if (same_mat_redux) {
+ matBuffer[0] = matBuffer[bufWidth + 1];
+ matBuffer[bufWidth - 1] = matBuffer[(2 * bufWidth) - 2];
+ matBuffer[bufWidth * (bufHeight - 1)] =
+ matBuffer[bufWidth * (bufHeight - 2) + 1];
+ matBuffer[(bufWidth * bufHeight) - 1] =
+ matBuffer[(bufWidth * (bufHeight - 1)) - 2];
+ for (i = 1; i < bufWidth - 1; i++) { /* lieing mats */
+ matBuffer[i] = matBuffer[bufWidth + i]; /* bottom*/
+ matBuffer[((bufHeight - 1)*bufWidth) + i]
+ = matBuffer[((bufHeight - 2)*bufWidth) + i]; /* top */
+ }
+ for (i = 1; i < bufHeight - 2; i++) { /* standing mats */
+ matBuffer[i * bufWidth] = matBuffer[(i * bufWidth) + 1]; /* left */
+ matBuffer[((i + 1) * bufWidth) - 1] =
+ matBuffer[((i + 1) * bufWidth) - 2]; /* right */
+ }
+ }
+
+ /* alle getallen in zbuffer 3 naar rechts shiften */
+ rz = edgeBuffer;
+ if(rz==0) return;
+
+ for(y=0; y < bufHeight * bufWidth; y++, rz++) {
+ (*rz)>>= 3;
+ }
+
+ /* Distance pointers */
+ rz1= edgeBuffer;
+ rz2= rz1 + bufWidth;
+ rz3= rz2 + bufWidth;
+
+ if (same_mat_redux) {
+ matptr_low = matBuffer;
+ matptr_cent = matptr_low + bufWidth;
+ matptr_high = matptr_cent + bufWidth;
+ }
+
+ if (osaCount == 1) {
+ cp = colourRect + targetoffset;
+ } else {
+ cp = colBuffer + targetoffset;
+ }
+
+ i = 0;
+
+ for(y = 0; y < (imHeight + heightoffset) ; y++) {
+
+
+ /* All these indices are a bit silly. I need to
+ * rewrite this, so all buffers use the same
+ * indexing. */
+ for(x = 0;
+ x < imWidth;
+ x++, rz1++, rz2++, rz3++, cp+=4,
+ matptr_low++,
+ matptr_cent++,
+ matptr_high++) {
+
+ col= abs( - rz1[0] - 2*rz1[1] - rz1[2]
+ - 2*rz2[0] + 12*rz2[1] - 2*rz2[2]
+ - rz3[0] - 2*rz3[1] - rz3[2]) / 3;
+
+ /* Several options for matdif:
+ *
+ * - suppress all boundaries with 0 dif
+ *
+ * - weaken col dif? Or decrease intensity by
+ * a factor when non 0 dif??
+ */
+
+ /* exp: matdif is non-0 if the mask-center
+ * material differs from any of the
+ * corners. */
+
+ if (same_mat_redux) {
+ matdif = abs (matptr_cent[1] - matptr_low[0])
+ + abs (matptr_cent[1] - matptr_low[1])
+ + abs (matptr_cent[1] - matptr_low[2])
+ + abs (matptr_cent[1] - matptr_cent[0])
+ + abs (matptr_cent[1] - matptr_low[2])
+ + abs (matptr_cent[1] - matptr_high[0])
+ + abs (matptr_cent[1] - matptr_high[1])
+ + abs (matptr_cent[1] - matptr_high[2]);
+
+ matdiffac = (matdif ? 0 : same_mat_redux);
+ }
+
+ col= ((intensity - matdiffac) * col)>>14;
+ if(col>255) col= 255;
+
+ /* Colour edge if
+ *
+ * 1. there is an appreciable, non-uniform
+ * gradient,
+ *
+ * 2. there are different materials bordering
+ * on the center pixel
+ */
+ if( (col>0)
+ /* && (matdif != 0) */) {
+
+ if(osaCount > 1) {
+ /* Currently done by tweaking alpha. The colBuffer is */
+ /* filled with pixels of the colour appropriate for the */
+ /* edges. This colour is alpha-blended over the image. */
+ /* This calculation determines how much colour each pixel */
+ /* gets. */
+ col/= osaCount;
+ val= cp[3]+col;
+ if(val>255) cp[3]= 255; else cp[3]= val;
+ }
+ else {
+ /* the pixel is blackened when col is too big */
+ val = cp[0] - col;
+ if(val<=0) {
+ cp[0]= edgeR;
+ } else {
+ cp[0]= val;
+ }
+ val = cp[1] - col;
+ if(val<=0) {
+ cp[1]= edgeG;
+ }else {
+ cp[1]= val;
+ }
+ val = cp[2] - col;
+ if(val<=0) {
+ cp[2]= edgeB;
+ } else {
+ cp[2]= val;
+ }
+ }
+ }
+ }
+ rz1+= 2;
+ rz2+= 2;
+ rz3+= 2;
+ if (same_mat_redux) {
+ matptr_low += 2;
+ matptr_cent += 2;
+ matptr_high += 2;
+ }
+
+ }
+
+} /* end of void renderEdges() */
+
+/* ------------------------------------------------------------------------- */
+
+void addEdgeOver(char *doel, char *bron) /* telt bron bij doel */
+{
+ float c;
+ int mul;
+
+ if( bron[3] == 0) return;
+ if( bron[3] == 255) { /* is getest, scheelt */
+ *((unsigned int *)doel)= *((unsigned int *)bron);
+ return;
+ }
+
+ /* This must be a special blend-mode, because we get a 'weird' data */
+ /* input format now. With edge = (c_e, a_e), picture = (c_p, a_p), we */
+ /* get: result = ( c_e*a_e + c_p(1 - a_e), a_p ). */
+
+ mul = 255 - bron[3];
+
+ /* Not sure if the conversion to float is really necessary here... I will*/
+ /* think about it another day. */
+ c = ((mul * doel[0] + bron[0] * bron[3])/255.0);
+ if(c>255) {doel[0]=255;} else { doel[0]= c;}
+ c = ((mul * doel[1] + bron[1] * bron[3])/255.0);
+ if(c>255) {doel[1]=255;} else { doel[1]= c;}
+ c = ((mul * doel[2] + bron[2] * bron[3])/255.0);
+ if(c>255) {doel[2]=255;} else { doel[2]= c;}
+}
+
+void calcEdgeRenderColBuf(char* colTargetBuffer)
+{
+
+/* int part; */
+ int keepLooping = 1;
+ int sample;
+
+ /* zbuffer fix: here? */
+ Zmulx= ((float) imWidth)/2.0;
+ Zmuly= ((float) imHeight)/2.0;
+
+ /* use these buffer fill functions */
+ zbuffunc = fillEdgeRenderFace;
+ zbuflinefunc = fillEdgeRenderEdge;
+
+ /* always buffer the max. extent */
+ Aminy = 0;
+ Amaxy = imHeight;
+
+ sample = 0; /* Zsample is used internally ! */
+ while ( (sample < osaCount) && keepLooping ) {
+ /* jitter */
+ Zjitx= -jit[sample][0];
+ Zjity= -jit[sample][1];
+
+ /* should reset dis buffer here */
+ resetDistanceBuffer();
+
+ /* kick all into a z buffer */
+ keepLooping = zBufferEdgeRenderObjects();
+
+ /* do filtering */
+ renderEdges(colTargetBuffer);
+
+ if(RE_local_test_break()) keepLooping = 0;
+ sample++;
+ }
+
+ /* correction for osa-sampling...*/
+ if( osaCount != 1) {
+ char *rp, *rt;
+ int a;
+
+ rt= colTargetBuffer;
+ rp= colBuffer;
+ for(a = imWidth * imHeight; a>0; a--, rt+=4, rp+=4) {
+ /* there seem to be rounding errors here... */
+ addEdgeOver(rt, rp);
+ }
+ }
+
+} /*End of void calcEdgeRenderZBuf(void) */
+
+/* ------------------------------------------------------------------------- */
+/* Clip flags etc. should still be set. When called in the span of 'normal' */
+/* rendering, this should be ok. */
+int zBufferEdgeRenderObjects(void)
+{
+ int keepLooping;
+ int faceCounter; /* counter for face number */
+ Material *ma;
+
+ keepLooping = 1;
+ ma = NULL;
+ faceCounter = 0;
+
+ while ( (faceCounter < R.totvlak) && keepLooping) {
+ if((faceCounter & 255)==0) { Zvlr= R.blovl[faceCounter>>8]; }
+ else Zvlr++;
+
+ ma= Zvlr->mat;
+
+ /*exp*/
+ mat_cache = ma;
+
+ /* face number is used in the fill functions */
+ Zvlnr = faceCounter + 1;
+
+ if(Zvlr->flag & R_VISIBLE) {
+
+ /* here we cull all transparent faces if mode == 0 */
+ if (selectmode || !(ma->mode & MA_ZTRA)) {
+ /* here we can add all kinds of extra selection criteria */
+ if(ma->mode & (MA_WIRE)) zbufclipwire(Zvlr);
+ else {
+ zbufclip(Zvlr->v1->ho, Zvlr->v2->ho, Zvlr->v3->ho,
+ Zvlr->v1->clip, Zvlr->v2->clip, Zvlr->v3->clip);
+ if(Zvlr->v4) {
+ Zvlnr+= 0x800000; /* in a sense, the 'adjoint' face */
+ zbufclip(Zvlr->v1->ho, Zvlr->v3->ho, Zvlr->v4->ho,
+ Zvlr->v1->clip, Zvlr->v3->clip, Zvlr->v4->clip);
+ }
+ }
+ }
+ };
+ if(RE_local_test_break()) keepLooping = 0;
+ faceCounter++;
+ }
+ return keepLooping;
+} /* End of int zBufferEdgeRenderObjects(void) */
+
+/* ------------------------------------------------------------------------- */
+
+void fillEdgeRenderFace(float *v1, float *v2, float *v3)
+{
+ /* Coordinates of the vertices are specified in ZCS */
+ double z0; /* used as temp var*/
+ double xx1;
+ double zxd,zyd,zy0, tmp;
+ float *minv,*maxv,*midv;
+ int zverg,x;
+ int my0,my2,sn1,sn2,rectx,zd;
+ int y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2/* , mask */;
+ int linex, liney, xoffset, yoffset; /* pointers to the pixel number */
+
+ /* These used to be doubles. We may want to change them back if the */
+ /* loss of accuracy proves to be a problem? There does not seem to be */
+ /* any performance issues here, so I'll just keep the doubles. */
+ /* float vec0[3], vec1[3], vec2[3]; */
+ double vec0[3], vec1[3], vec2[3];
+
+ /* MIN MAX */
+ /* sort vertices for min mid max y value */
+ if(v1[1]<v2[1]) {
+ if(v2[1]<v3[1]) { minv=v1; midv=v2; maxv=v3;}
+ else if(v1[1]<v3[1]) { minv=v1; midv=v3; maxv=v2;}
+ else { minv=v3; midv=v1; maxv=v2;}
+ }
+ else {
+ if(v1[1]<v3[1]) { minv=v2; midv=v1; maxv=v3;}
+ else if(v2[1]<v3[1]) { minv=v2; midv=v3; maxv=v1;}
+ else { minv=v3; midv=v2; maxv=v1;}
+ }
+
+ if(minv[1] == maxv[1]) return; /* beveiliging 'nul' grote vlakken */
+
+ my0 = ceil(minv[1]);
+ my2 = floor(maxv[1]);
+ omsl = floor(midv[1]);
+
+ /* outside the current z buffer slice: clip whole face */
+ if( (my2 < Aminy) || (my0 > Amaxy)) return;
+
+ if(my0<Aminy) my0= Aminy;
+
+ /* EDGES : DE LANGSTE */
+ xx1= maxv[1]-minv[1];
+ if(xx1>2.0/65536.0) {
+ z0= (maxv[0]-minv[0])/xx1;
+
+ tmp= (-65536.0*z0);
+ dx0= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(my2-minv[1])+minv[0]);
+ xs0= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx0= 0;
+ xs0= 65536.0*(MIN2(minv[0],maxv[0]));
+ }
+ /* EDGES : DE BOVENSTE */
+ xx1= maxv[1]-midv[1];
+ if(xx1>2.0/65536.0) {
+ z0= (maxv[0]-midv[0])/xx1;
+
+ tmp= (-65536.0*z0);
+ dx1= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(my2-midv[1])+midv[0]);
+ xs1= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx1= 0;
+ xs1= 65536.0*(MIN2(midv[0],maxv[0]));
+ }
+ /* EDGES : DE ONDERSTE */
+ xx1= midv[1]-minv[1];
+ if(xx1>2.0/65536.0) {
+ z0= (midv[0]-minv[0])/xx1;
+
+ tmp= (-65536.0*z0);
+ dx2= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(omsl-minv[1])+minv[0]);
+ xs2= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx2= 0;
+ xs2= 65536.0*(MIN2(minv[0],midv[0]));
+ }
+
+ /* ZBUF DX DY */
+ MTC_diff3DFF(vec1, v1, v2);
+ MTC_diff3DFF(vec2, v2, v3);
+ MTC_cross3Double(vec0, vec1, vec2);
+
+ /* cross product of two of the sides is 0 => this face is too small */
+ if(vec0[2]==0.0) return;
+
+ if(midv[1] == maxv[1]) omsl= my2;
+ if(omsl < Aminy) omsl= Aminy-1; /* dan neemt ie de eerste lus helemaal */
+
+ while (my2 > Amaxy) { /* my2 kan groter zijn */
+ xs0+=dx0;
+ if (my2<=omsl) {
+ xs2+= dx2;
+ }
+ else{
+ xs1+= dx1;
+ }
+ my2--;
+ }
+
+ xx1= (vec0[0]*v1[0]+vec0[1]*v1[1])/vec0[2]+v1[2];
+
+ zxd= -vec0[0]/vec0[2];
+ zyd= -vec0[1]/vec0[2];
+ zy0= my2*zyd+xx1;
+ zd= (int)CLAMPIS(zxd, INT_MIN, INT_MAX);
+
+ /* start-ofset in rect */
+ /* rectx= R.rectx; */
+ /* I suspect this var needs very careful setting... When edge rendering */
+ /* is on, this is strange */
+ rectx = imWidth;
+ yoffset = my2;
+ xoffset = 0;
+
+ xs3= 0; /* flag */
+ if(dx0>dx1) {
+ MTC_swapInt(&xs0, &xs1);
+ MTC_swapInt(&dx0, &dx1);
+ xs3= 1; /* flag */
+
+ }
+
+ liney = yoffset;
+ for(y=my2;y>omsl;y--) {
+
+ sn1= xs0>>16;
+ xs0+= dx0;
+
+ sn2= xs1>>16;
+ xs1+= dx1;
+
+ sn1++;
+
+ if(sn2>=rectx) sn2= rectx-1;
+ if(sn1<0) sn1= 0;
+ zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
+
+ if ((sn1 < 0) || (sn1>imWidth) ) printf("\n sn1 exceeds line");
+ linex = xoffset + sn1;
+ liney = yoffset;
+
+ x= sn2-sn1;
+
+ while(x>=0) {
+ insertInEdgeBuffer(linex , liney, zverg); /* line y not needed here */
+ zverg+= zd;
+ linex++;
+ x--;
+ }
+ zy0-= zyd;
+ yoffset--;
+ }
+
+ if(xs3) {
+ xs0= xs1;
+ dx0= dx1;
+ }
+ if(xs0>xs2) {
+ xs3= xs0;
+ xs0= xs2;
+ xs2= xs3;
+ xs3= dx0;
+ dx0= dx2;
+ dx2= xs3;
+ }
+
+ for(; y>=my0; y--) {
+
+ sn1= xs0>>16;
+ xs0+= dx0;
+
+ sn2= xs2>>16;
+ xs2+= dx2;
+
+ sn1++;
+
+ if(sn2>=rectx) sn2= rectx-1;
+ if(sn1<0) sn1= 0;
+ zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
+
+ linex = sn1;
+ liney = yoffset;
+
+ x= sn2-sn1;
+
+ while(x>=0) {
+ insertInEdgeBuffer(linex, liney, zverg); /* line y not needed here */
+ zverg+= zd;
+ linex++;
+ x--;
+ }
+ zy0-=zyd;
+ yoffset--;
+ }
+} /* end of void fillEdgeRenderFace(float *v1, float *v2, float *v3) */
+
+/* ------------------------------------------------------------------------- */
+
+void fillEdgeRenderEdge(float *vec1, float *vec2)
+{
+ int start, end, x, y, oldx, oldy, ofs;
+ int dz, vergz/* , mask */;
+ float dx, dy;
+ float v1[3], v2[3];
+ int linex, liney;
+ int xoffset, yoffset;
+
+
+ dx= vec2[0]-vec1[0];
+ dy= vec2[1]-vec1[1];
+
+ if(fabs(dx) > fabs(dy)) {
+
+ /* alle lijnen van links naar rechts */
+ if(vec1[0]<vec2[0]) {
+ VECCOPY(v1, vec1);
+ VECCOPY(v2, vec2);
+ }
+ else {
+ VECCOPY(v2, vec1);
+ VECCOPY(v1, vec2);
+ dx= -dx; dy= -dy;
+ }
+
+ start= floor(v1[0]);
+ end= start+floor(dx);
+ if(end >= imWidth) end = imWidth - 1;
+
+ oldy= floor(v1[1]);
+ dy/= dx;
+
+ vergz= v1[2];
+ dz= (v2[2]-v1[2])/dx;
+
+ yoffset = oldy;
+ xoffset = start;
+
+ if(dy<0) ofs= -imWidth;
+ else ofs= imWidth;
+
+ liney = yoffset;
+ linex = xoffset;
+
+ for(x= start; x<=end; x++, xoffset++) {
+
+ y= floor(v1[1]);
+ if(y!=oldy) {
+ oldy= y;
+ liney++;
+ }
+
+ if(x>=0 && y>=Aminy && y<=Amaxy) {
+ insertInEdgeBuffer(linex , liney, vergz);
+ }
+
+ v1[1]+= dy;
+ vergz+= dz;
+ }
+ }
+ else {
+
+ /* alle lijnen van onder naar boven */
+ if(vec1[1]<vec2[1]) {
+ VECCOPY(v1, vec1);
+ VECCOPY(v2, vec2);
+ }
+ else {
+ VECCOPY(v2, vec1);
+ VECCOPY(v1, vec2);
+ dx= -dx; dy= -dy;
+ }
+
+ start= floor(v1[1]);
+ end= start+floor(dy);
+
+ if(start>Amaxy || end<Aminy) return;
+
+ if(end>Amaxy) end= Amaxy;
+
+ oldx= floor(v1[0]);
+ dx/= dy;
+
+ vergz= v1[2];
+ dz= (v2[2]-v1[2])/dy;
+
+ yoffset = start;
+ xoffset = oldx;
+
+ if(dx<0) ofs= -1;
+ else ofs= 1;
+
+ linex = xoffset;
+ liney = yoffset;
+
+ for(y= start; y<=end; y++, liney++) {
+
+ x= floor(v1[0]);
+ if(x!=oldx) {
+ oldx= x;
+ linex += ofs;
+ }
+
+ if(x>=0 && y>=Aminy && (x < imWidth)) {
+ insertInEdgeBuffer(linex, liney, vergz);
+ }
+
+ v1[0]+= dx;
+ vergz+= dz;
+ }
+ }
+} /* End of void fillEdgeRenderEdge(float *vec1, float *vec2) */
+
+/* ------------------------------------------------------------------------- */
+
+/* eof edgeRender.c */
diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c
new file mode 100644
index 00000000000..8aebe3670d0
--- /dev/null
+++ b/source/blender/render/intern/source/envmap.c
@@ -0,0 +1,689 @@
+
+/* envmap.c RENDER
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * may 1999
+ *
+ * $Id$
+ */
+
+#include <math.h>
+#include <string.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+/* external modules: */
+#include "MEM_guardedalloc.h"
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h" /* for rectcpy */
+
+#include "DNA_texture_types.h"
+#include "DNA_image_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_texture_types.h"
+
+#include "BIF_space.h"
+#include "BIF_toolbox.h"
+
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_global.h"
+#include "BKE_world.h" // init_render_world
+#include "BKE_image.h" // BKE_write_ibuf
+
+
+/* this module */
+#include "RE_callbacks.h"
+#include "render.h"
+#include "render_intern.h"
+#include "envmap.h"
+#include "mydevice.h"
+#include "rendercore.h" /* calls zbufShade(DA).... I want to replace this with my own :)*/
+#include "renderHelp.h"
+#include "MTC_matrixops.h"
+#include "zbuf.h"
+
+/* ------------------------------------------------------------------------- */
+
+void envmap_split_ima(EnvMap *env);
+void envmap_renderdata(EnvMap *env);
+void envmap_transmatrix(float mat[][4], int part);
+void env_rotate_scene(float mat[][4], int mode);
+void env_layerflags(unsigned int notlay);
+void env_set_imats(void);
+void render_envmap(EnvMap *env);
+int envcube_isect(float *vec, float *answ);
+static void set_dxtdyt(float *dxts, float *dyts, float *dxt, float *dyt, int face);
+
+/* ------------------------------------------------------------------------- */
+
+EnvMap *RE_add_envmap(void)
+{
+ EnvMap *env;
+
+ env= MEM_callocN(sizeof(EnvMap), "envmap");
+ env->type= ENV_CUBE;
+ env->stype= ENV_STATIC;
+ env->clipsta= 0.1;
+ env->clipend= 100.0;
+ env->cuberes= 100;
+
+ return env;
+} /* end of EnvMap *RE_add_envmap() */
+
+/* ------------------------------------------------------------------------- */
+
+EnvMap *RE_copy_envmap(EnvMap *env)
+{
+ EnvMap *envn;
+ int a;
+
+ envn= MEM_dupallocN(env);
+ envn->ok= 0;
+ for(a=0; a<6; a++) envn->cube[a]= 0;
+ if(envn->ima) id_us_plus((ID *)envn->ima);
+
+ return envn;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void RE_free_envmapdata(EnvMap *env)
+{
+ Image *ima;
+ int a, part;
+
+ for(part=0; part<6; part++) {
+ ima= env->cube[part];
+ if(ima) {
+ if(ima->ibuf) IMB_freeImBuf(ima->ibuf);
+
+ for(a=0; a<BLI_ARRAY_NELEMS(ima->mipmap); a++) {
+ if(ima->mipmap[a]) IMB_freeImBuf(ima->mipmap[a]);
+ }
+ MEM_freeN(ima);
+ env->cube[part]= 0;
+ }
+ }
+ env->ok= 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void RE_free_envmap(EnvMap *env)
+{
+
+ RE_free_envmapdata(env);
+ MEM_freeN(env);
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+void envmap_split_ima(EnvMap *env)
+{
+ ImBuf *ibuf;
+ Image *ima;
+/* extern rectcpy(); */
+ int dx, part;
+
+ RE_free_envmapdata(env);
+
+ dx= env->ima->ibuf->y;
+ dx/= 2;
+ if(3*dx != env->ima->ibuf->x) {
+ error("Incorrect envmap size");
+ env->ok= 0;
+ env->ima->ok= 0;
+ }
+ else {
+ for(part=0; part<6; part++) {
+ ibuf= IMB_allocImBuf(dx, dx, 24, IB_rect, 0);
+ ima= MEM_callocN(sizeof(Image), "image");
+ ima->ibuf= ibuf;
+ ima->ok= 1;
+ env->cube[part]= ima;
+ }
+ IMB_rectop(env->cube[0]->ibuf, env->ima->ibuf,
+ 0, 0, 0, 0, dx, dx, IMB_rectcpy, 0);
+ IMB_rectop(env->cube[1]->ibuf, env->ima->ibuf,
+ 0, 0, dx, 0, dx, dx, IMB_rectcpy, 0);
+ IMB_rectop(env->cube[2]->ibuf, env->ima->ibuf,
+ 0, 0, 2*dx, 0, dx, dx, IMB_rectcpy, 0);
+ IMB_rectop(env->cube[3]->ibuf, env->ima->ibuf,
+ 0, 0, 0, dx, dx, dx, IMB_rectcpy, 0);
+ IMB_rectop(env->cube[4]->ibuf, env->ima->ibuf,
+ 0, 0, dx, dx, dx, dx, IMB_rectcpy, 0);
+ IMB_rectop(env->cube[5]->ibuf, env->ima->ibuf,
+ 0, 0, 2*dx, dx, dx, dx, IMB_rectcpy, 0);
+ env->ok= 2;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+/* ****************** RENDER ********************** */
+
+void envmap_renderdata(EnvMap *env)
+{
+ static RE_Render envR;
+ static Object *camera;
+
+ if(env) {
+ envR= R;
+ camera= G.scene->camera;
+
+ env->cuberes &= 0xFFFC;
+ R.rectx= R.r.xsch= R.recty= R.r.ysch= env->cuberes;
+ R.afmx= R.afmy= R.r.xsch/2;
+ R.xstart= R.ystart= -R.afmx;
+ R.xend= R.yend= R.xstart+R.rectx-1;
+
+ R.r.mode &= ~(R_BORDER | R_PANORAMA | R_ORTHO | R_MBLUR);
+ R.r.xparts= R.r.yparts= 1;
+ R.r.bufflag= 0;
+ R.r.size= 100;
+ R.ycor= 1.0;
+ R.r.yasp= R.r.xasp= 1;
+
+ R.near= env->clipsta;
+ R.far= env->clipend;
+
+ G.scene->camera= env->object;
+
+ }
+ else {
+ /* this to make sure init_renderdisplay works */
+ envR.winx= R.winx;
+ envR.winy= R.winy;
+ envR.winxof= R.winxof;
+ envR.winyof= R.winyof;
+
+ R= envR;
+ G.scene->camera= camera;
+ }
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+void envmap_transmatrix(float mat[][4], int part)
+{
+ float tmat[4][4], eul[3], rotmat[4][4];
+
+ eul[0]= eul[1]= eul[2]= 0.0;
+
+ if(part==0) { /* neg z */
+ ;
+ } else if(part==1) { /* pos z */
+ eul[0]= M_PI;
+ } else if(part==2) { /* pos y */
+ eul[0]= M_PI/2.0;
+ } else if(part==3) { /* neg x */
+ eul[0]= M_PI/2.0;
+ eul[2]= M_PI/2.0;
+ } else if(part==4) { /* neg y */
+ eul[0]= M_PI/2.0;
+ eul[2]= M_PI;
+ } else { /* pos x */
+ eul[0]= M_PI/2.0;
+ eul[2]= -M_PI/2.0;
+ }
+
+ MTC_Mat4CpyMat4(tmat, mat);
+ EulToMat4(eul, rotmat);
+ MTC_Mat4MulSerie(mat, tmat, rotmat,
+ 0, 0, 0,
+ 0, 0, 0);
+}
+
+/* ------------------------------------------------------------------------- */
+
+void env_rotate_scene(float mat[][4], int mode)
+{
+ VlakRen *vlr = NULL;
+ VertRen *ver = NULL;
+ LampRen *lar = NULL;
+ HaloRen *har = NULL;
+ float xn, yn, zn, imat[3][3], pmat[4][4], smat[4][4], tmat[4][4];
+ int a;
+
+ if(mode==0) {
+ MTC_Mat4Invert(tmat, mat);
+ MTC_Mat3CpyMat4(imat, tmat);
+ }
+ else {
+ MTC_Mat4CpyMat4(tmat, mat);
+ MTC_Mat3CpyMat4(imat, mat);
+ }
+
+ for(a=0; a<R.totvert; a++) {
+ if((a & 255)==0) ver= R.blove[a>>8];
+ else ver++;
+
+ MTC_Mat4MulVecfl(tmat, ver->co);
+
+ xn= ver->n[0];
+ yn= ver->n[1];
+ zn= ver->n[2];
+ /* geen transpose ! */
+ ver->n[0]= imat[0][0]*xn+imat[1][0]*yn+imat[2][0]*zn;
+ ver->n[1]= imat[0][1]*xn+imat[1][1]*yn+imat[2][1]*zn;
+ ver->n[2]= imat[0][2]*xn+imat[1][2]*yn+imat[2][2]*zn;
+ Normalise(ver->n);
+ }
+
+ for(a=0; a<R.tothalo; a++) {
+ if((a & 255)==0) har= R.bloha[a>>8];
+ else har++;
+
+ MTC_Mat4MulVecfl(tmat, har->co);
+ }
+
+ for(a=0; a<R.totvlak; a++) {
+ if((a & 255)==0) vlr= R.blovl[a>>8];
+ else vlr++;
+
+ xn= vlr->n[0];
+ yn= vlr->n[1];
+ zn= vlr->n[2];
+ /* geen transpose ! */
+ vlr->n[0]= imat[0][0]*xn+imat[1][0]*yn+imat[2][0]*zn;
+ vlr->n[1]= imat[0][1]*xn+imat[1][1]*yn+imat[2][1]*zn;
+ vlr->n[2]= imat[0][2]*xn+imat[1][2]*yn+imat[2][2]*zn;
+ Normalise(vlr->n);
+ }
+
+ set_normalflags();
+
+ for(a=0; a<R.totlamp; a++) {
+ lar= R.la[a];
+
+ /* smat should actually be a 3x3 matrix, the 4x4 declaration is */
+ /* just for confusion. */
+
+ /* Only the left-top 3x3 is copied...? smat is 4by4! imat is 3x3 */
+ /* Actually, it is not: Mat3CpyMat3 copies the first 9 floats! */
+ /* What should happen is mat4cpymat3 */
+/* Mat3CpyMat3(smat, lar->imat); */
+ MTC_Mat4CpyMat3nc(smat, lar->imat);
+ /* This would be lar->imat = smat * imat, so 3d = 4d * 3d? */
+ /* the mat3mulmat3 does a multiply on the wrong elements.... */
+/* Mat3MulMat3(lar->imat, smat, imat); */
+ MTC_Mat4MulMat33(lar->imat, smat, imat);
+ MTC_Mat3MulVecfl(imat, lar->vec);
+ MTC_Mat4MulVecfl(tmat, lar->co);
+
+ lar->sh_invcampos[0]= -lar->co[0];
+ lar->sh_invcampos[1]= -lar->co[1];
+ lar->sh_invcampos[2]= -lar->co[2];
+ MTC_Mat3MulVecfl(lar->imat, lar->sh_invcampos);
+ lar->sh_invcampos[2]*= lar->sh_zfac;
+
+ if(lar->shb) {
+ if(mode==1) {
+ MTC_Mat4Invert(pmat, mat);
+ MTC_Mat4MulMat4(smat, pmat, lar->shb->viewmat);
+ MTC_Mat4MulMat4(lar->shb->persmat, smat, lar->shb->winmat);
+ }
+ else MTC_Mat4MulMat4(lar->shb->persmat, lar->shb->viewmat, lar->shb->winmat);
+ }
+ }
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+void env_layerflags(unsigned int notlay)
+{
+ VlakRen *vlr = NULL;
+ int a;
+
+ for(a=0; a<R.totvlak; a++) {
+ if((a & 255)==0) vlr= R.blovl[a>>8];
+ else vlr++;
+ if(vlr->lay & notlay) vlr->flag &= ~R_VISIBLE;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+void env_set_imats()
+{
+ Base *base;
+ float mat[4][4];
+
+ base= G.scene->base.first;
+ while(base) {
+ MTC_Mat4MulMat4(mat, base->object->obmat, R.viewmat);
+ MTC_Mat4Invert(base->object->imat, mat);
+
+ base= base->next;
+ }
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+void render_envmap(EnvMap *env)
+{
+ /* only the cubemap is implemented */
+ ImBuf *ibuf;
+ Image *ima;
+ float oldviewinv[4][4], mat[4][4], tmat[4][4];
+ short part;
+
+ /* need a recalc: ortho-render has no correct viewinv */
+ MTC_Mat4Invert(oldviewinv, R.viewmat);
+
+ /* setup necessary globals */
+ envmap_renderdata(env);
+
+ RE_local_init_render_display();
+
+ R.rectot= MEM_mallocN(sizeof(int)*R.rectx*R.recty, "rectot");
+ R.rectz= MEM_mallocN(sizeof(int)*R.rectx*R.recty, "rectz");
+
+ for(part=0; part<6; part++) {
+
+ RE_local_clear_render_display(R.win);
+ fillrect(R.rectot, R.rectx, R.recty, 0);
+
+ RE_setwindowclip(1,-1); /* geen jit:(-1) */
+
+ MTC_Mat4CpyMat4(tmat, G.scene->camera->obmat);
+ MTC_Mat4Ortho(tmat);
+ envmap_transmatrix(tmat, part);
+ MTC_Mat4Invert(mat, tmat);
+ /* mat now is the camera 'viewmat' */
+
+ MTC_Mat4CpyMat4(R.viewmat, mat);
+ MTC_Mat4CpyMat4(R.viewinv, tmat);
+
+ /* we have to correct for the already rotated vertexcoords */
+ MTC_Mat4MulMat4(tmat, oldviewinv, R.viewmat);
+ MTC_Mat4Invert(env->imat, tmat);
+
+ env_rotate_scene(tmat, 1);
+ init_render_world();
+ setzbufvlaggen(RE_projectverto);
+ env_layerflags(env->notlay);
+ env_set_imats();
+
+ if(RE_local_test_break()==0) {
+
+ RE_local_printrenderinfo(0.0, part);
+
+ if(R.r.mode & R_OSA) zbufshadeDA();
+ else zbufshade();
+
+ }
+
+ /* rotate back */
+ env_rotate_scene(tmat, 0);
+
+ if(RE_local_test_break()==0) {
+ ibuf= IMB_allocImBuf(R.rectx, R.recty, 24, IB_rect, 0);
+ ima= MEM_callocN(sizeof(Image), "image");
+ memcpy(ibuf->rect, R.rectot, 4*ibuf->x*ibuf->y);
+ ima->ibuf= ibuf;
+ ima->ok= 1;
+ env->cube[part]= ima;
+ }
+
+ if(RE_local_test_break()) break;
+
+ }
+
+ if(R.rectz) MEM_freeN(R.rectz); R.rectz= 0;
+ if(R.rectot) MEM_freeN(R.rectot); R.rectot= 0;
+
+ if(RE_local_test_break()) RE_free_envmapdata(env);
+ else {
+ if(R.r.mode & R_OSA) env->ok= ENV_OSA;
+ else env->ok= ENV_NORMAL;
+ env->lastframe= G.scene->r.cfra;
+ }
+
+ /* restore */
+ envmap_renderdata(0);
+ env_set_imats();
+ init_render_world();
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+void make_envmaps()
+{
+ Tex *tex;
+ int do_init= 0;
+
+ tex= G.main->tex.first;
+ while(tex) {
+ if(tex->id.us && tex->type==TEX_ENVMAP) {
+ if(tex->env && tex->env->object) {
+ if(tex->env->object->lay & G.scene->lay) {
+ if(tex->env->stype!=ENV_LOAD) {
+
+ if(tex->env->ok==0) {
+ do_init= 1;
+ render_envmap(tex->env);
+ }
+ else if((R.r.mode & R_OSA) && tex->env->ok==ENV_NORMAL) {
+ do_init= 1;
+ RE_free_envmapdata(tex->env);
+ render_envmap(tex->env);
+ }
+ }
+ }
+ }
+ }
+ tex= tex->id.next;
+ }
+
+ if(do_init) {
+ RE_local_init_render_display();
+ RE_local_clear_render_display(R.win);
+ allqueue(REDRAWBUTSTEX, 0);
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+int envcube_isect(float *vec, float *answ)
+{
+ float labda;
+ int face;
+
+ /* which face */
+ if( vec[2]<=-fabs(vec[0]) && vec[2]<=-fabs(vec[1]) ) {
+ face= 0;
+ labda= -1.0/vec[2];
+ answ[0]= labda*vec[0];
+ answ[1]= labda*vec[1];
+ }
+ else if( vec[2]>=fabs(vec[0]) && vec[2]>=fabs(vec[1]) ) {
+ face= 1;
+ labda= 1.0/vec[2];
+ answ[0]= labda*vec[0];
+ answ[1]= -labda*vec[1];
+ }
+ else if( vec[1]>=fabs(vec[0]) ) {
+ face= 2;
+ labda= 1.0/vec[1];
+ answ[0]= labda*vec[0];
+ answ[1]= labda*vec[2];
+ }
+ else if( vec[0]<=-fabs(vec[1]) ) {
+ face= 3;
+ labda= -1.0/vec[0];
+ answ[0]= labda*vec[1];
+ answ[1]= labda*vec[2];
+ }
+ else if( vec[1]<=-fabs(vec[0]) ) {
+ face= 4;
+ labda= -1.0/vec[1];
+ answ[0]= -labda*vec[0];
+ answ[1]= labda*vec[2];
+ }
+ else {
+ face= 5;
+ labda= 1.0/vec[0];
+ answ[0]= -labda*vec[1];
+ answ[1]= labda*vec[2];
+ }
+ answ[0]= 0.5+0.5*answ[0];
+ answ[1]= 0.5+0.5*answ[1];
+ return face;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void set_dxtdyt(float *dxts, float *dyts, float *dxt, float *dyt, int face)
+{
+ if(face==2 || face==4) {
+ dxts[0]= dxt[0];
+ dyts[0]= dyt[0];
+ dxts[1]= dxt[2];
+ dyts[1]= dyt[2];
+ }
+ else if(face==3 || face==5) {
+ dxts[0]= dxt[1];
+ dxts[1]= dxt[2];
+ dyts[0]= dyt[1];
+ dyts[1]= dyt[2];
+ }
+ else {
+ dxts[0]= dxt[0];
+ dyts[0]= dyt[0];
+ dxts[1]= dxt[1];
+ dyts[1]= dyt[1];
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+extern float Tin, Ta, Tr, Tg, Tb; /* texture.c */
+int RE_envmaptex(Tex *tex, float *texvec, float *dxt, float *dyt)
+{
+ /* texvec should be the already reflected normal */
+ EnvMap *env;
+ float fac, vec[3], sco[3], col[20], dxts[3], dyts[3];
+ int face, face1;
+
+ env= tex->env;
+ if(env==0 || env->object==0) return 0;
+
+ if(env->stype==ENV_LOAD) {
+ env->ima= tex->ima;
+ if(env->ima && env->ima->ok) {
+ if(env->ima->ibuf==0) ima_ibuf_is_nul(tex);
+ if(env->ima->ok && env->ok==0) envmap_split_ima(env);
+ }
+ }
+
+ if(env->ok==0) {
+
+ Tin= 0.0;
+ return 0;
+ }
+
+ /* rotate to envmap space */
+ VECCOPY(vec, texvec);
+ MTC_Mat4Mul3Vecfl(env->object->imat, vec);
+
+ face= envcube_isect(vec, sco);
+ tex->ima= env->cube[face];
+
+ if(R.osatex) {
+ MTC_Mat4Mul3Vecfl(env->object->imat, dxt);
+ MTC_Mat4Mul3Vecfl(env->object->imat, dyt);
+
+ set_dxtdyt(dxts, dyts, dxt, dyt, face);
+ imagewraposa(tex, sco, dxts, dyts);
+
+ /* edges? */
+
+ if(Ta<1.0) {
+ col[0]= Ta; col[1]= Tr; col[2]= Tg; col[3]= Tb;
+
+ VecAddf(vec, vec, dxt);
+ face1= envcube_isect(vec, sco);
+ VecSubf(vec, vec, dxt);
+
+ if(face!=face1) {
+ tex->ima= env->cube[face1];
+ set_dxtdyt(dxts, dyts, dxt, dyt, face1);
+ imagewraposa(tex, sco, dxts, dyts);
+ col[4]= Ta; col[5]= Tr; col[6]= Tg; col[7]= Tb;
+ }
+ else col[4]= col[5]= col[6]= col[7]= 0.0;
+
+ /* here was the nasty bug! col[5,6,7] were not zero-ed. FPE! */
+
+ VecAddf(vec, vec, dyt);
+ face1= envcube_isect(vec, sco);
+ VecSubf(vec, vec, dyt);
+
+ if(face!=face1) {
+ tex->ima= env->cube[face1];
+ set_dxtdyt(dxts, dyts, dxt, dyt, face1);
+ imagewraposa(tex, sco, dxts, dyts);
+ col[8]= Ta; col[9]= Tr; col[10]= Tg; col[11]= Tb;
+ }
+ else col[8]= col[9]= col[10]= col[11]= 0.0;
+
+ fac= (col[0]+col[4]+col[8]);
+ fac= 1.0/fac;
+
+ Tr= fac*(col[0]*col[1] + col[4]*col[5] + col[8]*col[9] );
+ Tg= fac*(col[0]*col[2] + col[4]*col[6] + col[8]*col[10] );
+ Tb= fac*(col[0]*col[3] + col[4]*col[7] + col[8]*col[11] );
+ Ta= 1.0;
+
+ }
+ }
+ else {
+ imagewrap(tex, sco);
+ }
+
+ tex->ima= env->ima;
+
+ return 1;
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* eof */
diff --git a/source/blender/render/intern/source/errorHandler.c b/source/blender/render/intern/source/errorHandler.c
new file mode 100644
index 00000000000..fc21ee272c4
--- /dev/null
+++ b/source/blender/render/intern/source/errorHandler.c
@@ -0,0 +1,99 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Error handler for the rendering code. Maybe also useful elsewhere?
+ */
+
+#include "GEN_messaging.h"
+#include "stdio.h"
+#include "errorHandler.h"
+
+#include "render_intern.h"
+
+/* ------------------------------------------------------------------------- */
+
+/* counters for error handling */
+static int lastError; /* code of last encountered error */
+static int errorCount; /* count how many time it occured */
+/* ------------------------------------------------------------------------- */
+
+char errorStrings[RE_MAX_ERROR][100] = {
+ "0: No error",
+ "1: recalculated depth falls outside original range",
+ "2: invalid face/halo type",
+ "3: invalid face index",
+ "4: invalid data pointer",
+ "5: generic trace counter",
+ "6: overflow on z buffer depth",
+ "7: write outside edgerender buffer",
+ "8: cannot allocate memory",
+ "9: write outside colour target buffer",
+};
+
+/* ------------------------------------------------------------------------- */
+
+void RE_errortrace_reset(void)
+{
+ lastError = RE_NO_ERROR;
+ errorCount = 0;
+}
+
+void RE_error(int errType, char* fname)
+{
+ /*
+ * This memory behaviour should move to the generic stream...
+ */
+
+ if (lastError == errType) {
+ int teller;
+ errorCount++;
+ for (teller = 0; teller < 12; teller++)
+ fprintf(GEN_errorstream, "%c", 0x08); /* backspaces */
+ fprintf(GEN_errorstream, "( %8u )", errorCount);
+ } else {
+ fprintf(GEN_errorstream, "\n*** %s: %s ",
+ fname, errorStrings[errType]);
+ lastError = errType;
+ errorCount = 1;
+ }
+} /* end of void RE_error(int errType, char* errText) */
+
+/* ------------------------------------------------------------------------- */
+/* note: non-repeating */
+void RE_error_int(int errType, char* fname, int value)
+{
+ fprintf(GEN_errorstream, "\n*** %s: %s : %d",
+ fname, errorStrings[errType], value);
+ lastError = RE_NO_ERROR;
+} /* end of void RE_error_int(int errType, char* errText, int value) */
+
+/* ------------------------------------------------------------------------- */
+
+/* eof */
diff --git a/source/blender/render/intern/source/gammaCorrectionTables.c b/source/blender/render/intern/source/gammaCorrectionTables.c
new file mode 100644
index 00000000000..b25e7f0cdca
--- /dev/null
+++ b/source/blender/render/intern/source/gammaCorrectionTables.c
@@ -0,0 +1,168 @@
+/**
+ * Jitter offset table
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include "gammaCorrectionTables.h"
+#include <stdlib.h>
+#include <math.h>
+
+#include "render_intern.h"
+
+/* There are two parts here: one for the old renderer, one for the unified */
+/* renderer. we start with the latter. */
+
+/* Default gamma. For most CRTs, gamma ranges from 2.2 to 2.5 (Foley), so */
+/* 2.35 seems appropriate enough. Experience teaches a different number */
+/* though. Old blender: 2.0. It might be nice to make this a slider */
+#define RE_DEFAULT_GAMMA 2.0
+/* This 400 is sort of based on the number of intensity levels needed for */
+/* the typical dynamic range of a medium, in this case CRTs. (Foley) */
+/* (Actually, it says the number should be between 400 and 535.) */
+#define RE_GAMMA_TABLE_SIZE 400
+
+/* These indicate the status of the gamma lookup table --------------------- */
+
+static float gamma_range_table[RE_GAMMA_TABLE_SIZE + 1];
+static float gamfactor_table[RE_GAMMA_TABLE_SIZE];
+static float inv_gamma_range_table[RE_GAMMA_TABLE_SIZE + 1];
+static float inv_gamfactor_table[RE_GAMMA_TABLE_SIZE];
+static float colour_domain_table[RE_GAMMA_TABLE_SIZE + 1];
+static float colour_step;
+static float inv_colour_step;
+static float valid_gamma;
+static float valid_inv_gamma;
+static int gamma_table_initialised = 0;
+static int do_gamma;
+/* ------------------------------------------------------------------------- */
+
+float gammaCorrect(float c)
+{
+ int i;
+ float res = 0.0;
+
+ i = floor(c * inv_colour_step);
+ /* Clip to range [0,1]: outside, just do the complete calculation. */
+ /* We may have some performance problems here. Stretching up the LUT */
+ /* may help solve that, by exchanging LUT size for the interpolation. */
+ /* Negative colours are explicitly handled. */
+ if (i < 0) res = -pow(abs(c), valid_gamma);
+ else if (i >= RE_GAMMA_TABLE_SIZE ) res = pow(c, valid_gamma);
+ else res = gamma_range_table[i] +
+ ( (c - colour_domain_table[i]) * gamfactor_table[i]);
+
+ return res;
+} /* end of float gammaCorrect(float col) */
+
+/* ------------------------------------------------------------------------- */
+
+float invGammaCorrect(float col)
+{
+ int i;
+ float res = 0.0;
+
+ i = floor(col*inv_colour_step);
+ /* Negative colours are explicitly handled. */
+ if (i < 0) res = -pow(abs(col), valid_inv_gamma);
+ else if (i >= RE_GAMMA_TABLE_SIZE) res = pow(col, valid_inv_gamma);
+ else res = inv_gamma_range_table[i] +
+ ( (col - colour_domain_table[i]) * inv_gamfactor_table[i]);
+
+ return res;
+} /* end of float invGammaCorrect(float col) */
+
+
+/* ------------------------------------------------------------------------- */
+
+void makeGammaTables(float gamma)
+{
+ /* we need two tables: one forward, one backward */
+ int i;
+
+ valid_gamma = gamma;
+ valid_inv_gamma = 1.0 / gamma;
+ colour_step = 1.0 / RE_GAMMA_TABLE_SIZE;
+ inv_colour_step = (float) RE_GAMMA_TABLE_SIZE;
+
+ /* We could squeeze out the two range tables to gain some memory. */
+ for (i = 0; i < RE_GAMMA_TABLE_SIZE; i++) {
+ colour_domain_table[i] = i * colour_step;
+ gamma_range_table[i] = pow(colour_domain_table[i],
+ valid_gamma);
+ inv_gamma_range_table[i] = pow(colour_domain_table[i],
+ valid_inv_gamma);
+ }
+
+ /* The end of the table should match 1.0 carefully. In order to avoid */
+ /* rounding errors, we just set this explicitly. The last segment may */
+ /* have a different lenght than the other segments, but our */
+ /* interpolation is insensitive to that. */
+ colour_domain_table[RE_GAMMA_TABLE_SIZE] = 1.0;
+ gamma_range_table[RE_GAMMA_TABLE_SIZE] = 1.0;
+ inv_gamma_range_table[RE_GAMMA_TABLE_SIZE] = 1.0;
+
+ /* To speed up calculations, we make these calc factor tables. They are */
+ /* multiplication factors used in scaling the interpolation. */
+ for (i = 0; i < RE_GAMMA_TABLE_SIZE; i++ ) {
+ gamfactor_table[i] = inv_colour_step
+ * (gamma_range_table[i + 1] - gamma_range_table[i]) ;
+ inv_gamfactor_table[i] = inv_colour_step
+ * (inv_gamma_range_table[i + 1] - inv_gamma_range_table[i]) ;
+ }
+
+ gamma_table_initialised = 1;
+} /* end of void makeGammaTables(float gamma) */
+
+/* ------------------------------------------------------------------------- */
+
+int gammaTableIsInitialised(void)
+{
+ return gamma_table_initialised;
+}
+
+/* ------------------------------------------------------------------------- */
+int doGamma()
+{
+ return do_gamma;
+}
+
+/* ------------------------------------------------------------------------- */
+
+/**
+ * Set/unset performing gamma corrections.
+ */
+void setDoGamma(int i)
+{
+ do_gamma = i;
+}
+
+/* eof */
diff --git a/source/blender/render/intern/source/initrender.c b/source/blender/render/intern/source/initrender.c
new file mode 100644
index 00000000000..67fddc271e6
--- /dev/null
+++ b/source/blender/render/intern/source/initrender.c
@@ -0,0 +1,1329 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+
+/* Global includes */
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "PIL_time.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_rand.h"
+
+#include "MTC_matrixops.h"
+
+#include "DNA_image_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_material.h"
+#include "BKE_object.h"
+#include "BKE_image.h"
+#include "BKE_ipo.h"
+#include "BKE_key.h"
+#include "BKE_ika.h"
+#include "BKE_action.h"
+#include "BKE_writeavi.h"
+#include "BKE_scene.h"
+
+#include "BIF_toolbox.h"
+#include "BIF_writeavicodec.h"
+#include "BIF_writemovie.h" /* start_movie(), append_movie(), end_movie() */
+
+#include "BSE_drawview.h"
+#include "BSE_sequence.h"
+
+/* this module */
+#include "render.h"
+#include "render_intern.h"
+
+#include "RE_callbacks.h"
+#include "zbuf.h"
+#include "rendercore.h" /* part handler for the old renderer, shading functions */
+#include "renderPreAndPost.h"
+#include "outerRenderLoop.h"
+#include "renderHelp.h"
+#include "jitter.h"
+
+/* Own includes */
+#include "initrender.h"
+
+/* Some crud :/ */
+#define ELEM3(a, b, c, d) ( ELEM(a, b, c) || (a)==(d) )
+
+
+/* uit render.c */
+extern float fmask[256], centLut[16];
+extern unsigned short *mask1[9], *mask2[9], /* *igamtab1, */ *igamtab2/*, *gamtab */;
+extern char cmask[256], *centmask;
+
+Material defmaterial;
+short pa; /* pa is globaal part ivm print */
+short allparts[65][4];
+int qscount;
+
+/* ********************* *********************** */
+
+
+void init_def_material(void)
+{
+ Material *ma;
+
+ ma= &defmaterial;
+
+ init_material(&defmaterial);
+
+ init_render_material(ma);
+}
+
+void RE_init_render_data(void)
+{
+ memset(&R, 0, sizeof(RE_Render));
+ memset(&O, 0, sizeof(Osa));
+ O.dxwin[0]= 1.0;
+ O.dywin[1]= 1.0;
+
+ R.blove= (VertRen **)MEM_callocN(sizeof(void *)*(MAXVERT>>8),"Blove");
+ R.blovl= (VlakRen **)MEM_callocN(sizeof(void *)*(MAXVLAK>>8),"Blovl");
+ R.bloha= (HaloRen **)MEM_callocN(sizeof(void *)*(MAXVERT>>8),"Bloha");
+ R.la= (LampRen **)MEM_mallocN(MAXLAMP*sizeof(void *),"renderlamparray");
+
+ init_def_material();
+}
+
+void RE_free_render_data()
+{
+ MEM_freeN(R.blove);
+ R.blove= 0;
+ MEM_freeN(R.blovl);
+ R.blovl= 0;
+ MEM_freeN(R.bloha);
+ R.bloha= 0;
+ MEM_freeN(R.la);
+ R.la= 0;
+ if(R.rectot) MEM_freeN(R.rectot);
+ if(R.rectz) MEM_freeN(R.rectz);
+ if(R.rectspare) MEM_freeN(R.rectspare);
+ R.rectot= 0;
+ R.rectz= 0;
+ R.rectspare= 0;
+
+ end_render_material(&defmaterial);
+}
+
+/* ****************** GAMMA, MASKERS en LUTS **************** */
+
+float calc_weight(float *weight, int i, int j)
+{
+ float x, y, dist, totw= 0.0;
+ int a;
+
+ for(a=0; a<R.osa; a++) {
+ x= jit[a][0]-0.5+ i;
+ y= jit[a][1]-0.5+ j;
+ dist= sqrt(x*x+y*y);
+
+ weight[a]= 0.0;
+
+ if(R.r.mode & R_GAUSS) {
+ if(dist<1.5) {
+ x = dist*1.5;
+ weight[a]= (1.0/exp(x*x) - 1.0/exp(1.5*1.5*1.5*1.5));
+ }
+ }
+ else {
+ if(i==0 && j==0) weight[a]= 1.0;
+ }
+
+ totw+= weight[a];
+
+ }
+ return totw;
+}
+
+void RE_init_filt_mask(void)
+{
+ static int firsttime=1;
+ static float lastgamma= 0.0;
+ float gamma, igamma;
+ float weight[32], totw, val, *fpx1, *fpx2, *fpy1, *fpy2;
+ int i, j, a;
+ unsigned short *m1, *m2, shweight[32];
+
+ if(firsttime) {
+ for(a=0; a<9;a++) {
+ mask1[a]= MEM_mallocN(256*sizeof(short), "initfilt");
+ mask2[a]= MEM_mallocN(256*sizeof(short), "initfilt");
+ }
+ for(a=0; a<256; a++) {
+ cmask[a]= 0;
+ if(a & 1) cmask[a]++;
+ if(a & 2) cmask[a]++;
+ if(a & 4) cmask[a]++;
+ if(a & 8) cmask[a]++;
+ if(a & 16) cmask[a]++;
+ if(a & 32) cmask[a]++;
+ if(a & 64) cmask[a]++;
+ if(a & 128) cmask[a]++;
+ }
+ centmask= MEM_mallocN(65536, "Initfilt3");
+ for(a=0; a<16; a++) {
+ centLut[a]= -0.45+((float)a)/16.0;
+ }
+
+ gamtab= MEM_mallocN(65536*sizeof(short), "initGaus2");
+ igamtab1= MEM_mallocN(256*sizeof(short), "initGaus2");
+ igamtab2= MEM_mallocN(65536*sizeof(short), "initGaus2");
+
+ }
+
+ if(R.r.alphamode==R_ALPHAKEY) gamma= 1.0; /* ??? */
+
+ if(R.r.mode & R_GAMMA) gamma= 2.0;
+ else gamma= 1.0;
+ igamma= 1.0/gamma;
+
+ if(gamma!= lastgamma) {
+ lastgamma= gamma;
+
+ /* gamtab: in short, uit short */
+ for(a=0; a<65536; a++) {
+ val= a;
+ val/= 65535.0;
+
+ if(gamma==2.0) val= sqrt(val);
+ else if(gamma!=1.0) val= pow(val, igamma);
+
+ gamtab[a]= (65535.99*val);
+ }
+ /* inv gamtab1 : in byte, uit short */
+ for(a=1; a<=256; a++) {
+ if(gamma==2.0) igamtab1[a-1]= a*a-1;
+ else if(gamma==1.0) igamtab1[a-1]= 256*a-1;
+ else {
+ val= a/256.0;
+ igamtab1[a-1]= (65535.0*pow(val, gamma)) -1 ;
+ }
+ }
+
+ /* inv gamtab2 : in short, uit short */
+ for(a=0; a<65536; a++) {
+ val= a;
+ val/= 65535.0;
+ if(gamma==2.0) val= val*val;
+ else val= pow(val, gamma);
+
+ igamtab2[a]= 65535.0*val;
+ }
+ }
+
+ if(firsttime) {
+ firsttime= 0;
+ return;
+ }
+
+ val= 1.0/((float)R.osa);
+ for(a=0; a<256; a++) {
+ fmask[a]= ((float)cmask[a])*val;
+ }
+
+ for(a=0; a<9;a++) {
+ memset(mask1[a], 0, 256*2);
+ memset(mask2[a], 0, 256*2);
+ }
+
+ /* bereken totw */
+ totw= 0.0;
+ for(j= -1; j<2; j++) {
+ for(i= -1; i<2; i++) {
+ totw+= calc_weight(weight, i, j);
+ }
+ }
+
+ for(j= -1; j<2; j++) {
+ for(i= -1; i<2; i++) {
+ /* bereken ahv jit met ofset de gewichten */
+
+ memset(weight, 0, 32*2);
+ calc_weight(weight, i, j);
+
+ for(a=0; a<16; a++) shweight[a]= weight[a]*(65535.0/totw);
+
+ m1= mask1[ 3*(j+1)+i+1 ];
+ m2= mask2[ 3*(j+1)+i+1 ];
+
+ for(a=0; a<256; a++) {
+ if(a & 1) {
+ m1[a]+= shweight[0];
+ m2[a]+= shweight[8];
+ }
+ if(a & 2) {
+ m1[a]+= shweight[1];
+ m2[a]+= shweight[9];
+ }
+ if(a & 4) {
+ m1[a]+= shweight[2];
+ m2[a]+= shweight[10];
+ }
+ if(a & 8) {
+ m1[a]+= shweight[3];
+ m2[a]+= shweight[11];
+ }
+ if(a & 16) {
+ m1[a]+= shweight[4];
+ m2[a]+= shweight[12];
+ }
+ if(a & 32) {
+ m1[a]+= shweight[5];
+ m2[a]+= shweight[13];
+ }
+ if(a & 64) {
+ m1[a]+= shweight[6];
+ m2[a]+= shweight[14];
+ }
+ if(a & 128) {
+ m1[a]+= shweight[7];
+ m2[a]+= shweight[15];
+ }
+ }
+ }
+ }
+
+ /* centmask: de juiste subpixel ofset per masker */
+
+ fpx1= MEM_mallocN(256*sizeof(float), "initgauss4");
+ fpx2= MEM_mallocN(256*sizeof(float), "initgauss4");
+ fpy1= MEM_mallocN(256*sizeof(float), "initgauss4");
+ fpy2= MEM_mallocN(256*sizeof(float), "initgauss4");
+ for(a=0; a<256; a++) {
+ fpx1[a]= fpx2[a]= 0.0;
+ fpy1[a]= fpy2[a]= 0.0;
+ if(a & 1) {
+ fpx1[a]+= jit[0][0];
+ fpy1[a]+= jit[0][1];
+ fpx2[a]+= jit[8][0];
+ fpy2[a]+= jit[8][1];
+ }
+ if(a & 2) {
+ fpx1[a]+= jit[1][0];
+ fpy1[a]+= jit[1][1];
+ fpx2[a]+= jit[9][0];
+ fpy2[a]+= jit[9][1];
+ }
+ if(a & 4) {
+ fpx1[a]+= jit[2][0];
+ fpy1[a]+= jit[2][1];
+ fpx2[a]+= jit[10][0];
+ fpy2[a]+= jit[10][1];
+ }
+ if(a & 8) {
+ fpx1[a]+= jit[3][0];
+ fpy1[a]+= jit[3][1];
+ fpx2[a]+= jit[11][0];
+ fpy2[a]+= jit[11][1];
+ }
+ if(a & 16) {
+ fpx1[a]+= jit[4][0];
+ fpy1[a]+= jit[4][1];
+ fpx2[a]+= jit[12][0];
+ fpy2[a]+= jit[12][1];
+ }
+ if(a & 32) {
+ fpx1[a]+= jit[5][0];
+ fpy1[a]+= jit[5][1];
+ fpx2[a]+= jit[13][0];
+ fpy2[a]+= jit[13][1];
+ }
+ if(a & 64) {
+ fpx1[a]+= jit[6][0];
+ fpy1[a]+= jit[6][1];
+ fpx2[a]+= jit[14][0];
+ fpy2[a]+= jit[14][1];
+ }
+ if(a & 128) {
+ fpx1[a]+= jit[7][0];
+ fpy1[a]+= jit[7][1];
+ fpx2[a]+= jit[15][0];
+ fpy2[a]+= jit[15][1];
+ }
+ }
+
+ for(a= (1<<R.osa)-1; a>0; a--) {
+ val= count_mask(a);
+ i= (15.9*(fpy1[a & 255]+fpy2[a>>8])/val);
+ i<<=4;
+ i+= (15.9*(fpx1[a & 255]+fpx2[a>>8])/val);
+ centmask[a]= i;
+ }
+
+ MEM_freeN(fpx1);
+ MEM_freeN(fpx2);
+ MEM_freeN(fpy1);
+ MEM_freeN(fpy2);
+
+}
+
+void RE_free_filt_mask()
+{
+ int a;
+
+ for(a=0; a<9; a++) {
+ MEM_freeN(mask1[a]);
+ MEM_freeN(mask2[a]);
+ }
+ MEM_freeN(gamtab);
+ MEM_freeN(igamtab1);
+ MEM_freeN(igamtab2);
+
+ MEM_freeN(centmask);
+}
+
+/* add stuff */
+
+
+void defaultlamp()
+{
+ LampRen *lar;
+
+ lar= (LampRen *)MEM_callocN(sizeof(LampRen),"lampren");
+ R.la[R.totlamp++]=lar;
+
+ lar->type= LA_SUN;
+ lar->vec[0]= -R.viewmat[2][0];
+ lar->vec[1]= -R.viewmat[2][1];
+ lar->vec[2]= -R.viewmat[2][2];
+ Normalise(lar->vec);
+ lar->r= 1.0;
+ lar->g= 1.0;
+ lar->b= 1.0;
+ lar->lay= 65535;
+}
+
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+void RE_make_existing_file(char *name)
+{
+ char di[FILE_MAXDIR], fi[FILE_MAXFILE];
+
+ strcpy(di, name);
+ BLI_splitdirstring(di, fi);
+
+ /* exist testen */
+ if (BLI_exists(di) == 0) {
+ BLI_recurdir_fileops(di);
+ }
+}
+
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+extern float holoofs; /* render.c */
+void RE_setwindowclip(int mode, int jmode)
+{
+ /* jmode>=0: alleen jitter doen, anders berekenen */
+ /* mode==1 zet persmat en grvec */
+ Camera *cam=0;
+ float lens, fac, minx, miny, maxx, maxy;
+ float xd, yd, afmx, afmy;
+
+ if(G.scene->camera==0) return;
+
+ afmx= R.afmx;
+ afmy= R.afmy;
+
+ if(mode) {
+
+ if(G.scene->camera->type==OB_LAMP) {
+ /* fac= cos( PI*((float)(256- la->spsi))/512.0 ); */
+
+ /* phi= acos(fac); */
+ /* lens= 16.0*fac/sin(phi); */
+ lens= 35.0;
+ R.near= 0.1;
+ R.far= 1000.0;
+ }
+ else if(G.scene->camera->type==OB_CAMERA) {
+ cam= G.scene->camera->data;
+
+ lens= cam->lens;
+ R.near= cam->clipsta;
+ R.far= cam->clipend;
+ }
+ else {
+ lens= 16.0;
+ }
+
+ if( (R.r.xasp*afmx) >= (R.r.yasp*afmy) ) {
+ R.viewfac= (afmx*lens)/16.0;
+ }
+ else {
+ R.viewfac= R.ycor*(afmy*lens)/16.0;
+ }
+ if(R.r.mode & R_ORTHO) {
+ R.near*= 100.0; /* R.far niet doen */
+ R.viewfac*= 100.0;
+ }
+
+ R.pixsize= R.near/R.viewfac;
+
+ }
+
+ /* I think these offsets are wrong. They do not coincide with shadow */
+ /* calculations, btw. */
+ minx= R.xstart+.5;
+ miny= R.ycor*(R.ystart+.5);
+ maxx= R.xend+.4999;
+ maxy= R.ycor*(R.yend+.4999);
+ /* My guess: (or rather, what should be) */
+/* minx= R.xstart - 0.5; */
+/* miny= R.ycor * (R.ystart - 0.5); */
+ /* Since the SCS-s map directly to the pixel center coordinates, we need */
+ /* to stretch the clip area a bit, not just shift it. However, this gives*/
+ /* nasty problems for parts... */
+
+ if(R.flag & R_SEC_FIELD) {
+ if(R.r.mode & R_ODDFIELD) {
+ miny-= .5*R.ycor;
+ maxy-= .5*R.ycor;
+ }
+ else {
+ miny+= .5*R.ycor;
+ maxy+= .5*R.ycor;
+ }
+ }
+
+ xd= yd= 0.0;
+ if(jmode!= -1) {
+ xd= jit[jmode % R.osa][0];
+ yd= R.ycor*jit[jmode % R.osa][1];
+
+ }
+
+ if(G.special1 & G_HOLO) {
+ if(G.scene->camera->type==OB_CAMERA) {
+ cam= G.scene->camera->data;
+ if(cam->flag & CAM_HOLO2) {
+
+ if(cam->netend==0.0) cam->netend= (G.scene->r.efra);
+
+ fac= ((G.scene->r.cfra)-1.0)/(cam->netend)-0.5;
+ fac*= (R.rectx);
+ fac*= cam->hololen1;
+
+ holoofs= -fac;
+ minx-= fac;
+ maxx-= fac;
+ }
+ }
+ }
+
+ minx= R.pixsize*(minx+xd);
+ maxx= R.pixsize*(maxx+xd);
+ miny= R.pixsize*(miny+yd);
+ maxy= R.pixsize*(maxy+yd);
+
+ if(R.r.mode & R_ORTHO) {
+ /* hier de near & far vermenigvuldigen is voldoende! */
+
+ i_window(minx, maxx, miny, maxy, R.near, 100.0*R.far, R.winmat);
+ }
+ else i_window(minx, maxx, miny, maxy, R.near, R.far, R.winmat);
+
+}
+
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+void initparts()
+{
+ short nr, xd, yd, xpart, ypart, xparts, yparts;
+ short a, xminb, xmaxb, yminb, ymaxb;
+
+ if(R.r.mode & R_BORDER) {
+ xminb= R.r.border.xmin*R.rectx;
+ xmaxb= R.r.border.xmax*R.rectx;
+
+ yminb= R.r.border.ymin*R.recty;
+ ymaxb= R.r.border.ymax*R.recty;
+
+ if(xminb<0) xminb= 0;
+ if(xmaxb>R.rectx) xmaxb= R.rectx;
+ if(yminb<0) yminb= 0;
+ if(ymaxb>R.recty) ymaxb= R.recty;
+ }
+ else {
+ xminb=yminb= 0;
+ xmaxb= R.rectx;
+ ymaxb= R.recty;
+ }
+
+ xparts= R.r.xparts; /* voor border */
+ yparts= R.r.yparts;
+
+ for(nr=0;nr<xparts*yparts;nr++)
+ allparts[nr][0]= -1; /* array leegmaken */
+
+ xpart= R.rectx/xparts;
+ ypart= R.recty/yparts;
+
+ /* als border: testen of aantal parts minder kan */
+ if(R.r.mode & R_BORDER) {
+ a= (xmaxb-xminb-1)/xpart+1; /* zoveel parts in border */
+ if(a<xparts) xparts= a;
+ a= (ymaxb-yminb-1)/ypart+1; /* zoveel parts in border */
+ if(a<yparts) yparts= a;
+
+ xpart= (xmaxb-xminb)/xparts;
+ ypart= (ymaxb-yminb)/yparts;
+ }
+
+ for(nr=0; nr<xparts*yparts; nr++) {
+
+ if(R.r.mode & R_PANORAMA) {
+ allparts[nr][0]= 0;
+ allparts[nr][1]= 0;
+ allparts[nr][2]= R.rectx;
+ allparts[nr][3]= R.recty;
+ }
+ else {
+ xd= (nr % xparts);
+ yd= (nr-xd)/xparts;
+
+ allparts[nr][0]= xminb+ xd*xpart;
+ allparts[nr][1]= yminb+ yd*ypart;
+ if(xd<R.r.xparts-1) allparts[nr][2]= allparts[nr][0]+xpart;
+ else allparts[nr][2]= xmaxb;
+ if(yd<R.r.yparts-1) allparts[nr][3]= allparts[nr][1]+ypart;
+ else allparts[nr][3]= ymaxb;
+
+ if(allparts[nr][2]-allparts[nr][0]<=0) allparts[nr][0]= -1;
+ if(allparts[nr][3]-allparts[nr][1]<=0) allparts[nr][0]= -1;
+ }
+ }
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+short setpart(short nr) /* return 0 als geen goede part */
+{
+
+ if(allparts[nr][0]== -1) return 0;
+
+ R.xstart= allparts[nr][0]-R.afmx;
+ R.ystart= allparts[nr][1]-R.afmy;
+ R.xend= allparts[nr][2]-R.afmx;
+ R.yend= allparts[nr][3]-R.afmy;
+ R.rectx= R.xend-R.xstart;
+ R.recty= R.yend-R.ystart;
+
+ return 1;
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+void addparttorect(short nr, Part *part)
+{
+ unsigned int *rt, *rp;
+ short y, heigth, len;
+
+ /* de juiste offset in rectot */
+
+ rt= R.rectot+ (allparts[nr][1]*R.rectx+ allparts[nr][0]);
+ rp= part->rect;
+ len= (allparts[nr][2]-allparts[nr][0]);
+ heigth= (allparts[nr][3]-allparts[nr][1]);
+
+ for(y=0;y<heigth;y++) {
+ memcpy(rt, rp, 4*len);
+ rt+=R.rectx;
+ rp+= len;
+ }
+}
+
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+
+void RE_holoview()
+{
+ Camera *cam;
+ float dist, fac, fy, fz;
+
+ if(G.scene==0 || G.scene->camera==0) return;
+
+ if(G.scene->camera->type==OB_CAMERA) {
+ cam= G.scene->camera->data;
+ if(cam->flag & (CAM_HOLO1|CAM_HOLO2)) {
+ fy= G.scene->camera->loc[1];
+ fz= G.scene->camera->loc[2];
+ dist= cam->hololen*sqrt( fy*fy+ fz*fz );
+
+ fac= ((G.scene->r.cfra)-(G.scene->r.sfra))/((float)((G.scene->r.efra)-(G.scene->r.sfra)));
+
+ G.scene->camera->loc[0]= -dist+ 2*fac*dist;
+ }
+ }
+}
+
+void add_to_blurbuf(int blur)
+{
+ static unsigned int *blurrect= 0;
+ int tot, gamval;
+ short facr, facb;
+ char *rtr, *rtb;
+
+ if(blur<0) {
+ if(blurrect) {
+ if(R.rectot) MEM_freeN(R.rectot);
+ R.rectot= blurrect;
+ blurrect= 0;
+ }
+ }
+ else if(blur==R.osa-1) {
+ /* eerste keer */
+ blurrect= MEM_mallocN(R.rectx*R.recty*sizeof(int), "rectblur");
+ if(R.rectot) memcpy(blurrect, R.rectot, R.rectx*R.recty*4);
+ }
+ else if(blurrect) {
+ /* accumuleren */
+
+ facr= 256/(R.osa-blur);
+ facb= 256-facr;
+
+ if(R.rectot) {
+ rtr= (char *)R.rectot;
+ rtb= (char *)blurrect;
+ tot= R.rectx*R.recty;
+ while(tot--) {
+ if( *((unsigned int *)rtb) != *((unsigned int *)rtr) ) {
+
+ if(R.r.mode & R_GAMMA) {
+ gamval= (facr* igamtab2[ rtr[0]<<8 ] + facb* igamtab2[ rtb[0]<<8 ])>>8;
+ rtb[0]= gamtab[ gamval ]>>8;
+ gamval= (facr* igamtab2[ rtr[1]<<8 ] + facb* igamtab2[ rtb[1]<<8 ])>>8;
+ rtb[1]= gamtab[ gamval ]>>8;
+ gamval= (facr* igamtab2[ rtr[2]<<8 ] + facb* igamtab2[ rtb[2]<<8 ])>>8;
+ rtb[2]= gamtab[ gamval ]>>8;
+ gamval= (facr* igamtab2[ rtr[3]<<8 ] + facb* igamtab2[ rtb[3]<<8 ])>>8;
+ rtb[3]= gamtab[ gamval ]>>8;
+ }
+ else {
+ rtb[0]= (facr*rtr[0] + facb*rtb[0])>>8;
+ rtb[1]= (facr*rtr[1] + facb*rtb[1])>>8;
+ rtb[2]= (facr*rtr[2] + facb*rtb[2])>>8;
+ rtb[3]= (facr*rtr[3] + facb*rtb[3])>>8;
+ }
+ }
+ rtr+= 4;
+ rtb+= 4;
+ }
+ }
+ if(blur==0) {
+ /* laatste keer */
+ if(R.rectot) MEM_freeN(R.rectot);
+ R.rectot= blurrect;
+ blurrect= 0;
+ }
+ }
+}
+
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+void render() {
+ /* not too neat... should improve... */
+ if(R.r.mode & R_UNIFIED) {
+ unifiedRenderingLoop();
+ } else {
+ oldRenderLoop();
+ }
+}
+
+
+void oldRenderLoop(void) /* hierbinnen de PART en FIELD lussen */
+{
+ Part *part;
+ unsigned int *rt, *rt1, *rt2;
+ int len, y;
+ short blur, a,fields,fi,parts; /* pa is globaal ivm print */
+ unsigned int *border_buf= NULL;
+ unsigned int border_x= 0;
+ unsigned int border_y= 0;
+
+ if((R.r.mode & R_BORDER) && !(R.r.mode & R_MOVIECROP)) {
+ border_buf= R.rectot;
+ border_x= R.rectx;
+ border_y= R.recty;
+ R.rectot= 0;
+ }
+
+
+ if (R.rectz) MEM_freeN(R.rectz);
+ R.rectz = 0;
+
+ /* FIELDLUS */
+ fields= 1;
+ parts= R.r.xparts*R.r.yparts;
+
+ if(R.r.mode & R_FIELDS) {
+ fields= 2;
+ R.rectf1= R.rectf2= 0; /* fieldrecten */
+ R.r.ysch/= 2;
+ R.afmy/= 2;
+ R.r.yasp*= 2;
+ R.ycor= ( (float)R.r.yasp)/( (float)R.r.xasp);
+
+ }
+
+
+ for(fi=0; fi<fields; fi++) {
+
+ /* INIT */
+ BLI_srand( 2*(G.scene->r.cfra)+fi);
+
+
+ R.vlaknr= -1;
+ R.flag|= R_RENDERING;
+ if(fi==1) R.flag |= R_SEC_FIELD;
+
+
+ /* MOTIONBLUR lus */
+ if(R.r.mode & R_MBLUR) blur= R.osa;
+ else blur= 1;
+
+
+ while(blur--) {
+
+ /* WINDOW */
+ R.rectx= R.r.xsch;
+ R.recty= R.r.ysch;
+ R.xstart= -R.afmx;
+ R.ystart= -R.afmy;
+ R.xend= R.xstart+R.rectx-1;
+ R.yend= R.ystart+R.recty-1;
+
+
+ if(R.r.mode & R_MBLUR) set_mblur_offs(R.osa-blur);
+
+ initparts(); /* altijd doen ivm border */
+ setpart(0);
+
+ RE_local_init_render_display();
+ RE_local_clear_render_display(R.win);
+ RE_local_timecursor((G.scene->r.cfra));
+
+ prepareScene();
+
+ /* PARTS */
+ R.parts.first= R.parts.last= 0;
+ for(pa=0; pa<parts; pa++) {
+
+ if(RE_local_test_break()) break;
+
+ if(pa) { /* want pa==0 is al gedaan */
+ if(setpart(pa)==0) break;
+ }
+
+ if(R.r.mode & R_MBLUR) RE_setwindowclip(0, blur);
+ else RE_setwindowclip(0,-1);
+
+ if(R.r.mode & R_PANORAMA) setPanoRot(pa);
+
+ /* HOMOGENE COORDINATEN EN ZBUF EN CLIP OPT (per part) */
+ /* There may be some interference with z-coordinate */
+ /* calculation here? */
+
+ doClipping(RE_projectverto);
+ if(RE_local_test_break()) break;
+
+
+ /* ZBUFFER & SHADE: zbuffer stores int distances, int face indices */
+ R.rectot= (unsigned int *)MEM_callocN(sizeof(int)*R.rectx*R.recty, "rectot");
+ R.rectz = (unsigned int *)MEM_mallocN(sizeof(int)*R.rectx*R.recty, "rectz");
+
+ if(R.r.mode & R_MBLUR) RE_local_printrenderinfo(0.0, R.osa - blur);
+ else RE_local_printrenderinfo(0.0, -1);
+
+ /* choose render pipeline type, and whether or not to use the */
+ /* delta accumulation buffer. 3 choices. */
+ if(R.r.mode & R_OSA) zbufshadeDA();
+ else zbufshade();
+
+ if(RE_local_test_break()) break;
+
+ /* uitzondering */
+ if( (R.r.mode & R_BORDER) && (R.r.mode & R_MOVIECROP));
+ else {
+ /* PART OF BORDER AFHANDELEN */
+ if(parts>1 || (R.r.mode & R_BORDER)) {
+
+ part= MEM_callocN(sizeof(Part), "part");
+ BLI_addtail(&R.parts, part);
+ part->rect= R.rectot;
+ R.rectot= 0;
+
+ if (R.rectz) {
+ MEM_freeN(R.rectz);
+ R.rectz= 0;
+ }
+ }
+ }
+ }
+
+ /* PARTS SAMENVOEGEN OF BORDER INVOEGEN */
+
+ /* uitzondering: crop */
+ if( (R.r.mode & R_BORDER) && (R.r.mode & R_MOVIECROP)) ;
+ else {
+ R.rectx= R.r.xsch;
+ R.recty= R.r.ysch;
+
+ if(R.r.mode & R_PANORAMA) R.rectx*= R.r.xparts;
+
+ if(parts>1 || (R.r.mode & R_BORDER)) {
+ if(R.rectot) MEM_freeN(R.rectot);
+ if(R.r.mode & R_BORDER) {
+ if(border_x<R.rectx || border_y<R.recty || border_buf==NULL)
+ R.rectot= (unsigned int *)MEM_callocN(sizeof(int)*R.rectx*R.recty, "rectot");
+ else
+ R.rectot= border_buf;
+ }
+ else R.rectot=(unsigned int *)MEM_mallocN(sizeof(int)*R.rectx*R.recty, "rectot");
+
+ part= R.parts.first;
+ for(pa=0; pa<parts; pa++) {
+ if(allparts[pa][0]== -1) break;
+ if(part==0) break;
+
+ if(R.r.mode & R_PANORAMA) {
+ if(pa) {
+ allparts[pa][0] += pa*R.r.xsch;
+ allparts[pa][2] += pa*R.r.xsch;
+ }
+ }
+ addparttorect(pa, part);
+
+ part= part->next;
+ }
+
+ part= R.parts.first;
+ while(part) {
+ MEM_freeN(part->rect);
+ part= part->next;
+ }
+ BLI_freelistN(&R.parts);
+ }
+ }
+
+ if( (R.flag & R_HALO)) {
+ add_halo_flare();
+ }
+
+ if(R.r.mode & R_MBLUR) {
+ add_to_blurbuf(blur);
+ }
+
+ /* EINDE (blurlus) */
+ finalizeScene();
+
+ if(RE_local_test_break()) break;
+ }
+
+ /* definitief vrijgeven */
+ add_to_blurbuf(-1);
+
+ /* FIELD AFHANDELEN */
+ if(R.r.mode & R_FIELDS) {
+ if(R.flag & R_SEC_FIELD) R.rectf2= R.rectot;
+ else R.rectf1= R.rectot;
+ R.rectot= 0;
+ }
+
+ if(RE_local_test_break()) break;
+ }
+
+ /* FIELDS SAMENVOEGEN */
+ if(R.r.mode & R_FIELDS) {
+ R.r.ysch*= 2;
+ R.afmy*= 2;
+ R.recty*= 2;
+ R.r.yasp/=2;
+
+ if(R.rectot) MEM_freeN(R.rectot); /* komt voor bij afbreek */
+ R.rectot=(unsigned int *)MEM_mallocN(sizeof(int)*R.rectx*R.recty, "rectot");
+
+ if(RE_local_test_break()==0) {
+ rt= R.rectot;
+
+ if(R.r.mode & R_ODDFIELD) {
+ rt2= R.rectf1;
+ rt1= R.rectf2;
+ }
+ else {
+ rt1= R.rectf1;
+ rt2= R.rectf2;
+ }
+
+ len= 4*R.rectx;
+
+ for(a=0; a<R.recty; a+=2) {
+ memcpy(rt, rt1, len);
+ rt+= R.rectx;
+ rt1+= R.rectx;
+ memcpy(rt, rt2, len);
+ rt+= R.rectx;
+ rt2+= R.rectx;
+ }
+ }
+ }
+
+ /* R.rectx= R.r.xsch; */
+ /* if(R.r.mode & R_PANORAMA) R.rectx*= R.r.xparts; */
+ /* R.recty= R.r.ysch; */
+
+ /* als border: wel de skybuf doen */
+ if(R.r.mode & R_BORDER) {
+ if( (R.r.mode & R_MOVIECROP)==0) {
+ if(R.r.bufflag & 1) {
+ R.xstart= -R.afmx;
+ R.ystart= -R.afmy;
+ rt= R.rectot;
+ for(y=0; y<R.recty; y++, rt+= R.rectx) scanlinesky((char *)rt, y);
+ }
+ }
+ }
+
+ set_mblur_offs(0);
+
+ /* VRIJGEVEN */
+
+ /* zbuf test */
+
+ /* don't free R.rectz, only when its size is not the same as R.rectot */
+
+ if (R.rectz && parts == 1 && (R.r.mode & R_FIELDS) == 0);
+ else {
+ if(R.rectz) MEM_freeN(R.rectz);
+ R.rectz= 0;
+ }
+
+ if(R.rectf1) MEM_freeN(R.rectf1);
+ R.rectf1= 0;
+ if(R.rectf2) MEM_freeN(R.rectf2);
+ R.rectf2= 0;
+}
+
+
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+extern unsigned short usegamtab;
+void RE_initrender(struct View3D *ogl_render_view3d)
+{
+ double start_time;
+ Image *bima;
+ char name[256];
+
+ /* scenedata naar R */
+ R.r= G.scene->r;
+ R.r.postigamma= 1.0/R.r.postgamma;
+
+ /* voor zekerheid: bij voortijdige return */
+ R.rectx= R.r.xsch;
+ R.recty= R.r.ysch;
+
+ /* MAG ER WEL WORDEN GERENDERD */
+
+ /* verboden combinatie */
+ if((R.r.mode & R_BORDER) && (R.r.mode & R_PANORAMA)) {
+ error("No border allowed for Panorama");
+ G.afbreek= 1;
+ return;
+ }
+
+
+ if(R.r.xparts*R.r.yparts>64) {
+ error("No more than 64 parts");
+ G.afbreek= 1;
+ return;
+ }
+
+ if(R.r.yparts>1 && (R.r.mode & R_PANORAMA)) {
+ error("No Y-Parts allowed for Panorama");
+ G.afbreek= 1;
+ return;
+ }
+
+
+ /* BACKBUF TESTEN */
+ /* If an image is specified for use as backdrop, that image is loaded */
+ /* here. */
+ if((R.r.bufflag & 1) && (G.scene->r.scemode & R_OGL)==0) {
+ if(R.r.alphamode == R_ADDSKY) {
+ strcpy(name, R.r.backbuf);
+ BLI_convertstringcode(name, G.sce, G.scene->r.cfra);
+
+ if(R.backbuf) {
+ R.backbuf->id.us--;
+ bima= R.backbuf;
+ }
+ else bima= 0;
+
+ R.backbuf= add_image(name);
+
+ if(bima && bima->id.us<1) {
+ free_image_buffers(bima);
+ }
+ if(R.backbuf==0) {
+ error("No backbuf there!");
+ G.afbreek= 1;
+ return;
+ }
+ }
+ }
+
+
+ usegamtab= 0; /* zie hieronder */
+
+ if(R.r.mode & (R_OSA|R_MBLUR)) {
+ R.osa= R.r.osa;
+ if(R.osa>16) R.osa= 16;
+
+ init_render_jit(R.osa);
+ RE_init_filt_mask();
+
+ /* wordt af en toe tijdelijk op nul gezet, o.a. in transp zbuf */
+ if(R.r.mode & R_GAMMA) {
+ if((R.r.mode & R_OSA)) usegamtab= 1;
+ }
+ }
+ else R.osa= 0;
+
+ /* WINDOW */
+ R.r.xsch= (R.r.size*R.r.xsch)/100;
+ R.r.ysch= (R.r.size*R.r.ysch)/100;
+
+ R.afmx= R.r.xsch/2;
+ R.afmy= R.r.ysch/2;
+
+ /* when rendered without camera object */
+ /* it has to done here because of envmaps */
+ R.near= 0.1;
+ R.far= 1000.0;
+
+
+ if(R.afmx<1 || R.afmy<1) {
+ error("Image too small");
+ return;
+ }
+ R.ycor= ( (float)R.r.yasp)/( (float)R.r.xasp);
+
+ start_time= PIL_check_seconds_timer();
+
+ if(R.r.scemode & R_DOSEQ) {
+ R.rectx= R.r.xsch;
+ R.recty= R.r.ysch;
+
+ if(R.rectot) MEM_freeN(R.rectot);
+ R.rectot= (unsigned int *)MEM_callocN(sizeof(int)*R.rectx*R.recty, "rectot");
+
+ RE_local_timecursor((G.scene->r.cfra));
+
+ if(RE_local_test_break()==0) do_render_seq();
+
+ /* displayen */
+ if(R.rectot) RE_local_render_display(0, R.recty-1,
+ R.rectx, R.recty,
+ R.rectot);
+ }
+ else if(R.r.scemode & R_OGL) {
+ R.rectx= R.r.xsch;
+ R.recty= R.r.ysch;
+
+ if(R.rectot) MEM_freeN(R.rectot);
+ R.rectot= (unsigned int *)MEM_callocN(sizeof(int)*R.rectx*R.recty, "rectot");
+
+ RE_local_init_render_display();
+ drawview3d_render(ogl_render_view3d);
+ }
+ else {
+ if(G.scene->camera==0) {
+ G.scene->camera= scene_find_camera(G.scene);
+ }
+
+ if(G.scene->camera==0) {
+ error("No camera");
+ G.afbreek=1;
+ return;
+ }
+ else {
+
+ if(G.scene->camera->type==OB_CAMERA) {
+ Camera *cam= G.scene->camera->data;
+ if(cam->type==CAM_ORTHO) R.r.mode |= R_ORTHO;
+ }
+
+ render(); /* keert terug met complete rect xsch-ysch */
+ }
+ }
+
+ /* nog eens displayen: fields/seq/parts/pano etc */
+ if(R.rectot) {
+ RE_local_init_render_display();
+ RE_local_render_display(0, R.recty-1,
+ R.rectx, R.recty,
+ R.rectot);
+ }
+ else RE_local_clear_render_display(R.win);
+
+ RE_local_printrenderinfo((PIL_check_seconds_timer() - start_time), -1);
+
+ /* variabelen weer goed */
+ R.osatex= 0;
+ R.vlr= 0; /* bij cubemap */
+ R.flag= 0;
+}
+
+void RE_animrender(struct View3D *ogl_render_view3d)
+{
+ int cfrao;
+ char name[256];
+
+ if(G.scene==0) return;
+
+ /* scenedata naar R: (voor backbuf, R.rectx enz) */
+ R.r= G.scene->r;
+
+ /* START ANIMLUS overal wordt NIET de cfra uit R.r gebruikt: ivm rest blender */
+ cfrao= (G.scene->r.cfra);
+
+ if(G.scene->r.scemode & R_OGL) R.r.mode &= ~R_PANORAMA;
+
+ // these calculations apply for
+ // all movie formats
+ R.rectx= (R.r.size*R.r.xsch)/100;
+ R.recty= (R.r.size*R.r.ysch)/100;
+ if(R.r.mode & R_PANORAMA) {
+ R.rectx*= R.r.xparts;
+ R.recty*= R.r.yparts;
+ }
+
+ if (0) {
+#ifdef __sgi
+ } else if (R.r.imtype==R_MOVIE) {
+ start_movie();
+#endif
+#ifdef _WIN32
+ } else if (R.r.imtype == R_AVICODEC) {
+ start_avi_codec();
+#endif
+ } else if ELEM4(R.r.imtype, R_AVIRAW, R_AVIJPEG, R_MOVIE, R_AVICODEC) {
+ if ELEM(R.r.imtype, R_MOVIE, R_AVICODEC) {
+ printf("Selected movie format not supported on this platform,\nusing RAW AVI instead\n");
+ }
+ start_avi();
+ }
+
+ for((G.scene->r.cfra)=(G.scene->r.sfra); (G.scene->r.cfra)<=(G.scene->r.efra); (G.scene->r.cfra)++) {
+ double starttime= PIL_check_seconds_timer();
+
+ R.flag= R_ANIMRENDER;
+
+ RE_initrender(ogl_render_view3d);
+
+ /* SCHRIJF PLAATJE */
+ if(RE_local_test_break()==0) {
+
+ if (0) {
+#ifdef __sgi
+ } else if (R.r.imtype == R_MOVIE) {
+ append_movie((G.scene->r.cfra));
+#endif
+#ifdef _WIN32
+ } else if (R.r.imtype == R_AVICODEC) {
+ append_avi_codec((G.scene->r.cfra));
+#endif
+ } else if ELEM4(R.r.imtype, R_AVIRAW, R_AVIJPEG, R_MOVIE, R_AVICODEC) {
+ append_avi((G.scene->r.cfra));
+ } else {
+ makepicstring(name, (G.scene->r.cfra));
+ schrijfplaatje(name);
+ if(RE_local_test_break()==0) printf("Saved: %s", name);
+ }
+
+ timestr(PIL_check_seconds_timer()-starttime, name);
+ printf(" Time: %s\n", name);
+ fflush(stdout); /* nodig voor renderd !! */
+ }
+
+ if(G.afbreek==1) break;
+
+ }
+
+ (G.scene->r.cfra)= cfrao;
+
+ /* restoren tijd */
+ if(R.r.mode & (R_FIELDS|R_MBLUR)) {
+ do_all_ipos();
+ do_all_keys();
+ do_all_actions();
+ do_all_ikas();
+ }
+
+ if (0) {
+#ifdef __sgi
+ } else if (R.r.imtype==R_MOVIE) {
+ end_movie();
+#endif
+#ifdef _WIN32
+ } else if (R.r.imtype == R_AVICODEC) {
+ end_avi_codec();
+#endif
+ } else if ELEM4(R.r.imtype, R_AVIRAW, R_AVIJPEG, R_MOVIE, R_AVICODEC) {
+ end_avi();
+ }
+}
+
+/* *************************************************** */
+/* ******************* Screendumps ******************** */
+/* moved to the windowControl thing */
diff --git a/source/blender/render/intern/source/jitter.c b/source/blender/render/intern/source/jitter.c
new file mode 100644
index 00000000000..19311132a7e
--- /dev/null
+++ b/source/blender/render/intern/source/jitter.c
@@ -0,0 +1,192 @@
+/**
+ * Jitter offset table
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include "MEM_guardedalloc.h"
+
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+#include "render.h"
+#include "render_intern.h"
+#include "jitter.h"
+
+float jit[64][2];
+
+void init_render_jit(int nr);
+
+
+void RE_jitterate1(float *jit1, float *jit2, int num, float rad1)
+{
+ int i , j , k;
+ float vecx, vecy, dvecx, dvecy, x, y, len;
+
+ for (i = 2*num-2; i>=0 ; i-=2) {
+ dvecx = dvecy = 0.0;
+ x = jit1[i];
+ y = jit1[i+1];
+ for (j = 2*num-2; j>=0 ; j-=2) {
+ if (i != j){
+ vecx = jit1[j] - x - 1.0;
+ vecy = jit1[j+1] - y - 1.0;
+ for (k = 3; k>0 ; k--){
+ if( fabs(vecx)<rad1 && fabs(vecy)<rad1) {
+ len= sqrt(vecx*vecx + vecy*vecy);
+ if(len>0 && len<rad1) {
+ len= len/rad1;
+ dvecx += vecx/len;
+ dvecy += vecy/len;
+ }
+ }
+ vecx += 1.0;
+
+ if( fabs(vecx)<rad1 && fabs(vecy)<rad1) {
+ len= sqrt(vecx*vecx + vecy*vecy);
+ if(len>0 && len<rad1) {
+ len= len/rad1;
+ dvecx += vecx/len;
+ dvecy += vecy/len;
+ }
+ }
+ vecx += 1.0;
+
+ if( fabs(vecx)<rad1 && fabs(vecy)<rad1) {
+ len= sqrt(vecx*vecx + vecy*vecy);
+ if(len>0 && len<rad1) {
+ len= len/rad1;
+ dvecx += vecx/len;
+ dvecy += vecy/len;
+ }
+ }
+ vecx -= 2.0;
+ vecy += 1.0;
+ }
+ }
+ }
+
+ x -= dvecx/18.0 ;
+ y -= dvecy/18.0;
+ x -= floor(x) ;
+ y -= floor(y);
+ jit2[i] = x;
+ jit2[i+1] = y;
+ }
+ memcpy(jit1,jit2,2 * num * sizeof(float));
+}
+
+void RE_jitterate2(float *jit1, float *jit2, int num, float rad2)
+{
+ int i, j;
+ float vecx, vecy, dvecx, dvecy, x, y;
+
+ for (i=2*num -2; i>= 0 ; i-=2){
+ dvecx = dvecy = 0.0;
+ x = jit1[i];
+ y = jit1[i+1];
+ for (j =2*num -2; j>= 0 ; j-=2){
+ if (i != j){
+ vecx = jit1[j] - x - 1.0;
+ vecy = jit1[j+1] - y - 1.0;
+
+ if( fabs(vecx)<rad2) dvecx+= vecx*rad2;
+ vecx += 1.0;
+ if( fabs(vecx)<rad2) dvecx+= vecx*rad2;
+ vecx += 1.0;
+ if( fabs(vecx)<rad2) dvecx+= vecx*rad2;
+
+ if( fabs(vecy)<rad2) dvecy+= vecy*rad2;
+ vecy += 1.0;
+ if( fabs(vecy)<rad2) dvecy+= vecy*rad2;
+ vecy += 1.0;
+ if( fabs(vecy)<rad2) dvecy+= vecy*rad2;
+
+ }
+ }
+
+ x -= dvecx/2 ;
+ y -= dvecy/2;
+ x -= floor(x) ;
+ y -= floor(y);
+ jit2[i] = x;
+ jit2[i+1] = y;
+ }
+ memcpy(jit1,jit2,2 * num * sizeof(float));
+}
+
+
+void initjit(float *jit, int num)
+{
+ float *jit2, x, rad1, rad2, rad3;
+ int i;
+
+ if(num==0) return;
+
+ jit2= MEM_mallocN(12 + 2*sizeof(float)*num, "initjit");
+ rad1= 1.0/sqrt((float)num);
+ rad2= 1.0/((float)num);
+ rad3= sqrt((float)num)/((float)num);
+
+ BLI_srand(31415926 + num);
+ x= 0;
+ for(i=0; i<2*num; i+=2) {
+ jit[i]= x+ rad1*(0.5-BLI_drand());
+ jit[i+1]= ((float)i/2)/num +rad1*(0.5-BLI_drand());
+ x+= rad3;
+ x -= floor(x);
+ }
+
+ for (i=0 ; i<24 ; i++) {
+ RE_jitterate1(jit, jit2, num, rad1);
+ RE_jitterate1(jit, jit2, num, rad1);
+ RE_jitterate2(jit, jit2, num, rad2);
+ }
+
+ MEM_freeN(jit2);
+}
+
+void init_render_jit(int nr)
+{
+ static int lastjit= 0;
+
+ if(lastjit==nr) return;
+
+ memset(jit, 0, 64*2*4);
+ initjit(jit[0], nr);
+
+ lastjit= nr;
+
+}
+
+/* eof */
diff --git a/source/blender/render/intern/source/outerRenderLoop.c b/source/blender/render/intern/source/outerRenderLoop.c
new file mode 100644
index 00000000000..1e16fd251db
--- /dev/null
+++ b/source/blender/render/intern/source/outerRenderLoop.c
@@ -0,0 +1,515 @@
+/**
+ * The outer loop for rendering, but only for calling the
+ * unified renderer :)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+#include "BLI_blenlib.h"
+#include "BLI_rand.h"
+
+#include "BKE_global.h"
+#include "BKE_object.h"
+
+#include "render.h"
+#include "render_intern.h"
+#include "outerRenderLoop.h"
+#include "renderPreAndPost.h"
+#include "vanillaRenderPipe.h"
+#include "renderHelp.h"
+#include "RE_callbacks.h"
+
+extern short pa; /* can move to inside the outer loop */
+/* should make a gamtab module, just like the jitter... */
+extern unsigned short *mask1[9], *mask2[9], *igamtab2;
+
+
+/* Parts bookkeeping: done on this level, because it seems appropriate to me.*/
+static short partsCoordinates[65][4];
+short setPart(short nr);/* return 0 if this is a bad part. Sets data in R....*/
+void initParts(void);
+void addPartToRect(short nr, Part *part);
+void addToBlurBuffer(int blur);
+
+/* ------------------------------------------------------------------------- */
+void addToBlurBuffer(int blur)
+{
+ static unsigned int *blurrect= 0;
+ int tot, gamval;
+ short facr, facb;
+ char *rtr, *rtb;
+
+ if(blur<0) {
+ if(blurrect) {
+ if(R.rectot) MEM_freeN(R.rectot);
+ R.rectot= blurrect;
+ blurrect= 0;
+ }
+ }
+ else if(blur==R.osa-1) {
+ /* eerste keer */
+ blurrect= MEM_mallocN(R.rectx*R.recty*sizeof(int), "rectblur");
+ if(R.rectot) memcpy(blurrect, R.rectot, R.rectx*R.recty*4);
+ }
+ else if(blurrect) {
+ /* accumuleren */
+
+ facr= 256/(R.osa-blur);
+ facb= 256-facr;
+
+ if(R.rectot) {
+ rtr= (char *)R.rectot;
+ rtb= (char *)blurrect;
+ tot= R.rectx*R.recty;
+ while(tot--) {
+ if( *((unsigned int *)rtb) != *((unsigned int *)rtr) ) {
+
+ if(R.r.mode & R_GAMMA) {
+ gamval= (facr* igamtab2[ rtr[0]<<8 ] + facb* igamtab2[ rtb[0]<<8 ])>>8;
+ rtb[0]= gamtab[ gamval ]>>8;
+ gamval= (facr* igamtab2[ rtr[1]<<8 ] + facb* igamtab2[ rtb[1]<<8 ])>>8;
+ rtb[1]= gamtab[ gamval ]>>8;
+ gamval= (facr* igamtab2[ rtr[2]<<8 ] + facb* igamtab2[ rtb[2]<<8 ])>>8;
+ rtb[2]= gamtab[ gamval ]>>8;
+ gamval= (facr* igamtab2[ rtr[3]<<8 ] + facb* igamtab2[ rtb[3]<<8 ])>>8;
+ rtb[3]= gamtab[ gamval ]>>8;
+ }
+ else {
+ rtb[0]= (facr*rtr[0] + facb*rtb[0])>>8;
+ rtb[1]= (facr*rtr[1] + facb*rtb[1])>>8;
+ rtb[2]= (facr*rtr[2] + facb*rtb[2])>>8;
+ rtb[3]= (facr*rtr[3] + facb*rtb[3])>>8;
+ }
+ }
+ rtr+= 4;
+ rtb+= 4;
+ }
+ }
+ if(blur==0) {
+ /* laatste keer */
+ if(R.rectot) MEM_freeN(R.rectot);
+ R.rectot= blurrect;
+ blurrect= 0;
+ }
+ }
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+void addPartToRect(short nr, Part *part)
+{
+ unsigned int *rt, *rp;
+ short y, heigth, len;
+
+ /* de juiste offset in rectot */
+
+ rt= R.rectot+ (partsCoordinates[nr][1]*R.rectx+ partsCoordinates[nr][0]);
+ rp= part->rect;
+ len= (partsCoordinates[nr][2]-partsCoordinates[nr][0]);
+ heigth= (partsCoordinates[nr][3]-partsCoordinates[nr][1]);
+
+ for(y=0;y<heigth;y++) {
+ memcpy(rt, rp, 4*len);
+ rt+=R.rectx;
+ rp+= len;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+void initParts()
+{
+ short nr, xd, yd, xpart, ypart, xparts, yparts;
+ short a, xminb, xmaxb, yminb, ymaxb;
+
+ if(R.r.mode & R_BORDER) {
+ xminb= R.r.border.xmin*R.rectx;
+ xmaxb= R.r.border.xmax*R.rectx;
+
+ yminb= R.r.border.ymin*R.recty;
+ ymaxb= R.r.border.ymax*R.recty;
+
+ if(xminb<0) xminb= 0;
+ if(xmaxb>R.rectx) xmaxb= R.rectx;
+ if(yminb<0) yminb= 0;
+ if(ymaxb>R.recty) ymaxb= R.recty;
+ }
+ else {
+ xminb=yminb= 0;
+ xmaxb= R.rectx;
+ ymaxb= R.recty;
+ }
+
+ xparts= R.r.xparts; /* voor border */
+ yparts= R.r.yparts;
+
+ for(nr=0;nr<xparts*yparts;nr++)
+ partsCoordinates[nr][0]= -1; /* array leegmaken */
+
+ xpart= R.rectx/xparts;
+ ypart= R.recty/yparts;
+
+ /* als border: testen of aantal parts minder kan */
+ if(R.r.mode & R_BORDER) {
+ a= (xmaxb-xminb-1)/xpart+1; /* zoveel parts in border */
+ if(a<xparts) xparts= a;
+ a= (ymaxb-yminb-1)/ypart+1; /* zoveel parts in border */
+ if(a<yparts) yparts= a;
+
+ xpart= (xmaxb-xminb)/xparts;
+ ypart= (ymaxb-yminb)/yparts;
+ }
+
+ for(nr=0; nr<xparts*yparts; nr++) {
+
+ if(R.r.mode & R_PANORAMA) {
+ partsCoordinates[nr][0]= 0;
+ partsCoordinates[nr][1]= 0;
+ partsCoordinates[nr][2]= R.rectx;
+ partsCoordinates[nr][3]= R.recty;
+ }
+ else {
+ xd= (nr % xparts);
+ yd= (nr-xd)/xparts;
+
+ partsCoordinates[nr][0]= xminb+ xd*xpart;
+ partsCoordinates[nr][1]= yminb+ yd*ypart;
+ if(xd<R.r.xparts-1) partsCoordinates[nr][2]= partsCoordinates[nr][0]+xpart;
+ else partsCoordinates[nr][2]= xmaxb;
+ if(yd<R.r.yparts-1) partsCoordinates[nr][3]= partsCoordinates[nr][1]+ypart;
+ else partsCoordinates[nr][3]= ymaxb;
+
+ if(partsCoordinates[nr][2]-partsCoordinates[nr][0]<=0) partsCoordinates[nr][0]= -1;
+ if(partsCoordinates[nr][3]-partsCoordinates[nr][1]<=0) partsCoordinates[nr][0]= -1;
+ }
+ }
+}
+
+short setPart(short nr) /* return 0 als geen goede part */
+{
+
+ if(partsCoordinates[nr][0]== -1) return 0;
+
+ R.xstart= partsCoordinates[nr][0]-R.afmx;
+ R.ystart= partsCoordinates[nr][1]-R.afmy;
+ R.xend= partsCoordinates[nr][2]-R.afmx;
+ R.yend= partsCoordinates[nr][3]-R.afmy;
+ R.rectx= R.xend-R.xstart;
+ R.recty= R.yend-R.ystart;
+
+ return 1;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void unifiedRenderingLoop(void) /* hierbinnen de PART en FIELD lussen */
+{
+ Part *part;
+ unsigned int *rt, *rt1, *rt2;
+ int len;
+ short blur, a,fields,fi,parts; /* pa is globaal ivm print */
+ unsigned int *border_buf= NULL;
+ unsigned int border_x= 0;
+ unsigned int border_y= 0;
+
+ if((R.r.mode & R_BORDER) && !(R.r.mode & R_MOVIECROP)) {
+ border_buf= R.rectot;
+ border_x= R.rectx;
+ border_y= R.recty;
+ R.rectot= 0;
+ }
+
+
+ if (R.rectz) MEM_freeN(R.rectz);
+ R.rectz = 0;
+
+ /* FIELDLUS */
+ fields= 1;
+ parts= R.r.xparts*R.r.yparts;
+
+ if(R.r.mode & R_FIELDS) {
+ fields= 2;
+ R.rectf1= R.rectf2= 0; /* fieldrecten */
+ R.r.ysch/= 2;
+ R.afmy/= 2;
+ R.r.yasp*= 2;
+ R.ycor= ( (float)R.r.yasp)/( (float)R.r.xasp);
+
+ }
+
+
+ for(fi=0; fi<fields; fi++) {
+
+ /* INIT */
+ BLI_srand( 2*(G.scene->r.cfra)+fi);
+
+
+ R.vlaknr= -1;
+ R.flag|= R_RENDERING;
+ if(fi==1) R.flag |= R_SEC_FIELD;
+
+
+ /* MOTIONBLUR lus */
+ if(R.r.mode & R_MBLUR) blur= R.osa;
+ else blur= 1;
+
+
+ while(blur--) {
+
+ /* WINDOW */
+ R.rectx= R.r.xsch;
+ R.recty= R.r.ysch;
+ R.xstart= -R.afmx;
+ R.ystart= -R.afmy;
+ R.xend= R.xstart+R.rectx-1;
+ R.yend= R.ystart+R.recty-1;
+
+
+ if(R.r.mode & R_MBLUR) set_mblur_offs(R.osa-blur);
+
+ initParts(); /* altijd doen ivm border */
+ setPart(0);
+
+ RE_local_init_render_display();
+ RE_local_clear_render_display(R.win);
+ RE_local_timecursor((G.scene->r.cfra));
+
+ prepareScene();
+
+ /* PARTS */
+ R.parts.first= R.parts.last= 0;
+ for(pa=0; pa<parts; pa++) {
+
+ if(RE_local_test_break()) break;
+
+ if(pa) { /* want pa==0 is al gedaan */
+ if(setPart(pa)==0) break;
+ }
+
+ if(R.r.mode & R_MBLUR) RE_setwindowclip(0, blur);
+ else RE_setwindowclip(0,-1);
+
+ if(R.r.mode & R_PANORAMA) setPanoRot(pa);
+
+ /* HOMOGENE COORDINATEN EN ZBUF EN CLIP OPT (per part) */
+ /* There may be some interference with z-coordinate */
+ /* calculation here? */
+
+ doClipping(RE_projectverto);
+ if(RE_local_test_break()) break;
+
+
+ /* ZBUFFER & SHADE: zbuffer stores int distances, int face indices */
+ R.rectot= (unsigned int *)MEM_callocN(sizeof(int)*R.rectx*R.recty, "rectot");
+
+ if(R.r.mode & R_MBLUR) RE_local_printrenderinfo(0.0, R.osa - blur);
+ else RE_local_printrenderinfo(0.0, -1);
+
+ /* The inner loop */
+ zBufShadeAdvanced();
+
+ if(RE_local_test_break()) break;
+
+ /* uitzondering */
+ if( (R.r.mode & R_BORDER) && (R.r.mode & R_MOVIECROP));
+ else {
+ /* PART OF BORDER AFHANDELEN */
+ if(parts>1 || (R.r.mode & R_BORDER)) {
+
+ part= MEM_callocN(sizeof(Part), "part");
+ BLI_addtail(&R.parts, part);
+ part->rect= R.rectot;
+ R.rectot= 0;
+
+ if (R.rectz) {
+ MEM_freeN(R.rectz);
+ R.rectz= 0;
+ }
+ }
+ }
+ }
+
+ /* PARTS SAMENVOEGEN OF BORDER INVOEGEN */
+
+ /* uitzondering: crop */
+ if( (R.r.mode & R_BORDER) && (R.r.mode & R_MOVIECROP)) ;
+ else {
+ R.rectx= R.r.xsch;
+ R.recty= R.r.ysch;
+
+ if(R.r.mode & R_PANORAMA) R.rectx*= R.r.xparts;
+
+ if(parts>1 || (R.r.mode & R_BORDER)) {
+ if(R.rectot) MEM_freeN(R.rectot);
+ if(R.r.mode & R_BORDER) {
+ if(border_x<R.rectx || border_y<R.recty || border_buf==NULL)
+ R.rectot= (unsigned int *)MEM_callocN(sizeof(int)*R.rectx*R.recty, "rectot");
+ else
+ R.rectot= border_buf;
+ }
+ else R.rectot=(unsigned int *)MEM_mallocN(sizeof(int)*R.rectx*R.recty, "rectot");
+
+ part= R.parts.first;
+ for(pa=0; pa<parts; pa++) {
+ if(partsCoordinates[pa][0]== -1) break;
+ if(part==0) break;
+
+ if(R.r.mode & R_PANORAMA) {
+ if(pa) {
+ partsCoordinates[pa][0] += pa*R.r.xsch;
+ partsCoordinates[pa][2] += pa*R.r.xsch;
+ }
+ }
+ addPartToRect(pa, part);
+
+ part= part->next;
+ }
+
+ part= R.parts.first;
+ while(part) {
+ MEM_freeN(part->rect);
+ part= part->next;
+ }
+ BLI_freelistN(&R.parts);
+ }
+ }
+
+ /* don't do this for unified renderer? */
+/* if( (R.flag & R_HALO) && !G.magic) { */
+/* add_halo_flare(); */
+/* } */
+
+ if(R.r.mode & R_MBLUR) {
+ addToBlurBuffer(blur);
+ }
+
+ /* EINDE (blurlus) */
+ finalizeScene();
+
+ if(RE_local_test_break()) break;
+ }
+
+ /* definitief vrijgeven */
+ addToBlurBuffer(-1);
+
+ /* FIELD AFHANDELEN */
+ if(R.r.mode & R_FIELDS) {
+ if(R.flag & R_SEC_FIELD) R.rectf2= R.rectot;
+ else R.rectf1= R.rectot;
+ R.rectot= 0;
+ }
+
+ if(RE_local_test_break()) break;
+ }
+
+ /* FIELDS SAMENVOEGEN */
+ if(R.r.mode & R_FIELDS) {
+ R.r.ysch*= 2;
+ R.afmy*= 2;
+ R.recty*= 2;
+ R.r.yasp/=2;
+
+ if(R.rectot) MEM_freeN(R.rectot); /* komt voor bij afbreek */
+ R.rectot=(unsigned int *)MEM_mallocN(sizeof(int)*R.rectx*R.recty, "rectot");
+
+ if(RE_local_test_break()==0) {
+ rt= R.rectot;
+
+ if(R.r.mode & R_ODDFIELD) {
+ rt2= R.rectf1;
+ rt1= R.rectf2;
+ }
+ else {
+ rt1= R.rectf1;
+ rt2= R.rectf2;
+ }
+
+ len= 4*R.rectx;
+
+ for(a=0; a<R.recty; a+=2) {
+ memcpy(rt, rt1, len);
+ rt+= R.rectx;
+ rt1+= R.rectx;
+ memcpy(rt, rt2, len);
+ rt+= R.rectx;
+ rt2+= R.rectx;
+ }
+ }
+ }
+
+ /* R.rectx= R.r.xsch; */
+ /* if(R.r.mode & R_PANORAMA) R.rectx*= R.r.xparts; */
+ /* R.recty= R.r.ysch; */
+
+ /* als border: wel de skybuf doen */
+ /*
+ This may be tricky
+ */
+/* if(R.r.mode & R_BORDER) { */
+/* if( (R.r.mode & R_MOVIECROP)==0) { */
+/* if(R.r.bufflag & 1) { */
+/* R.xstart= -R.afmx; */
+/* R.ystart= -R.afmy; */
+/* rt= R.rectot; */
+/* for(y=0; y<R.recty; y++, rt+= R.rectx) scanLineSkyFloat((char *)rt, y); */
+/* } */
+/* } */
+/* } */
+
+ set_mblur_offs(0);
+
+ /* VRIJGEVEN */
+
+ /* zbuf test */
+
+ /* don't free R.rectz, only when its size is not the same as R.rectot */
+
+ if (R.rectz && parts == 1 && (R.r.mode & R_FIELDS) == 0);
+ else {
+ if(R.rectz) MEM_freeN(R.rectz);
+ R.rectz= 0;
+ }
+
+ if(R.rectf1) MEM_freeN(R.rectf1);
+ R.rectf1= 0;
+ if(R.rectf2) MEM_freeN(R.rectf2);
+ R.rectf2= 0;
+} /* End of void unifiedRenderingLoop()*/
+
+/* ------------------------------------------------------------------------- */
+
+/* eof */
+
diff --git a/source/blender/render/intern/source/pixelblending.c b/source/blender/render/intern/source/pixelblending.c
new file mode 100644
index 00000000000..4fa3703d865
--- /dev/null
+++ b/source/blender/render/intern/source/pixelblending.c
@@ -0,0 +1,919 @@
+/*
+ * pixelblending.c
+ *
+ * Functions to blend pixels with or without alpha, in various formats
+ * nzc - June 2000
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+
+/* global includes */
+#include "render.h"
+#include "render_intern.h"
+
+/* local includes */
+#include "vanillaRenderPipe_types.h"
+
+/* own includes */
+#include "pixelblending_types.h"
+#include "pixelblending.h"
+#include "gammaCorrectionTables.h"
+
+/* externals */
+
+/* ------------------------------------------------------------------------- */
+/* Debug/behaviour defines */
+/* if defined: alpha blending with floats clips colour, as with shorts */
+/* #define RE_FLOAT_COLOUR_CLIPPING */
+/* if defined: alpha values are clipped */
+/* For now, we just keep alpha clipping. We run into thresholding and */
+/* blending difficulties otherwise. Be careful here. */
+#define RE_ALPHA_CLIPPING
+
+/* functions --------------------------------------------------------------- */
+
+/*
+ One things about key-alpha is that simply dividing by the alpha will
+ sometimes cause 'overflows' in that the pixel colours will be shot
+ way over full colour. This should be caught, and subsequently, the
+ operation will end up modifying the alpha as well.
+
+ Actually, when the starting colour is premul, it shouldn't overflow
+ ever. Strange thing is that colours keep overflowing...
+
+*/
+void applyKeyAlphaCharCol(char* target) {
+
+ if ((!(target[3] == 0))
+ || (target[3] == 255)) {
+ /* else: nothing to do */
+ /* check whether div-ing is enough */
+ float cf[4];
+ cf[0] = target[0]/target[3];
+ cf[1] = target[1]/target[3];
+ cf[2] = target[2]/target[3];
+ if ((cf[0] <= 1.0) && (cf[1] <= 1.0) && (cf[2] <= 1.0)) {
+ /* all colours remain properly scaled? */
+ /* scale to alpha */
+ cf[0] = (float) target[0] * (255.0/ (float)target[3]);
+ cf[1] = (float) target[1] * (255.0/ (float)target[3]);
+ cf[2] = (float) target[2] * (255.0/ (float)target[3]);
+
+ /* Clipping is important. */
+ target[0] = (cf[0] > 255.0 ? 255 : (char) cf[0]);
+ target[1] = (cf[1] > 255.0 ? 255 : (char) cf[1]);
+ target[2] = (cf[2] > 255.0 ? 255 : (char) cf[2]);
+
+ } else {
+ /* shouldn't happen! we were premul, remember? */
+/* should go to error handler: printf("Non-premul colour detected\n"); */
+ }
+ }
+
+} /* end of void applyKeyAlphaCharCol(char* target) */
+
+/* ------------------------------------------------------------------------- */
+
+void addAddSampColF(float *sampvec, float *source, int mask, int osaNr,
+ char addfac)
+{
+ int a;
+
+ for(a=0; a < osaNr; a++) {
+ if(mask & (1<<a)) addalphaAddfacFloat(sampvec, source, addfac);
+ sampvec+= 4;
+ }
+} /* end of void addAddSampColF(float, float, int, int) */
+
+/* ------------------------------------------------------------------------- */
+
+void addOverSampColF(float *sampvec, float *source, int mask, int osaNr)
+{
+ int a;
+
+ for(a=0; a < osaNr; a++) {
+ if(mask & (1<<a)) addAlphaOverFloat(sampvec, source);
+ sampvec+= 4;
+ }
+} /* end of void addOverSampColF(float, float, int, int) */
+
+/* ------------------------------------------------------------------------- */
+
+int addUnderSampColF(float *sampvec, float *source, int mask, int osaNr)
+{
+ int a, retval = osaNr;
+
+ for(a=0; a < osaNr; a++) {
+ if(mask & (1<<a)) addAlphaUnderFloat(sampvec, source);
+ if(sampvec[3] > RE_FULL_COLOUR_FLOAT) retval--;
+ sampvec+= 4;
+ }
+ return retval;
+} /* end of int addToSampColF(float, float, int, int) */
+
+/* ------------------------------------------------------------------------- */
+
+int addToSampCol(unsigned short *sampcol, unsigned short *shortcol, int mask, int osaNr)
+{
+ int a, retval = osaNr;
+
+ for(a=0; a < osaNr; a++) {
+ if(mask & (1<<a)) addAlphaUnderShort(sampcol, shortcol);
+ if(sampcol[3]>0xFFF0) retval--;
+ sampcol+= 4;
+ }
+ return retval;
+} /* end of int addToSampCol(unsigned short, uhost, int, int) */
+
+/* ------------------------------------------------------------------------- */
+
+int addtosampcol(unsigned short *sampcol, unsigned short *shortcol, int mask)
+{
+ int a, retval = R.osa;
+
+ for(a=0; a < R.osa; a++) {
+ if(mask & (1<<a)) addAlphaUnderShort(sampcol, shortcol);
+ if(sampcol[3]>0xFFF0) retval--;
+ sampcol+= 4;
+ }
+ return retval;
+} /* end of int addtosampcol(unsigned short *sampcol, unsigned short *shortcol, int mask) */
+
+/* ------------------------------------------------------------------------- */
+
+void addAlphaOverShort(unsigned short *doel, unsigned short *bron) /* vult bron over doel in met alpha van bron */
+{
+ unsigned int c;
+ unsigned int mul;
+
+ if( doel[3]==0 || bron[3]>=0xFFF0) { /* is getest, scheelt veel */
+ *((unsigned int *)doel)= *((unsigned int *)bron);
+ *((unsigned int *)(doel+2))= *((unsigned int *)(bron+2));
+ return;
+ }
+
+ mul= 0xFFFF-bron[3];
+
+ c= ((mul*doel[0])>>16)+bron[0];
+ if(c>=0xFFF0) doel[0]=0xFFF0;
+ else doel[0]= c;
+ c= ((mul*doel[1])>>16)+bron[1];
+ if(c>=0xFFF0) doel[1]=0xFFF0;
+ else doel[1]= c;
+ c= ((mul*doel[2])>>16)+bron[2];
+ if(c>=0xFFF0) doel[2]=0xFFF0;
+ else doel[2]= c;
+ c= ((mul*doel[3])>>16)+bron[3];
+ if(c>=0xFFF0) doel[3]=0xFFF0;
+ else doel[3]= c;
+
+} /* end of void addAlphaOverShort(unsigned short *doel, unsigned short *bron) */
+
+/* ------------------------------------------------------------------------- */
+
+void addAlphaUnderShort(unsigned short *doel, unsigned short *bron) /* vult bron onder doel in met alpha van doel */
+{
+ unsigned int c;
+ unsigned int mul;
+
+ if(doel[3]>=0xFFF0) return;
+ if( doel[3]==0 ) { /* is getest, scheelt veel */
+ *((unsigned int *)doel)= *((unsigned int *)bron);
+ *((unsigned int *)(doel+2))= *((unsigned int *)(bron+2));
+ return;
+ }
+
+ mul= 0xFFFF-doel[3];
+
+ c= ((mul*bron[0])>>16)+doel[0];
+ if(c>=0xFFF0) doel[0]=0xFFF0;
+ else doel[0]= c;
+ c= ((mul*bron[1])>>16)+doel[1];
+ if(c>=0xFFF0) doel[1]=0xFFF0;
+ else doel[1]= c;
+ c= ((mul*bron[2])>>16)+doel[2];
+ if(c>=0xFFF0) doel[2]=0xFFF0;
+ else doel[2]= c;
+ c= ((mul*bron[3])>>16)+doel[3];
+ if(c>=0xFFF0) doel[3]=0xFFF0;
+ else doel[3]= c;
+
+} /* end of void addAlphaUnderShort(unsigned short *doel, unsigned short *bron) */
+
+/* ------------------------------------------------------------------------- */
+
+void addAlphaOverFloat(float *dest, float *source)
+{
+ /* d = s + (1-alpha_s)d*/
+ float c;
+ float mul;
+
+ /* I may want to disable this clipping */
+#ifdef RE_FLOAT_COLOUR_CLIPPING
+ if( /* (-RE_FULL_COLOUR_FLOAT < source[3]) */
+/* && */ (source[3] > RE_FULL_COLOUR_FLOAT) ) { /* is getest, scheelt veel */
+ dest[0] = source[0];
+ dest[1] = source[1];
+ dest[2] = source[2];
+ dest[3] = source[3];
+ return;
+ }
+#endif
+
+ mul= 1.0 - source[3];
+
+ c= (mul*dest[0]) + source[0];
+#ifdef RE_FLOAT_COLOUR_CLIPPING
+ if(c >= RE_FULL_COLOUR_FLOAT) dest[0] = RE_UNITY_COLOUR_FLOAT;
+ else
+#endif
+ dest[0]= c;
+
+ c= (mul*dest[1]) + source[1];
+#ifdef RE_FLOAT_COLOUR_CLIPPING
+ if(c >= RE_FULL_COLOUR_FLOAT) dest[1] = RE_UNITY_COLOUR_FLOAT;
+ else
+#endif
+ dest[1]= c;
+
+ c= (mul*dest[2]) + source[2];
+#ifdef RE_FLOAT_COLOUR_CLIPPING
+ if(c >= RE_FULL_COLOUR_FLOAT) dest[2] = RE_UNITY_COLOUR_FLOAT;
+ else
+#endif
+ dest[2]= c;
+
+ c= (mul*dest[3]) + source[3];
+#ifdef RE_ALPHA_CLIPPING
+ if(c >= RE_FULL_COLOUR_FLOAT) dest[3] = RE_UNITY_COLOUR_FLOAT;
+ else
+#endif
+ dest[3]= c;
+
+} /* end of void addAlphaOverFloat(float *doel, float *bron) */
+
+
+
+/* ------------------------------------------------------------------------- */
+
+void addAlphaUnderFloat(float *dest, float *source)
+{
+ float c;
+ float mul;
+
+ /* I may want to disable this clipping */
+#ifdef RE_FLOAT_COLOUR_CLIPPING
+ if( dest[3] >= RE_FULL_COLOUR_FLOAT) return;
+#endif
+ if( (-RE_EMPTY_COLOUR_FLOAT < dest[3])
+ && (dest[3] < RE_EMPTY_COLOUR_FLOAT) ) { /* is getest, scheelt veel */
+ dest[0] = source[0];
+ dest[1] = source[1];
+ dest[2] = source[2];
+ dest[3] = source[3];
+ return;
+ }
+
+ mul= 1.0 - dest[3];
+
+ c= (mul*source[0]) + dest[0];
+#ifdef RE_FLOAT_COLOUR_CLIPPING
+ if(c >= RE_FULL_COLOUR_FLOAT) dest[0] = RE_UNITY_COLOUR_FLOAT;
+ else
+#endif
+ dest[0]= c;
+
+ c= (mul*source[1]) + dest[1];
+#ifdef RE_FLOAT_COLOUR_CLIPPING
+ if(c >= RE_FULL_COLOUR_FLOAT) dest[1] = RE_UNITY_COLOUR_FLOAT;
+ else
+#endif
+ dest[1]= c;
+
+ c= (mul*source[2]) + dest[2];
+#ifdef RE_FLOAT_COLOUR_CLIPPING
+ if(c >= RE_FULL_COLOUR_FLOAT) dest[2] = RE_UNITY_COLOUR_FLOAT;
+ else
+#endif
+ dest[2]= c;
+
+ c= (mul*source[3]) + dest[3];
+#ifdef RE_ALPHA_CLIPPING
+ if(c >= RE_FULL_COLOUR_FLOAT) dest[3] = RE_UNITY_COLOUR_FLOAT;
+ else
+#endif
+ dest[3]= c;
+
+} /* end of void addAlphaUnderFloat(float *doel, float *bron) */
+
+/* ------------------------------------------------------------------------- */
+
+void cpShortColV2CharColV(unsigned short *source, char *dest)
+{
+ dest[0] = source[0]>>8;
+ dest[1] = source[1]>>8;
+ dest[2] = source[2]>>8;
+ dest[3] = source[3]>>8;
+} /* end of void cpShortColV2CharColV(unsigned short *source, char *dest) */
+/* ------------------------------------------------------------------------- */
+
+void cpCharColV2ShortColV(char *source, unsigned short *dest)
+{
+ dest[0] = source[0]<<8;
+ dest[1] = source[1]<<8;
+ dest[2] = source[2]<<8;
+ dest[3] = source[3]<<8;
+} /* end of void cpShortColV2CharColV(char *source, unsigned short *dest) */
+
+/* ------------------------------------------------------------------------- */
+
+void cpIntColV2CharColV(unsigned int *source, char *dest)
+{
+ dest[0] = source[0]>>24;
+ dest[1] = source[1]>>24;
+ dest[2] = source[2]>>24;
+ dest[3] = source[3]>>24;
+} /* end of void cpIntColV2CharColV(unsigned int *source, char *dest) */
+
+/* ------------------------------------------------------------------------- */
+
+void cpCharColV2FloatColV(char *source, float *dest)
+{
+ /* What about endianness? Might be caught at this level :) */
+ dest[0] = source[0]/255.0;
+ dest[1] = source[1]/255.0;
+ dest[2] = source[2]/255.0;
+ dest[3] = source[3]/255.0;
+} /* end of void cpCharColV2FloatColV(char *source, float *dest) */
+/* ------------------------------------------------------------------------- */
+
+void cpShortColV2FloatColV(unsigned short *source, float *dest)
+{
+ dest[0] = source[0]/65535.0;
+ dest[1] = source[1]/65535.0;
+ dest[2] = source[2]/65535.0;
+ dest[3] = source[3]/65535.0;
+} /* end of void cpShortColV2FloatColV(char *source, float *dest) */
+
+/* ------------------------------------------------------------------------- */
+
+void cpFloatColV2CharColV(float* source, char *dest)
+{
+ /* can't this be done more efficient? hope the conversions are correct... */
+ if (source[0] < 0.0) dest[0] = 0;
+ else if (source[0] > 1.0) dest[0] = 255;
+ else dest[0] = (char) (source[0] * 255.0);
+
+ if (source[1] < 0.0) dest[1] = 0;
+ else if (source[1] > 1.0) dest[1] = 255;
+ else dest[1] = (char) (source[1] * 255.0);
+
+ if (source[2] < 0.0) dest[2] = 0;
+ else if (source[2] > 1.0) dest[2] = 255;
+ else dest[2] = (char) (source[2] * 255.0);
+
+ if (source[3] < 0.0) dest[3] = 0;
+ else if (source[3] > 1.0) dest[3] = 255;
+ else dest[3] = (char) (source[3] * 255.0);
+
+} /* end of void cpFloatColV2CharColV(float* source, char *dest) */
+
+/* ------------------------------------------------------------------------- */
+
+void cpShortColV(unsigned short *source, unsigned short *dest)
+{
+ dest[0] = source[0];
+ dest[1] = source[1];
+ dest[2] = source[2];
+ dest[3] = source[3];
+} /* end of void cpShortColV(unsigned short *source, unsigned short *dest) */
+
+/* ------------------------------------------------------------------------- */
+void cpFloatColV(float *source, float *dest)
+{
+ dest[0] = source[0];
+ dest[1] = source[1];
+ dest[2] = source[2];
+ dest[3] = source[3];
+} /* end of void cpFloatColV(float *source, float *dest) */
+
+/* ------------------------------------------------------------------------- */
+
+void cpCharColV(char *source, char *dest)
+{
+ dest[0] = source[0];
+ dest[1] = source[1];
+ dest[2] = source[2];
+ dest[3] = source[3];
+} /* end of void cpCharColV(char *source, char *dest) */
+
+/* ------------------------------------------------------------------------- */
+void addalphaAddfacFloat(float *dest, float *source, char addfac)
+ /* doel= bron over doel */
+{
+ float m; /* weiging factor of destination */
+ float c; /* intermediate colour */
+
+ /* 1. copy source straight away if dest has zero alpha */
+ /* 2. copy dest straight away if dest has full alpha */
+ /* I am not sure whether (2) is correct. It seems to */
+ /* me that this should not happen if float colours */
+ /* aren't clipped at 1.0 . */
+ /* I'll keep the code, but disabled.... */
+ if ( (dest[3] < RE_EMPTY_COLOUR_FLOAT)
+ /* || source[3] > RE_FULL_COLOUR_FLOAT */ ) {
+ dest[0] = source[0];
+ dest[1] = source[1];
+ dest[2] = source[2];
+ dest[3] = source[3];
+ return;
+ }
+
+ /* Addfac is a number between 0 and 1: rescale */
+ /* final target is to diminish the influence of dest when addfac rises */
+ m = 1.0 - ( source[3] * ((255.0 - addfac) / 255.0));
+
+ /* blend colours*/
+ c= (m * dest[0]) + source[0];
+#ifdef RE_FLOAT_COLOUR_CLIPPING
+ if(c >= RE_FULL_COLOUR_FLOAT) dest[0] = RE_FULL_COLOUR_FLOAT;
+ else
+#endif
+ dest[0]= c;
+
+ c= (m * dest[1]) + source[1];
+#ifdef RE_FLOAT_COLOUR_CLIPPING
+ if(c >= RE_FULL_COLOUR_FLOAT) dest[1] = RE_FULL_COLOUR_FLOAT;
+ else
+#endif
+ dest[1]= c;
+
+ c= (m * dest[2]) + source[2];
+#ifdef RE_FLOAT_COLOUR_CLIPPING
+ if(c >= RE_FULL_COLOUR_FLOAT) dest[2] = RE_FULL_COLOUR_FLOAT;
+ else
+#endif
+ dest[2]= c;
+
+ c= dest[3] + source[3];
+#ifdef RE_ALPHA_CLIPPING
+ if(c >= RE_FULL_COLOUR_FLOAT) dest[3] = RE_FULL_COLOUR_FLOAT;
+ else
+#endif
+ dest[3]= c;
+
+} /* end of void addalphaAddfacFloat(unsigned short *doel, unsigned short *bron, char addfac_help) */
+
+/* ------------------------------------------------------------------------- */
+
+void addalphaAddfacShort(unsigned short *doel, unsigned short *bron, char addfac)
+ /* doel= bron over doel */
+{
+ float m; /* weiging factor of destination */
+ float c; /* intermediate colour */
+
+ /* 1. copy bron straight away if doel has zero alpha */
+ if( doel[3] == 0) {
+ *((unsigned int *)doel) = *((unsigned int *)bron);
+ *((unsigned int *)(doel+2)) = *((unsigned int *)(bron+2));
+ return;
+ }
+
+ /* Addfac is a number between 0 and 1: rescale */
+ /* final target is to diminish the influence of dest when addfac rises */
+ m = 1.0 - ( bron[3] * ((255.0 - addfac) / 255.0));
+
+ /* blend colours*/
+ c = (m * doel[0]) + bron[0];
+ if( c > 65535.0 ) doel[0]=65535;
+ else doel[0] = floor(c);
+ c = (m * doel[1]) + bron[1];
+ if( c > 65535.0 ) doel[1]=65535;
+ else doel[1] = floor(c);
+ c = (m * doel[2]) + bron[2];
+ if( c > 65535.0 ) doel[2]=65535;
+ else doel[2] = floor(c);
+
+ c = doel[3] + bron[3];
+ if(c > 65535.0) doel[3] = 65535;
+ else doel[3]= floor(c);
+
+} /* end of void addalphaAddfacShort(unsigned short *doel, unsigned short *bron, char addfac_help) */
+
+/* ------------------------------------------------------------------------- */
+
+void addHaloToHaloShort(unsigned short *d, unsigned short *s)
+{
+ /* float m; */ /* weiging factor of destination */
+ float c[4]; /* intermediate colour */
+ float rescale = 1.0;
+
+ /* 1. copy <s> straight away if <d> has zero alpha */
+ if( d[3] == 0) {
+ *((unsigned int *) d) = *((unsigned int *) s);
+ *((unsigned int *)(d + 2)) = *((unsigned int *)(s + 2));
+ return;
+ }
+
+ /* 2. halo blending */
+ /* no blending, just add */
+ c[0] = s[0] + d[0];
+ c[1] = s[1] + d[1];
+ c[2] = s[2] + d[2];
+ c[3] = s[3] + d[3];
+ /* One thing that may happen is that this pixel is over-saturated with light - */
+ /* i.e. too much light comes out, and the pixel is clipped. Currently, this */
+ /* leads to artifacts such as overproportional undersampling of background */
+ /* colours. */
+ /* Compensating for over-saturation: */
+ /* - increase alpha */
+ /* - increase alpha and rescale colours */
+
+ /* let's try alpha increase and clipping */
+
+ /* calculate how much rescaling we need */
+ if( c[0] > 65535.0 ) {
+ rescale *= c[0] /65535.0;
+ d[0] = 65535;
+ } else d[0] = floor(c[0]);
+ if( c[1] > 65535.0 ) {
+ rescale *= c[1] /65535.0;
+ d[1] = 65535;
+ } else d[1] = floor(c[1]);
+ if( c[2] > 65535.0 ) {
+ rescale *= c[2] /65535.0;
+ d[2] = 65535;
+ } else d[2] = floor(c[2]);
+
+ /* a bit too hefty I think */
+ c[3] *= rescale;
+
+ if( c[3] > 65535.0 ) d[3] = 65535; else d[3]= floor(c[3]);
+
+} /* end of void addHaloToHaloShort(unsigned short *dest, unsigned short *source, char addfac) */
+
+/* ------------------------------------------------------------------------- */
+
+void sampleShortColV2ShortColV(unsigned short *sample, unsigned short *dest, int osaNr)
+{
+ unsigned int intcol[4] = {0};
+ unsigned short *scol = sample;
+ int a = 0;
+
+ for(a=0; a < osaNr; a++, scol+=4) {
+ intcol[0]+= scol[0]; intcol[1]+= scol[1];
+ intcol[2]+= scol[2]; intcol[3]+= scol[3];
+ }
+
+ /* Now normalise the integrated colour. It is guaranteed */
+ /* to be correctly bounded. */
+ dest[0]= intcol[0]/osaNr;
+ dest[1]= intcol[1]/osaNr;
+ dest[2]= intcol[2]/osaNr;
+ dest[3]= intcol[3]/osaNr;
+
+} /* end of void sampleShortColVToShortColV(unsigned short *sample, unsigned short *dest) */
+
+
+/* ------------------------------------------------------------------------- */
+
+void sampleFloatColV2FloatColV(float *sample, float *dest, int osaNr)
+{
+ float intcol[4] = {0};
+ float *scol = sample;
+ int a = 0;
+
+ if (doGamma()) {
+ /* use a LUT and interpolation to do the gamma correction */
+ for(a=0; a < osaNr; a++, scol+=4) {
+ intcol[0] += gammaCorrect(scol[0]);
+ intcol[1] += gammaCorrect(scol[1]);
+ intcol[2] += gammaCorrect(scol[2]);
+ intcol[3] += scol[3];
+ }
+
+ /* renormalise */
+ intcol[0] /= osaNr;
+ intcol[1] /= osaNr;
+ intcol[2] /= osaNr;
+ intcol[3] /= osaNr;
+
+ /* back to pixel values */
+ dest[0] = invGammaCorrect(intcol[0]);
+ dest[1] = invGammaCorrect(intcol[1]);
+ dest[2] = invGammaCorrect(intcol[2]);
+ dest[3] = intcol[3];
+ } else {
+ /* no gamma */
+ for(a=0; a < osaNr; a++, scol+=4) {
+ intcol[0] += scol[0]; intcol[1] += scol[1];
+ intcol[2] += scol[2]; intcol[3] += scol[3];
+ }
+
+ dest[0]= intcol[0]/osaNr;
+ dest[1]= intcol[1]/osaNr;
+ dest[2]= intcol[2]/osaNr;
+ dest[3]= intcol[3]/osaNr;
+ }
+
+} /* end void sampleFloatColVToFloatColV(unsigned short *, unsigned short *) */
+
+/* ------------------------------------------------------------------------- */
+/* The following functions are 'old' blending functions: */
+
+/* ------------------------------------------------------------------------- */
+void keyalpha(char *doel) /* maakt premul 255 */
+{
+ int c;
+ short div;
+ div= doel[3];
+ if (!div)
+ {
+ doel[0] = (doel[0] ? 255 : 0);
+ doel[1] = (doel[1] ? 255 : 0);
+ doel[2] = (doel[2] ? 255 : 0);
+ } else
+ {
+ c= (doel[0]<<8)/div;
+ if(c>255) doel[0]=255;
+ else doel[0]= c;
+ c= (doel[1]<<8)/div;
+ if(c>255) doel[1]=255;
+ else doel[1]= c;
+ c= (doel[2]<<8)/div;
+ if(c>255) doel[2]=255;
+ else doel[2]= c;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+/* vult bron onder doel in met alpha van doel*/
+void addalphaUnder(char *doel, char *bron)
+{
+ int c;
+ int mul;
+
+ if(doel[3]==255) return;
+ if( doel[3]==0) { /* is getest, scheelt */
+ *((unsigned int *)doel)= *((unsigned int *)bron);
+ return;
+ }
+
+ mul= 255-doel[3];
+
+ c= doel[0]+ ((mul*bron[0])/255);
+ if(c>255) doel[0]=255;
+ else doel[0]= c;
+ c= doel[1]+ ((mul*bron[1])/255);
+ if(c>255) doel[1]=255;
+ else doel[1]= c;
+ c= doel[2]+ ((mul*bron[2])/255);
+ if(c>255) doel[2]=255;
+ else doel[2]= c;
+
+ c= doel[3]+ ((mul*bron[3])/255);
+ if(c>255) doel[3]=255;
+ else doel[3]= c;
+
+ /* doel[0]= MAX2(doel[0], bron[0]); */
+}
+
+/* ------------------------------------------------------------------------- */
+/* gamma-gecorr: vult bron onder doel in met alpha van doel */
+void addalphaUnderGamma(char *doel, char *bron)
+{
+ unsigned int tot;
+ int c, doe, bro;
+ int mul;
+
+ /* hier doel[3]==0 of doel==255 afvangen gebeurt al in skylus */
+ mul= 256-doel[3];
+
+ doe= igamtab1[(int)doel[0]];
+ bro= igamtab1[(int)bron[0]];
+ tot= (doe+ ((mul*bro)>>8));
+ if(tot>65535) tot=65535;
+ doel[0]= *((gamtab+tot)) >>8;
+
+ doe= igamtab1[(int)doel[1]];
+ bro= igamtab1[(int)bron[1]];
+ tot= (doe+ ((mul*bro)>>8));
+ if(tot>65535) tot=65535;
+ doel[1]= *((gamtab+tot)) >>8;
+
+ doe= igamtab1[(int)doel[2]];
+ bro= igamtab1[(int)bron[2]];
+ tot= (doe+ ((mul*bro)>>8));
+ if(tot>65535) tot=65535;
+ doel[2]= *((gamtab+tot)) >>8;
+
+ c= doel[3]+ ((mul*bron[3])/255);
+ if(c>255) doel[3]=255;
+ else doel[3]= c;
+ /* doel[0]= MAX2(doel[0], bron[0]); */
+}
+
+/* ------------------------------------------------------------------------- */
+/* doel= bron over doel */
+void addalphaOver(char *doel, char *bron)
+{
+ int c;
+ int mul;
+
+ if(bron[3]==0) return;
+ if( bron[3]==255) { /* is getest, scheelt */
+ *((unsigned int *)doel)= *((unsigned int *)bron);
+ return;
+ }
+
+ mul= 255-bron[3];
+
+ c= ((mul*doel[0])/255)+bron[0];
+ if(c>255) doel[0]=255;
+ else doel[0]= c;
+ c= ((mul*doel[1])/255)+bron[1];
+ if(c>255) doel[1]=255;
+ else doel[1]= c;
+ c= ((mul*doel[2])/255)+bron[2];
+ if(c>255) doel[2]=255;
+ else doel[2]= c;
+ c= ((mul*doel[3])/255)+bron[3];
+ if(c>255) doel[3]=255;
+ else doel[3]= c;
+}
+
+/* ------------------------------------------------------------------------- */
+void addalphaAdd(char *doel, char *bron) /* telt bron bij doel */
+{
+ int c;
+
+ if( doel[3]==0 || bron[3]==255) { /* is getest, scheelt veel */
+ *((unsigned int *)doel)= *((unsigned int *)bron);
+ return;
+ }
+ c= doel[0]+bron[0];
+ if(c>255) doel[0]=255;
+ else doel[0]= c;
+ c= doel[1]+bron[1];
+ if(c>255) doel[1]=255;
+ else doel[1]= c;
+ c= doel[2]+bron[2];
+ if(c>255) doel[2]=255;
+ else doel[2]= c;
+ c= doel[3]+bron[3];
+ if(c>255) doel[3]=255;
+ else doel[3]= c;
+}
+/* ------------------------------------------------------------------------- */
+void addalphaAddshort(unsigned short *doel, unsigned short *bron) /* telt bron bij doel */
+{
+ int c;
+
+ if( doel[3]==0) {
+ *((unsigned int *)doel)= *((unsigned int *)bron);
+ *((unsigned int *)(doel+2))= *((unsigned int *)(bron+2));
+ return;
+ }
+ c= doel[0]+bron[0];
+ if(c>65535) doel[0]=65535;
+ else doel[0]= c;
+ c= doel[1]+bron[1];
+ if(c>65535) doel[1]=65535;
+ else doel[1]= c;
+ c= doel[2]+bron[2];
+ if(c>65535) doel[2]=65535;
+ else doel[2]= c;
+ c= doel[3]+bron[3];
+ if(c>65535) doel[3]=65535;
+ else doel[3]= c;
+}
+
+/* ------------------------------------------------------------------------- */
+void addalphaAddFloat(float *dest, float *source)
+{
+
+ /* Makes me wonder whether this is required... */
+ if( dest[3] < RE_EMPTY_COLOUR_FLOAT) {
+ dest[0] = source[0];
+ dest[1] = source[1];
+ dest[2] = source[2];
+ dest[3] = source[3];
+ return;
+ }
+
+ /* no clipping! */
+ dest[0] = dest[0]+source[0];
+ dest[1] = dest[1]+source[1];
+ dest[2] = dest[2]+source[2];
+ dest[3] = dest[3]+source[3];
+
+}
+
+/* ALPHADDFAC:
+ *
+ * Z= X alphaover Y:
+ * Zrgb= (1-Xa)*Yrgb + Xrgb
+ *
+ * Om ook de add te doen moet (1-Xa) moduleren met 1 via fac
+ * (1-fac)*(1-Xa) + fac <=>
+ * 1-Xa-fac+fac*Xa+fac <=>
+ * Xa*(fac-1)+1
+ */
+
+
+/* ------------------------------------------------------------------------- */
+/* doel= bron over doel */
+void RE_addalphaAddfac(char *doel, char *bron, char addfac)
+{
+
+ int c, mul;
+
+ if( doel[3]==0) {
+ *((unsigned int *)doel)= *((unsigned int *)bron);
+ return;
+ }
+
+ mul= 255 - (bron[3]*(255-addfac))/255;
+
+ c= ((mul*doel[0])/255)+bron[0];
+ if(c>255) doel[0]=255;
+ else doel[0]= c;
+ c= ((mul*doel[1])/255)+bron[1];
+ if(c>255) doel[1]=255;
+ else doel[1]= c;
+ c= ((mul*doel[2])/255)+bron[2];
+ if(c>255) doel[2]=255;
+ else doel[2]= c;
+
+ /* c= ((mul*doel[3])/255)+bron[3]; */
+ c= doel[3]+bron[3];
+ if(c>255) doel[3]=255;
+ else doel[3]= c;
+}
+
+/* ------------------------------------------------------------------------- */
+/* doel= bron over doel */
+void addalphaAddfacshort(unsigned short *doel,
+ unsigned short *bron,
+ short addfac)
+{
+ int c, mul;
+
+ if( doel[3]==0) {
+ *((unsigned int *)doel)= *((unsigned int *)bron);
+ *((unsigned int *)(doel+2))= *((unsigned int *)(bron+2));
+ return;
+ }
+
+ mul= 0xFFFF - (bron[0]*(255-addfac))/255;
+
+ c= ((mul*doel[0])>>16)+bron[0];
+ if(c>=0xFFF0) doel[0]=0xFFF0;
+ else doel[0]= c;
+ c= ((mul*doel[1])>>16)+bron[1];
+ if(c>=0xFFF0) doel[1]=0xFFF0;
+ else doel[1]= c;
+ c= ((mul*doel[2])>>16)+bron[2];
+ if(c>=0xFFF0) doel[2]=0xFFF0;
+ else doel[2]= c;
+ c= ((mul*doel[3])>>16)+bron[3];
+ if(c>=0xFFF0) doel[3]=0xFFF0;
+ else doel[3]= c;
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* eof pixelblending.c */
+
+
diff --git a/source/blender/render/intern/source/pixelshading.c b/source/blender/render/intern/source/pixelshading.c
new file mode 100644
index 00000000000..ff69b4226bf
--- /dev/null
+++ b/source/blender/render/intern/source/pixelshading.c
@@ -0,0 +1,1917 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Shading of pixels
+ *
+ * 11-09-2000 nzc
+ *
+ * $Id$
+ *
+ * Shading hierarchy:
+ *
+ * (externally visible)
+ *
+ * renderPixel----------
+ * | renderHaloPixel-- shadeHaloFloat
+ * |
+ * | renderFacePixel-- shadeLampLusFloat
+ * | shadeSpotHaloPixelFloat-- spotHaloFloat
+ *
+ *
+ * renderSpotHaloPixel--(should call shadeSpotHaloPixelFloat, but there's numerical)
+ * ( issues there... need to iron that out still )
+ */
+
+#include <math.h>
+#include "BLI_arithb.h"
+
+/* External modules: */
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+#include "MTC_matrixops.h"
+#include "MTC_vectorops.h"
+
+#include "DNA_camera_types.h"
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_image_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_lamp_types.h"
+
+#include "BKE_global.h"
+#include "BKE_texture.h"
+#include "BKE_utildefines.h"
+
+#include "render.h"
+#include "render_intern.h"
+
+#include "vanillaRenderPipe_types.h"
+#include "pixelblending.h"
+#include "zbuf.h"
+#include "rendercore.h" /* for some shading functions... */
+#include "zbufferdatastruct.h"
+
+#include "shadbuf.h"
+#include "shadowBuffer.h"
+
+#include "renderHelp.h"
+
+#include "gammaCorrectionTables.h"
+#include "errorHandler.h"
+#include "pixelshading.h"
+
+/* ------------------------------------------------------------------------- */
+/* maybe declare local functions here? */
+/* ------------------------------------------------------------------------- */
+
+/* The collector is the communication channel with the render pipe. */
+extern RE_COLBUFTYPE collector[4]; /* used throughout as pixel colour accu */
+/* shortcol was the old collector */
+extern float holoofs, fmask[256];
+extern float Zmulx, Zmuly; /* Some kind of scale? */
+
+unsigned int calcHaloZ(HaloRen *har, unsigned int zz);
+
+/* ------------------------------------------------------------------------- */
+/* if defined: do full error tracing and reporting here */
+/* #define RE_PIXSHADE_FULL_SAFETY */
+/* if defined: use fake (dummy) colours for filling pixels (all is purple) */
+/* #define RE_FAKE_PIXELS */
+/* if defined: use fake (dummy) colours for filling faces (all blue) */
+/* #define RE_FAKE_FACE_PIXELS */
+/* if defined: use fake (dummy) colours for filling halos (all red) */
+/* #define RE_FAKE_HALO_PIXELS */
+/* #define RE_FAKE_HALO_PIXELS_2 */
+/* if defined: use fake (dummy) colours for filling spothalos (green) */
+/* #define RE_FAKE_SPOTHALO_PIXELS */
+/* if defined: use fake (dummy) colours for shading lighting */
+/* #define RE_FAKE_LAMP_SHADE */
+/* if defined: fake colours for sky pixels */
+/* #define RE_FAKE_SKY_PIXELS */
+
+/* ------------------------------------------------------------------------- */
+
+unsigned int calcHaloZ(HaloRen *har, unsigned int zz)
+{
+
+ if(har->type & HA_ONLYSKY) {
+ if(zz!=0x7FFFFFFF) zz= 0;
+ }
+ else {
+ zz= (zz>>8);
+ if(zz<0x800000) zz= (zz+0x7FFFFF);
+ else zz= (zz-0x800000);
+ }
+ return zz;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void *renderPixel(float x, float y, int *obdata)
+{
+ void* data = NULL;
+#ifdef RE_PIXSHADE_FULL_SAFETY
+ char fname[] = "renderPixel";
+#endif
+#ifdef RE_FAKE_PIXELS
+ collector[0] = RE_UNITY_COLOUR_FLOAT;
+ collector[1] = 0;
+ collector[2] = RE_UNITY_COLOUR_FLOAT;
+ collector[3] = RE_UNITY_COLOUR_FLOAT;
+ return NULL;
+#endif
+
+ if (obdata[3] & RE_POLY) {
+ /* face pixels aren't rendered in floats yet, so we wrap it here */
+ data = renderFacePixel(x, y, obdata[1]);
+ }
+ else if (obdata[3] & RE_HALO) {
+ data = renderHaloPixel(x, y, obdata[1]);
+ }
+ else if( obdata[1] == 0 ) {
+ /* for lamphalo, but doesn't seem to be called? Actually it is, and */
+ /* it returns NULL pointers. */
+ data = renderFacePixel(x, y, obdata[1]);
+ }
+#ifdef RE_PIXSHADE_FULL_SAFETY
+ else RE_error(RE_BAD_FACE_TYPE, fname);
+#endif /* RE_PIXSHADE_FULL_SAFETY */
+ return data;
+
+} /* end of void renderPixel(float x, float y, int *obdata) */
+
+/* ------------------------------------------------------------------------- */
+
+void *renderFacePixel(float x, float y, int vlaknr)
+/* Result goes into <collector> */
+{
+#ifdef RE_PIXSHADE_FULL_SAFETY
+ char fname[]= "renderFacePixelFloat";
+#endif
+ static VlakRen *vlr; /* static, because we don't want to recalculate vlr */
+ /* when we already know it */
+ static VertRen *v1, *v2, *v3;
+ static float t00, t01, t10, t11, dvlak, n1[3], n2[3], n3[3];
+ static float s00, s01, s10, s11;
+ float *o1, *o2, *o3;
+ float u, v, l, dl, hox, hoy, detsh, fac, deler, alpha;
+ char *cp1, *cp2, *cp3;
+
+/* RE_error(RE_TRACE_COUNTER, fname); */
+
+#ifdef RE_FAKE_FACE_PIXELS
+ collector[0] = 0;
+ collector[1] = 0;
+ collector[2] = RE_UNITY_COLOUR_FLOAT;
+ collector[3] = RE_UNITY_COLOUR_FLOAT;
+ /* try to keep the rest as clean as possible... */
+ if( ((vlaknr & 0x7FFFFF) <= R.totvlak)
+ && ! ((R.vlaknr== -1)||(vlaknr<=0)) ) {
+ /* a bit superfluous to do this always, but */
+ /* when this is switched on, it doesn't matter */
+ vlr= RE_findOrAddVlak( (vlaknr-1) & 0x7FFFFF);
+ } else vlr = NULL;
+ return vlr;
+#endif
+
+ if(R.vlaknr== -1) { /* doet initrender */
+ /* also set in the pixelrender loop */
+ vlr= R.vlr= 0;
+ }
+
+ if(vlaknr<=0) { /* sky */
+ R.vlaknr= 0;
+ collector[3] = 0.0;
+ }
+ else if( (vlaknr & 0x7FFFFF) <= R.totvlak) {
+
+ /* What follows now is a large bunch of texture coordinate mappings. */
+ /* When this face is the same as the previous one, that means all */
+ /* the coordinate remapping does not need to be recomputed. */
+ if(vlaknr!=R.vlaknr) {
+
+ vlr= RE_findOrAddVlak( (vlaknr-1) & 0x7FFFFF);
+
+ R.mat= vlr->mat;
+ R.matren= R.mat->ren;
+
+ if(R.matren==0) { /* tijdelijk voor debug */
+ collector[3] = RE_UNITY_COLOUR_FLOAT;
+ collector[2] = 0.0;
+ collector[1] = RE_UNITY_COLOUR_FLOAT;
+ collector[0] = RE_UNITY_COLOUR_FLOAT;
+ return NULL;
+ }
+
+ R.vlr= vlr;
+
+ R.vno= vlr->n;
+ R.osatex= (R.matren->texco & TEXCO_OSA);
+ R.vlaknr= vlaknr;
+
+ v1= vlr->v1;
+ dvlak= MTC_dot3Float(v1->co, vlr->n);
+
+ if( (vlr->flag & R_SMOOTH) || (R.matren->texco & NEED_UV)) { /* uv nodig */
+ if(vlaknr & 0x800000) {
+ v2= vlr->v3;
+ v3= vlr->v4;
+ }
+ else {
+ v2= vlr->v2;
+ v3= vlr->v3;
+ }
+
+ if(vlr->snproj==0) {
+ t00= v3->co[0]-v1->co[0]; t01= v3->co[1]-v1->co[1];
+ t10= v3->co[0]-v2->co[0]; t11= v3->co[1]-v2->co[1];
+ }
+ else if(vlr->snproj==1) {
+ t00= v3->co[0]-v1->co[0]; t01= v3->co[2]-v1->co[2];
+ t10= v3->co[0]-v2->co[0]; t11= v3->co[2]-v2->co[2];
+ }
+ else {
+ t00= v3->co[1]-v1->co[1]; t01= v3->co[2]-v1->co[2];
+ t10= v3->co[1]-v2->co[1]; t11= v3->co[2]-v2->co[2];
+ }
+
+ detsh= t00*t11-t10*t01;
+ t00/= detsh; t01/=detsh;
+ t10/=detsh; t11/=detsh;
+
+ if(vlr->flag & R_SMOOTH) { /* puno's goedzetten */
+ if(vlr->puno & ME_FLIPV1) MTC_cp3FloatInv(v1->n, n1);
+ else MTC_cp3Float(v1->n, n1);
+
+ if(vlaknr & 0x800000) {
+ if(vlr->puno & ME_FLIPV3) MTC_cp3FloatInv(v2->n, n2);
+ else MTC_cp3Float(v2->n, n2);
+
+ if(vlr->puno & ME_FLIPV4) MTC_cp3FloatInv(v3->n, n3);
+ else MTC_cp3Float(v3->n, n3);
+ }
+ else {
+ if(vlr->puno & ME_FLIPV2) MTC_cp3FloatInv(v2->n, n2);
+ else MTC_cp3Float(v2->n, n2);
+
+ if(vlr->puno & ME_FLIPV3) MTC_cp3FloatInv(v3->n, n3);
+ else MTC_cp3Float(v3->n, n3);
+ }
+ }
+ if(R.matren->texco & TEXCO_STICKY) {
+ s00= v3->ho[0]/v3->ho[3] - v1->ho[0]/v1->ho[3];
+ s01= v3->ho[1]/v3->ho[3] - v1->ho[1]/v1->ho[3];
+ s10= v3->ho[0]/v3->ho[3] - v2->ho[0]/v2->ho[3];
+ s11= v3->ho[1]/v3->ho[3] - v2->ho[1]/v2->ho[3];
+
+ detsh= s00*s11-s10*s01;
+ s00/= detsh; s01/=detsh;
+ s10/=detsh; s11/=detsh;
+ }
+ }
+ } /* end of if vlaknr*/
+
+ /* This trafo might be migrated to a separate function. It is used */
+ /* quite often. */
+ /* COXYZ nieuwe methode */
+ if( (G.special1 & G_HOLO)
+ && (((Camera *)G.scene->camera->data)->flag & CAM_HOLO2) ) {
+ R.view[0]= (x+(R.xstart)+1.0+holoofs);
+ }
+ else {
+ R.view[0]= (x+(R.xstart)+1.0);
+ }
+
+ if(R.flag & R_SEC_FIELD) {
+ if(R.r.mode & R_ODDFIELD) R.view[1]= (y+R.ystart+0.5)*R.ycor;
+ else R.view[1]= (y+R.ystart+1.5)*R.ycor;
+ }
+ else R.view[1]= (y+R.ystart+1.0)*R.ycor;
+
+ R.view[2]= -R.viewfac;
+
+ if(R.r.mode & R_PANORAMA) {
+ float panoco, panosi;
+ panoco = getPanovCo();
+ panosi = getPanovSi();
+ u= R.view[0]; v= R.view[2];
+
+ R.view[0]= panoco*u + panosi*v;
+ R.view[2]= -panosi*u + panoco*v;
+ }
+
+ deler= vlr->n[0]*R.view[0] + vlr->n[1]*R.view[1] + vlr->n[2]*R.view[2];
+ if (deler!=0.0) fac= R.zcor= dvlak/deler;
+ else fac= R.zcor= 0.0;
+
+ R.co[0]= fac*R.view[0];
+ R.co[1]= fac*R.view[1];
+ R.co[2]= fac*R.view[2];
+
+ if(R.osatex || (R.r.mode & R_SHADOW) ) {
+ u= dvlak/(deler-vlr->n[0]);
+ v= dvlak/(deler- R.ycor*vlr->n[1]);
+
+ O.dxco[0]= R.co[0]- (R.view[0]-1.0)*u;
+ O.dxco[1]= R.co[1]- (R.view[1])*u;
+ O.dxco[2]= R.co[2]- (R.view[2])*u;
+
+ O.dyco[0]= R.co[0]- (R.view[0])*v;
+ O.dyco[1]= R.co[1]- (R.view[1]-1.0*R.ycor)*v;
+ O.dyco[2]= R.co[2]- (R.view[2])*v;
+
+ }
+
+ fac= Normalise(R.view);
+ R.zcor*= fac; /* voor mist */
+
+ if(R.osatex) {
+ if( (R.matren->texco & TEXCO_REFL) ) {
+ O.dxview= 1.0/fac;
+ O.dyview= R.ycor/fac;
+ }
+ }
+
+ /* UV en TEX*/
+ if( (vlr->flag & R_SMOOTH) || (R.matren->texco & NEED_UV)) {
+ if(vlr->snproj==0) {
+ u= (R.co[0]-v3->co[0])*t11-(R.co[1]-v3->co[1])*t10;
+ v= (R.co[1]-v3->co[1])*t00-(R.co[0]-v3->co[0])*t01;
+ if(R.osatex) {
+ O.dxuv[0]= O.dxco[0]*t11- O.dxco[1]*t10;
+ O.dxuv[1]= O.dxco[1]*t00- O.dxco[0]*t01;
+ O.dyuv[0]= O.dyco[0]*t11- O.dyco[1]*t10;
+ O.dyuv[1]= O.dyco[1]*t00- O.dyco[0]*t01;
+ }
+ }
+ else if(vlr->snproj==1) {
+ u= (R.co[0]-v3->co[0])*t11-(R.co[2]-v3->co[2])*t10;
+ v= (R.co[2]-v3->co[2])*t00-(R.co[0]-v3->co[0])*t01;
+ if(R.osatex) {
+ O.dxuv[0]= O.dxco[0]*t11- O.dxco[2]*t10;
+ O.dxuv[1]= O.dxco[2]*t00- O.dxco[0]*t01;
+ O.dyuv[0]= O.dyco[0]*t11- O.dyco[2]*t10;
+ O.dyuv[1]= O.dyco[2]*t00- O.dyco[0]*t01;
+ }
+ }
+ else {
+ u= (R.co[1]-v3->co[1])*t11-(R.co[2]-v3->co[2])*t10;
+ v= (R.co[2]-v3->co[2])*t00-(R.co[1]-v3->co[1])*t01;
+ if(R.osatex) {
+ O.dxuv[0]= O.dxco[1]*t11- O.dxco[2]*t10;
+ O.dxuv[1]= O.dxco[2]*t00- O.dxco[1]*t01;
+ O.dyuv[0]= O.dyco[1]*t11- O.dyco[2]*t10;
+ O.dyuv[1]= O.dyco[2]*t00- O.dyco[1]*t01;
+ }
+ }
+ l= 1.0+u+v;
+
+ if(vlr->flag & R_SMOOTH) {
+ R.vn[0]= l*n3[0]-u*n1[0]-v*n2[0];
+ R.vn[1]= l*n3[1]-u*n1[1]-v*n2[1];
+ R.vn[2]= l*n3[2]-u*n1[2]-v*n2[2];
+
+ Normalise(R.vn);
+ if(R.osatex && (R.matren->texco & (TEXCO_NORM+TEXCO_REFL)) ) {
+ dl= O.dxuv[0]+O.dxuv[1];
+ O.dxno[0]= dl*n3[0]-O.dxuv[0]*n1[0]-O.dxuv[1]*n2[0];
+ O.dxno[1]= dl*n3[1]-O.dxuv[0]*n1[1]-O.dxuv[1]*n2[1];
+ O.dxno[2]= dl*n3[2]-O.dxuv[0]*n1[2]-O.dxuv[1]*n2[2];
+ dl= O.dyuv[0]+O.dyuv[1];
+ O.dyno[0]= dl*n3[0]-O.dyuv[0]*n1[0]-O.dyuv[1]*n2[0];
+ O.dyno[1]= dl*n3[1]-O.dyuv[0]*n1[1]-O.dyuv[1]*n2[1];
+ O.dyno[2]= dl*n3[2]-O.dyuv[0]*n1[2]-O.dyuv[1]*n2[2];
+
+ }
+ }
+ else {
+ VECCOPY(R.vn, vlr->n);
+ }
+
+ if(R.matren->mode & MA_ZINV) { /* z invert */
+ /* R.vn[0]= -R.vn[0]; */
+ /* R.vn[1]= -R.vn[1]; */
+ }
+
+ if(R.matren->texco & TEXCO_ORCO) {
+ if(v2->orco) {
+ o1= v1->orco;
+ o2= v2->orco;
+ o3= v3->orco;
+
+ R.lo[0]= l*o3[0]-u*o1[0]-v*o2[0];
+ R.lo[1]= l*o3[1]-u*o1[1]-v*o2[1];
+ R.lo[2]= l*o3[2]-u*o1[2]-v*o2[2];
+
+ if(R.osatex) {
+ dl= O.dxuv[0]+O.dxuv[1];
+ O.dxlo[0]= dl*o3[0]-O.dxuv[0]*o1[0]-O.dxuv[1]*o2[0];
+ O.dxlo[1]= dl*o3[1]-O.dxuv[0]*o1[1]-O.dxuv[1]*o2[1];
+ O.dxlo[2]= dl*o3[2]-O.dxuv[0]*o1[2]-O.dxuv[1]*o2[2];
+ dl= O.dyuv[0]+O.dyuv[1];
+ O.dylo[0]= dl*o3[0]-O.dyuv[0]*o1[0]-O.dyuv[1]*o2[0];
+ O.dylo[1]= dl*o3[1]-O.dyuv[0]*o1[1]-O.dyuv[1]*o2[1];
+ O.dylo[2]= dl*o3[2]-O.dyuv[0]*o1[2]-O.dyuv[1]*o2[2];
+ }
+ }
+ }
+
+ if(R.matren->texco & TEXCO_GLOB) {
+ VECCOPY(R.gl, R.co);
+ MTC_Mat4MulVecfl(R.viewinv, R.gl);
+ if(R.osatex) {
+ VECCOPY(O.dxgl, O.dxco);
+ MTC_Mat3MulVecfl(R.imat, O.dxco);
+ VECCOPY(O.dygl, O.dyco);
+ MTC_Mat3MulVecfl(R.imat, O.dyco);
+ }
+ }
+ if((R.matren->texco & TEXCO_UV) || (R.matren->mode & (MA_VERTEXCOL|MA_FACETEXTURE))) {
+ if(R.vlr->tface) {
+ float *uv1, *uv2, *uv3;
+
+ uv1= R.vlr->tface->uv[0];
+ if( (vlaknr & 0x800000) || (R.vlr->flag & R_FACE_SPLIT) ) {
+ uv2= R.vlr->tface->uv[2];
+ uv3= R.vlr->tface->uv[3];
+ }
+ else {
+ uv2= R.vlr->tface->uv[1];
+ uv3= R.vlr->tface->uv[2];
+ }
+
+ R.uv[0]= -1.0 + 2.0*(l*uv3[0]-u*uv1[0]-v*uv2[0]);
+ R.uv[1]= -1.0 + 2.0*(l*uv3[1]-u*uv1[1]-v*uv2[1]);
+
+ if(R.osatex) {
+ float duv[2];
+
+ dl= O.dxuv[0]+O.dxuv[1];
+ duv[0]= O.dxuv[0];
+ duv[1]= O.dxuv[1];
+
+ O.dxuv[0]= 2.0*(dl*uv3[0]-duv[0]*uv1[0]-duv[1]*uv2[0]);
+ O.dxuv[1]= 2.0*(dl*uv3[1]-duv[0]*uv1[1]-duv[1]*uv2[1]);
+
+ dl= O.dyuv[0]+O.dyuv[1];
+ duv[0]= O.dyuv[0];
+ duv[1]= O.dyuv[1];
+
+ O.dyuv[0]= 2.0*(dl*uv3[0]-duv[0]*uv1[0]-duv[1]*uv2[0]);
+ O.dyuv[1]= 2.0*(dl*uv3[1]-duv[0]*uv1[1]-duv[1]*uv2[1]);
+ }
+ }
+ else {
+ R.uv[0]= 2.0*(u+.5);
+ R.uv[1]= 2.0*(v+.5);
+ }
+ }
+ if(R.matren->texco & TEXCO_NORM) {
+ R.orn[0]= R.vn[0];
+ R.orn[1]= -R.vn[1];
+ R.orn[2]= R.vn[2];
+ }
+ if(R.matren->mode & MA_VERTEXCOL) {
+
+ /* some colour calculations here */
+ cp1= (char *)vlr->vcol;
+ if(cp1) {
+ if( (vlaknr & 0x800000) || (R.vlr->flag & R_FACE_SPLIT) ) {
+ cp2= (char *)(vlr->vcol+2);
+ cp3= (char *)(vlr->vcol+3);
+ }
+ else {
+ cp2= (char *)(vlr->vcol+1);
+ cp3= (char *)(vlr->vcol+2);
+ }
+ R.vcol[0]= (l*cp3[3]-u*cp1[3]-v*cp2[3])/255.0;
+ R.vcol[1]= (l*cp3[2]-u*cp1[2]-v*cp2[2])/255.0;
+ R.vcol[2]= (l*cp3[1]-u*cp1[1]-v*cp2[1])/255.0;
+
+ }
+ else {
+ R.vcol[0]= 0.0;
+ R.vcol[1]= 0.0;
+ R.vcol[2]= 0.0;
+ }
+ }
+ if(R.matren->mode & MA_FACETEXTURE) {
+ if((R.matren->mode & MA_VERTEXCOL)==0) {
+ R.vcol[0]= 1.0;
+ R.vcol[1]= 1.0;
+ R.vcol[2]= 1.0;
+ }
+ /* shading here */
+ if(vlr->tface) render_realtime_texture();
+ }
+
+ /* hierna klopt de u en v EN O.dxuv en O.dyuv niet meer */
+ if(R.matren->texco & TEXCO_STICKY) {
+ if(v2->sticky) {
+
+ /* opnieuw u en v berekenen */
+ hox= x/Zmulx -1.0;
+ hoy= y/Zmuly -1.0;
+ u= (hox - v3->ho[0]/v3->ho[3])*s11
+ - (hoy - v3->ho[1]/v3->ho[3])*s10;
+ v= (hoy - v3->ho[1]/v3->ho[3])*s00
+ - (hox - v3->ho[0]/v3->ho[3])*s01;
+ l= 1.0+u+v;
+
+ o1= v1->sticky;
+ o2= v2->sticky;
+ o3= v3->sticky;
+
+ R.sticky[0]= l*o3[0]-u*o1[0]-v*o2[0];
+ R.sticky[1]= l*o3[1]-u*o1[1]-v*o2[1];
+
+ if(R.osatex) {
+ O.dxuv[0]= s11/Zmulx;
+ O.dxuv[1]= - s01/Zmulx;
+ O.dyuv[0]= - s10/Zmuly;
+ O.dyuv[1]= s00/Zmuly;
+
+ dl= O.dxuv[0]+O.dxuv[1];
+ O.dxsticky[0]= dl*o3[0]-O.dxuv[0]*o1[0]-O.dxuv[1]*o2[0];
+ O.dxsticky[1]= dl*o3[1]-O.dxuv[0]*o1[1]-O.dxuv[1]*o2[1];
+ dl= O.dyuv[0]+O.dyuv[1];
+ O.dysticky[0]= dl*o3[0]-O.dyuv[0]*o1[0]-O.dyuv[1]*o2[0];
+ O.dysticky[1]= dl*o3[1]-O.dyuv[0]*o1[1]-O.dyuv[1]*o2[1];
+ }
+ }
+ }
+ }
+ else {
+ VECCOPY(R.vn, vlr->n);
+ }
+ if(R.matren->texco & TEXCO_WINDOW) {
+ R.winco[0]= (x+(R.xstart))/(float)R.afmx;
+ R.winco[1]= (y+(R.ystart))/(float)R.afmy;
+ }
+
+ /* After all texture coordinates are set and converted and */
+ /* transformed, we need to put some colour on it: */
+ shadeLampLusFloat();
+
+ /* MIST */
+ if( (R.wrld.mode & WO_MIST) && (R.matren->mode & MA_NOMIST)==0 ){
+ /* alpha returned in float? */
+ alpha= mistfactor(R.co);
+ }
+ else alpha= 1.0;
+
+ /* RAYTRACE (tijdelijk?) UITGESCHAKELD */
+
+ if(R.matren->alpha!=1.0 || alpha!=1.0) {
+ fac= alpha*(R.matren->alpha);
+
+ collector[0] *= fac; /* This applies to transparent faces! Even */
+ collector[1] *= fac; /* though it may seem to be a premul op, it */
+ collector[2] *= fac; /* isn't. */
+ collector[3] = fac; /* doesn't need scaling? */
+ }
+ else {
+ collector[3] = 1.0;
+ }
+ }
+ else {
+ collector[0] = 1.0;
+ collector[1] = 1.0;
+ collector[2] = 0.0;
+ collector[3] = 1.0;
+ }
+
+ /* Spothalos: do this here for covered pixels. It seems messy to place */
+ /* it here, structure-wise, but it's more efficient. Also, not having it */
+ /* here makes it difficult to do proper overlaying later on. */
+ /* It starts off with a coordinate transform again. */
+ if(R.flag & R_LAMPHALO) {
+ if(vlaknr<=0) { /* bereken viewvec en zet R.co op far */
+
+ /* this view vector stuff should get its own function */
+ if( (G.special1 & G_HOLO) &&
+ ((Camera *)G.scene->camera->data)->flag & CAM_HOLO2) {
+ R.view[0]= (x+(R.xstart)+1.0+holoofs);
+ } else {
+ R.view[0]= (x+(R.xstart)+1.0);
+ }
+
+ if(R.flag & R_SEC_FIELD) {
+ if(R.r.mode & R_ODDFIELD) R.view[1]= (y+R.ystart+0.5)*R.ycor;
+ else R.view[1]= (y+R.ystart+1.5)*R.ycor;
+ } else {
+ R.view[1]= (y+R.ystart+1.0)*R.ycor;
+ }
+
+ R.view[2]= -R.viewfac;
+
+ if(R.r.mode & R_PANORAMA) {
+ float panoco, panosi;
+ panoco = getPanovCo();
+ panosi = getPanovSi();
+ u= R.view[0]; v= R.view[2];
+
+ R.view[0]= panoco*u + panosi*v;
+ R.view[2]= -panosi*u + panoco*v;
+ }
+
+ R.co[2]= 0.0;
+
+ }
+
+ shadeSpotHaloPixelFloat(collector);
+/* renderspothaloFix(collector); */
+
+ }
+
+#ifdef RE_PIXSHADE_FULL_SAFETY
+ if (!vlr) RE_error(RE_BAD_DATA_POINTER, fname);
+#endif
+
+ return vlr;
+
+} /* end of void renderFacePixelFloat(float x, float y, int vlaknr) */
+
+/* ------------------------------------------------------------------------- */
+/*
+ - uses R.view to determine which pixel, I think?
+ - the spothalo is dumped quite unceremoniously on top of the col vector
+ This function is also (sort of) implemented in shadespothalofix, but without
+ all the clipping stuff. Somehow, the clipping here is _quite_ critical.
+ */
+void shadeSpotHaloPixelFloat(float *col)
+{
+ LampRen *lar;
+ float factor = 0.0;
+ int a;
+ float rescol[4];
+
+
+ for(a=0; a<R.totlamp; a++) {
+ lar= R.la[a];
+ if(lar->type==LA_SPOT && (lar->mode & LA_HALO) && lar->haint>0) {
+
+ if(lar->org) {
+ lar->r= lar->org->r;
+ lar->g= lar->org->g;
+ lar->b= lar->org->b;
+ }
+
+ /* determines how much spothalo we see */
+ spotHaloFloat(lar, R.view, &factor);
+
+ if(factor>0.0) {
+
+ /* Why is alpha clipped? */
+ if(factor > RE_FULL_COLOUR_FLOAT) rescol[3]= 1.0;
+ else rescol[3]= factor;
+
+ /* erg vervelend: gammagecorrigeerd renderen EN addalphaADD */
+ /* gaat niet goed samen */
+ /* eigenlijk moet er een aparte 'optel' gamma komen */
+ /*
+ There is a strange thing here: the spothalo seems to be
+ calculated in the space you would get when you go from
+ value space through inverse gamma! So we gamma-transform
+ to value-space, then integrate, blend, and gamma correct
+ _again_.
+ */
+
+ rescol[0] = factor * lar->r; /* Lampren rgb's are floats */
+ rescol[1] = factor * lar->g;
+ rescol[2] = factor * lar->b;
+
+ /* ---->add values, disregard alpha */
+ /* - check for dest. alpha = 0. If so , just copy */
+ /* this is a slightly different approach: I do the gamma */
+ /* correction BEFORE the addition. What does the other */
+ /* approach do? */
+ if (col[3]< RE_EMPTY_COLOUR_FLOAT) {
+ col[0] = gammaCorrect(rescol[0]);
+ col[1] = gammaCorrect(rescol[1]);
+ col[2] = gammaCorrect(rescol[2]);
+ col[3] = rescol[3];
+ } else {
+ col[0] += gammaCorrect(rescol[0]);
+ col[1] += gammaCorrect(rescol[1]);
+ col[2] += gammaCorrect(rescol[2]);
+ col[3] += rescol[3];
+ }
+
+ /* this clipping may have to go? Actually, if it's */
+ /* done sooner, it may be more efficient */
+ if(col[0] > RE_FULL_COLOUR_FLOAT) col[0] = 1.0;
+ if(col[1] > RE_FULL_COLOUR_FLOAT) col[1] = 1.0;
+ if(col[2] > RE_FULL_COLOUR_FLOAT) col[2] = 1.0;
+ if(col[3] > RE_FULL_COLOUR_FLOAT) col[3] = 1.0;
+ if(col[0] < RE_EMPTY_COLOUR_FLOAT) col[0] = 0.0;
+ if(col[1] < RE_EMPTY_COLOUR_FLOAT) col[1] = 0.0;
+ if(col[2] < RE_EMPTY_COLOUR_FLOAT) col[2] = 0.0;
+ if(col[3] < RE_EMPTY_COLOUR_FLOAT) col[3] = 0.0;
+ }
+ }
+ }
+
+ if(col[0] < RE_EMPTY_COLOUR_FLOAT) col[0] = 0.0;
+ if(col[1] < RE_EMPTY_COLOUR_FLOAT) col[1] = 0.0;
+ if(col[2] < RE_EMPTY_COLOUR_FLOAT) col[2] = 0.0;
+ if(col[3] < RE_EMPTY_COLOUR_FLOAT) col[3] = 0.0;
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+void spotHaloFloat(struct LampRen *lar, float *view, float *intens)
+{
+ double a, b, c, disc, nray[3], npos[3];
+ float t0, t1 = 0.0, t2= 0.0, t3, haint;
+ float p1[3], p2[3], ladist, maxz = 0.0, maxy = 0.0;
+ int snijp, doclip=1, use_yco=0;
+ int ok1=0, ok2=0;
+
+ *intens= 0.0;
+ haint= lar->haint;
+
+ VECCOPY(npos, lar->sh_invcampos); /* in initlamp berekend */
+
+ /* view roteren */
+ VECCOPY(nray, view);
+ MTC_Mat3MulVecd(lar->imat, nray);
+
+ if(R.wrld.mode & WO_MIST) {
+ /* een beetje patch... */
+ R.zcor= -lar->co[2];
+ haint *= mistfactor(lar->co);
+ if(haint==0.0) {
+ return;
+ }
+ }
+
+
+ /* maxz roteren */
+ if(R.co[2]==0) doclip= 0; /* is als halo op sky */
+ else {
+ p1[0]= R.co[0]-lar->co[0];
+ p1[1]= R.co[1]-lar->co[1];
+ p1[2]= R.co[2]-lar->co[2];
+
+ maxz= lar->imat[0][2]*p1[0]+lar->imat[1][2]*p1[1]+lar->imat[2][2]*p1[2];
+ maxz*= lar->sh_zfac;
+ maxy= lar->imat[0][1]*p1[0]+lar->imat[1][1]*p1[1]+lar->imat[2][1]*p1[2];
+
+ if( fabs(nray[2]) <0.000001 ) use_yco= 1;
+ }
+
+ /* z scalen zodat het volume genormaliseerd is */
+ nray[2]*= lar->sh_zfac;
+ /* nray hoeft niet genormaliseerd */
+
+ ladist= lar->sh_zfac*lar->dist;
+
+ /* oplossen */
+ a = nray[0] * nray[0] + nray[1] * nray[1] - nray[2]*nray[2];
+ b = nray[0] * npos[0] + nray[1] * npos[1] - nray[2]*npos[2];
+ c = npos[0] * npos[0] + npos[1] * npos[1] - npos[2]*npos[2];
+
+ snijp= 0;
+ if (fabs(a) < 0.00000001) {
+ /*
+ * Only one intersection point...
+ */
+ return;
+ }
+ else {
+ disc = b*b - a*c;
+
+ if(disc==0.0) {
+ t1=t2= (-b)/ a;
+ snijp= 2;
+ }
+ else if (disc > 0.0) {
+ disc = sqrt(disc);
+ t1 = (-b + disc) / a;
+ t2 = (-b - disc) / a;
+ snijp= 2;
+ }
+ }
+ if(snijp==2) {
+ /* sorteren */
+ if(t1>t2) {
+ a= t1; t1= t2; t2= a;
+ }
+
+ /* z van snijpunten met diabolo */
+ p1[2]= npos[2] + t1*nray[2];
+ p2[2]= npos[2] + t2*nray[2];
+
+ /* beide punten evalueren */
+ if(p1[2]<=0.0) ok1= 1;
+ if(p2[2]<=0.0 && t1!=t2) ok2= 1;
+
+ /* minstens 1 punt met negatieve z */
+ if(ok1==0 && ok2==0) return;
+
+ /* snijpunt met -ladist, de bodem van de kegel */
+ if(use_yco==0) {
+ t3= (-ladist-npos[2])/nray[2];
+
+ /* moet 1 van de snijpunten worden vervangen? */
+ if(ok1) {
+ if(p1[2]<-ladist) t1= t3;
+ }
+ else {
+ ok1= 1;
+ t1= t3;
+ }
+ if(ok2) {
+ if(p2[2]<-ladist) t2= t3;
+ }
+ else {
+ ok2= 1;
+ t2= t3;
+ }
+ }
+ else if(ok1==0 || ok2==0) return;
+
+ /* minstens 1 zichtbaar snijpunt */
+ if(t1<0.0 && t2<0.0) return;
+
+ if(t1<0.0) t1= 0.0;
+ if(t2<0.0) t2= 0.0;
+
+ if(t1==t2) return;
+
+ /* voor zekerheid nog eens sorteren */
+ if(t1>t2) {
+ a= t1; t1= t2; t2= a;
+ }
+
+ /* t0 berekenen: is de maximale zichtbare z (als halo door vlak */
+ /* doorsneden wordt) */
+ if(doclip) {
+ if(use_yco==0) t0= (maxz-npos[2])/nray[2];
+ else t0= (maxy-npos[1])/nray[1];
+
+ if(t0<t1) return;
+ if(t0<t2) t2= t0;
+ }
+
+ /* bereken punten */
+ p1[0]= npos[0] + t1*nray[0];
+ p1[1]= npos[1] + t1*nray[1];
+ p1[2]= npos[2] + t1*nray[2];
+ p2[0]= npos[0] + t2*nray[0];
+ p2[1]= npos[1] + t2*nray[1];
+ p2[2]= npos[2] + t2*nray[2];
+
+
+ /* nu hebben we twee punten, hiermee maken we drie lengtes */
+
+ a= sqrt(p1[0]*p1[0]+p1[1]*p1[1]+p1[2]*p1[2]);
+ b= sqrt(p2[0]*p2[0]+p2[1]*p2[1]+p2[2]*p2[2]);
+ c= VecLenf(p1, p2);
+
+ a/= ladist;
+ a= sqrt(a);
+ b/= ladist;
+ b= sqrt(b);
+ c/= ladist;
+
+ *intens= c*( (1.0-a)+(1.0-b) );
+
+ /* LET OP: a,b en c NIET op 1.0 clippen, dit geeft kleine
+ overflowtjes op de rand (vooral bij smalle halo's) */
+ if(*intens<=0.0) return;
+
+ /* zachte gebied */
+ /* vervalt omdat t0 nu ook voor p1/p2 wordt gebruikt */
+ /* if(doclip && t0<t2) { */
+ /* *intens *= (t0-t1)/(t2-t1); */
+ /* } */
+
+ *intens *= haint;
+
+ if(lar->shb && lar->shb->shadhalostep) {
+ /* from shadbuf.c, returns float */
+ *intens *= shadow_halo(lar, p1, p2);
+ }
+ /* if(lar->mode & LA_TEXTURE) do_lamphalo_tex(lar, p1, p2, intens); */
+
+ }
+} /* end of void spotHaloFloat(struct LampRen *, float *view, float *intens) */
+
+/* ------------------------------------------------------------------------- */
+
+void shadeLampLusFloat()
+{
+ LampRen *lar;
+ register Material *ma;
+ float i, inp, inpr, t, lv[3], lampdist, ld = 0;
+ float ir, ig, ib;
+ float isr=0,isg=0,isb=0;
+ float lvrot[3], *vn, *view, shadfac, soft;
+ int a;
+ float shadfacvec[3] = {1.0, 1.0, 1.0};
+
+ vn= R.vn;
+ view= R.view;
+ ma= R.matren;
+
+ /* aparte lus */
+ if(ma->mode & MA_ONLYSHADOW) {
+ shadfac= ir= 0.0;
+ for(a=0; a<R.totlamp; a++) {
+ lar= R.la[a];
+
+ if(lar->mode & LA_LAYER) if((lar->lay & R.vlr->lay)==0) continue;
+
+ if(lar->shb) {
+ /* alleen testen binnen spotbundel */
+ lv[0]= R.co[0]-lar->co[0];
+ lv[1]= R.co[1]-lar->co[1];
+ lv[2]= R.co[2]-lar->co[2];
+ Normalise(lv);
+ inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2];
+ if(inpr>lar->spotsi) {
+
+ inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2];
+
+ RE_testshadowbuf(lar->shadowBufOb, lar->shb, inp, shadfacvec);
+/* testshadowbuf(lar->shb, inp, shadfacvec); */
+
+ i= shadfacvec[0];
+
+ t= inpr - lar->spotsi;
+ if(t<lar->spotbl && lar->spotbl!=0.0) {
+ t/= lar->spotbl;
+ t*= t;
+ i= t*i+(1.0-t);
+ }
+
+ shadfac+= i;
+ ir+= 1.0;
+ }
+ else {
+ shadfac+= 1.0;
+ ir+= 1.0;
+ }
+ }
+ }
+ if(ir>0.0) shadfac/= ir;
+ ma->alpha= (R.mat->alpha)*(1.0-shadfac);
+
+ collector[0] = 0.0;
+ collector[1] = 0.0;
+ collector[2] = 0.0;
+ /* alpha is not set.... why?*/
+ return;
+ }
+
+ if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) {
+ ma->r= R.vcol[0];
+ ma->g= R.vcol[1];
+ ma->b= R.vcol[2];
+ }
+
+ /* mirror reflection colour */
+ R.refcol[0]= R.refcol[1]= R.refcol[2]= R.refcol[3]= 0.0;
+
+ if(ma->texco) {
+
+ if(ma->texco & TEXCO_REFL) {
+ RE_calc_R_ref();
+ }
+
+ if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) {
+ R.mat->r= R.vcol[0];
+ R.mat->g= R.vcol[1];
+ R.mat->b= R.vcol[2];
+ }
+
+ do_material_tex();
+ }
+
+ if(ma->mode & MA_SHLESS) {
+ if( (ma->mode & (MA_VERTEXCOL+MA_VERTEXCOLP+MA_FACETEXTURE) )) {
+ ir= R.vcol[0]*ma->r;
+ ig= R.vcol[1]*ma->g;
+ ib= R.vcol[2]*ma->b;
+ }
+ else {
+ ir= ma->r; /* apparently stored as [0,1]? */
+ ig= ma->g;
+ ib= ma->b;
+ }
+
+ collector[0] = ir; /* no clipping, no alpha */
+ collector[1] = ig;
+ collector[2] = ib;
+ return;
+ }
+
+ if( (ma->mode & (MA_VERTEXCOL+MA_VERTEXCOLP))== MA_VERTEXCOL ) {
+ ir= ma->emit+R.vcol[0];
+ ig= ma->emit+R.vcol[1];
+ ib= ma->emit+R.vcol[2];
+ }
+ else ir= ig= ib= ma->emit;
+
+ for(a=0; a<R.totlamp; a++) {
+ lar= R.la[a];
+
+ /* test op lamplayer */
+ if(lar->mode & LA_LAYER) if((lar->lay & R.vlr->lay)==0) continue;
+
+ /* lampdist berekening */
+ if(lar->type==LA_SUN || lar->type==LA_HEMI) {
+ VECCOPY(lv, lar->vec);
+ lampdist= 1.0;
+ }
+ else {
+ lv[0]= R.co[0]-lar->co[0];
+ lv[1]= R.co[1]-lar->co[1];
+ lv[2]= R.co[2]-lar->co[2];
+ ld= sqrt(lv[0]*lv[0]+lv[1]*lv[1]+lv[2]*lv[2]);
+ lv[0]/= ld;
+ lv[1]/= ld;
+ lv[2]/= ld;
+
+ /* ld wordt verderop nog gebruikt (texco's) */
+
+ if(lar->mode & LA_QUAD) {
+ t= 1.0;
+ if(lar->ld1>0.0)
+ t= lar->dist/(lar->dist+lar->ld1*ld);
+ if(lar->ld2>0.0)
+ t*= lar->distkw/(lar->distkw+lar->ld2*ld*ld);
+
+ lampdist= t;
+ }
+ else {
+ lampdist= (lar->dist/(lar->dist+ld));
+ }
+
+ if(lar->mode & LA_SPHERE) {
+ t= lar->dist - ld;
+ if(t<0.0) continue;
+
+ t/= lar->dist;
+ lampdist*= (t);
+ }
+
+ }
+
+ if(lar->mode & LA_TEXTURE) do_lamp_tex(lar, lv);
+
+ if(lar->type==LA_SPOT) {
+
+ /* hier de fie Inp() vertaagt! */
+
+ if(lar->mode & LA_SQUARE) {
+ if(lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]>0.0) {
+ float x;
+
+ /* rotate view to lampspace */
+ VECCOPY(lvrot, lv);
+ MTC_Mat3MulVecfl(lar->imat, lvrot);
+
+ x= MAX2(fabs(lvrot[0]/lvrot[2]) , fabs(lvrot[1]/lvrot[2]));
+ /* 1.0/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */
+
+ inpr= 1.0/(sqrt(1+x*x));
+ }
+ else inpr= 0.0;
+ }
+ else {
+ inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2];
+ }
+
+ t= lar->spotsi;
+ if(inpr<t) continue;
+ else {
+ t= inpr-t;
+ i= 1.0;
+ soft= 1.0;
+ if(t<lar->spotbl && lar->spotbl!=0.0) {
+ /* zachte gebied */
+ i= t/lar->spotbl;
+ t= i*i;
+ soft= (3.0*t-2.0*t*i);
+ inpr*= soft;
+ }
+ if(lar->mode & LA_ONLYSHADOW && lar->shb) {
+ if(ma->mode & MA_SHADOW) {
+ /* inprodukt positief: voorzijde vlak! */
+ inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2];
+ if(inp>0.0) {
+
+ /* testshadowbuf==0.0 : 100% schaduw */
+ RE_testshadowbuf(lar->shadowBufOb, lar->shb, inp, shadfacvec);
+/* testshadowbuf(lar->shb, inp, shadfacvec); */
+ shadfac = 1.0 - shadfacvec[0];
+
+ if(shadfac>0.0) {
+ shadfac*= inp*soft*lar->energy;
+ ir -= shadfac;
+ ig -= shadfac;
+ ib -= shadfac;
+
+ continue;
+ }
+ }
+ }
+ }
+ lampdist*=inpr;
+ }
+ if(lar->mode & LA_ONLYSHADOW) continue;
+
+ if(lar->mode & LA_OSATEX) {
+ R.osatex= 1; /* signaal voor multitex() */
+
+ O.dxlv[0]= lv[0] - (R.co[0]-lar->co[0]+O.dxco[0])/ld;
+ O.dxlv[1]= lv[1] - (R.co[1]-lar->co[1]+O.dxco[1])/ld;
+ O.dxlv[2]= lv[2] - (R.co[2]-lar->co[2]+O.dxco[2])/ld;
+
+ O.dylv[0]= lv[0] - (R.co[0]-lar->co[0]+O.dyco[0])/ld;
+ O.dylv[1]= lv[1] - (R.co[1]-lar->co[1]+O.dyco[1])/ld;
+ O.dylv[2]= lv[2] - (R.co[2]-lar->co[2]+O.dyco[2])/ld;
+ }
+
+ }
+
+ /* inprodukt en reflectivity*/
+ inp=i= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2];
+ if(lar->type==LA_HEMI) {
+ i= 0.5*i+0.5;
+ }
+ if(i>0.0) {
+ i*= lampdist*ma->ref;
+ }
+
+ /* schaduw en spec */
+ if(i> -0.41) { /* beetje willekeurig, beetje getest */
+ shadfac= 1.0;
+ if(lar->shb) {
+ if(ma->mode & MA_SHADOW) {
+ float shadfacvec[3] = {1.0, 1.0, 1.0};
+ RE_testshadowbuf(lar->shadowBufOb, lar->shb, inp, shadfacvec);
+/* testshadowbuf(lar->shb, inp, shadfacvec); */
+ shadfac = shadfacvec[0];
+
+/* shadfac = 1.0; : no shadow */
+ if(shadfac==0.0) continue;
+ i*= shadfac;
+ }
+ }
+ /* specularity */
+
+ if(ma->spec!=0.0) {
+
+ if(lar->type==LA_SUN || lar->type==LA_HEMI) {
+ if(lar->type==LA_SUN) {
+ lv[2]-= 1.0;
+ }
+ else {
+ lv[0]+= view[0];
+ lv[1]+= view[1];
+ lv[2]+= view[2];
+ }
+
+ Normalise(lv);
+
+ t= vn[0]*lv[0]+vn[1]*lv[1]+vn[2]*lv[2];
+
+ if(lar->type==LA_HEMI) {
+ t= 0.5*t+0.5;
+ }
+ /* let op: shadfac en lampdist uit onderstaande */
+
+ /* no more speclim */
+
+ t= ma->spec*RE_Spec(t, ma->har);
+ isr+= t*(lar->r * ma->specr);
+ isg+= t*(lar->g * ma->specg);
+ isb+= t*(lar->b * ma->specb);
+ }
+ else {
+ /* Does specular reflection? This would be the place */
+ /* to put BRDFs. */
+ t= shadfac*ma->spec*lampdist*CookTorr(vn, lv, view, ma->har);
+ isr+= t*(lar->r * ma->specr);
+ isg+= t*(lar->g * ma->specg);
+ isb+= t*(lar->b * ma->specb);
+ }
+ }
+ }
+ if(i>0.0) {
+ ir+= i*lar->r;
+ ig+= i*lar->g;
+ ib+= i*lar->b;
+ }
+ }
+
+ /* clipping: maybe don't clip? (nzc) */
+ /* yes, it shouldn't be done... unfortunately the current
+ * gammaCorrect implementation doesn't handle negative values
+ * correctly ( (-1)^2 = 1!!) (ton)
+ */
+/* if(ir<0.0) ir= 0.0; */
+/* if(ig<0.0) ig= 0.0; */
+/* if(ib<0.0) ib= 0.0; */
+/* if(isr<0.0) isr= 0.0; */
+/* if(isg<0.0) isg= 0.0; */
+/* if(isb<0.0) isb= 0.0; */
+ /* Well, it does now. -(1^2) = -1 :) (nzc) */
+
+ if(ma->mode & MA_ZTRA) { /* ztra shade */
+ if(ma->spectra!=0.0) {
+
+ t = MAX3(isr, isb, isg);
+ t *= ma->spectra;
+ if(t>1.0) t= 1.0;
+ if(ma->mapto & MAP_ALPHA) ma->alpha= (1.0-t)*ma->alpha+t;
+ else ma->alpha= (1.0-t)*R.mat->alpha+t;
+ }
+ }
+
+ if(R.refcol[0]==0.0) {
+ collector[0] = (ma->r * ir) + ma->ambr + isr;
+ collector[1] = (ma->g * ig) + ma->ambg + isg;
+ collector[2] = (ma->b * ib) + ma->ambb + isb;
+ /* clip for >0 ? */
+ }
+ else {
+ collector[0] = (ma->mirr * R.refcol[1])
+ + ((1.0 - (ma->mirr * R.refcol[0])) * ((ma->r * ir) + ma->ambr))
+ + isr;
+ collector[1] = (ma->mirg*R.refcol[2])
+ + ((1.0 - (ma->mirg * R.refcol[0])) * ((ma->g * ig) +ma->ambg))
+ +isg;
+ collector[2] = (ma->mirb*R.refcol[3])
+ + ((1.0 - (ma->mirb * R.refcol[0])) * ((ma->b * ib) +ma->ambb))
+ +isb;
+ }
+
+#ifdef RE_FAKE_LAMP_SHADE
+ collector[0] = 0.5;
+ collector[1] = 0.5;
+ collector[2] = 1.0;
+#endif
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+void* renderHaloPixel(float x, float y, int haloNr) {
+ HaloRen *har = NULL;
+ float dist = 0.0;
+ unsigned int zz = 0;
+
+#ifdef RE_FAKE_HALO_PIXELS
+ collector[0] = RE_UNITY_COLOUR_FLOAT;
+ collector[1] = 0;
+ collector[2] = 0;
+ collector[3] = RE_UNITY_COLOUR_FLOAT;
+ har = RE_findOrAddHalo(haloNr); /* crash prevention */
+ return (void*) har;
+#endif
+
+ /* Find har to go with haloNr */
+ har = RE_findOrAddHalo(haloNr);
+
+ /* zz is a strange number... This call should effect that halo's are */
+ /* never cut? Seems a bit strange to me now... */
+ /* This might be the zbuffer depth */
+ zz = calcHaloZ(har, 0x7FFFFFFF);
+
+ /* distance of this point wrt. the halo center. Maybe xcor is also needed? */
+ dist = ((x - har->xs) * (x - har->xs))
+ + ((y - har->ys) * (y - har->ys) * R.ycor * R.ycor) ;
+
+ collector[0] = RE_ZERO_COLOUR_FLOAT; collector[1] = RE_ZERO_COLOUR_FLOAT;
+ collector[2] = RE_ZERO_COLOUR_FLOAT; collector[3] = RE_ZERO_COLOUR_FLOAT;
+
+ if (dist < har->radsq) {
+ shadeHaloFloat(har, collector, zz, dist,
+ (x - har->xs), (y - har->ys) * R.ycor, har->flarec);
+ /* make a second fake pixel? */
+#ifdef RE_FAKE_HALO_PIXELS_2
+ collector[0] = RE_UNITY_COLOUR_FLOAT;
+ collector[1] = 0;
+ collector[2] = 0;
+ collector[3] = RE_UNITY_COLOUR_FLOAT;
+#endif
+ }; /* else: this pixel is not rendered for this halo: no colour */
+
+ return (void*) har;
+
+} /* end of void* renderHaloPixel(float x, float y, int haloNr) */
+
+/* ------------------------------------------------------------------------- */
+
+extern float hashvectf[];
+void shadeHaloFloat(HaloRen *har,
+ float *col, unsigned int zz,
+ float dist, float xn,
+ float yn, short flarec)
+{
+ /* in col invullen */
+ /* migrate: fill collector */
+ float t, zn, radist, ringf=0.0, linef=0.0, alpha, si, co, colf[4];
+ int a;
+
+ if(R.wrld.mode & WO_MIST) {
+ if(har->type & HA_ONLYSKY) {
+ /* sterren geen mist */
+ alpha= har->alfa;
+ }
+ else {
+ /* een beetje patch... */
+ R.zcor= -har->co[2];
+ alpha= mistfactor(har->co)*har->alfa;
+ }
+ }
+ else alpha= har->alfa;
+
+ if(alpha==0.0) {
+ col[0] = 0.0;
+ col[1] = 0.0;
+ col[2] = 0.0;
+ col[3] = 0.0;
+ return;
+ }
+
+ radist= sqrt(dist);
+
+ /* let op: hiermee wordt gesjoemeld: flarec wordt op nul gezet in de pixstruct */
+ if(flarec) har->pixels+= (int)(har->rad-radist);
+
+ if(har->ringc) {
+ float *rc, fac;
+ int ofs;
+
+ /* per ring een alicirc */
+ ofs= har->seed;
+
+ for(a= har->ringc; a>0; a--, ofs+=2) {
+
+ rc= hashvectf + (ofs % 768);
+
+ fac= fabs( rc[1]*(har->rad*fabs(rc[0]) - radist) );
+
+ if(fac< 1.0) {
+ ringf+= (1.0-fac);
+ }
+ }
+ }
+
+ if(har->type & HA_VECT) {
+ dist= fabs( har->cos*(yn) - har->sin*(xn) )/har->rad;
+ if(dist>1.0) dist= 1.0;
+ if(har->tex) {
+ zn= har->sin*xn - har->cos*yn;
+ yn= har->cos*xn + har->sin*yn;
+ xn= zn;
+ }
+ }
+ else dist= dist/har->radsq;
+
+ if(har->type & HA_FLARECIRC) {
+
+ dist= 0.5+fabs(dist-0.5);
+
+ }
+
+ if(har->hard>=30) {
+ dist= sqrt(dist);
+ if(har->hard>=40) {
+ dist= sin(dist*M_PI_2);
+ if(har->hard>=50) {
+ dist= sqrt(dist);
+ }
+ }
+ }
+ else if(har->hard<20) dist*=dist;
+
+ dist=(1.0-dist);
+
+ if(har->linec) {
+ float *rc, fac;
+ int ofs;
+
+ /* per starpoint een aliline */
+ ofs= har->seed;
+
+ for(a= har->linec; a>0; a--, ofs+=3) {
+
+ rc= hashvectf + (ofs % 768);
+
+ fac= fabs( (xn)*rc[0]+(yn)*rc[1]);
+
+ if(fac< 1.0 ) {
+ linef+= (1.0-fac);
+ }
+ }
+
+ linef*= dist;
+
+ }
+
+ if(har->starpoints) {
+ float ster, hoek;
+ /* rotatie */
+ hoek= atan2(yn, xn);
+ hoek*= (1.0+0.25*har->starpoints);
+
+ co= cos(hoek);
+ si= sin(hoek);
+
+ hoek= (co*xn+si*yn)*(co*yn-si*xn);
+
+ ster= fabs(hoek);
+ if(ster>1.0) {
+ ster= (har->rad)/(ster);
+
+ if(ster<1.0) dist*= sqrt(ster);
+ }
+ }
+
+ /* halo wordt doorsneden? */
+ if(har->zs> zz-har->zd) {
+ t= ((float)(zz-har->zs))/(float)har->zd;
+ alpha*= sqrt(sqrt(t));
+ }
+
+ dist*= alpha;
+ ringf*= dist;
+ linef*= alpha;
+
+ if(dist<0.003) {
+ col[0] = 0.0;
+ col[1] = 0.0;
+ col[2] = 0.0;
+ col[3] = 0.0;
+ return;
+ }
+
+ /* The colour is either the rgb spec-ed by the user, or extracted from */
+ /* the texture */
+ if(har->tex) {
+ colf[3]= dist;
+ do_halo_tex(har, xn, yn, colf);
+ colf[0]*= colf[3];
+ colf[1]*= colf[3];
+ colf[2]*= colf[3];
+
+ }
+ else {
+ colf[0]= dist*har->r;
+ colf[1]= dist*har->g;
+ colf[2]= dist*har->b;
+ if(har->type & HA_XALPHA) colf[3]= dist*dist;
+ else colf[3]= dist;
+ }
+
+ if(har->mat && har->mat->mode & MA_HALO_SHADE) {
+ /* we test for lights because of preview... */
+ if(R.totlamp) render_lighting_halo(har, colf);
+ }
+
+ /* Next, we do the line and ring factor modifications. It seems we do */
+ /* uchar calculations, but it's basically doing float arith with a 255 */
+ /* scale factor. */
+ if(linef!=0.0) {
+ Material *ma= har->mat;
+ linef *= 255.0;
+
+ colf[0]+= linef * ma->specr;
+ colf[1]+= linef * ma->specg;
+ colf[2]+= linef * ma->specb;
+
+ if(har->type & HA_XALPHA) colf[3]+= linef*linef;
+ else colf[3]+= linef;
+ }
+ if(ringf!=0.0) {
+ Material *ma= har->mat;
+ ringf *= 255.0;
+
+ colf[0]+= ringf * ma->mirr;
+ colf[1]+= ringf * ma->mirg;
+ colf[2]+= ringf * ma->mirb;
+
+ if(har->type & HA_XALPHA) colf[3]+= ringf*ringf;
+ else colf[3]+= ringf;
+ }
+
+ /* convert to [0.0; 1.0] range */
+ col[0] = colf[0] / 255.0;
+ col[1] = colf[1] / 255.0;
+ col[2] = colf[2] / 255.0;
+ col[3] = colf[3];
+
+} /* end of shadeHaloFloat() */
+
+/* ------------------------------------------------------------------------- */
+
+void renderSpotHaloPixel(float x, float y, float* target)
+{
+ float u = 0.0, v = 0.0;
+
+#ifdef RE_FAKE_SPOTHALO_PIXELS
+ target[0] = 0.0;
+ target[1] = 1.0;
+ target[2] = 0.0;
+ target[3] = 1.0;
+ return;
+#endif
+
+ /* Strange fix? otherwise done inside shadepixel. It's sort */
+ /* of like telling this is a 'sky' pixel. */
+ R.vlaknr = 0;
+ target[3] = 0.0;
+
+ /*
+ Here's the viewvector setting again.
+ */
+ if( (G.special1 & G_HOLO) && ((Camera *)G.scene->camera->data)->flag & CAM_HOLO2) {
+ R.view[0]= (x+(R.xstart)+1.0+holoofs);
+ }
+ else {
+ R.view[0]= (x+(R.xstart)+1.0);
+ }
+
+ if(R.flag & R_SEC_FIELD) {
+ if(R.r.mode & R_ODDFIELD) R.view[1]= (y+R.ystart+0.5)*R.ycor;
+ else R.view[1]= (y+R.ystart+1.5)*R.ycor;
+ }
+ else R.view[1]= (y+R.ystart+1.0)*R.ycor;
+
+ R.view[2]= -R.viewfac;
+
+ if(R.r.mode & R_PANORAMA) {
+ float panoco, panosi;
+ panoco = getPanovCo();
+ panosi = getPanovSi();
+ u= R.view[0]; v= R.view[2];
+
+ R.view[0]= panoco*u + panosi*v;
+ R.view[2]= -panosi*u + panoco*v;
+ }
+
+ R.co[2]= 0.0;
+
+ /* This little function is a patch for spothalos on non-covered pixels. */
+ renderspothaloFix(target);
+
+} /* end of void renderSpotHaloPixel(float x, float y, float colbuf[4]) */
+
+/* ------------------------------------------------------------------------- */
+/*
+ This routine is only for sky-pixels. Therefore, no gamma needs to be done.
+ One strange side-effect is when you have a negative halo lamp. This suddenly
+ gives loads of colour. That particular case has been explicitly guarded: no
+ halo for negative halo spots!
+
+ This routine uses the viewvector in R... to determine what to shade. Just
+ deposit the colour to be blended in col.
+
+ I would like to add colours 'normally', so this routine would be the same
+ for spothalo on covered pixels, but that doesn't work. Some strange clipping
+ occurs...
+ */
+void renderspothaloFix(float *col)
+{
+ LampRen *lar;
+ float i;
+ int a;
+
+ for(a=0; a<R.totlamp; a++) {
+ lar= R.la[a];
+ if((lar->type==LA_SPOT)
+ && (lar->mode & LA_HALO)
+ && !(lar->mode & LA_NEG)
+ && (lar->haint>0)) {
+
+ if(lar->org) {
+ lar->r= lar->org->r;
+ lar->g= lar->org->g;
+ lar->b= lar->org->b;
+ }
+
+ /* returns the intensity in i */
+ spotHaloFloat(lar, R.view, &i);
+
+ if(i>0.0) {
+ /* Premul colours here! */
+ col[0] = i * lar->r;
+ col[1] = i * lar->g;
+ col[2] = i * lar->b;
+ col[3] = i;
+ }
+ }
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+
+ There are three different modes for blending sky behind a picture:
+ 1. sky = blend in sky directly
+ 2. premul = don't do sky, but apply alpha (so pretend the picture ends
+ exactly at it's boundaries)
+ 3. key = don't do anything
+ Now the stupid thing is that premul means do nothing for us, and key
+ we have to adjust a bit...
+
+*/
+
+/* Sky vars. */
+enum RE_SkyAlphaBlendingType keyingType = RE_ALPHA_SKY; /* The blending type */
+
+void setSkyBlendingMode(enum RE_SkyAlphaBlendingType mode) {
+ if ((RE_ALPHA_NODEF < mode) && (mode < RE_ALPHA_MAX) ) {
+ keyingType = mode;
+ } else {
+ /* error: false mode received */
+ keyingType = RE_ALPHA_SKY;
+ }
+}
+
+enum RE_SkyAlphaBlendingType getSkyBlendingMode() {
+ return keyingType;
+}
+
+/* This one renders into collector, as always. */
+void renderSkyPixelFloat(float x, float y)
+{
+#ifdef RE_FAKE_SKY_PIXELS
+ collector[0] = 1.0;
+ collector[1] = 1.0;
+ collector[2] = 0.0;
+ collector[3] = 1.0;
+ return;
+#endif
+
+ switch (keyingType) {
+ case RE_ALPHA_PREMUL:
+ /* Premul: don't fill, and don't change the values! */
+ case RE_ALPHA_KEY:
+ /*
+ Key: Leave pixels fully coloured, but retain alpha data, so you
+ can composit the picture later on.
+ - Should operate on the stack outcome!
+ */
+/* collector[0] = 0.0; */
+/* collector[1] = 0.0; */
+/* collector[2] = 0.0; */
+/* collector[3] = 0.0; */
+ collector[3]= 0.0;
+ collector[0]= R.wrld.horr;
+ collector[1]= R.wrld.horg;
+ collector[2]= R.wrld.horb;
+ break;
+ case RE_ALPHA_SKY:
+ /* Fill in the sky as if it were a normal face. */
+ shadeSkyPixel(x, y);
+ break;
+ default:
+ ; /* Error: illegal alpha blending state */
+ }
+}
+
+/*
+ Stuff the sky colour into the collector.
+ */
+void shadeSkyPixel(float fx, float fy) {
+
+ /*
+ The rules for sky:
+ 1. Draw an image, if a background image was provided. Stop
+ 2. get texture and colour blend, and combine these.
+ */
+
+ float fac;
+
+ /* 1. Do a backbuffer image: */
+ if(R.r.bufflag & 1) {
+ fillBackgroundImage(fx, fy);
+ return;
+ } else if((R.wrld.skytype & (WO_SKYBLEND+WO_SKYTEX))==0) {
+ /*
+ 2. Test for these types of sky. The old renderer always had to check for
+ coverage, but we don't need that anymore
+ - SKYBLEND or SKYTEX disabled: fill in a flat colour
+ - otherwise, do the appropriate mapping (tex or colour blend)
+ There used to be cached chars here, but they are not useful anymore
+ */
+ collector[0] = R.wrld.horr;
+ collector[1] = R.wrld.horg;
+ collector[2] = R.wrld.horb;
+ collector[3] = RE_UNITY_COLOUR_FLOAT;
+ } else {
+ /*
+ 3. Which type(s) is(are) this (these)? This has to be done when no simple
+ way of determining the colour exists.
+ */
+
+ /* This one true because of the context of this routine */
+/* if(rect[3] < 254) { */
+ if(R.wrld.skytype & WO_SKYPAPER) {
+ R.view[0]= (fx+(R.xstart))/(float)R.afmx;
+ R.view[1]= (fy+(R.ystart))/(float)R.afmy;
+ R.view[2]= 0.0;
+ }
+ else {
+ /* Wasn't this some pano stuff? */
+ R.view[0]= (fx+(R.xstart)+1.0);
+
+ if(R.flag & R_SEC_FIELD) {
+ if(R.r.mode & R_ODDFIELD) R.view[1]= (fy+R.ystart+0.5)*R.ycor;
+ else R.view[1]= (fy+R.ystart+1.5)*R.ycor;
+ }
+ else R.view[1]= (fy+R.ystart+1.0)*R.ycor;
+
+ R.view[2]= -R.viewfac;
+
+ fac= Normalise(R.view);
+ if(R.wrld.skytype & WO_SKYTEX) {
+ O.dxview= 1.0/fac;
+ O.dyview= R.ycor/fac;
+ }
+ }
+
+ if(R.r.mode & R_PANORAMA) {
+ float panoco, panosi;
+ float u, v;
+
+ panoco = getPanovCo();
+ panosi = getPanovSi();
+ u= R.view[0]; v= R.view[2];
+
+ R.view[0]= panoco*u + panosi*v;
+ R.view[2]= -panosi*u + panoco*v;
+ }
+
+ /* get sky colour in the collector */
+ shadeSkyPixelFloat(fy);
+ }
+
+
+}
+
+/* Only line number is important here. Result goes to collector[4] */
+void shadeSkyPixelFloat(float y)
+{
+
+ /* Why is this setting forced? Seems silly to me. It is tested in the texture unit. */
+ R.wrld.skytype |= WO_ZENUP;
+
+ /* Some view vector stuff. */
+ if(R.wrld.skytype & WO_SKYREAL) {
+
+ R.inprz= R.view[0]*R.grvec[0]+ R.view[1]*R.grvec[1]+ R.view[2]*R.grvec[2];
+
+ if(R.inprz<0.0) R.wrld.skytype-= WO_ZENUP;
+ R.inprz= fabs(R.inprz);
+ }
+ else if(R.wrld.skytype & WO_SKYPAPER) {
+ R.inprz= 0.5+ 0.5*R.view[1];
+ }
+ else {
+ /* the fraction of how far we are above the bottom of the screen */
+ R.inprz= fabs(0.5+ R.view[1]);
+ }
+
+ /* Careful: SKYTEX and SKYBLEND are NOT mutually exclusive! If */
+ /* SKYBLEND is active, the texture and colour blend are added. */
+ if(R.wrld.skytype & WO_SKYTEX) {
+ VECCOPY(R.lo, R.view);
+ if(R.wrld.skytype & WO_SKYREAL) {
+
+ MTC_Mat3MulVecfl(R.imat, R.lo);
+
+ SWAP(float, R.lo[1], R.lo[2]);
+
+ }
+
+ R.osatex= 0;
+
+ /* sky texture? I wonder how this manages to work... */
+ /* Does this communicate with R.wrld.hor{rgb}? Yes. */
+ do_sky_tex();
+ /* internally, T{rgb} are used for communicating colours in the */
+ /* texture pipe, externally, this particular routine uses the */
+ /* R.wrld.hor{rgb} thingies. */
+
+ }
+
+ /* Why are this R. members? */
+ if(R.inprz>1.0) R.inprz= 1.0;
+ R.inprh= 1.0-R.inprz;
+
+ /* No clipping, no conversion! */
+ if(R.wrld.skytype & WO_SKYBLEND) {
+ collector[0] = (R.inprh*R.wrld.horr + R.inprz*R.wrld.zenr);
+ collector[1] = (R.inprh*R.wrld.horg + R.inprz*R.wrld.zeng);
+ collector[2] = (R.inprh*R.wrld.horb + R.inprz*R.wrld.zenb);
+ } else {
+ /* Done when a texture was grabbed. */
+ collector[0]= R.wrld.horr;
+ collector[1]= R.wrld.horg;
+ collector[2]= R.wrld.horb;
+ }
+
+ collector[3]= RE_UNITY_COLOUR_FLOAT;
+ /* om verkeerde optimalisatie alphaover van flares te voorkomen */
+ /* ??? seems strange to me... This used to be a 1 when the colours */
+ /* were chars. might need a separate flag for this... */
+}
+
+
+/*
+ Render pixel (x,y) from the backbuffer into the collector
+
+ backbuf is type Image, backbuf->ibuf is an ImBuf. ibuf->rect is the
+ rgba data (32 bit total), in ibuf->x by ibuf->y pixels. Copying
+ should be really easy. I hope I understand the way ImBuf works
+ correctly. (nzc)
+*/
+void fillBackgroundImage(float x, float y)
+{
+
+ int iy, ix;
+ unsigned int* imBufPtr;
+ char *colSource;
+
+ /* This double check is bad... */
+ if (!(R.backbuf->ok)) {
+ /* Something went sour here... bail... */
+ collector[0] = 0.0;
+ collector[1] = 0.0;
+ collector[2] = 0.0;
+ collector[3] = 1.0;
+ return;
+ }
+ /* load image if not already done?*/
+ if(R.backbuf->ibuf==0) {
+ R.backbuf->ibuf= IMB_loadiffname(R.backbuf->name, IB_rect);
+ if(R.backbuf->ibuf==0) {
+ /* load failed .... keep skipping */
+ R.backbuf->ok= 0;
+ return;
+ }
+ }
+
+ /* Now for the real extraction: */
+ /* Get the y-coordinate of the scanline? */
+ iy= (int) ((y+R.afmy+R.ystart)*R.backbuf->ibuf->y)/(2*R.afmy);
+ ix= (int) ((x+R.afmx+R.xstart)*R.backbuf->ibuf->x)/(2*R.afmx);
+
+ /* correct in case of fields rendering: */
+ if(R.flag & R_SEC_FIELD) {
+ if((R.r.mode & R_ODDFIELD)==0) {
+ if( iy<R.backbuf->ibuf->y) iy++;
+ }
+ else {
+ if( iy>0) iy--;
+ }
+ }
+
+ /* Offset into the buffer: start of scanline y: */
+ imBufPtr = R.backbuf->ibuf->rect
+ + (iy * R.backbuf->ibuf->x)
+ + ix;
+
+ colSource = (char*) imBufPtr;
+
+ cpCharColV2FloatColV(colSource, collector);
+
+}
+
+/* eof */
diff --git a/source/blender/render/intern/source/renderHelp.c b/source/blender/render/intern/source/renderHelp.c
new file mode 100644
index 00000000000..c7294d0feeb
--- /dev/null
+++ b/source/blender/render/intern/source/renderHelp.c
@@ -0,0 +1,294 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Some helpful conversions/functions.
+ *
+ * $Id$
+ */
+
+#include <math.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#include "render.h"
+#include "render_intern.h"
+#include "renderHelp.h"
+#include "zbuf.h"
+
+
+
+static float panovco, panovsi;
+static float panophi=0.0;
+static float tempPanoPhi;
+
+static int panotestclip(float *v);
+
+void pushTempPanoPhi(float p) {
+ tempPanoPhi = panophi;
+ panophi = p;
+}
+
+void popTempPanoPhi() {
+ panophi = tempPanoPhi;
+}
+
+float getPanoPhi(){
+ return panophi;
+}
+float getPanovCo(){
+ return panovco;
+}
+float getPanovSi(){
+ return panovsi;
+}
+
+void setPanoRot(int part)
+{
+/* extern float panovco, panovsi; */
+ static float alpha= 1.0;
+
+ /* part==0 alles initialiseren */
+
+ if(part==0) {
+
+ alpha= ((float)R.r.xsch)/R.viewfac;
+ alpha= 2.0*atan(alpha/2.0);
+ }
+
+
+ /* we roteren alles om de y-as met phi graden */
+
+ panophi= -0.5*(R.r.xparts-1)*alpha + part*alpha;
+
+ panovsi= sin(-panophi);
+ panovco= cos(-panophi);
+
+}
+
+
+
+
+static int panotestclip(float *v)
+{
+ /* gebruiken voor halo's en info's */
+ float abs4;
+ short c=0;
+
+ if((R.r.mode & R_PANORAMA)==0) return RE_testclip(v);
+
+ abs4= fabs(v[3]);
+
+ if(v[2]< -abs4) c=16; /* hier stond vroeger " if(v[2]<0) ", zie clippz() */
+ else if(v[2]> abs4) c+= 32;
+
+ if( v[1]>abs4) c+=4;
+ else if( v[1]< -abs4) c+=8;
+
+ abs4*= R.r.xparts;
+ if( v[0]>abs4) c+=2;
+ else if( v[0]< -abs4) c+=1;
+
+ return c;
+}
+
+/*
+
+ This adds the hcs coordinates to vertices. It iterates over all
+ vertices, halos and faces. After the conversion, we clip in hcs.
+
+ Elsewhere, all primites are converted to vertices.
+ Called in
+ - envmapping (envmap.c)
+ - shadow buffering (shadbuf.c)
+ - preparation for rendering (renderPreAndPost.c)
+
+*/
+
+/* move to renderer */
+void setzbufvlaggen( void (*projectfunc)(float *, float *) )
+/* ook homoco's */
+{
+ VlakRen *vlr = NULL;
+ VertRen *ver = NULL;
+ HaloRen *har = NULL;
+ float zn, vec[3], si, co, hoco[4];
+ int a;
+ float panophi = 0.0;
+
+ panophi = getPanoPhi();
+ si= sin(panophi);
+ co= cos(panophi);
+
+ /* calculate view coordinates (and zbuffer value) */
+ for(a=0; a< R.totvert;a++) {
+ if((a & 255)==0) ver= R.blove[a>>8];
+ else ver++;
+
+ if(R.r.mode & R_PANORAMA) {
+ vec[0]= co*ver->co[0] + si*ver->co[2];
+ vec[1]= ver->co[1];
+ vec[2]= -si*ver->co[0] + co*ver->co[2];
+ }
+ else {
+ VECCOPY(vec, ver->co);
+ }
+ /* Go from wcs to hcs ... */
+ projectfunc(vec, ver->ho);
+ /* ... and clip in that system. */
+ ver->clip = RE_testclip(ver->ho);
+ /*
+ Because all other ops are performed in other systems, this is
+ the only thing that has to be done.
+ */
+ }
+
+ /* calculate view coordinates (and zbuffer value) */
+ for(a=0; a<R.tothalo; a++) {
+ if((a & 255)==0) har= R.bloha[a>>8];
+ else har++;
+
+ if(R.r.mode & R_PANORAMA) {
+ vec[0]= co*har->co[0] + si*har->co[2];
+ vec[1]= har->co[1];
+ vec[2]= -si*har->co[0] + co*har->co[2];
+ }
+ else {
+ VECCOPY(vec, har->co);
+ }
+
+ projectfunc(vec, hoco);
+
+ hoco[3]*= 2.0;
+
+ if( panotestclip(hoco) ) {
+ har->miny= har->maxy= -10000; /* de render clipt 'm weg */
+ }
+ else if(hoco[3]<0.0) {
+ har->miny= har->maxy= -10000; /* de render clipt 'm weg */
+ }
+ else /* this seems to be strange code here...*/
+ {
+ zn= hoco[3]/2.0;
+ har->xs= 0.5*R.rectx*(1.0+hoco[0]/zn); /* the 0.5 negates the previous 2...*/
+ har->ys= 0.5*R.recty*(1.0+hoco[1]/zn);
+
+ /* this should be the zbuffer coordinate */
+ har->zs= 0x7FFFFF*(1.0+hoco[2]/zn);
+ /* taking this from the face clip functions? seems ok... */
+ har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn);
+ vec[0]+= har->hasize;
+ projectfunc(vec, hoco);
+ vec[0]-= har->hasize;
+ zn= hoco[3];
+ har->rad= fabs(har->xs- 0.5*R.rectx*(1.0+hoco[0]/zn));
+
+ /* deze clip is eigenlijk niet OK */
+ if(har->type & HA_ONLYSKY) {
+ if(har->rad>3.0) har->rad= 3.0;
+ }
+
+ har->radsq= har->rad*har->rad;
+
+ har->miny= har->ys - har->rad/R.ycor;
+ har->maxy= har->ys + har->rad/R.ycor;
+
+ /* de Zd is bij pano nog steeds verkeerd: zie testfile in blenderbugs/halo+pano.blend */
+
+ vec[2]-= har->hasize; /* z is negatief, wordt anders geclipt */
+ projectfunc(vec, hoco);
+ zn= hoco[3];
+ zn= fabs(har->zs - 0x7FFFFF*(1.0+hoco[2]/zn));
+ har->zd= CLAMPIS(zn, 0, INT_MAX);
+
+ /* if( har->zs < 2*har->zd) { */
+ /* PRINT2(d, d, har->zs, har->zd); */
+ /* har->alfa= har->mat->alpha * ((float)(har->zs))/(float)(2*har->zd); */
+ /* } */
+
+ }
+
+ }
+
+ /* vlaggen op 0 zetten als eruit geclipt */
+ for(a=0; a<R.totvlak; a++) {
+ if((a & 255)==0) vlr= R.blovl[a>>8];
+ else vlr++;
+
+ vlr->flag |= R_VISIBLE;
+ if(vlr->v4) {
+ if(vlr->v1->clip & vlr->v2->clip & vlr->v3->clip & vlr->v4->clip) vlr->flag &= ~R_VISIBLE;
+ }
+ else if(vlr->v1->clip & vlr->v2->clip & vlr->v3->clip) vlr->flag &= ~R_VISIBLE;
+
+ }
+
+}
+
+/* ------------------------------------------------------------------------- */
+/* move to renderer */
+
+void set_normalflags(void)
+{
+ VlakRen *vlr = NULL;
+ float vec[3], xn, yn, zn;
+ int a1;
+
+ /* KLAP NORMAAL EN SNIJ PROJECTIE */
+ for(a1=0; a1<R.totvlak; a1++) {
+ if((a1 & 255)==0) vlr= R.blovl[a1>>8];
+ else vlr++;
+
+ if(vlr->flag & R_NOPUNOFLIP) {
+ /* render normaal flippen, wel niet zo netjes, maar anders dan moet de render() ook over... */
+ vlr->n[0]= -vlr->n[0];
+ vlr->n[1]= -vlr->n[1];
+ vlr->n[2]= -vlr->n[2];
+ }
+ else {
+
+ vec[0]= vlr->v1->co[0];
+ vec[1]= vlr->v1->co[1];
+ vec[2]= vlr->v1->co[2];
+
+ if( (vec[0]*vlr->n[0] +vec[1]*vlr->n[1] +vec[2]*vlr->n[2])<0.0 ) {
+ vlr->puno= ~(vlr->puno);
+ vlr->n[0]= -vlr->n[0];
+ vlr->n[1]= -vlr->n[1];
+ vlr->n[2]= -vlr->n[2];
+ }
+ }
+ xn= fabs(vlr->n[0]);
+ yn= fabs(vlr->n[1]);
+ zn= fabs(vlr->n[2]);
+ if(zn>=xn && zn>=yn) vlr->snproj= 0;
+ else if(yn>=xn && yn>=zn) vlr->snproj= 1;
+ else vlr->snproj= 2;
+
+ }
+}
diff --git a/source/blender/render/intern/source/renderPreAndPost.c b/source/blender/render/intern/source/renderPreAndPost.c
new file mode 100644
index 00000000000..761ac75d430
--- /dev/null
+++ b/source/blender/render/intern/source/renderPreAndPost.c
@@ -0,0 +1,94 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Prepare the scene data for rendering.
+ *
+ * $Id$
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "render.h"
+#include "render_intern.h"
+#include "renderPreAndPost.h"
+#include "RE_callbacks.h"
+
+#include "shadbuf.h"
+#include "envmap.h"
+#include "renderHelp.h"
+#include "shadowBuffer.h"
+
+/**
+ * Rotate all objects, make shadowbuffers and environment maps.
+ */
+void prepareScene()
+{
+ int a;
+
+
+ if(R.rectot) MEM_freeN(R.rectot);
+ R.rectot= 0;
+ if(R.rectz) MEM_freeN(R.rectz);
+ R.rectz= 0;
+
+ RE_local_get_renderdata();
+
+ /* SCHADUWBUFFER */
+ for(a=0; a<R.totlamp; a++) {
+ if(RE_local_test_break()) break;
+ /* Again, switch between old and new shadowing system. The
+ * buffer objects were initially created in
+ * blenderWorldManipulation.c */
+ if (R.r.mode & R_UNIFIED) {
+ if (R.la[a]->shadowBufOb) {
+ RE_buildShadowBuffer(R.la[a]->shadowBufOb,
+ R.la[a]);
+ }
+ } else {
+ if(R.la[a]->shb) makeshadowbuf(R.la[a]);
+ }
+ }
+
+ /* ENVIRONMENT MAPS */
+ make_envmaps();
+}
+
+void finalizeScene(void)
+{
+ /* Among other things, it releases the shadow buffers. */
+ RE_local_free_renderdata();
+}
+
+
+void doClipping( void (*projectfunc)(float *, float *) )
+{
+ setzbufvlaggen(projectfunc);
+}
+
+/* eof */
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
new file mode 100644
index 00000000000..32db34d7ac6
--- /dev/null
+++ b/source/blender/render/intern/source/rendercore.c
@@ -0,0 +1,2902 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/* system includes */
+#include <math.h>
+#include <string.h>
+#include <stdlib.h>
+
+/* External modules: */
+#include "MEM_guardedalloc.h"
+#include "BLI_arithb.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+#include "MTC_matrixops.h"
+#include "BKE_utildefines.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_image_types.h"
+#include "DNA_object_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_lamp_types.h"
+
+#include "BKE_global.h"
+#include "BKE_texture.h"
+
+/* local include */
+#include "RE_callbacks.h"
+#include "old_zbuffer_types.h"
+#include "render.h"
+#include "render_intern.h"
+#include "zbuf.h" /* stuff like bgnaccumbuf, fillrect, ...*/
+#include "pixelblending.h"
+#include "shadbuf.h"
+#include "renderHelp.h"
+
+#include "jitter.h"
+
+/* own include */
+#include "rendercore.h"
+#include "rendercore_int.h"
+
+/* globals for this file */
+/* moved to renderData.c? Not yet... */
+RE_Render R;
+Osa O;
+
+extern float Zjitx,Zjity, Zmulx, Zmuly;
+PixStrMain psmfirst;
+int psmteller;
+
+float holoofs= 0.0, fmask[256], centLut[16];
+unsigned short usegamtab=0, shortcol[4], *mask1[9], *mask2[9], *igamtab1, *igamtab2, *gamtab;
+char cmask[256], *centmask;
+
+/* functions */
+/* comes from texture.c (only used here !) */
+/* extern void do_halo_tex(HaloRen *har, float xn, float yn, float *colf); */
+
+void gamtabdit(unsigned short *in, char *out);
+/* int count_mask(unsigned short ); */
+void scanlinehalo(unsigned int *rectz, unsigned int *rectt, short ys);
+/* void add_halo_flare(void); */
+void edge_enhance(void);
+
+/* Dither with gamma table? */
+void gamtabdit(unsigned short *in, char *out)
+/* unsigned short *in; */
+/* char *out; */
+{
+ static short rerr=0, gerr=0, berr=0;
+ unsigned int col;
+ char *cp;
+
+ cp= (char *)&col;
+ out[0]= in[0]>>8;
+
+ col= gamtab[in[2]]+berr;
+ if(col>65535) col= 65535;
+ out[1]= cp[2];
+ berr= cp[3];
+
+ col= gamtab[in[4]]+gerr;
+ if(col>65535) col= 65535;
+ out[2]= cp[2];
+ gerr= cp[3];
+
+ col= gamtab[in[6]]+rerr;
+ if(col>65535) col= 65535;
+ out[3]= cp[2];
+ rerr= cp[3];
+
+}
+
+float mistfactor(float *co) /* dist en hoogte, return alpha */
+{
+ float fac, hi;
+
+ fac= R.zcor - R.wrld.miststa; /* R.zcor wordt per pixel berekend */
+
+ /* fac= -co[2]-R.wrld.miststa; */
+
+ if(fac>0.0) {
+ if(fac< R.wrld.mistdist) {
+
+ fac= (fac/(R.wrld.mistdist));
+
+ if(R.wrld.mistype==0) fac*= fac;
+ else if(R.wrld.mistype==1);
+ else fac= sqrt(fac);
+ }
+ else fac= 1.0;
+ }
+ else fac= 0.0;
+
+ /* de hoogte schakelt de mist af */
+ if(R.wrld.misthi!=0.0 && fac!=0.0) {
+ /* op hoogte misthi is mist volledig weg */
+
+ hi= R.viewinv[0][2]*co[0]+R.viewinv[1][2]*co[1]+R.viewinv[2][2]*co[2]+R.viewinv[3][2];
+
+ if(hi>R.wrld.misthi) fac= 0.0;
+ else if(hi>0.0) {
+ hi= (R.wrld.misthi-hi)/R.wrld.misthi;
+ fac*= hi*hi;
+ }
+ }
+
+ return 1.0-fac;
+}
+
+void RE_sky(char *col)
+{
+ float rf, gf, bf;
+
+ if((R.wrld.skytype & (WO_SKYBLEND+WO_SKYTEX))==0) {
+ *( (unsigned int *)col)= R.wrld.fastcol;
+ return;
+ }
+
+ R.wrld.skytype |= WO_ZENUP;
+
+ if(R.wrld.skytype & WO_SKYREAL) {
+
+ R.inprz= R.view[0]*R.grvec[0]+ R.view[1]*R.grvec[1]+ R.view[2]*R.grvec[2];
+
+ if(R.inprz<0.0) R.wrld.skytype-= WO_ZENUP;
+ R.inprz= fabs(R.inprz);
+ }
+ else if(R.wrld.skytype & WO_SKYPAPER) {
+ R.inprz= 0.5+ 0.5*R.view[1];
+ }
+ else {
+ R.inprz= fabs(0.5+ R.view[1]);
+ }
+
+ if(R.wrld.skytype & WO_SKYTEX) {
+ VECCOPY(R.lo, R.view);
+ if(R.wrld.skytype & WO_SKYREAL) {
+
+ MTC_Mat3MulVecfl(R.imat, R.lo);
+
+ SWAP(float, R.lo[1], R.lo[2]);
+
+ }
+
+ R.osatex= 0;
+
+ do_sky_tex();
+
+ }
+
+ if(R.inprz>1.0) R.inprz= 1.0;
+ R.inprh= 1.0-R.inprz;
+
+ if(R.wrld.skytype & WO_SKYBLEND) {
+ rf= 255.0*(R.inprh*R.wrld.horr + R.inprz*R.wrld.zenr);
+ gf= 255.0*(R.inprh*R.wrld.horg + R.inprz*R.wrld.zeng);
+ bf= 255.0*(R.inprh*R.wrld.horb + R.inprz*R.wrld.zenb);
+
+ if (rf>255.0) col[0]= 255;
+ else col[0]= (char)rf;
+ if (gf>255.0) col[1]= 255;
+ else col[1]= (char)gf;
+ if (bf>255.0) col[2]= 255;
+ else col[2]= (char)bf;
+ }
+ else {
+ col[0]= 255.0*R.wrld.horr;
+ col[1]= 255.0*R.wrld.horg;
+ col[2]= 255.0*R.wrld.horb;
+ }
+ col[3]= 1; /* om verkeerde optimalisatie alphaover van flares te voorkomen */
+}
+
+/* ------------------------------------------------------------------------- */
+
+void scanlinesky(char *rect, int y)
+{
+ /* have to type this! set to : addalphaUnder: char*, char*
+ * addalphaUnderGamma: ditto called with char *, uint* !!!
+ * unmangle this shit... */
+ void (*alphafunc)();
+ float fac;
+ int dx, x, ofs;
+ unsigned int col=0, *rt;
+ short *sp;
+ char *cp, *cp1;
+ float u, v;
+
+ if(R.r.alphamode & R_ALPHAPREMUL) return;
+
+ if(R.r.alphamode & R_ALPHAKEY) {
+
+ cp= (char *)&col;
+ cp[3]= 1;
+ cp[0]= 255.0*R.wrld.horr;
+ cp[1]= 255.0*R.wrld.horg;
+ cp[2]= 255.0*R.wrld.horb;
+
+ for(x=0; x<R.rectx; x++, rect+= 4) {
+ if(rect[3]==0) {
+ *( ( unsigned int *)rect)= col;
+ }
+ else {
+ /* voorkomen dat 'col' in afbeelding voorkomt */
+ cp1= (char *)rect;
+ if( cp[0]==cp1[0] && cp[1]==cp1[1] && cp[2]==cp1[2] ) {
+
+ if(cp1[3]==255) cp1[3]= 254;
+ else cp1[3]++;
+ }
+
+ if(rect[3]!=255) {
+ keyalpha(rect);
+ }
+ }
+ }
+ return;
+ }
+
+ if(R.wrld.mode & WO_MIST) alphafunc= addalphaUnder;
+ else alphafunc= addalphaUnderGamma;
+
+
+ if(R.r.bufflag & 1) {
+ if(R.backbuf->ok) {
+ if(R.backbuf->ibuf==0) {
+ R.backbuf->ibuf= IMB_loadiffname(R.backbuf->name, IB_rect);
+ if(R.backbuf->ibuf==0) {
+ R.backbuf->ok= 0;
+ return;
+ }
+ }
+ /* welke scanline/ */
+ y= ((y+R.afmy+R.ystart)*R.backbuf->ibuf->y)/(2*R.afmy);
+
+ if(R.flag & R_SEC_FIELD) {
+ if((R.r.mode & R_ODDFIELD)==0) {
+ if( y<R.backbuf->ibuf->y) y++;
+ }
+ else {
+ if( y>0) y--;
+ }
+ }
+
+ rt= (R.backbuf->ibuf->rect + y*R.backbuf->ibuf->x);
+
+ /* op welke plek */
+ fac= ((float)R.backbuf->ibuf->x)/(float)(2*R.afmx);
+ ofs= (R.afmx+R.xstart)*fac;
+ rt+= ofs;
+
+ dx= (int) (65536.0*fac);
+ sp= (short *)&ofs;
+
+ #ifdef BBIG_ENDIAN
+ #else
+ sp++;
+ #endif
+
+ ofs= 0;
+ x= R.rectx;
+ while( x-- ) {
+ if( rect[3] != 255) {
+ if(rect[3]==0) *((unsigned int *)rect)= *rt;
+ else {
+ alphafunc(rect, rt);
+ }
+ }
+ rect+= 4;
+
+ ofs+= dx;
+ while( *sp>0 ) {
+ ofs-= 65536;
+ rt++;
+ }
+ }
+
+ }
+ return;
+ }
+
+ if((R.wrld.skytype & (WO_SKYBLEND+WO_SKYTEX))==0) {
+ for(x=0; x<R.rectx; x++, rect+= 4) {
+ if(rect[3] != 255) {
+ if(rect[3]==0) *((unsigned int *)rect)= R.wrld.fastcol;
+ else {
+ alphafunc(rect, &R.wrld.fastcol);
+ }
+ }
+ }
+ }
+ else {
+
+ for(x=0; x<R.rectx; x++, rect+= 4) {
+ if(rect[3] < 254) {
+ if(R.wrld.skytype & WO_SKYPAPER) {
+ R.view[0]= (x+(R.xstart))/(float)R.afmx;
+ R.view[1]= (y+(R.ystart))/(float)R.afmy;
+ R.view[2]= 0.0;
+ }
+ else {
+ R.view[0]= (x+(R.xstart)+1.0);
+
+ if(R.flag & R_SEC_FIELD) {
+ if(R.r.mode & R_ODDFIELD) R.view[1]= (y+R.ystart+0.5)*R.ycor;
+ else R.view[1]= (y+R.ystart+1.5)*R.ycor;
+ }
+ else R.view[1]= (y+R.ystart+1.0)*R.ycor;
+
+ R.view[2]= -R.viewfac;
+
+ fac= Normalise(R.view);
+ if(R.wrld.skytype & WO_SKYTEX) {
+ O.dxview= 1.0/fac;
+ O.dyview= R.ycor/fac;
+ }
+ }
+
+ if(R.r.mode & R_PANORAMA) {
+ float panoco, panosi;
+ panoco = getPanovCo();
+ panosi = getPanovSi();
+ u= R.view[0]; v= R.view[2];
+
+ R.view[0]= panoco*u + panosi*v;
+ R.view[2]= -panosi*u + panoco*v;
+ }
+
+ RE_sky((char *)&col);
+
+ if(rect[3]==0) *((unsigned int *)rect)= col;
+ else alphafunc(rect, &col);
+ }
+ }
+ }
+}
+
+/* ************************************** */
+
+
+
+extern float Tin; /* texture.c */
+void do_lamphalo_tex(LampRen *lar, float *p1, float *p2, float *intens)
+{
+ /* p1 p2 already are rotated in spot-space */
+ float v1[3], vec[3];
+ float dist, totin=0.0;
+ int a, steps= 32;
+
+ v1[0]= p1[0];
+ v1[1]= p1[1];
+ v1[2]= p1[2]/lar->sh_zfac;
+
+ VecSubf(vec, p2, p1);
+ dist= Normalise(vec);
+
+ /* fixed number of steps */
+ dist/= (float)steps;
+
+ for(a=0; a<steps; a++) {
+
+ VecAddf(v1, v1, vec);
+ VECCOPY(R.co, v1);
+ do_lamp_tex(lar, v1);
+ totin+= Tin;
+
+ }
+
+ totin/= (float)steps;
+
+ *intens *= totin;
+ /* why isn't there a return value here? */
+}
+
+
+
+void spothalo(struct LampRen *lar, float *view, float *intens)
+{
+ double a, b, c, disc, nray[3], npos[3];
+ float t0, t1 = 0.0, t2= 0.0, t3, haint;
+ float p1[3], p2[3], ladist, maxz = 0.0, maxy = 0.0;
+ int snijp, doclip=1, use_yco=0;
+ int ok1=0, ok2=0;
+
+ *intens= 0.0;
+ haint= lar->haint;
+
+ VECCOPY(npos, lar->sh_invcampos); /* in initlamp berekend */
+
+ /* view roteren */
+ VECCOPY(nray, view);
+ MTC_Mat3MulVecd(lar->imat, nray);
+
+ if(R.wrld.mode & WO_MIST) {
+ /* een beetje patch... */
+ R.zcor= -lar->co[2];
+ haint *= mistfactor(lar->co);
+ if(haint==0.0) {
+ return;
+ }
+ }
+
+
+ /* maxz roteren */
+ if(R.co[2]==0) doclip= 0; /* is als halo op sky */
+ else {
+ p1[0]= R.co[0]-lar->co[0];
+ p1[1]= R.co[1]-lar->co[1];
+ p1[2]= R.co[2]-lar->co[2];
+
+ maxz= lar->imat[0][2]*p1[0]+lar->imat[1][2]*p1[1]+lar->imat[2][2]*p1[2];
+ maxz*= lar->sh_zfac;
+ maxy= lar->imat[0][1]*p1[0]+lar->imat[1][1]*p1[1]+lar->imat[2][1]*p1[2];
+
+ if( fabs(nray[2]) <0.000001 ) use_yco= 1;
+ }
+
+ /* z scalen zodat het volume genormaliseerd is */
+ nray[2]*= lar->sh_zfac;
+ /* nray hoeft niet genormaliseerd */
+
+ ladist= lar->sh_zfac*lar->dist;
+
+ /* oplossen */
+ a = nray[0] * nray[0] + nray[1] * nray[1] - nray[2]*nray[2];
+ b = nray[0] * npos[0] + nray[1] * npos[1] - nray[2]*npos[2];
+ c = npos[0] * npos[0] + npos[1] * npos[1] - npos[2]*npos[2];
+
+ snijp= 0;
+ if (fabs(a) < 0.00000001) {
+ /*
+ * Only one intersection point...
+ */
+ return;
+ }
+ else {
+ disc = b*b - a*c;
+
+ if(disc==0.0) {
+ t1=t2= (-b)/ a;
+ snijp= 2;
+ }
+ else if (disc > 0.0) {
+ disc = sqrt(disc);
+ t1 = (-b + disc) / a;
+ t2 = (-b - disc) / a;
+ snijp= 2;
+ }
+ }
+ if(snijp==2) {
+ /* sorteren */
+ if(t1>t2) {
+ a= t1; t1= t2; t2= a;
+ }
+
+ /* z van snijpunten met diabolo */
+ p1[2]= npos[2] + t1*nray[2];
+ p2[2]= npos[2] + t2*nray[2];
+
+ /* beide punten evalueren */
+ if(p1[2]<=0.0) ok1= 1;
+ if(p2[2]<=0.0 && t1!=t2) ok2= 1;
+
+ /* minstens 1 punt met negatieve z */
+ if(ok1==0 && ok2==0) return;
+
+ /* snijpunt met -ladist, de bodem van de kegel */
+ if(use_yco==0) {
+ t3= (-ladist-npos[2])/nray[2];
+
+ /* moet 1 van de snijpunten worden vervangen? */
+ if(ok1) {
+ if(p1[2]<-ladist) t1= t3;
+ }
+ else {
+ ok1= 1;
+ t1= t3;
+ }
+ if(ok2) {
+ if(p2[2]<-ladist) t2= t3;
+ }
+ else {
+ ok2= 1;
+ t2= t3;
+ }
+ }
+ else if(ok1==0 || ok2==0) return;
+
+ /* minstens 1 zichtbaar snijpunt */
+ if(t1<0.0 && t2<0.0) return;
+
+ if(t1<0.0) t1= 0.0;
+ if(t2<0.0) t2= 0.0;
+
+ if(t1==t2) return;
+
+ /* voor zekerheid nog eens sorteren */
+ if(t1>t2) {
+ a= t1; t1= t2; t2= a;
+ }
+
+ /* t0 berekenen: is de maximale zichtbare z (als halo door vlak doorsneden wordt) */
+ if(doclip) {
+ if(use_yco==0) t0= (maxz-npos[2])/nray[2];
+ else t0= (maxy-npos[1])/nray[1];
+
+ if(t0<t1) return;
+ if(t0<t2) t2= t0;
+ }
+
+ /* bereken punten */
+ p1[0]= npos[0] + t1*nray[0];
+ p1[1]= npos[1] + t1*nray[1];
+ p1[2]= npos[2] + t1*nray[2];
+ p2[0]= npos[0] + t2*nray[0];
+ p2[1]= npos[1] + t2*nray[1];
+ p2[2]= npos[2] + t2*nray[2];
+
+
+ /* nu hebben we twee punten, hiermee maken we drie lengtes */
+
+ a= sqrt(p1[0]*p1[0]+p1[1]*p1[1]+p1[2]*p1[2]);
+ b= sqrt(p2[0]*p2[0]+p2[1]*p2[1]+p2[2]*p2[2]);
+ c= VecLenf(p1, p2);
+
+ a/= ladist;
+ a= sqrt(a);
+ b/= ladist;
+ b= sqrt(b);
+ c/= ladist;
+
+ *intens= c*( (1.0-a)+(1.0-b) );
+
+ /* LET OP: a,b en c NIET op 1.0 clippen, dit geeft kleine
+ overflowtjes op de rand (vooral bij smalle halo's) */
+ if(*intens<=0.0) return;
+
+ /* zachte gebied */
+ /* vervalt omdat t0 nu ook voor p1/p2 wordt gebruikt */
+ /* if(doclip && t0<t2) { */
+ /* *intens *= (t0-t1)/(t2-t1); */
+ /* } */
+
+ *intens *= haint;
+
+ if(lar->shb && lar->shb->shadhalostep) {
+ *intens *= shadow_halo(lar, p1, p2);
+ }
+ /* if(lar->mode & LA_TEXTURE) do_lamphalo_tex(lar, p1, p2, intens); */
+
+ }
+}
+
+void renderspothalo(unsigned short *col)
+{
+ LampRen *lar;
+ float i;
+ int colt, a;
+ unsigned short scol[4];
+
+
+ for(a=0; a<R.totlamp; a++) {
+ lar= R.la[a];
+ if(lar->type==LA_SPOT && (lar->mode & LA_HALO) && lar->haint>0) {
+
+ if(lar->org) {
+ lar->r= lar->org->r;
+ lar->g= lar->org->g;
+ lar->b= lar->org->b;
+ }
+
+ spothalo(lar, R.view, &i);
+
+ if(i>0.0) {
+
+ i*= 65536.0;
+
+ colt= i;
+ if(colt>65535) scol[3]= 65535; else scol[3]= colt;
+
+ /* erg vervelend: gammagecorrigeerd renderen EN addalphaADD gaat niet goed samen */
+ /* eigenlijk moet er een aparte 'optel' gamma komen */
+
+ colt= i*lar->r;
+ if(colt>65535) scol[0]= 65535; else scol[0]= colt;
+ if(usegamtab) scol[0]= igamtab2[scol[0]];
+ colt= i*lar->g;
+ if(colt>65535) scol[1]= 65535; else scol[1]= colt;
+ if(usegamtab) scol[1]= igamtab2[scol[1]];
+ colt= i*lar->b;
+ if(colt>65535) scol[2]= 65535; else scol[2]= colt;
+ if(usegamtab) scol[2]= igamtab2[scol[2]];
+
+ addalphaAddshort(col, scol);
+ }
+ }
+ }
+}
+
+void render_lighting_halo(HaloRen *har, float *colf)
+{
+ LampRen *lar;
+ float i, inp, inpr, lv[3], lampdist, ld, t, *vn;
+ float ir, ig, ib, shadfac, soft;
+ int a;
+
+ ir= ig= ib= 0.0;
+ VECCOPY(R.co, har->co);
+ vn= har->no;
+
+ O.dxco[0]= har->hasize;
+ O.dxco[1]= 0.0;
+ O.dxco[2]= 0.0;
+
+ O.dyco[0]= 0.0;
+ O.dyco[1]= har->hasize;
+ O.dyco[2]= 0.0;
+
+ for(a=0; a<R.totlamp; a++) {
+ lar= R.la[a];
+
+ /* test op lamplayer */
+ if(lar->mode & LA_LAYER) if((lar->lay & har->lay)==0) continue;
+
+ /* lampdist berekening */
+ if(lar->type==LA_SUN || lar->type==LA_HEMI) {
+ VECCOPY(lv, lar->vec);
+ lampdist= 1.0;
+ }
+ else {
+ lv[0]= R.co[0]-lar->co[0];
+ lv[1]= R.co[1]-lar->co[1];
+ lv[2]= R.co[2]-lar->co[2];
+ ld= sqrt(lv[0]*lv[0]+lv[1]*lv[1]+lv[2]*lv[2]);
+ lv[0]/= ld;
+ lv[1]/= ld;
+ lv[2]/= ld;
+
+ /* ld wordt verderop nog gebruikt (texco's) */
+
+ if(lar->mode & LA_QUAD) {
+ t= 1.0;
+ if(lar->ld1>0.0)
+ t= lar->dist/(lar->dist+lar->ld1*ld);
+ if(lar->ld2>0.0)
+ t*= lar->distkw/(lar->distkw+lar->ld2*ld*ld);
+
+ lampdist= t;
+ }
+ else {
+ lampdist= (lar->dist/(lar->dist+ld));
+ }
+
+ if(lar->mode & LA_SPHERE) {
+ t= lar->dist - ld;
+ if(t<0.0) continue;
+
+ t/= lar->dist;
+ lampdist*= (t);
+ }
+
+ }
+
+ if(lar->mode & LA_TEXTURE) do_lamp_tex(lar, lv);
+
+ if(lar->type==LA_SPOT) {
+
+ /* hier de fie Inp() vertaagt! */
+
+ if(lar->mode & LA_SQUARE) {
+ if(lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]>0.0) {
+ float x, lvrot[3];
+
+ /* rotate view to lampspace */
+ VECCOPY(lvrot, lv);
+ MTC_Mat3MulVecfl(lar->imat, lvrot);
+
+ x= MAX2(fabs(lvrot[0]/lvrot[2]) , fabs(lvrot[1]/lvrot[2]));
+ /* 1.0/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */
+
+ inpr= 1.0/(sqrt(1.0+x*x));
+ }
+ else inpr= 0.0;
+ }
+ else {
+ inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2];
+ }
+
+ t= lar->spotsi;
+ if(inpr<t) continue;
+ else {
+ t= inpr-t;
+ i= 1.0;
+ soft= 1.0;
+ if(t<lar->spotbl && lar->spotbl!=0.0) {
+ /* zachte gebied */
+ i= t/lar->spotbl;
+ t= i*i;
+ soft= (3.0*t-2.0*t*i);
+ inpr*= soft;
+ }
+ if(lar->mode & LA_ONLYSHADOW) {
+ /* if(ma->mode & MA_SHADOW) { */
+ /* inprodukt positief: voorzijde vlak! */
+ inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2];
+ if(inp>0.0) {
+ /* testshadowbuf==0.0 : 100% schaduw */
+ shadfac = testshadowbuf(lar->shb, inp);
+ if( shadfac>0.0 ) {
+ shadfac*= inp*soft*lar->energy;
+ ir -= shadfac;
+ ig -= shadfac;
+ ib -= shadfac;
+
+ continue;
+ }
+ }
+ /* } */
+ }
+ lampdist*=inpr;
+ }
+ if(lar->mode & LA_ONLYSHADOW) continue;
+
+ }
+
+ /* inprodukt en reflectivity*/
+
+ inp= 1.0-fabs(vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2]);
+
+ /* inp= cos(0.5*M_PI-acos(inp)); */
+
+ i= inp;
+
+ if(lar->type==LA_HEMI) {
+ i= 0.5*i+0.5;
+ }
+ if(i>0.0) {
+ i*= lampdist;
+ /* i*= lampdist*ma->ref; */
+ }
+
+ /* schaduw */
+ if(i> -0.41) { /* beetje willekeurig, beetje getest */
+ shadfac= 1.0;
+ if(lar->shb) {
+ /* if(ma->mode & MA_SHADOW) { */
+ shadfac = testshadowbuf(lar->shb, inp);
+ if(shadfac==0.0) continue;
+ i*= shadfac;
+ /* } */
+ }
+ }
+
+ if(i>0.0) {
+ ir+= i*lar->r;
+ ig+= i*lar->g;
+ ib+= i*lar->b;
+ }
+ }
+
+ if(ir<0.0) ir= 0.0;
+ if(ig<0.0) ig= 0.0;
+ if(ib<0.0) ib= 0.0;
+
+ colf[0]*= ir;
+ colf[1]*= ig;
+ colf[2]*= ib;
+
+}
+
+
+extern float hashvectf[];
+void RE_shadehalo(HaloRen *har, char *col, unsigned int zz, float dist, float xn, float yn, short flarec)
+{
+ /* in col invullen */
+ float t, zn, radist, ringf=0.0, linef=0.0, alpha, si, co, colf[4];
+ int colt, a;
+
+ if(R.wrld.mode & WO_MIST) {
+ if(har->type & HA_ONLYSKY) {
+ /* sterren geen mist */
+ alpha= har->alfa;
+ }
+ else {
+ /* een beetje patch... */
+ R.zcor= -har->co[2];
+ alpha= mistfactor(har->co)*har->alfa;
+ }
+ }
+ else alpha= har->alfa;
+
+ if(alpha==0.0) {
+ col[0] = 0;
+ col[1] = 0;
+ col[2] = 0;
+ col[3] = 0;
+
+/* *( (int *)col )=0; */
+
+ return;
+ }
+
+ radist= sqrt(dist);
+
+ /* let op: hiermee wordt gesjoemeld: flarec wordt op nul gezet in de pixstruct */
+ if(flarec) har->pixels+= (int)(har->rad-radist);
+
+ if(har->ringc) {
+ float *rc, fac;
+ int ofs;
+
+ /* per ring een alicirc */
+ ofs= har->seed;
+
+ for(a= har->ringc; a>0; a--, ofs+=2) {
+
+ rc= hashvectf + (ofs % 768);
+
+ fac= fabs( rc[1]*(har->rad*fabs(rc[0]) - radist) );
+
+ if(fac< 1.0) {
+ ringf+= (1.0-fac);
+ }
+ }
+ }
+
+ if(har->type & HA_VECT) {
+ dist= fabs( har->cos*(yn) - har->sin*(xn) )/har->rad;
+ if(dist>1.0) dist= 1.0;
+ if(har->tex) {
+ zn= har->sin*xn - har->cos*yn;
+ yn= har->cos*xn + har->sin*yn;
+ xn= zn;
+ }
+ }
+ else dist= dist/har->radsq;
+
+ if(har->type & HA_FLARECIRC) {
+
+ dist= 0.5+fabs(dist-0.5);
+
+ }
+
+ if(har->hard>=30) {
+ dist= sqrt(dist);
+ if(har->hard>=40) {
+ dist= sin(dist*M_PI_2);
+ if(har->hard>=50) {
+ dist= sqrt(dist);
+ }
+ }
+ }
+ else if(har->hard<20) dist*=dist;
+
+ dist=(1.0-dist);
+
+ if(har->linec) {
+ float *rc, fac;
+ int ofs;
+
+ /* per starpoint een aliline */
+ ofs= har->seed;
+
+ for(a= har->linec; a>0; a--, ofs+=3) {
+
+ rc= hashvectf + (ofs % 768);
+
+ fac= fabs( (xn)*rc[0]+(yn)*rc[1]);
+
+ if(fac< 1.0 ) {
+ linef+= (1.0-fac);
+ }
+ }
+
+ linef*= dist;
+
+ }
+
+ if(har->starpoints) {
+ float ster, hoek;
+ /* rotatie */
+ hoek= atan2(yn, xn);
+ hoek*= (1.0+0.25*har->starpoints);
+
+ co= cos(hoek);
+ si= sin(hoek);
+
+ hoek= (co*xn+si*yn)*(co*yn-si*xn);
+
+ ster= fabs(hoek);
+ if(ster>1.0) {
+ ster= (har->rad)/(ster);
+
+ if(ster<1.0) dist*= sqrt(ster);
+ }
+ }
+
+ /* halo wordt doorsneden? */
+ if(har->zs> zz-har->zd) {
+ t= ((float)(zz-har->zs))/(float)har->zd;
+ alpha*= sqrt(sqrt(t));
+ }
+
+ dist*= alpha;
+ ringf*= dist;
+ linef*= alpha;
+
+ if(dist<0.003) {
+ *( (int *)col )=0;
+ return;
+ }
+
+ /* texture? */
+ if(har->tex) {
+ colf[3]= dist;
+ do_halo_tex(har, xn, yn, colf);
+
+ /* dist== colf[3]; */
+
+ colf[0]*= colf[3];
+ colf[1]*= colf[3];
+ colf[2]*= colf[3];
+
+ }
+ else {
+ colf[0]= dist*har->r;
+ colf[1]= dist*har->g;
+ colf[2]= dist*har->b;
+
+ if(har->type & HA_XALPHA) colf[3]= dist*dist;
+ else colf[3]= dist;
+ }
+
+ if(har->mat && har->mat->mode & MA_HALO_SHADE) {
+ /* we test for lights because of preview... */
+ if(R.totlamp) render_lighting_halo(har, colf);
+ }
+
+ if(linef!=0.0) {
+ Material *ma= har->mat;
+
+ colf[0]+= 255.0*linef*ma->specr;
+ colf[1]+= 255.0*linef*ma->specg;
+ colf[2]+= 255.0*linef*ma->specb;
+
+ if(har->type & HA_XALPHA) colf[3]+= linef*linef;
+ else colf[3]+= linef;
+ }
+ if(ringf!=0.0) {
+ Material *ma= har->mat;
+
+ colf[0]+= 255.0*ringf*ma->mirr;
+ colf[1]+= 255.0*ringf*ma->mirg;
+ colf[2]+= 255.0*ringf*ma->mirb;
+
+ if(har->type & HA_XALPHA) colf[3]+= ringf*ringf;
+ else colf[3]+= ringf;
+ }
+
+ colt= 255.0*colf[3];
+ if(colt>254) col[3]= 255; else col[3]= colt;
+
+ colt= colf[2];
+ if(colt>254) col[2]= 255; else col[2]= colt;
+
+ colt= colf[1];
+ if(colt>254) col[1]= 255; else col[1]= colt;
+
+ colt= colf[0];
+ if(colt>254) col[0]= 255; else col[0]= colt;
+
+}
+
+
+unsigned int calchalo_z(HaloRen *har, unsigned int zz)
+{
+
+ if(har->type & HA_ONLYSKY) {
+ if(zz!=0x7FFFFFFF) zz= 0;
+ }
+ else {
+ zz= (zz>>8);
+ if(zz<0x800000) zz= (zz+0x7FFFFF);
+ else zz= (zz-0x800000);
+ }
+ return zz;
+}
+
+void scanlinehaloPS(unsigned int *rectz, long *rectdelta, unsigned int *rectt, short ys)
+{
+ HaloRen *har = NULL;
+ PixStr *ps;
+ float dist,xsq,ysq,xn,yn;
+ unsigned int a, *rz, *rt, zz;
+ long *rd;
+ int accol[4];
+ short minx,maxx,x,aantal, aantalm, behind, flarec;
+ char col[4];
+
+ for(a=0;a<R.tothalo;a++) {
+ if((a & 255)==0) har= R.bloha[a>>8];
+ else har++;
+
+ if(RE_local_test_break()) break;
+
+ if(ys>har->maxy);
+ else if(ys<har->miny);
+ else {
+ minx= floor(har->xs-har->rad);
+ maxx= ceil(har->xs+har->rad);
+
+ if(maxx<0);
+ else if(R.rectx<minx);
+ else {
+ if(minx<0) minx= 0;
+ if(maxx>=R.rectx) maxx= R.rectx-1;
+
+ rt= rectt+minx;
+ rd= rectdelta+minx;
+ rz= rectz+minx;
+
+ yn= (ys-har->ys)*R.ycor;
+ ysq= yn*yn;
+ for(x=minx; x<=maxx; x++) {
+
+ flarec= har->flarec; /* har->pixels mag maar 1 x geteld worden */
+
+ if( IS_A_POINTER_CODE(*rd)) {
+ xn= x-har->xs;
+ xsq= xn*xn;
+ dist= xsq+ysq;
+ if(dist<har->radsq) {
+ ps= (PixStr *) POINTER_FROM_CODE(*rd);
+ aantal= behind= 0;
+ accol[0]=accol[1]=accol[2]=accol[3]= 0;
+ while(ps) {
+ aantalm= count_mask(ps->mask);
+ aantal+= aantalm;
+
+ zz= calchalo_z(har, ps->z);
+ if(zz> har->zs) {
+ *( (int *)col )= 0;
+ RE_shadehalo(har, col, zz, dist, xn, yn, flarec);
+ accol[0]+= aantalm*col[0];
+ accol[1]+= aantalm*col[1];
+ accol[2]+= aantalm*col[2];
+ accol[3]+= aantalm*col[3];
+ flarec= 0;
+ }
+
+ ps= ps->next;
+ }
+ ps= (PixStr *) POINTER_FROM_CODE(*rd);
+ aantal= R.osa-aantal;
+
+ zz= calchalo_z(har, *rz);
+ if(zz> har->zs) {
+ *( (int *)col )= 0;
+ RE_shadehalo(har, col, zz, dist, xn, yn, flarec);
+ accol[0]+= aantal*col[0];
+ accol[1]+= aantal*col[1];
+ accol[2]+= aantal*col[2];
+ accol[3]+= aantal*col[3];
+ }
+
+
+ col[0]= accol[0]/R.osa;
+ col[1]= accol[1]/R.osa;
+ col[2]= accol[2]/R.osa;
+ col[3]= accol[3]/R.osa;
+
+ /* if(behind > (R.osa>>1)) addalphaUnder(rt,col); */
+ RE_addalphaAddfac((char *)rt, (char *)col, har->add);
+ }
+ }
+ else {
+ zz= calchalo_z(har, *rz);
+ if(zz> har->zs) {
+ xn= x- har->xs;
+ xsq= xn*xn;
+ dist= xsq+ysq;
+ if(dist<har->radsq) {
+ RE_shadehalo(har, col, zz, dist, xn, yn, flarec);
+ RE_addalphaAddfac((char *)rt, (char *)col, har->add);
+ }
+ }
+ }
+ rt++;
+ rz++;
+ rd++;
+ }
+
+ }
+ }
+ }
+
+}
+
+void scanlinehalo(unsigned int *rectz, unsigned int *rectt, short ys)
+{
+ HaloRen *har = NULL;
+ float dist,xsq,ysq,xn,yn;
+ unsigned int a, *rz, *rt, zz;
+ short minx,maxx, x;
+ char col[4];
+
+ for(a=0; a<R.tothalo; a++) {
+ if((a & 255)==0) har= R.bloha[a>>8];
+ else har++;
+
+ if(RE_local_test_break()) break;
+
+ if(ys>har->maxy);
+ else if(ys<har->miny);
+ else {
+ minx= floor(har->xs-har->rad);
+ maxx= ceil(har->xs+har->rad);
+
+ if(maxx<0);
+ else if(R.rectx<minx);
+ else {
+ if(minx<0) minx= 0;
+ if(maxx>=R.rectx) maxx= R.rectx-1;
+
+ rt= rectt+minx;
+ rz= rectz+minx;
+
+ yn= (ys-har->ys)*R.ycor;
+ ysq= yn*yn;
+ for(x=minx; x<=maxx; x++) {
+
+ zz= calchalo_z(har, *rz);
+ if(zz> har->zs) {
+ xn= x- har->xs;
+ xsq= xn*xn;
+ dist= xsq+ysq;
+ if(dist<har->radsq) {
+ RE_shadehalo(har, col, zz, dist, xn, yn, har->flarec);
+ RE_addalphaAddfac((char *)rt, (char *)col, har->add);
+ }
+ }
+
+ rt++;
+ rz++;
+ }
+ }
+ }
+ }
+
+}
+
+void halovert()
+{
+ HaloRen *har = NULL;
+ float dist, xsq, ysq, xn, yn;
+ unsigned int a, *rectz, *rz, *rectt, *rt, zz;
+ int minx, maxx, miny, maxy, x, y;
+ char col[4];
+
+
+ for(a=0;a<R.tothalo;a++) {
+ if((a & 255)==0) har= R.bloha[a>>8];
+ else har++;
+
+ if(RE_local_test_break()) break;
+
+ if(har->maxy<0);
+ else if(R.recty<har->miny);
+ else {
+ minx= floor(har->xs-har->rad);
+ maxx= ceil(har->xs+har->rad);
+
+ if(maxx<0);
+ else if(R.rectx<minx);
+ else {
+
+ miny= floor(har->ys-har->rad);
+ maxy= ceil(har->ys+har->rad);
+
+ if(minx<0) minx= 0;
+ if(maxx>=R.rectx) maxx= R.rectx-1;
+ if(miny<0) miny= 0;
+ if(maxy>R.recty) maxy= R.recty;
+
+ rectt= R.rectot+ R.rectx*miny;
+ rectz= R.rectz+ R.rectx*miny;
+
+ for(y=miny;y<maxy;y++) {
+
+ rz= rectz+minx;
+
+ rt= (rectt+minx);
+
+ yn= (y - har->ys)*R.ycor;
+ ysq= yn*yn;
+ for(x=minx;x<=maxx;x++) {
+
+ zz= calchalo_z(har, *rz);
+
+ if(zz> har->zs) {
+
+ xn= x - har->xs;
+ xsq= xn*xn;
+ dist= xsq+ysq;
+ if(dist<har->radsq) {
+ RE_shadehalo(har, col, zz, dist, xn, yn, har->flarec);
+
+ RE_addalphaAddfac((char *)rt, (char *)col, har->add);
+
+ }
+ }
+ rt++;
+ rz++;
+ }
+
+ rectt+= R.rectx;
+ rectz+= R.rectx;
+
+ if(RE_local_test_break()) break;
+ }
+
+ }
+ }
+ }
+}
+
+float RE_Spec(float inp, int hard)
+{
+ float b1;
+
+ if(inp>=1.0) return 1.0;
+ else if (inp<=0.0) return 0.0;
+
+ b1= inp*inp;
+ /* avoid FPE */
+ if(b1<0.01) b1= 0.01;
+
+ if((hard & 1)==0) inp= 1.0;
+ if(hard & 2) inp*= b1;
+ b1*= b1;
+ if(hard & 4) inp*= b1;
+ b1*= b1;
+ if(hard & 8) inp*= b1;
+ b1*= b1;
+ if(hard & 16) inp*= b1;
+ b1*= b1;
+
+ /* avoid FPE */
+ if(b1<0.001) b1= 0.0;
+
+ if(hard & 32) inp*= b1;
+ b1*= b1;
+ if(hard & 64) inp*=b1;
+
+ if(hard & 128) {
+ b1*= b1;
+ inp*=b1;
+ }
+
+ return inp;
+}
+
+
+float CookTorr(float *n, float *l, float *v, int hard)
+{
+ float i, nh, nv, h[3];
+
+ h[0]= v[0]+l[0];
+ h[1]= v[1]+l[1];
+ h[2]= v[2]+l[2];
+ Normalise(h);
+
+ nh= n[0]*h[0]+n[1]*h[1]+n[2]*h[2];
+ if(nh<0.0) return 0.0;
+ nv= n[0]*v[0]+n[1]*v[1]+n[2]*v[2];
+ if(nv<0.0) nv= 0.0;
+ i= RE_Spec(nh, hard);
+
+ i= i/(0.1+nv);
+ return i;
+}
+
+void RE_calc_R_ref()
+{
+ float i;
+
+ /* R.vn dot R.view */
+ i= -2*(R.vn[0]*R.view[0]+R.vn[1]*R.view[1]+R.vn[2]*R.view[2]);
+
+ R.ref[0]= (R.view[0]+i*R.vn[0]);
+ R.ref[1]= (R.view[1]+i*R.vn[1]);
+ R.ref[2]= (R.view[2]+i*R.vn[2]);
+ if(R.osatex) {
+ if(R.vlr->flag & R_SMOOTH) {
+ i= -2*( (R.vn[0]+O.dxno[0])*(R.view[0]+O.dxview) +
+ (R.vn[1]+O.dxno[1])*R.view[1]+ (R.vn[2]+O.dxno[2])*R.view[2] );
+
+ O.dxref[0]= R.ref[0]- ( R.view[0]+O.dxview+i*(R.vn[0]+O.dxno[0]));
+ O.dxref[1]= R.ref[1]- (R.view[1]+ i*(R.vn[1]+O.dxno[1]));
+ O.dxref[2]= R.ref[2]- (R.view[2]+ i*(R.vn[2]+O.dxno[2]));
+
+ i= -2*( (R.vn[0]+O.dyno[0])*R.view[0]+
+ (R.vn[1]+O.dyno[1])*(R.view[1]+O.dyview)+ (R.vn[2]+O.dyno[2])*R.view[2] );
+
+ O.dyref[0]= R.ref[0]- (R.view[0]+ i*(R.vn[0]+O.dyno[0]));
+ O.dyref[1]= R.ref[1]- (R.view[1]+O.dyview+i*(R.vn[1]+O.dyno[1]));
+ O.dyref[2]= R.ref[2]- (R.view[2]+ i*(R.vn[2]+O.dyno[2]));
+
+ }
+ else {
+
+ i= -2*( R.vn[0]*(R.view[0]+O.dxview) +
+ R.vn[1]*R.view[1]+ R.vn[2]*R.view[2] );
+
+ O.dxref[0]= R.ref[0]- (R.view[0]+O.dxview+i*R.vn[0]);
+ O.dxref[1]= R.ref[1]- (R.view[1]+ i*R.vn[1]);
+ O.dxref[2]= R.ref[2]- (R.view[2]+ i*R.vn[2]);
+
+ i= -2*( R.vn[0]*R.view[0]+
+ R.vn[1]*(R.view[1]+O.dyview)+ R.vn[2]*R.view[2] );
+
+ O.dyref[0]= R.ref[0]- (R.view[0]+ i*R.vn[0]);
+ O.dyref[1]= R.ref[1]- (R.view[1]+O.dyview+i*R.vn[1]);
+ O.dyref[2]= R.ref[2]- (R.view[2]+ i*R.vn[2]);
+ }
+ }
+
+}
+
+void shadelamplus()
+{
+ LampRen *lar;
+ Material *ma;
+ float i, inp, inpr, t, lv[3], lampdist, ld = 0, ir, ig, ib, isr=0,isg=0,isb=0;
+ float lvrot[3], *vn, *view, shadfac, soft;
+ int a;
+
+ vn= R.vn;
+ view= R.view;
+ ma= R.matren;
+
+ /* aparte lus */
+ if(ma->mode & MA_ONLYSHADOW) {
+ shadfac= ir= 0.0;
+ for(a=0; a<R.totlamp; a++) {
+ lar= R.la[a];
+
+ if(lar->mode & LA_LAYER) if((lar->lay & R.vlr->lay)==0) continue;
+
+ if(lar->shb) {
+ /* alleen testen binnen spotbundel */
+ lv[0]= R.co[0]-lar->co[0];
+ lv[1]= R.co[1]-lar->co[1];
+ lv[2]= R.co[2]-lar->co[2];
+ Normalise(lv);
+ inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2];
+ if(inpr>lar->spotsi) {
+
+ inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2];
+
+ i = testshadowbuf(lar->shb, inp);
+
+ t= inpr - lar->spotsi;
+ if(t<lar->spotbl && lar->spotbl!=0.0) {
+ t/= lar->spotbl;
+ t*= t;
+ i= t*i+(1.0-t);
+ }
+
+ shadfac+= i;
+ ir+= 1.0;
+ }
+ else {
+ shadfac+= 1.0;
+ ir+= 1.0;
+ }
+ }
+ }
+ if(ir>0.0) shadfac/= ir;
+ ma->alpha= (R.mat->alpha)*(1.0-shadfac);
+
+ shortcol[0]=shortcol[1]=shortcol[2]= 0;
+
+ return;
+ }
+
+ if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) {
+ ma->r= R.vcol[0];
+ ma->g= R.vcol[1];
+ ma->b= R.vcol[2];
+ }
+
+ /* mirror reflection colour */
+ R.refcol[0]= R.refcol[1]= R.refcol[2]= R.refcol[3]= 0.0;
+
+ if(ma->texco) {
+
+ if(ma->texco & TEXCO_REFL) {
+ RE_calc_R_ref();
+ }
+
+ if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) {
+ R.mat->r= R.vcol[0];
+ R.mat->g= R.vcol[1];
+ R.mat->b= R.vcol[2];
+ }
+
+ do_material_tex();
+ }
+
+ if(ma->mode & MA_SHLESS) {
+ if( (ma->mode & (MA_VERTEXCOL+MA_VERTEXCOLP+MA_FACETEXTURE) )) {
+ ir= R.vcol[0]*ma->r;
+ ig= R.vcol[1]*ma->g;
+ ib= R.vcol[2]*ma->b;
+ }
+ else {
+ ir= ma->r;
+ ig= ma->g;
+ ib= ma->b;
+ }
+
+ if(usegamtab) {
+ a= 65535*ir;
+ if(a<0) a=0; else if(a>65535) a= 65535;
+ shortcol[0]= igamtab2[a];
+ a= 65535*ig;
+ if(a<0) a=0; else if(a>65535) a= 65535;
+ shortcol[1]= igamtab2[a];
+ a= 65535*ib;
+ if(a<0) a=0; else if(a>65535) a= 65535;
+ shortcol[2]= igamtab2[a];
+ }
+ else {
+ a= 65535*ir;
+ if(a<0) shortcol[0]= 0; else if(a>65535) shortcol[0]= 65535; else shortcol[0]= a;
+ a= 65535*ig;
+ if(a<0) shortcol[1]= 0; else if(a>65535) shortcol[1]= 65535; else shortcol[1]= a;
+ a= 65535*ib;
+ if(a<0) shortcol[2]= 0; else if(a>65535) shortcol[2]= 65535; else shortcol[2]= a;
+ }
+ return;
+ }
+
+ if( (ma->mode & (MA_VERTEXCOL+MA_VERTEXCOLP))== MA_VERTEXCOL ) {
+ ir= ma->emit+R.vcol[0];
+ ig= ma->emit+R.vcol[1];
+ ib= ma->emit+R.vcol[2];
+ }
+ else ir= ig= ib= ma->emit;
+
+ for(a=0; a<R.totlamp; a++) {
+ lar= R.la[a];
+
+ /* test op lamplayer */
+ if(lar->mode & LA_LAYER) if((lar->lay & R.vlr->lay)==0) continue;
+
+ /* lampdist berekening */
+ if(lar->type==LA_SUN || lar->type==LA_HEMI) {
+ VECCOPY(lv, lar->vec);
+ lampdist= 1.0;
+ }
+ else {
+ lv[0]= R.co[0]-lar->co[0];
+ lv[1]= R.co[1]-lar->co[1];
+ lv[2]= R.co[2]-lar->co[2];
+ ld= sqrt(lv[0]*lv[0]+lv[1]*lv[1]+lv[2]*lv[2]);
+ lv[0]/= ld;
+ lv[1]/= ld;
+ lv[2]/= ld;
+
+ /* ld wordt verderop nog gebruikt (texco's) */
+
+ if(lar->mode & LA_QUAD) {
+ t= 1.0;
+ if(lar->ld1>0.0)
+ t= lar->dist/(lar->dist+lar->ld1*ld);
+ if(lar->ld2>0.0)
+ t*= lar->distkw/(lar->distkw+lar->ld2*ld*ld);
+
+ lampdist= t;
+ }
+ else {
+ lampdist= (lar->dist/(lar->dist+ld));
+ }
+
+ if(lar->mode & LA_SPHERE) {
+ t= lar->dist - ld;
+ if(t<0.0) continue;
+
+ t/= lar->dist;
+ lampdist*= (t);
+ }
+
+ }
+
+ if(lar->mode & LA_TEXTURE) do_lamp_tex(lar, lv);
+
+ if(lar->type==LA_SPOT) {
+
+ /* hier de fie Inp() vertaagt! */
+
+ if(lar->mode & LA_SQUARE) {
+ if(lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]>0.0) {
+ float x;
+
+ /* rotate view to lampspace */
+ VECCOPY(lvrot, lv);
+ MTC_Mat3MulVecfl(lar->imat, lvrot);
+
+ x= MAX2(fabs(lvrot[0]/lvrot[2]) , fabs(lvrot[1]/lvrot[2]));
+ /* 1.0/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */
+
+ inpr= 1.0/(sqrt(1+x*x));
+ }
+ else inpr= 0.0;
+ }
+ else {
+ inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2];
+ }
+
+ t= lar->spotsi;
+ if(inpr<t) continue;
+ else {
+ t= inpr-t;
+ i= 1.0;
+ soft= 1.0;
+ if(t<lar->spotbl && lar->spotbl!=0.0) {
+ /* zachte gebied */
+ i= t/lar->spotbl;
+ t= i*i;
+ soft= (3.0*t-2.0*t*i);
+ inpr*= soft;
+ }
+ if(lar->mode & LA_ONLYSHADOW && lar->shb) {
+ if(ma->mode & MA_SHADOW) {
+ /* inprodukt positief: voorzijde vlak! */
+ inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2];
+ if(inp>0.0) {
+ /* testshadowbuf==0.0 : 100% schaduw */
+ shadfac = 1.0 - testshadowbuf(lar->shb, inp);
+ if(shadfac>0.0) {
+ shadfac*= inp*soft*lar->energy;
+ ir -= shadfac;
+ ig -= shadfac;
+ ib -= shadfac;
+
+ continue;
+ }
+ }
+ }
+ }
+ lampdist*=inpr;
+ }
+ if(lar->mode & LA_ONLYSHADOW) continue;
+
+ if(lar->mode & LA_OSATEX) {
+ R.osatex= 1; /* signaal voor multitex() */
+
+ O.dxlv[0]= lv[0] - (R.co[0]-lar->co[0]+O.dxco[0])/ld;
+ O.dxlv[1]= lv[1] - (R.co[1]-lar->co[1]+O.dxco[1])/ld;
+ O.dxlv[2]= lv[2] - (R.co[2]-lar->co[2]+O.dxco[2])/ld;
+
+ O.dylv[0]= lv[0] - (R.co[0]-lar->co[0]+O.dyco[0])/ld;
+ O.dylv[1]= lv[1] - (R.co[1]-lar->co[1]+O.dyco[1])/ld;
+ O.dylv[2]= lv[2] - (R.co[2]-lar->co[2]+O.dyco[2])/ld;
+ }
+
+ }
+
+ /* inprodukt en reflectivity*/
+ inp=i= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2];
+ if(lar->type==LA_HEMI) {
+ i= 0.5*i+0.5;
+ }
+ if(i>0.0) {
+ i*= lampdist*ma->ref;
+ }
+
+ /* schaduw en spec */
+ if(i> -0.41) { /* beetje willekeurig, beetje getest */
+ shadfac= 1.0;
+ if(lar->shb) {
+ if(ma->mode & MA_SHADOW) {
+ shadfac = testshadowbuf(lar->shb, inp);
+ if(shadfac==0.0) continue;
+ i*= shadfac;
+ }
+ }
+ /* specularity */
+
+ if(ma->spec!=0.0) {
+
+ if(lar->type==LA_SUN || lar->type==LA_HEMI) {
+ if(lar->type==LA_SUN) {
+ lv[2]-= 1.0;
+ }
+ else {
+ lv[0]+= view[0];
+ lv[1]+= view[1];
+ lv[2]+= view[2];
+ }
+
+ Normalise(lv);
+
+ t= vn[0]*lv[0]+vn[1]*lv[1]+vn[2]*lv[2];
+
+ if(lar->type==LA_HEMI) {
+ t= 0.5*t+0.5;
+ }
+ /* let op: shadfac en lampdist uit onderstaande */
+
+ /* no more speclim */
+
+ t= ma->spec*RE_Spec(t, ma->har);
+ isr+= t*(lar->r * ma->specr);
+ isg+= t*(lar->g * ma->specg);
+ isb+= t*(lar->b * ma->specb);
+ }
+ else {
+ t= shadfac*ma->spec*lampdist*CookTorr(vn, lv, view, ma->har);
+ isr+= t*(lar->r * ma->specr);
+ isg+= t*(lar->g * ma->specg);
+ isb+= t*(lar->b * ma->specb);
+ }
+ }
+ }
+ if(i>0.0) {
+ ir+= i*lar->r;
+ ig+= i*lar->g;
+ ib+= i*lar->b;
+ }
+ }
+
+ if(ir<0.0) ir= 0.0;
+ if(ig<0.0) ig= 0.0;
+ if(ib<0.0) ib= 0.0;
+ if(isr<0.0) isr= 0.0;
+ if(isg<0.0) isg= 0.0;
+ if(isb<0.0) isb= 0.0;
+
+ if(ma->mode & MA_ZTRA) { /* ztra shade */
+ if(ma->spectra!=0.0) {
+
+ t = MAX3(isr, isb, isg);
+ t *= ma->spectra;
+ if(t>1.0) t= 1.0;
+ if(ma->mapto & MAP_ALPHA) ma->alpha= (1.0-t)*ma->alpha+t;
+ else ma->alpha= (1.0-t)*R.mat->alpha+t;
+ }
+ }
+
+ if(R.refcol[0]==0.0) {
+ a= 65535.0*( ma->r*ir +ma->ambr +isr);
+ if(a>65535) a=65535; else if(a<0) a= 0;
+ shortcol[0]= a;
+ a= 65535.0*(ma->g*ig +ma->ambg +isg);
+ if(a>65535) a=65535; else if(a<0) a= 0;
+ shortcol[1]= a;
+ a= 65535*(ma->b*ib +ma->ambb +isb);
+ if(a>65535) a=65535; else if(a<0) a= 0;
+ shortcol[2]= a;
+ }
+ else {
+ a= 65535.0*( ma->mirr*R.refcol[1] + (1.0 - ma->mirr*R.refcol[0])*(ma->r*ir +ma->ambr) +isr);
+ if(a>65535) a=65535; else if(a<0) a= 0;
+ shortcol[0]= a;
+ a= 65535.0*( ma->mirg*R.refcol[2] + (1.0 - ma->mirg*R.refcol[0])*(ma->g*ig +ma->ambg) +isg);
+ if(a>65535) a=65535; else if(a<0) a= 0;
+ shortcol[1]= a;
+ a= 65535.0*( ma->mirb*R.refcol[3] + (1.0 - ma->mirb*R.refcol[0])*(ma->b*ib +ma->ambb) +isb);
+ if(a>65535) a=65535; else if(a<0) a= 0;
+ shortcol[2]= a;
+ }
+
+ if(usegamtab) {
+ shortcol[0]= igamtab2[ shortcol[0] ];
+ shortcol[1]= igamtab2[ shortcol[1] ];
+ shortcol[2]= igamtab2[ shortcol[2] ];
+ }
+}
+
+
+void shadepixel(float x, float y, int vlaknr)
+ /* x,y: windowcoordinaat van 0 tot rectx,y */
+{
+ static VlakRen *vlr;
+ static VertRen *v1, *v2, *v3;
+ static float t00, t01, t10, t11, dvlak, n1[3], n2[3], n3[3];
+ static float s00, s01, s10, s11;
+ float *o1, *o2, *o3;
+ float u, v, l, dl, hox, hoy, detsh, fac, deler, alpha;
+ char *cp1, *cp2, *cp3;
+
+ if(R.vlaknr== -1) { /* doet initrender */
+ vlr= R.vlr= 0;
+ }
+
+ if(vlaknr<=0) { /* sky */
+ R.vlaknr= 0;
+ shortcol[3]= 0;
+ }
+ else if( (vlaknr & 0x7FFFFF) <= R.totvlak) {
+
+ if(vlaknr!=R.vlaknr) {
+ vlr= RE_findOrAddVlak( (vlaknr-1) & 0x7FFFFF);
+
+ R.mat= vlr->mat;
+ R.matren= R.mat->ren;
+
+ if(R.matren==0) { /* tijdelijk voor debug */
+ shortcol[3]= 65535;
+ shortcol[2]= 0;
+ shortcol[1]= 65535;
+ shortcol[0]= 65535;
+ return;
+ }
+
+ R.vlr= vlr;
+
+ R.vno= vlr->n;
+ R.osatex= (R.matren->texco & TEXCO_OSA);
+ R.vlaknr= vlaknr;
+
+ v1= vlr->v1;
+ dvlak= v1->co[0]*vlr->n[0]+v1->co[1]*vlr->n[1]+v1->co[2]*vlr->n[2];
+
+ if( (vlr->flag & R_SMOOTH) || (R.matren->texco & NEED_UV)) { /* uv nodig */
+ if(vlaknr & 0x800000) {
+ v2= vlr->v3;
+ v3= vlr->v4;
+ }
+ else {
+ v2= vlr->v2;
+ v3= vlr->v3;
+ }
+
+ if(vlr->snproj==0) {
+ t00= v3->co[0]-v1->co[0]; t01= v3->co[1]-v1->co[1];
+ t10= v3->co[0]-v2->co[0]; t11= v3->co[1]-v2->co[1];
+ }
+ else if(vlr->snproj==1) {
+ t00= v3->co[0]-v1->co[0]; t01= v3->co[2]-v1->co[2];
+ t10= v3->co[0]-v2->co[0]; t11= v3->co[2]-v2->co[2];
+ }
+ else {
+ t00= v3->co[1]-v1->co[1]; t01= v3->co[2]-v1->co[2];
+ t10= v3->co[1]-v2->co[1]; t11= v3->co[2]-v2->co[2];
+ }
+
+ detsh= t00*t11-t10*t01;
+ t00/= detsh; t01/=detsh;
+ t10/=detsh; t11/=detsh;
+
+ if(vlr->flag & R_SMOOTH) { /* puno's goedzetten */
+ if(vlr->puno & ME_FLIPV1) {
+ n1[0]= -v1->n[0]; n1[1]= -v1->n[1]; n1[2]= -v1->n[2];
+ } else {
+ n1[0]= v1->n[0]; n1[1]= v1->n[1]; n1[2]= v1->n[2];
+ }
+ if(vlaknr & 0x800000) {
+ if(vlr->puno & ME_FLIPV3) {
+ n2[0]= -v2->n[0]; n2[1]= -v2->n[1]; n2[2]= -v2->n[2];
+ } else {
+ n2[0]= v2->n[0]; n2[1]= v2->n[1]; n2[2]= v2->n[2];
+ }
+
+ if(vlr->puno & ME_FLIPV4) {
+ n3[0]= -v3->n[0]; n3[1]= -v3->n[1]; n3[2]= -v3->n[2];
+ } else {
+ n3[0]= v3->n[0]; n3[1]= v3->n[1]; n3[2]= v3->n[2];
+ }
+
+ }
+ else {
+ if(vlr->puno & ME_FLIPV2) {
+ n2[0]= -v2->n[0]; n2[1]= -v2->n[1]; n2[2]= -v2->n[2];
+ } else {
+ n2[0]= v2->n[0]; n2[1]= v2->n[1]; n2[2]= v2->n[2];
+ }
+
+ if(vlr->puno & ME_FLIPV3) {
+ n3[0]= -v3->n[0]; n3[1]= -v3->n[1]; n3[2]= -v3->n[2];
+ } else {
+ n3[0]= v3->n[0]; n3[1]= v3->n[1]; n3[2]= v3->n[2];
+ }
+ }
+ }
+ if(R.matren->texco & TEXCO_STICKY) {
+ s00= v3->ho[0]/v3->ho[3] - v1->ho[0]/v1->ho[3];
+ s01= v3->ho[1]/v3->ho[3] - v1->ho[1]/v1->ho[3];
+ s10= v3->ho[0]/v3->ho[3] - v2->ho[0]/v2->ho[3];
+ s11= v3->ho[1]/v3->ho[3] - v2->ho[1]/v2->ho[3];
+
+ detsh= s00*s11-s10*s01;
+ s00/= detsh; s01/=detsh;
+ s10/=detsh; s11/=detsh;
+ }
+ }
+ }
+
+ /* COXYZ nieuwe methode */
+ if( (G.special1 & G_HOLO) && ((Camera *)G.scene->camera->data)->flag & CAM_HOLO2) {
+ R.view[0]= (x+(R.xstart)+1.0+holoofs);
+ }
+ else {
+ R.view[0]= (x+(R.xstart)+1.0);
+ }
+
+ if(R.flag & R_SEC_FIELD) {
+ if(R.r.mode & R_ODDFIELD) R.view[1]= (y+R.ystart+0.5)*R.ycor;
+ else R.view[1]= (y+R.ystart+1.5)*R.ycor;
+ }
+ else R.view[1]= (y+R.ystart+1.0)*R.ycor;
+
+ R.view[2]= -R.viewfac;
+
+ if(R.r.mode & R_PANORAMA) {
+ float panoco, panosi;
+ panoco = getPanovCo();
+ panosi = getPanovSi();
+
+ u= R.view[0]; v= R.view[2];
+ R.view[0]= panoco*u + panosi*v;
+ R.view[2]= -panosi*u + panoco*v;
+ }
+
+ deler= vlr->n[0]*R.view[0] + vlr->n[1]*R.view[1] + vlr->n[2]*R.view[2];
+ if (deler!=0.0) fac= R.zcor= dvlak/deler;
+ else fac= R.zcor= 0.0;
+
+ R.co[0]= fac*R.view[0];
+ R.co[1]= fac*R.view[1];
+ R.co[2]= fac*R.view[2];
+
+ if(R.osatex || (R.r.mode & R_SHADOW) ) {
+ u= dvlak/(deler-vlr->n[0]);
+ v= dvlak/(deler- R.ycor*vlr->n[1]);
+
+ O.dxco[0]= R.co[0]- (R.view[0]-1.0)*u;
+ O.dxco[1]= R.co[1]- (R.view[1])*u;
+ O.dxco[2]= R.co[2]- (R.view[2])*u;
+
+ O.dyco[0]= R.co[0]- (R.view[0])*v;
+ O.dyco[1]= R.co[1]- (R.view[1]-1.0*R.ycor)*v;
+ O.dyco[2]= R.co[2]- (R.view[2])*v;
+
+ }
+
+ fac= Normalise(R.view);
+ R.zcor*= fac; /* voor mist */
+
+ if(R.osatex) {
+ if( (R.matren->texco & TEXCO_REFL) ) {
+ O.dxview= 1.0/fac;
+ O.dyview= R.ycor/fac;
+ }
+ }
+
+ /* UV en TEX*/
+ if( (vlr->flag & R_SMOOTH) || (R.matren->texco & NEED_UV)) {
+ if(vlr->snproj==0) {
+ u= (R.co[0]-v3->co[0])*t11-(R.co[1]-v3->co[1])*t10;
+ v= (R.co[1]-v3->co[1])*t00-(R.co[0]-v3->co[0])*t01;
+ if(R.osatex) {
+ O.dxuv[0]= O.dxco[0]*t11- O.dxco[1]*t10;
+ O.dxuv[1]= O.dxco[1]*t00- O.dxco[0]*t01;
+ O.dyuv[0]= O.dyco[0]*t11- O.dyco[1]*t10;
+ O.dyuv[1]= O.dyco[1]*t00- O.dyco[0]*t01;
+ }
+ }
+ else if(vlr->snproj==1) {
+ u= (R.co[0]-v3->co[0])*t11-(R.co[2]-v3->co[2])*t10;
+ v= (R.co[2]-v3->co[2])*t00-(R.co[0]-v3->co[0])*t01;
+ if(R.osatex) {
+ O.dxuv[0]= O.dxco[0]*t11- O.dxco[2]*t10;
+ O.dxuv[1]= O.dxco[2]*t00- O.dxco[0]*t01;
+ O.dyuv[0]= O.dyco[0]*t11- O.dyco[2]*t10;
+ O.dyuv[1]= O.dyco[2]*t00- O.dyco[0]*t01;
+ }
+ }
+ else {
+ u= (R.co[1]-v3->co[1])*t11-(R.co[2]-v3->co[2])*t10;
+ v= (R.co[2]-v3->co[2])*t00-(R.co[1]-v3->co[1])*t01;
+ if(R.osatex) {
+ O.dxuv[0]= O.dxco[1]*t11- O.dxco[2]*t10;
+ O.dxuv[1]= O.dxco[2]*t00- O.dxco[1]*t01;
+ O.dyuv[0]= O.dyco[1]*t11- O.dyco[2]*t10;
+ O.dyuv[1]= O.dyco[2]*t00- O.dyco[1]*t01;
+ }
+ }
+ l= 1.0+u+v;
+
+ if(vlr->flag & R_SMOOTH) {
+ R.vn[0]= l*n3[0]-u*n1[0]-v*n2[0];
+ R.vn[1]= l*n3[1]-u*n1[1]-v*n2[1];
+ R.vn[2]= l*n3[2]-u*n1[2]-v*n2[2];
+
+ Normalise(R.vn);
+ if(R.osatex && (R.matren->texco & (TEXCO_NORM+TEXCO_REFL)) ) {
+ dl= O.dxuv[0]+O.dxuv[1];
+ O.dxno[0]= dl*n3[0]-O.dxuv[0]*n1[0]-O.dxuv[1]*n2[0];
+ O.dxno[1]= dl*n3[1]-O.dxuv[0]*n1[1]-O.dxuv[1]*n2[1];
+ O.dxno[2]= dl*n3[2]-O.dxuv[0]*n1[2]-O.dxuv[1]*n2[2];
+ dl= O.dyuv[0]+O.dyuv[1];
+ O.dyno[0]= dl*n3[0]-O.dyuv[0]*n1[0]-O.dyuv[1]*n2[0];
+ O.dyno[1]= dl*n3[1]-O.dyuv[0]*n1[1]-O.dyuv[1]*n2[1];
+ O.dyno[2]= dl*n3[2]-O.dyuv[0]*n1[2]-O.dyuv[1]*n2[2];
+
+ }
+ }
+ else {
+ VECCOPY(R.vn, vlr->n);
+ }
+
+ if(R.matren->mode & MA_ZINV) { /* z invert */
+ /* R.vn[0]= -R.vn[0]; */
+ /* R.vn[1]= -R.vn[1]; */
+ }
+
+ if(R.matren->texco & TEXCO_ORCO) {
+ if(v2->orco) {
+ o1= v1->orco;
+ o2= v2->orco;
+ o3= v3->orco;
+
+ R.lo[0]= l*o3[0]-u*o1[0]-v*o2[0];
+ R.lo[1]= l*o3[1]-u*o1[1]-v*o2[1];
+ R.lo[2]= l*o3[2]-u*o1[2]-v*o2[2];
+
+ if(R.osatex) {
+ dl= O.dxuv[0]+O.dxuv[1];
+ O.dxlo[0]= dl*o3[0]-O.dxuv[0]*o1[0]-O.dxuv[1]*o2[0];
+ O.dxlo[1]= dl*o3[1]-O.dxuv[0]*o1[1]-O.dxuv[1]*o2[1];
+ O.dxlo[2]= dl*o3[2]-O.dxuv[0]*o1[2]-O.dxuv[1]*o2[2];
+ dl= O.dyuv[0]+O.dyuv[1];
+ O.dylo[0]= dl*o3[0]-O.dyuv[0]*o1[0]-O.dyuv[1]*o2[0];
+ O.dylo[1]= dl*o3[1]-O.dyuv[0]*o1[1]-O.dyuv[1]*o2[1];
+ O.dylo[2]= dl*o3[2]-O.dyuv[0]*o1[2]-O.dyuv[1]*o2[2];
+ }
+ }
+ }
+
+ if(R.matren->texco & TEXCO_GLOB) {
+ VECCOPY(R.gl, R.co);
+ MTC_Mat4MulVecfl(R.viewinv, R.gl);
+ if(R.osatex) {
+ VECCOPY(O.dxgl, O.dxco);
+ MTC_Mat3MulVecfl(R.imat, O.dxco);
+ VECCOPY(O.dygl, O.dyco);
+ MTC_Mat3MulVecfl(R.imat, O.dyco);
+ }
+ }
+ if((R.matren->texco & TEXCO_UV) || (R.matren->mode & (MA_VERTEXCOL|MA_FACETEXTURE))) {
+ if(R.vlr->tface) {
+ float *uv1, *uv2, *uv3;
+
+ uv1= R.vlr->tface->uv[0];
+ if( (vlaknr & 0x800000) || (R.vlr->flag & R_FACE_SPLIT) ) {
+ uv2= R.vlr->tface->uv[2];
+ uv3= R.vlr->tface->uv[3];
+ }
+ else {
+ uv2= R.vlr->tface->uv[1];
+ uv3= R.vlr->tface->uv[2];
+ }
+
+ R.uv[0]= -1.0 + 2.0*(l*uv3[0]-u*uv1[0]-v*uv2[0]);
+ R.uv[1]= -1.0 + 2.0*(l*uv3[1]-u*uv1[1]-v*uv2[1]);
+
+ if(R.osatex) {
+ float duv[2];
+
+ dl= O.dxuv[0]+O.dxuv[1];
+ duv[0]= O.dxuv[0];
+ duv[1]= O.dxuv[1];
+
+ O.dxuv[0]= 2.0*(dl*uv3[0]-duv[0]*uv1[0]-duv[1]*uv2[0]);
+ O.dxuv[1]= 2.0*(dl*uv3[1]-duv[0]*uv1[1]-duv[1]*uv2[1]);
+
+ dl= O.dyuv[0]+O.dyuv[1];
+ duv[0]= O.dyuv[0];
+ duv[1]= O.dyuv[1];
+
+ O.dyuv[0]= 2.0*(dl*uv3[0]-duv[0]*uv1[0]-duv[1]*uv2[0]);
+ O.dyuv[1]= 2.0*(dl*uv3[1]-duv[0]*uv1[1]-duv[1]*uv2[1]);
+ }
+
+ }
+ else {
+ R.uv[0]= 2.0*(u+.5);
+ R.uv[1]= 2.0*(v+.5);
+ }
+ }
+ if(R.matren->texco & TEXCO_NORM) {
+ R.orn[0]= R.vn[0];
+ R.orn[1]= -R.vn[1];
+ R.orn[2]= R.vn[2];
+ }
+ if(R.matren->mode & MA_VERTEXCOL) {
+ cp1= (char *)vlr->vcol;
+ if(cp1) {
+ if( (vlaknr & 0x800000) || (R.vlr->flag & R_FACE_SPLIT) ) {
+ cp2= (char *)(vlr->vcol+2);
+ cp3= (char *)(vlr->vcol+3);
+ }
+ else {
+ cp2= (char *)(vlr->vcol+1);
+ cp3= (char *)(vlr->vcol+2);
+ }
+ R.vcol[0]= (l*cp3[3]-u*cp1[3]-v*cp2[3])/255.0;
+ R.vcol[1]= (l*cp3[2]-u*cp1[2]-v*cp2[2])/255.0;
+ R.vcol[2]= (l*cp3[1]-u*cp1[1]-v*cp2[1])/255.0;
+
+ }
+ else {
+ R.vcol[0]= 0.0;
+ R.vcol[1]= 0.0;
+ R.vcol[2]= 0.0;
+ }
+ }
+ if(R.matren->mode & MA_FACETEXTURE) {
+ if((R.matren->mode & MA_VERTEXCOL)==0) {
+ R.vcol[0]= 1.0;
+ R.vcol[1]= 1.0;
+ R.vcol[2]= 1.0;
+ }
+ if(vlr->tface) render_realtime_texture();
+ }
+
+
+ /* hierna klopt de u en v EN O.dxuv en O.dyuv niet meer */
+ if(R.matren->texco & TEXCO_STICKY) {
+ if(v2->sticky) {
+
+ /* opnieuw u en v berekenen */
+ hox= x/Zmulx -1.0;
+ hoy= y/Zmuly -1.0;
+ u= (hox - v3->ho[0]/v3->ho[3])*s11 - (hoy - v3->ho[1]/v3->ho[3])*s10;
+ v= (hoy - v3->ho[1]/v3->ho[3])*s00 - (hox - v3->ho[0]/v3->ho[3])*s01;
+ l= 1.0+u+v;
+
+ o1= v1->sticky;
+ o2= v2->sticky;
+ o3= v3->sticky;
+
+ R.sticky[0]= l*o3[0]-u*o1[0]-v*o2[0];
+ R.sticky[1]= l*o3[1]-u*o1[1]-v*o2[1];
+
+ if(R.osatex) {
+ O.dxuv[0]= s11/Zmulx;
+ O.dxuv[1]= - s01/Zmulx;
+ O.dyuv[0]= - s10/Zmuly;
+ O.dyuv[1]= s00/Zmuly;
+
+ dl= O.dxuv[0]+O.dxuv[1];
+ O.dxsticky[0]= dl*o3[0]-O.dxuv[0]*o1[0]-O.dxuv[1]*o2[0];
+ O.dxsticky[1]= dl*o3[1]-O.dxuv[0]*o1[1]-O.dxuv[1]*o2[1];
+ dl= O.dyuv[0]+O.dyuv[1];
+ O.dysticky[0]= dl*o3[0]-O.dyuv[0]*o1[0]-O.dyuv[1]*o2[0];
+ O.dysticky[1]= dl*o3[1]-O.dyuv[0]*o1[1]-O.dyuv[1]*o2[1];
+ }
+ }
+ }
+ }
+ else {
+ VECCOPY(R.vn, vlr->n);
+ }
+ if(R.matren->texco & TEXCO_WINDOW) {
+ R.winco[0]= (x+(R.xstart))/(float)R.afmx;
+ R.winco[1]= (y+(R.ystart))/(float)R.afmy;
+ }
+
+
+ shadelamplus();
+
+ /* MIST */
+ if( (R.wrld.mode & WO_MIST) && (R.matren->mode & MA_NOMIST)==0 ){
+ alpha= mistfactor(R.co);
+ }
+ else alpha= 1.0;
+
+ /* RAYTRACE (tijdelijk?) UITGESCHAKELD */
+
+ if(R.matren->alpha!=1.0 || alpha!=1.0) {
+ fac= alpha*(R.matren->alpha);
+
+ /* gamma */
+ if(R.osa && usegamtab) fac*= fac;
+
+ shortcol[3]= 65535.0*fac;
+ shortcol[0]*= fac;
+ shortcol[1]*= fac;
+ shortcol[2]*= fac;
+ }
+ else {
+ shortcol[3]= 65535;
+ }
+ }
+ else {
+ shortcol[0]= 65535;
+ shortcol[1]= 65535;
+ shortcol[2]= 0;
+ shortcol[3]= 65535;
+ }
+
+ if(R.flag & R_LAMPHALO) {
+ if(vlaknr<=0) { /* bereken viewvec en zet R.co op far */
+
+ if( (G.special1 & G_HOLO) && ((Camera *)G.scene->camera->data)->flag & CAM_HOLO2) {
+ R.view[0]= (x+(R.xstart)+1.0+holoofs);
+ }
+ else {
+ R.view[0]= (x+(R.xstart)+1.0);
+ }
+
+ if(R.flag & R_SEC_FIELD) {
+ if(R.r.mode & R_ODDFIELD) R.view[1]= (y+R.ystart+0.5)*R.ycor;
+ else R.view[1]= (y+R.ystart+1.5)*R.ycor;
+ }
+ else R.view[1]= (y+R.ystart+1.0)*R.ycor;
+
+ R.view[2]= -R.viewfac;
+
+ if(R.r.mode & R_PANORAMA) {
+ float panoco, panosi;
+ panoco = getPanovCo();
+ panosi = getPanovSi();
+
+ u= R.view[0]; v= R.view[2];
+ R.view[0]= panoco*u + panosi*v;
+ R.view[2]= -panosi*u + panoco*v;
+ }
+
+ R.co[2]= 0.0;
+
+ }
+ renderspothalo(shortcol);
+ }
+}
+
+PixStr *addpsmain()
+{
+ PixStrMain *psm;
+
+ psm= &psmfirst;
+
+ while(psm->next) {
+ psm= psm->next;
+ }
+
+ psm->next= (PixStrMain *)MEM_mallocN(sizeof(PixStrMain),"pixstrMain");
+
+ psm= psm->next;
+ psm->next=0;
+ psm->ps= (PixStr *)MEM_mallocN(4096*sizeof(PixStr),"pixstr");
+ psmteller= 0;
+
+ return psm->ps;
+}
+
+void freeps()
+{
+ PixStrMain *psm,*next;
+
+ psm= &psmfirst;
+
+ while(psm) {
+ next= psm->next;
+ if(psm->ps) {
+ MEM_freeN(psm->ps);
+ psm->ps= 0;
+ }
+ if(psm!= &psmfirst) MEM_freeN(psm);
+ psm= next;
+ }
+
+ psmfirst.next= 0;
+ psmfirst.ps= 0;
+}
+
+void addps(long *rd, int vlak, unsigned int z, short ronde)
+{
+ static PixStr *prev;
+ PixStr *ps, *last = NULL;
+ int vlakand;
+
+ if( IS_A_POINTER_CODE(*rd)) {
+ ps= (PixStr *) POINTER_FROM_CODE(*rd);
+ vlakand= (vlak & 0x7FFFFF);
+
+ if( (ps->vlak0 & 0x7FFFFF) == vlakand ) return;
+
+ while(ps) {
+ if( (ps->vlak & 0x7FFFFF) == vlakand ) {
+ ps->mask |= (1<<ronde);
+ return;
+ }
+ last= ps;
+ ps= ps->next;
+ }
+
+ if((psmteller & 4095)==0) prev= addpsmain();
+ else prev++;
+ psmteller++;
+
+ last->next= prev;
+ prev->next= 0;
+ prev->vlak= vlak;
+ prev->z= z;
+ prev->mask = (1<<ronde);
+ prev->ronde= ronde;
+
+ return;
+ }
+
+ /* eerste PS maken */
+ if((psmteller & 4095)==0) prev= addpsmain();
+ else prev++;
+ psmteller++;
+
+ prev->next= 0;
+ prev->vlak0= (int) *rd;
+ prev->vlak= vlak;
+ prev->z= z;
+ prev->mask = (1<<ronde);
+ prev->ronde= ronde;
+ *rd= POINTER_TO_CODE(prev);
+}
+
+
+int count_mask(unsigned short mask)
+{
+ return (cmask[mask & 255]+cmask[mask>>8]);
+}
+
+float count_maskf(unsigned short mask)
+{
+ return (fmask[mask & 255]+fmask[mask>>8]);
+}
+
+
+void add_filt_mask(unsigned int mask, unsigned short *col, unsigned int *rb1, unsigned int *rb2, unsigned int *rb3)
+{
+ /* bereken de waarde van mask */
+ unsigned int a, maskand, maskshift;
+ int j;
+ unsigned short val, r, g, b, al;
+
+ al= col[3];
+ r= col[0];
+ g= col[1];
+ b= col[2];
+
+ maskand= (mask & 255);
+ maskshift= (mask >>8);
+
+ for(j=2; j>=0; j--) {
+
+ a= j;
+
+ val= *(mask1[a] +maskand) + *(mask2[a] +maskshift);
+ if(val) {
+ rb1[3]+= val*al;
+ rb1[0]+= val*r;
+ rb1[1]+= val*g;
+ rb1[2]+= val*b;
+ }
+ a+=3;
+
+ val= *(mask1[a] +maskand) + *(mask2[a] +maskshift);
+ if(val) {
+ rb2[3]+= val*al;
+ rb2[0]+= val*r;
+ rb2[1]+= val*g;
+ rb2[2]+= val*b;
+ }
+ a+=3;
+
+ val= *(mask1[a] +maskand) + *(mask2[a] +maskshift);
+ if(val) {
+ rb3[3]+= val*al;
+ rb3[0]+= val*r;
+ rb3[1]+= val*g;
+ rb3[2]+= val*b;
+ }
+
+ rb1+= 4;
+ rb2+= 4;
+ rb3+= 4;
+ }
+}
+
+void edge_enhance(void)
+{
+ /* use zbuffer to define edges, add it to the image */
+ int val, y, x, col, *rz, *rz1, *rz2, *rz3;
+ char *cp;
+
+ /* alle getallen in zbuffer 3 naar rechts shiften */
+ rz= (int *)R.rectz;
+ if(rz==0) return;
+
+ for(y=0; y<R.recty; y++) {
+ for(x=0; x<R.rectx; x++, rz++) {
+ (*rz)>>= 3;
+ }
+ }
+
+ /* eerste order, werkt toch niet goed!:
+ val= abs(rz1[0]-rz2[1])+ 2*abs(rz1[1]-rz2[1])+ abs(rz1[2]-rz2[1]);
+ val+= 2*abs(rz2[0]-rz2[1])+ 2*abs(rz1[2]-rz2[1]);
+ val+= abs(rz3[0]-rz2[1])+ 2*abs(rz3[1]-rz2[1])+ abs(rz3[2]-rz2[1]);
+ *rz= val;
+ */
+
+ rz1= (int *)R.rectz;
+ rz2= rz1+R.rectx;
+ rz3= rz2+R.rectx;
+ rz= (int *)R.rectot+R.rectx;
+
+ if(R.r.mode & R_OSA) {
+ cp= (char *)(R.rectaccu+R.rectx);
+ }
+ else {
+ cp= (char *)(R.rectot+R.rectx);
+ }
+
+ /* rz itself does not seem to be used. */
+
+ for(y=0; y<R.recty-2; y++) {
+
+ rz++;
+ for(x=0; x<R.rectx-2; x++, rz++, rz1++, rz2++, rz3++, cp+=4) {
+
+ col= abs(12*rz2[1]-rz1[0]-2*rz1[1]-rz1[2]-2*rz2[0]-2*rz2[2]-rz3[0]-2*rz3[1]-rz3[2])/3;
+ /* removed the abs... now, only front/back? pixels are */
+ /* accentuated? No, the lines seem shifted strangely. the does */
+ /* not seem to be any overlap? strange... */
+/* col= -( 12*rz2[1] */
+/* - rz1[0] - 2*rz1[1] - rz1[2] */
+/* - 2*rz2[0] - 2*rz2[2] */
+/* - rz3[0] - 2*rz3[1] - rz3[2]) /3; */
+
+ col= (R.r.edgeint*col)>>14;
+ if(col>255) col= 255;
+
+ if(col>0) {
+ if(R.r.mode & R_OSA) {
+ col/= R.osa;
+
+ val= cp[3]+col;
+ if(val>255) cp[3]= 255; else cp[3]= val;
+ }
+ else {
+ val= cp[0]- col;
+ if(val<0) cp[0]= 0; else cp[0]= val;
+ val= cp[1]- col;
+ if(val<0) cp[1]= 0; else cp[1]= val;
+ val= cp[2]- col;
+ if(val<0) cp[2]= 0; else cp[2]= val;
+ }
+ }
+ }
+ rz++;
+ rz1+= 2;
+ rz2+= 2;
+ rz3+= 2;
+ cp+= 8;
+ }
+
+}
+
+/* ********************* HOOFDLUSSEN ******************** */
+
+extern unsigned short *Acolrow;
+/* short zbuffermetdehand(); */
+void zbufshadeDA(void) /* Delta Accum Pixel Struct */
+{
+ PixStr *ps;
+ float xd, yd, xs, ys;
+ unsigned int *rz, *rp, *rt, mask, fullmask;
+ unsigned int *rowbuf1, *rowbuf2, *rowbuf3, *rb1, *rb2, *rb3;
+ int a, b;
+ long *rd;
+ unsigned short *colrb, *acol;
+ short v, x, y;
+ char *colrt, tempcol[4];
+
+ R.rectdaps= MEM_callocN(sizeof(long)*R.rectx*R.recty+4,"zbufDArectd");
+ if(R.flag & R_ZTRA) bgnaccumbuf();
+
+ psmteller= 0;
+
+ if(R.r.mode & R_EDGE) {
+ R.rectaccu= (unsigned int *)MEM_callocN(sizeof(int)*R.rectx*R.recty,"zbufshadeDA");
+ }
+
+ for(v=0; v<R.osa; v++) {
+
+ xd= jit[v][0];
+ yd= jit[v][1];
+ Zjitx= -xd;
+ Zjity= -yd;
+
+ RE_local_printrenderinfo(0.0, v);
+
+ /* RECTDELTA */
+ fillrect(R.rectot,R.rectx,R.recty,0);
+
+ zbufferall();
+
+ if(v==0) {
+ a= R.rectx*R.recty;
+ rt= R.rectot;
+ rd= R.rectdaps;
+ while(a--) {
+ *rd= (long)*rt;
+ rd++; rt++;
+ }
+ }
+ else {
+ rd= R.rectdaps;
+ rp= R.rectot;
+ rz= R.rectz;
+ for(y=0; y<R.recty; y++) {
+ for(x=0; x<R.rectx; x++, rp++, rd++) {
+ if(*rd!= (long) *rp) {
+ addps(rd, *rp, *(rz+x), v);
+ }
+ }
+ rz+= R.rectx;
+ }
+ }
+ /* 1 is voor osa */
+ if(R.r.mode & R_EDGE) edge_enhance();
+
+ if(RE_local_test_break()) break;
+ }
+ if(R.flag & (R_ZTRA+R_HALO) ) { /* om de juiste zbuffer Z voor transp en halo's terug te halen */
+ xd= jit[0][0];
+ yd= jit[0][1];
+ Zjitx= -xd;
+ Zjity= -yd;
+ RE_setwindowclip(0, 0);
+ RE_local_printrenderinfo(0.0, v);
+ zbufferall();
+ }
+
+ R.vlaknr= -1;
+ rd= R.rectdaps;
+ rz= R.rectz;
+ colrt= (char *)R.rectot;
+
+
+ fullmask= (1<<R.osa)-1;
+ /* de rowbuf is 4 pixels breder dan het plaatje! */
+ rowbuf1= MEM_callocN(3*(R.rectx+4)*4*sizeof(float), "ZbufshadeDA3");
+ rowbuf2= MEM_callocN(3*(R.rectx+4)*4*sizeof(float), "ZbufshadeDA3");
+ rowbuf3= MEM_callocN(3*(R.rectx+4)*4*sizeof(float), "ZbufshadeDA3");
+
+ for(y=0;y<=R.recty;y++) {
+
+ rb1= rowbuf1;
+ rb2= rowbuf2;
+ rb3= rowbuf3;
+
+ if(y<R.recty) {
+ for(x=0; x<R.rectx; x++, rd++) {
+
+ if( IS_A_POINTER_CODE(*rd)) {
+ ps= (PixStr *) POINTER_FROM_CODE(*rd);
+ mask= 0;
+
+ while(ps) {
+ b= centmask[ps->mask];
+ xs= (float)x+centLut[b & 15];
+ ys= (float)y+centLut[b>>4];
+
+ shadepixel(xs, ys, ps->vlak);
+
+ if(shortcol[3]) {
+ add_filt_mask(ps->mask, shortcol, rb1, rb2, rb3);
+ }
+ mask |= ps->mask;
+
+ ps= ps->next;
+ }
+ ps= (PixStr *) POINTER_FROM_CODE(*rd);
+ mask= (~mask) & fullmask;
+
+ b= centmask[mask];
+ xs= (float)x+centLut[b & 15];
+ ys= (float)y+centLut[b>>4];
+
+ shadepixel(xs, ys, ps->vlak0);
+
+ if(shortcol[3]) {
+ add_filt_mask(mask, shortcol, rb1, rb2, rb3);
+ }
+ }
+ else {
+ shadepixel((float)x, (float)y, (int)*rd);
+ if(shortcol[3]) {
+ add_filt_mask(fullmask, shortcol, rb1, rb2, rb3);
+ }
+ }
+
+ rb1+=4;
+ rb2+=4;
+ rb3+=4;
+ }
+ }
+ if(y>0) {
+
+ colrb= (unsigned short *)(rowbuf3+4);
+
+ /* LET OP: ENDIAN */
+
+ for(x=0; x<R.rectx; x++,colrt+=4) {
+ colrt[0]= ( (char *) (gamtab+colrb[0+MOST_SIG_BYTE]) )[MOST_SIG_BYTE];
+ colrt[1]= ( (char *) (gamtab+colrb[2+MOST_SIG_BYTE]) )[MOST_SIG_BYTE];
+ colrt[2]= ( (char *) (gamtab+colrb[4+MOST_SIG_BYTE]) )[MOST_SIG_BYTE];
+ colrt[3]= ( (char *) (gamtab+colrb[6+MOST_SIG_BYTE]) )[MOST_SIG_BYTE];
+ colrb+= 8;
+ }
+ if(R.flag & R_ZTRA) {
+ abufsetrow(y-1);
+ acol= Acolrow;
+ colrt-= 4*R.rectx;
+
+ for(x=0; x<R.rectx; x++, colrt+=4, acol+=4) {
+ if(acol[3]) {
+ tempcol[0]= (acol[0]>>8);
+ tempcol[1]= (acol[1]>>8);
+ tempcol[2]= (acol[2]>>8);
+ tempcol[3]= (acol[3]>>8);
+ addalphaOver(colrt, tempcol);
+ }
+ }
+ }
+
+ if(R.flag & R_HALO) {
+ /* van deze pixels zijn de pixstr al 1 scanline oud */
+ scanlinehaloPS(rz-R.rectx, rd-2*R.rectx, ((unsigned int *)colrt)-R.rectx, y-1);
+
+ }
+ scanlinesky(colrt-4*R.rectx, y-1);
+
+ /* scanline begint netjes: halo's gebruiken ook textures! */
+ R.vlaknr= -1;
+
+ }
+ if(y<R.recty) {
+ memset(rowbuf3, 0, (R.rectx+4)*4*4);
+ rb3= rowbuf3;
+ rowbuf3= rowbuf2;
+ rowbuf2= rowbuf1;
+ rowbuf1= rb3;
+
+ if( y>0 && G.background==0) {
+ if((y & 1)==0) {
+ RE_local_render_display(y-2, y-1,
+ R.rectx, R.recty,
+ R.rectot);
+ }
+ }
+ rz+= R.rectx;
+ }
+ if(RE_local_test_break()) break;
+ }
+
+ if( (R.r.mode & R_EDGE) && RE_local_test_break()==0) {
+ rt= R.rectot;
+ rp= R.rectaccu;
+ for(a= R.rectx*R.recty; a>0; a--, rt++, rp++) {
+ addalphaOver((char *)rt, (char *)rp);
+ }
+ }
+
+ /* hier stond dof */
+
+ MEM_freeN(R.rectdaps);
+ freeps();
+ MEM_freeN(rowbuf1);
+ MEM_freeN(rowbuf2);
+ MEM_freeN(rowbuf3);
+ R.rectdaps= 0;
+
+ if(R.r.mode & R_EDGE) if(R.rectaccu) MEM_freeN(R.rectaccu);
+ R.rectaccu= 0;
+ if(R.flag & R_ZTRA) endaccumbuf();
+} /* end of void zbufshadeDA() */
+
+/* ------------------------------------------------------------------------ */
+
+void zbufshade(void)
+{
+ unsigned int *rz,*rp;
+ float fy;
+ int x,y;
+ unsigned short *acol;
+ char *charcol, *rt;
+
+ Zjitx=Zjity= -.5;
+
+ zbufferall();
+
+ /* SHADE */
+ rp= R.rectot;
+ rz= R.rectz;
+ charcol= (char *)shortcol;
+
+ #ifdef BBIG_ENDIAN
+ #else
+ charcol++; /* short anders uitlezen */
+ #endif
+
+ if(R.flag & R_ZTRA) bgnaccumbuf();
+
+ for(y=0; y<R.recty; y++) {
+ R.vlaknr= -1;
+ fy= y;
+
+ if(R.flag & R_ZTRA) { /* zbuf tra */
+ abufsetrow(y);
+ acol= Acolrow;
+
+ for(x=0; x<R.rectx; x++, rp++, acol+= 4) {
+ /* spothalo's added here... *rp is the target colour? */
+ shadepixel((float)x, fy, *rp);
+
+ if(acol[3]) addAlphaOverShort(shortcol, acol);
+
+ if(shortcol[3]) {
+ rt= (char *)rp;
+ rt[0]= charcol[0];
+ rt[1]= charcol[2];
+ rt[2]= charcol[4];
+ rt[3]= charcol[6];
+ }
+ else *rp= 0;
+ }
+ }
+ else {
+ for(x=0; x<R.rectx; x++, rp++) {
+ shadepixel((float)x, fy, *rp);
+ if(shortcol[3]) {
+ rt= (char *)rp;
+ rt[0]= charcol[0];
+ rt[1]= charcol[2];
+ rt[2]= charcol[4];
+ rt[3]= charcol[6];
+ }
+ else *rp= 0;
+ }
+ }
+
+ if(R.flag & R_HALO) {
+ scanlinehalo(rz, (rp-R.rectx), y);
+ rz+= R.rectx;
+ }
+ scanlinesky( (char *)(rp-R.rectx), y);
+
+ if((y & 1) && G.background!=1) {
+ RE_local_render_display(y-1, y,
+ R.rectx, R.recty,
+ R.rectot);
+ }
+
+ if(RE_local_test_break()) break;
+ }
+
+ if(R.flag & R_ZTRA) endaccumbuf();
+
+ if(R.r.mode & R_EDGE) edge_enhance();
+
+ /* if((R.flag & R_HALO) && MISC_test_break()==0) halovert(); */
+
+} /* end of void zbufshade() */
+
+/* ------------------------------------------------------------------------ */
+
+void renderhalo(HaloRen *har) /* postprocess versie */
+{
+
+ float dist, xsq, ysq, xn, yn;
+ unsigned int *rectt, *rt;
+ int minx, maxx, miny, maxy, x, y;
+ char col[4];
+
+
+ har->miny= miny= har->ys - har->rad/R.ycor;
+ har->maxy= maxy= har->ys + har->rad/R.ycor;
+
+ if(maxy<0);
+ else if(R.recty<miny);
+ else {
+ minx= floor(har->xs-har->rad);
+ maxx= ceil(har->xs+har->rad);
+
+ if(maxx<0);
+ else if(R.rectx<minx);
+ else {
+
+ if(minx<0) minx= 0;
+ if(maxx>=R.rectx) maxx= R.rectx-1;
+ if(miny<0) miny= 0;
+ if(maxy>R.recty) maxy= R.recty;
+
+ rectt= R.rectot+ R.rectx*miny;
+
+ for(y=miny;y<maxy;y++) {
+
+ rt= (rectt+minx);
+
+ yn= (y - har->ys)*R.ycor;
+ ysq= yn*yn;
+
+ for(x=minx; x<=maxx; x++) {
+ xn= x - har->xs;
+ xsq= xn*xn;
+ dist= xsq+ysq;
+ if(dist<har->radsq) {
+ RE_shadehalo(har, col, 0, dist, xn, yn, har->flarec);
+
+ RE_addalphaAddfac((char *)rt, col, har->add);
+ }
+ rt++;
+ }
+
+ rectt+= R.rectx;
+
+ if(RE_local_test_break()) break;
+ }
+
+ }
+ }
+} /* end of void renderhalo(HaloRen *har), postprocess versie */
+
+/* ------------------------------------------------------------------------ */
+
+/* extern float hashvectf[]; */
+void RE_renderflare(HaloRen *har)
+{
+ HaloRen fla;
+ Material *ma;
+ float *rc, rad, alfa, visifac, vec[3];
+ int b, type;
+
+ fla= *har;
+ fla.linec= fla.ringc= fla.flarec= 0;
+
+ rad= har->rad;
+ alfa= har->alfa;
+
+ visifac= R.ycor*(har->pixels);
+ /* alle stralen opgeteld / r^3 == 1.0! */
+ visifac /= (har->rad*har->rad*har->rad);
+ visifac*= visifac;
+
+ ma= har->mat;
+
+ /* eerste halo: gewoon doen */
+
+ har->rad= rad*ma->flaresize*visifac;
+ har->radsq= har->rad*har->rad;
+ har->zs= 0.0;
+
+ har->alfa= alfa*visifac;
+
+ renderhalo(har);
+
+ /* volgende halo's: de flares */
+ rc= hashvectf + ma->seed2;
+
+ for(b=1; b<har->flarec; b++) {
+
+ fla.r= fabs(255.0*rc[0]);
+ fla.g= fabs(255.0*rc[1]);
+ fla.b= fabs(255.0*rc[2]);
+ fla.alfa= ma->flareboost*fabs(alfa*visifac*rc[3]);
+ fla.hard= 20.0 + fabs(70*rc[7]);
+ fla.tex= 0;
+
+ type= (int)(fabs(3.9*rc[6]));
+
+ fla.rad= ma->subsize*sqrt(fabs(2.0*har->rad*rc[4]));
+
+ if(type==3) {
+ fla.rad*= 3.0;
+ fla.rad+= R.rectx/10;
+ }
+
+ fla.radsq= fla.rad*fla.rad;
+
+ vec[0]= 1.4*rc[5]*(har->xs-R.afmx);
+ vec[1]= 1.4*rc[5]*(har->ys-R.afmy);
+ vec[2]= 32.0*sqrt(vec[0]*vec[0] + vec[1]*vec[1] + 1.0);
+
+ fla.xs= R.afmx + vec[0] + (1.2+rc[8])*R.rectx*vec[0]/vec[2];
+ fla.ys= R.afmy + vec[1] + (1.2+rc[8])*R.rectx*vec[1]/vec[2];
+
+ if(R.flag & R_SEC_FIELD) {
+ if(R.r.mode & R_ODDFIELD) fla.ys += 0.5;
+ else fla.ys -= 0.5;
+ }
+ if(type & 1) fla.type= HA_FLARECIRC;
+ else fla.type= 0;
+ renderhalo(&fla);
+
+ fla.alfa*= 0.5;
+ if(type & 2) fla.type= HA_FLARECIRC;
+ else fla.type= 0;
+ renderhalo(&fla);
+
+ rc+= 7;
+ }
+} /* end of void renderflare(HaloRen *har) */
+
+void add_halo_flare(void)
+{
+/* extern void RE_projectverto(); */ /* uit zbuf.c */
+ HaloRen *har = NULL;
+ int a, mode;
+
+ mode= R.r.mode;
+ R.r.mode &= ~R_PANORAMA;
+ R.xstart= -R.afmx;
+ R.ystart= -R.afmy;
+ R.xend= R.xstart+R.rectx-1;
+ R.yend= R.ystart+R.recty-1;
+
+ RE_setwindowclip(1,-1); /* geen jit:(-1) */
+ setzbufvlaggen(RE_projectverto);
+
+ for(a=0; a<R.tothalo; a++) {
+ if((a & 255)==0) har= R.bloha[a>>8];
+ else har++;
+
+ if(har->flarec) {
+ RE_renderflare(har);
+ }
+ }
+
+ R.r.mode= mode;
+} /* end of void add_halo_flare() */
+
+
+/* end of render.c */
+
+
diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c
new file mode 100644
index 00000000000..03b9d117e23
--- /dev/null
+++ b/source/blender/render/intern/source/renderdatabase.c
@@ -0,0 +1,248 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Storage, retrieval and query of render specific data.
+ */
+
+/*
+ * All data from a Blender scene is converter by the renderconverter/
+ * into a special format that is used by the render module to make
+ * images out of. These functions interface to the render-specific
+ * database.
+ *
+ * The blo{ha/ve/vl} arrays store pointers to blocks of 256 data
+ * entries each.
+ *
+ * The index of an entry is >>8 (the highest 24 * bits), to find an
+ * offset in a 256-entry block.
+ *
+ * - If the 256-entry block entry has an entry in the
+ * blove/bloha/blovl array of the current block, the i-th entry in
+ * that block is allocated to this entry.
+ *
+ * - If the entry has no block allocated for it yet, memory is
+ * allocated.
+ *
+ * The pointer to the correct entry is returned. Memory is guarateed
+ * to exist (as long as the malloc does not break). Since guarded
+ * allocation is used, memory _must_ be available. Otherwise, an
+ * exit(0) would occur.
+ *
+ */
+
+#include <math.h>
+#include "MEM_guardedalloc.h"
+#include "BLI_arithb.h"
+
+#include "DNA_texture_types.h"
+#include "BKE_texture.h"
+
+#include "render.h"
+#include "render_intern.h"
+
+/* ------------------------------------------------------------------------- */
+
+VertRen *RE_findOrAddVert(int nr)
+{
+ VertRen *v;
+ int a;
+
+ if(nr<0 || nr>MAXVERT ) {
+ printf("error in findOrAddVert: %d\n",nr);
+ return R.blove[0];
+ }
+ a= nr>>8;
+ v= R.blove[a];
+ if(v==0) {
+ v= (VertRen *)MEM_callocN(256*sizeof(VertRen),"findOrAddVert");
+ R.blove[a]= v;
+ }
+ v+= (nr & 255);
+ return v;
+}
+
+/* ------------------------------------------------------------------------ */
+
+HaloRen *RE_findOrAddHalo(int nr)
+{
+ HaloRen *h;
+ int a;
+
+ if(nr<0 || nr>MAXVERT ) {
+ printf("error in findOrAddHalo: %d\n",nr);
+ return R.bloha[0];
+ }
+ a= nr>>8;
+ h= R.bloha[a];
+ if(h==0) {
+ h= (HaloRen *)MEM_callocN(256*sizeof(HaloRen),"findOrAdHalo");
+ R.bloha[a]= h;
+ }
+ h+= (nr & 255);
+ return h;
+}
+
+/* ------------------------------------------------------------------------ */
+
+VlakRen *RE_findOrAddVlak(int nr)
+{
+ VlakRen *v;
+ int a;
+
+ if(nr<0 || nr>MAXVLAK ) {
+ printf("error in findOrAddVlak: %d\n",nr);
+ return R.blovl[0];
+ }
+ a= nr>>8;
+ v= R.blovl[a];
+ if(v==0) {
+ v= (VlakRen *)MEM_callocN(256*sizeof(VlakRen),"findOrAddVlak");
+ R.blovl[a]= v;
+ }
+ v+= (nr & 255);
+ return v;
+}
+
+/* ------------------------------------------------------------------------- */
+
+extern float Tin, Tr, Tg, Tb;
+HaloRen *RE_inithalo(Material *ma,
+ float *vec,
+ float *vec1,
+ float *orco,
+ float hasize,
+ float vectsize)
+{
+ HaloRen *har;
+ MTex *mtex;
+ float xn, yn, zn, texvec[3], hoco[4], hoco1[4];
+
+ if(hasize==0) return 0;
+
+ RE_projectverto(vec, hoco);
+ if(hoco[3]==0.0) return 0;
+ if(vec1) {
+ RE_projectverto(vec1, hoco1);
+ if(hoco1[3]==0.0) return 0;
+ }
+
+ har= RE_findOrAddHalo(R.tothalo++);
+ VECCOPY(har->co, vec);
+ har->hasize= hasize;
+
+ /* projectvert wordt in zbufvlaggen gedaan ivm parts/border/pano */
+
+ /* halovect */
+ if(vec1) {
+
+ har->type |= HA_VECT;
+
+ zn= hoco[3];
+ har->xs= 0.5*R.rectx*(hoco[0]/zn);
+ har->ys= 0.5*R.recty*(hoco[1]/zn);
+ har->zs= 0x7FFFFF*(1.0+hoco[2]/zn);
+
+ har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn);
+
+ xn= har->xs - 0.5*R.rectx*(hoco1[0]/hoco1[3]);
+ yn= har->ys - 0.5*R.recty*(hoco1[1]/hoco1[3]);
+ if(xn==0.0 || (xn==0.0 && yn==0.0)) zn= 0.0;
+ else zn= atan2(yn, xn);
+
+ har->sin= sin(zn);
+ har->cos= cos(zn);
+ zn= VecLenf(vec1, vec);
+
+ har->hasize= vectsize*zn + (1.0-vectsize)*hasize;
+
+ VecSubf(har->no, vec, vec1);
+ Normalise(har->no);
+ }
+
+ if(ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
+
+ har->alfa= ma->alpha;
+ har->r= 255.0*ma->r;
+ har->g= 255.0*ma->g;
+ har->b= 255.0*ma->b;
+ har->add= 255.0*ma->add;
+ har->mat= ma->ren;
+ har->hard= ma->har;
+ har->seed= ma->ren->seed1 % 256;
+
+ if(ma->mode & MA_STAR) har->starpoints= ma->starc;
+ if(ma->mode & MA_HALO_LINES) har->linec= ma->linec;
+ if(ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc;
+ if(ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec;
+
+
+ if(ma->mtex[0]) {
+
+ if( (ma->mode & MA_HALOTEX) ) har->tex= 1;
+ else {
+
+ mtex= ma->mtex[0];
+ VECCOPY(texvec, vec);
+
+ if(mtex->texco & TEXCO_NORM) {
+ ;
+ }
+ else if(mtex->texco & TEXCO_OBJECT) {
+ /* texvec[0]+= imatbase->ivec[0]; */
+ /* texvec[1]+= imatbase->ivec[1]; */
+ /* texvec[2]+= imatbase->ivec[2]; */
+ /* Mat3MulVecfl(imatbase->imat, texvec); */
+ }
+ else {
+ if(orco) {
+ VECCOPY(texvec, orco);
+ }
+ }
+
+ externtex(mtex, texvec);
+
+ yn= Tin*mtex->colfac;
+ zn= Tin*mtex->varfac;
+
+ if(mtex->mapto & MAP_COL) {
+ zn= 1.0-yn;
+ har->r= 255.0*(yn*Tr+ zn*ma->r);
+ har->g= 255.0*(yn*Tg+ zn*ma->g);
+ har->b= 255.0*(yn*Tb+ zn*ma->b);
+ }
+ if(mtex->texco & 16) {
+ har->alfa= 255.0*Tin;
+ }
+ }
+ }
+
+ return har;
+}
+/* ------------------------------------------------------------------------- */
diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c
new file mode 100644
index 00000000000..bd0a844a354
--- /dev/null
+++ b/source/blender/render/intern/source/shadbuf.c
@@ -0,0 +1,771 @@
+/* shadbuf.c RENDER
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * april 95
+ *
+ * $Id$
+ *
+ * 27-Jun-2001 switched the shadow buffer for UR to the object-shadow
+ * buffers, and removed all references and fixes for UR rendering from
+ * this one.
+ * */
+
+#include <math.h>
+#include <string.h>
+
+#include "MTC_matrixops.h"
+#include "MEM_guardedalloc.h"
+#include "BLI_arithb.h"
+
+#include "DNA_lamp_types.h"
+
+#include "render.h"
+#include "render_intern.h"
+
+#include "shadbuf.h"
+#include "renderHelp.h"
+#include "jitter.h"
+#include "zbuf.h"
+
+/* if defined: objects don't cast shadows anymore */
+/* #define RE_NO_SHADOWS */
+
+/* unused? */
+static int bias= 0x00500000;
+/* crud */
+#define MIN2(x,y) ( (x)<(y) ? (x) : (y) )
+
+/* ------------------------------------------------------------------------- */
+
+void lrectreadRectz(int x1, int y1, int x2, int y2, char *r1);
+int sizeoflampbuf(struct ShadBuf *shb);
+int firstreadshadbuf(struct ShadBuf *shb, int xs, int ys, int nr);
+float readshadowbuf(struct ShadBuf *shb, int xs, int ys, int zs);
+float readshadowbuf_halo(struct ShadBuf *shb, int xs, int ys, int zs);
+float *give_jitter_tab(int samp);
+/* ------------------------------------------------------------------------- */
+
+
+void initshadowbuf(LampRen *lar, float mat[][4])
+{
+ struct ShadBuf *shb;
+ float hoek, temp, viewinv[4][4];
+
+ /* if(la->spsi<16) return; */
+
+ /* geheugen reserveren */
+ shb= (struct ShadBuf *)MEM_callocN( sizeof(struct ShadBuf),"initshadbuf");
+ lar->shb= shb;
+
+ if(shb==0) return;
+
+ VECCOPY(shb->co, lar->co);
+
+ /* percentage: min en max in de gaten houden */
+ shb->size= (lar->bufsize*R.r.size)/100;
+ if(shb->size<512) shb->size= 512;
+ else if(shb->size > lar->bufsize) shb->size= lar->bufsize;
+
+ shb->samp= lar->samp;
+ shb->soft= lar->soft;
+ shb->shadhalostep= lar->shadhalostep;
+
+ shb->zbuf= (unsigned long *)MEM_mallocN( sizeof(unsigned long)*(shb->size*shb->size)/256, "initshadbuf2");
+ shb->cbuf= (char *)MEM_callocN( (shb->size*shb->size)/256, "initshadbuf3");
+
+ if(shb->zbuf==0 || shb->cbuf==0) {
+ if(shb->zbuf) MEM_freeN(shb->zbuf);
+ MEM_freeN(lar->shb);
+ lar->shb= 0;
+ return;
+ }
+
+ MTC_Mat4Ortho(mat);
+ MTC_Mat4Invert(shb->winmat, mat); /* winmat is hier temp */
+
+ /* matrix: combinatie van inverse view en lampmat */
+ /* opnieuw berekenen: de ortho-render heeft geen correcte viewinv */
+ MTC_Mat4Invert(viewinv, R.viewmat);
+ MTC_Mat4MulMat4(shb->viewmat, viewinv, shb->winmat);
+
+ /* projektie */
+ hoek= saacos(lar->spotsi);
+ temp= 0.5*shb->size*cos(hoek)/sin(hoek);
+ shb->d= lar->clipsta;
+
+ shb->pixsize= (shb->d)/temp;
+
+ shb->far= lar->clipend;
+ /* bias is percentage, 2x groter gemaakt ivm invalshoek correctie */
+ shb->bias= (0.02*lar->bias)*0x7FFFFFFF;
+ shb->bias= shb->bias*(100/R.r.size);
+
+}
+/* ------------------------------------------------------------------------- */
+
+
+void lrectreadRectz(int x1, int y1, int x2, int y2, char *r1) /* leest deel uit rectz in r1 */
+{
+ unsigned int len4, *rz;
+
+ if(x1>=R.rectx || x2>=R.rectx || y1>=R.recty || y2>=R.recty) return;
+ if(x1>x2 || y1>y2) return;
+
+ len4= 4*(x2- x1+1);
+ rz= R.rectz+R.rectx*y1+x1;
+ for(;y1<=y2;y1++) {
+ memcpy(r1,rz,len4);
+ rz+= R.rectx;
+ r1+= len4;
+ }
+}
+
+
+int sizeoflampbuf(struct ShadBuf *shb)
+{
+ int num,count=0;
+ char *cp;
+
+ cp= shb->cbuf;
+ num= (shb->size*shb->size)/256;
+
+ while(num--) count+= *(cp++);
+
+ return 256*count;
+}
+
+float *give_jitter_tab(int samp)
+{
+ /* these are all possible jitter tables, takes up some
+ * 12k, not really bad!
+ * For soft shadows, it saves memory and render time
+ */
+ static int tab[17]={1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256};
+ static float jit[1496][2];
+ static char ctab[17]= {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ int a, offset=0;
+
+ if(samp<2) samp= 2;
+ else if(samp>16) samp= 16;
+
+ for(a=0; a<samp-1; a++) offset+= tab[a];
+
+ if(ctab[samp]==0) {
+ initjit(jit[offset], samp*samp);
+ ctab[samp]= 1;
+ }
+
+ return jit[offset];
+
+}
+
+void makeshadowbuf(LampRen *lar)
+{
+ struct ShadBuf *shb= lar->shb;
+ float panophi;
+ float temp, wsize, dist;
+ int *rz, *rz1, verg, verg1;
+ unsigned long *ztile;
+ int a, x, y, minx, miny, byt1, byt2;
+ short temprx,tempry, square;
+ char *rc, *rcline, *ctile, *zt;
+
+ panophi = getPanoPhi();
+
+ /* viewvars onthouden */
+ temprx= R.rectx; tempry= R.recty;
+ R.rectx= R.recty= shb->size;
+
+ shb->jit= give_jitter_tab(shb->samp);
+
+ /* matrices en window: in R.winmat komt transformatie
+ van obsview naar lampview, inclusief lampwinmat */
+
+ wsize= shb->pixsize*(shb->size/2.0);
+
+ i_window(-wsize, wsize, -wsize, wsize, shb->d, shb->far, shb->winmat);
+
+ MTC_Mat4MulMat4(shb->persmat, shb->viewmat, shb->winmat);
+
+ /* temp, will be restored */
+ MTC_Mat4SwapMat4(shb->persmat, R.winmat);
+
+ /* zbufferen */
+ if(R.rectz) MEM_freeN(R.rectz);
+ R.rectz= (unsigned int *)MEM_mallocN(sizeof(int)*shb->size*shb->size,"makeshadbuf");
+ rcline= MEM_mallocN(256*4+sizeof(int),"makeshadbuf2");
+
+ /* onthouden: panorama rot */
+ temp= panophi;
+ panophi= 0.0;
+ pushTempPanoPhi(0.0);
+
+ /* pano interference here? */
+ setzbufvlaggen(projectvert);
+
+ popTempPanoPhi();
+ panophi= temp;
+
+ zbuffershad(lar);
+
+ /* alle pixels 1 x ingevuld verwijderen (oneven) */
+ /* probleem hierbij kan geven dat er abrupte overgangen van zacht gebied
+ * naar geen zacht gebied is: bijv als eronder een klein vlakje zit
+ * DAAROM ER WEER UIT
+ * ook vanwege shadowhalo!
+ *
+ a= shb->size*shb->size;
+ rz= R.rectz;
+ while(a--) {
+ if(*rz & 1) *rz= 0x7FFFFFFF;
+ rz++;
+ }
+ */
+
+ square= lar->mode & LA_SQUARE;
+
+ /* Z tiles aanmaken: dit systeem is 24 bits!!! */
+
+ ztile= shb->zbuf;
+ ctile= shb->cbuf;
+ for(y=0; y<shb->size; y+=16) {
+ if(y< shb->size/2) miny= y+15-shb->size/2;
+ else miny= y-shb->size/2;
+
+ for(x=0; x<shb->size; x+=16) {
+
+ /* ligt rechthoek binnen spotbundel? */
+ a= shb->size/2;
+ if(x< a) minx= x+15-a;
+ else minx= x-a;
+
+ dist= sqrt( (float)(minx*minx+miny*miny) );
+
+ if(square==0 && dist>(float)(a+12)) { /* 12, tested with a onlyshadow lamp */
+ a= 256; verg= 0; /* 0x80000000; */ /* 0x7FFFFFFF; */
+ rz1= (&verg)+1;
+ }
+ else {
+ lrectreadRectz(x, y, MIN2(shb->size-1,x+15), MIN2(shb->size-1,y+15), rcline);
+ rz1= (int *)rcline;
+
+ verg= (*rz1 & 0xFFFFFF00);
+
+ for(a=0;a<256;a++,rz1++) {
+ if( (*rz1 & 0xFFFFFF00) !=verg) break;
+ }
+ }
+ if(a==256) { /* compleet leeg vakje */
+ *ctile= 0;
+ *ztile= *(rz1-1);
+ }
+ else {
+
+ /* ACOMP enz. zijn defined L/B endian */
+
+ rc= rcline;
+ rz1= (int *)rcline;
+ verg= rc[ACOMP];
+ verg1= rc[BCOMP];
+ rc+= 4;
+ byt1= 1; byt2= 1;
+ for(a=1;a<256;a++,rc+=4) {
+ byt1 &= (verg==rc[ACOMP]);
+ byt2 &= (verg1==rc[BCOMP]);
+
+ if(byt1==0) break;
+ }
+ if(byt1 && byt2) { /* alleen byte opslaan */
+ *ctile= 1;
+ *ztile= (unsigned long)MEM_mallocN(256+4, "tile1");
+ rz= (int *)*ztile;
+ *rz= *rz1;
+
+ zt= (char *)(rz+1);
+ rc= rcline;
+ for(a=0; a<256; a++, zt++, rc+=4) *zt= rc[GCOMP];
+ }
+ else if(byt1) { /* short opslaan */
+ *ctile= 2;
+ *ztile= (unsigned long)MEM_mallocN(2*256+4,"Tile2");
+ rz= (int *)*ztile;
+ *rz= *rz1;
+
+ zt= (char *)(rz+1);
+ rc= rcline;
+ for(a=0; a<256; a++, zt+=2, rc+=4) {
+ zt[0]= rc[BCOMP];
+ zt[1]= rc[GCOMP];
+ }
+ }
+ else { /* triple opslaan */
+ *ctile= 3;
+ *ztile= (unsigned long)MEM_mallocN(3*256,"Tile3");
+
+ zt= (char *)*ztile;
+ rc= rcline;
+ for(a=0; a<256; a++, zt+=3, rc+=4) {
+ zt[0]= rc[ACOMP];
+ zt[1]= rc[BCOMP];
+ zt[2]= rc[GCOMP];
+ }
+ }
+ }
+ ztile++;
+ ctile++;
+ }
+ }
+
+ MEM_freeN(rcline);
+ MEM_freeN(R.rectz); R.rectz= 0;
+
+ R.rectx= temprx; R.recty= tempry;
+ MTC_Mat4SwapMat4(shb->persmat, R.winmat);
+
+ /* printf("lampbuf %d\n", sizeoflampbuf(shb)); */
+}
+
+int firstreadshadbuf(struct ShadBuf *shb, int xs, int ys, int nr)
+{
+ /* return 1 als volledig gecomprimeerde shadbuftile && z==const */
+ static int *rz;
+ int ofs;
+ char *ct;
+
+ /* always test borders of shadowbuffer */
+ if(xs<0) xs= 0; else if(xs>=shb->size) xs= shb->size-1;
+ if(ys<0) ys= 0; else if(ys>=shb->size) ys= shb->size-1;
+
+ /* z berekenen */
+ ofs= (ys>>4)*(shb->size>>4) + (xs>>4);
+ ct= shb->cbuf+ofs;
+ if(*ct==0) {
+ if(nr==0) {
+ rz= *( (int **)(shb->zbuf+ofs) );
+ return 1;
+ }
+ else if(rz!= *( (int **)(shb->zbuf+ofs) )) return 0;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+float readshadowbuf(struct ShadBuf *shb, int xs, int ys, int zs) /* return 1.0 : volledig licht */
+{
+ float temp;
+ int *rz, ofs;
+ int zsamp;
+ char *ct, *cz;
+
+ /* simpleclip */
+ /* if(xs<0 || ys<0) return 1.0; */
+ /* if(xs>=shb->size || ys>=shb->size) return 1.0; */
+
+ /* always test borders of shadowbuffer */
+ if(xs<0) xs= 0; else if(xs>=shb->size) xs= shb->size-1;
+ if(ys<0) ys= 0; else if(ys>=shb->size) ys= shb->size-1;
+
+ /* z berekenen */
+ ofs= (ys>>4)*(shb->size>>4) + (xs>>4);
+ ct= shb->cbuf+ofs;
+ rz= *( (int **)(shb->zbuf+ofs) );
+
+ if(*ct==3) {
+ ct= ((char *)rz)+3*16*(ys & 15)+3*(xs & 15);
+ cz= (char *)&zsamp;
+ cz[ACOMP]= ct[0];
+ cz[BCOMP]= ct[1];
+ cz[GCOMP]= ct[2];
+ }
+ else if(*ct==2) {
+ ct= ((char *)rz);
+ ct+= 4+2*16*(ys & 15)+2*(xs & 15);
+ zsamp= *rz;
+
+ cz= (char *)&zsamp;
+ cz[BCOMP]= ct[0];
+ cz[GCOMP]= ct[1];
+ }
+ else if(*ct==1) {
+ ct= ((char *)rz);
+ ct+= 4+16*(ys & 15)+(xs & 15);
+ zsamp= *rz;
+
+ cz= (char *)&zsamp;
+ cz[GCOMP]= ct[0];
+
+ }
+ else {
+ /* got warning on this from alpha .... */
+ /* but it's working code! (ton) */
+ zsamp= (int) rz;
+ }
+
+ /* if(zsamp >= 0x7FFFFE00) return 1.0; */ /* geen schaduw als op oneindig wordt gesampeld*/
+
+ if(zsamp > zs) return 1.0; /* absoluut geen schaduw */
+ else if( zsamp < zs-bias) return 0.0 ; /* absoluut wel schaduw */
+ else { /* zacht gebied */
+
+ temp= ( (float)(zs- zsamp) )/(float)bias;
+ return 1.0 - temp*temp;
+
+ }
+}
+
+
+float testshadowbuf(struct ShadBuf *shb, float inp) /* return 1.0: geen schaduw */
+{
+ float fac, co[4], dx[3], dy[3], aantal=0;
+ float xs1,ys1, siz, *j, xres, yres;
+ int xs,ys, zs;
+ short a,num;
+
+#ifdef RE_NO_SHADOWS
+ return 1.0;
+#endif
+
+ /* if(inp <= 0.0) return 1.0; */
+
+ /* renderco en osaco roteren */
+ siz= 0.5*(float)shb->size;
+ VECCOPY(co, R.co);
+ co[3]= 1.0;
+
+ MTC_Mat4MulVec4fl(shb->persmat, co); /* rationele hom co */
+
+ xs1= siz*(1.0+co[0]/co[3]);
+ ys1= siz*(1.0+co[1]/co[3]);
+
+ /* Clip for z: near and far clip values of the shadow buffer. We
+ * can test for -1.0/1.0 because of the properties of the
+ * coordinate transformations. */
+ fac= (co[2]/co[3]);
+
+ if(fac>=1.0) {
+ return 0.0;
+ } else if(fac<= -1.0) {
+ return 1.0;
+ }
+
+ zs= ((float)0x7FFFFFFF)*fac;
+
+ /* num*num samples nemen, gebied met fac vergroten */
+ num= shb->samp*shb->samp;
+ fac= shb->soft;
+
+
+ bias= (1.1-inp*inp)*shb->bias;
+
+ if(num==1) {
+ return readshadowbuf(shb,(int)xs1, (int)ys1, zs);
+ }
+
+ co[0]= R.co[0]+O.dxco[0];
+ co[1]= R.co[1]+O.dxco[1];
+ co[2]= R.co[2]+O.dxco[2];
+ co[3]= 1.0;
+ MTC_Mat4MulVec4fl(shb->persmat,co); /* rationele hom co */
+ dx[0]= xs1- siz*(1.0+co[0]/co[3]);
+ dx[1]= ys1- siz*(1.0+co[1]/co[3]);
+
+ co[0]= R.co[0]+O.dyco[0];
+ co[1]= R.co[1]+O.dyco[1];
+ co[2]= R.co[2]+O.dyco[2];
+ co[3]= 1.0;
+ MTC_Mat4MulVec4fl(shb->persmat,co); /* rationele hom co */
+ dy[0]= xs1- siz*(1.0+co[0]/co[3]);
+ dy[1]= ys1- siz*(1.0+co[1]/co[3]);
+
+ xres= fac*( fabs(dx[0])+fabs(dy[0]) );
+ yres= fac*( fabs(dx[1])+fabs(dy[1]) );
+
+ if(xres<fac) xres= fac;
+ if(yres<fac) yres= fac;
+
+ xs1-= (xres)/2;
+ ys1-= (yres)/2;
+
+ j= shb->jit;
+
+ if(xres<16.0 && yres<16.0) {
+ if(firstreadshadbuf(shb, (int)xs1, (int)ys1, 0)) {
+ if(firstreadshadbuf(shb, (int)(xs1+xres), (int)ys1, 1)) {
+ if(firstreadshadbuf(shb, (int)xs1, (int)(ys1+yres), 1)) {
+ if(firstreadshadbuf(shb, (int)(xs1+xres), (int)(ys1+yres), 1)) {
+ return readshadowbuf(shb,(int)xs1, (int)ys1, zs);
+ }
+ }
+ }
+ }
+ }
+
+ for(a=num;a>0;a--) {
+ /* i.p.v. jit ook met random geprobeerd: lelijk! */
+ xs= xs1 + xres*j[0];
+ ys= ys1 + yres*j[1];
+ j+=2;
+
+ aantal+= readshadowbuf(shb, xs, ys, zs);
+ }
+
+ /* Renormalizes for the sample number: */
+ return aantal/( (float)(num) );
+}
+
+/* different function... sampling behind clipend can be LIGHT, bias is negative! */
+/* return: light */
+float readshadowbuf_halo(struct ShadBuf *shb, int xs, int ys, int zs)
+{
+ float temp;
+ int *rz, ofs;
+ int zbias, zsamp;
+ char *ct, *cz;
+
+ /* simpleclip */
+ if(xs<0 || ys<0) return 0.0;
+ if(xs>=shb->size || ys>=shb->size) return 0.0;
+
+ /* z berekenen */
+ ofs= (ys>>4)*(shb->size>>4) + (xs>>4);
+ ct= shb->cbuf+ofs;
+ rz= *( (int **)(shb->zbuf+ofs) );
+
+ if(*ct==3) {
+ ct= ((char *)rz)+3*16*(ys & 15)+3*(xs & 15);
+ cz= (char *)&zsamp;
+ zsamp= 0;
+ cz[ACOMP]= ct[0];
+ cz[BCOMP]= ct[1];
+ cz[GCOMP]= ct[2];
+ }
+ else if(*ct==2) {
+ ct= ((char *)rz);
+ ct+= 4+2*16*(ys & 15)+2*(xs & 15);
+ zsamp= *rz;
+
+ cz= (char *)&zsamp;
+ cz[BCOMP]= ct[0];
+ cz[GCOMP]= ct[1];
+ }
+ else if(*ct==1) {
+ ct= ((char *)rz);
+ ct+= 4+16*(ys & 15)+(xs & 15);
+ zsamp= *rz;
+
+ cz= (char *)&zsamp;
+ cz[GCOMP]= ct[0];
+
+ }
+ else {
+ /* same as before */
+ /* still working code! (ton) */
+ zsamp= (int) rz;
+ }
+
+ /* geen schaduw als op oneindig wordt gesampeld*/
+
+ if(zsamp >= 0x7FFFFE00) return 1.0;
+
+ if(zsamp > zs) return 1.0; /* absoluut geen schaduw */
+ else {
+ /* bias is negative, so the (zs-bias) can be beyond 0x7fffffff */
+ zbias= 0x7fffffff - zs;
+ if(zbias > -bias) {
+ if( zsamp < zs-bias) return 0.0 ; /* absoluut wel schaduw */
+ }
+ else return 0.0 ; /* absoluut wel schaduw */
+ }
+
+ /* zacht gebied */
+
+ temp= ( (float)(zs- zsamp) )/(float)bias;
+ return 1.0 - temp*temp;
+}
+
+
+float shadow_halo(LampRen *lar, float *p1, float *p2)
+{
+ /* p1 p2 already are rotated in spot-space */
+ ShadBuf *shb= lar->shb;
+ float co[4], siz;
+ float labda, labdao, labdax, labday, ldx, ldy;
+ float zf, xf1, yf1, zf1, xf2, yf2, zf2;
+ float count, lightcount;
+ int x, y, z, xs1, ys1;
+ int dx = 0, dy = 0;
+
+ siz= 0.5*(float)shb->size;
+ /* negative! The other side is more important */
+ bias= -shb->bias;
+
+ co[0]= p1[0];
+ co[1]= p1[1];
+ co[2]= p1[2]/lar->sh_zfac;
+ co[3]= 1.0;
+ MTC_Mat4MulVec4fl(shb->winmat, co); /* rationele hom co */
+ xf1= siz*(1.0+co[0]/co[3]);
+ yf1= siz*(1.0+co[1]/co[3]);
+ zf1= (co[2]/co[3]);
+
+
+ co[0]= p2[0];
+ co[1]= p2[1];
+ co[2]= p2[2]/lar->sh_zfac;
+ co[3]= 1.0;
+ MTC_Mat4MulVec4fl(shb->winmat, co); /* rationele hom co */
+ xf2= siz*(1.0+co[0]/co[3]);
+ yf2= siz*(1.0+co[1]/co[3]);
+ zf2= (co[2]/co[3]);
+
+ /* de 2dda */
+
+ xs1= (int)xf1;
+ ys1= (int)yf1;
+
+ if(xf1 != xf2) {
+ if(xf2-xf1 > 0.0) {
+ labdax= (xf1-xs1-1.0)/(xf1-xf2);
+ ldx= -shb->shadhalostep/(xf1-xf2);
+ dx= shb->shadhalostep;
+ }
+ else {
+ labdax= (xf1-xs1)/(xf1-xf2);
+ ldx= shb->shadhalostep/(xf1-xf2);
+ dx= -shb->shadhalostep;
+ }
+ }
+ else {
+ labdax= 1.0;
+ ldx= 0.0;
+ }
+
+ if(yf1 != yf2) {
+ if(yf2-yf1 > 0.0) {
+ labday= (yf1-ys1-1.0)/(yf1-yf2);
+ ldy= -shb->shadhalostep/(yf1-yf2);
+ dy= shb->shadhalostep;
+ }
+ else {
+ labday= (yf1-ys1)/(yf1-yf2);
+ ldy= shb->shadhalostep/(yf1-yf2);
+ dy= -shb->shadhalostep;
+ }
+ }
+ else {
+ labday= 1.0;
+ ldy= 0.0;
+ }
+
+ x= xs1;
+ y= ys1;
+ labda= count= lightcount= 0.0;
+
+/* printf("start %x %x \n", (int)(0x7FFFFFFF*zf1), (int)(0x7FFFFFFF*zf2)); */
+
+ while(1) {
+ labdao= labda;
+
+ if(labdax==labday) {
+ labdax+= ldx;
+ x+= dx;
+ labday+= ldy;
+ y+= dy;
+ }
+ else {
+ if(labdax<labday) {
+ labdax+= ldx;
+ x+= dx;
+ } else {
+ labday+= ldy;
+ y+= dy;
+ }
+ }
+
+ labda= MIN2(labdax, labday);
+ if(labda==labdao || labda>=1.0) break;
+
+ zf= zf1 + labda*(zf2-zf1);
+ count+= 1.0;
+
+ if(zf<= 0.0) lightcount += 1.0; /* close to the spot */
+ else {
+
+ /* make sure, behind the clipend we extend halolines. */
+ if(zf>=1.0) z= 0x7FFFF000;
+ else z= (int)(0x7FFFF000*zf);
+
+ lightcount+= readshadowbuf_halo(shb, x, y, z);
+
+ }
+ }
+
+ if(count!=0.0) return (lightcount/count);
+ return 0.0;
+
+}
+
+
+
+
+/* sampelen met filter
+ xstart= xs-1;
+ ystart= ys-1;
+ if(xstart<0) xstart= 0;
+ if(ystart<0) ystart= 0;
+ xend= xstart+2;
+ yend= ystart+2;
+ if(xend>=shb->size) { xstart= shb->size-3; xend= shb->size-1;}
+ if(yend>=shb->size) { ystart= shb->size-3; yend= shb->size-1;}
+
+ fid= filt3;
+ for(ys=ystart;ys<=yend;ys++) {
+ rz= shb->buf+ ys*shb->size+ xstart;
+ for(xs= xstart;xs<=xend;xs++,rz++) {
+ if( *rz+0x100000<zs) aantal+= *fid;
+ fid++;
+ }
+ }
+
+
+ return 1.0-((float)aantal)/16.0;
+*/
+
+
+
+
+
+
+
+
+
+
diff --git a/source/blender/render/intern/source/shadowBuffer.cpp b/source/blender/render/intern/source/shadowBuffer.cpp
new file mode 100644
index 00000000000..76668f4e9ac
--- /dev/null
+++ b/source/blender/render/intern/source/shadowBuffer.cpp
@@ -0,0 +1,100 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <assert.h>
+//#include <iostream.h>
+
+#include "render.h"
+#include "render_intern.h"
+#include "shadbuf.h"
+#include "shadowBuffer.h" /* the C header */
+#include "RE_ShadowBuffer.h" /* the base buffer */
+#include "RE_DummyShadowBuffer.h" /* A dummy shadow buffer */
+#include "RE_basicShadowBuffer.h" /* the 'old' shadow buffer */
+
+struct ShadBuf;
+struct LampRen;
+struct Lamp;
+/*
+ * Creates a shadow buffer of a certain type
+ */
+RE_ShadowBufferHandle RE_createShadowBuffer(struct LampRen *lar,
+ float mat[][4],
+ int mode)
+{
+ /* make a dummy: this always returns a fixed value */
+ RE_ShadowBuffer* buf = NULL;
+ switch (mode) {
+ case 0:
+ buf = new RE_DummyShadowBuffer();
+ break;
+ case 1:
+ /* loop to the old c-based buffer */
+ /* memory release is done implicitly! */
+ initshadowbuf(lar, mat);
+ break;
+ case 2:
+ buf = new RE_BasicShadowBuffer(lar, mat);
+ break;
+ case 3:
+// cout << "Deep shadow buffer requested\n";
+ break;
+ default:
+// cerr << "Bad shadow buffer type specified\n";
+ ; /* nada */
+ }
+ return (RE_ShadowBufferHandle) buf;
+}
+
+void RE_deleteShadowBuffer(RE_ShadowBufferHandle buf)
+{
+// cout << "requesting buffer delete\n";
+ assert(buf);
+ delete (RE_ShadowBuffer*) buf;
+}
+
+void RE_buildShadowBuffer(RE_ShadowBufferHandle buf,
+ struct LampRen *lar)
+{
+ assert(buf);
+ ((RE_ShadowBuffer*) buf)->importScene(lar);
+}
+
+
+void RE_testshadowbuf(RE_ShadowBufferHandle buf,
+ struct ShadBuf* shbp,
+ float inp,
+ float* shadres)
+{
+ assert(buf);
+ ((RE_ShadowBuffer*) buf)->readShadowValue(shbp, inp, shadres);
+}
diff --git a/source/blender/render/intern/source/vanillaRenderPipe.c b/source/blender/render/intern/source/vanillaRenderPipe.c
new file mode 100644
index 00000000000..5f78e1b25c9
--- /dev/null
+++ b/source/blender/render/intern/source/vanillaRenderPipe.c
@@ -0,0 +1,1654 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * vanillaRenderPipe.c
+ *
+ * 28-06-2000 nzc
+ *
+ * $Id$
+ *
+ */
+
+/*
+ The render pipe
+ ---------------
+
+ The overall results of the render pass should end up in R.rectot. This
+ buffer already exists, and although its contents may change, its location
+ may not. A lot of other routines depend on it!
+
+*/
+
+/* global includes */
+#include <math.h>
+#include <limits.h> /* INT_MIN,MAX are used here */
+#include <stdlib.h>
+#include "MTC_vectorops.h"
+#include "MTC_matrixops.h"
+#include "MEM_guardedalloc.h"
+
+#include "DNA_camera_types.h"
+#include "DNA_object_types.h"
+#include "BKE_global.h"
+
+/* local includes (from the render module) */
+#include "RE_callbacks.h"
+#include "render.h" /* all kinds of stuff */
+#include "render_intern.h"
+#include "zbuf.h" /* for vergzvlak, zbufclip, zbufclipwire */
+#include "edgeRender.h" /* all edge rendering stuff */
+#include "pixelshading.h" /* painting the pixels */
+#include "rendercore.h"
+
+/* general calculus and data manipulation, also local */
+#include "gammaCorrectionTables.h"
+#include "jitter.h"
+#include "pixelblending.h"
+#include "zbufferdatastruct.h"
+
+/* own includes */
+#include "vanillaRenderPipe.h"
+#include "vanillaRenderPipe_int.h"
+
+/* crud */
+#define MIN2(x,y) ( (x)<(y) ? (x) : (y) )
+
+/* ------------------------------------------------------------------------- */
+/* Debug defines: disable all for production level code. */
+/* These variables control faking of rendered colours, extra tracing, */
+/* extra error checking and such. */
+/* ------------------------------------------------------------------------- */
+
+/* if defined: _very_ explicit tracing and checking enabled */
+/* #define RE_FULL_SAFETY */
+/* if defined: use 'simple' alpha thresholding on oversampling */
+/* #define RE_SIMPLE_ALPHA_THRESHOLD */
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef RE_FULL_SAFETY
+/* Full safety does the following: */
+/* - add extra bounds checking */
+/* - add extra type checking */
+/* - do a little performance analysis */
+/* - trace the original sources */
+
+/* trace the version of the source */
+char vanillaRenderPipe_ext_h[] = VANILLARENDERPIPE_EXT_H;
+char vanillaRenderPipe_int_h[] = VANILLARENDERPIPE_INT_H;
+char vanillaRenderPipe_types_h[] = VANILLARENDERPIPE_TYPES_H;
+char vanillaRenderPipe_c[] =
+"$Id$";
+/* counters for error handling */
+static int conflictsresolved; /* number of conflicts in one frame */
+
+#include "errorHandler.h"
+#endif /* RE_FULL_SAFETY stuff */
+
+/* ------------------------------------------------------------------------- */
+
+/* External : -------------------------------------------------------------- */
+
+extern float centLut[16]; /* Lookup for jitter offsets. */
+extern unsigned int Zsample; /* Nr. of the currently active oversample. This */
+ /* counter must be set explicitly by the */
+ /* function that builds the z-buffer. */
+ /* The buffer-filling functions use it. */
+extern float Zjitx,Zjity; /* The x,y values for jitter offset */
+
+extern float Zmulx, Zmuly; /* Some kind of scale? */
+
+extern unsigned int Zvlnr; /* Face rendering pointer and counter: these */
+extern VlakRen *Zvlr; /* are used for 'caching' render results. */
+
+ /* These function pointers are used for z buffer filling. */
+extern void (*zbuffunc)(float *, float *, float *);
+extern void (*zbuflinefunc)(float *, float *);
+
+extern char cmask[256]; /* When a pixel is supersampled, we must */
+extern char *centmask; /* compute its colour on a point _on_ the face. */
+ /* These two are used to compute an offset to */
+ /* guarantee we use valid coordinates. */
+
+/* unsorted */
+extern float holoofs, fmask[256];
+extern unsigned short usegamtab, shortcol[4],
+ *mask1[9], *mask2[9],/* *igamtab1, */ *igamtab2/*, *gamtab */;
+
+extern RE_APixstrExt *APixbufExt;/*Zbuffer: linked list of face, halo indices*/
+
+/* Globals : --------------------------------------------------------------- */
+
+RE_COLBUFTYPE *AColourBuffer; /* Buffer for colours of 1 line of pixels */
+static int Aminy; /* y value of first line in the accu buffer */
+static int Amaxy; /* y value of last line in the accu buffer */
+ /* -also used to clip when zbuffering */
+
+/* Buffer width refers to the size of the buffers we build. Image size is */
+/* the same as R.rectx, R.recty. */
+static int imageHeight; /* image size in pixels in y direction */
+static int imageWidth; /* image size in pixels in x direction */
+static int bufferHeight; /* image size in pixels in y direction */
+static int bufferWidth; /* image size in pixels in x direction */
+static int zBufferWidth; /* special width because zbuffer needs to be */
+ /* wider */
+
+static int Azvoordeel; /* A small offset for transparent rendering. */
+int alphaLUT[32]; /* alpha lookuptable, for oversampling */
+ /* Its function has been superceded because */
+ /* pixels are always integrated. This */
+ /* performs the same normalization. */
+int osaNr; /* The oversample number. I keep it */
+ /* separately here, because I treat no OSA */
+ /* as if it were osa=1. */
+RE_COLBUFTYPE collector[4]; /* used throughout as pixel colour accu */
+RE_COLBUFTYPE sampcol[RE_MAX_OSA_COUNT * 4]; /* subpixel accu buffer */
+
+/* ------------------------------------------------------------------------- */
+/* Local (for now) */
+/* void integrateStack(struct RE_faceField* stack, */
+/* int ptr, */
+/* float x, */
+/* float y, */
+/* int osaNr); */
+void integratePerSubStack(struct RE_faceField* stack,
+ int ptr,
+ float x,
+ float y,
+ int osaNr);
+
+/* ------------------------------------------------------------------------- */
+
+void zBufShadeAdvanced()
+{
+ int y, keepLooping = 1;
+ float xjit = 0.0, yjit = 0.0;
+
+#ifdef RE_FULL_SAFETY
+ /* reset trace */
+ RE_errortrace_reset();
+ conflictsresolved = 0;
+ fprintf(stderr, "\n*** Activated full error trace on "
+ "unified renderer using:\n\t%s\n\t%s\n\t%s\n\t%s",
+ vanillaRenderPipe_c, vanillaRenderPipe_ext_h,
+ vanillaRenderPipe_int_h, vanillaRenderPipe_types_h);
+#endif
+
+ Zjitx=Zjity= -0.5; /* jitter preset: 0.5 pixel */
+
+ /* EDGE: for edge rendering we should compute a larger buffer, but this */
+ /* may require modifications at a deeper level. For now, we just */
+ /* 'ignore' edge pixels. */
+ imageHeight = R.recty;
+ imageWidth = R.rectx;
+ bufferHeight = R.recty;
+ bufferWidth = R.rectx;
+
+ /* Set osaNr. Treat 'no osa' as 'osa = 1' */
+ if(R.r.mode & R_OSA) {
+ osaNr = R.osa;
+ if(osaNr > 16) { /* check was moved from calcZBufLine */
+ printf("zBufShadeAdvanced> osa too large (internal error)\n");
+ G.afbreek= 1;
+ return;
+ }
+ } else {
+ /* little hack */
+ osaNr = 1;
+ xjit = jit[0][0];
+ yjit = jit[0][1];
+ jit[0][0] = 0.45;
+ jit[0][1] = 0.45;
+ }
+
+ RE_setwindowclip(0, -1); /* just to be sure, reset the view matrix */
+
+ initRenderBuffers(bufferWidth);
+
+ /* ugh! should be converted sooner!! */
+ switch (R.r.alphamode) {
+ case R_ALPHAKEY:
+ setSkyBlendingMode(RE_ALPHA_KEY);
+ break;
+ case R_ALPHAPREMUL:
+ setSkyBlendingMode(RE_ALPHA_PREMUL);
+ break;
+/* not there... this is the default case */
+/* case R_ALPHASKY: */
+/* setSkyBlendingMode(RE_ALPHA_SKY); */
+/* break; */
+ default:
+ setSkyBlendingMode(RE_ALPHA_SKY);
+ }
+
+ y = 0;
+ while ( (y < bufferHeight) && keepLooping) {
+ calcZBufLine(y);
+ R.vlaknr= -1; /* huh? why reset this counter? for shadePixel! */
+ renderZBufLine(y);
+ transferColourBufferToOutput(y);
+
+ if((y & 1) && G.background!=1) RE_local_render_display(y-1, y,
+ imageWidth,
+ imageHeight,
+ R.rectot);
+
+ if(RE_local_test_break()) keepLooping = 0;
+ y++;
+ }
+ freeRenderBuffers();
+
+ /* Edge rendering is done purely as a post-effect */
+ if(R.r.mode & R_EDGE) {
+ addEdges((char*)R.rectot, imageWidth, imageHeight,
+ osaNr,
+ R.r.edgeint, R.r.same_mat_redux,
+ G.compat, G.notonlysolid,
+ R.r.edgeR, R.r.edgeG, R.r.edgeB);
+ }
+
+ add_halo_flare(); /* from rendercore */
+
+#ifdef RE_FULL_SAFETY
+ fprintf(stderr, "\n--- resolved %d conflicts", conflictsresolved);
+ fflush(stderr);
+#endif
+
+ if (!(R.r.mode & R_OSA)) {
+ jit[0][0] = xjit;
+ jit[0][1] = yjit;
+ }
+
+} /* end of void zbufshadeAdvanced() */
+
+/* ------------------------------------------------------------------------- */
+
+void initRenderBuffers(int bwidth)
+{
+
+ /* The +1 is needed because the fill-functions use a +1 offset when */
+ /* filling in pixels. Mind that also the buffer-clearing function needs */
+ /* this offset (done in calcZBufLine). */
+ /* The offset is wrong: it shouldn't be there. I need to fix this still. */
+ AColourBuffer = MEM_callocN(4 * sizeof(RE_COLBUFTYPE) * bwidth,
+ "Acolrow");
+ zBufferWidth = bwidth + 1;
+ initZbuffer(bwidth + 1);
+
+ Aminy= -1000; /* indices of lines in the z buffer: no lines buffered */
+ Amaxy= -1000;
+
+ /* Use slider when the gamma button is pressed. */
+ if (R.r.mode & R_GAMMA) {
+ makeGammaTables(R.r.gamma);
+ setDoGamma(1);
+ } else {
+ /*
+ Needed for spotlights! Maybe a separate gammatable would be
+ required here
+ */
+ makeGammaTables(1.0);
+ setDoGamma(0);
+ }
+
+} /* End of void initZBuffers(void) */
+
+/* ------------------------------------------------------------------------- */
+
+void freeRenderBuffers(void) {
+ if (AColourBuffer) MEM_freeN(AColourBuffer);
+ freeZbuffer();
+} /* End of void freeZBuffers(void) */
+
+/* ------------------------------------------------------------------------- */
+
+void calcZBufLine(int y)
+{
+
+ int part;
+ int keepLooping = 1;
+
+ if(y<0) return;
+
+ /* zbuffer fix: here? */
+ Zmulx= ((float) bufferWidth)/2.0;
+ Zmuly= ((float) bufferHeight)/2.0;
+
+
+ /* use these buffer fill functions */
+ zbuffunc = zBufferFillFace;
+ zbuflinefunc = zBufferFillEdge;
+
+ /* (FORALL y: Aminy =< y =< Amaxy: y is buffered) */
+ if( (y < Aminy) || (y > Amaxy)) {
+ /* prepare buffer */
+ part = (y/RE_ZBUFLEN); /* These two lines are mystifying me... */
+ Aminy = part * RE_ZBUFLEN; /* Possibly for rounding things? */
+ Amaxy = Aminy + RE_ZBUFLEN - 1;
+/* if(Amaxy >= R.recty) Amaxy = R.recty-1; */
+ if(Amaxy >= bufferHeight) Amaxy = bufferHeight - 1;
+ resetZbuffer();
+
+ Zsample = 0; /* Zsample is used internally ! */
+ while ( (Zsample < osaNr) && keepLooping ) {
+ /* Apply jitter to this pixel. The jitter offsets are globals. */
+ /* They are added in zbufclip() */
+ /* Negative: these offsets are added to the vertex coordinates */
+ /* so it equals translating viewpoint over the positive vector. */
+ Zjitx= -jit[Zsample][0];
+ Zjity= -jit[Zsample][1];
+
+ keepLooping = fillZBufDistances();
+
+ if(RE_local_test_break()) keepLooping = 0;
+ Zsample++;
+ }
+ };
+
+} /*End of void calcZBufLine(int y) */
+
+/* ------------------------------------------------------------------------- */
+
+int countAndSortPixelFaces(int zrow[RE_MAX_FACES_PER_PIXEL][RE_PIXELFIELDSIZE],
+ RE_APixstrExt *ap)
+{
+#ifdef RE_FULL_SAFETY
+ char fname[] = "countAndSortPixelFaces";
+#endif
+ int totvlak; /* face counter */
+ int i; /* generic counter */
+
+ totvlak= 0;
+ while(ap) {
+ for(i=0; i<4; i++) {
+ if(ap->t[i]) {
+ zrow[totvlak][0] = ap->zmin[i];
+ zrow[totvlak][1] = ap->p[i];
+ zrow[totvlak][2] = ap->mask[i];
+ zrow[totvlak][3] = ap->t[i];
+ zrow[totvlak][4] = ap->zmax[i];
+ totvlak++;
+ if(totvlak > (RE_MAX_FACES_PER_PIXEL - 1))
+ {
+ totvlak = (RE_MAX_FACES_PER_PIXEL - 1);
+#ifdef RE_FULL_SAFETY
+ RE_error(RE_TOO_MANY_FACES, fname);
+#endif
+ }
+ } else break;
+ };
+ ap= ap->next;
+ }
+
+ if(totvlak==2) { /* Sort faces ----------------------------- */
+ if(zrow[0][0] < zrow[1][0]) {
+ i= zrow[0][0]; zrow[0][0]= zrow[1][0]; zrow[1][0]= i;
+ i= zrow[0][1]; zrow[0][1]= zrow[1][1]; zrow[1][1]= i;
+ i= zrow[0][2]; zrow[0][2]= zrow[1][2]; zrow[1][2]= i;
+ i= zrow[0][3]; zrow[0][3]= zrow[1][3]; zrow[1][3]= i;
+ i= zrow[0][4]; zrow[0][4]= zrow[1][4]; zrow[1][4]= i;
+ } /* else: two faces, and ordering is ok */
+ } else if (totvlak != 1) qsort(zrow, totvlak,
+ sizeof(int)*RE_PIXELFIELDSIZE, vergzvlak);
+ return totvlak;
+} /* end of int countAndSortPixelFaces(int* zrow,RE_APixstrExt *ap ) */
+
+/* ------------------------------------------------------------------------- */
+/* Oversampler v3 - check CVS for older versions */
+/* */
+/* In this version, I have split up the rendering into several parts, so I */
+/* can generate better profiles. */
+/* */
+/* - multiple blend functions ? */
+/* - x-rays? */
+/* - volumetric stuff ? */
+/* - maybe the oversampling should move to the shading part */
+/* */
+/* ------------------------------------------------------------------------- */
+
+/* These variables describe the buffers needed for the oversampling. */
+/* 1. A bit vector with flags to indicate which pixels have received colour. */
+static int VR_covered = 0;
+/* 2. The local vector collector, for resolving conflicts only. */
+static int VR_cbuf[RE_MAX_FACES_PER_PIXEL][2];
+
+/**
+ * Analyze the z-buffer, and pre-sample the colours.
+ */
+int composeStack(int zrow[RE_MAX_FACES_PER_PIXEL][RE_PIXELFIELDSIZE],
+ struct RE_faceField* stack, int ptr,
+ int totvlak, float x, float y, int osaNr) {
+
+#ifdef RE_FULL_SAFETY
+ char* fname = "composeStack";
+#endif
+ float xs = 0.0;
+ float ys = 0.0; /* coordinates for the render-spot */
+
+ float alphathreshold[RE_MAX_OSA_COUNT];
+ int inconflict = 0;
+ int saturationthreshold = 0;
+ int saturated = 0;
+ int i = 0;
+ int Ccount = 0;
+ int Cthresh = 0;
+ int save_totvlak = totvlak;
+ int fullsubpixelflags = 0;
+
+ VR_covered = 0;
+ for(i = 0; i < osaNr; i++) alphathreshold[i] = 0.0;
+ saturationthreshold = ( (1<<osaNr) - 1);
+
+ while ( (!saturated || (saturated && inconflict) ) && (totvlak > 0) ) {
+ totvlak--;
+
+ i= centmask[ zrow[totvlak][RE_MASK] ]; /* recenter sample position - */
+ xs= (float)x+centLut[i & 15];
+ ys= (float)y+centLut[i >> 4];
+
+ /* stack face ----------- */
+ stack[ptr].data = renderPixel(xs, ys, zrow[totvlak]);
+ stack[ptr].faceType = zrow[totvlak][RE_TYPE];
+ cpFloatColV(collector, stack[ptr].colour);
+ stack[ptr].mask = zrow[totvlak][RE_MASK];
+
+ /* This is done so that spothalos are properly overlayed on halos */
+ /* maybe we need to check the colour here... */
+ if(zrow[totvlak][RE_TYPE] & RE_POLY) VR_covered |= zrow[totvlak][RE_MASK];
+
+ /* calculate conflict parameters: ---------------------------------- */
+ if( zrow[totvlak][RE_ZMIN] < Cthresh ) {
+ inconflict = 1;
+ /* Prevent from switching on bad data. This may be done more */
+ /* efficiently later on. It is _quite_ important. */
+ if (totvlak == save_totvlak - 1) Ccount = 0;
+ else if(Ccount == 0) Ccount = 2;
+ else Ccount++;
+ stack[ptr].conflictCount = Ccount;
+ if (zrow[totvlak][RE_ZMAX] > Cthresh)
+ Cthresh = zrow[totvlak][RE_ZMAX];
+#ifdef RE_FULL_SAFETY
+ if (Ccount == 2) conflictsresolved++;
+#endif
+ } else {
+ Cthresh = zrow[totvlak][RE_ZMAX];
+ Ccount = 0;
+ stack[ptr].conflictCount = 0;
+ if (totvlak > 0 )
+ inconflict = (zrow[totvlak-1][RE_ZMIN] < Cthresh);
+ else inconflict = 0;
+ }
+
+ ptr++;
+
+ /* alpha threshold ------------------------------------------------- */
+ /* There are currently two ways of blending: alpha-over, and add. */
+ /* Add-blending does strange things, in the sense that alpha is */
+ /* simply added, and colour is sort of alpha-over blended. Using the */
+ /* same thresholding relation seems to work ok. For less than unity */
+ /* add factor, the alpha threshold may rise faster, but currently we */
+ /* do not check for this factor. */
+ for(i = 0; i < osaNr; i++) {
+ if ( zrow[totvlak][RE_MASK] & (1<<i)) {
+ alphathreshold[i] +=
+ ((1.0 - alphathreshold[i]) * collector[3]);
+ if (alphathreshold[i] > RE_FULL_ALPHA_FLOAT)
+ fullsubpixelflags |= (1<<i);
+ }
+ }
+ saturated = (fullsubpixelflags >= saturationthreshold);
+
+ } /* done stacking ----------------------------------------------------- */
+
+ /*
+ STACK_SKY Sometimes, a sky pixel is needed. Since there are
+ some issues with mist/ ztra/ env, I always put the sky here.
+ */
+/* if (!saturated) { */
+ totvlak--;
+
+ xs= (float)x;
+ ys= (float)y;
+
+ renderSkyPixelFloat(xs, ys);
+
+ stack[ptr].faceType = RE_SKY;
+ cpFloatColV(collector, stack[ptr].colour);
+ stack[ptr].data = NULL;
+ stack[ptr].mask = 0xFFFF;
+ stack[ptr].conflictCount = 0;
+ ptr++;
+/* } */
+
+ /* Index of the top of the stack */
+ return ptr;
+}
+
+/*
+ Start resolving the conflict: the stack is primed to the top-most valid
+ layer on the stack. Call this layer n. Layer n has a conflict count of c.
+ This means layers [ n - c, ..., n ]
+ */
+int resolveConflict(struct RE_faceField* stack, int ptr, float x, float y) {
+#ifdef RE_FULL_SAFETY
+ char* fname = "resolveConflicts";
+#endif
+ int face;
+ int layer;
+ float dx, dy;
+ float xs = 0.0;
+ float ys = 0.0; /* coordinates for the render-spot */
+ int i;
+
+ for(i = 0; i< osaNr; i++) { /* per bin, buffer all faces */
+ dx = jit[i][0];
+ dy = jit[i][1];
+ xs = (float)x + dx;
+ ys = (float)y + dy;
+
+ face = 0; /* only counts covering faces ------------------- */
+ layer = 0; /* counts all faces ----------------------------- */
+
+ while (layer < stack[ptr].conflictCount) {
+ if ( (1<<i) & stack[ptr - layer].mask) {
+ VR_cbuf[face][0] =
+ calcDepth(xs, ys,
+ stack[ptr - layer].data,
+ stack[ptr - layer].faceType);
+ VR_cbuf[face][1] = ptr - layer;
+ face++;
+ }
+ layer++;
+ }
+ qsort(VR_cbuf, face, sizeof(int)*2, vergzvlak);
+ for(layer = 0; layer < face; layer++) {
+ blendOverFloat(stack[VR_cbuf[layer][1]].faceType, /* type */
+ sampcol + (4 * i), /* dest */
+ stack[VR_cbuf[layer][1]].colour, /* src */
+ stack[VR_cbuf[layer][1]].data); /* data */
+ }
+ }
+
+ /* The number of layers that were handled. This is how many layers the */
+ /* top-level algorithm needs to skip. */
+ return stack[ptr].conflictCount;
+}
+
+/* The colour stack is blended down in a pretty straight-forward manner, or */
+/* a part of the stack is re-evaluated to resolve the conflict. */
+/* About 25-30% of rendering time is eaten here! */
+void integrateStack(struct RE_faceField* stack, int ptr,
+ float x,
+ float y,
+ int osaNr) {
+ /* sample the colour stack: back to front ---------------------------- */
+ /* is there a possible way to ignore alpha? this would save 25% work */
+ ptr--;
+ /* Little different now: let ptr point to the topmost valid face.*/
+ while (ptr >= 0) {
+ if (stack[ptr].conflictCount == 0) {
+ /*
+ No conflict: sample one colour into multiple bins
+ */
+ blendOverFloatRow(stack[ptr].faceType,
+ sampcol,
+ stack[ptr].colour,
+ stack[ptr].data,
+ stack[ptr].mask,
+ osaNr);
+ ptr--;
+ } else {
+ /*
+ Recalc all z-values, and integrate per sub-pixel.
+ */
+ ptr -= resolveConflict(stack, ptr, x, y);
+ }
+ }
+
+ /* Done sampling. Now we still need to fill in pixels that were not */
+ /* covered at all It seems strange that we have to check for empty alpha */
+ /* but somehow this is necessary. Check out the cover condition :).... */
+
+ /* It is important that we find a more efficient algorithm here, because */
+ /* this little loop eats _lots_ of cycles. */
+
+ /* Should be integrated in the rest of the rendering... */
+
+ if((R.flag & R_LAMPHALO)
+ /*&&
+ ( VR_covered < ((1 << osaNr) - 1 ) )*/
+ ) {
+ float halocol[4];
+ int i;
+ renderSpotHaloPixel(x, y, halocol);
+ /* test seems to be wrong? */
+ if (halocol[3] > RE_EMPTY_COLOUR_FLOAT) {
+ for (i = 0; i < osaNr; i++) {
+ /* here's a pinch: if the pixel was only covered by a halo, */
+ /* we still need to fill spothalo. How do we detect this? */
+ if (!(VR_covered & (1 << i)))
+ /* maybe a copy is enough here... */
+ addAlphaOverFloat(sampcol + (4 * i), halocol);
+ }
+ }
+ }
+}
+
+/**
+ * New approach: sample substacks. Each substack is first copied into
+ * a stack buffer, and then blended down.
+ * */
+void integratePerSubStack(struct RE_faceField* stack,
+ int ptr,
+ float x,
+ float y,
+ int osaNr) {
+ int i = 0;
+ int j = 0;
+ int k = 0;
+ int l = 0;
+ int filterMask = 0;
+ /* next step would be to improve on the substack, I guess */
+ int subStack[RE_MAX_FACES_PER_PIXEL + 1];
+ float colSubStack[4 * (RE_MAX_FACES_PER_PIXEL + 1)];
+ int subStackPtr = 0;
+ int subStackSize = 0;
+ float xs, ys;
+
+
+ while (i < osaNr) {
+ xs = x + jit[i][0];
+ ys = y + jit[i][1];
+
+ /*
+ * 1. Copy all relevant faces. Mind that stack is built from
+ * low index = low z to high index =high z. The sub-stack is
+ * exactly the other way around! (low index = high z)
+ */
+ filterMask = (1 << i);
+ subStackPtr = 0;
+ j = ptr - 1; /* the topmost valid face */
+ while (j >= 0) {
+ if (stack[j].conflictCount) {
+ /* Conflict: we sort the faces for distance right
+ * away. We could adapt conflict count, and adjust the
+ * stack later on, but that's really doing too much,
+ * too complicated. This is just fine.
+ * */
+ k = 0;
+ l = 0;
+ /* check whether the face intersects, and if so,
+ * stores depth */
+ while (k < stack[j].conflictCount) {
+ if (stack[j - k].mask & filterMask) {
+ VR_cbuf[l][0] = calcDepth(xs, ys,
+ stack[j - k].data,
+ stack[j - k].faceType);
+ VR_cbuf[l][1] = j - k;
+ l++;
+ }
+ k++;
+ }
+ /* VR_cbuf now contains l pairs (distance, stackindex) */
+ qsort(VR_cbuf, l, sizeof(int)*2, vergzvlak);
+ /*
+ * Now we put the sorted indices on the
+ * substack. qsort delivers low index = low z, which
+ * is the right wrong order for the substack */
+ k = 0;
+ while (k < l) {
+ subStack[subStackPtr] = VR_cbuf[k][1];
+ cpFloatColV(stack[VR_cbuf[k][1]].colour, &colSubStack[4*subStackPtr]);
+ subStackPtr++;
+ k++;
+ }
+
+ j -= stack[j].conflictCount;
+ } else {
+ /* no conflict */
+ if (stack[j].mask & filterMask) {
+ subStack[subStackPtr] = j;
+ cpFloatColV(stack[j].colour, &colSubStack[4*subStackPtr]);
+ subStackPtr++;
+ }
+ j--;
+ }
+ }
+ subStackSize = subStackPtr;
+
+ /* 2. Operations on the faces can go here for now. I might
+ * want to mix this code with the blending. Currently, I only
+ * handle env/ztra faces. It's a dirty patch now...*/
+ subStackPtr = subStackSize - 1;
+ while (subStackPtr >= 0) {
+ /* we can make a general meachanism here for operations */
+ if (stack[subStack[subStackPtr]].faceType == RE_POLY){
+ VlakRen* vlr = (VlakRen*) stack[subStack[subStackPtr]].data;
+ if (vlr->mat) {
+ /* ENV faces */
+ if (vlr->mat->mode & MA_ENV) {
+ int m;
+ colSubStack[4*subStackPtr] = 0.0;
+ colSubStack[(4*subStackPtr) + 1] = 0.0;
+ colSubStack[(4*subStackPtr) + 2] = 0.0;
+ colSubStack[(4*subStackPtr) + 3] = 0.0;
+ m = subStackPtr - 1;
+ while (m >= 0) {
+ if (stack[subStack[m]].faceType != RE_SKY) {
+ colSubStack[4*m] = 0.0;
+ colSubStack[(4*m) + 1] = 0.0;
+ colSubStack[(4*m) + 2] = 0.0;
+ colSubStack[(4*m) + 3] = 0.0;
+ }
+ m--;
+ }
+ }
+ /* ZTRA faces */
+ else if (!(vlr->mat->mode & MA_ZTRA)) {
+ int m;
+ m = subStackPtr - 1;
+ while (m >= 0) {
+ if (stack[subStack[m]].faceType != RE_SKY) {
+ colSubStack[4*m] = 0.0;
+ colSubStack[(4*m) + 1] = 0.0;
+ colSubStack[(4*m) + 2] = 0.0;
+ colSubStack[(4*m) + 3] = 0.0;
+ }
+ m--;
+ }
+ }
+ }
+ }
+ subStackPtr--;
+ }
+
+ /* 3. blend down */
+ subStackPtr = 0;
+ while( subStackPtr < subStackSize ) {
+ blendOverFloat(stack[subStack[subStackPtr]].faceType, /* type */
+ sampcol + (4 * i), /* dest */
+ &colSubStack[4 * subStackPtr],
+ stack[subStack[subStackPtr]].data); /* data */
+ subStackPtr++;
+ }
+
+ i++;
+ }
+}
+
+
+
+/* ------------------------------------------------------------------------- */
+/* Rendering: per line */
+/* */
+/* For each pixel in this line, we render as follows: */
+/* a. Count the number of objects buffered for this pixel, and sort on z */
+/* ------- Result is left in zrow */
+/* b. Shade the pixel: */
+/* 1. From front to back: calculate the colour for this object */
+/* 2. Blend this colour in with the already calculated colour */
+/* Repeat 1. and 2. until no faces remain. */
+/* For each pixel, a face is only rendered once, even if it is */
+/* jittered. All subpixels get the colour of the weighted centre */
+/* of the jitter-positions this face covers. */
+/* ------- Result is left in sampcol[] */
+/* c. Copy the result to the colour buffer */
+/* d. Do gamma-corrected blending */
+/* */
+/* zrow may need some clarification: */
+/* 0 - min. distance */
+/* 1 - face/halo index */
+/* 2 - masks */
+/* 3 - type RE_POLY or RE_HALO */
+/* 4 - max. distance */
+/* It is used to store copies of RE_APixstrExt records. These are sorted for */
+/* distance, and then used for rendering pixels. zrow might be replaced by */
+/* an RE_APixstrExt* array */
+/* - redo the numbering to something more logical */
+void renderZBufLine(int y) {
+ int zrow[RE_MAX_FACES_PER_PIXEL][RE_PIXELFIELDSIZE];
+ RE_APixstrExt *ap; /* iterator for the face-lists */
+ int apteller;
+ int x; /* pixel counter */
+ RE_COLBUFTYPE *colbuf; /* pointer into the line buffer */
+ RE_COLBUFTYPE *j = NULL; /* generic pixel pointer */
+ int i; /* yet another counter */
+ int stackDepth; /* faces-behind-this-pixel counter */
+ struct RE_faceField RE_OSAstack[RE_MAX_FACES_PER_PIXEL + 1];
+ int RE_OSAstack_ptr; /* Points to the lowest empty field. The indexed */
+ /* field is NOT readable. */
+
+ /* Prepare buffers and iterators */
+ colbuf = AColourBuffer;
+ eraseColBuf(AColourBuffer);
+ ap = APixbufExt + (zBufferWidth * (y - Aminy));
+ apteller = (zBufferWidth * (y - Aminy));
+
+ /* Rendering: give the right colour to this pixel (shade it) */
+ for( x = 0; x < bufferWidth; x++, ap++, colbuf+=4) {
+ if(ap->t[0]) {
+ /* reset sample collector */
+ j = sampcol;
+ for(i = 0; i < osaNr; i++, j+=4) {
+ j[0] = RE_ZERO_COLOUR_FLOAT; j[1] = RE_ZERO_COLOUR_FLOAT;
+ j[2] = RE_ZERO_COLOUR_FLOAT; j[3] = RE_ZERO_COLOUR_FLOAT;
+ };
+
+ /* a. count and sort number of faces */
+ stackDepth = countAndSortPixelFaces(zrow, ap);
+
+ /* b,c. oversample all subpixels, then integrate */
+ RE_OSAstack_ptr = 0;
+ RE_OSAstack_ptr = composeStack(zrow,
+ RE_OSAstack, RE_OSAstack_ptr,
+ stackDepth, x, y, osaNr);
+/* #ifdef RE_OLD_INTEGRATION */
+/* printf("Performing old integration\n"); */
+/* integrateStack(RE_OSAstack, RE_OSAstack_ptr, */
+/* x, y, osaNr); */
+/* #endif */
+/* #ifndef RE_OLD_INTEGRATION */
+/* printf("Performing new integration\n"); */
+ integratePerSubStack(RE_OSAstack, RE_OSAstack_ptr,
+ x, y, osaNr);
+/* #endif */
+
+ /* d. Gamma corrected blending */
+ sampleFloatColV2FloatColV(sampcol, colbuf, osaNr);
+ } else {
+ /* Remember to do things back-to-front! */
+
+ /* This is a bit dirty. Depending on sky-mode, the pixel is */
+ /* blended in differently. */
+ renderSkyPixelFloat(x, y);
+ cpFloatColV(collector, colbuf);
+
+ /* Spothalos are part of the normal pixelshader, so for covered */
+ /* pixels they are handled ok. They are 'normally' alpha blended */
+ /* onto the existing colour in the collector. */
+ if(R.flag & R_LAMPHALO) {
+ renderSpotHaloPixel(x, y, collector);
+ }
+ addAlphaOverFloat(colbuf, collector);
+ }
+ } /* End of pixel loop */
+
+} /* End of void renderZBufLine(int y) */
+
+
+/* ------------------------------------------------------------------------- */
+
+int fillZBufDistances()
+{
+ int keepLooping = 1;
+
+ keepLooping = zBufferAllFaces(); /* Solid and transparent faces*/
+ keepLooping = zBufferAllHalos() && keepLooping; /* ...and halos*/
+ return keepLooping;
+
+} /* End of void fillZBufDistances() */
+
+/* ------------------------------------------------------------------------- */
+/* Transparent faces and the 'Azvoordeel' */
+/* A transparent face can get a z-offset, which is a */
+/* way of pretending the face is a bit closer than it */
+/* actually is. This is used in animations, when faces */
+/* that are used to glue on animated characters, items, */
+/* et. need their shadows to be drawn on top of the */
+/* objects they stand on. The Azvoordeel is added to */
+/* the calculated z-coordinate in the buffer-fill */
+/* procedures. */
+
+/* static int RE_treat_face_as_opaque; */
+
+int zBufferAllFaces(void)
+{
+ int keepLooping = 1;
+ int faceCounter; /* counter for face number */
+ float vec[3], hoco[4], mul, zval, fval;
+ Material *ma=0;
+
+ faceCounter = 0;
+
+/* printf("Going to buffer faces:\n"); */
+/* printf("\tfirst pass:\n"); */
+
+/* RE_treat_face_as_opaque = 1; */
+
+ while ( (faceCounter < R.totvlak) && keepLooping) {
+ if((faceCounter & 255)==0) { Zvlr= R.blovl[faceCounter>>8]; }
+ else Zvlr++;
+
+ ma= Zvlr->mat;
+
+ /* VERY dangerous construction... zoffs is set by a slide in the ui */
+ /* so it should be safe... */
+ if((ma->mode & (MA_ZTRA)) && (ma->zoffs != 0.0)) {
+ mul= 0x7FFFFFFF;
+ zval= mul*(1.0+Zvlr->v1->ho[2]/Zvlr->v1->ho[3]);
+
+ VECCOPY(vec, Zvlr->v1->co);
+ /* z is negatief, wordt anders geclipt */
+ vec[2]-= ma->zoffs;
+ RE_projectverto(vec, hoco); /* vec onto hoco */
+ fval= mul*(1.0+hoco[2]/hoco[3]);
+
+ Azvoordeel= (int) fabs(zval - fval );
+ } else {
+ Azvoordeel= 0;
+ }
+ /* face number is used in the fill functions */
+ Zvlnr = faceCounter + 1;
+
+ if(Zvlr->flag & R_VISIBLE) { /* might test for this sooner... */
+
+ if(ma->mode & (MA_WIRE)) zbufclipwire(Zvlr);
+ else {
+ zbufclip(Zvlr->v1->ho, Zvlr->v2->ho, Zvlr->v3->ho,
+ Zvlr->v1->clip, Zvlr->v2->clip, Zvlr->v3->clip);
+ if(Zvlr->v4) {
+ Zvlnr+= 0x800000; /* in a sense, the 'adjoint' face */
+ zbufclip(Zvlr->v1->ho, Zvlr->v3->ho, Zvlr->v4->ho,
+ Zvlr->v1->clip, Zvlr->v3->clip, Zvlr->v4->clip);
+ }
+ }
+ }
+ if(RE_local_test_break()) keepLooping = 0;
+ faceCounter++;
+ }
+
+ return keepLooping;
+} /* End of int zBufferAllFaces(void) */
+
+/* ------------------------------------------------------------------------- */
+/* We cheat a little here: we only fill the halo on the first pass, and we */
+/* set a full complement of mask flags. This can be done because we consider */
+/* halos to be flat (billboards), so we do not have to correct the z range */
+/* every time we insert a halo. Also, halos fall off to zero at the edges, */
+/* so we can safely render them in pixels where they do not exist. */
+int zBufferAllHalos(void)
+{
+ HaloRen *har = NULL;
+ unsigned int haloCounter = 0;
+ int dist = 0;
+ int keepLooping = 1;
+ short miny = 0, maxy = 0, minx = 0, maxx = 0;
+ short ycount = 0, xcount = 0;
+ RE_APixstrExt *ap, *apoffset;
+ int mask; /* jitter mask */
+
+ if (!Zsample)
+ {
+ mask = (1 << osaNr) - 1 ; /* Fill all samples together */
+
+ while ( (haloCounter < R.tothalo) && keepLooping) {
+ if((haloCounter & 255)==0) har= R.bloha[haloCounter>>8];
+ else har++;
+
+ /* Halos are sometimes wrongly kicked out of the box they belong */
+ /* in... */
+
+ /* Only buffer the current alpha buffer contents!!! The line */
+ /* indices have already been clipped to picture size. */
+ minx = floor(har->xs - har->rad) - 1; /* assume min =< max is true*/
+ if (minx < 0 ) minx = 0;
+ maxx = ceil(har->xs + har->rad ) + 1;
+ /* Do the extra -1 because of the +1 later on. I guess halos might */
+ /* have to start one pixel sooner? Or maybe the lower clip should */
+ /* be adjusted */
+ if (maxx >= zBufferWidth - 1) maxx = zBufferWidth - 2;
+
+ miny = har->miny;
+ if (miny < Aminy) miny = Aminy;
+ maxy = har->maxy;
+ if (maxy > Amaxy) maxy = Amaxy;
+
+ if ( (minx <= maxx) && (miny <= maxy)) {
+ /* distance to this halo? */
+ dist = har->zBufDist /* * R.ycor */;
+ /* strange that the ycor influences the z coordinate ..*/
+ ycount = miny;
+ while (ycount <= maxy) {
+ apoffset = APixbufExt + (zBufferWidth * (ycount - Aminy));
+ ap = apoffset + minx;
+ xcount = minx;
+ while (xcount <= maxx) {
+ insertFlatObjectNoOsa(ap, haloCounter, RE_HALO, dist, mask);
+ xcount++;
+ ap++;
+ }
+ ycount++;
+ }
+ }
+ if(RE_local_test_break()) keepLooping = 0;
+ haloCounter++;
+ }
+ }
+
+ return keepLooping;
+} /* end of int zbufferAllHalos(void) */
+
+/* ------------------------------------------------------------------------- */
+void zBufferFillHalo(void)
+{
+ /* so far, intentionally empty */
+} /* end of void zBufferFillHalo(void) */
+
+/* ------------------------------------------------------------------------- */
+void zBufferFillFace(float *v1, float *v2, float *v3)
+{
+ /* Coordinates of the vertices are specified in ZCS */
+ int apteller, apoffsetteller;
+ double z0; /* used as temp var*/
+ double xx1;
+ double zxd,zyd,zy0, tmp;
+ float *minv,*maxv,*midv;
+ register int zverg,zvlak,x;
+ int my0,my2,sn1,sn2,rectx,zd;
+ int y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2, mask;
+
+ /* These used to be doubles. We may want to change them back if the */
+ /* loss of accuracy proves to be a problem? There does not seem to be */
+ /* any performance issues here, so I'll just keep the doubles. */
+ /* float vec0[3], vec1[3], vec2[3]; */
+ double vec0[3], vec1[3], vec2[3];
+
+ /* MIN MAX */
+ /* sort vertices for min mid max y value */
+ if(v1[1]<v2[1]) {
+ if(v2[1]<v3[1]) { minv=v1; midv=v2; maxv=v3;}
+ else if(v1[1]<v3[1]) { minv=v1; midv=v3; maxv=v2;}
+ else { minv=v3; midv=v1; maxv=v2;}
+ }
+ else {
+ if(v1[1]<v3[1]) { minv=v2; midv=v1; maxv=v3;}
+ else if(v2[1]<v3[1]) { minv=v2; midv=v3; maxv=v1;}
+ else { minv=v3; midv=v2; maxv=v1;}
+ }
+
+ if(minv[1] == maxv[1]) return; /* beveiliging 'nul' grote vlakken */
+
+ my0 = ceil(minv[1]);
+ my2 = floor(maxv[1]);
+ omsl = floor(midv[1]);
+
+ /* outside the current z buffer slice: clip whole face */
+ if( (my2 < Aminy) || (my0 > Amaxy)) return;
+
+ if(my0<Aminy) my0= Aminy;
+
+ /* EDGES : DE LANGSTE */
+ xx1= maxv[1]-minv[1];
+ if(xx1>2.0/65536.0) {
+ z0= (maxv[0]-minv[0])/xx1;
+
+ tmp= (-65536.0*z0);
+ dx0= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(my2-minv[1])+minv[0]);
+ xs0= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx0= 0;
+ xs0= 65536.0*(MIN2(minv[0],maxv[0]));
+ }
+ /* EDGES : DE BOVENSTE */
+ xx1= maxv[1]-midv[1];
+ if(xx1>2.0/65536.0) {
+ z0= (maxv[0]-midv[0])/xx1;
+
+ tmp= (-65536.0*z0);
+ dx1= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(my2-midv[1])+midv[0]);
+ xs1= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx1= 0;
+ xs1= 65536.0*(MIN2(midv[0],maxv[0]));
+ }
+ /* EDGES : DE ONDERSTE */
+ xx1= midv[1]-minv[1];
+ if(xx1>2.0/65536.0) {
+ z0= (midv[0]-minv[0])/xx1;
+
+ tmp= (-65536.0*z0);
+ dx2= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(omsl-minv[1])+minv[0]);
+ xs2= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx2= 0;
+ xs2= 65536.0*(MIN2(minv[0],midv[0]));
+ }
+
+ /* ZBUF DX DY */
+ /* xyz_1 = v_1 - v_2 */
+ MTC_diff3DFF(vec1, v1, v2);
+ /* xyz_2 = v_2 - v_3 */
+ MTC_diff3DFF(vec2, v2, v3);
+ /* xyz_0 = xyz_1 cross xyz_2 */
+ MTC_cross3Double(vec0, vec1, vec2);
+
+ /* cross product of two of the sides is 0 => this face is too small */
+ if(vec0[2]==0.0) return;
+
+ if(midv[1] == maxv[1]) omsl= my2;
+ if(omsl < Aminy) omsl= Aminy-1; /* dan neemt ie de eerste lus helemaal */
+
+ while (my2 > Amaxy) { /* my2 kan groter zijn */
+ xs0+=dx0;
+ if (my2<=omsl) {
+ xs2+= dx2;
+ }
+ else{
+ xs1+= dx1;
+ }
+ my2--;
+ }
+
+ xx1= (vec0[0]*v1[0]+vec0[1]*v1[1])/vec0[2]+v1[2];
+
+ zxd= -vec0[0]/vec0[2];
+ zyd= -vec0[1]/vec0[2];
+ zy0= my2*zyd+xx1;
+ zd= (int)CLAMPIS(zxd, INT_MIN, INT_MAX);
+
+ /* start-ofset in rect */
+ /* rectx= R.rectx; */
+ /* I suspect this var needs very careful setting... When edge rendering */
+ /* is on, this is strange */
+ rectx = zBufferWidth;
+ apoffsetteller = rectx*(my2-Aminy);
+
+ mask= 1<<Zsample;
+ zvlak= Zvlnr;
+
+ xs3= 0; /* flag */
+ if(dx0>dx1) {
+ MTC_swapInt(&xs0, &xs1);
+ MTC_swapInt(&dx0, &dx1);
+ xs3= 1; /* flag */
+
+ }
+
+ for(y=my2;y>omsl;y--) {
+
+ sn1= xs0>>16;
+ xs0+= dx0;
+
+ sn2= xs1>>16;
+ xs1+= dx1;
+
+ sn1++;
+
+ if(sn2>=rectx) sn2= rectx-1;
+ if(sn1<0) sn1= 0;
+ zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
+ apteller = apoffsetteller + sn1;
+ x= sn2-sn1;
+
+ zverg-= Azvoordeel;
+
+ while(x>=0) {
+ insertObject(apteller, /* RE_treat_face_as_opaque, */ Zvlnr, RE_POLY, zverg, mask);
+ zverg+= zd;
+ apteller++;
+ x--;
+ }
+ zy0-= zyd;
+ apoffsetteller -= rectx;
+ }
+
+ if(xs3) {
+ xs0= xs1;
+ dx0= dx1;
+ }
+ if(xs0>xs2) {
+ xs3= xs0;
+ xs0= xs2;
+ xs2= xs3;
+ xs3= dx0;
+ dx0= dx2;
+ dx2= xs3;
+ }
+
+ for(; y>=my0; y--) {
+
+ sn1= xs0>>16;
+ xs0+= dx0;
+
+ sn2= xs2>>16;
+ xs2+= dx2;
+
+ sn1++;
+
+ if(sn2>=rectx) sn2= rectx-1;
+ if(sn1<0) sn1= 0;
+ zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
+ apteller = apoffsetteller + sn1;
+ x= sn2-sn1;
+
+ zverg-= Azvoordeel;
+
+ while(x>=0) {
+ insertObject(apteller, /* RE_treat_face_as_opaque, */ Zvlnr, RE_POLY, zverg, mask);
+ zverg+= zd;
+ apteller++;
+ x--;
+ }
+
+ zy0-=zyd;
+ apoffsetteller -= rectx;
+ }
+} /* end of void zBufferFillFace(float *v1, float *v2, float *v3) */
+
+/* ------------------------------------------------------------------------- */
+
+void zBufferFillEdge(float *vec1, float *vec2)
+{
+ int apteller;
+ int start, end, x, y, oldx, oldy, ofs;
+ int dz, vergz, mask;
+ float dx, dy;
+ float v1[3], v2[3];
+
+ dx= vec2[0]-vec1[0];
+ dy= vec2[1]-vec1[1];
+
+ if(fabs(dx) > fabs(dy)) {
+
+ /* alle lijnen van links naar rechts */
+ if(vec1[0]<vec2[0]) {
+ VECCOPY(v1, vec1);
+ VECCOPY(v2, vec2);
+ }
+ else {
+ VECCOPY(v2, vec1);
+ VECCOPY(v1, vec2);
+ dx= -dx; dy= -dy;
+ }
+
+ start= floor(v1[0]);
+ end= start+floor(dx);
+ if(end >= zBufferWidth) end = zBufferWidth - 1;
+
+ oldy= floor(v1[1]);
+ dy/= dx;
+
+ vergz= v1[2];
+ vergz-= Azvoordeel;
+ dz= (v2[2]-v1[2])/dx;
+
+ apteller = zBufferWidth*(oldy-Aminy) +start;
+ mask = 1<<Zsample;
+
+ if(dy<0) ofs= -zBufferWidth;
+ else ofs= zBufferWidth;
+
+ for(x= start; x<=end; x++, /* ap++, */ apteller++) {
+
+ y= floor(v1[1]);
+ if(y!=oldy) {
+ oldy= y;
+ apteller += ofs;
+ }
+
+ if(x>=0 && y>=Aminy && y<=Amaxy) {
+ insertObject(apteller, /* RE_treat_face_as_opaque, */ Zvlnr, RE_POLY, vergz, mask);
+ }
+
+ v1[1]+= dy;
+ vergz+= dz;
+ }
+ }
+ else {
+
+ /* alle lijnen van onder naar boven */
+ if(vec1[1]<vec2[1]) {
+ VECCOPY(v1, vec1);
+ VECCOPY(v2, vec2);
+ }
+ else {
+ VECCOPY(v2, vec1);
+ VECCOPY(v1, vec2);
+ dx= -dx; dy= -dy;
+ }
+
+ start= floor(v1[1]);
+ end= start+floor(dy);
+
+ if(start>Amaxy || end<Aminy) return;
+
+ if(end>Amaxy) end= Amaxy;
+
+ oldx= floor(v1[0]);
+ dx/= dy;
+
+ vergz= v1[2];
+ vergz-= Azvoordeel;
+ dz= (v2[2]-v1[2])/dy;
+
+ apteller = zBufferWidth*(start-Aminy) +oldx;
+
+ mask= 1<<Zsample;
+
+ if(dx<0) ofs= -1;
+ else ofs= 1;
+
+ for(y= start; y<=end; y++, apteller += zBufferWidth) {
+
+ x= floor(v1[0]);
+ if(x!=oldx) {
+ oldx= x;
+ apteller += ofs;
+ }
+
+ if(x>=0 && y>=Aminy && (x < zBufferWidth)) {
+ insertObject(apteller, /* RE_treat_face_as_opaque, */ Zvlnr, RE_POLY, vergz, mask);
+ }
+
+ v1[0]+= dx;
+ vergz+= dz;
+ }
+ }
+} /* End of void zBufferFillEdge(float *vec1, float *vec2) */
+
+
+/* ------------------------------------------------------------------------- */
+/* Colour buffer related: */
+/* This transforms the 4 inputvalues RE_COLBUFTYPE to a new value */
+/* It expects the values R.r.postigamma, R.r.postmul and R.r.postadd. */
+/* This is the standard transformation, more elaborate tools are for later. */
+/* ------------------------------------------------------------------------- */
+void std_transFloatColV2CharColV( RE_COLBUFTYPE *buf, char *target)
+{
+ float fval;
+
+ /* alpha */
+ if(buf[3]<=0.0) target[3]= 0;
+ else if(buf[3]>1.0) target[3]= 255;
+ else target[3]= 255.0*buf[3];
+
+ if(R.r.postgamma==1.0) {
+ /* r */
+ fval= R.r.postmul*buf[0] + R.r.postadd;
+ if(fval<=0.0) target[0]= 0;
+ else if(fval>1.0) target[0]= 255;
+ else target[0]= 255.0*fval;
+
+ /* g */
+ fval= R.r.postmul*buf[1] + R.r.postadd;
+ if(fval<=0.0) target[1]= 0;
+ else if(fval>1.0) target[1]= 255;
+ else target[1]= 255.0*fval;
+
+ /* b */
+ fval= R.r.postmul*buf[2] + R.r.postadd;
+ if(fval<=0.0) target[2]= 0;
+ else if(fval>1.0) target[2]= 255;
+ else target[2]= 255.0*fval;
+
+ }
+ else {
+ /* putting the postmul within the pow() gives an
+ * easier control for the user, values from 1.0-2.0
+ * are relevant then
+ */
+
+
+ /* r */
+ fval= pow(R.r.postmul*buf[0], R.r.postigamma) + R.r.postadd;
+ if(fval<=0.0) target[0]= 0;
+ else if(fval>1.0) target[0]= 255;
+ else target[0]= 255.0*fval;
+
+ /* g */
+ fval=pow( R.r.postmul*buf[1], R.r.postigamma) + R.r.postadd;
+ if(fval<=0.0) target[1]= 0;
+ else if(fval>1.0) target[1]= 255;
+ else target[1]= 255.0*fval;
+
+ /* b */
+ fval= pow(R.r.postmul*buf[2], R.r.postigamma) + R.r.postadd;
+ if(fval<=0.0) target[2]= 0;
+ else if(fval>1.0) target[2]= 255;
+ else target[2]= 255.0*fval;
+ }
+
+} /* end of void std_transFloatColV2CharColV( RE_COLBUFTYPE *buf, uchar *target) */
+
+
+/* ----------------------------------------------------------------------------
+
+ Colour buffer related:
+
+ The colour buffer is a buffer of a single screen line. It contains
+ four fields of type RE_COLBUFTYPE per pixel.
+
+ We can do several post-process steps. I would prefer to move them outside
+ the render module later on, but it's ok to leave it here for now. For the
+ time being, we have:
+ - post-process function
+ Does some operations with the colours.
+ - Multiply with some factor
+ - Add constant offset
+ - Apply extra gamma correction (seems weird...)
+ - key-alpha correction
+ Key alpha means 'un-applying' the alpha. For fully covered pixels, this
+ operation has no effect.
+
+---------------------------------------------------------------------------- */
+void transferColourBufferToOutput(int y)
+{
+ /* Copy the contents of AColourBuffer to R.rectot + y * R.rectx */
+ int x = 0;
+ RE_COLBUFTYPE *buf = AColourBuffer;
+ char *target = (char*) (R.rectot + (y * imageWidth));
+
+#ifdef RE_FULL_SAFETY
+ /* since the R.rectot always has size imageWidth * imageHeight, this */
+ /* check is possible. I may want to check this per assignment later on. */
+ if ( (y < 0) || ((y > (imageHeight - 1) ))) {
+ char fname[] = "transferColourBufferToOutput";
+ RE_error_int(RE_WRITE_OUTSIDE_COLOUR_BUFFER, fname, y);
+ return;
+ }
+#endif
+
+ /* Copy the first <imageWidth> pixels. We can do some more clipping on */
+ /* the z buffer, I think. */
+ while (x < imageWidth) {
+
+ std_transFloatColV2CharColV(buf, target);
+
+ /* old function was: leave it for test */
+/* cpFloatColV2CharColV(buf, target); */
+
+ /*
+ Key-alpha mode:
+ Need to un-apply alpha if alpha is non-full. For full alpha,
+ the operation doesn't have effect. Do this after the post-
+ processing, so we can still use the benefits of that.
+
+ */
+
+ if (getSkyBlendingMode() == RE_ALPHA_KEY) {
+ applyKeyAlphaCharCol(target);
+ }
+
+ target+=4;
+ buf+=4;
+ x++;
+ }
+} /* end of void transferColourBufferToOutput(int y) */
+
+/* ------------------------------------------------------------------------- */
+
+void eraseColBuf(RE_COLBUFTYPE *buf) {
+ /* By definition, the buffer's length is 4 * R.rectx items */
+ int i = 0;
+/* while (i < 4 * R.rectx) { */
+ while (i < 4 * bufferWidth) {
+ *buf = RE_ZERO_COLOUR_FLOAT;
+ buf++; i++;
+ }
+} /* End of void eraseColBuf(RE_COLBUFTYPE *buf) */
+
+/* ------------------------------------------------------------------------- */
+
+int calcDepth(float x, float y, void* data, int type)
+{
+#ifdef RE_FULL_SAFETY
+ char fname[] = "calcDepth";
+ if (data == NULL) {
+ RE_error(RE_BAD_DATA_POINTER, fname);
+ return 0;
+ }
+#endif
+
+ if (type & RE_POLY) {
+ VlakRen* vlr = (VlakRen*) data;
+ VertRen* v1;
+ float dvlak, deler, fac, hoco_z, hoco_w;
+ int zbuf_co;
+
+ v1 = vlr->v1;
+
+ /* vertex dot face normal: WCS */
+ dvlak= v1->co[0]*vlr->n[0]+v1->co[1]*vlr->n[1]+v1->co[2]*vlr->n[2];
+
+ /* jitter has been added to x, y ! */
+ /* view vector R.view: screen coords */
+ if( (G.special1 & G_HOLO) &&
+ ((Camera *)G.scene->camera->data)->flag & CAM_HOLO2) {
+ R.view[0]= (x+(R.xstart) + 0.5 +holoofs);
+ } else R.view[0]= (x+(R.xstart) + 0.5 );
+
+ if(R.flag & R_SEC_FIELD) {
+ if(R.r.mode & R_ODDFIELD) R.view[1]= (y + R.ystart)*R.ycor;
+ else R.view[1]= (y+R.ystart + 1.0)*R.ycor;
+ } else R.view[1]= (y+R.ystart + 0.5 )*R.ycor;
+
+
+ /* for pano, another rotation in the xz plane is needed.... */
+
+ /* this is ok, in WCS */
+ R.view[2]= -R.viewfac; /* distance to viewplane */
+
+ /* face normal dot view vector: but how can this work? */
+ deler = MTC_dot3Float(vlr->n, R.view);
+ if (deler!=0.0) fac = dvlak/deler;
+ else fac = 0.0;
+
+ /* indices are wrong.... but gives almost the right value? */
+ hoco_z = (fac*R.view[2]) * R.winmat[2][2] + R.winmat[3][2];
+ hoco_w = (fac*R.view[2]) * R.winmat[2][3] + R.winmat[3][3];
+
+ zbuf_co = 0x7FFFFFFF*(hoco_z/hoco_w);
+
+ return zbuf_co; /* z component of R.co */
+ } else if (type & RE_HALO) {
+ HaloRen* har = (HaloRen*) data;
+ return har->zBufDist;
+ }
+#ifdef RE_FULL_SAFETY
+ else RE_error(RE_BAD_FACE_TYPE, fname);
+#endif /* RE_FULL_SAFETY */
+ return 0;
+} /* end of int calcDepth(float x, float y, void* data, int type) */
+
+/* Maybe these two should be in pixelblendeing.c---------------------------- */
+
+void blendOverFloat(int type, float* dest, float* source, void* data)
+{
+#ifdef RE_FULL_SAFETY
+ char fname[] = "blendOverFloat";
+ if (data == NULL){
+ RE_error(RE_BAD_DATA_POINTER, fname);
+ return;
+ }
+#endif
+
+ if (type & RE_POLY) {
+ VlakRen *ver = (VlakRen*) data;
+ if ((ver->mat != NULL) && (ver->mat->add > RE_FACE_ADD_THRESHOLD)) {
+ char addf = (char) (ver->mat->add * 255.0);
+ addalphaAddfacFloat(dest, source, addf);
+ }
+ else
+ addAlphaOverFloat(dest, source);
+ } else if (type & RE_HALO) {
+ HaloRen *har= (HaloRen*) data;
+ addalphaAddfacFloat(dest, source, har->add);
+ } else if (type & RE_SKY) {
+ addAlphaOverFloat(dest, source);
+ }
+#ifdef RE_FULL_SAFETY
+ else RE_error(RE_BAD_FACE_TYPE, fname);
+#endif
+
+} /* end of void blendOverFloat(int , float*, float*, void*) */
+
+/* ------------------------------------------------------------------------- */
+void blendOverFloatRow(int type, float* dest, float* source,
+ void* data, int mask, int osaNr)
+{
+#ifdef RE_FULL_SAFETY
+ char* fname = "blendOverFloatRow";
+ if ((data == NULL) && ((type & RE_POLY) || (type & RE_HALO))) {
+ RE_error(RE_BAD_DATA_POINTER, fname);
+ return;
+ }
+#endif
+
+ if (type & RE_POLY) {
+ VlakRen *ver = (VlakRen*) data;
+ if ((ver->mat != NULL)
+ && (ver->mat->add > RE_FACE_ADD_THRESHOLD)) {
+ char addf = (ver->mat->add * 255.0);
+ addAddSampColF(dest, source, mask, osaNr, addf);
+ } else {
+ addOverSampColF(dest, source, mask, osaNr);
+ }
+ } else if (type & RE_HALO) {
+ HaloRen *har = (HaloRen*) data;
+ addAddSampColF(dest, source, mask, osaNr, har->add);
+ } else if (type & RE_SKY) {
+ addOverSampColF(dest, source, mask, osaNr);
+ }
+#ifdef RE_FULL_SAFETY
+ else RE_error(RE_BAD_FACE_TYPE, fname);
+#endif
+} /* end of void blendOverFloatRow(int, float*, float*, void*) */
+
+/* ------------------------------------------------------------------------- */
+
+/* eof vanillaRenderPipe.c */
diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c
new file mode 100644
index 00000000000..295e13b8d5f
--- /dev/null
+++ b/source/blender/render/intern/source/zbuf.c
@@ -0,0 +1,2329 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*---------------------------------------------------------------------------*/
+/* Common includes */
+/*---------------------------------------------------------------------------*/
+
+#include <math.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include "MTC_matrixops.h"
+#include "MEM_guardedalloc.h"
+
+#include "BKE_global.h"
+
+#include "DNA_lamp_types.h"
+#include "DNA_mesh_types.h"
+
+#include "radio_types.h"
+#include "radio.h" /* needs RG, some root data for radiosity */
+
+#include "render.h"
+#include "render_intern.h"
+#include "RE_callbacks.h"
+#include "old_zbuffer_types.h"
+/* local includes */
+/* can be removed when the old renderer disappears */
+#include "rendercore.h" /* shade_pixel and count_mask */
+#include "pixelblending.h"
+#include "jitter.h"
+
+/* own includes */
+#include "zbuf.h"
+#include "zbuf_int.h"
+
+/* crud */
+#define MIN2(x,y) ( (x)<(y) ? (x) : (y) )
+/*-----------------------------------------------------------*/
+/* Globals for this file */
+/*-----------------------------------------------------------*/
+
+extern float centLut[16];
+extern char *centmask;
+
+float *vlzp[32][3], labda[3][2], vez[400], *p[40];
+
+float Zmulx; /* Half the screenwidth, in pixels. (used in render.c, */
+ /* zbuf.c) */
+float Zmuly; /* Half the screenheight, in pixels. (used in render.c,*/
+ /* zbuf.c) */
+float Zjitx; /* Jitter offset in x. When jitter is disabled, this */
+ /* should be 0.5. (used in render.c, zbuf.c) */
+float Zjity; /* Jitter offset in y. When jitter is disabled, this */
+ /* should be 0.5. (used in render.c, zbuf.c) */
+
+unsigned int Zvlnr, Zsample;
+VlakRen *Zvlr;
+void (*zbuffunc)(float *, float *, float *);
+void (*zbuflinefunc)(float *, float *);
+
+APixstr *APixbuf; /* Zbuffer: linked list of face indices */
+unsigned short *Acolrow; /* Zbuffer: colour buffer, one line high */
+int *Arectz; /* Zbuffer: distance buffer, almost obsolete */
+int Aminy; /* y value of first line in the accu buffer */
+int Amaxy; /* y value of last line in the accu buffer */
+int Azvoordeel = 0;
+APixstrMain apsmfirst;
+short apsmteller = 0;
+
+/*-----------------------------------------------------------*/
+/* Functions */
+/*-----------------------------------------------------------*/
+
+void fillrect(unsigned int *rect, int x, unsigned int y, unsigned int val)
+{
+ unsigned int len,*drect;
+
+ len= x*y;
+ drect= rect;
+ while(len>0) {
+ len--;
+ *drect= val;
+ drect++;
+ }
+}
+
+/* ************* ACCU ZBUF ************ */
+
+/*-APixstr---------------------------------------------------*/
+
+APixstr *addpsmainA()
+{
+ APixstrMain *psm;
+
+ psm= &apsmfirst;
+
+ while(psm->next) {
+ psm= psm->next;
+ }
+
+ psm->next= MEM_mallocN(sizeof(APixstrMain), "addpsmainA");
+
+ psm= psm->next;
+ psm->next=0;
+ psm->ps= MEM_callocN(4096*sizeof(APixstr),"pixstr");
+ apsmteller= 0;
+
+ return psm->ps;
+}
+
+void freepsA()
+{
+ APixstrMain *psm, *next;
+
+ psm= &apsmfirst;
+
+ while(psm) {
+ next= psm->next;
+ if(psm->ps) {
+ MEM_freeN(psm->ps);
+ psm->ps= 0;
+ }
+ if(psm!= &apsmfirst) MEM_freeN(psm);
+ psm= next;
+ }
+
+ apsmfirst.next= 0;
+ apsmfirst.ps= 0;
+ apsmteller= 0;
+}
+
+APixstr *addpsA(void)
+{
+ static APixstr *prev;
+
+ /* eerste PS maken */
+ if((apsmteller & 4095)==0) prev= addpsmainA();
+ else prev++;
+ apsmteller++;
+
+ return prev;
+}
+
+/* vult kleur in, met windowcoordinaat, van Aminy->Amaxy */
+void zbufinvulAc(float *v1, float *v2, float *v3)
+{
+ APixstr *ap, *apofs, *apn;
+ double x0,y0,z0,x1,y1,z1,x2,y2,z2,xx1;
+ double zxd,zyd,zy0, tmp;
+ float *minv,*maxv,*midv;
+ int *rz,zverg,x;
+ int my0,my2,sn1,sn2,rectx,zd,*rectzofs;
+ int y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2, mask;
+
+ /* MIN MAX */
+ if(v1[1]<v2[1]) {
+ if(v2[1]<v3[1]) {
+ minv=v1; midv=v2; maxv=v3;
+ }
+ else if(v1[1]<v3[1]) {
+ minv=v1; midv=v3; maxv=v2;
+ }
+ else {
+ minv=v3; midv=v1; maxv=v2;
+ }
+ }
+ else {
+ if(v1[1]<v3[1]) {
+ minv=v2; midv=v1; maxv=v3;
+ }
+ else if(v2[1]<v3[1]) {
+ minv=v2; midv=v3; maxv=v1;
+ }
+ else {
+ minv=v3; midv=v2; maxv=v1;
+ }
+ }
+
+ if(minv[1] == maxv[1]) return; /* beveiliging 'nul' grote vlakken */
+
+ my0= ceil(minv[1]);
+ my2= floor(maxv[1]);
+ omsl= floor(midv[1]);
+
+ if(my2<Aminy || my0> Amaxy) return;
+
+ if(my0<Aminy) my0= Aminy;
+
+ /* EDGES : DE LANGSTE */
+ xx1= maxv[1]-minv[1];
+ if(xx1>2.0/65536.0) {
+ z0= (maxv[0]-minv[0])/xx1;
+
+ tmp= (-65536.0*z0);
+ dx0= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(my2-minv[1])+minv[0]);
+ xs0= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx0= 0;
+ xs0= 65536.0*(MIN2(minv[0],maxv[0]));
+ }
+ /* EDGES : DE BOVENSTE */
+ xx1= maxv[1]-midv[1];
+ if(xx1>2.0/65536.0) {
+ z0= (maxv[0]-midv[0])/xx1;
+
+ tmp= (-65536.0*z0);
+ dx1= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(my2-midv[1])+midv[0]);
+ xs1= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx1= 0;
+ xs1= 65536.0*(MIN2(midv[0],maxv[0]));
+ }
+ /* EDGES : DE ONDERSTE */
+ xx1= midv[1]-minv[1];
+ if(xx1>2.0/65536.0) {
+ z0= (midv[0]-minv[0])/xx1;
+
+ tmp= (-65536.0*z0);
+ dx2= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(omsl-minv[1])+minv[0]);
+ xs2= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx2= 0;
+ xs2= 65536.0*(MIN2(minv[0],midv[0]));
+ }
+
+ /* ZBUF DX DY */
+ x1= v1[0]- v2[0];
+ x2= v2[0]- v3[0];
+ y1= v1[1]- v2[1];
+ y2= v2[1]- v3[1];
+ z1= v1[2]- v2[2];
+ z2= v2[2]- v3[2];
+ x0= y1*z2-z1*y2;
+ y0= z1*x2-x1*z2;
+ z0= x1*y2-y1*x2;
+ if(z0==0.0) return;
+
+ if(midv[1]==maxv[1]) omsl= my2;
+ if(omsl<Aminy) omsl= Aminy-1; /* dan neemt ie de eerste lus helemaal */
+
+ while (my2 > Amaxy) { /* my2 kan groter zijn */
+ xs0+=dx0;
+ if (my2<=omsl) {
+ xs2+= dx2;
+ }
+ else{
+ xs1+= dx1;
+ }
+ my2--;
+ }
+
+ xx1= (x0*v1[0]+y0*v1[1])/z0+v1[2];
+
+ zxd= -x0/z0;
+ zyd= -y0/z0;
+ zy0= my2*zyd+xx1;
+ zd= (int)CLAMPIS(zxd, INT_MIN, INT_MAX);
+
+ /* start-ofset in rect */
+ rectx= R.rectx;
+ rectzofs= (int *)(Arectz+rectx*(my2-Aminy));
+ apofs= (APixbuf+ rectx*(my2-Aminy));
+ mask= 1<<Zsample;
+
+ xs3= 0; /* flag */
+ if(dx0>dx1) {
+ xs3= xs0;
+ xs0= xs1;
+ xs1= xs3;
+ xs3= dx0;
+ dx0= dx1;
+ dx1= xs3;
+ xs3= 1; /* flag */
+
+ }
+
+ for(y=my2;y>omsl;y--) {
+
+ sn1= xs0>>16;
+ xs0+= dx0;
+
+ sn2= xs1>>16;
+ xs1+= dx1;
+
+ sn1++;
+
+ if(sn2>=rectx) sn2= rectx-1;
+ if(sn1<0) sn1= 0;
+ zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
+ rz= rectzofs+sn1;
+ ap= apofs+sn1;
+ x= sn2-sn1;
+
+ zverg-= Azvoordeel;
+
+ while(x>=0) {
+ if(zverg< *rz) {
+ apn= ap;
+ while(apn) { /* loopunrolled */
+ if(apn->p[0]==0) {apn->p[0]= Zvlnr; apn->z[0]= zverg; apn->mask[0]= mask; break; }
+ if(apn->p[0]==Zvlnr) {apn->mask[0]|= mask; break; }
+ if(apn->p[1]==0) {apn->p[1]= Zvlnr; apn->z[1]= zverg; apn->mask[1]= mask; break; }
+ if(apn->p[1]==Zvlnr) {apn->mask[1]|= mask; break; }
+ if(apn->p[2]==0) {apn->p[2]= Zvlnr; apn->z[2]= zverg; apn->mask[2]= mask; break; }
+ if(apn->p[2]==Zvlnr) {apn->mask[2]|= mask; break; }
+ if(apn->p[3]==0) {apn->p[3]= Zvlnr; apn->z[3]= zverg; apn->mask[3]= mask; break; }
+ if(apn->p[3]==Zvlnr) {apn->mask[3]|= mask; break; }
+ if(apn->next==0) apn->next= addpsA();
+ apn= apn->next;
+ }
+ }
+ zverg+= zd;
+ rz++;
+ ap++;
+ x--;
+ }
+ zy0-= zyd;
+ rectzofs-= rectx;
+ apofs-= rectx;
+ }
+
+ if(xs3) {
+ xs0= xs1;
+ dx0= dx1;
+ }
+ if(xs0>xs2) {
+ xs3= xs0;
+ xs0= xs2;
+ xs2= xs3;
+ xs3= dx0;
+ dx0= dx2;
+ dx2= xs3;
+ }
+
+ for(; y>=my0; y--) {
+
+ sn1= xs0>>16;
+ xs0+= dx0;
+
+ sn2= xs2>>16;
+ xs2+= dx2;
+
+ sn1++;
+
+ if(sn2>=rectx) sn2= rectx-1;
+ if(sn1<0) sn1= 0;
+ zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
+ rz= rectzofs+sn1;
+ ap= apofs+sn1;
+ x= sn2-sn1;
+
+ zverg-= Azvoordeel;
+
+ while(x>=0) {
+ if(zverg< *rz) {
+ apn= ap;
+ while(apn) { /* loopunrolled */
+ if(apn->p[0]==0) {apn->p[0]= Zvlnr; apn->z[0]= zverg; apn->mask[0]= mask; break; }
+ if(apn->p[0]==Zvlnr) {apn->mask[0]|= mask; break; }
+ if(apn->p[1]==0) {apn->p[1]= Zvlnr; apn->z[1]= zverg; apn->mask[1]= mask; break; }
+ if(apn->p[1]==Zvlnr) {apn->mask[1]|= mask; break; }
+ if(apn->p[2]==0) {apn->p[2]= Zvlnr; apn->z[2]= zverg; apn->mask[2]= mask; break; }
+ if(apn->p[2]==Zvlnr) {apn->mask[2]|= mask; break; }
+ if(apn->p[3]==0) {apn->p[3]= Zvlnr; apn->z[3]= zverg; apn->mask[3]= mask; break; }
+ if(apn->p[3]==Zvlnr) {apn->mask[3]|= mask; break; }
+ if(apn->next==0) apn->next= addpsA();
+ apn= apn->next;
+ }
+ }
+ zverg+= zd;
+ rz++;
+ ap++;
+ x--;
+ }
+
+ zy0-=zyd;
+ rectzofs-= rectx;
+ apofs-= rectx;
+ }
+}
+
+void zbuflineAc(float *vec1, float *vec2)
+{
+ APixstr *ap, *apn;
+ unsigned int *rectz;
+ int start, end, x, y, oldx, oldy, ofs;
+ int dz, vergz, mask;
+ float dx, dy;
+ float v1[3], v2[3];
+
+ dx= vec2[0]-vec1[0];
+ dy= vec2[1]-vec1[1];
+
+ if(fabs(dx) > fabs(dy)) {
+
+ /* alle lijnen van links naar rechts */
+ if(vec1[0]<vec2[0]) {
+ VECCOPY(v1, vec1);
+ VECCOPY(v2, vec2);
+ }
+ else {
+ VECCOPY(v2, vec1);
+ VECCOPY(v1, vec2);
+ dx= -dx; dy= -dy;
+ }
+
+ start= floor(v1[0]);
+ end= start+floor(dx);
+ if(end>=R.rectx) end= R.rectx-1;
+
+ oldy= floor(v1[1]);
+ dy/= dx;
+
+ vergz= v1[2];
+ vergz-= Azvoordeel;
+ dz= (v2[2]-v1[2])/dx;
+
+ rectz= (unsigned int *)(Arectz+R.rectx*(oldy-Aminy) +start);
+ ap= (APixbuf+ R.rectx*(oldy-Aminy) +start);
+ mask= 1<<Zsample;
+
+ if(dy<0) ofs= -R.rectx;
+ else ofs= R.rectx;
+
+ for(x= start; x<=end; x++, rectz++, ap++) {
+
+ y= floor(v1[1]);
+ if(y!=oldy) {
+ oldy= y;
+ rectz+= ofs;
+ ap+= ofs;
+ }
+
+ if(x>=0 && y>=Aminy && y<=Amaxy) {
+ if(vergz<*rectz) {
+
+ apn= ap;
+ while(apn) { /* loopunrolled */
+ if(apn->p[0]==0) {apn->p[0]= Zvlnr; apn->z[0]= vergz; apn->mask[0]= mask; break; }
+ if(apn->p[0]==Zvlnr) {apn->mask[0]|= mask; break; }
+ if(apn->p[1]==0) {apn->p[1]= Zvlnr; apn->z[1]= vergz; apn->mask[1]= mask; break; }
+ if(apn->p[1]==Zvlnr) {apn->mask[1]|= mask; break; }
+ if(apn->p[2]==0) {apn->p[2]= Zvlnr; apn->z[2]= vergz; apn->mask[2]= mask; break; }
+ if(apn->p[2]==Zvlnr) {apn->mask[2]|= mask; break; }
+ if(apn->p[3]==0) {apn->p[3]= Zvlnr; apn->z[3]= vergz; apn->mask[3]= mask; break; }
+ if(apn->p[3]==Zvlnr) {apn->mask[3]|= mask; break; }
+ if(apn->next==0) apn->next= addpsA();
+ apn= apn->next;
+ }
+
+ }
+ }
+
+ v1[1]+= dy;
+ vergz+= dz;
+ }
+ }
+ else {
+
+ /* alle lijnen van onder naar boven */
+ if(vec1[1]<vec2[1]) {
+ VECCOPY(v1, vec1);
+ VECCOPY(v2, vec2);
+ }
+ else {
+ VECCOPY(v2, vec1);
+ VECCOPY(v1, vec2);
+ dx= -dx; dy= -dy;
+ }
+
+ start= floor(v1[1]);
+ end= start+floor(dy);
+
+ if(start>Amaxy || end<Aminy) return;
+
+ if(end>Amaxy) end= Amaxy;
+
+ oldx= floor(v1[0]);
+ dx/= dy;
+
+ vergz= v1[2];
+ vergz-= Azvoordeel;
+ dz= (v2[2]-v1[2])/dy;
+
+ rectz= (unsigned int *)( Arectz+ (start-Aminy)*R.rectx+ oldx );
+ ap= (APixbuf+ R.rectx*(start-Aminy) +oldx);
+ mask= 1<<Zsample;
+
+ if(dx<0) ofs= -1;
+ else ofs= 1;
+
+ for(y= start; y<=end; y++, rectz+=R.rectx, ap+=R.rectx) {
+
+ x= floor(v1[0]);
+ if(x!=oldx) {
+ oldx= x;
+ rectz+= ofs;
+ ap+= ofs;
+ }
+
+ if(x>=0 && y>=Aminy && x<R.rectx) {
+ if(vergz<*rectz) {
+
+ apn= ap;
+ while(apn) { /* loopunrolled */
+ if(apn->p[0]==0) {apn->p[0]= Zvlnr; apn->z[0]= vergz; apn->mask[0]= mask; break; }
+ if(apn->p[0]==Zvlnr) {apn->mask[0]|= mask; break; }
+ if(apn->p[1]==0) {apn->p[1]= Zvlnr; apn->z[1]= vergz; apn->mask[1]= mask; break; }
+ if(apn->p[1]==Zvlnr) {apn->mask[1]|= mask; break; }
+ if(apn->p[2]==0) {apn->p[2]= Zvlnr; apn->z[2]= vergz; apn->mask[2]= mask; break; }
+ if(apn->p[2]==Zvlnr) {apn->mask[2]|= mask; break; }
+ if(apn->p[3]==0) {apn->p[3]= Zvlnr; apn->z[3]= vergz; apn->mask[3]= mask; break; }
+ if(apn->p[3]==Zvlnr) {apn->mask[3]|= mask; break; }
+ if(apn->next==0) apn->next= addpsA();
+ apn= apn->next;
+ }
+
+ }
+ }
+
+ v1[0]+= dx;
+ vergz+= dz;
+ }
+ }
+}
+
+
+
+/* ************* NORMAL ZBUFFER ************ */
+
+void hoco_to_zco(float *zco, float *hoco)
+{
+ float deler;
+
+ deler= hoco[3];
+ zco[0]= Zmulx*(1.0+hoco[0]/deler)+ Zjitx;
+ zco[1]= Zmuly*(1.0+hoco[1]/deler)+ Zjity;
+ zco[2]= 0x7FFFFFFF *(hoco[2]/deler);
+}
+
+void zbufline(vec1, vec2)
+float *vec1, *vec2;
+{
+ unsigned int *rectz, *rectp;
+ int start, end, x, y, oldx, oldy, ofs;
+ int dz, vergz;
+ float dx, dy;
+ float v1[3], v2[3];
+
+ dx= vec2[0]-vec1[0];
+ dy= vec2[1]-vec1[1];
+
+ if(fabs(dx) > fabs(dy)) {
+
+ /* alle lijnen van links naar rechts */
+ if(vec1[0]<vec2[0]) {
+ VECCOPY(v1, vec1);
+ VECCOPY(v2, vec2);
+ }
+ else {
+ VECCOPY(v2, vec1);
+ VECCOPY(v1, vec2);
+ dx= -dx; dy= -dy;
+ }
+
+ start= floor(v1[0]);
+ end= start+floor(dx);
+ if(end>=R.rectx) end= R.rectx-1;
+
+ oldy= floor(v1[1]);
+ dy/= dx;
+
+ vergz= v1[2];
+ dz= (v2[2]-v1[2])/dx;
+
+ rectz= R.rectz+ oldy*R.rectx+ start;
+ rectp= R.rectot+ oldy*R.rectx+ start;
+
+ if(dy<0) ofs= -R.rectx;
+ else ofs= R.rectx;
+
+ for(x= start; x<=end; x++, rectz++, rectp++) {
+
+ y= floor(v1[1]);
+ if(y!=oldy) {
+ oldy= y;
+ rectz+= ofs;
+ rectp+= ofs;
+ }
+
+ if(x>=0 && y>=0 && y<R.recty) {
+ if(vergz<*rectz) {
+ *rectz= vergz;
+ *rectp= Zvlnr;
+ }
+ }
+
+ v1[1]+= dy;
+ vergz+= dz;
+ }
+ }
+ else {
+ /* alle lijnen van onder naar boven */
+ if(vec1[1]<vec2[1]) {
+ VECCOPY(v1, vec1);
+ VECCOPY(v2, vec2);
+ }
+ else {
+ VECCOPY(v2, vec1);
+ VECCOPY(v1, vec2);
+ dx= -dx; dy= -dy;
+ }
+
+ start= floor(v1[1]);
+ end= start+floor(dy);
+
+ if(end>=R.recty) end= R.recty-1;
+
+ oldx= floor(v1[0]);
+ dx/= dy;
+
+ vergz= v1[2];
+ dz= (v2[2]-v1[2])/dy;
+
+ rectz= R.rectz+ start*R.rectx+ oldx;
+ rectp= R.rectot+ start*R.rectx+ oldx;
+
+ if(dx<0) ofs= -1;
+ else ofs= 1;
+
+ for(y= start; y<=end; y++, rectz+=R.rectx, rectp+=R.rectx) {
+
+ x= floor(v1[0]);
+ if(x!=oldx) {
+ oldx= x;
+ rectz+= ofs;
+ rectp+= ofs;
+ }
+
+ if(x>=0 && y>=0 && x<R.rectx) {
+ if(vergz<*rectz) {
+ *rectz= vergz;
+ *rectp= Zvlnr;
+ }
+ }
+
+ v1[0]+= dx;
+ vergz+= dz;
+ }
+ }
+}
+
+
+void zbufclipwire(VlakRen *vlr)
+{
+ float *f1, *f2, *f3, *f4= 0, deler;
+ int c1, c2, c3, c4, ec, and, or;
+
+ /* edgecode: 1= tekenen */
+ ec = vlr->ec;
+ if(ec==0) return;
+
+ c1= vlr->v1->clip;
+ c2= vlr->v2->clip;
+ c3= vlr->v3->clip;
+ f1= vlr->v1->ho;
+ f2= vlr->v2->ho;
+ f3= vlr->v3->ho;
+
+ if(vlr->v4) {
+ f4= vlr->v4->ho;
+ c4= vlr->v4->clip;
+
+ and= (c1 & c2 & c3 & c4);
+ or= (c1 | c2 | c3 | c4);
+ }
+ else {
+ and= (c1 & c2 & c3);
+ or= (c1 | c2 | c3);
+ }
+
+ if(or) { /* niet in midden */
+ if(and) { /* helemaal eruit */
+ return;
+ }
+ else { /* clippen */
+
+ if(ec & ME_V1V2) {
+ QUATCOPY(vez, f1);
+ QUATCOPY(vez+4, f2);
+ if( clipline(vez, vez+4)) {
+ hoco_to_zco(vez, vez);
+ hoco_to_zco(vez+4, vez+4);
+ zbuflinefunc(vez, vez+4);
+ }
+ }
+ if(ec & ME_V2V3) {
+ QUATCOPY(vez, f2);
+ QUATCOPY(vez+4, f3);
+ if( clipline(vez, vez+4)) {
+ hoco_to_zco(vez, vez);
+ hoco_to_zco(vez+4, vez+4);
+ zbuflinefunc(vez, vez+4);
+ }
+ }
+ if(vlr->v4) {
+ if(ec & ME_V3V4) {
+ QUATCOPY(vez, f3);
+ QUATCOPY(vez+4, f4);
+ if( clipline(vez, vez+4)) {
+ hoco_to_zco(vez, vez);
+ hoco_to_zco(vez+4, vez+4);
+ zbuflinefunc(vez, vez+4);
+ }
+ }
+ if(ec & ME_V4V1) {
+ QUATCOPY(vez, f4);
+ QUATCOPY(vez+4, f1);
+ if( clipline(vez, vez+4)) {
+ hoco_to_zco(vez, vez);
+ hoco_to_zco(vez+4, vez+4);
+ zbuflinefunc(vez, vez+4);
+ }
+ }
+ }
+ else {
+ if(ec & ME_V3V1) {
+ QUATCOPY(vez, f3);
+ QUATCOPY(vez+4, f1);
+ if( clipline(vez, vez+4)) {
+ hoco_to_zco(vez, vez);
+ hoco_to_zco(vez+4, vez+4);
+ zbuflinefunc(vez, vez+4);
+ }
+ }
+ }
+
+ return;
+ }
+ }
+
+ deler= f1[3];
+ vez[0]= Zmulx*(1.0+f1[0]/deler)+ Zjitx;
+ vez[1]= Zmuly*(1.0+f1[1]/deler)+ Zjity;
+ vez[2]= 0x7FFFFFFF *(f1[2]/deler);
+
+ deler= f2[3];
+ vez[4]= Zmulx*(1.0+f2[0]/deler)+ Zjitx;
+ vez[5]= Zmuly*(1.0+f2[1]/deler)+ Zjity;
+ vez[6]= 0x7FFFFFFF *(f2[2]/deler);
+
+ deler= f3[3];
+ vez[8]= Zmulx*(1.0+f3[0]/deler)+ Zjitx;
+ vez[9]= Zmuly*(1.0+f3[1]/deler)+ Zjity;
+ vez[10]= 0x7FFFFFFF *(f3[2]/deler);
+
+ if(vlr->v4) {
+ deler= f4[3];
+ vez[12]= Zmulx*(1.0+f4[0]/deler)+ Zjitx;
+ vez[13]= Zmuly*(1.0+f4[1]/deler)+ Zjity;
+ vez[14]= 0x7FFFFFFF *(f4[2]/deler);
+
+ if(ec & ME_V3V4) zbuflinefunc(vez+8, vez+12);
+ if(ec & ME_V4V1) zbuflinefunc(vez+12, vez);
+ }
+ else {
+ if(ec & ME_V3V1) zbuflinefunc(vez+8, vez);
+ }
+
+ if(ec & ME_V1V2) zbuflinefunc(vez, vez+4);
+ if(ec & ME_V2V3) zbuflinefunc(vez+4, vez+8);
+
+
+
+}
+
+void zbufinvulGLinv(v1,v2,v3)
+float *v1,*v2,*v3;
+/* vult in R.rectot de waarde Zvlnr in met R.rectz */
+/* KEERT Z-VERGELIJKING OM: ALLES ACHTER IS ZICHTBAAR */
+{
+ double x0,y0,z0,x1,y1,z1,x2,y2,z2,xx1;
+ double zxd,zyd,zy0,tmp;
+ float *minv,*maxv,*midv;
+ unsigned int *rectpofs,*rp;
+ int *rz,zverg,zvlak,x;
+ int my0,my2,sn1,sn2,rectx,zd,*rectzofs;
+ int y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2;
+
+ /* MIN MAX */
+ if(v1[1]<v2[1]) {
+ if(v2[1]<v3[1]) {
+ minv=v1; midv=v2; maxv=v3;
+ }
+ else if(v1[1]<v3[1]) {
+ minv=v1; midv=v3; maxv=v2;
+ }
+ else {
+ minv=v3; midv=v1; maxv=v2;
+ }
+ }
+ else {
+ if(v1[1]<v3[1]) {
+ minv=v2; midv=v1; maxv=v3;
+ }
+ else if(v2[1]<v3[1]) {
+ minv=v2; midv=v3; maxv=v1;
+ }
+ else {
+ minv=v3; midv=v2; maxv=v1;
+ }
+ }
+
+ my0= ceil(minv[1]);
+ my2= floor(maxv[1]);
+ omsl= floor(midv[1]);
+
+ if(my2<0 || my0> R.recty) return;
+
+ if(my0<0) my0=0;
+
+ /* EDGES : DE LANGSTE */
+ xx1= maxv[1]-minv[1];
+ if(xx1>2.0/65536.0) {
+ z0= (maxv[0]-minv[0])/xx1;
+
+ tmp= (-65536.0*z0);
+ dx0= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(my2-minv[1])+minv[0]);
+ xs0= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx0= 0;
+ xs0= 65536.0*(MIN2(minv[0],maxv[0]));
+ }
+ /* EDGES : DE BOVENSTE */
+ xx1= maxv[1]-midv[1];
+ if(xx1>2.0/65536.0) {
+ z0= (maxv[0]-midv[0])/xx1;
+
+ tmp= (-65536.0*z0);
+ dx1= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(my2-midv[1])+midv[0]);
+ xs1= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx1= 0;
+ xs1= 65536.0*(MIN2(midv[0],maxv[0]));
+ }
+ /* EDGES : DE ONDERSTE */
+ xx1= midv[1]-minv[1];
+ if(xx1>2.0/65536.0) {
+ z0= (midv[0]-minv[0])/xx1;
+
+ tmp= (-65536.0*z0);
+ dx2= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(omsl-minv[1])+minv[0]);
+ xs2= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx2= 0;
+ xs2= 65536.0*(MIN2(minv[0],midv[0]));
+ }
+
+ /* ZBUF DX DY */
+ x1= v1[0]- v2[0];
+ x2= v2[0]- v3[0];
+ y1= v1[1]- v2[1];
+ y2= v2[1]- v3[1];
+ z1= v1[2]- v2[2];
+ z2= v2[2]- v3[2];
+ x0= y1*z2-z1*y2;
+ y0= z1*x2-x1*z2;
+ z0= x1*y2-y1*x2;
+
+ if(z0==0.0) return;
+
+ if(midv[1]==maxv[1]) omsl= my2;
+ if(omsl<0) omsl= -1; /* dan neemt ie de eerste lus helemaal */
+
+ while (my2 >= R.recty) { /* my2 kan groter zijn */
+ xs0+=dx0;
+ if (my2<=omsl) {
+ xs2+= dx2;
+ }
+ else{
+ xs1+= dx1;
+ }
+ my2--;
+ }
+
+ xx1= (x0*v1[0]+y0*v1[1])/z0+v1[2];
+
+ zxd= -x0/z0;
+ zyd= -y0/z0;
+ zy0= my2*zyd+xx1;
+ zd= (int)CLAMPIS(zxd, INT_MIN, INT_MAX);
+
+ /* start-ofset in rect */
+ rectx= R.rectx;
+ rectzofs= (int *)(R.rectz+rectx*my2);
+ rectpofs= (R.rectot+rectx*my2);
+ zvlak= Zvlnr;
+
+ xs3= 0; /* flag */
+ if(dx0>dx1) {
+ xs3= xs0;
+ xs0= xs1;
+ xs1= xs3;
+ xs3= dx0;
+ dx0= dx1;
+ dx1= xs3;
+ xs3= 1; /* flag */
+
+ }
+
+ for(y=my2;y>omsl;y--) {
+
+ sn1= xs0>>16;
+ xs0+= dx0;
+
+ sn2= xs1>>16;
+ xs1+= dx1;
+
+ sn1++;
+
+ if(sn2>=rectx) sn2= rectx-1;
+ if(sn1<0) sn1= 0;
+ zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
+ rz= rectzofs+sn1;
+ rp= rectpofs+sn1;
+ x= sn2-sn1;
+ while(x>=0) {
+ if(zverg> *rz || *rz==0x7FFFFFFF) {
+ *rz= zverg;
+ *rp= zvlak;
+ }
+ zverg+= zd;
+ rz++;
+ rp++;
+ x--;
+ }
+ zy0-=zyd;
+ rectzofs-= rectx;
+ rectpofs-= rectx;
+ }
+
+ if(xs3) {
+ xs0= xs1;
+ dx0= dx1;
+ }
+ if(xs0>xs2) {
+ xs3= xs0;
+ xs0= xs2;
+ xs2= xs3;
+ xs3= dx0;
+ dx0= dx2;
+ dx2= xs3;
+ }
+
+ for(;y>=my0;y--) {
+
+ sn1= xs0>>16;
+ xs0+= dx0;
+
+ sn2= xs2>>16;
+ xs2+= dx2;
+
+ sn1++;
+
+ if(sn2>=rectx) sn2= rectx-1;
+ if(sn1<0) sn1= 0;
+ zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
+ rz= rectzofs+sn1;
+ rp= rectpofs+sn1;
+ x= sn2-sn1;
+ while(x>=0) {
+ if(zverg> *rz || *rz==0x7FFFFFFF) {
+ *rz= zverg;
+ *rp= zvlak;
+ }
+ zverg+= zd;
+ rz++;
+ rp++;
+ x--;
+ }
+
+ zy0-=zyd;
+ rectzofs-= rectx;
+ rectpofs-= rectx;
+ }
+}
+
+void zbufinvulGL(float *v1, float *v2, float *v3) /* vult in R.rectot de waarde Zvlnr in met R.rectz */
+{
+ double x0,y0,z0;
+ double x1,y1,z1,x2,y2,z2,xx1;
+ double zxd,zyd,zy0,tmp;
+ float *minv,*maxv,*midv;
+ unsigned int *rectpofs,*rp;
+ int *rz,zverg,zvlak,x;
+ int my0,my2,sn1,sn2,rectx,zd,*rectzofs;
+ int y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2;
+
+ /* MIN MAX */
+ if(v1[1]<v2[1]) {
+ if(v2[1]<v3[1]) {
+ minv=v1; midv=v2; maxv=v3;
+ }
+ else if(v1[1]<v3[1]) {
+ minv=v1; midv=v3; maxv=v2;
+ }
+ else {
+ minv=v3; midv=v1; maxv=v2;
+ }
+ }
+ else {
+ if(v1[1]<v3[1]) {
+ minv=v2; midv=v1; maxv=v3;
+ }
+ else if(v2[1]<v3[1]) {
+ minv=v2; midv=v3; maxv=v1;
+ }
+ else {
+ minv=v3; midv=v2; maxv=v1;
+ }
+ }
+
+ if(minv[1] == maxv[1]) return; /* beveiliging 'nul' grote vlakken */
+
+ my0= ceil(minv[1]);
+ my2= floor(maxv[1]);
+ omsl= floor(midv[1]);
+
+ if(my2<0 || my0> R.recty) return;
+
+ if(my0<0) my0= 0;
+
+ /* EDGES : DE LANGSTE */
+ xx1= maxv[1]-minv[1];
+ if(xx1!=0.0) {
+ z0= (maxv[0]-minv[0])/xx1;
+
+ tmp= -65536.0*z0;
+ dx0= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(my2-minv[1]) + minv[0]);
+ xs0= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx0= 0;
+ xs0= 65536.0*(MIN2(minv[0],maxv[0]));
+ }
+ /* EDGES : DE BOVENSTE */
+ xx1= maxv[1]-midv[1];
+ if(xx1!=0.0) {
+ z0= (maxv[0]-midv[0])/xx1;
+
+ tmp= -65536.0*z0;
+ dx1= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(my2-midv[1])+midv[0]);
+ xs1= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx1= 0;
+ xs1= 65536.0*(MIN2(midv[0],maxv[0]));
+ }
+ /* EDGES : DE ONDERSTE */
+ xx1= midv[1]-minv[1];
+ if(xx1!=0.0) {
+ z0= (midv[0]-minv[0])/xx1;
+
+ tmp= -65536.0*z0;
+ dx2= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(omsl-minv[1])+minv[0]);
+ xs2= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx2= 0;
+ xs2= 65536.0*(MIN2(minv[0],midv[0]));
+ }
+
+ /* ZBUF DX DY */
+ x1= v1[0]- v2[0];
+ x2= v2[0]- v3[0];
+ y1= v1[1]- v2[1];
+ y2= v2[1]- v3[1];
+ z1= v1[2]- v2[2];
+ z2= v2[2]- v3[2];
+ x0= y1*z2-z1*y2;
+ y0= z1*x2-x1*z2;
+ z0= x1*y2-y1*x2;
+
+ if(z0==0.0) return;
+
+ if(midv[1]==maxv[1]) omsl= my2;
+ if(omsl<0) omsl= -1; /* dan neemt ie de eerste lus helemaal */
+
+ while (my2 >= R.recty) { /* my2 kan groter zijn */
+ xs0+=dx0;
+ if (my2<=omsl) {
+ xs2+= dx2;
+ }
+ else{
+ xs1+= dx1;
+ }
+ my2--;
+ }
+
+ xx1= (x0*v1[0]+y0*v1[1])/z0+v1[2];
+
+ zxd= -x0/z0;
+ zyd= -y0/z0;
+ zy0= my2*zyd+xx1;
+ zd= (int)CLAMPIS(zxd, INT_MIN, INT_MAX);
+
+ /* start-ofset in rect */
+ rectx= R.rectx;
+ rectzofs= (int *)(R.rectz+rectx*my2);
+ rectpofs= (R.rectot+rectx*my2);
+ zvlak= Zvlnr;
+
+ xs3= 0; /* flag */
+ if(dx0>dx1) {
+ xs3= xs0;
+ xs0= xs1;
+ xs1= xs3;
+ xs3= dx0;
+ dx0= dx1;
+ dx1= xs3;
+ xs3= 1; /* flag */
+
+ }
+
+ for(y=my2;y>omsl;y--) {
+
+ /* dit is ongevoelig voor endians */
+ sn1= xs0>>16;
+ xs0+= dx0;
+
+ sn2= xs1>>16;
+ xs1+= dx1;
+
+ sn1++;
+
+ if(sn2>=rectx) sn2= rectx-1;
+ if(sn1<0) sn1= 0;
+ zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
+ rz= rectzofs+sn1;
+ rp= rectpofs+sn1;
+ x= sn2-sn1;
+
+ while(x>=0) {
+ if(zverg< *rz) {
+ *rz= zverg;
+ *rp= zvlak;
+ }
+ zverg+= zd;
+ rz++;
+ rp++;
+ x--;
+ }
+ zy0-=zyd;
+ rectzofs-= rectx;
+ rectpofs-= rectx;
+ }
+
+ if(xs3) {
+ xs0= xs1;
+ dx0= dx1;
+ }
+ if(xs0>xs2) {
+ xs3= xs0;
+ xs0= xs2;
+ xs2= xs3;
+ xs3= dx0;
+ dx0= dx2;
+ dx2= xs3;
+ }
+
+ for(;y>=my0;y--) {
+
+ sn1= xs0>>16;
+ xs0+= dx0;
+
+ sn2= xs2>>16;
+ xs2+= dx2;
+
+ sn1++;
+
+ if(sn2>=rectx) sn2= rectx-1;
+ if(sn1<0) sn1= 0;
+ zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
+ rz= rectzofs+sn1;
+ rp= rectpofs+sn1;
+ x= sn2-sn1;
+ while(x>=0) {
+ if(zverg< *rz) {
+ *rz= zverg;
+ *rp= zvlak;
+ }
+ zverg+= zd;
+ rz++;
+ rp++;
+ x--;
+ }
+
+ zy0-=zyd;
+ rectzofs-= rectx;
+ rectpofs-= rectx;
+ }
+}
+
+
+void zbufinvulGL_onlyZ(float *v1, float *v2, float *v3) /* vult alleen R.rectz. oneven z= 1x ingevuld */
+{
+ double x0,y0,z0,x1,y1,z1,x2,y2,z2,xx1;
+ double zxd,zyd,zy0,tmp;
+ float *minv,*maxv,*midv;
+ int *rz,zverg,x;
+ int my0,my2,sn1,sn2,rectx,zd,*rectzofs;
+ int y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2;
+
+ /* MIN MAX */
+ if(v1[1]<v2[1]) {
+ if(v2[1]<v3[1]) {
+ minv=v1;
+ midv=v2;
+ maxv=v3;
+ }
+ else if(v1[1]<v3[1]) {
+ minv=v1;
+ midv=v3;
+ maxv=v2;
+ }
+ else {
+ minv=v3;
+ midv=v1;
+ maxv=v2;
+ }
+ }
+ else {
+ if(v1[1]<v3[1]) {
+ minv=v2;
+ midv=v1;
+ maxv=v3;
+ }
+ else if(v2[1]<v3[1]) {
+ minv=v2;
+ midv=v3;
+ maxv=v1;
+ }
+ else {
+ minv=v3;
+ midv=v2;
+ maxv=v1;
+ }
+ }
+
+ my0= ceil(minv[1]);
+ my2= floor(maxv[1]);
+ omsl= floor(midv[1]);
+
+ if(my2<0 || my0> R.recty) return;
+
+ if(my0<0) my0=0;
+
+ /* EDGES : DE LANGSTE */
+ xx1= maxv[1]-minv[1];
+ if(xx1!=0.0) {
+ z0= (maxv[0]-minv[0])/xx1;
+
+ tmp= (-65536.0*z0);
+ dx0= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(my2-minv[1])+minv[0]);
+ xs0= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx0= 0;
+ xs0= 65536.0*(MIN2(minv[0],maxv[0]));
+ }
+ /* EDGES : DE BOVENSTE */
+ xx1= maxv[1]-midv[1];
+ if(xx1!=0.0) {
+ z0= (maxv[0]-midv[0])/xx1;
+
+ tmp= (-65536.0*z0);
+ dx1= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(my2-midv[1])+midv[0]);
+ xs1= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx1= 0;
+ xs1= 65536.0*(MIN2(midv[0],maxv[0]));
+ }
+ /* EDGES : DE ONDERSTE */
+ xx1= midv[1]-minv[1];
+ if(xx1!=0.0) {
+ z0= (midv[0]-minv[0])/xx1;
+
+ tmp= (-65536.0*z0);
+ dx2= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(omsl-minv[1])+minv[0]);
+ xs2= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx2= 0;
+ xs2= 65536.0*(MIN2(minv[0],midv[0]));
+ }
+
+ /* ZBUF DX DY */
+ x1= v1[0]- v2[0];
+ x2= v2[0]- v3[0];
+ y1= v1[1]- v2[1];
+ y2= v2[1]- v3[1];
+ z1= v1[2]- v2[2];
+ z2= v2[2]- v3[2];
+ x0= y1*z2-z1*y2;
+ y0= z1*x2-x1*z2;
+ z0= x1*y2-y1*x2;
+
+ if(z0==0.0) return;
+
+ if(midv[1]==maxv[1]) omsl= my2;
+ if(omsl<0) omsl= -1; /* dan neemt ie de eerste lus helemaal */
+
+ while (my2 >= R.recty) { /* my2 kan groter zijn */
+ xs0+=dx0;
+ if (my2<=omsl) {
+ xs2+= dx2;
+ }
+ else{
+ xs1+= dx1;
+ }
+ my2--;
+ }
+
+ xx1= (x0*v1[0]+y0*v1[1])/z0+v1[2];
+
+ zxd= -x0/z0;
+ zyd= -y0/z0;
+ zy0= my2*zyd+xx1;
+ zd= (int)CLAMPIS(zxd, INT_MIN, INT_MAX);
+
+ /* start-ofset in rect */
+ rectx= R.rectx;
+ rectzofs= (int *)(R.rectz+rectx*my2);
+
+ xs3= 0; /* flag */
+ if(dx0>dx1) {
+ xs3= xs0;
+ xs0= xs1;
+ xs1= xs3;
+ xs3= dx0;
+ dx0= dx1;
+ dx1= xs3;
+ xs3= 1; /* flag */
+
+ }
+
+ for(y=my2;y>omsl;y--) {
+
+ sn1= xs0>>16;
+ xs0+= dx0;
+
+ sn2= xs1>>16;
+ xs1+= dx1;
+
+ sn1++;
+
+ if(sn2>=rectx) sn2= rectx-1;
+ if(sn1<0) sn1= 0;
+ zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
+ rz= rectzofs+sn1;
+
+ x= sn2-sn1;
+ while(x>=0) {
+ if(zverg< *rz) {
+ *rz= zverg;
+ }
+ zverg+= zd;
+ rz++;
+ x--;
+ }
+ zy0-=zyd;
+ rectzofs-= rectx;
+ }
+
+ if(xs3) {
+ xs0= xs1;
+ dx0= dx1;
+ }
+ if(xs0>xs2) {
+ xs3= xs0;
+ xs0= xs2;
+ xs2= xs3;
+ xs3= dx0;
+ dx0= dx2;
+ dx2= xs3;
+ }
+
+ for(;y>=my0;y--) {
+
+ sn1= xs0>>16;
+ xs0+= dx0;
+
+ sn2= xs2>>16;
+ xs2+= dx2;
+
+ sn1++;
+
+ if(sn2>=rectx) sn2= rectx-1;
+ if(sn1<0) sn1= 0;
+ zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
+ rz= rectzofs+sn1;
+
+ x= sn2-sn1;
+ while(x>=0) {
+ if(zverg< *rz) {
+ *rz= zverg;
+ }
+ zverg+= zd;
+ rz++;
+ x--;
+ }
+
+ zy0-=zyd;
+ rectzofs-= rectx;
+ }
+}
+
+void print3floats(float *v1, float *v2, float *v3)
+{
+ printf("1 %f %f %f %f\n", v1[0], v1[1], v1[2], v1[3]);
+ printf("2 %f %f %f %f\n", v2[0], v2[1], v2[2], v2[3]);
+ printf("3 %f %f %f %f\n", v3[0], v3[1], v3[2], v3[3]);
+}
+
+static short cliptestf(float p, float q, float *u1, float *u2)
+{
+ float r;
+
+ if(p<0.0) {
+ if(q<p) return 0;
+ else if(q<0.0) {
+ r= q/p;
+ if(r>*u2) return 0;
+ else if(r>*u1) *u1=r;
+ }
+ }
+ else {
+ if(p>0.0) {
+ if(q<0.0) return 0;
+ else if(q<p) {
+ r= q/p;
+ if(r<*u1) return 0;
+ else if(r<*u2) *u2=r;
+ }
+ }
+ else if(q<0.0) return 0;
+ }
+ return 1;
+}
+
+int RE_testclip(float *v)
+{
+ float abs4; /* LET OP: deze func moet zelfde doen als cliptestf, anders problemen in zbufclip()*/
+ short c=0;
+
+ abs4= fabs(v[3]);
+
+ if(v[2]< -abs4) c=16; /* hier stond vroeger " if(v[2]<0) ", zie clippz() */
+ else if(v[2]> abs4) c+= 32;
+
+ if( v[0]>abs4) c+=2;
+ else if( v[0]< -abs4) c+=1;
+
+ if( v[1]>abs4) c+=4;
+ else if( v[1]< -abs4) c+=8;
+
+ return c;
+}
+
+
+static void clipp(float *v1, float *v2, int b1, int *b2, int *b3, int a)
+{
+ float da,db,u1=0.0,u2=1.0;
+
+ labda[b1][0]= -1.0;
+ labda[b1][1]= -1.0;
+
+ da= v2[a]-v1[a];
+ db= v2[3]-v1[3];
+
+ /* volgens het oorspronkelijke artikel van Liang&Barsky, wordt bij het clippen van
+ * hoco's met het viewplane, het getal "0" gebruikt ipv "-w" .
+ * Dit wijkt af van de andere clipping (links en onder) en vond ik ook niet erg
+ * 'homogeen'. Het is dus een fout, wie had dat gedacht van L&B!
+ */
+
+ if(cliptestf(-da-db, v1[3]+v1[a], &u1,&u2)) {
+ if(cliptestf(da-db, v1[3]-v1[a], &u1,&u2)) {
+ *b3=1;
+ if(u2<1.0) {
+ labda[b1][1]= u2;
+ *b2=1;
+ }
+ else labda[b1][1]=1.0; /* u2 */
+ if(u1>0.0) {
+ labda[b1][0]= u1;
+ *b2=1;
+ } else labda[b1][0]=0.0;
+ }
+ }
+}
+
+static int clipline(float *v1, float *v2) /* return 0: niet tekenen */
+{
+ float dz,dw, u1=0.0, u2=1.0;
+ float dx, dy;
+
+ dz= v2[2]-v1[2];
+ dw= v2[3]-v1[3];
+
+ if(cliptestf(-dz-dw, v1[3]+v1[2], &u1,&u2)) {
+ if(cliptestf(dz-dw, v1[3]-v1[2], &u1,&u2)) {
+
+ dx= v2[0]-v1[0];
+ dz= v2[3]-v1[3];
+
+ if(cliptestf(-dx-dz, v1[0]+v1[3], &u1,&u2)) {
+ if(cliptestf(dx-dz, v1[3]-v1[0], &u1,&u2)) {
+
+ dy= v2[1]-v1[1];
+
+ if(cliptestf(-dy-dz,v1[1]+v1[3],&u1,&u2)) {
+ if(cliptestf(dy-dz,v1[3]-v1[1],&u1,&u2)) {
+
+ if(u2<1.0) {
+ v2[0]= v1[0]+u2*dx;
+ v2[1]= v1[1]+u2*dy;
+ v2[2]= v1[2]+u2*dz;
+ v2[3]= v1[3]+u2*dw;
+ }
+ if(u1>0.0) {
+ v1[0]= v1[0]+u1*dx;
+ v1[1]= v1[1]+u1*dy;
+ v1[2]= v1[2]+u1*dz;
+ v1[3]= v1[3]+u1*dw;
+ }
+ return 1;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+static void maakvertpira(float *v1, float *v2, int *b1, int b2, int *clve)
+{
+ float l1,l2,*adr;
+
+ l1= labda[b2][0];
+ l2= labda[b2][1];
+
+ if(l1!= -1.0) {
+ if(l1!= 0.0) {
+ adr= vez+4*(*clve);
+ p[*b1]=adr;
+ (*clve)++;
+ adr[0]= v1[0]+l1*(v2[0]-v1[0]);
+ adr[1]= v1[1]+l1*(v2[1]-v1[1]);
+ adr[2]= v1[2]+l1*(v2[2]-v1[2]);
+ adr[3]= v1[3]+l1*(v2[3]-v1[3]);
+ } else p[*b1]= v1;
+ (*b1)++;
+ }
+ if(l2!= -1.0) {
+ if(l2!= 1.0) {
+ adr= vez+4*(*clve);
+ p[*b1]=adr;
+ (*clve)++;
+ adr[0]= v1[0]+l2*(v2[0]-v1[0]);
+ adr[1]= v1[1]+l2*(v2[1]-v1[1]);
+ adr[2]= v1[2]+l2*(v2[2]-v1[2]);
+ adr[3]= v1[3]+l2*(v2[3]-v1[3]);
+ (*b1)++;
+ }
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+void RE_projectverto(float *v1, float *adr)
+{
+ /* berekent homogene co van vertex v1 */
+ float x,y,z;
+
+ x= v1[0];
+ y= v1[1];
+ z= v1[2];
+ adr[0]= x*R.winmat[0][0] + z*R.winmat[2][0];
+ adr[1]= y*R.winmat[1][1]+ z*R.winmat[2][1];
+ adr[2]= z*R.winmat[2][2] + R.winmat[3][2];
+ adr[3]= z*R.winmat[2][3] + R.winmat[3][3];
+
+} /* end of void RE_projectverto(float *v1, float *adr) */
+
+/* ------------------------------------------------------------------------- */
+
+void projectvert(float *v1, float *adr)
+{
+ /* berekent homogene co van vertex v1 */
+ float x,y,z;
+
+ x= v1[0];
+ y= v1[1];
+ z= v1[2];
+ adr[0]= x*R.winmat[0][0]+ y*R.winmat[1][0]+ z*R.winmat[2][0]+ R.winmat[3][0];
+ adr[1]= x*R.winmat[0][1]+ y*R.winmat[1][1]+ z*R.winmat[2][1]+ R.winmat[3][1];
+ adr[2]= x*R.winmat[0][2]+ y*R.winmat[1][2]+ z*R.winmat[2][2]+ R.winmat[3][2];
+ adr[3]= x*R.winmat[0][3]+ y*R.winmat[1][3]+ z*R.winmat[2][3]+ R.winmat[3][3];
+}
+
+
+void zbufclip(float *f1, float *f2, float *f3, int c1, int c2, int c3)
+{
+ float deler;
+
+ if(c1 | c2 | c3) { /* niet in midden */
+ if(c1 & c2 & c3) { /* helemaal eruit */
+ return;
+ } else { /* clippen */
+ int arg, v, b, clipflag[3], b1, b2, b3, c4, clve=3, clvlo, clvl=1;
+
+ vez[0]= f1[0]; vez[1]= f1[1]; vez[2]= f1[2]; vez[3]= f1[3];
+ vez[4]= f2[0]; vez[5]= f2[1]; vez[6]= f2[2]; vez[7]= f2[3];
+ vez[8]= f3[0]; vez[9]= f3[1]; vez[10]= f3[2];vez[11]= f3[3];
+
+ vlzp[0][0]= vez;
+ vlzp[0][1]= vez+4;
+ vlzp[0][2]= vez+8;
+
+ clipflag[0]= ( (c1 & 48) | (c2 & 48) | (c3 & 48) );
+ if(clipflag[0]==0) { /* anders opnieuw berekend verderop, na de eerste (z) clip */
+ clipflag[1]= ( (c1 & 3) | (c2 & 3) | (c3 & 3) );
+ clipflag[2]= ( (c1 & 12) | (c2 & 12) | (c3 & 12) );
+ }
+
+ for(b=0;b<3;b++) {
+
+ if(clipflag[b]) {
+
+ clvlo= clvl;
+
+ for(v=0; v<clvlo; v++) {
+
+ if(vlzp[v][0]!=0) { /* vlak is er nog */
+ b2= b3 =0; /* clipvlaggen */
+
+ if(b==0) arg= 2;
+ else if (b==1) arg= 0;
+ else arg= 1;
+
+ clipp(vlzp[v][0],vlzp[v][1],0,&b2,&b3, arg);
+ clipp(vlzp[v][1],vlzp[v][2],1,&b2,&b3, arg);
+ clipp(vlzp[v][2],vlzp[v][0],2,&b2,&b3, arg);
+
+ if(b2==0 && b3==1) {
+ /* er helemaal in */;
+ } else if(b3==0) {
+ vlzp[v][0]=0;
+ /* er helemaal uit */;
+ } else {
+ b1=0;
+ maakvertpira(vlzp[v][0],vlzp[v][1],&b1,0,&clve);
+ maakvertpira(vlzp[v][1],vlzp[v][2],&b1,1,&clve);
+ maakvertpira(vlzp[v][2],vlzp[v][0],&b1,2,&clve);
+
+ /* als frontclip is gedaan: nu pas clipvlaggen zetten */
+ if(b==0) {
+ clipflag[1]= clipflag[2]= 0;
+ f1= vez;
+ for(b3=0; b3<clve; b3++) {
+ c4= RE_testclip(f1);
+ clipflag[1] |= (c4 & 3);
+ clipflag[2] |= (c4 & 12);
+ f1+= 4;
+ }
+ }
+
+ vlzp[v][0]=0;
+ if(b1>2) {
+ for(b3=3; b3<=b1; b3++) {
+ vlzp[clvl][0]= p[0];
+ vlzp[clvl][1]= p[b3-2];
+ vlzp[clvl][2]= p[b3-1];
+ clvl++;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* persp deling */
+ /* valt hier nog te optimaliseren door alleen te gebruiken vertices te doen? */
+ if(clve>38) printf("clip overflow: clve clvl %d %d\n",clve,clvl);
+ f1=vez;
+ for(c1=0;c1<clve;c1++) {
+ deler= f1[3];
+ f1[0]= Zmulx*(1.0+f1[0]/deler)+ Zjitx;
+ f1[1]= Zmuly*(1.0+f1[1]/deler)+ Zjity;
+ f1[2]= 0x7FFFFFFF *(f1[2]/deler);
+ f1+=4;
+ }
+ for(b=1;b<clvl;b++) {
+ if(vlzp[b][0]) {
+ zbuffunc(vlzp[b][0],vlzp[b][1],vlzp[b][2]);
+ }
+ }
+ return;
+ }
+ }
+
+ /* persp deling: HCS to ZCS */
+
+ deler= f1[3];
+ vez[0]= Zmulx*(1.0+f1[0]/deler)+ Zjitx;
+ vez[1]= Zmuly*(1.0+f1[1]/deler)+ Zjity;
+ vez[2]= 0x7FFFFFFF *(f1[2]/deler);
+
+ deler= f2[3];
+ vez[4]= Zmulx*(1.0+f2[0]/deler)+ Zjitx;
+ vez[5]= Zmuly*(1.0+f2[1]/deler)+ Zjity;
+ vez[6]= 0x7FFFFFFF *(f2[2]/deler);
+
+ deler= f3[3];
+ vez[8]= Zmulx*(1.0+f3[0]/deler)+ Zjitx;
+ vez[9]= Zmuly*(1.0+f3[1]/deler)+ Zjity;
+ vez[10]= 0x7FFFFFFF *(f3[2]/deler);
+
+ zbuffunc(vez,vez+4,vez+8);
+}
+
+/* ***************** ZBUFFER MAINROUTINES **************** */
+
+
+void zbufferall(void)
+{
+ VlakRen *vlr= NULL;
+ Material *ma=0;
+ int v;
+ short transp=0, env=0, wire=0;
+
+ Zmulx= ((float)R.rectx)/2.0;
+ Zmuly= ((float)R.recty)/2.0;
+
+ fillrect(R.rectz, R.rectx, R.recty, 0x7FFFFFFF);
+
+ Zvlnr= 0;
+
+ zbuffunc= zbufinvulGL;
+ zbuflinefunc= zbufline;
+
+ for(v=0;v<R.totvlak;v++) {
+
+ if((v & 255)==0) vlr= R.blovl[v>>8];
+ else vlr++;
+
+ if(vlr->flag & R_VISIBLE) {
+ if(vlr->mat!=ma) {
+ ma= vlr->mat;
+ transp= ma->mode & MA_ZTRA;
+ env= (ma->mode & MA_ENV);
+ wire= (ma->mode & MA_WIRE);
+
+ if(ma->mode & MA_ZINV) zbuffunc= zbufinvulGLinv;
+ else zbuffunc= zbufinvulGL;
+ }
+
+ if(transp==0) {
+ if(env) Zvlnr= 0;
+ else Zvlnr= v+1;
+
+ if(wire) zbufclipwire(vlr);
+ else {
+ zbufclip(vlr->v1->ho, vlr->v2->ho, vlr->v3->ho, vlr->v1->clip, vlr->v2->clip, vlr->v3->clip);
+ if(vlr->v4) {
+ if(Zvlnr) Zvlnr+= 0x800000;
+ zbufclip(vlr->v1->ho, vlr->v3->ho, vlr->v4->ho, vlr->v1->clip, vlr->v3->clip, vlr->v4->clip);
+ }
+ }
+ }
+ }
+ }
+}
+
+static int hashlist_projectvert(float *v1, float *hoco)
+{
+ static VertBucket bucket[256], *buck;
+
+ if(v1==0) {
+ memset(bucket, 0, 256*sizeof(VertBucket));
+ return 0;
+ }
+
+ buck= &bucket[ (((long)v1)/16) & 255 ];
+ if(buck->vert==v1) {
+ COPY_16(hoco, buck->hoco);
+ return buck->clip;
+ }
+
+ projectvert(v1, hoco);
+ buck->clip = RE_testclip(hoco);
+ buck->vert= v1;
+ COPY_16(buck->hoco, hoco);
+ return buck->clip;
+}
+
+
+void RE_zbufferall_radio(struct RadView *vw, RNode **rg_elem, int rg_totelem)
+{
+ RNode **re, *rn;
+ float hoco[4][4];
+ int a;
+ int c1, c2, c3, c4= 0;
+ unsigned int *rectoto, *rectzo;
+ int rectxo, rectyo;
+
+ if(rg_totelem==0) return;
+
+ hashlist_projectvert(0, 0);
+
+ rectxo= R.rectx;
+ rectyo= R.recty;
+ rectoto= R.rectot;
+ rectzo= R.rectz;
+
+ R.rectx= vw->rectx;
+ R.recty= vw->recty;
+ R.rectot= vw->rect;
+ R.rectz= vw->rectz;
+
+ Zmulx= ((float)R.rectx)/2.0;
+ Zmuly= ((float)R.recty)/2.0;
+
+ /* needed for projectvert */
+ MTC_Mat4MulMat4(R.winmat, vw->viewmat, vw->winmat);
+
+ fillrect(R.rectz, R.rectx, R.recty, 0x7FFFFFFF);
+ fillrect(R.rectot, R.rectx, R.recty, 0xFFFFFF);
+
+ zbuffunc= zbufinvulGL;
+
+ re= rg_elem;
+ re+= (rg_totelem-1);
+ for(a= rg_totelem-1; a>=0; a--, re--) {
+ rn= *re;
+ if( (rn->f & RAD_SHOOT)==0 ) { /* no shootelement */
+
+ if( rn->f & RAD_BACKFACE) Zvlnr= 0xFFFFFF;
+ else Zvlnr= a;
+
+ c1= hashlist_projectvert(rn->v1, hoco[0]);
+ c2= hashlist_projectvert(rn->v2, hoco[1]);
+ c3= hashlist_projectvert(rn->v3, hoco[2]);
+
+ if(rn->v4) {
+ c4= hashlist_projectvert(rn->v4, hoco[3]);
+ }
+
+ zbufclip(hoco[0], hoco[1], hoco[2], c1, c2, c3);
+ if(rn->v4) {
+ zbufclip(hoco[0], hoco[2], hoco[3], c1, c3, c4);
+ }
+ }
+ }
+
+ /* restore */
+ R.rectx= rectxo;
+ R.recty= rectyo;
+ R.rectot= rectoto;
+ R.rectz= rectzo;
+
+}
+
+void zbuffershad(LampRen *lar)
+{
+ VlakRen *vlr= NULL;
+ Material *ma=0;
+ int a, ok=1, lay= -1;
+
+ if(lar->mode & LA_LAYER) lay= lar->lay;
+
+ Zmulx= ((float)R.rectx)/2.0;
+ Zmuly= ((float)R.recty)/2.0;
+ Zjitx= Zjity= -.5;
+
+ fillrect(R.rectz,R.rectx,R.recty,0x7FFFFFFE);
+
+ zbuffunc= zbufinvulGL_onlyZ;
+
+ for(a=0;a<R.totvlak;a++) {
+
+ if((a & 255)==0) vlr= R.blovl[a>>8];
+ else vlr++;
+
+ if(vlr->mat!= ma) {
+ ma= vlr->mat;
+ ok= 1;
+ if((ma->mode & MA_TRACEBLE)==0) ok= 0;
+ }
+ /* traceble er weer in: automatische verwijdering niet geweldig */
+
+ if(ok && (vlr->flag & R_VISIBLE) && (vlr->lay & lay)) {
+ zbufclip(vlr->v1->ho, vlr->v2->ho, vlr->v3->ho, vlr->v1->clip, vlr->v2->clip, vlr->v3->clip);
+ if(vlr->v4) zbufclip(vlr->v1->ho, vlr->v3->ho, vlr->v4->ho, vlr->v1->clip, vlr->v3->clip, vlr->v4->clip);
+ }
+ }
+}
+
+
+
+/* ******************** ABUF ************************* */
+
+
+void bgnaccumbuf(void)
+{
+
+ Acolrow= MEM_mallocN(4*sizeof(short)*R.rectx, "Acolrow");
+ Arectz= MEM_mallocN(sizeof(int)*ABUFPART*R.rectx, "Arectz");
+ APixbuf= MEM_mallocN(ABUFPART*R.rectx*sizeof(APixstr), "APixbuf");
+
+ Aminy= -1000;
+ Amaxy= -1000;
+
+ apsmteller= 0;
+ apsmfirst.next= 0;
+ apsmfirst.ps= 0;
+} /* End of void bgnaccumbuf(void) */
+
+/* ------------------------------------------------------------------------ */
+
+void endaccumbuf(void)
+{
+
+ MEM_freeN(Acolrow);
+ MEM_freeN(Arectz);
+ MEM_freeN(APixbuf);
+ freepsA();
+} /* End of void endaccumbuf(void) */
+
+/* ------------------------------------------------------------------------ */
+
+void copyto_abufz(int sample)
+{
+ PixStr *ps;
+ int x, y, *rza;
+ long *rd;
+
+ memcpy(Arectz, R.rectz+ R.rectx*Aminy, 4*R.rectx*(Amaxy-Aminy+1));
+
+ if( (R.r.mode & R_OSA)==0 || sample==0) return;
+
+ rza= Arectz;
+ rd= (R.rectdaps+ R.rectx*Aminy);
+
+ sample= (1<<sample);
+
+ for(y=Aminy; y<=Amaxy; y++) {
+ for(x=0; x<R.rectx; x++) {
+
+ if( IS_A_POINTER_CODE(*rd)) {
+ ps= (PixStr *) POINTER_FROM_CODE(*rd);
+
+ while(ps) {
+ if(sample & ps->mask) {
+ *rza= ps->z;
+ break;
+ }
+ ps= ps->next;
+ }
+ }
+
+ rd++; rza++;
+ }
+ }
+} /* end of void copyto_abufz(int sample) */
+
+
+/* ------------------------------------------------------------------------ */
+
+void zbuffer_abuf()
+{
+ float vec[3], hoco[4], mul, zval, fval;
+ Material *ma=0;
+ int v, len;
+
+ Zjitx= Zjity= -.5;
+ Zmulx= ((float)R.rectx)/2.0;
+ Zmuly= ((float)R.recty)/2.0;
+
+ /* clear APixstructen */
+ len= sizeof(APixstr)*R.rectx*ABUFPART;
+ memset(APixbuf, 0, len);
+
+ zbuffunc= zbufinvulAc;
+ zbuflinefunc= zbuflineAc;
+
+ for(Zsample=0; Zsample<R.osa || R.osa==0; Zsample++) {
+
+ copyto_abufz(Zsample); /* init zbuffer */
+
+ if(R.r.mode & R_OSA) {
+ Zjitx= -jit[Zsample][0];
+ Zjity= -jit[Zsample][1];
+ }
+
+/* printf("Start facetrace\n"); */
+
+ for(v=0; v<R.totvlak; v++) {
+ if((v & 255)==0) {
+ Zvlr= R.blovl[v>>8];
+ }
+ else Zvlr++;
+
+ ma= Zvlr->mat;
+
+/* printf("Face %d :%x at %f\n", v, ma, Zvlr->v1->ho[3]); */
+
+
+ if(ma->mode & (MA_ZTRA)) {
+
+ /* voordeeltje voor transp renderen */
+ if( ma->zoffs != 0.0) {
+ mul= 0x7FFFFFFF;
+ zval= mul*(1.0+Zvlr->v1->ho[2]/Zvlr->v1->ho[3]);
+
+ VECCOPY(vec, Zvlr->v1->co);
+ /* z is negatief, wordt anders geclipt */
+ vec[2]-= ma->zoffs;
+ RE_projectverto(vec, hoco);
+ fval= mul*(1.0+hoco[2]/hoco[3]);
+
+ Azvoordeel= (int) fabs(zval - fval );
+
+ /* PATCH: als transp en niet transp dicht op elkaar liggen: Zbuf aliasing: eruit! */
+ /* Azvoordeel= 0xFFFF; */
+ }
+ else Azvoordeel= 0;
+ /* else Azvoordeel= 0xFFFF; */
+
+ Zvlnr= v+1;
+
+ if(Zvlr->flag & R_VISIBLE) {
+
+ if(ma->mode & (MA_WIRE)) zbufclipwire(Zvlr);
+ else {
+ zbufclip(Zvlr->v1->ho, Zvlr->v2->ho, Zvlr->v3->ho, Zvlr->v1->clip, Zvlr->v2->clip, Zvlr->v3->clip);
+ if(Zvlr->v4) {
+ Zvlnr+= 0x800000;
+ zbufclip(Zvlr->v1->ho, Zvlr->v3->ho, Zvlr->v4->ho, Zvlr->v1->clip, Zvlr->v3->clip, Zvlr->v4->clip);
+ }
+ }
+ }
+ }
+ if(RE_local_test_break()) break;
+ }
+
+ if((R.r.mode & R_OSA)==0) break;
+ if(RE_local_test_break()) break;
+ }
+
+} /* end of void zbuffer_abuf() */
+
+
+int vergzvlak(const void *a1, const void *a2)
+{
+ const int *x1=a1, *x2=a2;
+
+ if( x1[0] < x2[0] ) return 1;
+ else if( x1[0] > x2[0]) return -1;
+ return 0;
+}
+
+void shadetrapixel(float x, float y, int vlak)
+{
+ if( (vlak & 0x7FFFFF) > R.totvlak) {
+ printf("error in shadetrapixel nr: %d\n", (vlak & 0x7FFFFF));
+ return;
+ }
+
+ shadepixel(x, y, vlak);
+}
+
+extern unsigned short usegamtab;
+extern unsigned short shortcol[4];
+void abufsetrow(int y)
+{
+ APixstr *ap, *apn;
+ float xs, ys;
+ int x, part, a, b, zrow[100][3], totvlak, alpha[32], tempgam, nr, intcol[4];
+ int sval, tempRf;
+ unsigned short *col, tempcol[4], sampcol[16*4], *scol;
+
+ if(y<0) return;
+ if(R.osa>16) {
+ printf("abufsetrow: osa too large\n");
+ G.afbreek= 1;
+ return;
+ }
+
+ tempRf= R.flag;
+ R.flag &= ~R_LAMPHALO;
+
+ /* alpha LUT */
+ if(R.r.mode & R_OSA ) {
+ x= (65536/R.osa);
+ for(a=0; a<=R.osa; a++) {
+ alpha[a]= a*x;
+ }
+ }
+ /* moet pixbuf worden gemaakt? */
+ if(y<Aminy || y>Amaxy) {
+ part= (y/ABUFPART);
+ Aminy= part*ABUFPART;
+ Amaxy= Aminy+ABUFPART-1;
+ if(Amaxy>=R.recty) Amaxy= R.recty-1;
+ freepsA();
+ zbuffer_abuf();
+ }
+
+ /* render rij */
+ col= Acolrow;
+ memset(col, 0, 2*4*R.rectx);
+ ap= APixbuf+R.rectx*(y-Aminy);
+ ys= y;
+ tempgam= usegamtab;
+ usegamtab= 0;
+
+ for(x=0; x<R.rectx; x++, col+=4, ap++) {
+ if(ap->p[0]) {
+ /* sorteer op z */
+ totvlak= 0;
+ apn= ap;
+ while(apn) {
+ for(a=0; a<4; a++) {
+ if(apn->p[a]) {
+ zrow[totvlak][0]= apn->z[a];
+ zrow[totvlak][1]= apn->p[a];
+ zrow[totvlak][2]= apn->mask[a];
+ totvlak++;
+ if(totvlak>99) totvlak= 99;
+ }
+ else break;
+ }
+ apn= apn->next;
+ }
+ if(totvlak==1) {
+
+ if(R.r.mode & R_OSA ) {
+ b= centmask[ ap->mask[0] ];
+ xs= (float)x+centLut[b & 15];
+ ys= (float)y+centLut[b>>4];
+ }
+ else {
+ xs= x; ys= y;
+ }
+ shadetrapixel(xs, ys, ap->p[0]);
+
+ nr= count_mask(ap->mask[0]);
+ if( (R.r.mode & R_OSA) && nr<R.osa) {
+ a= alpha[ nr ];
+ col[0]= (shortcol[0]*a)>>16;
+ col[1]= (shortcol[1]*a)>>16;
+ col[2]= (shortcol[2]*a)>>16;
+ col[3]= (shortcol[3]*a)>>16;
+ }
+ else {
+ col[0]= shortcol[0];
+ col[1]= shortcol[1];
+ col[2]= shortcol[2];
+ col[3]= shortcol[3];
+ }
+ }
+ else {
+
+ if(totvlak==2) {
+ if(zrow[0][0] < zrow[1][0]) {
+ a= zrow[0][0]; zrow[0][0]= zrow[1][0]; zrow[1][0]= a;
+ a= zrow[0][1]; zrow[0][1]= zrow[1][1]; zrow[1][1]= a;
+ a= zrow[0][2]; zrow[0][2]= zrow[1][2]; zrow[1][2]= a;
+ }
+
+ }
+ else { /* totvlak>2 */
+ qsort(zrow, totvlak, sizeof(int)*3, vergzvlak);
+ }
+
+ /* samenvoegen als pixels aanvullen */
+
+ while(totvlak>0) {
+ totvlak--;
+
+ if(R.r.mode & R_OSA) {
+ b= centmask[ zrow[totvlak][2] ];
+ xs= (float)x+centLut[b & 15];
+ ys= (float)y+centLut[b>>4];
+ }
+ else {
+ xs= x; ys= y;
+ }
+ shadetrapixel(xs, ys, zrow[totvlak][1]);
+
+ a= count_mask(zrow[totvlak][2]);
+ if( (R.r.mode & R_OSA ) && a<R.osa) {
+ if(totvlak>0) {
+ memset(sampcol, 0, 4*2*R.osa);
+ sval= addtosampcol(sampcol, shortcol, zrow[totvlak][2]);
+
+ /* sval==0: aplha helemaal vol */
+ while( (sval != 0) && (totvlak>0) ) {
+ a= count_mask(zrow[totvlak-1][2]);
+ if(a==R.osa) break;
+ totvlak--;
+
+ b= centmask[ zrow[totvlak][2] ];
+
+ xs= (float)x+centLut[b & 15];
+ ys= (float)y+centLut[b>>4];
+
+ shadetrapixel(xs, ys, zrow[totvlak][1]);
+ sval= addtosampcol(sampcol, shortcol, zrow[totvlak][2]);
+ }
+ scol= sampcol;
+ intcol[0]= scol[0]; intcol[1]= scol[1];
+ intcol[2]= scol[2]; intcol[3]= scol[3];
+ scol+= 4;
+ for(a=1; a<R.osa; a++, scol+=4) {
+ intcol[0]+= scol[0]; intcol[1]+= scol[1];
+ intcol[2]+= scol[2]; intcol[3]+= scol[3];
+ }
+ tempcol[0]= intcol[0]/R.osa;
+ tempcol[1]= intcol[1]/R.osa;
+ tempcol[2]= intcol[2]/R.osa;
+ tempcol[3]= intcol[3]/R.osa;
+
+ addAlphaUnderShort(col, tempcol);
+
+ }
+ else {
+ a= alpha[a];
+ shortcol[0]= (shortcol[0]*a)>>16;
+ shortcol[1]= (shortcol[1]*a)>>16;
+ shortcol[2]= (shortcol[2]*a)>>16;
+ shortcol[3]= (shortcol[3]*a)>>16;
+ addAlphaUnderShort(col, shortcol);
+ }
+ }
+ else addAlphaUnderShort(col, shortcol);
+
+ if(col[3]>=0xFFF0) break;
+ }
+ }
+ }
+ }
+
+ usegamtab= tempgam;
+ R.flag= tempRf;
+}
+
+/* end of zbuf.c */
+
+
+
+
diff --git a/source/blender/render/intern/source/zbufferdatastruct.c b/source/blender/render/intern/source/zbufferdatastruct.c
new file mode 100644
index 00000000000..f8e683d46bd
--- /dev/null
+++ b/source/blender/render/intern/source/zbufferdatastruct.c
@@ -0,0 +1,342 @@
+/**
+ * zbufferdatastruct.c
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * The z buffer consists of an array of lists. Each list holds the objects
+ * behind a pixel. These can be sorted for closest distance. Per object,
+ * we store:
+ * - object type
+ * - object index
+ * - minimum distance
+ * - maximum distance
+ * - oversample flags
+ *
+ * The buffer was created to fit the new unified renderpipeline. We might
+ * turn it into an object later on.
+ *
+ * The z buffer has an unlimited depth. The oversampling code chops at a
+ * certain number of faces. This number is defined in
+ * vanillaRenderPipe_types.h
+ *
+ * Version 1 of the z buffer inserted objects by means of linear
+ * search: we walk along the list until we find the right object or
+ * until we have to insert a new one. This is terribly inefficient
+ * when we are dealing with large numbers of objects. Can we find a
+ * better solution here?
+ *
+ * Because we treat halos as billboards, we optimize halo
+ * insertion. For this purpose the fillFlatObject() functions have
+ * been implemented. */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+#include "zbufferdatastruct.h"
+#include "render.h"
+#include "render_intern.h"
+/* if defined: all jittersamples are stored individually. _very_ serious */
+/* performance hit ! also gives some buffer size problems in big scenes */
+/* #define RE_INDIVIDUAL_SUBPIXELS */
+
+/* ------------------------------------------------------------------------- */
+
+static RE_APixstrExtMain RE_apsemfirst; /* pixstr bookkeeping var */
+static short RE_apsemteller = 0; /* pixstr bookkeeping var */
+static int RE_zbufferwidth; /* width of the z-buffer (pixels) */
+RE_APixstrExt *APixbufExt; /* Zbuffer: linked list of face, halo indices */
+
+/*-RE_APixstrExt------------------------------------------------------------ */
+
+void initZbuffer(int width)
+{
+ APixbufExt = MEM_callocN(RE_ZBUFLEN * width * sizeof(RE_APixstrExt),
+ "APixbufExt");
+ RE_zbufferwidth = width;
+ RE_apsemteller = 0;
+ RE_apsemfirst.next = NULL;
+ RE_apsemfirst.ps = NULL;
+} /* end of RE_APixstrExt *initZbufferDataStruct() */
+
+/* ------------------------------------------------------------------------- */
+
+void freeZbuffer(void)
+{
+ if (APixbufExt) MEM_freeN(APixbufExt);
+ freepseA();
+} /* end of void freeZbuffer(void) */
+
+/* ------------------------------------------------------------------------- */
+
+void resetZbuffer(void)
+{
+ int len;
+
+ freepseA();
+ len = sizeof(RE_APixstrExt) * RE_zbufferwidth * RE_ZBUFLEN;
+ memset(APixbufExt, 0, len);
+} /* end of void resetZbuffer(void) */
+
+/* ------------------------------------------------------------------------- */
+
+RE_APixstrExt *addpsemainA()
+{
+ RE_APixstrExtMain *psm;
+
+ psm= &RE_apsemfirst;
+
+ while(psm->next) {
+ psm= psm->next;
+ }
+
+ psm->next= MEM_callocN(sizeof(RE_APixstrExtMain), "addpsemainA");
+
+ psm= psm->next;
+
+ /* Initialise the new structure to safe values. Memory that is newly */
+ /* allocated must be zero... Not sure if that happens everywhere now.*/
+ psm->next=0;
+ psm->ps= MEM_callocN(4096*sizeof(RE_APixstrExt),"pixstrext");
+ RE_apsemteller= 0;
+
+ return psm->ps;
+} /* End of RE_APixstrExt *addpsemainA() */
+
+/* ------------------------------------------------------------------------- */
+
+void freepseA()
+{
+ RE_APixstrExtMain *psm, *next;
+
+ psm= &RE_apsemfirst;
+
+ while(psm) {
+ next= psm->next;
+ if(psm->ps) {
+ MEM_freeN(psm->ps);
+ psm->ps= 0;
+ }
+ if(psm!= &RE_apsemfirst) MEM_freeN(psm);
+ psm= next;
+ }
+
+ RE_apsemfirst.next= 0;
+ RE_apsemfirst.ps= 0;
+ RE_apsemteller= 0;
+} /* End of void freepseA() */
+
+/* ------------------------------------------------------------------------- */
+
+RE_APixstrExt *addpseA(void)
+{
+ static RE_APixstrExt *prev;
+
+ /* eerste PS maken */
+ if((RE_apsemteller & 4095)==0) prev= addpsemainA();
+ else prev++;
+ RE_apsemteller++;
+
+ return prev;
+} /* End of RE_APixstrExt *addpseA(void) */
+
+/* ------------------------------------------------------------------------- */
+
+void insertObject(int apteller,
+/* int opaque, */
+ int obindex,
+ int obtype,
+ int dist,
+ int mask)
+{
+ /* Guard the insertion if needed? */
+ RE_APixstrExt* apn = &APixbufExt[apteller];
+
+ while(apn) {
+ if(apn->t[0] == RE_NONE) {
+ apn->p[0] = obindex; apn->t[0] = obtype;
+ apn->zmin[0] = dist; apn->zmax[0] = dist;
+ apn->mask[0] = mask;
+ break;
+ }
+#ifndef RE_INDIVIDUAL_SUBPIXELS
+ if((apn->p[0] == obindex) && (apn->t[0] & obtype)) {
+ if(dist < apn->zmin[0]) apn->zmin[0] = dist;
+ else if(dist > apn->zmax[0]) apn->zmax[0] = dist;
+ apn->mask[0]|= mask;
+ break;
+ }
+#endif
+ if(apn->t[1] == RE_NONE) {
+ apn->p[1] = obindex; apn->t[1] = obtype;
+ apn->zmin[1] = dist; apn->zmax[1] = dist;
+ apn->mask[1] = mask;
+ break;
+ }
+#ifndef RE_INDIVIDUAL_SUBPIXELS
+ if((apn->p[1] == obindex) && (apn->t[1] & obtype)) {
+ if(dist < apn->zmin[1]) apn->zmin[1] = dist;
+ else if(dist > apn->zmax[1]) apn->zmax[1] = dist;
+ apn->mask[1]|= mask;
+ break;
+ }
+#endif
+ if(apn->t[2] == RE_NONE) {
+ apn->p[2] = obindex; apn->t[2] = obtype;
+ apn->zmin[2] = dist; apn->zmax[2] = dist;
+ apn->mask[2] = mask;
+ break;
+ }
+#ifndef RE_INDIVIDUAL_SUBPIXELS
+ if((apn->p[2] == obindex) && (apn->t[2] & obtype)) {
+ if(dist < apn->zmin[2]) apn->zmin[2] = dist;
+ else if(dist > apn->zmax[2]) apn->zmax[2] = dist;
+ apn->mask[2]|= mask;
+ break;
+ }
+#endif
+ if(apn->t[3] == RE_NONE) {
+ apn->p[3] = obindex; apn->t[3] = obtype;
+ apn->zmin[3] = dist; apn->zmax[3] = dist;
+ apn->mask[3] = mask;
+ break;
+ }
+#ifndef RE_INDIVIDUAL_SUBPIXELS
+ if((apn->p[3] == obindex) && (apn->t[3] & obtype)) {
+ if(dist < apn->zmin[3]) apn->zmin[3] = dist;
+ else if(dist > apn->zmax[3]) apn->zmax[3] = dist;
+ apn->mask[3]|= mask;
+ break;
+ }
+#endif
+ if(apn->next==0) apn->next= addpseA();
+ apn= apn->next;
+ }
+} /* end of insertObject(RE_APixstrExt*, int, int, int, int) */
+
+/* ------------------------------------------------------------------------- */
+
+void insertFlatObject(RE_APixstrExt *apn, int obindex, int obtype, int dist, int mask)
+{
+ while(apn) {
+ if(apn->t[0] == RE_NONE) {
+ apn->p[0] = obindex; apn->zmin[0] = dist;
+ apn->zmax[0] = dist; apn->mask[0] = mask;
+ apn->t[0] = obtype;
+ break;
+ }
+#ifndef RE_INDIVIDUAL_SUBPIXELS
+ if( (apn->t[0] & obtype) && (apn->p[0] == obindex)) {
+ apn->mask[0]|= mask; break;
+ }
+#endif
+ if(apn->t[1] == RE_NONE) {
+ apn->p[1] = obindex; apn->zmin[1] = dist;
+ apn->zmax[1] = dist; apn->mask[1] = mask;
+ apn->t[1] = obtype;
+ break;
+ }
+#ifndef RE_INDIVIDUAL_SUBPIXELS
+ if( (apn->t[1] & obtype) && (apn->p[1] == obindex)) {
+ apn->mask[1]|= mask; break;
+ }
+#endif
+ if(apn->t[2] == RE_NONE) {
+ apn->p[2] = obindex; apn->zmin[2] = dist;
+ apn->zmax[2] = dist; apn->mask[2] = mask;
+ apn->t[2] = obtype;
+ break;
+ }
+#ifndef RE_INDIVIDUAL_SUBPIXELS
+ if( (apn->t[2] & obtype) && (apn->p[2] == obindex)) {
+ apn->mask[2]|= mask; break;
+ }
+#endif
+ if(apn->t[3] == RE_NONE) {
+ apn->p[3] = obindex; apn->zmin[3] = dist;
+ apn->zmax[3] = dist; apn->mask[3] = mask;
+ apn->t[3] = obtype;
+ break;
+ }
+#ifndef RE_INDIVIDUAL_SUBPIXELS
+ if( (apn->t[3] & obtype) && (apn->p[3] == obindex)) {
+ apn->mask[3]|= mask; break;
+ }
+#endif
+ if(apn->next==0) apn->next= addpseA();
+ apn= apn->next;
+ };
+} /* end of void insertFlatObject(RE_APixstrExt, int, int, int, int)*/
+
+/* ------------------------------------------------------------------------- */
+/* This function might be helped by an end-of-list marker */
+void insertFlatObjectNoOsa(RE_APixstrExt *ap,
+ int obindex,
+ int obtype,
+ int dist,
+ int mask)
+{
+ while(ap) {
+ if(ap->t[0] == RE_NONE) {
+ ap->p[0] = obindex; ap->zmin[0] = dist;
+ ap->zmax[0] = dist; ap->mask[0] = mask;
+ ap->t[0] = obtype;
+ break;
+ }
+
+ if(ap->t[1] == RE_NONE) {
+ ap->p[1] = obindex; ap->zmin[1] = dist;
+ ap->zmax[1] = dist; ap->mask[1] = mask;
+ ap->t[1] = obtype;
+ break;
+ }
+
+ if(ap->t[2] == RE_NONE) {
+ ap->p[2] = obindex; ap->zmin[2] = dist;
+ ap->zmax[2] = dist; ap->mask[2] = mask;
+ ap->t[2] = obtype;
+ break;
+ }
+
+ if(ap->t[3] == RE_NONE) {
+ ap->p[3] = obindex; ap->zmin[3] = dist;
+ ap->zmax[3] = dist; ap->mask[3] = mask;
+ ap->t[3] = obtype;
+ break;
+ }
+
+ if(ap->next==0) ap->next= addpseA();
+ ap= ap->next;
+ };
+} /* end of void insertFlatObjectNoOsa(RE_APixstrExt, int, int, int, int)*/
+
+/* ------------------------------------------------------------------------- */
+
+/* EOF */