commit
42b11dc1a7
|
@ -42,7 +42,14 @@ window.cameraIngame = function(kart) {
|
||||||
camNormal[2] += (kart.kartNormal[2]-camNormal[2])*0.075;
|
camNormal[2] += (kart.kartNormal[2]-camNormal[2])*0.075;
|
||||||
vec3.normalize(camNormal, camNormal);
|
vec3.normalize(camNormal, camNormal);
|
||||||
|
|
||||||
camAngle += dirDiff(kart.physicalDir+kart.driftOff/2, camAngle)*0.075;
|
if (kart.physBasis != null) {
|
||||||
|
var kartA = kart.physicalDir+kart.driftOff/2;
|
||||||
|
var forward = [Math.sin(kartA), 0, -Math.cos(kartA)];
|
||||||
|
vec3.transformMat4(forward, forward, kart.physBasis.mat);
|
||||||
|
camAngle += dirDiff(Math.atan2(forward[0], -forward[2]), camAngle)*0.075;
|
||||||
|
} else {
|
||||||
|
camAngle += dirDiff(kart.physicalDir+kart.driftOff/2, camAngle)*0.075;
|
||||||
|
}
|
||||||
camAngle = fixDir(camAngle);
|
camAngle = fixDir(camAngle);
|
||||||
|
|
||||||
boostOff += (((kart.boostNorm+kart.boostMT > 0)?5:0) - boostOff)*0.075
|
boostOff += (((kart.boostNorm+kart.boostMT > 0)?5:0) - boostOff)*0.075
|
||||||
|
@ -52,14 +59,23 @@ window.cameraIngame = function(kart) {
|
||||||
var dist = 192;
|
var dist = 192;
|
||||||
this.targetShadowPos = vec3.add([], kart.pos, [Math.sin(kart.angle)*dist, 0, -Math.cos(kart.angle)*dist])
|
this.targetShadowPos = vec3.add([], kart.pos, [Math.sin(kart.angle)*dist, 0, -Math.cos(kart.angle)*dist])
|
||||||
|
|
||||||
thisObj.view = {p:p, mv:mat};
|
thisObj.view = {p:p, mv:mat, pos: vec3.scale([], vec3.transformMat4([], [0,0,0], mat4.invert([], mat)), 1024)};
|
||||||
|
|
||||||
return thisObj.view;
|
return thisObj.view;
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildBasis() {
|
function buildBasis() {
|
||||||
//order y, x, z
|
//order y, x, z
|
||||||
var basis = gramShmidt(camNormal, [Math.cos(camAngle), 0, Math.sin(camAngle)], [Math.sin(camAngle), 0, -Math.cos(camAngle)]);
|
var kart = thisObj.kart;
|
||||||
|
var forward = [Math.sin(camAngle), 0, -Math.cos(camAngle)];
|
||||||
|
var side = [Math.cos(camAngle), 0, Math.sin(camAngle)];
|
||||||
|
/*
|
||||||
|
if (kart.physBasis != null) {
|
||||||
|
vec3.transformMat4(forward, forward, kart.physBasis.mat);
|
||||||
|
vec3.transformMat4(side, side, kart.physBasis.mat);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
var basis = gramShmidt(camNormal, side, forward);
|
||||||
var temp = basis[0];
|
var temp = basis[0];
|
||||||
basis[0] = basis[1];
|
basis[0] = basis[1];
|
||||||
basis[1] = temp; //todo: cleanup
|
basis[1] = temp; //todo: cleanup
|
||||||
|
|
|
@ -102,7 +102,7 @@ window.cameraIntro = function() {
|
||||||
|
|
||||||
thisObj.targetShadowPos = lookAtPos;
|
thisObj.targetShadowPos = lookAtPos;
|
||||||
|
|
||||||
return {p:p, mv:mat}
|
return {p:p, mv:mat, pos: vec3.scale([], vec3.transformMat4([], [0,0,0], mat4.invert([], mat)), 1024)}
|
||||||
}
|
}
|
||||||
|
|
||||||
var initCam = function(scene, came) {
|
var initCam = function(scene, came) {
|
||||||
|
|
|
@ -55,6 +55,7 @@ window.cameraSpectator = function(kart) {
|
||||||
if (zoomLevel > curCam.zoomEnd) zoomLevel = curCam.zoomEnd;
|
if (zoomLevel > curCam.zoomEnd) zoomLevel = curCam.zoomEnd;
|
||||||
|
|
||||||
thisObj.view = camFunc[curCam.camType](scene, curCam);
|
thisObj.view = camFunc[curCam.camType](scene, curCam);
|
||||||
|
thisObj.view.pos = vec3.scale([], vec3.transformMat4([], [0,0,0], mat4.invert([], thisObj.view.mv)), 1024)
|
||||||
return thisObj.view;
|
return thisObj.view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -141,8 +141,10 @@ window.MKDS_COLTYPE = new (function(){
|
||||||
this.PHYS_MAP[this.LOOP] = 11;
|
this.PHYS_MAP[this.LOOP] = 11;
|
||||||
|
|
||||||
//collision sound handlers
|
//collision sound handlers
|
||||||
|
//26 is blue water, 30 is white
|
||||||
|
//28 and 15 might be sand/dirt
|
||||||
|
|
||||||
var waterRoad = {drift: MKDS_COLSOUNDS.DRIFT_WATER, brake: MKDS_COLSOUNDS.BRAKE_WATER, land: MKDS_COLSOUNDS.LAND_WATER, drive: MKDS_COLSOUNDS.DRIVE_WATER};
|
var waterRoad = {drift: MKDS_COLSOUNDS.DRIFT_WATER, brake: MKDS_COLSOUNDS.BRAKE_WATER, land: MKDS_COLSOUNDS.LAND_WATER, drive: MKDS_COLSOUNDS.DRIVE_WATER, particle: 30};
|
||||||
|
|
||||||
this.SOUNDMAP = {
|
this.SOUNDMAP = {
|
||||||
0x00: //road
|
0x00: //road
|
||||||
|
@ -164,7 +166,7 @@ window.MKDS_COLTYPE = new (function(){
|
||||||
{drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_ASPHALT},
|
{drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_ASPHALT},
|
||||||
{drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_ASPHALT},
|
{drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_ASPHALT},
|
||||||
{drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_ASPHALT},
|
{drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_ASPHALT},
|
||||||
{drift: MKDS_COLSOUNDS.DRIFT_WATER, brake: MKDS_COLSOUNDS.BRAKE_WATER, land: MKDS_COLSOUNDS.LAND_WATERDEEP, drive: MKDS_COLSOUNDS.DRIVE_WATER},
|
{drift: MKDS_COLSOUNDS.DRIFT_WATER, brake: MKDS_COLSOUNDS.BRAKE_WATER, land: MKDS_COLSOUNDS.LAND_WATERDEEP, drive: MKDS_COLSOUNDS.DRIVE_WATER, particle: 30},
|
||||||
{drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_ASPHALT},
|
{drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_ASPHALT},
|
||||||
{},
|
{},
|
||||||
{},
|
{},
|
||||||
|
@ -187,27 +189,27 @@ window.MKDS_COLTYPE = new (function(){
|
||||||
|
|
||||||
0x03: //road 4
|
0x03: //road 4
|
||||||
[
|
[
|
||||||
{drift: MKDS_COLSOUNDS.DRIFT_SAND, brake: MKDS_COLSOUNDS.BRAKE_SAND , land: MKDS_COLSOUNDS.LAND_SAND, drive: MKDS_COLSOUNDS.DRIVE_SAND},
|
{drift: MKDS_COLSOUNDS.DRIFT_SAND, brake: MKDS_COLSOUNDS.BRAKE_SAND , land: MKDS_COLSOUNDS.LAND_SAND, drive: MKDS_COLSOUNDS.DRIVE_SAND, particle: 28},
|
||||||
{drift: MKDS_COLSOUNDS.DRIFT_DIRT, brake: MKDS_COLSOUNDS.BRAKE_DIRT, land: MKDS_COLSOUNDS.LAND_DIRT, drive: MKDS_COLSOUNDS.DRIVE_DIRT},
|
{drift: MKDS_COLSOUNDS.DRIFT_DIRT, brake: MKDS_COLSOUNDS.BRAKE_DIRT, land: MKDS_COLSOUNDS.LAND_DIRT, drive: MKDS_COLSOUNDS.DRIVE_DIRT, particle: 15},
|
||||||
|
|
||||||
{drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_GRASS, drive: MKDS_COLSOUNDS.DRIVE_GRASS},
|
{drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_GRASS, drive: MKDS_COLSOUNDS.DRIVE_GRASS, particle: 32},
|
||||||
|
|
||||||
{drift: MKDS_COLSOUNDS.DRIFT_SAND, brake: MKDS_COLSOUNDS.BRAKE_SAND, land: MKDS_COLSOUNDS.LAND_SAND, drive: MKDS_COLSOUNDS.DRIVE_SAND},
|
{drift: MKDS_COLSOUNDS.DRIFT_SAND, brake: MKDS_COLSOUNDS.BRAKE_SAND, land: MKDS_COLSOUNDS.LAND_SAND, drive: MKDS_COLSOUNDS.DRIVE_SAND, particle: 28},
|
||||||
{drift: MKDS_COLSOUNDS.DRIFT_SAND, brake: MKDS_COLSOUNDS.BRAKE_SAND, land: MKDS_COLSOUNDS.LAND_SAND, drive: MKDS_COLSOUNDS.DRIVE_SAND},
|
{drift: MKDS_COLSOUNDS.DRIFT_SAND, brake: MKDS_COLSOUNDS.BRAKE_SAND, land: MKDS_COLSOUNDS.LAND_SAND, drive: MKDS_COLSOUNDS.DRIVE_SAND, particle: 28},
|
||||||
{drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_SNOW}, //snow
|
{drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_SNOW, particle:112}, //snow
|
||||||
{},
|
{},
|
||||||
{}
|
{}
|
||||||
],
|
],
|
||||||
|
|
||||||
0x05: //road 5
|
0x05: //road 5
|
||||||
[
|
[
|
||||||
{drift: MKDS_COLSOUNDS.DRIFT_SAND, brake: MKDS_COLSOUNDS.BRAKE_SAND , land: MKDS_COLSOUNDS.LAND_SAND, drive: MKDS_COLSOUNDS.DRIVE_SAND},
|
{drift: MKDS_COLSOUNDS.DRIFT_SAND, brake: MKDS_COLSOUNDS.BRAKE_SAND , land: MKDS_COLSOUNDS.LAND_SAND, drive: MKDS_COLSOUNDS.DRIVE_SAND, particle: 28},
|
||||||
{drift: MKDS_COLSOUNDS.DRIFT_DIRT, brake: MKDS_COLSOUNDS.BRAKE_DIRT, land: MKDS_COLSOUNDS.LAND_DIRT, drive: MKDS_COLSOUNDS.DRIVE_DIRT},
|
{drift: MKDS_COLSOUNDS.DRIFT_DIRT, brake: MKDS_COLSOUNDS.BRAKE_DIRT, land: MKDS_COLSOUNDS.LAND_DIRT, drive: MKDS_COLSOUNDS.DRIVE_DIRT, particle: 15},
|
||||||
|
|
||||||
{drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_GRASS, drive: MKDS_COLSOUNDS.DRIVE_GRASS},
|
{drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_GRASS, drive: MKDS_COLSOUNDS.DRIVE_GRASS, particle: 32},
|
||||||
|
|
||||||
{drift: MKDS_COLSOUNDS.DRIFT_SAND, brake: MKDS_COLSOUNDS.BRAKE_SAND, land: MKDS_COLSOUNDS.LAND_SAND, drive: MKDS_COLSOUNDS.DRIVE_SAND},
|
{drift: MKDS_COLSOUNDS.DRIFT_SAND, brake: MKDS_COLSOUNDS.BRAKE_SAND, land: MKDS_COLSOUNDS.LAND_SAND, drive: MKDS_COLSOUNDS.DRIVE_SAND, particle: 28},
|
||||||
{drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_GRASS, drive: MKDS_COLSOUNDS.DRIVE_GRASS},
|
{drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_GRASS, drive: MKDS_COLSOUNDS.DRIVE_GRASS, particle: 32},
|
||||||
{},
|
{},
|
||||||
{},
|
{},
|
||||||
{}
|
{}
|
||||||
|
@ -216,7 +218,7 @@ window.MKDS_COLTYPE = new (function(){
|
||||||
0x06: //slippery
|
0x06: //slippery
|
||||||
[
|
[
|
||||||
{drift: MKDS_COLSOUNDS.DRIFT_ICE, brake: MKDS_COLSOUNDS.BRAKE_ICE, land:MKDS_COLSOUNDS.LAND_ICE},
|
{drift: MKDS_COLSOUNDS.DRIFT_ICE, brake: MKDS_COLSOUNDS.BRAKE_ICE, land:MKDS_COLSOUNDS.LAND_ICE},
|
||||||
{drift: MKDS_COLSOUNDS.DRIFT_MARSH, brake: MKDS_COLSOUNDS.BRAKE_MARSH, land:MKDS_COLSOUNDS.LAND_MARSH, drive: MKDS_COLSOUNDS.DRIVE_MARSH},
|
{drift: MKDS_COLSOUNDS.DRIFT_MARSH, brake: MKDS_COLSOUNDS.BRAKE_MARSH, land:MKDS_COLSOUNDS.LAND_MARSH, drive: MKDS_COLSOUNDS.DRIVE_MARSH, particle: 24},
|
||||||
{},
|
{},
|
||||||
{},
|
{},
|
||||||
{},
|
{},
|
||||||
|
|
|
@ -19,6 +19,7 @@ window.controlRaceCPU = function(nkm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.fetchInput = fetchInput;
|
this.fetchInput = fetchInput;
|
||||||
|
this.setRouteID = setRouteID;
|
||||||
|
|
||||||
var battleMode = (nkm.sections["EPAT"] == null);
|
var battleMode = (nkm.sections["EPAT"] == null);
|
||||||
|
|
||||||
|
@ -53,11 +54,30 @@ window.controlRaceCPU = function(nkm) {
|
||||||
|
|
||||||
var dist = vec3.dot(destNorm, kart.pos) + destConst;
|
var dist = vec3.dot(destNorm, kart.pos) + destConst;
|
||||||
if (dist < ePoi.pointSize) advancePoint();
|
if (dist < ePoi.pointSize) advancePoint();
|
||||||
|
if (ePath.loop) debugger;
|
||||||
|
|
||||||
destPoint = vec3.add([], ePoi.pos, vec3.scale([], vec3.lerp([], posOffset, destOff, offTrans), ePoi.pointSize));
|
destPoint = vec3.add([], ePoi.pos, vec3.scale([], vec3.lerp([], posOffset, destOff, offTrans), ePoi.pointSize));
|
||||||
var dirToPt = Math.atan2(destPoint[0]-kart.pos[0], kart.pos[2]-destPoint[2]);
|
var dirToPt = Math.atan2(destPoint[0]-kart.pos[0], kart.pos[2]-destPoint[2]);
|
||||||
|
|
||||||
var diff = dirDiff(dirToPt, kart.physicalDir);
|
var physDir = kart.physicalDir;
|
||||||
|
if (kart.physBasis) {
|
||||||
|
if (kart.physBasis.loop) {
|
||||||
|
return {
|
||||||
|
accel: true, //x
|
||||||
|
decel: false, //z
|
||||||
|
drift: false, //s
|
||||||
|
item: false, //a
|
||||||
|
|
||||||
|
//-1 to 1, intensity.
|
||||||
|
turn: 0,
|
||||||
|
airTurn: 0 //air excitebike turn, doesn't really have much function
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var forward = [Math.sin(physDir), 0, -Math.cos(physDir)];
|
||||||
|
vec3.transformMat4(forward, forward, kart.physBasis.mat);
|
||||||
|
var physDir = Math.atan2(forward[0], -forward[2]);
|
||||||
|
}
|
||||||
|
var diff = dirDiff(dirToPt, physDir);
|
||||||
var turn = Math.min(Math.max(-1, (diff*3)), 1);
|
var turn = Math.min(Math.max(-1, (diff*3)), 1);
|
||||||
|
|
||||||
offTrans += 1/240;
|
offTrans += 1/240;
|
||||||
|
@ -94,6 +114,11 @@ window.controlRaceCPU = function(nkm) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setRouteID(routeID) {
|
||||||
|
ePoiInd = routeID-1
|
||||||
|
advancePoint();
|
||||||
|
}
|
||||||
|
|
||||||
function advancePoint() {
|
function advancePoint() {
|
||||||
if (++ePoiInd < ePath.startInd+ePath.pathLen) {
|
if (++ePoiInd < ePath.startInd+ePath.pathLen) {
|
||||||
//next within this path
|
//next within this path
|
||||||
|
@ -102,10 +127,14 @@ window.controlRaceCPU = function(nkm) {
|
||||||
//advance to one of next possible paths
|
//advance to one of next possible paths
|
||||||
|
|
||||||
if (battleMode) {
|
if (battleMode) {
|
||||||
var pathInd = ((Math.random()>0.5 && ePath.source.length>0)?ePath.source:ePath.dest)[Math.floor(Math.random()*ePath.dest.length)];
|
var loc = (Math.random()>0.5 && ePath.source.length>0)?ePath.source:ePath.dest;
|
||||||
|
var pathInd = loc[Math.floor(Math.random()*loc.length)];
|
||||||
ePoiInd = pathInd;
|
ePoiInd = pathInd;
|
||||||
ePoi = points[ePoiInd];
|
var pt = points[ePoiInd];
|
||||||
recomputePath();
|
if (pt != null) {
|
||||||
|
ePoi = pt;
|
||||||
|
recomputePath();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
var pathInd = ePath.dest[Math.floor(Math.random()*ePath.dest.length)];
|
var pathInd = ePath.dest[Math.floor(Math.random()*ePath.dest.length)];
|
||||||
ePath = paths[pathInd];
|
ePath = paths[pathInd];
|
||||||
|
|
|
@ -18,6 +18,7 @@ window.IngameRes = function(rom) {
|
||||||
|
|
||||||
this.Race = new narc(lz77.decompress(rom.getFile("/data/Scene/Race.carc"))); //contains lakitu, count, various graphics
|
this.Race = new narc(lz77.decompress(rom.getFile("/data/Scene/Race.carc"))); //contains lakitu, count, various graphics
|
||||||
this.RaceLoc = new narc(lz77.decompress(rom.getFile("/data/Scene/Race_us.carc"))); //contains lakitu lap signs, START, YOU WIN etc. some of these will be replaced by hi res graphics by default.
|
this.RaceLoc = new narc(lz77.decompress(rom.getFile("/data/Scene/Race_us.carc"))); //contains lakitu lap signs, START, YOU WIN etc. some of these will be replaced by hi res graphics by default.
|
||||||
|
this.RaceEffect = new spa(r.MainEffect.getFile("RaceEffect.spa"));
|
||||||
|
|
||||||
this.MainFont = new nftr(r.Main2D.getFile("marioFont.NFTR"));
|
this.MainFont = new nftr(r.Main2D.getFile("marioFont.NFTR"));
|
||||||
//debugger;
|
//debugger;
|
||||||
|
@ -30,20 +31,25 @@ window.IngameRes = function(rom) {
|
||||||
"koura_w" /*blue shell item rep*/, "f_box", "killer" /*bullet bill*/
|
"koura_w" /*blue shell item rep*/, "f_box", "killer" /*bullet bill*/
|
||||||
]
|
]
|
||||||
|
|
||||||
|
//order
|
||||||
|
//donkey, toad, bowser?, luigi, mario, peach, wario, yoshi, daisy, waluigi, dry bones (karon), robo, heyho
|
||||||
|
var toSoundOff = [
|
||||||
|
4, 0, 1, 2, 5, 6, 7, 3, 10, 8, 9, 11, 12
|
||||||
|
];
|
||||||
|
|
||||||
var charNames = [
|
var charNames = [
|
||||||
"mario", "donkey", "kinopio", "koopa", "peach", "wario", "yoshi", "luigi", "karon", "daisy", "waluigi", "robo", "heyho"
|
"mario", "donkey", "kinopio", "koopa", "peach", "wario", "yoshi", "luigi", "karon", "daisy", "waluigi", "robo", "heyho"
|
||||||
]
|
];
|
||||||
|
|
||||||
var charAbbrv = [
|
var charAbbrv = [
|
||||||
"MR", "DK", "KO", "KP", "PC", "WR", "YS", "LG", "KA", "DS", "WL", "RB", "HH"
|
"MR", "DK", "KO", "KP", "PC", "WR", "YS", "LG", "KA", "DS", "WL", "RB", "HH"
|
||||||
]
|
];
|
||||||
|
|
||||||
var tireName = ["kart_tire_L", "kart_tire_M", "kart_tire_S"];
|
var tireName = ["kart_tire_L", "kart_tire_M", "kart_tire_S"];
|
||||||
|
|
||||||
var characters = [];
|
var characters = [];
|
||||||
var karts = [];
|
var karts = [];
|
||||||
|
|
||||||
var test = new spa(r.MainEffect.getFile("RaceEffect.spa"));
|
|
||||||
loadItems();
|
loadItems();
|
||||||
loadTires();
|
loadTires();
|
||||||
|
|
||||||
|
@ -75,6 +81,7 @@ window.IngameRes = function(rom) {
|
||||||
loseA: new nsbca(r.KartModelSub.getFile(base+"_lose.nsbca")),
|
loseA: new nsbca(r.KartModelSub.getFile(base+"_lose.nsbca")),
|
||||||
spinA: new nsbca(r.KartModelSub.getFile(base+"_spin.nsbca")),
|
spinA: new nsbca(r.KartModelSub.getFile(base+"_spin.nsbca")),
|
||||||
winA: new nsbca(r.KartModelSub.getFile(base+"_win.nsbca")),
|
winA: new nsbca(r.KartModelSub.getFile(base+"_win.nsbca")),
|
||||||
|
sndOff: toSoundOff[ind]*14,
|
||||||
}
|
}
|
||||||
characters[ind] = obj;
|
characters[ind] = obj;
|
||||||
return characters[ind];
|
return characters[ind];
|
||||||
|
|
|
@ -165,6 +165,11 @@ window.courseScene = function(mainNarc, texNarc, music, chars, options, gameRes)
|
||||||
vec3.scale(targ, targ, 1/1024);
|
vec3.scale(targ, targ, 1/1024);
|
||||||
mat4.mul(scn.shadMat, mat4.ortho(mat4.create(), targ[0]-shadres, targ[0]+shadres, targ[1]-shadres, targ[1]+shadres, -targ[2]-2.5, -targ[2]+2.5), scn.lightMat);
|
mat4.mul(scn.shadMat, mat4.ortho(mat4.create(), targ[0]-shadres, targ[0]+shadres, targ[1]-shadres, targ[1]+shadres, -targ[2]-2.5, -targ[2]+2.5), scn.lightMat);
|
||||||
|
|
||||||
|
var places = [];
|
||||||
|
for (var i=0; i<scn.karts.length; i++) { places.push(scn.karts[i]); }
|
||||||
|
places.sort(function(a, b) {return b.getPosition() - a.getPosition()});
|
||||||
|
for (var i=0; i<places.length; i++) { places[i].placement = i+1; };
|
||||||
|
|
||||||
for (var i=0; i<scn.karts.length; i++) {
|
for (var i=0; i<scn.karts.length; i++) {
|
||||||
var ent = scn.karts[i];
|
var ent = scn.karts[i];
|
||||||
if (ent.active) ent.update(scn);
|
if (ent.active) ent.update(scn);
|
||||||
|
@ -291,9 +296,9 @@ window.courseScene = function(mainNarc, texNarc, music, chars, options, gameRes)
|
||||||
// the thresholds for different win sounds and music
|
// the thresholds for different win sounds and music
|
||||||
// thresh, goalsound, goalmusic, goalpostmusic
|
// thresh, goalsound, goalmusic, goalpostmusic
|
||||||
var finishPercents = [
|
var finishPercents = [
|
||||||
[0, 66, 46, 58],
|
[0, 66, 46, 58, 9],
|
||||||
[0.5, 66, 47, 56],
|
[0.5, 66, 47, 56, 10],
|
||||||
[1.1, 67, 48, 57]
|
[1.1, 67, 48, 57, 11]
|
||||||
]
|
]
|
||||||
|
|
||||||
function lapAdvance(kart) {
|
function lapAdvance(kart) {
|
||||||
|
@ -309,20 +314,21 @@ window.courseScene = function(mainNarc, texNarc, music, chars, options, gameRes)
|
||||||
else if (kart.lapNumber == 4) {
|
else if (kart.lapNumber == 4) {
|
||||||
var finishTuple = [];
|
var finishTuple = [];
|
||||||
for (var i=0; i<finishPercents.length; i++) {
|
for (var i=0; i<finishPercents.length; i++) {
|
||||||
if (finishPercents[i][0] > winPercent) continue;
|
|
||||||
finishTuple = finishPercents[i];
|
finishTuple = finishPercents[i];
|
||||||
|
if (finishPercents[i][0] >= winPercent) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
kart.controller = new controlRaceCPU(scn.nkm, {});
|
kart.controller = new controlRaceCPU(scn.nkm, {});
|
||||||
kart.controller.setKart(kart);
|
kart.controller.setKart(kart);
|
||||||
|
|
||||||
kart.anim.setAnim(winPercent>0.5?kart.charRes.LoseA:kart.charRes.winA);
|
kart.anim.setAnim(winPercent>0.5?kart.charRes.loseA:kart.charRes.winA);
|
||||||
kart.animMode = "raceEnd";
|
kart.animMode = "raceEnd";
|
||||||
|
|
||||||
scn.camera = (new cameraSpectator(kart, scn));
|
scn.camera = (new cameraSpectator(kart, scn));
|
||||||
nitroAudio.playSound(finishTuple[1], {volume:2}, 0);
|
nitroAudio.playSound(finishTuple[1], {volume:2}, 0);
|
||||||
nitroAudio.playSound(finishTuple[2], {volume:2}, null);
|
nitroAudio.playSound(finishTuple[2], {volume:2}, null);
|
||||||
nitroAudio.instaKill(scn.musicPlayer);
|
nitroAudio.instaKill(scn.musicPlayer);
|
||||||
|
kart.playCharacterSound(finishTuple[4], 2);
|
||||||
musicRestartTimer = 0;
|
musicRestartTimer = 0;
|
||||||
musicRestart = 7.5*60;
|
musicRestart = 7.5*60;
|
||||||
musicRestartType = 1;
|
musicRestartType = 1;
|
||||||
|
|
|
@ -179,7 +179,7 @@ window.ObjDecor = function(obji, scene) {
|
||||||
forceBill = false;
|
forceBill = false;
|
||||||
return {mdl:[{nsbmd:"choropu.nsbmd"}], other:[null, null, "choropu.nsbtp"]}; //has nsbtp
|
return {mdl:[{nsbmd:"choropu.nsbmd"}], other:[null, null, "choropu.nsbtp"]}; //has nsbtp
|
||||||
case 0x019B: //cheep cheep (bouncing)
|
case 0x019B: //cheep cheep (bouncing)
|
||||||
return {mdl:[{nsbmd:"pukupuku.nsbmd"}], other:[null, null, "pukupuku.nsbtp"]}; //has nsbtp
|
return {mdl:[{nsbmd:"pukupuku.nsbmd"}]}; //has nsbtp //, other:[null, null, "pukupuku.nsbtp"]
|
||||||
case 0x019D: //snowman
|
case 0x019D: //snowman
|
||||||
return {mdl:[{nsbmd:"sman_top.nsbmd"}, {nsbmd:"sman_bottom.nsbmd"}]};
|
return {mdl:[{nsbmd:"sman_top.nsbmd"}, {nsbmd:"sman_bottom.nsbmd"}]};
|
||||||
case 0x019E: //trunk with bats
|
case 0x019E: //trunk with bats
|
||||||
|
|
|
@ -45,6 +45,7 @@ window.ItemBox = function(obji, scene) {
|
||||||
for (var j=0; j<10; j++) {
|
for (var j=0; j<10; j++) {
|
||||||
scene.particles.push(new ItemShard(scene, ok, res.mdl[2]));
|
scene.particles.push(new ItemShard(scene, ok, res.mdl[2]));
|
||||||
}
|
}
|
||||||
|
scene.particles.push(new NitroEmitter(scene, ok, 47));
|
||||||
t.mode = 1;
|
t.mode = 1;
|
||||||
t.time = 0;
|
t.time = 0;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -21,6 +21,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||||
|
|
||||||
var params = scene.gameRes.kartPhys.karts[kartN];
|
var params = scene.gameRes.kartPhys.karts[kartN];
|
||||||
var offsets = scene.gameRes.kartOff.karts[kartN];
|
var offsets = scene.gameRes.kartOff.karts[kartN];
|
||||||
|
this.wheelClass = (offsets.name[10] == "L")?2:((offsets.name[10] == "M")?1:0);
|
||||||
|
|
||||||
this.local = controller.local;
|
this.local = controller.local;
|
||||||
this.active = true;
|
this.active = true;
|
||||||
|
@ -66,12 +67,20 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||||
this.drawWheels = drawWheels;
|
this.drawWheels = drawWheels;
|
||||||
this.drawChar = drawChar;
|
this.drawChar = drawChar;
|
||||||
|
|
||||||
|
this.getPosition = getPosition;
|
||||||
|
this.playCharacterSound = playCharacterSound;
|
||||||
|
|
||||||
this.trackAttach = null; //a normal for the kart to attach to (loop)
|
this.trackAttach = null; //a normal for the kart to attach to (loop)
|
||||||
this.boostMT = 0;
|
this.boostMT = 0;
|
||||||
this.boostNorm = 0;
|
this.boostNorm = 0;
|
||||||
|
|
||||||
this.kartColVel = vec3.create();
|
this.kartColVel = vec3.create();
|
||||||
this.kartColTimer = 0;
|
this.kartColTimer = 0;
|
||||||
|
this.kartWallTimer = 0;
|
||||||
|
this.charSoundTimer = 0;
|
||||||
|
|
||||||
|
this.placement = 0;
|
||||||
|
this.lastPlacement = 0;
|
||||||
|
|
||||||
var charRes = scene.gameRes.getChar(charN);
|
var charRes = scene.gameRes.getChar(charN);
|
||||||
var kartRes = scene.gameRes.getKart(kartN);
|
var kartRes = scene.gameRes.getKart(kartN);
|
||||||
|
@ -95,14 +104,24 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||||
this.lastInput = null;
|
this.lastInput = null;
|
||||||
|
|
||||||
//race statistics
|
//race statistics
|
||||||
this.lapNumber = 0;
|
this.lapNumber = 1;
|
||||||
this.passedKTP2 = false;
|
this.passedKTP2 = false;
|
||||||
this.checkPointNumber = 0;
|
this.checkPointNumber = 0;
|
||||||
|
this.OOB = 0;
|
||||||
|
|
||||||
|
this.wheelParticles = [
|
||||||
|
new NitroEmitter(scene, k, -1, [1, 1.5, -1]),
|
||||||
|
new NitroEmitter(scene, k, -1, [-1, 1.5, -1])
|
||||||
|
];
|
||||||
|
|
||||||
|
scene.particles.push(this.wheelParticles[0]);
|
||||||
|
scene.particles.push(this.wheelParticles[1]);
|
||||||
|
|
||||||
var nkm = scene.nkm;
|
var nkm = scene.nkm;
|
||||||
var startLine = nkm.sections["KTPS"].entries[0];
|
var startLine = nkm.sections["KTPS"].entries[0];
|
||||||
var passLine = nkm.sections["KTP2"].entries[0];
|
var passLine = nkm.sections["KTP2"].entries[0];
|
||||||
var checkpoints = nkm.sections["CPOI"].entries;
|
var checkpoints = nkm.sections["CPOI"].entries;
|
||||||
var respawns = nkm.sections["CPOI"].entries;
|
var respawns = nkm.sections["KTPJ"].entries;
|
||||||
var futureChecks = [1];
|
var futureChecks = [1];
|
||||||
|
|
||||||
var hitGroundAnim = [ //length 13, on y axis
|
var hitGroundAnim = [ //length 13, on y axis
|
||||||
|
@ -193,6 +212,10 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||||
mat4.scale(wmat, wmat, [scale, scale, scale]);
|
mat4.scale(wmat, wmat, [scale, scale, scale]);
|
||||||
if (i<2) mat4.rotateY(wmat, wmat, ((k.driveAnimF-14)/14)*Math.PI/6);
|
if (i<2) mat4.rotateY(wmat, wmat, ((k.driveAnimF-14)/14)*Math.PI/6);
|
||||||
mat4.rotateX(wmat, wmat, wheelTurn);
|
mat4.rotateX(wmat, wmat, wheelTurn);
|
||||||
|
|
||||||
|
if (i>1) {
|
||||||
|
k.wheelParticles[i-2].offset = vec3.scale(k.wheelParticles[i-2].offset, vec3.add(k.wheelParticles[i-2].offset, offsets.wheels[i], [k.wheelClass*(i-2.5)*-2, (-params.colRadius)-k.wheelClass*2, 0]), 1/16);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var scale = 16;
|
var scale = 16;
|
||||||
|
@ -262,7 +285,20 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||||
drawChar(view, pMatrix);
|
drawChar(view, pMatrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
k.lWheelParticle = null;
|
||||||
|
|
||||||
function update(scene) {
|
function update(scene) {
|
||||||
|
if (k.placement != k.lastPlacement) {
|
||||||
|
if (k.placement < k.lastPlacement) {
|
||||||
|
if (k.charSoundTimer == 0) {
|
||||||
|
playCharacterSound(5);
|
||||||
|
k.charSoundTimer = 60;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
k.lastPlacement = k.placement;
|
||||||
|
}
|
||||||
|
|
||||||
var lastPos = vec3.clone(k.pos);
|
var lastPos = vec3.clone(k.pos);
|
||||||
updateMat = true;
|
updateMat = true;
|
||||||
|
|
||||||
|
@ -314,7 +350,8 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||||
sounds.boost = null;
|
sounds.boost = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onGround && k.speed > 0.5) {
|
var isMoving = onGround && k.speed > 0.5;
|
||||||
|
if (isMoving) {
|
||||||
if (lastCollided != sounds.lastTerrain || lastBE != sounds.lastBE || sounds.drive == null) {
|
if (lastCollided != sounds.lastTerrain || lastBE != sounds.lastBE || sounds.drive == null) {
|
||||||
if (sounds.drive != null) nitroAudio.kill(sounds.drive);
|
if (sounds.drive != null) nitroAudio.kill(sounds.drive);
|
||||||
if (lastColSounds.drive != null) {
|
if (lastColSounds.drive != null) {
|
||||||
|
@ -337,7 +374,10 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||||
} else {
|
} else {
|
||||||
if (sounds.drift != null) { nitroAudio.kill(sounds.drift); sounds.drift = null; }
|
if (sounds.drift != null) { nitroAudio.kill(sounds.drift); sounds.drift = null; }
|
||||||
if (sounds.drive != null) { nitroAudio.kill(sounds.drive); sounds.drive = null; }
|
if (sounds.drive != null) { nitroAudio.kill(sounds.drive); sounds.drive = null; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
k.wheelParticles[0].pause = !isMoving;
|
||||||
|
k.wheelParticles[1].pause = !isMoving;
|
||||||
|
|
||||||
//end sound update
|
//end sound update
|
||||||
|
|
||||||
|
@ -346,25 +386,55 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||||
} else if (k.cannon != null) { //when cannon is active, we fly forward at max move speed until we get to the cannon point.
|
} else if (k.cannon != null) { //when cannon is active, we fly forward at max move speed until we get to the cannon point.
|
||||||
var c = scene.nkm.sections["KTPC"].entries[k.cannon];
|
var c = scene.nkm.sections["KTPC"].entries[k.cannon];
|
||||||
|
|
||||||
var mat = mat4.create();
|
if (c.id2 != 0) {
|
||||||
mat4.rotateY(mat, mat, c.angle[1]*(Math.PI/180));
|
var c2 = scene.nkm.sections["KTPC"].entries[c.id2];
|
||||||
mat4.rotateX(mat, mat, c.angle[0]*(-Math.PI/180));
|
c = c2;
|
||||||
|
|
||||||
var forward = [0, 0, 1];
|
var mat = mat4.create();
|
||||||
var up = [0, 1, 0];
|
mat4.rotateY(mat, mat, c.angle[1]*(Math.PI/180));
|
||||||
|
mat4.rotateX(mat, mat, c.angle[0]*(-Math.PI/180));
|
||||||
|
|
||||||
k.vel = vec3.scale([], vec3.transformMat4(forward, forward, mat), MAXSPEED);
|
k.pos = vec3.clone(c2.pos);
|
||||||
k.speed = MAXSPEED;
|
vec3.add(k.pos, k.pos, vec3.transformMat4([], [0,16,16], mat));
|
||||||
vec3.add(k.pos, k.pos, k.vel);
|
|
||||||
k.physicalDir = (180-c.angle[1])*(Math.PI/180);
|
|
||||||
k.angle = k.physicalDir;
|
|
||||||
k.kartTargetNormal = vec3.transformMat4(up, up, mat);
|
|
||||||
|
|
||||||
var planeConst = -vec3.dot(c.pos, forward);
|
k.physicalDir = (180-c2.angle[1])*(Math.PI/180);
|
||||||
var cannonDist = vec3.dot(k.pos, forward) + planeConst;
|
k.angle = k.physicalDir;
|
||||||
if (cannonDist > 0) k.cannon = null;
|
k.cannon = null;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
var mat = mat4.create();
|
||||||
|
mat4.rotateY(mat, mat, c.angle[1]*(Math.PI/180));
|
||||||
|
mat4.rotateX(mat, mat, c.angle[0]*(-Math.PI/180));
|
||||||
|
|
||||||
|
var forward = [0, 0, 1];
|
||||||
|
var up = [0, 1, 0];
|
||||||
|
|
||||||
|
k.vel = vec3.scale([], vec3.transformMat4(forward, forward, mat), MAXSPEED);
|
||||||
|
k.speed = Math.min(k.speed+1, MAXSPEED);
|
||||||
|
vec3.add(k.pos, k.pos, k.vel);
|
||||||
|
k.physicalDir = (180-c.angle[1])*(Math.PI/180);
|
||||||
|
k.angle = k.physicalDir;
|
||||||
|
k.kartTargetNormal = vec3.transformMat4(up, up, mat);
|
||||||
|
|
||||||
|
var planeConst = -vec3.dot(c.pos, forward);
|
||||||
|
var cannonDist = vec3.dot(k.pos, forward) + planeConst;
|
||||||
|
if (cannonDist > 0) k.cannon = null;
|
||||||
|
}
|
||||||
} else { //default kart mode
|
} else { //default kart mode
|
||||||
|
|
||||||
|
if (k.OOB > 0) {
|
||||||
|
playCharacterSound(0);
|
||||||
|
var current = checkpoints[k.checkPointNumber];
|
||||||
|
var respawn = respawns[current.respawn];
|
||||||
|
k.physicalDir = (180-respawn.angle[1])*(Math.PI/180);
|
||||||
|
k.angle = k.physicalDir;
|
||||||
|
k.speed = 0;
|
||||||
|
k.vel = vec3.create();
|
||||||
|
k.pos = vec3.clone(respawn.pos);
|
||||||
|
vec3.add(k.pos, k.pos, [0,16,0]);
|
||||||
|
if (k.controller.setRouteID != null) k.controller.setRouteID(respawn.id1);
|
||||||
|
k.OOB = 0;
|
||||||
|
}
|
||||||
var groundEffect = 0;
|
var groundEffect = 0;
|
||||||
if (lastCollided != -1) {
|
if (lastCollided != -1) {
|
||||||
groundEffect = MKDS_COLTYPE.PHYS_MAP[lastCollided];
|
groundEffect = MKDS_COLTYPE.PHYS_MAP[lastCollided];
|
||||||
|
@ -402,6 +472,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||||
if ((onGround) && !(input.accel && input.drift && (k.speed > 2 || !k.driftLanded))) {
|
if ((onGround) && !(input.accel && input.drift && (k.speed > 2 || !k.driftLanded))) {
|
||||||
//end drift, execute miniturbo
|
//end drift, execute miniturbo
|
||||||
k.drifting = false;
|
k.drifting = false;
|
||||||
|
clearWheelParticles();
|
||||||
if (sounds.powerslide != null) {
|
if (sounds.powerslide != null) {
|
||||||
nitroAudio.instaKill(sounds.powerslide);
|
nitroAudio.instaKill(sounds.powerslide);
|
||||||
sounds.powerslide = null;
|
sounds.powerslide = null;
|
||||||
|
@ -434,11 +505,15 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||||
|
|
||||||
if (onGround) {
|
if (onGround) {
|
||||||
if (!k.driftLanded) {
|
if (!k.driftLanded) {
|
||||||
if (k.driftMode == 0) k.drifting = false;
|
if (k.driftMode == 0) {
|
||||||
|
k.drifting = false;
|
||||||
|
clearWheelParticles();
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
k.driftPSMode = 0;
|
k.driftPSMode = 0;
|
||||||
k.driftPSTick = 0;
|
k.driftPSTick = 0;
|
||||||
k.driftLanded = true;
|
k.driftLanded = true;
|
||||||
|
if (k.drifting) setWheelParticles(20, 1); //20 = smoke, 1 = drift priority
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (k.drifting) {
|
if (k.drifting) {
|
||||||
|
@ -467,7 +542,8 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||||
k.driftPSMode++;
|
k.driftPSMode++;
|
||||||
k.driftPSTick = 1;
|
k.driftPSTick = 1;
|
||||||
|
|
||||||
//play blue spark sound
|
//play blue spark sound, flare
|
||||||
|
setWheelParticles(126, 2); //126 = blue flare, 2 = flare priority
|
||||||
var blue = nitroAudio.playSound(210, {}, 0, k);
|
var blue = nitroAudio.playSound(210, {}, 0, k);
|
||||||
blue.gainN.gain.value = 2;
|
blue.gainN.gain.value = 2;
|
||||||
|
|
||||||
|
@ -487,6 +563,8 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||||
k.driftPSMode++;
|
k.driftPSMode++;
|
||||||
k.driftPSTick = 1;
|
k.driftPSTick = 1;
|
||||||
//play red sparks sound, full MT!
|
//play red sparks sound, full MT!
|
||||||
|
setWheelParticles(22, 2); //22 = red flare, 2 = flare priority
|
||||||
|
setWheelParticles(17, 1); //17 = red mt, 1 = drift priority
|
||||||
sounds.powerslide = nitroAudio.playSound(209, {}, 0, k);
|
sounds.powerslide = nitroAudio.playSound(209, {}, 0, k);
|
||||||
sounds.powerslide.gainN.gain.value = 2;
|
sounds.powerslide.gainN.gain.value = 2;
|
||||||
} else k.driftPSTick = 0;
|
} else k.driftPSTick = 0;
|
||||||
|
@ -562,6 +640,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||||
|
|
||||||
if (!onGround) {
|
if (!onGround) {
|
||||||
this.kartTargetNormal = [0, 1, 0];
|
this.kartTargetNormal = [0, 1, 0];
|
||||||
|
if (k.physBasis != null) vec3.transformMat4(this.kartTargetNormal,this.kartTargetNormal,k.physBasis.mat);
|
||||||
vec3.add(k.vel, k.vel, k.gravity)
|
vec3.add(k.vel, k.vel, k.gravity)
|
||||||
if (k.ylock >= 0) {
|
if (k.ylock >= 0) {
|
||||||
ylvel += k.gravity[1];
|
ylvel += k.gravity[1];
|
||||||
|
@ -584,6 +663,8 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (k.kartColTimer > 0) k.kartColTimer--;
|
if (k.kartColTimer > 0) k.kartColTimer--;
|
||||||
|
if (k.kartWallTimer > 0) k.kartWallTimer--;
|
||||||
|
if (k.charSoundTimer > 0) k.charSoundTimer--;
|
||||||
|
|
||||||
wheelTurn += k.speed/16;
|
wheelTurn += k.speed/16;
|
||||||
wheelTurn = fixDir(wheelTurn);
|
wheelTurn = fixDir(wheelTurn);
|
||||||
|
@ -602,7 +683,15 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||||
|
|
||||||
var steps = 0;
|
var steps = 0;
|
||||||
var remainingT = 1;
|
var remainingT = 1;
|
||||||
var velSeg = vec3.clone(k.vel);
|
var baseVel = k.vel;
|
||||||
|
if (k.physBasis != null) {
|
||||||
|
if (k.physBasis.time-- < 0) exitBasis();
|
||||||
|
else {
|
||||||
|
baseVel = vec3.transformMat4([], baseVel, k.physBasis.mat);
|
||||||
|
k.vel[1] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var velSeg = vec3.clone(baseVel);
|
||||||
var posSeg = vec3.clone(k.pos);
|
var posSeg = vec3.clone(k.pos);
|
||||||
var ignoreList = [];
|
var ignoreList = [];
|
||||||
while (steps++ < 10 && remainingT > 0.01) {
|
while (steps++ < 10 && remainingT > 0.01) {
|
||||||
|
@ -611,7 +700,10 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||||
colResponse(posSeg, velSeg, result, ignoreList)
|
colResponse(posSeg, velSeg, result, ignoreList)
|
||||||
remainingT -= result.t;
|
remainingT -= result.t;
|
||||||
if (remainingT > 0.01) {
|
if (remainingT > 0.01) {
|
||||||
velSeg = vec3.scale(vec3.create(), k.vel, remainingT);
|
if (k.physBasis != null) {
|
||||||
|
baseVel = vec3.transformMat4([], k.vel, k.physBasis.mat);
|
||||||
|
}
|
||||||
|
velSeg = vec3.scale(vec3.create(), baseVel, remainingT);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
vec3.add(posSeg, posSeg, velSeg);
|
vec3.add(posSeg, posSeg, velSeg);
|
||||||
|
@ -642,6 +734,43 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||||
positionChanged(lastPos, k.pos);
|
positionChanged(lastPos, k.pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function playCharacterSound(sound, volume) {
|
||||||
|
//0 - hit
|
||||||
|
//1 - hit spin
|
||||||
|
//2 - hit ?? hit grnd
|
||||||
|
//3 - hit banana? race start?
|
||||||
|
//4 - hit spin?
|
||||||
|
//5 - good pass?
|
||||||
|
//6 - good OK!
|
||||||
|
//7 - use item
|
||||||
|
//8 - hit someone?
|
||||||
|
//9 = win
|
||||||
|
//10 = alright
|
||||||
|
//11 = bad
|
||||||
|
//12 = good record
|
||||||
|
//13 = bad record
|
||||||
|
if (volume == null) volume = 1;
|
||||||
|
nitroAudio.playSound(sound + charRes.sndOff, {volume: 2*volume}, 2, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearWheelParticles(prio) {
|
||||||
|
for (var i=0; i<2; i++) {
|
||||||
|
if (prio == null) {
|
||||||
|
//clear all specials
|
||||||
|
k.wheelParticles[i].clearEmitter(1); //drift mode
|
||||||
|
//k.wheelParticles[i].clearEmitter(2); //drift flare (blue mt, red big flash)
|
||||||
|
} else {
|
||||||
|
k.wheelParticles[i].clearEmitter(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setWheelParticles(id, prio) {
|
||||||
|
for (var i=0; i<2; i++) {
|
||||||
|
k.wheelParticles[i].setEmitter(id, prio);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function genFutureChecks() {
|
function genFutureChecks() {
|
||||||
//all future points that
|
//all future points that
|
||||||
var chosen = {}
|
var chosen = {}
|
||||||
|
@ -661,6 +790,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||||
|
|
||||||
function positionChanged(oldPos, pos) {
|
function positionChanged(oldPos, pos) {
|
||||||
//crossed into new checkpoint?
|
//crossed into new checkpoint?
|
||||||
|
if (checkpoints.length == 0) return;
|
||||||
for (var i=0; i<futureChecks.length; i++) {
|
for (var i=0; i<futureChecks.length; i++) {
|
||||||
var check = checkpoints[futureChecks[i]];
|
var check = checkpoints[futureChecks[i]];
|
||||||
var distOld = vec2.sub([], [check.x1, check.z1], [oldPos[0], oldPos[2]]);
|
var distOld = vec2.sub([], [check.x1, check.z1], [oldPos[0], oldPos[2]]);
|
||||||
|
@ -685,11 +815,21 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||||
k.lapNumber++;
|
k.lapNumber++;
|
||||||
k.checkPointNumber = 0;
|
k.checkPointNumber = 0;
|
||||||
k.passedKTP2 = 0;
|
k.passedKTP2 = 0;
|
||||||
|
futureChecks = [1];
|
||||||
scene.lapAdvance(k);
|
scene.lapAdvance(k);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getPosition() {
|
||||||
|
if (futureChecks.length == 0) return 0;
|
||||||
|
var check = checkpoints[futureChecks[0]];
|
||||||
|
var dist = vec2.sub([], [check.x1, check.z1], [k.pos[0], k.pos[2]]);
|
||||||
|
var dot = vec2.dot(dist, [check.sinus, check.cosinus]);
|
||||||
|
|
||||||
|
return k.checkPointNumber + (1-(Math.abs(dot)/(0xFFFF))) + k.lapNumber*checkpoints.length;
|
||||||
|
}
|
||||||
|
|
||||||
function forwardCrossedKTP(ktp, oldPos, pos) {
|
function forwardCrossedKTP(ktp, oldPos, pos) {
|
||||||
var distOld = vec2.sub([], [ktp.pos[0], ktp.pos[2]], [oldPos[0], oldPos[2]]);
|
var distOld = vec2.sub([], [ktp.pos[0], ktp.pos[2]], [oldPos[0], oldPos[2]]);
|
||||||
var dist = vec2.sub([], [ktp.pos[0], ktp.pos[2]], [pos[0], pos[2]]);
|
var dist = vec2.sub([], [ktp.pos[0], ktp.pos[2]], [pos[0], pos[2]]);
|
||||||
|
@ -768,7 +908,13 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||||
function buildBasis() {
|
function buildBasis() {
|
||||||
//order y, x, z
|
//order y, x, z
|
||||||
var dir = k.physicalDir+k.driftOff+(Math.sin((COLBOUNCE_TIME-k.kartColTimer)/3)*(Math.PI/6)*(k.kartColTimer/COLBOUNCE_TIME));
|
var dir = k.physicalDir+k.driftOff+(Math.sin((COLBOUNCE_TIME-k.kartColTimer)/3)*(Math.PI/6)*(k.kartColTimer/COLBOUNCE_TIME));
|
||||||
var basis = gramShmidt(k.kartNormal, [Math.cos(dir), 0, Math.sin(dir)], [Math.sin(dir), 0, -Math.cos(dir)]);
|
var forward = [Math.sin(dir), 0, -Math.cos(dir)];
|
||||||
|
var side = [Math.cos(dir), 0, Math.sin(dir)];
|
||||||
|
if (k.physBasis != null) {
|
||||||
|
vec3.transformMat4(forward, forward, k.physBasis.mat);
|
||||||
|
vec3.transformMat4(side, side, k.physBasis.mat);
|
||||||
|
}
|
||||||
|
var basis = gramShmidt(k.kartNormal, side, forward);
|
||||||
var temp = basis[0];
|
var temp = basis[0];
|
||||||
basis[0] = basis[1];
|
basis[0] = basis[1];
|
||||||
basis[1] = temp; //todo: cleanup
|
basis[1] = temp; //todo: cleanup
|
||||||
|
@ -781,6 +927,56 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function enterBasis(normal) {
|
||||||
|
//establish a new basis for the kart velocity based on this normal.
|
||||||
|
//used by looping and sticky track surface types.
|
||||||
|
|
||||||
|
//first let's get the forward direction in our current basis
|
||||||
|
|
||||||
|
var dir = k.angle;
|
||||||
|
var forward, side;
|
||||||
|
if (k.physBasis != null) {
|
||||||
|
forward = vec3.transformMat4([], [- Math.sin(dir), 0, Math.cos(dir)], k.physBasis.mat);
|
||||||
|
side = vec3.transformMat4([], [Math.cos(dir), 0, Math.sin(dir)], k.physBasis.mat);
|
||||||
|
} else {
|
||||||
|
forward = [-Math.sin(dir), 0, Math.cos(dir)];
|
||||||
|
side = [Math.cos(dir), 0, Math.sin(dir)];
|
||||||
|
}
|
||||||
|
|
||||||
|
var basis = gramShmidt(normal, side, forward);
|
||||||
|
var temp = basis[0];
|
||||||
|
basis[0] = basis[1];
|
||||||
|
basis[1] = temp; //todo: cleanup
|
||||||
|
var m4 = [
|
||||||
|
basis[0][0], basis[0][1], basis[0][2], 0,
|
||||||
|
basis[1][0], basis[1][1], basis[1][2], 0,
|
||||||
|
basis[2][0], basis[2][1], basis[2][2], 0,
|
||||||
|
0, 0, 0, 1
|
||||||
|
];
|
||||||
|
|
||||||
|
k.physicalDir = dirDiff(k.physicalDir, k.angle);
|
||||||
|
k.angle = 0; //our front direction is now aligned with z.
|
||||||
|
k.vel = [Math.sin(k.angle)*k.speed, k.vel[1], -Math.cos(k.angle)*k.speed];
|
||||||
|
|
||||||
|
k.physBasis = {
|
||||||
|
mat: m4,
|
||||||
|
inv: mat4.invert([], m4),
|
||||||
|
time: 15,
|
||||||
|
loop: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function exitBasis() {
|
||||||
|
//return to a normal y up, z forward basis.
|
||||||
|
|
||||||
|
var v = vec3.transformMat4([], k.vel, k.physBasis.mat);
|
||||||
|
k.physicalDir = dirDiff(k.physicalDir, k.angle);
|
||||||
|
k.angle = Math.atan2(v[0], -v[2]);
|
||||||
|
k.physicalDir += k.angle;
|
||||||
|
k.vel = v;
|
||||||
|
k.physBasis = null;
|
||||||
|
}
|
||||||
|
|
||||||
function sndUpdate(view) {
|
function sndUpdate(view) {
|
||||||
k.soundProps.pos = vec3.transformMat4([], k.pos, view);
|
k.soundProps.pos = vec3.transformMat4([], k.pos, view);
|
||||||
if (k.soundProps.lastPos != null) k.soundProps.vel = vec3.sub([], k.soundProps.pos, k.soundProps.lastPos);
|
if (k.soundProps.lastPos != null) k.soundProps.vel = vec3.sub([], k.soundProps.pos, k.soundProps.lastPos);
|
||||||
|
@ -805,6 +1001,11 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||||
return MKDS_COLTYPE.SOUNDMAP[collision][effect] || {};
|
return MKDS_COLTYPE.SOUNDMAP[collision][effect] || {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function colParticle(collision, effect) {
|
||||||
|
if (MKDS_COLTYPE.SOUNDMAP[collision] == null) return null
|
||||||
|
return MKDS_COLTYPE.SOUNDMAP[collision][effect].particle || null;
|
||||||
|
}
|
||||||
|
|
||||||
function project(u, v) {
|
function project(u, v) {
|
||||||
return vec3.scale([], u, (vec3.dot(u, v)/vec3.dot(u, u)))
|
return vec3.scale([], u, (vec3.dot(u, v)/vec3.dot(u, u)))
|
||||||
}
|
}
|
||||||
|
@ -815,26 +1016,42 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||||
var colType = (plane.CollisionType>>8)&31;
|
var colType = (plane.CollisionType>>8)&31;
|
||||||
var colBE = (plane.CollisionType>>5)&7;
|
var colBE = (plane.CollisionType>>5)&7;
|
||||||
|
|
||||||
|
var change = (colType != lastCollided);
|
||||||
lastCollided = colType;
|
lastCollided = colType;
|
||||||
lastBE = colBE;
|
lastBE = colBE;
|
||||||
lastColSounds = colSound(lastCollided, colBE);
|
lastColSounds = colSound(lastCollided, colBE);
|
||||||
|
|
||||||
var n = vec3.normalize([], dat.normal);
|
var n = vec3.normalize([], dat.normal);
|
||||||
|
var an = n;
|
||||||
|
if (k.physBasis != null) {
|
||||||
|
an = vec3.transformMat4([], n, k.physBasis.inv);
|
||||||
|
}
|
||||||
var gravS = Math.sqrt(vec3.dot(k.gravity, k.gravity));
|
var gravS = Math.sqrt(vec3.dot(k.gravity, k.gravity));
|
||||||
var angle = Math.acos(vec3.dot(vec3.scale(vec3.create(), k.gravity, -1/gravS), n));
|
var angle = Math.acos(vec3.dot(vec3.scale(vec3.create(), k.gravity, -1/gravS), n));
|
||||||
var adjustPos = true;
|
var adjustPos = true;
|
||||||
|
|
||||||
|
if (colType == MKDS_COLTYPE.OOB || colType == MKDS_COLTYPE.FALL) {
|
||||||
|
k.OOB = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (MKDS_COLTYPE.GROUP_WALL.indexOf(colType) != -1) { //wall
|
if (MKDS_COLTYPE.GROUP_WALL.indexOf(colType) != -1) { //wall
|
||||||
//sliding plane, except normal is transformed to be entirely on the xz plane (cannot ride on top of wall, treated as vertical)
|
//sliding plane, except normal is transformed to be entirely on the xz plane (cannot ride on top of wall, treated as vertical)
|
||||||
var xz = Math.sqrt(n[0]*n[0]+n[2]*n[2])
|
var xz = Math.sqrt(an[0]*an[0]+an[2]*an[2])
|
||||||
var adjN = [n[0]/xz, 0, n[2]/xz]
|
var adjN = [an[0]/xz, 0, an[2]/xz]
|
||||||
var proj = vec3.dot(k.vel, adjN);
|
var proj = vec3.dot(k.vel, adjN);
|
||||||
|
|
||||||
if (proj < -1) {
|
if (proj < -1) {
|
||||||
if (lastColSounds.hit != null) nitroAudio.playSound(lastColSounds.hit, {volume:1}, 0, k)
|
if (k.kartWallTimer == 0) {
|
||||||
|
if (lastColSounds.hit != null) nitroAudio.playSound(lastColSounds.hit, {volume:1}, 0, k)
|
||||||
|
var colObj = {pos:pos, vel:[0,0,0], mat: mat4.fromTranslation([], pos)};
|
||||||
|
scene.particles.push(new NitroEmitter(scene, colObj, 13));
|
||||||
|
scene.particles.push(new NitroEmitter(scene, colObj, 14));
|
||||||
|
}
|
||||||
|
k.kartWallTimer = 15;
|
||||||
}
|
}
|
||||||
vec3.sub(k.vel, k.vel, vec3.scale(vec3.create(), adjN, proj));
|
vec3.sub(k.vel, k.vel, vec3.scale(vec3.create(), adjN, proj));
|
||||||
|
|
||||||
|
|
||||||
//convert back to angle + speed to keep change to kart vel
|
//convert back to angle + speed to keep change to kart vel
|
||||||
|
|
||||||
var v = k.vel;
|
var v = k.vel;
|
||||||
|
@ -846,13 +1063,31 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||||
k.boostNorm = BOOSTTIME;
|
k.boostNorm = BOOSTTIME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var stick = (colType == MKDS_COLTYPE.STICKY || colType == MKDS_COLTYPE.LOOP);
|
||||||
|
|
||||||
if (k.vel[1] > 0) k.vel[1] = 0;
|
if (k.vel[1] > 0) k.vel[1] = 0;
|
||||||
var proj = vec3.dot(k.vel, n);
|
var proj = vec3.dot(k.vel, an);
|
||||||
if (proj < -4 && k.vel[1] < -2) { proj -= 1.5; }
|
if (!stick && proj < -4 && k.vel[1] < -2) { proj -= 1.5; }
|
||||||
vec3.sub(k.vel, k.vel, vec3.scale(vec3.create(), n, proj));
|
vec3.sub(k.vel, k.vel, vec3.scale(vec3.create(), an, proj));
|
||||||
|
|
||||||
|
if (stick) {
|
||||||
|
enterBasis(dat.pNormal);
|
||||||
|
k.physBasis.loop = colType == MKDS_COLTYPE.LOOP;
|
||||||
|
} else {
|
||||||
|
if (k.physBasis != null)
|
||||||
|
exitBasis();
|
||||||
|
}
|
||||||
|
|
||||||
k.kartTargetNormal = dat.pNormal;
|
k.kartTargetNormal = dat.pNormal;
|
||||||
if (!onGround) {
|
|
||||||
console.log("ground: "+colType+", "+colBE);
|
if (change) {
|
||||||
|
var particle = colParticle(lastCollided, colBE);
|
||||||
|
if (particle == null)
|
||||||
|
clearWheelParticles(0);
|
||||||
|
else
|
||||||
|
setWheelParticles(particle, 0);
|
||||||
|
}
|
||||||
|
if (!onGround && !stick) {
|
||||||
groundAnim = 0;
|
groundAnim = 0;
|
||||||
if (lastColSounds.land != null) nitroAudio.playSound(lastColSounds.land, {volume:1}, 0, k)
|
if (lastColSounds.land != null) nitroAudio.playSound(lastColSounds.land, {volume:1}, 0, k)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
window.spa = function(input) {
|
window.spa = function(input) {
|
||||||
var t = this;
|
var t = this;
|
||||||
this.load = load;
|
this.load = load;
|
||||||
|
this.getTexture = getTexture;
|
||||||
|
|
||||||
var colourBuffer;
|
var colourBuffer;
|
||||||
|
|
||||||
|
@ -36,42 +37,108 @@ window.spa = function(input) {
|
||||||
|
|
||||||
offset += 24;
|
offset += 24;
|
||||||
if (version == "12_1") {
|
if (version == "12_1") {
|
||||||
this.particles = [];
|
t.particles = [];
|
||||||
for (let i=0; i<particleCount; i++) {
|
for (var i=0; i<particleCount; i++) {
|
||||||
this.particles[i] = readParticle(view, offset);
|
t.particles[i] = readParticle(view, offset);
|
||||||
offset = this.particles[i].nextOff;
|
t.particles[i].parent = t;
|
||||||
|
offset = t.particles[i].nextOff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
offset = firstTexOffset;
|
offset = firstTexOffset;
|
||||||
this.particleTextures = [];
|
t.particleTextures = [];
|
||||||
for (let i=0; i<particleTexCount; i++) {
|
for (var i=0; i<particleTexCount; i++) {
|
||||||
this.particleTextures[i] = readParticleTexture(view, offset);
|
t.particleTextures[i] = readParticleTexture(view, offset);
|
||||||
offset = this.particleTextures[i].nextOff;
|
offset = t.particleTextures[i].nextOff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//window.debugParticle = true;
|
||||||
if (window.debugParticle) {
|
if (window.debugParticle) {
|
||||||
for (let i=0; i<particleCount; i++) {
|
for (var i=0; i<particleCount; i++) {
|
||||||
var text = document.createElement("textarea");
|
var text = document.createElement("textarea");
|
||||||
var p = this.particles[i];
|
var p = t.particles[i];
|
||||||
|
p.parent = null;
|
||||||
text.value = JSON.stringify(p, true, 4);
|
text.value = JSON.stringify(p, true, 4);
|
||||||
|
p.parent = t;
|
||||||
text.style.width = 500;
|
text.style.width = 500;
|
||||||
text.style.height = 200;
|
text.style.height = 200;
|
||||||
|
|
||||||
|
|
||||||
var obj = this.particleTextures[p.textureId];
|
var obj = t.particleTextures[p.textureId];
|
||||||
if (p.texAnim) obj = this.particleTextures[p.texAnim.textures[0]];
|
if (p.texAnim) obj = t.particleTextures[p.texAnim.textures[0]];
|
||||||
if (obj == null) {
|
if (obj == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var test = readTexWithPal(obj.info, obj);
|
var test = readTexWithPal(obj.info, obj);
|
||||||
|
document.body.appendChild(document.createElement("br"));
|
||||||
|
document.body.appendChild(document.createTextNode(i+":"));
|
||||||
document.body.appendChild(test);
|
document.body.appendChild(test);
|
||||||
document.body.appendChild(text);
|
document.body.appendChild(text);
|
||||||
document.body.appendChild(document.createElement("br"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getTexture(id, gl) {
|
||||||
|
var t = this;
|
||||||
|
var obj = t.particleTextures[id];
|
||||||
|
if (obj == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (obj.glTex == null) {
|
||||||
|
var canvas = readTexWithPal(obj.info, obj);
|
||||||
|
var m = obj.info;
|
||||||
|
if (m.flipX || m.flipY) {
|
||||||
|
var fC = document.createElement("canvas");
|
||||||
|
var ctx = fC.getContext("2d");
|
||||||
|
fC.width = (m.flipX)?canvas.width*2:canvas.width;
|
||||||
|
fC.height = (m.flipY)?canvas.height*2:canvas.height;
|
||||||
|
ctx.drawImage(canvas, 0, 0);
|
||||||
|
ctx.save();
|
||||||
|
if (m.flipX) {
|
||||||
|
ctx.translate(2*canvas.width, 0);
|
||||||
|
ctx.scale(-1, 1);
|
||||||
|
ctx.drawImage(canvas, 0, 0);
|
||||||
|
ctx.restore();
|
||||||
|
ctx.save();
|
||||||
|
}
|
||||||
|
if (m.flipY) {
|
||||||
|
ctx.translate(0, 2*canvas.height);
|
||||||
|
ctx.scale(1, -1);
|
||||||
|
ctx.drawImage(fC, 0, 0);
|
||||||
|
ctx.restore();
|
||||||
|
}
|
||||||
|
var t = loadTex(fC, gl, !m.repeatX, !m.repeatY);
|
||||||
|
t.realWidth = canvas.width;
|
||||||
|
t.realHeight = canvas.height;
|
||||||
|
obj.glTex = t;
|
||||||
|
} else {
|
||||||
|
var t = loadTex(canvas, gl, !m.repeatX, !m.repeatY);
|
||||||
|
t.realWidth = canvas.width;
|
||||||
|
t.realHeight = canvas.height;
|
||||||
|
obj.glTex = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return obj.glTex;
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadTex(img, gl, clampx, clampy) { //general purpose function for loading an image into a texture.
|
||||||
|
var texture = gl.createTexture();
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
||||||
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
|
||||||
|
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
||||||
|
if (clampx) gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||||
|
if (clampy) gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
texture.width = img.width;
|
||||||
|
texture.height = img.height;
|
||||||
|
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, null);
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
function readParticle(view, off) {
|
function readParticle(view, off) {
|
||||||
var obj = {};
|
var obj = {};
|
||||||
var ParticleFlags =
|
var ParticleFlags =
|
||||||
|
@ -106,6 +173,7 @@ window.spa = function(input) {
|
||||||
Bit29: 0x20000000
|
Bit29: 0x20000000
|
||||||
}
|
}
|
||||||
|
|
||||||
|
obj.ParticleFlags = ParticleFlags;
|
||||||
obj.flag = view.getUint32(off, true);
|
obj.flag = view.getUint32(off, true);
|
||||||
obj.position = [view.getInt32(off+0x4, true)/4096, view.getInt32(off+0x8, true)/4096, view.getInt32(off+0xC, true)/4096];
|
obj.position = [view.getInt32(off+0x4, true)/4096, view.getInt32(off+0x8, true)/4096, view.getInt32(off+0xC, true)/4096];
|
||||||
//this is just hilarious at this point
|
//this is just hilarious at this point
|
||||||
|
@ -118,8 +186,8 @@ window.spa = function(input) {
|
||||||
//not sure what this vector is for. grass it's (0, 1, 0), smoke it's (-0.706787109375, 0, -0.707275390625) billboard alignment vector? (it's a bit crazy for powerslide)
|
//not sure what this vector is for. grass it's (0, 1, 0), smoke it's (-0.706787109375, 0, -0.707275390625) billboard alignment vector? (it's a bit crazy for powerslide)
|
||||||
obj.vector = [view.getInt16(off+0x1C, true)/4096, view.getInt16(off+0x1E, true)/4096, view.getInt16(off+0x20, true)/4096];
|
obj.vector = [view.getInt16(off+0x1C, true)/4096, view.getInt16(off+0x1E, true)/4096, view.getInt16(off+0x20, true)/4096];
|
||||||
obj.color = view.getUint16(off+0x22, true); //15 bit, usually 32767 for white.
|
obj.color = view.getUint16(off+0x22, true); //15 bit, usually 32767 for white.
|
||||||
obj.randomxz = view.getUint32(off+0x24, true); //random xz velocity intensity
|
obj.randomxz = view.getUint32(off+0x24, true)/4096; //random xz velocity intensity
|
||||||
obj.velocity = view.getUint32(off+0x28, true); //initial velocity related
|
obj.velocity = view.getUint32(off+0x28, true)/4096; //initial velocity related (along predefined vector)
|
||||||
obj.size = view.getUint32(off+0x2C, true)/4096; //size
|
obj.size = view.getUint32(off+0x2C, true)/4096; //size
|
||||||
obj.aspect = view.getUint16(off+0x30, true) / 4096; //aspect
|
obj.aspect = view.getUint16(off+0x30, true) / 4096; //aspect
|
||||||
|
|
||||||
|
@ -130,8 +198,8 @@ window.spa = function(input) {
|
||||||
obj.rotVelFrom = view.getInt16(off+0x34, true);
|
obj.rotVelFrom = view.getInt16(off+0x34, true);
|
||||||
obj.rotVelTo = view.getInt16(off+0x36, true);
|
obj.rotVelTo = view.getInt16(off+0x36, true);
|
||||||
|
|
||||||
obj.unknown13 = view.getUint16(off+0x38, true); //??? (0)
|
obj.scX = view.getInt16(off+0x38, true)/0x8000; //??? (0) //scale center offset?
|
||||||
obj.unknown14 = view.getUint16(off+0x3A, true); //??? (4B)
|
obj.scY = view.getInt16(off+0x3A, true)/0x8000; //??? (4B) //scale center offset?
|
||||||
obj.emitterLifetime = view.getUint16(off+0x3C, true); //stop emitting particles after this many frames
|
obj.emitterLifetime = view.getUint16(off+0x3C, true); //stop emitting particles after this many frames
|
||||||
obj.duration = view.getUint16(off+0x3E, true);
|
obj.duration = view.getUint16(off+0x3E, true);
|
||||||
|
|
||||||
|
@ -146,8 +214,8 @@ window.spa = function(input) {
|
||||||
obj.textureId = view.getUint8(off+0x47, true);
|
obj.textureId = view.getUint8(off+0x47, true);
|
||||||
obj.unknown21 = view.getUint32(off+0x48, true); //negative number makes grass disappear (1 for grass, smoke)
|
obj.unknown21 = view.getUint32(off+0x48, true); //negative number makes grass disappear (1 for grass, smoke)
|
||||||
obj.unknown22 = view.getUint32(off+0x4C, true); //some numbers make grass disappear (0x458d00 for grass, 0x74725f60 for smoke)
|
obj.unknown22 = view.getUint32(off+0x4C, true); //some numbers make grass disappear (0x458d00 for grass, 0x74725f60 for smoke)
|
||||||
obj.xScaleDelta = view.getUint16(off+0x50, true); //x scale delta for some reason. usually 0
|
obj.xScaleDelta = view.getInt16(off+0x50, true)/4096; //x scale delta for some reason. usually 0
|
||||||
obj.yScaleDelta = view.getUint16(off+0x52, true); //y scale delta for some reason. usually 0
|
obj.yScaleDelta = view.getInt16(off+0x52, true)/4096; //y scale delta for some reason. usually 0
|
||||||
obj.unknown25 = view.getUint32(off+0x54, true); //FFFFFFFF makes run at half framerate. idk? usually 0
|
obj.unknown25 = view.getUint32(off+0x54, true); //FFFFFFFF makes run at half framerate. idk? usually 0
|
||||||
off += 0x58;
|
off += 0x58;
|
||||||
|
|
||||||
|
@ -165,7 +233,8 @@ window.spa = function(input) {
|
||||||
unkBase: view.getUint16(off, true)/4096,
|
unkBase: view.getUint16(off, true)/4096,
|
||||||
scaleFrom: view.getUint16(off+2, true)/4096,
|
scaleFrom: view.getUint16(off+2, true)/4096,
|
||||||
scaleTo: view.getUint16(off+4, true)/4096,
|
scaleTo: view.getUint16(off+4, true)/4096,
|
||||||
param: view.getUint16(off+6, true),
|
fromZeroTime: view.getUint8(off+6, true)/0xFF, //time to dedicate to an animation from zero size
|
||||||
|
holdTime: view.getUint8(off+7, true)/0xFF, //time to dedicate to holding state at the end.
|
||||||
flagParam: view.getUint16(off+8, true),
|
flagParam: view.getUint16(off+8, true),
|
||||||
unk4b: view.getUint16(off+10, true),
|
unk4b: view.getUint16(off+10, true),
|
||||||
};
|
};
|
||||||
|
@ -173,7 +242,7 @@ window.spa = function(input) {
|
||||||
}
|
}
|
||||||
if ((obj.flag & ParticleFlags.ColorAnimation) != 0)
|
if ((obj.flag & ParticleFlags.ColorAnimation) != 0)
|
||||||
{
|
{
|
||||||
obj.ColorAnimation = {
|
obj.colorAnim = {
|
||||||
colorFrom: view.getUint16(off, true), //color from
|
colorFrom: view.getUint16(off, true), //color from
|
||||||
colorTo: view.getUint16(off+2, true), //color to (seems to be same as base color)
|
colorTo: view.getUint16(off+2, true), //color to (seems to be same as base color)
|
||||||
framePct: view.getUint16(off+4, true), //frame pct to become color to (FFFF means always from, 8000 is about the middle)
|
framePct: view.getUint16(off+4, true), //frame pct to become color to (FFFF means always from, 8000 is about the middle)
|
||||||
|
@ -203,7 +272,7 @@ window.spa = function(input) {
|
||||||
if ((obj.flag & ParticleFlags.TextureAnimation) != 0)
|
if ((obj.flag & ParticleFlags.TextureAnimation) != 0)
|
||||||
{
|
{
|
||||||
var textures = [];
|
var textures = [];
|
||||||
for (let i=0; i<8; i++) textures[i] = view.getUint8(off+i);
|
for (var i=0; i<8; i++) textures[i] = view.getUint8(off+i);
|
||||||
obj.texAnim = {
|
obj.texAnim = {
|
||||||
textures: textures,
|
textures: textures,
|
||||||
frames: view.getUint8(off+8),
|
frames: view.getUint8(off+8),
|
||||||
|
@ -215,7 +284,7 @@ window.spa = function(input) {
|
||||||
if ((obj.flag & ParticleFlags.Bit16) != 0)
|
if ((obj.flag & ParticleFlags.Bit16) != 0)
|
||||||
{
|
{
|
||||||
obj.Bit16 = [];
|
obj.Bit16 = [];
|
||||||
for (let i=0; i<20; i++) obj.Bit16[i] = view.getUint8(off+i);
|
for (var i=0; i<20; i++) obj.Bit16[i] = view.getUint8(off+i);
|
||||||
off += 20;
|
off += 20;
|
||||||
}
|
}
|
||||||
if ((obj.flag & ParticleFlags.Gravity) != 0)
|
if ((obj.flag & ParticleFlags.Gravity) != 0)
|
||||||
|
@ -239,31 +308,31 @@ window.spa = function(input) {
|
||||||
{
|
{
|
||||||
//seems to be 4 int 16s typically in some kind of pattern.
|
//seems to be 4 int 16s typically in some kind of pattern.
|
||||||
obj.Bit25 = [];
|
obj.Bit25 = [];
|
||||||
for (let i=0; i<8; i++) obj.Bit25[i] = view.getUint8(off+i);
|
for (var i=0; i<8; i++) obj.Bit25[i] = view.getUint8(off+i);
|
||||||
off += 8;
|
off += 8;
|
||||||
}
|
}
|
||||||
if ((obj.flag & ParticleFlags.Bit26) != 0)
|
if ((obj.flag & ParticleFlags.Bit26) != 0)
|
||||||
{
|
{
|
||||||
obj.Bit26 = [];
|
obj.Bit26 = [];
|
||||||
for (let i=0; i<16; i++) obj.Bit26[i] = view.getUint8(off+i);
|
for (var i=0; i<16; i++) obj.Bit26[i] = view.getUint8(off+i);
|
||||||
off += 16;
|
off += 16;
|
||||||
}
|
}
|
||||||
if ((obj.flag & ParticleFlags.Bit27) != 0)
|
if ((obj.flag & ParticleFlags.Bit27) != 0)
|
||||||
{
|
{
|
||||||
obj.Bit27 = [];
|
obj.Bit27 = [];
|
||||||
for (let i=0; i<4; i++) obj.Bit27[i] = view.getUint8(off+i);
|
for (var i=0; i<4; i++) obj.Bit27[i] = view.getUint8(off+i);
|
||||||
off += 4;
|
off += 4;
|
||||||
}
|
}
|
||||||
if ((obj.flag & ParticleFlags.Bit28) != 0)
|
if ((obj.flag & ParticleFlags.Bit28) != 0)
|
||||||
{
|
{
|
||||||
obj.Bit28 = [];
|
obj.Bit28 = [];
|
||||||
for (let i=0; i<8; i++) obj.Bit28[i] = view.getUint8(off+i);
|
for (var i=0; i<8; i++) obj.Bit28[i] = view.getUint8(off+i);
|
||||||
off += 8;
|
off += 8;
|
||||||
}
|
}
|
||||||
if ((obj.flag & ParticleFlags.Bit29) != 0)
|
if ((obj.flag & ParticleFlags.Bit29) != 0)
|
||||||
{
|
{
|
||||||
obj.Bit29 = [];
|
obj.Bit29 = [];
|
||||||
for (let i=0; i<16; i++) obj.Bit29[i] = view.getUint8(off+i);
|
for (var i=0; i<16; i++) obj.Bit29[i] = view.getUint8(off+i);
|
||||||
off += 16;
|
off += 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,7 +347,7 @@ window.spa = function(input) {
|
||||||
|
|
||||||
var flags = view.getUint16(off+4, true);
|
var flags = view.getUint16(off+4, true);
|
||||||
obj.info = {
|
obj.info = {
|
||||||
pal0trans: (flags>>3)&1, //weirdly different format
|
pal0trans: true,//z(flags>>3)&1, //weirdly different format
|
||||||
format: ((flags)&7),
|
format: ((flags)&7),
|
||||||
height: 8 << ((flags>>8)&0xF),
|
height: 8 << ((flags>>8)&0xF),
|
||||||
width: 8 << ((flags>>4)&0xF),
|
width: 8 << ((flags>>4)&0xF),
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
|
@ -5,35 +5,35 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
window.ItemShard = function(scene, targ, model) {
|
window.ItemShard = function(scene, targ, model) {
|
||||||
var t = this;
|
var t = this;
|
||||||
t.update = update;
|
t.update = update;
|
||||||
t.draw = draw;
|
t.draw = draw;
|
||||||
|
|
||||||
t.time = 0;
|
t.time = 0;
|
||||||
t.pos = vec3.clone(targ.pos);
|
t.pos = vec3.clone(targ.pos);
|
||||||
t.vel = vec3.add([], targ.vel, [(Math.random()-0.5)*5, Math.random()*7, (Math.random()-0.5)*5]);
|
t.vel = vec3.add([], targ.vel, [(Math.random()-0.5)*5, Math.random()*7, (Math.random()-0.5)*5]);
|
||||||
t.dirVel = [(Math.random()-0.5), (Math.random()-0.5), (Math.random()-0.5)];
|
t.dirVel = [(Math.random()-0.5), (Math.random()-0.5), (Math.random()-0.5)];
|
||||||
t.dir = [Math.random()*2*Math.PI, Math.random()*2*Math.PI, Math.random()*2*Math.PI];
|
t.dir = [Math.random()*2*Math.PI, Math.random()*2*Math.PI, Math.random()*2*Math.PI];
|
||||||
t.scale = Math.random()+0.5;
|
t.scale = Math.random()+0.5;
|
||||||
t.scale = [t.scale, t.scale, t.scale];
|
t.scale = [t.scale, t.scale, t.scale];
|
||||||
|
|
||||||
function update(scene) {
|
function update(scene) {
|
||||||
vec3.add(t.pos, t.pos, t.vel);
|
vec3.add(t.pos, t.pos, t.vel);
|
||||||
vec3.add(t.vel, t.vel, [0, -0.17, 0]);
|
vec3.add(t.vel, t.vel, [0, -0.17, 0]);
|
||||||
vec3.add(t.dir, t.dir, t.dirVel);
|
vec3.add(t.dir, t.dir, t.dirVel);
|
||||||
|
|
||||||
if (t.time++ > 30) scene.removeParticle(t);
|
if (t.time++ > 30) scene.removeParticle(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
function draw(view, pMatrix, gl) {
|
function draw(view, pMatrix, gl) {
|
||||||
var mat = mat4.translate(mat4.create(), view, t.pos);
|
var mat = mat4.translate(mat4.create(), view, t.pos);
|
||||||
|
|
||||||
mat4.rotateZ(mat, mat, t.dir[2]);
|
mat4.rotateZ(mat, mat, t.dir[2]);
|
||||||
mat4.rotateY(mat, mat, t.dir[1]);
|
mat4.rotateY(mat, mat, t.dir[1]);
|
||||||
mat4.rotateX(mat, mat, t.dir[0]);
|
mat4.rotateX(mat, mat, t.dir[0]);
|
||||||
|
|
||||||
mat4.scale(mat, mat, vec3.scale([], t.scale, 16));
|
mat4.scale(mat, mat, vec3.scale([], t.scale, 16));
|
||||||
model.draw(mat, pMatrix);
|
model.draw(mat, pMatrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,173 @@
|
||||||
|
//
|
||||||
|
// nitroEmitter.js
|
||||||
|
//--------------------
|
||||||
|
// Implemtents the generic nitro particle emitter.
|
||||||
|
// by riperiperi
|
||||||
|
//
|
||||||
|
|
||||||
|
window.NitroEmitter = function(scene, targ, emitterID, vector, offset) {
|
||||||
|
var t = this;
|
||||||
|
t.update = update;
|
||||||
|
t.draw = draw;
|
||||||
|
|
||||||
|
var pRes = scene.gameRes.RaceEffect;
|
||||||
|
var emitter = (emitterID == -1)?null:pRes.particles[emitterID];
|
||||||
|
t.attached = targ; //an entity with pos and vel.
|
||||||
|
|
||||||
|
if (vector == null) vector = [0, 1, 0];
|
||||||
|
if (offset == null) offset = [0,0,0];
|
||||||
|
t.offset = offset;
|
||||||
|
t.vector = vector;
|
||||||
|
t.pctParticle = 0;
|
||||||
|
t.time = 0;
|
||||||
|
t.dead = false;
|
||||||
|
t.curPrio = 0;
|
||||||
|
t.doNotDelete = (emitter == null);
|
||||||
|
t.pause = false;
|
||||||
|
|
||||||
|
t.setEmitter = setEmitter;
|
||||||
|
t.clearEmitter = clearEmitter;
|
||||||
|
|
||||||
|
var particleList = [emitterID, -1, -1, -1];
|
||||||
|
|
||||||
|
function setEmitter(emitterID, prio) {
|
||||||
|
particleList[prio] = emitterID;
|
||||||
|
if (t.curPrio <= prio) {
|
||||||
|
//activate this emitter immediately.
|
||||||
|
t.curPrio = prio;
|
||||||
|
t.dead = false;
|
||||||
|
emitter = pRes.particles[emitterID];
|
||||||
|
t.time = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearEmitter(prio) {
|
||||||
|
//if (t.curPrio > prio) return; //this emitter cannot be unset
|
||||||
|
if (prio == t.curPrio) {
|
||||||
|
findNextEmitter();
|
||||||
|
} else {
|
||||||
|
particleList[prio] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function findNextEmitter() {
|
||||||
|
particleList[t.curPrio] = -1;
|
||||||
|
var em = t.curPrio-1;
|
||||||
|
while (em >= 0) {
|
||||||
|
if (particleList[em] != -1) {
|
||||||
|
t.dead = false;
|
||||||
|
emitter = pRes.particles[particleList[em]];
|
||||||
|
t.time = 0;
|
||||||
|
t.curPrio = em;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
em--;
|
||||||
|
}
|
||||||
|
if (em == -1) {
|
||||||
|
t.curPrio = 0;
|
||||||
|
emitter = null;
|
||||||
|
dead = true;
|
||||||
|
}
|
||||||
|
t.curPrio = em;
|
||||||
|
}
|
||||||
|
|
||||||
|
function update(scene) {
|
||||||
|
if (emitter == null || t.dead || t.pause) return;
|
||||||
|
if ((t.time % (emitter.frequency)) == 0 && t.time >= emitter.delay) {
|
||||||
|
//should we create new particles? fractional logic for doing this
|
||||||
|
t.pctParticle += emitter.particleChance;
|
||||||
|
while (t.pctParticle >= 1) {
|
||||||
|
|
||||||
|
var attach = (emitter.flag & 0x8000) > 0;
|
||||||
|
|
||||||
|
t.pctParticle -= 1;
|
||||||
|
//create a new particle
|
||||||
|
//TODO: make these transform with the target's world matrix
|
||||||
|
var pos = vec3.create();
|
||||||
|
//add offset
|
||||||
|
vec3.add(pos, pos, t.offset);
|
||||||
|
//add emitter properties
|
||||||
|
vec3.add(pos, pos, emitter.position);
|
||||||
|
var spread = [Math.random()*2-1, Math.random()*2-1, Math.random()*2-1];
|
||||||
|
var spreadMode = (emitter.flag & 0xF);
|
||||||
|
if (spreadMode == 2) {
|
||||||
|
spread[1] = 0; //spread is only in xz direction
|
||||||
|
}
|
||||||
|
vec3.normalize(spread, spread);
|
||||||
|
if (spreadMode == 0) {
|
||||||
|
spread = [0,0,0];
|
||||||
|
}
|
||||||
|
vec3.scale(spread, spread, Math.random()*emitter.areaSpread*2);
|
||||||
|
vec3.add(pos, pos, spread);
|
||||||
|
|
||||||
|
vec3.scale(pos, pos, 16);
|
||||||
|
if (!attach) {
|
||||||
|
if (targ.mat != null) {
|
||||||
|
vec3.transformMat4(pos, pos, targ.mat);
|
||||||
|
} else {
|
||||||
|
vec3.add(pos, pos, targ.pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//inherit velocity
|
||||||
|
var vel = (attach)?vec3.create():vec3.clone(targ.vel);
|
||||||
|
vec3.scale(vel, vel, 1/32);
|
||||||
|
|
||||||
|
var vector = vec3.clone(t.vector);
|
||||||
|
if (!attach) {
|
||||||
|
if (targ.mat != null) {
|
||||||
|
//tranform our vector by the target matrix
|
||||||
|
var mat = targ.mat;
|
||||||
|
var org = [];
|
||||||
|
mat4.getTranslation(org, mat);
|
||||||
|
mat[12] = 0;
|
||||||
|
mat[13] = 0;
|
||||||
|
mat[14] = 0;
|
||||||
|
|
||||||
|
vec3.transformMat4(vector, vector, mat);
|
||||||
|
|
||||||
|
mat[12] = org[0];
|
||||||
|
mat[13] = org[1];
|
||||||
|
mat[14] = org[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vec3.normalize(vector, vector);
|
||||||
|
vec3.add(vel, vel, vec3.scale([], vector, emitter.velocity));
|
||||||
|
|
||||||
|
var xz = [Math.random()*2-1, 0, Math.random()*2-1];
|
||||||
|
vec3.normalize(xz, xz);
|
||||||
|
vec3.scale(xz, xz, Math.random()*emitter.randomxz);
|
||||||
|
vec3.add(vel, vel, xz);
|
||||||
|
|
||||||
|
var rotVel = ((emitter.rotVelFrom + ((Math.random()*emitter.rotVelTo-emitter.rotVelFrom) | 0))/65535) * Math.PI*2;
|
||||||
|
var dir = ((emitter.flag & 0x2000) > 0)?(Math.random()*Math.PI*2):0;
|
||||||
|
var duration = emitter.duration + emitter.duration * emitter.varDuration/0xFF * (Math.random() * 2 - 1);
|
||||||
|
var scaleMod = (emitter.varScale/0xFF * (Math.random() * 2 - 1)) + 1;
|
||||||
|
|
||||||
|
var scale = [scaleMod * emitter.size, scaleMod * emitter.size * emitter.aspect];
|
||||||
|
|
||||||
|
var particle = new NitroParticle(scene, emitter, pos, vel, dir, rotVel, duration, scale, (attach?t.attached:null));
|
||||||
|
particle.ovel = (attach)?vec3.create():vec3.scale([], targ.vel, 1/32);
|
||||||
|
|
||||||
|
scene.particles.push(particle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var pos = vec3.clone(targ.pos);
|
||||||
|
|
||||||
|
}
|
||||||
|
t.time++;
|
||||||
|
|
||||||
|
if (t.time == emitter.emitterLifetime) {
|
||||||
|
t.dead = true;
|
||||||
|
if (!t.doNotDelete) scene.removeParticle(t);
|
||||||
|
else {
|
||||||
|
findNextEmitter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function draw(view, pMatrix, gl) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,251 @@
|
||||||
|
//
|
||||||
|
// nitroParticle.js
|
||||||
|
//--------------------
|
||||||
|
// Implements a generic nitro particle. Currently positioned and updated in software for debug
|
||||||
|
// simplicity - but should be moved to vertex shader in future.
|
||||||
|
// by riperiperi
|
||||||
|
//
|
||||||
|
|
||||||
|
window.NitroParticle = function(scene, emitter, pos, vel, dir, dirVel, duration, scale, attached) {
|
||||||
|
var t = this;
|
||||||
|
t.update = update;
|
||||||
|
t.draw = draw;
|
||||||
|
|
||||||
|
t.time = 0;
|
||||||
|
t.duration = duration | 0;
|
||||||
|
t.pos = vec3.add(pos, pos, [0, 0, 0]);
|
||||||
|
t.vel = vel;
|
||||||
|
t.dirVel = dirVel; //float
|
||||||
|
t.dir = dir; //float
|
||||||
|
t.attached = attached;
|
||||||
|
t.scale = scale; //vec2
|
||||||
|
t.emitter = emitter;
|
||||||
|
|
||||||
|
t.aScale = 1;
|
||||||
|
//decode 16 bit color into float
|
||||||
|
t.baseColor = convertCol(emitter.color);
|
||||||
|
t.baseColor[3] = emitter.opacity / 0x1F;
|
||||||
|
t.aColor = vec4.clone(t.baseColor);
|
||||||
|
|
||||||
|
t.frame = emitter.textureId;
|
||||||
|
if (t.emitter.texAnim)
|
||||||
|
t.frame = t.emitter.texAnim.textures[0];
|
||||||
|
|
||||||
|
function convertCol(col) {
|
||||||
|
return [
|
||||||
|
((col&31)/31),
|
||||||
|
(((col>>5)&31)/31),
|
||||||
|
(((col>>10)&31)/31),
|
||||||
|
1 //Math.round((col>>15)*255);
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function update(scene) {
|
||||||
|
var particlePct = t.time / t.duration;
|
||||||
|
|
||||||
|
t.pos[0] += t.vel[0] * 16;
|
||||||
|
t.pos[1] += t.vel[1] * (t.emitter.yOffIntensity/128) * 16;
|
||||||
|
t.pos[2] += t.vel[2] * 16;
|
||||||
|
if (t.emitter.gravity) {
|
||||||
|
vec3.add(t.vel, t.vel, t.emitter.gravity);
|
||||||
|
}
|
||||||
|
if (t.emitter.colorAnim) {
|
||||||
|
var ca = t.emitter.colorAnim;
|
||||||
|
var from = convertCol(ca.colorFrom);
|
||||||
|
var to = convertCol(ca.colorTo);
|
||||||
|
var pctFloat = (ca.framePct/0xFFFF);
|
||||||
|
vec4.lerp(t.aColor, from, to, Math.max(0, (particlePct - pctFloat)/(1 - pctFloat)));
|
||||||
|
t.aColor[3] = t.emitter.opacity/0x1F;
|
||||||
|
} else {
|
||||||
|
t.aColor = vec4.clone(t.baseColor);
|
||||||
|
}
|
||||||
|
if (t.emitter.opacityAnim) {
|
||||||
|
var oa = t.emitter.opacityAnim;
|
||||||
|
var pctFade = oa.startFade / 0xFFFF;
|
||||||
|
var opaMul = 1-Math.max(0, (particlePct - pctFade)/(1 - pctFade));
|
||||||
|
t.aColor[3] = opaMul;// * oa.intensity/0x0FFF;
|
||||||
|
//vec4.scale(t.aColor, t.aColor, opaMul);
|
||||||
|
}
|
||||||
|
if (t.emitter.texAnim) {
|
||||||
|
var ta = t.emitter.texAnim;
|
||||||
|
var frame = 0;
|
||||||
|
if ((ta.unknown1 & 128) > 0) {
|
||||||
|
//select frame based on particle duration
|
||||||
|
var frame = ta.textures[Math.min((particlePct * ta.frames) | 0, ta.frames-1)];
|
||||||
|
} else {
|
||||||
|
//repeating anim with framerate
|
||||||
|
//not sure what framerate is, but its likely in the unknowns.
|
||||||
|
var frame = ta.textures[(t.time % ta.frames)];
|
||||||
|
}
|
||||||
|
t.frame = frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
t.dir += t.dirVel;
|
||||||
|
|
||||||
|
if (t.time++ >= t.duration) scene.removeParticle(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
function draw(view, pMatrix, gl) {
|
||||||
|
var particlePct = t.time / t.duration;
|
||||||
|
|
||||||
|
var pos = t.pos;
|
||||||
|
var vel = t.vel;
|
||||||
|
|
||||||
|
if (t.attached != null) {
|
||||||
|
pos = vec3.transformMat4([], pos, t.attached.mat);
|
||||||
|
|
||||||
|
|
||||||
|
//tranform our vector by the target matrix
|
||||||
|
var mat = t.attached.mat;
|
||||||
|
var org = [];
|
||||||
|
|
||||||
|
mat4.getTranslation(org, mat);
|
||||||
|
mat[12] = 0;
|
||||||
|
mat[13] = 0;
|
||||||
|
mat[14] = 0;
|
||||||
|
|
||||||
|
vel = vec3.transformMat4([], vel, mat);
|
||||||
|
|
||||||
|
mat[12] = org[0];
|
||||||
|
mat[13] = org[1];
|
||||||
|
mat[14] = org[2];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var mat = mat4.translate(mat4.create(), view, pos);
|
||||||
|
|
||||||
|
var bbMode = t.emitter.flag & 0xF0;
|
||||||
|
|
||||||
|
if (bbMode == 0x10) { //spark, billboards towards camera
|
||||||
|
var camPos = scene.camera.view.pos;
|
||||||
|
|
||||||
|
camPos = vec3.sub([], camPos, pos);
|
||||||
|
vec3.normalize(camPos, camPos);
|
||||||
|
|
||||||
|
var n = vec3.sub([], vel, t.ovel);
|
||||||
|
vec3.normalize(n,n);
|
||||||
|
mat4.multiply(mat, mat, mat4.invert([], mat4.lookAt([], [0,0,0], camPos, n)));
|
||||||
|
|
||||||
|
} else if (bbMode == 0x20) { //no billboard
|
||||||
|
mat4.rotateY(mat, mat, t.dir);
|
||||||
|
} else if (bbMode == 0x30) { //spark, no billboard
|
||||||
|
var camPos = scene.camera.view.pos;
|
||||||
|
|
||||||
|
camPos = vec3.sub([], camPos, pos);
|
||||||
|
vec3.normalize(camPos, camPos);
|
||||||
|
|
||||||
|
var n = vec3.sub([], vel, t.ovel);
|
||||||
|
vec3.normalize(n,n);
|
||||||
|
mat4.multiply(mat, mat, mat4.invert([], mat4.lookAt([], [0,0,0], camPos, n)));
|
||||||
|
mat4.rotateY(mat, mat, t.dir);
|
||||||
|
} else { //billboard
|
||||||
|
mat4.multiply(mat, mat, nitroRender.billboardMat);
|
||||||
|
mat4.rotateZ(mat, mat, t.dir);
|
||||||
|
}
|
||||||
|
var finalScale = 1;
|
||||||
|
if (t.emitter.scaleAnim) {
|
||||||
|
var sa = t.emitter.scaleAnim;
|
||||||
|
if (particlePct < sa.fromZeroTime) {
|
||||||
|
var fzPct = particlePct / sa.fromZeroTime;
|
||||||
|
finalScale = sa.scaleFrom * fzPct;
|
||||||
|
} else {
|
||||||
|
var rescaledPct = Math.min(1, (particlePct - sa.fromZeroTime) / (1-(sa.fromZeroTime + sa.holdTime*(1-sa.fromZeroTime))));
|
||||||
|
finalScale = sa.scaleFrom * (1-rescaledPct) + sa.scaleTo * rescaledPct;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mat4.scale(mat, mat, vec3.scale([], [t.scale[0], t.scale[1], 1], 12*finalScale));
|
||||||
|
mat4.translate(mat, mat, [t.emitter.xScaleDelta, t.emitter.yScaleDelta, 0]);
|
||||||
|
|
||||||
|
drawGeneric(mat, pMatrix, gl);
|
||||||
|
}
|
||||||
|
|
||||||
|
var MAT3I = mat3.create();
|
||||||
|
var MAT4I = mat4.create();
|
||||||
|
function drawGeneric(mv, project, gl) {
|
||||||
|
var shader = nitroRender.nitroShader;
|
||||||
|
if (!nitroRender.flagShadow) {
|
||||||
|
gl.uniform1f(shader.shadOffUniform, 0.001);
|
||||||
|
gl.uniform1f(shader.lightIntensityUniform, 0);
|
||||||
|
}
|
||||||
|
if (window.VTX_PARTICLE == null) genGlobalVtx(gl);
|
||||||
|
var obj = window.VTX_PARTICLE;
|
||||||
|
|
||||||
|
nitroRender.setColMult(t.aColor);
|
||||||
|
|
||||||
|
gl.uniformMatrix4fv(shader.mvMatrixUniform, false, mv);
|
||||||
|
gl.uniformMatrix4fv(shader.pMatrixUniform, false, project);
|
||||||
|
//matrix stack unused, just put an identity in slot 0
|
||||||
|
gl.uniformMatrix4fv(shader.matStackUniform, false, MAT4I);
|
||||||
|
|
||||||
|
var frame = t.emitter.parent.getTexture(t.frame, gl);
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, frame);
|
||||||
|
//texture matrix not used
|
||||||
|
gl.uniformMatrix3fv(shader.texMatrixUniform, false, MAT3I);
|
||||||
|
if (obj != nitroRender.last.obj) {
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, obj.vPos);
|
||||||
|
gl.vertexAttribPointer(shader.vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
|
||||||
|
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, obj.vTx);
|
||||||
|
gl.vertexAttribPointer(shader.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0);
|
||||||
|
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, obj.vCol);
|
||||||
|
gl.vertexAttribPointer(shader.colorAttribute, 4, gl.FLOAT, false, 0, 0);
|
||||||
|
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, obj.vMat);
|
||||||
|
gl.vertexAttribPointer(shader.matAttribute, 1, gl.FLOAT, false, 0, 0);
|
||||||
|
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, obj.vNorm);
|
||||||
|
gl.vertexAttribPointer(shader.normAttribute, 3, gl.FLOAT, false, 0, 0);
|
||||||
|
nitroRender.last.obj = obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
||||||
|
|
||||||
|
nitroRender.setColMult([1, 1, 1, 1]);
|
||||||
|
if (!nitroRender.flagShadow) {
|
||||||
|
nitroRender.resetShadOff();
|
||||||
|
gl.uniform1f(shader.lightIntensityUniform, 0.3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function genGlobalVtx(gl) {
|
||||||
|
var vecPos = [-1,-1,0, 1,-1,0, -1,1,0, 1,1,0];
|
||||||
|
var vecTx = [1,1, 0,1, 1,0, 0,0];
|
||||||
|
var vecCol = [1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1];
|
||||||
|
var vecMat = [0,0,0,0];
|
||||||
|
var vecNorm = [0,1,0, 0,1,0, 0,1,0, 0,1,0];
|
||||||
|
|
||||||
|
var pos = gl.createBuffer();
|
||||||
|
var col = gl.createBuffer();
|
||||||
|
var tx = gl.createBuffer();
|
||||||
|
var mat = gl.createBuffer();
|
||||||
|
var norm = gl.createBuffer();
|
||||||
|
|
||||||
|
var posArray = new Float32Array(vecPos);
|
||||||
|
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, pos);
|
||||||
|
gl.bufferData(gl.ARRAY_BUFFER, posArray, gl.STATIC_DRAW);
|
||||||
|
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, tx);
|
||||||
|
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vecTx), gl.STATIC_DRAW);
|
||||||
|
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, col);
|
||||||
|
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vecCol), gl.STATIC_DRAW);
|
||||||
|
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, mat);
|
||||||
|
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vecMat), gl.STATIC_DRAW);
|
||||||
|
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, norm);
|
||||||
|
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vecNorm), gl.STATIC_DRAW);
|
||||||
|
|
||||||
|
window.VTX_PARTICLE = {
|
||||||
|
posArray: posArray,
|
||||||
|
vPos: pos,
|
||||||
|
vTx: tx,
|
||||||
|
vCol: col,
|
||||||
|
vMat: mat,
|
||||||
|
vNorm: norm,
|
||||||
|
verts: vecPos.length/3,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -246,10 +246,9 @@ window.nitroRender = new function() {
|
||||||
|
|
||||||
gl.uniformMatrix4fv(shader.shadowMatUniform, false, sMat);
|
gl.uniformMatrix4fv(shader.shadowMatUniform, false, sMat);
|
||||||
gl.uniformMatrix4fv(shader.farShadowMatUniform, false, fsMat);
|
gl.uniformMatrix4fv(shader.farShadowMatUniform, false, fsMat);
|
||||||
|
gl.uniform1f(shader.lightIntensityUniform, 0.3);
|
||||||
|
|
||||||
gl.uniform1f(shader.shadOffUniform, 0.00005+((mobile)?0.0005:0));
|
this.resetShadOff();
|
||||||
gl.uniform1f(shader.farShadOffUniform, 0.0005);
|
|
||||||
|
|
||||||
gl.activeTexture(gl.TEXTURE1);
|
gl.activeTexture(gl.TEXTURE1);
|
||||||
gl.bindTexture(gl.TEXTURE_2D, sTex);
|
gl.bindTexture(gl.TEXTURE_2D, sTex);
|
||||||
gl.uniform1i(shader.lightSamplerUniform, 1);
|
gl.uniform1i(shader.lightSamplerUniform, 1);
|
||||||
|
@ -262,6 +261,12 @@ window.nitroRender = new function() {
|
||||||
this.prepareShader();
|
this.prepareShader();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.resetShadOff = function() {
|
||||||
|
var shader = shaders[1];
|
||||||
|
gl.uniform1f(shader.shadOffUniform, 0.00005+((mobile)?0.0005:0));
|
||||||
|
gl.uniform1f(shader.farShadOffUniform, 0.0005);
|
||||||
|
}
|
||||||
|
|
||||||
this.unsetShadowMode = function() {
|
this.unsetShadowMode = function() {
|
||||||
this.nitroShader = shaders[0];
|
this.nitroShader = shaders[0];
|
||||||
gl.useProgram(this.nitroShader);
|
gl.useProgram(this.nitroShader);
|
||||||
|
@ -384,7 +389,7 @@ function nitroModel(bmd, btx, remap) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (remap != null) {
|
if (remap != null) {
|
||||||
setTextureRemap(remap)
|
setTextureRemap(remap);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (btx != null) {
|
if (btx != null) {
|
||||||
|
|
|
@ -16,9 +16,39 @@ window.nitroShaders = new (function() {
|
||||||
\n\
|
\n\
|
||||||
uniform sampler2D uSampler;\n\
|
uniform sampler2D uSampler;\n\
|
||||||
\n\
|
\n\
|
||||||
|
float indexValue() {\n\
|
||||||
|
int x = int(mod(gl_FragCoord.x, 4.0));\n\
|
||||||
|
int y = int(mod(gl_FragCoord.y, 4.0));\n\
|
||||||
|
int i = (x + y * 4);\n\
|
||||||
|
if (i == 0) return 0.0;\n\
|
||||||
|
else if (i == 1) return 8.0;\n\
|
||||||
|
else if (i == 2) return 2.0;\n\
|
||||||
|
else if (i == 3) return 10.0;\n\
|
||||||
|
else if (i == 4) return 12.0;\n\
|
||||||
|
else if (i == 5) return 4.0;\n\
|
||||||
|
else if (i == 6) return 14.0;\n\
|
||||||
|
else if (i == 7) return 6.0;\n\
|
||||||
|
else if (i == 8) return 3.0;\n\
|
||||||
|
else if (i == 9) return 11.0;\n\
|
||||||
|
else if (i == 10) return 1.0;\n\
|
||||||
|
else if (i == 11) return 9.0;\n\
|
||||||
|
else if (i == 12) return 15.0;\n\
|
||||||
|
else if (i == 13) return 7.0;\n\
|
||||||
|
else if (i == 14) return 13.0;\n\
|
||||||
|
else if (i == 15) return 5.0;\n\
|
||||||
|
}\n\
|
||||||
|
\n\
|
||||||
|
float dither(float color) {\n\
|
||||||
|
float closestColor = (color < 0.5) ? 0.0 : 1.0;\n\
|
||||||
|
float secondClosestColor = 1.0 - closestColor;\n\
|
||||||
|
float d = indexValue();\n\
|
||||||
|
float distance = abs(closestColor - color);\n\
|
||||||
|
return (distance < d) ? closestColor : secondClosestColor;\n\
|
||||||
|
}\n\
|
||||||
|
\n\
|
||||||
void main(void) {\n\
|
void main(void) {\n\
|
||||||
gl_FragColor = texture2D(uSampler, vTextureCoord)*color;\n\
|
gl_FragColor = texture2D(uSampler, vTextureCoord)*color;\n\
|
||||||
if (gl_FragColor.a == 0.0) discard;\n\
|
if (gl_FragColor.a < 1.0 && (gl_FragColor.a == 0.0 || dither(gl_FragColor.a) == 0.0)) discard;\n\
|
||||||
}"
|
}"
|
||||||
|
|
||||||
this.defaultVert = "attribute vec3 aVertexPosition;\n\
|
this.defaultVert = "attribute vec3 aVertexPosition;\n\
|
||||||
|
@ -62,20 +92,20 @@ window.nitroShaders = new (function() {
|
||||||
\n\
|
\n\
|
||||||
uniform sampler2D uSampler;\n\
|
uniform sampler2D uSampler;\n\
|
||||||
\n\
|
\n\
|
||||||
float shadowCompare(sampler2D map, vec2 pos, float compare) {\n\
|
float shadowCompare(sampler2D map, vec2 pos, float compare, float so) {\n\
|
||||||
float depth = texture2D(map, pos).r;\n\
|
float depth = texture2D(map, pos).r;\n\
|
||||||
return step(compare, depth);\n\
|
return smoothstep(compare-so, compare, depth);\n\
|
||||||
}\n\
|
}\n\
|
||||||
\n\
|
\n\
|
||||||
float shadowLerp(sampler2D depths, vec2 size, vec2 uv, float compare){\n\
|
float shadowLerp(sampler2D depths, vec2 size, vec2 uv, float compare, float so){\n\
|
||||||
vec2 texelSize = vec2(1.0)/size;\n\
|
vec2 texelSize = vec2(1.0)/size;\n\
|
||||||
vec2 f = fract(uv*size+0.5);\n\
|
vec2 f = fract(uv*size+0.5);\n\
|
||||||
vec2 centroidUV = floor(uv*size+0.5)/size;\n\
|
vec2 centroidUV = floor(uv*size+0.5)/size;\n\
|
||||||
\n\
|
\n\
|
||||||
float lb = shadowCompare(depths, centroidUV+texelSize*vec2(0.0, 0.0), compare);\n\
|
float lb = shadowCompare(depths, centroidUV+texelSize*vec2(0.0, 0.0), compare, so);\n\
|
||||||
float lt = shadowCompare(depths, centroidUV+texelSize*vec2(0.0, 1.0), compare);\n\
|
float lt = shadowCompare(depths, centroidUV+texelSize*vec2(0.0, 1.0), compare, so);\n\
|
||||||
float rb = shadowCompare(depths, centroidUV+texelSize*vec2(1.0, 0.0), compare);\n\
|
float rb = shadowCompare(depths, centroidUV+texelSize*vec2(1.0, 0.0), compare, so);\n\
|
||||||
float rt = shadowCompare(depths, centroidUV+texelSize*vec2(1.0, 1.0), compare);\n\
|
float rt = shadowCompare(depths, centroidUV+texelSize*vec2(1.0, 1.0), compare, so);\n\
|
||||||
float a = mix(lb, lt, f.y);\n\
|
float a = mix(lb, lt, f.y);\n\
|
||||||
float b = mix(rb, rt, f.y);\n\
|
float b = mix(rb, rt, f.y);\n\
|
||||||
float c = mix(a, b, f.x);\n\
|
float c = mix(a, b, f.x);\n\
|
||||||
|
@ -89,14 +119,14 @@ window.nitroShaders = new (function() {
|
||||||
float dist = max(ldNorm.x, ldNorm.y);\n\
|
float dist = max(ldNorm.x, ldNorm.y);\n\
|
||||||
\n\
|
\n\
|
||||||
if (dist > 0.5) {\n\
|
if (dist > 0.5) {\n\
|
||||||
gl_FragColor = col*mix(vec4(0.5, 0.5, 0.7, 1.0), vec4(1.0, 1.0, 1.0, 1.0), shadowLerp(farLightDSampler, vec2(4096.0, 4096.0), fLightDist.xy, fLightDist.z-farShadOff));\n\
|
gl_FragColor = col*mix(vec4(0.5, 0.5, 0.7, 1.0), vec4(1.0, 1.0, 1.0, 1.0), shadowLerp(farLightDSampler, vec2(4096.0, 4096.0), fLightDist.xy, fLightDist.z-farShadOff, farShadOff*2.0));\n\
|
||||||
} else if (dist > 0.4) {\n\
|
} else if (dist > 0.4) {\n\
|
||||||
float lerp1 = shadowLerp(farLightDSampler, vec2(4096.0, 4096.0), fLightDist.xy, fLightDist.z-farShadOff);\n\
|
float lerp1 = shadowLerp(farLightDSampler, vec2(4096.0, 4096.0), fLightDist.xy, fLightDist.z-farShadOff, farShadOff*2.0);\n\
|
||||||
float lerp2 = shadowLerp(lightDSampler, vec2(2048.0, 2048.0), lightDist.xy, lightDist.z-shadOff);\n\
|
float lerp2 = shadowLerp(lightDSampler, vec2(2048.0, 2048.0), lightDist.xy, lightDist.z-shadOff, shadOff*4.0);\n\
|
||||||
\n\
|
\n\
|
||||||
gl_FragColor = col*mix(vec4(0.5, 0.5, 0.7, 1.0), vec4(1.0, 1.0, 1.0, 1.0), mix(lerp2, lerp1, (dist-0.4)*10.0));\n\
|
gl_FragColor = col*mix(vec4(0.5, 0.5, 0.7, 1.0), vec4(1.0, 1.0, 1.0, 1.0), mix(lerp2, lerp1, (dist-0.4)*10.0));\n\
|
||||||
} else {\n\
|
} else {\n\
|
||||||
gl_FragColor = col*mix(vec4(0.5, 0.5, 0.7, 1.0), vec4(1.0, 1.0, 1.0, 1.0), shadowLerp(lightDSampler, vec2(2048.0, 2048.0), lightDist.xy, lightDist.z-shadOff));\n\
|
gl_FragColor = col*mix(vec4(0.5, 0.5, 0.7, 1.0), vec4(1.0, 1.0, 1.0, 1.0), shadowLerp(lightDSampler, vec2(2048.0, 2048.0), lightDist.xy, lightDist.z-shadOff, shadOff*4.0));\n\
|
||||||
}\n\
|
}\n\
|
||||||
\n\
|
\n\
|
||||||
if (gl_FragColor.a == 0.0) discard;\n\
|
if (gl_FragColor.a == 0.0) discard;\n\
|
||||||
|
@ -118,6 +148,7 @@ window.nitroShaders = new (function() {
|
||||||
\n\
|
\n\
|
||||||
uniform mat4 shadowMat;\n\
|
uniform mat4 shadowMat;\n\
|
||||||
uniform mat4 farShadowMat;\n\
|
uniform mat4 farShadowMat;\n\
|
||||||
|
uniform float lightIntensity; \n\
|
||||||
\n\
|
\n\
|
||||||
varying vec2 vTextureCoord;\n\
|
varying vec2 vTextureCoord;\n\
|
||||||
varying vec4 color;\n\
|
varying vec4 color;\n\
|
||||||
|
@ -133,7 +164,7 @@ window.nitroShaders = new (function() {
|
||||||
lightDist = (shadowMat*pos + vec4(1, 1, 1, 0)) / 2.0;\n\
|
lightDist = (shadowMat*pos + vec4(1, 1, 1, 0)) / 2.0;\n\
|
||||||
fLightDist = (farShadowMat*pos + vec4(1, 1, 1, 0)) / 2.0;\n\
|
fLightDist = (farShadowMat*pos + vec4(1, 1, 1, 0)) / 2.0;\n\
|
||||||
vec3 adjNorm = normalize(vec3(uMVMatrix * matStack[int(matrixID)] * vec4(aNormal, 0.0)));\n\
|
vec3 adjNorm = normalize(vec3(uMVMatrix * matStack[int(matrixID)] * vec4(aNormal, 0.0)));\n\
|
||||||
float diffuse = 0.7-dot(adjNorm, vec3(0.0, -1.0, 0.0))*0.3;\n\
|
float diffuse = (1.0-lightIntensity)-dot(adjNorm, vec3(0.0, -1.0, 0.0))*lightIntensity;\n\
|
||||||
\n\
|
\n\
|
||||||
color = aColor*colMult;\n\
|
color = aColor*colMult;\n\
|
||||||
color = vec4(color.x*diffuse, color.y*diffuse, color.z*diffuse, color.w);\n\
|
color = vec4(color.x*diffuse, color.y*diffuse, color.z*diffuse, color.w);\n\
|
||||||
|
@ -270,6 +301,7 @@ window.nitroShaders = new (function() {
|
||||||
var shadUnif = [
|
var shadUnif = [
|
||||||
["shadowMatUniform", "shadowMat"],
|
["shadowMatUniform", "shadowMat"],
|
||||||
["farShadowMatUniform", "farShadowMat"],
|
["farShadowMatUniform", "farShadowMat"],
|
||||||
|
["lightIntensityUniform", "lightIntensity"],
|
||||||
|
|
||||||
["shadOffUniform", "shadOff"],
|
["shadOffUniform", "shadOff"],
|
||||||
["farShadOffUniform", "farShadOff"],
|
["farShadOffUniform", "farShadOff"],
|
||||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue