/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * * 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 * any later version. * * 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 */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** // Invert a 3x3 matrix inside a 4x4 one (used for lighting vectors) __inline void mat_3x3_inverse (float md[4][4], float ms[4][4]) { md[0][0] = ms[0][0]; md[1][1] = ms[1][1]; md[2][2] = ms[2][2]; md[0][1] = ms[1][0]; md[1][0] = ms[0][1]; md[0][2] = ms[2][0]; md[2][0] = ms[0][2]; md[1][2] = ms[2][1]; md[2][1] = ms[1][2]; } __inline float DotProduct(register float *v1, register float *v2) { register float result; result = v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; return(result); } __inline void NormalizeVector(float *v) { register float len; len = (float)sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); if (len !=0) { v[0] /= len; v[1] /= len; v[2] /= len; } else { v[0] = 0; v[1] = 0; v[2] = 0; } } __inline void TransformVector (float *src, float *dst, float mat[4][4]) { dst[0] = mat[0][0]*src[0] + mat[1][0]*src[1] + mat[2][0]*src[2]; dst[1] = mat[0][1]*src[0] + mat[1][1]*src[1] + mat[2][1]*src[2]; dst[2] = mat[0][2]*src[0] + mat[1][2]*src[1] + mat[2][2]*src[2]; } // !! // Thanks to Gugaman for the idea that took the speed soaring! // Vector calculations are now at a minimum. // !! __inline void calc_light (VERTEX *v) { float light_intensity = 0.0f; VERTEX *vtx = (VERTEX*)v; register float color[3] = {0, 0, 0}; DWORD l; for (l=0; lvec); if (light_intensity < 0) light_intensity = 0; color[0] += rdp.light[l].r * light_intensity; color[1] += rdp.light[l].g * light_intensity; color[2] += rdp.light[l].b * light_intensity; } // Add ambient lighting color[0] += rdp.light[l].r; color[1] += rdp.light[l].g; color[2] += rdp.light[l].b; if (color[0] > 1.0f) color[0] = 1.0f; if (color[1] > 1.0f) color[1] = 1.0f; if (color[2] > 1.0f) color[2] = 1.0f; vtx->r = (BYTE)(color[0]*255.0f); vtx->g = (BYTE)(color[1]*255.0f); vtx->b = (BYTE)(color[2]*255.0f); } __inline void calc_light_white (VERTEX *v, float l_vec[3], BYTE lcol[3], float matrix[4][4]) { float light_intensity = 0.0f; VERTEX *vtx = (VERTEX*)v; static float vec[3]; // Calculate light vectors mat_3x3_inverse (rdp.inverse, matrix); TransformVector (l_vec, vec, rdp.inverse); NormalizeVector (vec); light_intensity = DotProduct (vec, v->vec); if (light_intensity < 0) light_intensity = 0; if (light_intensity > 1.0f) light_intensity = 1.0f; float col = 255.0f * light_intensity; vtx->r = (BYTE)col; vtx->g = (BYTE)col; vtx->b = (BYTE)col; } /*__inline void calc_sphere (VERTEX *v) { float vec[3]; TransformVector (v->vec, vec, rdp.model); NormalizeVector (vec); if (rdp.cur_cache[0]) { v->u0 = (asinf(vec[0])/3.14f + 0.5f) * rdp.cur_cache[0]->scale_x * (32.0f/(float)rdp.cur_cache[0]->width) * 255.0f * rdp.tiles[rdp.cur_tile].s_scale * 1024; v->v0 = (asinf(vec[1])/3.14f + 0.5f) * rdp.cur_cache[0]->scale_y * (32.0f/(float)rdp.cur_cache[0]->height) * 255.0f * rdp.tiles[rdp.cur_tile].t_scale * 1024; } }*/ __inline void calc_linear (VERTEX *v) { float vec[3]; TransformVector (v->vec, vec, rdp.combined); // TransformVector (v->vec, vec, rdp.proj); NormalizeVector (vec); if (rdp.cur_cache[0]) { // scale >> 6 is size to map to v->ou = (vec[0] * 0.5f + 0.5f) * (rdp.tiles[rdp.cur_tile].org_s_scale >> 6); v->ov = (vec[1] * 0.5f + 0.5f) * (rdp.tiles[rdp.cur_tile].org_t_scale >> 6); } } #define min(a,b) ((a) < (b) ? (a) : (b)) #define max(a,b) ((a) > (b) ? (a) : (b)) __inline void calc_sphere (VERTEX *v) { //RDP("calc_sphere\n"); float vec[3]; int s_scale = min(rdp.tiles[rdp.cur_tile].org_s_scale >> 6, rdp.tiles[rdp.cur_tile].lr_s); int t_scale = min(rdp.tiles[rdp.cur_tile].org_t_scale >> 6, rdp.tiles[rdp.cur_tile].lr_t); TransformVector (v->vec, vec, rdp.combined); // TransformVector (v->vec, vec, rdp.proj); NormalizeVector (vec); if (rdp.cur_cache[0]) { // scale >> 6 is size to map to // v->ou = (asinf(vec[0])/3.14f + 0.5f) * (rdp.tiles[rdp.cur_tile].org_s_scale >> 6); // v->ov = (asinf(vec[1])/3.14f + 0.5f) * (rdp.tiles[rdp.cur_tile].org_t_scale >> 6); v->ou = (asinf(vec[0])/3.14f + 0.5f) * s_scale; v->ov = (asinf(vec[1])/3.14f + 0.5f) * t_scale; } }