diff options
author | Kevin Rushforth <[email protected]> | 2004-06-09 04:25:41 +0000 |
---|---|---|
committer | Kevin Rushforth <[email protected]> | 2004-06-09 04:25:41 +0000 |
commit | 343b658c32a6473c545187c1e276ee5d06c2686a (patch) | |
tree | ad2606538b7db1c3553c53a79ccccb2ed5b5e4e2 /src/native/d3d/GeometryArrayRetained.cpp | |
parent | 06cebb1e576da6f7222f999ab059dcfa3d8edd39 (diff) |
Initial creation of j3d-core-utils sources in CVS repository
git-svn-id: https://svn.java.net/svn/j3d-core~svn/trunk@7 ba19aa83-45c5-6ac9-afd3-db810772062c
Diffstat (limited to 'src/native/d3d/GeometryArrayRetained.cpp')
-rw-r--r-- | src/native/d3d/GeometryArrayRetained.cpp | 5254 |
1 files changed, 5254 insertions, 0 deletions
diff --git a/src/native/d3d/GeometryArrayRetained.cpp b/src/native/d3d/GeometryArrayRetained.cpp new file mode 100644 index 0000000..e8596d0 --- /dev/null +++ b/src/native/d3d/GeometryArrayRetained.cpp @@ -0,0 +1,5254 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2004 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +#include "StdAfx.h" + + +//#define VBDEBUG +//#define TEXDEBUG + +#define getVertexFormat(texSize) \ + (((texSize) << D3DFVF_TEXCOUNT_SHIFT) & D3DFVF_TEXCOUNT_MASK) + +/* + * This correspond to the constant in d3dtypes.h + * under D3D 7.0/8.0 header and may not portable : + * D3DFVF_TEXTUREFORMAT1 3 + * D3DFVF_TEXTUREFORMAT2 0 + * D3DFVF_TEXTUREFORMAT3 1 + * D3DFVF_TEXTUREFORMAT4 2 + */ +CONST static DWORD TexFormatSizeTable[5] = {0, 3, 0, 1, 2}; +static float defaultTexCoord[4] = {0, 0, 0, 0}; + +typedef struct _D3DDRAWPRIMITIVESTRIDEDDATA +{ + DWORD positionStride; + jfloat *fpositionPtr; + jdouble *dpositionPtr; + DWORD normalStride; + jfloat *normalPtr; + DWORD diffuseStride; + jfloat *fdiffusePtr; + jbyte *bdiffusePtr; + jint *indexPtr; + jint initialIndexIndex; + DWORD textureCoordsStride[D3DDP_MAXTEXCOORD]; + jfloat* textureCoordsPtr[D3DDP_MAXTEXCOORD]; + jint texCoordPosition[D3DDP_MAXTEXCOORD]; + boolean useAlpha; + boolean modulateAlpha; + jfloat alpha; +} D3DDRAWPRIMITIVESTRIDEDDATA, *LPD3DDRAWPRIMITIVESTRIDEDDATA; + + +void copyIndexVertexToVB(D3dCtx *d3dCtx, + D3DDRAWPRIMITIVESTRIDEDDATA* strideData, + DWORD indexCount, + jint cDirty, + BOOL insertStrideToVB, + BOOL expandQuadIndex) +{ + HRESULT hr; + + if (cDirty & javax_media_j3d_GeometryArrayRetained_INDEX_CHANGED) { + jint *src = strideData->indexPtr + strideData->initialIndexIndex; + LPDIRECT3DINDEXBUFFER8 indexBuffer = d3dCtx->pVB->indexBuffer; + D3DINDEXBUFFER_DESC desc; + BYTE *bptr; + + indexBuffer->GetDesc(&desc); + hr = indexBuffer->Lock(0, 0, &bptr, 0); + if (FAILED(hr)) { + D3dCtx::d3dWarning(LOCKINDEXVBFAIL, hr); + return; + } + + int i = indexCount; + + if (desc.Format == D3DFMT_INDEX16) { + USHORT *dst = (USHORT *) bptr; + + if (!expandQuadIndex) { + while (--i >= 0) { + *dst++ = *src++; + } + } else { + USHORT *endptr = dst + (USHORT) 3*indexCount/2; + + while (dst < endptr) { + *dst++ = *src; + *dst++ = *(src+1); + *dst++ = *(src+2); + *dst++ = *src; + src++; + src++; + *dst++ = *src; + src++; + *dst++ = *src; + src++; + } + } + } else { + UINT *dst = (UINT *) bptr; + + if (!expandQuadIndex) { + while (--i >= 0) { + *dst++ = *src++; + } + } else { + UINT *endptr = dst + (UINT) 3*indexCount/2; + while (dst < endptr) { + *dst++ = *src; + *dst++ = *(src+1); + *dst++ = *(src+2); + *dst++ = *src; + src++; + src++; + *dst++ = *src; + src++; + *dst++ = *src; + src++; + } + + dst = (UINT *) bptr; + } + } + + indexBuffer->Unlock(); + } + + if (insertStrideToVB) { + d3dCtx->pVB->addStride(d3dCtx->pVB->indexCount); + } +} + +// This function copy the stride vertex data into Vertex Buffer +// point by vbptr and update vbptr +void copyVertexToVB(D3dCtx *d3dCtx, + D3DDRAWPRIMITIVESTRIDEDDATA* strideData, + DWORD vcount, + float **vbptr, + jint cDirty, + BOOL insertStrideToVB, + jdouble* xform, + jdouble* nxform) +{ + float *dst; + float *src; + double *dsrc; + DWORD i; + DWORD srcStride; + DWORD currStride; + + DWORD dstStride = d3dCtx->pVB->stride >> 2; + DWORD vertexFormat = d3dCtx->pVB->vertexFormat; + float *endptr; + + // Copy Position + if (cDirty & javax_media_j3d_GeometryArrayRetained_COORDINATE_CHANGED) { + dst = *vbptr; + // Before we call two times src++ in position and + // normal copy so we only need to add dstStride - 2 + // at the end. + srcStride = strideData->positionStride - 2; + endptr = dst + vcount*dstStride; + dstStride -= 2; + src = strideData->fpositionPtr; + + if (xform == NULL) { + if (src != NULL) { + while (dst < endptr) { + *dst++ = *src++; // pos x + *dst++ = *src++; // pos y + *dst = *src; // pos z + dst += dstStride; + src += srcStride; + } + } else { + // double is used for position coordinate in executeVA() + dsrc = strideData->dpositionPtr; + while (dst < endptr) { + *dst++ = *dsrc++; // pos x + *dst++ = *dsrc++; // pos y + *dst = *dsrc; // pos z + dst += dstStride; + dsrc += srcStride; + } + } + } else { + if (src != NULL) { + float x, y, z, w; + while (dst < endptr) { + x = *src++; + y = *src++; + z = *src; // pos z + w = 1/(xform[12]*x + xform[13]*y + xform[14]*z + xform[15]); + *dst++ = (xform[0]*x + xform[1]*y + xform[2]*z + xform[3])*w; + *dst++ = (xform[4]*x + xform[5]*y + xform[6]*z + xform[7])*w; + *dst = (xform[8]*x + xform[9]*y + xform[10]*z + xform[11])*w; + dst += dstStride; + src += srcStride; + } + } else { + double x, y, z, w; + // double is used for position coordinate in executeVA() + dsrc = strideData->dpositionPtr; + while (dst < endptr) { + x = *src++; + y = *src++; + z = *src; // pos z + w = 1/(xform[12]*x + xform[13]*y + xform[14]*z + xform[15]); + *dst++ = (xform[0]*x + xform[1]*y + xform[2]*z + xform[3])*w; + *dst++ = (xform[4]*x + xform[5]*y + xform[6]*z + xform[7])*w; + *dst = (xform[8]*x + xform[9]*y + xform[10]*z + xform[11])*w; + dst += dstStride; + dsrc += srcStride; + } + } + + } + // restore value + dstStride += 2; + } + + // Copy Normal + if (vertexFormat & D3DFVF_NORMAL) { + if (cDirty & javax_media_j3d_GeometryArrayRetained_NORMAL_CHANGED) { + dst = *vbptr + 3; + src = strideData->normalPtr; + srcStride = strideData->normalStride - 2; + endptr = dst + vcount*dstStride; + dstStride -= 2; + if (nxform == NULL) { + while (dst < endptr) { + *dst++ = *src++; // norm x + *dst++ = *src++; // norm y + *dst = *src; // norm z + dst += dstStride; + src += srcStride; + } + } else { + float nx, ny, nz, nw; + while (dst < endptr) { + nx = *src++; + ny = *src++; + nz = *src; // pos z + nw = 1/(nxform[12]*nx + nxform[13]*ny + nxform[14]*nz + nxform[15]); + *dst++ = (nxform[0]*nx + nxform[1]*ny + nxform[2]*nz + nxform[3])*nw; + *dst++ = (nxform[4]*nx + nxform[5]*ny + nxform[6]*nz + nxform[7])*nw; + *dst = (nxform[8]*nx + nxform[9]*ny + nxform[10]*nz + nxform[11])*nw; + dst += dstStride; + dsrc += srcStride; + } + } + // restore value + dstStride += 2; + } + // nx,ny,nz copy in addtion to x, y, z + currStride = 6; + } else { + // This is used to keep track of the offset + // from beginning of the current type copy. + currStride = 3; // x,y,z already copy + } + + // Copy Diffuse Color (DWORD & float are of the same size) + + if (vertexFormat & D3DFVF_DIFFUSE) { + if (cDirty & javax_media_j3d_GeometryArrayRetained_COLOR_CHANGED) { + + DWORD* wdst = (DWORD *) *vbptr + currStride; + DWORD* wendptr = wdst + vcount*dstStride; + + if (strideData->fdiffusePtr) { + float* wsrc = strideData->fdiffusePtr; + float r, g, b, a; + if ((d3dCtx->currDisplayListID <= 0) || + !strideData->modulateAlpha) { + // execute() or executeVA() + + if (strideData->useAlpha) { + srcStride = strideData->diffuseStride - 3; + while (wdst < wendptr) { + r = *wsrc++; + g = *wsrc++; + b = *wsrc++; + a = *wsrc; + *wdst = D3DCOLOR_COLORVALUE(r, g, b, a); + wdst += dstStride; + wsrc += srcStride; + } + } else { + srcStride = strideData->diffuseStride - 2; + while (wdst < wendptr) { + r = *wsrc++; + g = *wsrc++; + b = *wsrc; + *wdst = D3DCOLOR_COLORVALUE(r, g, b, 0); + wdst += dstStride; + wsrc += srcStride; + } + } + } else { + // buildGA() & modulateAlpha + float alpha = strideData->alpha; + if (strideData->useAlpha) { + srcStride = strideData->diffuseStride - 3; + while (wdst < wendptr) { + r = *wsrc++; + g = *wsrc++; + b = *wsrc++; + a = *wsrc * alpha; + *wdst = D3DCOLOR_COLORVALUE(r, g, b, a); + wdst += dstStride; + wsrc += srcStride; + } + } else { + srcStride = strideData->diffuseStride - 2; + while (wdst < wendptr) { + r = *wsrc++; + g = *wsrc++; + b = *wsrc; + *wdst = D3DCOLOR_COLORVALUE(r, g, b, alpha); + wdst += dstStride; + wsrc += srcStride; + } + } + + } + } else { // byte color pointer + jbyte* wsrc = strideData->bdiffusePtr; + jbyte r, g, b, a; + if ((d3dCtx->currDisplayListID <= 0) || + !strideData->modulateAlpha) { + // execute() or executeVA() + + if (strideData->useAlpha) { + srcStride = strideData->diffuseStride - 3; + while (wdst < wendptr) { + r = *wsrc++; + g = *wsrc++; + b = *wsrc++; + a = *wsrc; + *wdst = D3DCOLOR_RGBA(r, g, b, a); + wdst += dstStride; + wsrc += srcStride; + } + } else { + srcStride = strideData->diffuseStride - 2; + while (wdst < wendptr) { + r = *wsrc++; + g = *wsrc++; + b = *wsrc; + *wdst = D3DCOLOR_RGBA(r, g, b, 0); + wdst += dstStride; + wsrc += srcStride; + } + } + } else { + // buildGA() & modeulateAlpha + // Currently buildGA() will not use byte color + // so this code should never execute. + jbyte alpha = (jbyte) 255*strideData->alpha; + if (strideData->useAlpha) { + srcStride = strideData->diffuseStride - 3; + while (wdst < wendptr) { + r = *wsrc++; + g = *wsrc++; + b = *wsrc++; + a = (jbyte)(((int)(*wsrc) & 0xff) * strideData->alpha); + *wdst = D3DCOLOR_RGBA(r, g, b, a); + wdst += dstStride; + wsrc += srcStride; + } + } else { + srcStride = strideData->diffuseStride - 2; + while (wdst < wendptr) { + r = *wsrc++; + g = *wsrc++; + b = *wsrc; + *wdst = D3DCOLOR_RGBA(r, g, b, alpha); + wdst += dstStride; + wsrc += srcStride; + } + } + + } + } + + } + + currStride++; // additional one DWORD of color copy + } + + // Copy Texture + int ts; + int texPos; + boolean invalidTexCoord; + +#ifdef TEXDEBUG + printf("In copyVertexToVB TexSet Used %d\n", d3dCtx->texSetUsed); +#endif + for (i=0; i < d3dCtx->texSetUsed; i++) { + ts = d3dCtx->texStride[i]; + + // TODO: skip when ts = 0 + if (ts == 0) { + continue; + } + texPos = strideData->texCoordPosition[i]; + + invalidTexCoord = ((texPos != d3dCtx->pVB->texCoordPosition[i]) || + (texPos == TEX_OBJ_LINEAR)); + +#ifdef TEXDEBUG + printf("%d texPos %d, invalidate Cached TexCoord %d, ts %d\n",i, texPos, invalidTexCoord, ts); +#endif + if ((cDirty & javax_media_j3d_GeometryArrayRetained_TEXTURE_CHANGED) || + invalidTexCoord) { + + if (texPos >= 0) { + dst = *vbptr + currStride; + src = strideData->textureCoordsPtr[i]; + endptr = dst + vcount*dstStride; +#ifdef TEXDEBUG + printf("copy directly, ts %d\n", ts); +#endif + if (ts == 2) { + dstStride--; + srcStride = strideData->textureCoordsStride[i] - 1; + while (dst < endptr) { + *dst++ = *src++; // tx + *dst = *src; // ty + dst += dstStride; + src += srcStride; + } + dstStride++; + } else if (ts == 3) { + dstStride -= 2; + srcStride = strideData->textureCoordsStride[i] - 2; + while (dst < endptr) { + *dst++ = *src++; // tx + *dst++ = *src++; // ty + *dst = *src; // tz + dst += dstStride; + src += srcStride; + } + dstStride += 2; + } else { + // ts == 4 + dstStride -= 3; + srcStride = strideData->textureCoordsStride[i] - 3; + while (dst < endptr) { + *dst++ = *src++; // tx + *dst++ = *src++; // ty + *dst++ = *src++; // tz + *dst = *src; // tw + dst += dstStride; + src += srcStride; + } + dstStride += 3; + } + + } else { + if (texPos == TEX_OBJ_LINEAR) { + // automatic texture generation for Object Linear + float *ps = d3dCtx->planeS[i]; + float *pt = d3dCtx->planeT[i]; + float *pr = d3dCtx->planeR[i]; + float *pq = d3dCtx->planeQ[i]; +#ifdef TEXDEBUG + printf("gen obj linear tex, ts %d\n", ts); +#endif + if (strideData->fpositionPtr) { + float x, y, z; + dst = *vbptr + currStride; + endptr = dst + vcount*dstStride; + src = strideData->fpositionPtr; + srcStride = strideData->positionStride - 2; + if (ts == 2) { + dstStride--; + if (xform == NULL) { + while (dst < endptr) { + x = *src++; + y = *src++; + z = *src; + *dst++ = ps[0]*x + ps[1]*y + ps[2]*z + ps[3]; + *dst = pt[0]*x + pt[1]*y + pt[2]*z + pt[3]; + dst += dstStride; + src += srcStride; + } + } else { + float tx, ty, tz, tw; + while (dst < endptr) { + tx = *src++; + ty = *src++; + tz = *src; + tw = 1/(xform[12]*x + xform[13]*y + xform[14]*z + xform[15]); + x = (xform[0]*tx + xform[1]*ty + xform[2]*tz + xform[3])*tw; + y = (xform[4]*tx + xform[5]*ty + xform[6]*tz + xform[7])*tw; + z = (xform[8]*tx + xform[9]*ty + xform[10]*tz + xform[11])*tw; + *dst++ = ps[0]*x + ps[1]*y + ps[2]*z + ps[3]; + *dst = pt[0]*x + pt[1]*y + pt[2]*z + pt[3]; + dst += dstStride; + src += srcStride; + } + } + dstStride++; + } else if (ts == 3) { + dstStride -= 2; + if (xform == NULL) { + while (dst < endptr) { + x = *src++; + y = *src++; + z = *src; + *dst++ = ps[0]*x + ps[1]*y + ps[2]*z + ps[3]; + *dst++ = pt[0]*x + pt[1]*y + pt[2]*z + pt[3]; + *dst = pr[0]*x + pr[1]*y + pr[2]*z + pr[3]; + dst += dstStride; + src += srcStride; + } + } else { + float tx, ty, tz, tw; + while (dst < endptr) { + tx = *src++; + ty = *src++; + tz = *src; + tw = 1/(xform[12]*x + xform[13]*y + xform[14]*z + xform[15]); + x = (xform[0]*tx + xform[1]*ty + xform[2]*tz + xform[3])*tw; + y = (xform[4]*tx + xform[5]*ty + xform[6]*tz + xform[7])*tw; + z = (xform[8]*tx + xform[9]*ty + xform[10]*tz + xform[11])*tw; + *dst++ = ps[0]*x + ps[1]*y + ps[2]*z + ps[3]; + *dst++ = pt[0]*x + pt[1]*y + pt[2]*z + pt[3]; + *dst = pr[0]*x + pr[1]*y + pr[2]*z + pr[3]; + dst += dstStride; + src += srcStride; + } + } + + dstStride += 2; + } else { + // ts == 4 + dstStride -= 3; + + if (!d3dCtx->texTransformSet[i]) { + if (xform == NULL) { + while (dst < endptr) { + x = *src++; + y = *src++; + z = *src; + *dst++ = ps[0]*x + ps[1]*y + ps[2]*z + ps[3]; + *dst++ = pt[0]*x + pt[1]*y + pt[2]*z + pt[3]; + *dst++ = pr[0]*x + pr[1]*y + pr[2]*z + pr[3]; + *dst = pq[0]*x + pq[1]*y + pq[2]*z + pq[3]; + dst += dstStride; + src += srcStride; + } + } else { + float tx, ty, tz, tw; + while (dst < endptr) { + tx = *src++; + ty = *src++; + tz = *src; + tw = 1/(xform[12]*x + xform[13]*y + xform[14]*z + xform[15]); + x = (xform[0]*tx + xform[1]*ty + xform[2]*tz + xform[3])*tw; + y = (xform[4]*tx + xform[5]*ty + xform[6]*tz + xform[7])*tw; + z = (xform[8]*tx + xform[9]*ty + xform[10]*tz + xform[11])*tw; + *dst++ = ps[0]*x + ps[1]*y + ps[2]*z + ps[3]; + *dst++ = pt[0]*x + pt[1]*y + pt[2]*z + pt[3]; + *dst++ = pr[0]*x + pr[1]*y + pr[2]*z + pr[3]; + *dst = pq[0]*x + pq[1]*y + pq[2]*z + pq[3]; + dst += dstStride; + src += srcStride; + } + } + } else { + // do texture transform manually + D3DXMATRIX *m = &(d3dCtx->texTransform[i]); + double tx, ty, tz, tw; + if (xform == NULL) { + while (dst < endptr) { + x = *src++; + y = *src++; + z = *src; + tx = ps[0]*x + ps[1]*y + ps[2]*z + ps[3]; + ty = pt[0]*x + pt[1]*y + pt[2]*z + pt[3]; + tz = pr[0]*x + pr[1]*y + pr[2]*z + pr[3]; + tw = pq[0]*x + pq[1]*y + pq[2]*z + pq[3]; + *dst++ = (*m)._11*tx + (*m)._21*ty + (*m)._31*tz + (*m)._41*tw; + *dst++ = (*m)._12*tx + (*m)._22*ty + (*m)._32*tz + (*m)._42*tw; + *dst++ = (*m)._13*tx + (*m)._23*ty + (*m)._33*tz + (*m)._43*tw; + *dst = (*m)._14*tx + (*m)._24*ty + (*m)._34*tz + (*m)._44*tw; + dst += dstStride; + src += srcStride; + } + } else { + float tx, ty, tz, tw; + while (dst < endptr) { + tx = *src++; + ty = *src++; + tz = *src; + tw = 1/(xform[12]*x + xform[13]*y + xform[14]*z + xform[15]); + x = (xform[0]*tx + xform[1]*ty + xform[2]*tz + xform[3])*tw; + y = (xform[4]*tx + xform[5]*ty + xform[6]*tz + xform[7])*tw; + z = (xform[8]*tx + xform[9]*ty + xform[10]*tz + xform[11])*tw; + tx = ps[0]*x + ps[1]*y + ps[2]*z + ps[3]; + ty = pt[0]*x + pt[1]*y + pt[2]*z + pt[3]; + tz = pr[0]*x + pr[1]*y + pr[2]*z + pr[3]; + tw = pq[0]*x + pq[1]*y + pq[2]*z + pq[3]; + *dst++ = (*m)._11*tx + (*m)._21*ty + (*m)._31*tz + (*m)._41*tw; + *dst++ = (*m)._12*tx + (*m)._22*ty + (*m)._32*tz + (*m)._42*tw; + *dst++ = (*m)._13*tx + (*m)._23*ty + (*m)._33*tz + (*m)._43*tw; + *dst = (*m)._14*tx + (*m)._24*ty + (*m)._34*tz + (*m)._44*tw; + dst += dstStride; + src += srcStride; + } + } + } + dstStride += 3; + } + } else { + // double type position pointer + double x, y, z; + dst = *vbptr + currStride; + endptr = dst + vcount*dstStride; + dsrc = strideData->dpositionPtr; + srcStride = strideData->positionStride - 2; + if (ts == 2) { + dstStride--; + if (xform == NULL) { + while (dst < endptr) { + x = *dsrc++; + y = *dsrc++; + z = *dsrc; + *dst++ = ps[0]*x + ps[1]*y + ps[2]*z + ps[3]; + *dst = pt[0]*x + pt[1]*y + pt[2]*z + pt[3]; + dst += dstStride; + dsrc += srcStride; + } + } else { + double tx, ty, tz, tw; + while (dst < endptr) { + tx = *src++; + ty = *src++; + tz = *src; + tw = 1/(xform[12]*x + xform[13]*y + xform[14]*z + xform[15]); + x = (xform[0]*tx + xform[1]*ty + xform[2]*tz + xform[3])*tw; + y = (xform[4]*tx + xform[5]*ty + xform[6]*tz + xform[7])*tw; + z = (xform[8]*tx + xform[9]*ty + xform[10]*tz + xform[11])*tw; + *dst++ = ps[0]*x + ps[1]*y + ps[2]*z + ps[3]; + *dst = pt[0]*x + pt[1]*y + pt[2]*z + pt[3]; + dst += dstStride; + src += srcStride; + } + } + dstStride++; + } else if (ts == 3) { + dstStride -= 2; + if (xform == NULL) { + while (dst < endptr) { + x = *dsrc++; + y = *dsrc++; + z = *dsrc; + *dst++ = ps[0]*x + ps[1]*y + ps[2]*z + ps[3]; + *dst++ = pt[0]*x + pt[1]*y + pt[2]*z + pt[3]; + *dst = pr[0]*x + pr[1]*y + pr[2]*z + pr[3]; + dst += dstStride; + dsrc += srcStride; + } + } else { + double tx, ty, tz, tw; + while (dst < endptr) { + tx = *src++; + ty = *src++; + tz = *src; + tw = 1/(xform[12]*x + xform[13]*y + xform[14]*z + xform[15]); + x = (xform[0]*tx + xform[1]*ty + xform[2]*tz + xform[3])*tw; + y = (xform[4]*tx + xform[5]*ty + xform[6]*tz + xform[7])*tw; + z = (xform[8]*tx + xform[9]*ty + xform[10]*tz + xform[11])*tw; + *dst++ = ps[0]*x + ps[1]*y + ps[2]*z + ps[3]; + *dst++ = pt[0]*x + pt[1]*y + pt[2]*z + pt[3]; + *dst = pr[0]*x + pr[1]*y + pr[2]*z + pr[3]; + dst += dstStride; + src += srcStride; + } + } + dstStride += 2; + } else { + // ts == 4 + dstStride -= 3; + if (!d3dCtx->texTransformSet[i]) { + if (xform == NULL) { + while (dst < endptr) { + x = *dsrc++; + y = *dsrc++; + z = *dsrc; + *dst++ = ps[0]*x + ps[1]*y + ps[2]*z + ps[3]; + *dst++ = pt[0]*x + pt[1]*y + pt[2]*z + pt[3]; + *dst++ = pr[0]*x + pr[1]*y + pr[2]*z + pr[3]; + *dst = pq[0]*x + pq[1]*y + pq[2]*z + pq[3]; + dst += dstStride; + dsrc += srcStride; + } + } else { + double tx, ty, tz, tw; + while (dst < endptr) { + tx = *src++; + ty = *src++; + tz = *src; + tw = 1/(xform[12]*x + xform[13]*y + xform[14]*z + xform[15]); + x = (xform[0]*tx + xform[1]*ty + xform[2]*tz + xform[3])*tw; + y = (xform[4]*tx + xform[5]*ty + xform[6]*tz + xform[7])*tw; + z = (xform[8]*tx + xform[9]*ty + xform[10]*tz + xform[11])*tw; + *dst++ = ps[0]*x + ps[1]*y + ps[2]*z + ps[3]; + *dst++ = pt[0]*x + pt[1]*y + pt[2]*z + pt[3]; + *dst++ = pr[0]*x + pr[1]*y + pr[2]*z + pr[3]; + *dst = pq[0]*x + pq[1]*y + pq[2]*z + pq[3]; + dst += dstStride; + src += srcStride; + } + } + } else { +// do texture transform manually + D3DXMATRIX *m = &(d3dCtx->texTransform[i]); + double tx, ty, tz, tw; + if (xform == NULL) { + while (dst < endptr) { + x = *src++; + y = *src++; + z = *src; + tx = ps[0]*x + ps[1]*y + ps[2]*z + ps[3]; + ty = pt[0]*x + pt[1]*y + pt[2]*z + pt[3]; + tz = pr[0]*x + pr[1]*y + pr[2]*z + pr[3]; + tw = pq[0]*x + pq[1]*y + pq[2]*z + pq[3]; + *dst++ = ((*m)._11*tx + (*m)._21*ty + (*m)._31*tz + (*m)._41*tw); + *dst++ = ((*m)._12*tx + (*m)._22*ty + (*m)._32*tz + (*m)._42*tw); + *dst++ = ((*m)._13*tx + (*m)._23*ty + (*m)._33*tz + (*m)._43*tw); + *dst = (*m)._14*tx + (*m)._24*ty + (*m)._34*tz + (*m)._44*tw; + dst += dstStride; + src += srcStride; + } + } else { + float tx, ty, tz, tw; + while (dst < endptr) { + tx = *src++; + ty = *src++; + tz = *src; + tw = 1/(xform[12]*x + xform[13]*y + xform[14]*z + xform[15]); + x = (xform[0]*tx + xform[1]*ty + xform[2]*tz + xform[3])*tw; + y = (xform[4]*tx + xform[5]*ty + xform[6]*tz + xform[7])*tw; + z = (xform[8]*tx + xform[9]*ty + xform[10]*tz + xform[11])*tw; + tx = ps[0]*x + ps[1]*y + ps[2]*z + ps[3]; + ty = pt[0]*x + pt[1]*y + pt[2]*z + pt[3]; + tz = pr[0]*x + pr[1]*y + pr[2]*z + pr[3]; + tw = pq[0]*x + pq[1]*y + pq[2]*z + pq[3]; + *dst++ = ((*m)._11*tx + (*m)._21*ty + (*m)._31*tz + (*m)._41*tw); + *dst++ = ((*m)._12*tx + (*m)._22*ty + (*m)._32*tz + (*m)._42*tw); + *dst++ = ((*m)._13*tx + (*m)._23*ty + (*m)._33*tz + (*m)._43*tw); + *dst = (*m)._14*tx + (*m)._24*ty + (*m)._34*tz + (*m)._44*tw; + dst += dstStride; + src += srcStride; + } + } + } + dstStride += 3; + } + } + } else if (texPos == TEX_GEN_INVALID) { + // application error, disable by setting texCoord to zero +#ifdef TEXDEBUG + printf("app error, ts %d\n", ts); +#endif + dst = *vbptr + currStride; + endptr = dst + vcount*dstStride; + if (ts == 2) { + dstStride--; + while (dst < endptr) { + *dst++ = 0; + *dst = 0; + dst += dstStride; + } + dstStride++; + } else if (ts == 3) { + dstStride -= 2; + while (dst < endptr) { + *dst++ = 0; + *dst++ = 0; + *dst = 0; + dst += dstStride; + } + dstStride += 2; + } else { + // ts == 4 + dstStride -= 3; + while (dst < endptr) { + *dst++ = 0; + *dst++ = 0; + *dst++ = 0; + *dst = 0; + dst += dstStride; + } + dstStride += 3; + } + } else { + // Other automatic texture generation type handle + // by driver + //printf("TexStage %d, Tex gen by driver, texPos = %d\n", i, texPos); + } + } + } + + currStride += ts; + } + + if (insertStrideToVB) { + d3dCtx->pVB->addStride(vcount); + } + + // Adjust VB pointer so that when this function is invoked + // again, it append to the VB correctly. + *vbptr += (vcount*dstStride); +} + + +void copyOneVertexToVB(D3dCtx *d3dCtx, + float **vbptr, + D3DDRAWPRIMITIVESTRIDEDDATA* strideData, + DWORD idx, + jint cDirty, + jdouble* xform, + jdouble* nxform) +{ + float *src; + float *dst = *vbptr; + DWORD vertexFormat = d3dCtx->pVB->vertexFormat; + float posX, posY, posZ; + + // Copy Position + + // if (cDirty & javax_media_j3d_GeometryArrayRetained_COORDINATE_CHANGED) + // Set the posX, posY, posZ anyway since TexGeneration will use it + // if dirty. + + if (strideData->fpositionPtr != NULL) { + src = strideData->fpositionPtr + + idx*strideData->positionStride; + + if (xform == NULL) { + posX = *src++; // pos x + posY = *src++; // pos y + posZ = *src; // pos z + } else { + float x, y, z, w; + x = *src++; + y = *src++; + z = *src; + w = 1/(xform[12]*x + xform[13]*y + xform[14]*z + xform[15]); + posX = (xform[0]*x + xform[1]*y + xform[2]*z + xform[3])*w; + posY = (xform[4]*x + xform[5]*y + xform[6]*z + xform[7])*w; + posZ = (xform[8]*x + xform[9]*y + xform[10]*z + xform[11])*w; + } + } else { + // double is used for position coordinate in executeVA() + double *dsrc = strideData->dpositionPtr + + idx*strideData->positionStride; + + if (xform == NULL) { + posX = (float) *dsrc++; // pos x + posY = (float) *dsrc++; // pos y + posZ = (float) *dsrc; // pos z + } else { + double x, y, z, w; + x = *dsrc++; + y = *dsrc++; + z = *dsrc; + w = 1/(xform[12]*x + xform[13]*y + xform[14]*z + xform[15]); + posX = (float) (xform[0]*x + xform[1]*y + xform[2]*z + xform[3])*w; + posY = (float) (xform[4]*x + xform[5]*y + xform[6]*z + xform[7])*w; + posZ = (float) (xform[8]*x + xform[9]*y + xform[10]*z + xform[11])*w; + } + } + *dst++ = posX; + *dst++ = posY; + *dst++ = posZ; + + // Copy Normal + if (vertexFormat & D3DFVF_NORMAL) { + if (cDirty & javax_media_j3d_GeometryArrayRetained_NORMAL_CHANGED) { + src = strideData->normalPtr + + idx*strideData->normalStride; + if (nxform == NULL) { + *dst++ = *src++; // norm x + *dst++ = *src++; // norm y + *dst++ = *src; // norm z + } else { + float nx, ny, nz, nw; + nx = *src++; // norm x + ny = *src++; // norm y + nz = *src; // norm z + nw = 1/(nxform[12]*nx + nxform[13]*ny + nxform[14]*nz + nxform[15]); + *dst++ = (nxform[0]*nx + nxform[1]*ny + nxform[2]*nz + nxform[3])*nw; + *dst++ = (nxform[4]*nx + nxform[5]*ny + nxform[6]*nz + nxform[7])*nw; + *dst = (nxform[8]*nx + nxform[9]*ny + nxform[10]*nz + nxform[11])*nw; + } + } + } + + + // Copy Diffuse Color (DWORD & float are of the same size) + if (vertexFormat & D3DFVF_DIFFUSE) { + if (cDirty & javax_media_j3d_GeometryArrayRetained_COLOR_CHANGED) { + DWORD* wdst = (DWORD *) dst; + if (strideData->fdiffusePtr) { + src = strideData->fdiffusePtr + + idx*strideData->diffuseStride; + float r, g, b, a; + if ((d3dCtx->currDisplayListID <= 0) || + !strideData->modulateAlpha) { + // execute() or executeVA() + if (strideData->useAlpha) { + r = *src++; + g = *src++; + b = *src++; + a = *src; + } else { + r = *src++; + g = *src++; + b = *src; + a = 0; + } + } else { + // buildGA() & modeulateAlpha + if (strideData->useAlpha) { + r = *src++; + g = *src++; + b = *src++; + a = *src * strideData->alpha; + } else { + r = *src++; + g = *src++; + b = *src; + a = strideData->alpha; + } + } + *wdst = D3DCOLOR_COLORVALUE(r, g, b, a); + } else { // byte color pointer + jbyte* wsrc = strideData->bdiffusePtr + + idx*strideData->diffuseStride; + jbyte r, g, b, a; + if ((d3dCtx->currDisplayListID <= 0) || + !strideData->modulateAlpha) { + // execute() or executeVA() + if (strideData->useAlpha) { + r = *wsrc++; + g = *wsrc++; + b = *wsrc++; + a = *wsrc; + } else { + r = *wsrc++; + g = *wsrc++; + b = *wsrc; + a = 0; + } + } else { + // buildGA() & modeulateAlpha + // Currently buildGA() will not use byte color + // so this code should never execute. + jbyte alpha = (jbyte) (255*strideData->alpha); + if (strideData->useAlpha) { + r = *wsrc++; + g = *wsrc++; + b = *wsrc++; + a = (jbyte)(((int)(*wsrc) & 0xff) * strideData->alpha); + } else { + r = *wsrc++; + g = *wsrc++; + b = *wsrc; + a = alpha; + + } + } + *wdst = D3DCOLOR_RGBA(r, g, b, a); + } + } + dst++; // additional one DWORD of color copy + } + + + // Copy Texture + int ts; + int texPos; + boolean invalidTexCoord; + + for (int i=0; i < d3dCtx->texSetUsed; i++) { + ts = d3dCtx->texStride[i]; + if (ts == 0) { + continue; + } + texPos = strideData->texCoordPosition[i]; + + invalidTexCoord = ((texPos != d3dCtx->pVB->texCoordPosition[i]) || + (texPos == TEX_OBJ_LINEAR)); + + if ((cDirty & javax_media_j3d_GeometryArrayRetained_TEXTURE_CHANGED) || invalidTexCoord) { + if (texPos >= 0) { + src = strideData->textureCoordsPtr[i] + + idx*strideData->textureCoordsStride[i]; + *dst++ = *src++; // tx + *dst++ = *src++; // ty + if (ts >= 3) { + *dst++ = *src++; // tx + if (ts >= 4) { + *dst++ = *src; // tx + } + } + } else { + // automatic texture generation + if (texPos == TEX_OBJ_LINEAR) { + float *ps = d3dCtx->planeS[i]; + float *pt = d3dCtx->planeT[i]; + float *pr = d3dCtx->planeR[i]; + float *pq = d3dCtx->planeQ[i]; + + if ((ts < 4) || (!d3dCtx->texTransformSet[i])) { + *dst++ = ps[0]*posX + ps[1]*posY + ps[2]*posZ + ps[3]; + *dst++ = pt[0]*posX + pt[1]*posY + pt[2]*posZ + pt[3]; + if (ts >= 3) { + *dst++ = pr[0]*posX + pr[1]*posY + pr[2]*posZ + pr[3]; + if (ts >= 4) { + *dst++ = pq[0]*posX + pq[1]*posY + pq[2]*posZ + pq[3]; + } + } + } else { + float tx, ty, tz, tw; + D3DXMATRIX *m = &(d3dCtx->texTransform[i]); + tx = ps[0]*posX + ps[1]*posY + ps[2]*posZ + ps[3]; + ty = pt[0]*posX + pt[1]*posY + pt[2]*posZ + pt[3]; + tz = pr[0]*posX + pr[1]*posY + pr[2]*posZ + pr[3]; + tw = pq[0]*posX + pq[1]*posY + pq[2]*posZ + pq[3]; + *dst++ = (*m)._11*tx + (*m)._21*ty + (*m)._31*tz + (*m)._41*tw; + *dst++ = (*m)._12*tx + (*m)._22*ty + (*m)._32*tz + (*m)._42*tw; + *dst++ = (*m)._13*tx + (*m)._23*ty + (*m)._33*tz + (*m)._43*tw; + *dst++ = (*m)._14*tx + (*m)._24*ty + (*m)._34*tz + (*m)._44*tw; + } + } else if (texPos == TEX_GEN_INVALID) { + // application error, disable by setting texCoord to zero + *dst++ = 0; + *dst++ = 0; + if (ts >= 3) { + *dst++ = 0; + if (ts >= 4) { + *dst++ = 0; + } + } + } else { + // should not happen + dst += ts; + } + } + } else { + dst += ts; + } + } + + *vbptr = dst; +} + + +float* allocateVB(D3dCtx *d3dCtx, + LPDIRECT3DDEVICE8 device, + int vcount, + int maxVertexLimit, + jint *cdirty) +{ + LPD3DVERTEXBUFFER vb = d3dCtx->pVB->nextVB; + HRESULT hr; + float *ptr = NULL; + + + if (vcount > maxVertexLimit) { + vcount = maxVertexLimit; + } + + if ((vb != NULL) && (vb->vcount < vcount)) { + delete vb; + d3dCtx->pVB->nextVB = NULL; + vb = NULL; + } + + if (vb == NULL) { + vb = new D3dVertexBuffer(); + if (vb == NULL) { + D3dCtx::d3dWarning(OUTOFMEMORY); + return NULL; + } + + vb->stride = d3dCtx->pVB->stride; + vb->vertexFormat = d3dCtx->pVB->vertexFormat; + // Don't set totalVertexCount + vb->isIndexPrimitive = d3dCtx->pVB->isIndexPrimitive; + vb->primitiveType = d3dCtx->pVB->primitiveType; + vb->isPointFlagUsed = d3dCtx->pVB->isPointFlagUsed; + vb->vcount = vcount; + vb->maxVertexLimit = maxVertexLimit; + +#ifdef VBDEBUG + printf("Create secondary VertexBuffer of size %d, display list ID %d, pointFlag %d\n", + vb->vcount, d3dCtx->currDisplayListID, vb->isPointFlagUsed); +#endif + if (!vb->isPointFlagUsed) { + hr = device->CreateVertexBuffer(vb->stride*vcount, + D3DUSAGE_WRITEONLY, + vb->vertexFormat, + D3DPOOL_DEFAULT, + &vb->buffer); + } else { + hr = device->CreateVertexBuffer(vb->stride*vcount, + D3DUSAGE_WRITEONLY|D3DUSAGE_POINTS, + vb->vertexFormat, + D3DPOOL_DEFAULT, + &vb->buffer); + } + if (FAILED(hr)) { + vb->buffer = NULL; + delete vb; + D3dCtx::d3dWarning(CREATEVBFAIL, hr); + return NULL; + } + d3dCtx->pVB->nextVB = vb; + *cdirty = javax_media_j3d_GeometryArrayRetained_VERTEX_CHANGED; + } + + hr = vb->buffer->Lock(0, 0, (BYTE**) &ptr, 0); + + if (FAILED(hr)) { + D3dCtx::d3dWarning(LOCKVBFAIL, hr); + delete vb; + d3dCtx->pVB->nextVB = NULL; + return NULL; + } + + d3dCtx->pVB = vb; + + vb->stripLen = 0; + return ptr; +} + + + +BOOL createCopyVBVertex(D3dCtx *d3dCtx, + LPDIRECT3DDEVICE8 device, + D3DDRAWPRIMITIVESTRIDEDDATA *strideData, + int vcount, jint cDirty, + jdouble* xform, + jdouble* nxform) +{ + LPD3DVERTEXBUFFER vb = d3dCtx->pVB; + float *vbptr; + + + if (vb->stripLen > 0) { + // VertexBuffer already used, create a new one or used + // the next VB in the list + // maxVertexLimit is already check before, so we can + // pass vcount as maxVertexLimit + vbptr = allocateVB(d3dCtx, device, vcount, vcount, &cDirty); + if (vbptr == NULL) { + return FALSE; + } + + } else { + // use the same VB + HRESULT hr; + hr = vb->buffer->Lock(0, 0, (BYTE**)&vbptr, 0); + + if (FAILED(hr)) { + D3dCtx::d3dWarning(LOCKVBFAIL, hr); + return FALSE; + } + + } + + copyVertexToVB(d3dCtx, strideData, vcount, &vbptr, cDirty, true, + xform, nxform); + + d3dCtx->pVB->buffer->Unlock(); + return TRUE; +} + + +/* + * Draw Primitive with vertexCount > D3DMAXNUMVERTICES. + * In this case we call the drawing routine multiple times. + */ +void splitVertexToMultipleVB(D3dCtx *d3dCtx, + LPD3DDRAWPRIMITIVESTRIDEDDATA strideData, + int vcount, + int maxVertexLimit, + jint cDirty, + jdouble* xform, + jdouble* nxform) +{ + int i, inc; + int min = 0; + int max = 0; + jfloat *oldfPosition; + double *olddPosition; + jfloat *oldNormal; + jfloat *oldfDiffuse; + jbyte *oldbDiffuse; + float* oldTexCoords[D3DDP_MAXTEXCOORD]; + int vc; + int texSetUsed = d3dCtx->texSetUsed; + LPDIRECT3DDEVICE8 device = d3dCtx->pDevice; + jfloat fr, fg, fb, fa; + jbyte br, bg, bb, ba; + boolean success; + + DWORD vertexFormat = d3dCtx->pVB->vertexFormat; + + // save stride pointers since strip set may have + // multiple call to this procedure. + oldfPosition = strideData->fpositionPtr; + olddPosition = strideData->dpositionPtr; + oldNormal = strideData->normalPtr; + oldfDiffuse = strideData->fdiffusePtr; + oldbDiffuse = strideData->bdiffusePtr; + + for (i=0; i < texSetUsed; i++) { + oldTexCoords[i] = strideData->textureCoordsPtr[i]; + } + + + + switch (d3dCtx->pVB->primitiveType) { + case D3DPT_TRIANGLEFAN: + { + // Copy the very first vertx and repeat the last vertex + jfloat fx, fy, fz, nx, ny, nz; + jdouble dx, dy, dz; + jfloat tx[D3DDP_MAXTEXCOORD]; + jfloat ty[D3DDP_MAXTEXCOORD]; + jfloat tz[D3DDP_MAXTEXCOORD]; + jfloat tw[D3DDP_MAXTEXCOORD]; + inc = maxVertexLimit - 2; + + if (oldfPosition) { + fx = *oldfPosition; + fy = *(oldfPosition+1); + fz = *(oldfPosition+2); + } else { + // must be double, since this routine will + // not invoke when there is no position available + dx = *olddPosition; + dy = *(olddPosition+1); + dz = *(olddPosition+2); + } + + if (oldNormal) { + nx = *oldNormal; + ny = *(oldNormal+1); + nz = *(oldNormal+2); + } + if (oldfDiffuse) { + fr = *oldfDiffuse; + fg = *(oldfDiffuse+1); + fb = *(oldfDiffuse+2); + if (strideData->useAlpha) { + fa = *(oldfDiffuse+3); + } + } else if (oldbDiffuse) { + br = *oldbDiffuse; + bg = *(oldbDiffuse+1); + bb = *(oldbDiffuse+2); + if (strideData->useAlpha) { + ba = *(oldbDiffuse+3); + } + } + + for (i=0; i < texSetUsed; i++) { + tx[i] = *oldTexCoords[i]; + ty[i] = *(oldTexCoords[i]+1); + if (d3dCtx->texStride[i] > 2) { + tz[i] = *(oldTexCoords[i]+2); + if (d3dCtx->texStride[i] > 3) { + tw[i] = *(oldTexCoords[i]+3); + } + } + } + while (true) { + vc = (vcount >= maxVertexLimit ? maxVertexLimit : vcount); + + success = createCopyVBVertex(d3dCtx, device, strideData, + vc, cDirty, xform, nxform); + // restore old values + if (oldfPosition) { + *(strideData->fpositionPtr) = fx; + *(strideData->fpositionPtr+1) = fy; + *(strideData->fpositionPtr+2) = fz; + } else { + *(strideData->dpositionPtr) = dx; + *(strideData->dpositionPtr+1) = dy; + *(strideData->dpositionPtr+2) = dz; + } + if (oldNormal) { + *(strideData->normalPtr) = nx; + *(strideData->normalPtr+1) = ny; + *(strideData->normalPtr+2) = nz; + } + if (oldfDiffuse) { + *(strideData->fdiffusePtr) = fr; + *(strideData->fdiffusePtr+1) = fg; + *(strideData->fdiffusePtr+2) = fb; + if (strideData->useAlpha) { + *(strideData->fdiffusePtr+3) = fa; + } + } else if (oldbDiffuse) { + *(strideData->bdiffusePtr) = br; + *(strideData->bdiffusePtr+1) = bg; + *(strideData->bdiffusePtr+2) = bb; + if (strideData->useAlpha) { + *(strideData->bdiffusePtr+3) = ba; + } + } + for (i=0; i < texSetUsed; i++) { + *(strideData->textureCoordsPtr[i]) = tx[i]; + *(strideData->textureCoordsPtr[i]+1) = ty[i]; + if (d3dCtx->texStride[i] > 2) { + *(strideData->textureCoordsPtr[i]+2) = tz[i]; + if (d3dCtx->texStride[i] > 3) { + *(strideData->textureCoordsPtr[i]+3) = tw[i]; + } + } + } + + vcount -= inc; + if (!success || (vcount <= 2)) { + break; + } + + if (oldfPosition) { + strideData->fpositionPtr += strideData->positionStride*inc; + fx = *strideData->fpositionPtr; + *strideData->fpositionPtr = *oldfPosition; + fy = *(strideData->fpositionPtr+1); + *(strideData->fpositionPtr+1) = *(oldfPosition+1); + fz = *(strideData->fpositionPtr+2); + *(strideData->fpositionPtr+2) = *(oldfPosition+2); + } else { + strideData->dpositionPtr += strideData->positionStride*inc; + dx = *strideData->dpositionPtr; + *strideData->dpositionPtr = *olddPosition; + dy = *(strideData->dpositionPtr+1); + *(strideData->dpositionPtr+1) = *(olddPosition+1); + dz = *(strideData->dpositionPtr+2); + *(strideData->dpositionPtr+2) = *(olddPosition+2); + } + + + if (oldNormal) { + strideData->normalPtr += strideData->normalStride*inc; + nx = *strideData->normalPtr; + *strideData->normalPtr = *oldNormal; + ny = *(strideData->normalPtr+1); + *(strideData->normalPtr+1) = *(oldNormal+1); + nz = *(strideData->normalPtr+2); + *(strideData->normalPtr+2) = *(oldNormal+2); + } + + if (oldfDiffuse) { + strideData->fdiffusePtr += strideData->diffuseStride*inc; + fr = *strideData->fdiffusePtr; + *strideData->fdiffusePtr = *oldfDiffuse; + fg = *(strideData->fdiffusePtr+1); + *(strideData->fdiffusePtr+1) = *(oldfDiffuse+1); + fb = *(strideData->fdiffusePtr+2); + *(strideData->fdiffusePtr+2) = *(oldfDiffuse+2); + if (strideData->useAlpha) { + fa = *(strideData->fdiffusePtr+3); + *(strideData->fdiffusePtr+3) = *(oldfDiffuse+3); + } + } else if (oldbDiffuse) { + strideData->bdiffusePtr += strideData->diffuseStride*inc; + br = *strideData->bdiffusePtr; + *strideData->bdiffusePtr = *oldbDiffuse; + bg = *(strideData->bdiffusePtr+1); + *(strideData->bdiffusePtr+1) = *(oldbDiffuse+1); + bb = *(strideData->bdiffusePtr+2); + *(strideData->bdiffusePtr+2) = *(oldbDiffuse+2); + if (strideData->useAlpha) { + ba = *(strideData->bdiffusePtr+3); + *(strideData->bdiffusePtr+3) = *(oldbDiffuse+3); + } + } + + for (i=0; i < texSetUsed; i++) { + strideData->textureCoordsPtr[i] += + strideData->textureCoordsStride[i]*inc; + + tx[i] = *strideData->textureCoordsPtr[i]; + ty[i] = *(strideData->textureCoordsPtr[i]+1); + *(strideData->textureCoordsPtr[i]) = *oldTexCoords[i]; + *(strideData->textureCoordsPtr[i]+1) = *(oldTexCoords[i]+1); + if (d3dCtx->texStride[i] > 2) { + tz[i] = *(strideData->textureCoordsPtr[i]+2); + *(strideData->textureCoordsPtr[i]+2) + = *(oldTexCoords[i]+ 2); + if (d3dCtx->texStride[i] > 3) { + tw[i] = *(strideData->textureCoordsPtr[i]+3); + *(strideData->textureCoordsPtr[i]+3) + = *(oldTexCoords[i]+ 3); + } + + } + } + + } + break; + } + case D3DPT_POINTLIST: + if (max == 0) { + max = maxVertexLimit; + } + // fall through + case D3DPT_LINESTRIP: + if (max == 0) { + max = maxVertexLimit; + min = 1; // repeat the last vertex; + } + // fall through + case D3DPT_TRIANGLELIST: + if (max == 0) { + if (d3dCtx->pVB->isIndexPrimitive) { + // QuadArray + max = maxVertexLimit - (maxVertexLimit % 4); + } else { + max = maxVertexLimit - (maxVertexLimit % 3); + } + } + // fall through + case D3DPT_LINELIST: + if (max == 0) { + max = maxVertexLimit - (maxVertexLimit % 2); + } + // fall through + case D3DPT_TRIANGLESTRIP: + if (max == 0) { + max = maxVertexLimit - (maxVertexLimit % 4); + min = 2; // repeat the last two vertices + } + inc = max - min; + + while (true) { + vc = (vcount >= max ? max : vcount); + + if (!createCopyVBVertex(d3dCtx, device, strideData, vc, + cDirty, xform, nxform)) { + break; + } + + vcount -= inc; + if (vcount <= min) { + break; + } + if (oldfPosition) { + strideData->fpositionPtr += strideData->positionStride*inc; + } else { + strideData->dpositionPtr += strideData->positionStride*inc; + } + + if (oldNormal) { + strideData->normalPtr += strideData->normalStride*inc; + } + if (oldfDiffuse) { + strideData->fdiffusePtr += strideData->diffuseStride*inc; + } else if (oldbDiffuse) { + strideData->bdiffusePtr += strideData->diffuseStride*inc; + } + for (i=0; i < texSetUsed; i++) { + strideData->textureCoordsPtr[i] += + strideData->textureCoordsStride[i]*inc; + } + } + break; + } + + // Restore old pointers; + strideData->fpositionPtr = oldfPosition; + strideData->dpositionPtr = olddPosition; + strideData->normalPtr = oldNormal; + strideData->fdiffusePtr = oldfDiffuse; + strideData->bdiffusePtr = oldbDiffuse; + + for (i=0; i < texSetUsed; i++) { + strideData->textureCoordsPtr[i] = oldTexCoords[i]; + } +} + + +BOOL reIndexifyIndexVertexToVBs(D3dCtx *d3dCtx, + D3DDRAWPRIMITIVESTRIDEDDATA* strideData, + DWORD indexCount, + DWORD vcount, + jint cDirty, + BOOL expandQuadIndex, + DWORD maxVertexLimit, + jdouble* xform, + jdouble* nxform) +{ + LPD3DVERTEXBUFFER vb = d3dCtx->pVB; + HRESULT hr; + LPDIRECT3DDEVICE8 device = d3dCtx->pDevice; + + int vbSize; + + if (!expandQuadIndex) { + vbSize = indexCount; + } else { + vbSize = (3*indexCount) >> 1; + } + + if (vb->stripLen > 0) { + // VertexBuffer already used, create a new one or used + // the next VB in the list + // maxVertexLimit is already check before, so we can + // pass indexCount as maxVertexLimit. + // The maximum vertex that can happens is equal + // to indexCount so we can just set vcount = indexCount + vb = vb->nextVB; + if ((vb != NULL) && (vb->vcount < vbSize)) { + delete vb; + d3dCtx->pVB->nextVB = NULL; + vb = NULL; + } + + if (vb == NULL) { + vb = new D3dVertexBuffer(); + if (vb == NULL) { + D3dCtx::d3dWarning(OUTOFMEMORY); + return false; + } + + vb->stride = d3dCtx->pVB->stride; + vb->vertexFormat = d3dCtx->pVB->vertexFormat; + // Don't set totalVertexCount + vb->isIndexPrimitive = d3dCtx->pVB->isIndexPrimitive; + vb->primitiveType = d3dCtx->pVB->primitiveType; + vb->isPointFlagUsed = d3dCtx->pVB->isPointFlagUsed; + vb->vcount = vbSize; + vb->maxVertexLimit = maxVertexLimit; + +#ifdef VBDEBUG + printf("Create secondary VertexBuffer of size %d, display list ID %d, pointFlag %d\n", + vbSize, d3dCtx->currDisplayListID, vb->isPointFlagUsed); +#endif + + if (!vb->isPointFlagUsed) { + hr = device->CreateVertexBuffer(vb->stride*vbSize, + D3DUSAGE_WRITEONLY, + vb->vertexFormat, + D3DPOOL_DEFAULT, + &vb->buffer); + } else { + hr = device->CreateVertexBuffer(vb->stride*vbSize, + D3DUSAGE_WRITEONLY|D3DUSAGE_POINTS, + vb->vertexFormat, + D3DPOOL_DEFAULT, + &vb->buffer); + vb->isPointFlagUsed = true; + } + + if (FAILED(hr)) { + vb->buffer = NULL; + vb->release(); + D3dCtx::d3dWarning(CREATEVBFAIL, hr); + return false; + } + d3dCtx->pVB->nextVB = vb; + cDirty = javax_media_j3d_GeometryArrayRetained_VERTEX_CHANGED; + } + } + + if (vb->indexBuffer == NULL) { + // No need to set totalIndexCount + vb->indexCount = vbSize; + + if (indexCount <= 0xffff) { + hr = device->CreateIndexBuffer(vbSize*sizeof(WORD), + D3DUSAGE_WRITEONLY, + D3DFMT_INDEX16, + D3DPOOL_DEFAULT, + &vb->indexBuffer); + } else { + hr = device->CreateIndexBuffer(vbSize*sizeof(UINT), + D3DUSAGE_WRITEONLY, + D3DFMT_INDEX32, + D3DPOOL_DEFAULT, + &vb->indexBuffer); + } + + if (FAILED(hr)) { + vb->indexBuffer = NULL; + vb->release(); + D3dCtx::d3dWarning(CREATEINDEXVBFAIL, hr); + return false; + } + + cDirty |= javax_media_j3d_GeometryArrayRetained_INDEX_CHANGED; + } + + float *vbptr; + // Note that DWORD (use for color) is of same size + // as float (use for vertex/normal) + hr = vb->buffer->Lock(0, 0, (BYTE**)&vbptr, 0); + if (FAILED(hr)) { + D3dCtx::d3dWarning(LOCKVBFAIL, hr); + // recreate it next time + vb->release(); + return false; + } + + d3dCtx->pVB = vb; + + // The current VB is not yet used. + vb->stripLen = 0; + + if (cDirty) { + D3DINDEXBUFFER_DESC desc; + BYTE *bptr; + + vb->indexBuffer->GetDesc(&desc); + hr = vb->indexBuffer->Lock(0, 0, &bptr, 0); + if (FAILED(hr)) { + D3dCtx::d3dWarning(LOCKINDEXVBFAIL, hr); + vb->buffer->Unlock(); + return false; + } + + if (d3dCtx->reIndexifyTable == NULL) { + // vcount will not change during renderIndexGeometry + // and splitIndexVertex so it is safe not to check + // size of reIndexifyTable and recreate a bigger + // one. + d3dCtx->reIndexifyTable = new DWORD[vcount]; + if (d3dCtx->reIndexifyTable == NULL) { + D3dCtx::d3dWarning(OUTOFMEMORY, hr); + vb->release(); + return false; + } + + } + + ZeroMemory(d3dCtx->reIndexifyTable, sizeof(DWORD)*vcount); + + DWORD i; + jint *idxPtr = strideData->indexPtr + strideData->initialIndexIndex; + USHORT firstEntry = *idxPtr; + DWORD *table = d3dCtx->reIndexifyTable; + + if (desc.Format == D3DFMT_INDEX16) { + USHORT *dst = (USHORT *) bptr; + USHORT newIdx, prevIdx = -1, count = 0; + USHORT idx[3], vc = 0; + + for (i=0; i < indexCount; i++) { + newIdx = table[*idxPtr]; + if ((newIdx == 0) && (*idxPtr != firstEntry)) { + newIdx = ++count; + table[*idxPtr] = newIdx; + } + if (!expandQuadIndex) { + *dst++ = newIdx; + } else { + if (vc < 3) { + idx[vc++] = newIdx; + } else { + // vc = 3 + *dst++ = idx[0]; + *dst++ = idx[1]; + *dst++ = idx[2]; + *dst++ = idx[0]; + *dst++ = idx[2]; + *dst++ = newIdx; + vc = 0; + } + } + if (newIdx != prevIdx) { + copyOneVertexToVB(d3dCtx, &vbptr, strideData, + *idxPtr++, cDirty, xform, nxform); + prevIdx = newIdx; + } else { + idxPtr++; + } + + } + } else { + DWORD *dst = (DWORD *) bptr; + DWORD newIdx, prevIdx = -1, count = 0; + DWORD idx[3], vc = 0; + + for (i=0; i < indexCount; i++) { + newIdx = table[*idxPtr]; + if ((newIdx == 0) && (*idxPtr != firstEntry)) { + newIdx = ++count; + table[*idxPtr] = newIdx; + } + if (!expandQuadIndex) { + *dst++ = newIdx; + } else { + if (vc < 3) { + idx[vc++] = newIdx; + } else { + // vc = 3 + *dst++ = idx[0]; + *dst++ = idx[1]; + *dst++ = idx[2]; + *dst++ = idx[0]; + *dst++ = idx[2]; + *dst++ = newIdx; + vc = 0; + } + } + if (newIdx != prevIdx) { + copyOneVertexToVB(d3dCtx, &vbptr, strideData, + *idxPtr++, cDirty, xform, nxform); + prevIdx = newIdx; + } else { + idxPtr++; + } + } + } + } + + + vb->addStride(vbSize); + vb->indexBuffer->Unlock(); + vb->buffer->Unlock(); + return true; +} + + +void splitIndexVertexToMultipleVB(D3dCtx *d3dCtx, + LPD3DDRAWPRIMITIVESTRIDEDDATA strideData, + int indexCount, + int vertexCount, + int maxVertexLimit, + jint cDirty, + BOOL expandQuadIndex, + jdouble* xform, + jdouble* nxform) +{ + int vc; + BOOL success; + int inc; + int min = 0; + int max = 0; + int initialIdxIdx = strideData->initialIndexIndex; + + + switch (d3dCtx->pVB->primitiveType) { + case D3DPT_TRIANGLEFAN: + { + jint firstIdx = strideData->indexPtr[initialIdxIdx]; + jint prevIdx = firstIdx; + + inc = maxVertexLimit - 2; + + while (true) { + vc = (indexCount >= maxVertexLimit ? maxVertexLimit : indexCount); + success = reIndexifyIndexVertexToVBs(d3dCtx, + strideData, + vc, + vertexCount, + cDirty, + expandQuadIndex, + maxVertexLimit, + xform, nxform); + // restore index + strideData->indexPtr[strideData->initialIndexIndex] = prevIdx; + indexCount -= inc; + + if (!success || (indexCount <= 2)) { + break; + } + // repeat the last index + strideData->initialIndexIndex += (vc - 2); + // replace by first index + prevIdx = strideData->indexPtr[strideData->initialIndexIndex]; + strideData->indexPtr[strideData->initialIndexIndex] = firstIdx; + } + } + break; + case D3DPT_POINTLIST: + if (max == 0) { + max = maxVertexLimit; + } + // fall through + case D3DPT_LINESTRIP: + if (max == 0) { + max = maxVertexLimit; + min = 1; // repeat the last vertex; + } + // fall through + case D3DPT_TRIANGLELIST: + if (max == 0) { + if (expandQuadIndex) { + // QuadArray + max = maxVertexLimit - (maxVertexLimit % 4); + } else { + max = maxVertexLimit - (maxVertexLimit % 3); + } + } + // fall through + case D3DPT_LINELIST: + if (max == 0) { + max = maxVertexLimit - (maxVertexLimit % 2); + } + // fall through + case D3DPT_TRIANGLESTRIP: + if (max == 0) { + max = maxVertexLimit - (maxVertexLimit % 4); + min = 2; // repeat the last two vertices + } + inc = max - min; + + while (true) { + vc = (indexCount >= max ? max : indexCount); + + if (!reIndexifyIndexVertexToVBs(d3dCtx, + strideData, + vc, + vertexCount, + cDirty, + expandQuadIndex, + maxVertexLimit, + xform, nxform)) { + break; + } + + indexCount -= inc; + if (indexCount <= min) { + break; + } + strideData->initialIndexIndex += inc; + } + } + strideData->initialIndexIndex = initialIdxIdx; +} + +// This is used by quad polygon line mode +void DrawPolygonLine(D3dCtx *d3dCtx, + LPDIRECT3DDEVICE8 device, + DWORD vertexFormat, + D3DDRAWPRIMITIVESTRIDEDDATA *strideData) +{ + HRESULT hr; + float *vbptr; + + hr = d3dCtx->pVB->buffer->Lock(0, 0, (BYTE**) &vbptr, 0 ); + if (FAILED(hr)) { + D3dCtx::d3dWarning(LOCKVBFAIL, hr); + return; + } + // DisplayList will not use in this case, so xform = nxform = NULL + copyVertexToVB(d3dCtx, strideData, 4, &vbptr, + javax_media_j3d_GeometryArrayRetained_VERTEX_CHANGED, true, + NULL, NULL); + d3dCtx->pVB->buffer->Unlock(); + device->SetStreamSource(0, d3dCtx->pVB->buffer, + d3dCtx->pVB->stride); + device->SetIndices(d3dCtx->lineModeIndexBuffer, 0); + device->SetVertexShader(vertexFormat); + + device->DrawIndexedPrimitive(D3DPT_LINESTRIP, 0, 4, 0, 4); +} + + +// This is used by indexed quad polygon line mode +void DrawIndexPolygonLine(D3dCtx *d3dCtx, + LPDIRECT3DDEVICE8 device, + DWORD vertexFormat, + D3DDRAWPRIMITIVESTRIDEDDATA *strideData, + jint idx0, jint idx1, jint idx2, jint idx3) +{ + HRESULT hr; + float *vbptr; + + hr = d3dCtx->pVB->buffer->Lock(0, 0, (BYTE**) &vbptr, 0 ); + if (FAILED(hr)) { + D3dCtx::d3dWarning(LOCKVBFAIL, hr); + return; + } + + copyOneVertexToVB(d3dCtx, &vbptr, strideData, idx0, + javax_media_j3d_GeometryArrayRetained_VERTEX_CHANGED, + NULL, NULL); + copyOneVertexToVB(d3dCtx, &vbptr, strideData, idx1, + javax_media_j3d_GeometryArrayRetained_VERTEX_CHANGED, + NULL, NULL); + copyOneVertexToVB(d3dCtx, &vbptr, strideData, idx2, + javax_media_j3d_GeometryArrayRetained_VERTEX_CHANGED, + NULL, NULL); + copyOneVertexToVB(d3dCtx, &vbptr, strideData, idx3, + javax_media_j3d_GeometryArrayRetained_VERTEX_CHANGED, + NULL, NULL); + + d3dCtx->pVB->buffer->Unlock(); + device->SetStreamSource(0, d3dCtx->pVB->buffer, + d3dCtx->pVB->stride); + device->SetVertexShader(vertexFormat); + device->SetIndices(d3dCtx->lineModeIndexBuffer, 0); + + device->DrawIndexedPrimitive(D3DPT_LINESTRIP, 0, 4, 0, 4); +} + + +void renderGeometry(JNIEnv *env, + D3dCtx *d3dCtx, + LPDIRECT3DDEVICE8 device, + jobject geo, + jint geo_type, + D3DDRAWPRIMITIVESTRIDEDDATA *strideData, + DWORD vertexFormat, + jint vcount, + jdouble* xform, + jdouble* nxform, + jint cDirty) +{ + D3DPRIMITIVETYPE d3dRenderType; + BOOL renderTypeSet = false; + int i, j, genMode; + LPD3DVERTEXBUFFER vb = NULL; + D3dVertexBufferVector *vbVector; + float *vbptr; + +#ifdef VBDEBUG + BOOL createNew = false; +#endif + + if (vcount <= 0) { + return; + } + + jclass geoClass = env->GetObjectClass(geo); + DWORD maxVertexLimit = d3dCtx->deviceInfo->maxVertexCount[geo_type]; + DWORD texSetUsed = d3dCtx->texSetUsed; + HRESULT hr; + BOOL needPointFlag = (geo_type == GEO_TYPE_POINT_SET) || + ((geo_type != GEO_TYPE_LINE_STRIP_SET) && + (geo_type != GEO_TYPE_LINE_SET) && + (d3dCtx->fillMode == D3DFILL_POINT)); + + BOOL buildDL = (d3dCtx->currDisplayListID > 0); + + lockGeometry(); + + if (!buildDL) { + jfieldID fieldID = env->GetFieldID(geoClass, "pVertexBuffers", "J"); + jobject cloneSource = NULL; + + vbVector = reinterpret_cast<D3dVertexBufferVector *> + (env->GetLongField(geo, fieldID)); + + if (vbVector == NULL) { + // It is possible this is the mirrorGeometry + // from cloneNonIndexGeometry() + jfieldID fieldID2 = env->GetFieldID(geoClass, + "cloneSourceArray", + "Ljavax/media/j3d/IndexedGeometryArrayRetained;"); + cloneSource = env->GetObjectField(geo, fieldID2); + + if (cloneSource != NULL) { + jclass cloneClass = env->GetObjectClass(cloneSource); + fieldID = env->GetFieldID(cloneClass, "pVertexBuffers", "J"); + + vbVector = reinterpret_cast<D3dVertexBufferVector *> + (env->GetLongField(cloneSource, fieldID)); + } + + } + + + // This is the first time rendering is invoked on the + // first GeometryArray + if (vbVector == NULL) { + vbVector = new D3dVertexBufferVector(); + if (vbVector == NULL) { + D3dCtx::d3dWarning(OUTOFMEMORY); + unlockGeometry(); + return; + } + if (cloneSource == NULL) { + env->SetLongField(geo, fieldID, + reinterpret_cast<long>(vbVector)); + } else { + env->SetLongField(cloneSource, fieldID, + reinterpret_cast<long>(vbVector)); + } + + } else { + // Found the vb in the list of vbVector + for (LPD3DVERTEXBUFFER *s = vbVector->begin(); + s != vbVector->end(); ++s) { + if ((*s)->ctx == d3dCtx) { + vb = *s; + break; + } + } + } + } + + if (vb == NULL) { + // This is the first time rendering is invoked + // using this ctx + vb = new D3dVertexBuffer(); + + if (vb == NULL) { + D3dCtx::d3dWarning(OUTOFMEMORY); + unlockGeometry(); + return; + } + vb->ctx = d3dCtx; + vb->maxVertexLimit = maxVertexLimit; + + if (!buildDL) { + vb->vbVector = vbVector; + + // add it to the GeometryArray pVertexBuffers list + vbVector->push_back(vb); + + // add it to the ctx lists + vb->next = d3dCtx->vertexBufferTable.next; + vb->previous = &(d3dCtx->vertexBufferTable); + d3dCtx->vertexBufferTable.next = vb; + if (vb->next != NULL) { + vb->next->previous = vb; + } + } + } + + if ((vb->buffer != NULL) && + ((vb->vertexFormat != vertexFormat) || + (vb->totalVertexCount < vcount) || + (cDirty & + javax_media_j3d_GeometryArrayRetained_STRIPCOUNT_CHANGED) || + (!vb->isPointFlagUsed && needPointFlag))) { + // immediate release VB and reconstruct a new one + vb->release(); + } + + if (vb->buffer == NULL) { + vb->stride = D3DXGetFVFVertexSize(vertexFormat); + vb->vertexFormat = vertexFormat; + vb->totalVertexCount = vcount; + vb->vcount = (vcount >= maxVertexLimit ? maxVertexLimit : vcount); +#ifdef VBDEBUG + printf("Create primary VertexBuffer of size %d, display list ID %d, pointFlag %d\n", + vb->vcount, d3dCtx->currDisplayListID, needPointFlag); +#endif + if (!needPointFlag) { + hr = device->CreateVertexBuffer(vb->stride*vb->vcount, + D3DUSAGE_WRITEONLY, + vertexFormat, + D3DPOOL_DEFAULT, + &vb->buffer); + } else { + hr = device->CreateVertexBuffer(vb->stride*vb->vcount, + D3DUSAGE_WRITEONLY|D3DUSAGE_POINTS, + vertexFormat, + D3DPOOL_DEFAULT, + &vb->buffer); + vb->isPointFlagUsed = true; + } + + if (FAILED(hr)) { + vb->buffer = NULL; + D3dCtx::d3dWarning(CREATEVBFAIL, hr); + unlockGeometry(); + return; + } +#ifdef VBDEBUG + createNew = true; +#endif + cDirty = javax_media_j3d_GeometryArrayRetained_VERTEX_CHANGED; + } + + unlockGeometry(); + + if (buildDL) { + // In display list mode, add it to the displayList ID table + d3dCtx->displayListTable[d3dCtx->currDisplayListID]->add(vb); + } else { + + if (vb->primitiveType == D3DPT_FORCE_DWORD) { + // This happens when previous frame use Quad Line + // so buffer not yet initialize + cDirty = javax_media_j3d_GeometryArrayRetained_VERTEX_CHANGED; + } + + if (!cDirty && + ((geo_type != GEO_TYPE_QUAD_SET) || + (d3dCtx->fillMode != D3DFILL_WIREFRAME))) { + for (i=0; i < d3dCtx->texSetUsed; i++) { + genMode = strideData->texCoordPosition[i]; + if ((genMode == TEX_OBJ_LINEAR) || + ((genMode != vb->texCoordPosition[i]) && + (genMode != TEX_GEN_AUTO))) { + // For object linear mode user can set the plane + // equations so we need to change texture coordinate. + break; + } + } + if (i == d3dCtx->texSetUsed) { + vb->render(d3dCtx); +#ifdef TEXDEBUG + printf("Skip VB Copy\n"); +#endif + return; + } + } + } + + // Note that DWORD (use for color) is of same size + // as float (use for vertex/normal) + + hr = vb->buffer->Lock(0, 0, (BYTE**)&vbptr, 0); + if (FAILED(hr)) { + D3dCtx::d3dWarning(LOCKVBFAIL, hr); + // recreate it next time + vb->release(); + return; + } + + d3dCtx->pVB = vb; + // The current VB is not yet used. + vb->stripLen = 0; + + switch (geo_type) { + case GEO_TYPE_TRI_STRIP_SET: + d3dRenderType = D3DPT_TRIANGLESTRIP; + renderTypeSet = true; +#ifdef VBDEBUG + if (createNew) { + printf("Tri strip set %d\n", vcount); + } +#endif + // fall through + case GEO_TYPE_TRI_FAN_SET: + if (renderTypeSet == false) { +#ifdef VBDEBUG + if (createNew) { + printf("Tri fan set %d\n", vcount); + } +#endif + d3dRenderType = D3DPT_TRIANGLEFAN; + renderTypeSet = true; + } + // fall through + case GEO_TYPE_LINE_STRIP_SET: + { + if (renderTypeSet == false) { + d3dRenderType = D3DPT_LINESTRIP; + renderTypeSet = true; +#ifdef VBDEBUG + if (createNew) { + printf("Tri line set %d \n", vcount); + } +#endif + } + + jfieldID strip_field = env->GetFieldID(geoClass, + "stripVertexCounts", "[I"); + jarray sarray = (jarray)env->GetObjectField(geo, strip_field); + jsize strip_len = (jsize)env->GetArrayLength(sarray); + + jint* strips = (jint *)env->GetPrimitiveArrayCritical(sarray, NULL); + + int nlastStrip = 0; + int totalLen = 0; + int oldTotalLen = 0; + int vsum = 0; + + vb->primitiveType = d3dRenderType; + + if (vcount <= vb->vcount) { + copyVertexToVB(d3dCtx, strideData, vcount, + &vbptr, cDirty, false, xform, nxform); + vb->addStrides(strip_len, strips); +#ifdef VBDEBUG + if (createNew) { + printf("Strip Length %d : ", strip_len); + for (int k=0; k < strip_len; k++) { + printf("%d ", strips[k]); + } + printf("\n"); + } +#endif + } else { +#ifdef VBDEBUG + if (createNew) { + printf("Strip Length %d : ", strip_len); + } +#endif + + for (i = 0; i < strip_len; i++) { + if (strideData->fpositionPtr) { + strideData->fpositionPtr += + strideData->positionStride*nlastStrip; + } else { + strideData->dpositionPtr += + strideData->positionStride*nlastStrip; + } + + if (strideData->normalPtr) { + strideData->normalPtr += + strideData->normalStride*nlastStrip; + } + + if (strideData->fdiffusePtr) { + strideData->fdiffusePtr += + strideData->diffuseStride*nlastStrip; + } else if (strideData->bdiffusePtr) { + strideData->bdiffusePtr += + strideData->diffuseStride*nlastStrip; + } + + + if (strideData->textureCoordsPtr[0]) { + for (j=0; j < texSetUsed; j++) { + strideData->textureCoordsPtr[j] += + strideData->textureCoordsStride[j]* nlastStrip; + } + } + + + nlastStrip = strips[i]; + oldTotalLen = totalLen; + totalLen += nlastStrip; + + if (totalLen > vcount) { + // This should not happen since + // setValidVertexCount is disable + // in v1.3. We should always have + // (sum of strips[] < vcount) + nlastStrip = (vcount - (totalLen - nlastStrip)); + totalLen = vcount; + } + + if (nlastStrip <= 0) { + continue; + } + + + if (vbptr == NULL) { + // This happen when the lastStrip copy + // is greater than maxVertexLimit. + // So we Unlock the last buffer + vbptr = allocateVB(d3dCtx, device, + vcount - oldTotalLen, + maxVertexLimit, &cDirty); + vsum = 0; + if (vbptr == NULL) { + break; // render whatever geometry the current VB have + } + } +#ifdef VBDEBUG + if (createNew) { + printf(" %d ", nlastStrip); + } +#endif + if ((vsum + nlastStrip) <= d3dCtx->pVB->vcount) { + // There is space available to put in vertices + vsum += nlastStrip; + copyVertexToVB(d3dCtx, strideData, nlastStrip, + &vbptr, cDirty, true, xform, nxform); + } else { + // Need to create a new VB + if (nlastStrip <= maxVertexLimit) { + // No need to split strip in multiple VB + if (d3dCtx->pVB->stripLen > 0) { + if (vbptr != NULL) { + d3dCtx->pVB->buffer->Unlock(); + } + vbptr = allocateVB(d3dCtx, device, + vcount - oldTotalLen, + maxVertexLimit, &cDirty); + if (vbptr == NULL) { + break; + } + vsum = 0; + } + vsum += nlastStrip; + copyVertexToVB(d3dCtx, strideData, nlastStrip, + &vbptr, cDirty, true, + xform, nxform); + } else { + d3dCtx->pVB->buffer->Unlock(); + vbptr = NULL; + vsum = 0; + // Multiple VBs for large vertex size + splitVertexToMultipleVB(d3dCtx, strideData, + nlastStrip, + maxVertexLimit, + cDirty, xform, nxform); + vbptr = NULL; + } + } + } +#ifdef VBDEBUG + if (createNew) { + printf("\n"); + } +#endif + } + env->ReleasePrimitiveArrayCritical(sarray, strips, NULL); + } + break; + case GEO_TYPE_QUAD_SET: +#ifdef VBDEBUG + if (createNew) { + printf("quad set %d\n", vcount); + } +#endif + + if (buildDL || + (d3dCtx->fillMode != D3DFILL_WIREFRAME)) { + /* + * Note we can't just check + * if (d3dCtx->fillMode != D3DFILL_WIREFRAME) + * since the fillMode may set back to + * non-line mode AFTER build display list + * In fact it is gaurantee that when displaylist + * mode is used we are not in line mode + */ + + // break down solid into two triangles + if (createQuadIndices(d3dCtx, vcount)) { + // It happens when + // vcount*3/2 != d3dCtx->quadIndexBufferSize + // to conform with index buffer Limitation in + // graphics card. So we adjust using a smaller + // maxVertexLimit when spliting into + // multiple Vertex Buffers. + maxVertexLimit = 2*d3dCtx->quadIndexBufferSize/3; + vb->maxVertexLimit = maxVertexLimit; + vb->vcount = vb->maxVertexLimit; + } + d3dRenderType = D3DPT_TRIANGLELIST; + vb->isIndexPrimitive = true; + renderTypeSet = true; + // fall through + } else { // line mode + // we don't want to see extra line appear in the + // diagonal of quads if it splits into two + // triangles. This is REALLY SLOW !!! + int len = vcount >> 2; + int offsetPos = 0; + int offsetNorm = 0; + int offsetColor = 0; + int strideOffsetPos = strideData->positionStride << 2; + int strideOffsetNorm = strideData->normalStride << 2; + int strideOffsetColor = strideData->diffuseStride << 2; + jfloat *pdf = strideData->fpositionPtr; + jdouble *pdd = strideData->dpositionPtr; + jfloat *pn = strideData->normalPtr; + jfloat *pcf = strideData->fdiffusePtr; + jbyte *pcb = strideData->bdiffusePtr; + jfloat* pt[D3DDP_MAXTEXCOORD]; + + pt[0] = NULL; + + if (((vertexFormat & D3DFVF_DIFFUSE) == 0) && + (!d3dCtx->isLightEnable)) { + d3dCtx->setAmbientLightMaterial(); + } + + vb->buffer->Unlock(); + vbptr = NULL; +#ifdef VBDEBUG + if (createNew) { + printf("quad set polygon line %d\n", vcount); + } +#endif + + for (i=0; i < texSetUsed; i++) { + pt[i] = (FLOAT *) strideData->textureCoordsPtr[i]; + } + + jfloat *fptr; + jdouble *dptr; + jbyte *bptr; + jfloat *fspt; + jdouble *dspt; + int posStride = strideData->positionStride; + D3DVERTEX worldCoord[3]; + D3DTLVERTEX screenCoord[3]; + + vb->primitiveType = D3DPT_FORCE_DWORD; + + if (d3dCtx->lineModeIndexBuffer == NULL) { + createLineModeIndexBuffer(d3dCtx); + } + + for (i = 0; i < (vcount >> 2); i++) { + if (pdf) { + fspt = fptr = pdf + offsetPos; + strideData->fpositionPtr = fptr; + } else { + dspt = dptr = pdd + offsetPos; + strideData->dpositionPtr = dptr; + } + + if (pn) { + fptr = pn + offsetNorm; + strideData->normalPtr = fptr; + } + + if (pcf) { + fptr = pcf + offsetColor; + strideData->fdiffusePtr = fptr; + } else if (pcb) { + bptr = pcb + offsetColor; + strideData->bdiffusePtr = bptr; + } + + if (pt[0]) { + for (j=0; j < texSetUsed; j++) { + DWORD stride3 = 3*strideData->textureCoordsStride[j]; + fptr = pt[j] + i*(strideData->textureCoordsStride[j] << 2); + strideData->textureCoordsPtr[j] = fptr; + } + } + if (d3dCtx->cullMode != D3DCULL_NONE) { + // Do back face culling here + if (pdf) { + worldCoord[0].x = fspt[0]; + worldCoord[0].y = fspt[1]; + worldCoord[0].z = fspt[2]; + fspt += posStride; + worldCoord[1].x = fspt[0]; + worldCoord[1].y = fspt[1]; + worldCoord[1].z = fspt[2]; + fspt += posStride; + worldCoord[2].x = fspt[0]; + worldCoord[2].y = fspt[1]; + worldCoord[2].z = fspt[2]; + } else { + worldCoord[0].x = dspt[0]; + worldCoord[0].y = dspt[1]; + worldCoord[0].z = dspt[2]; + dspt += posStride; + worldCoord[1].x = dspt[0]; + worldCoord[1].y = dspt[1]; + worldCoord[1].z = dspt[2]; + dspt += posStride; + worldCoord[2].x = dspt[0]; + worldCoord[2].y = dspt[1]; + worldCoord[2].z = dspt[2]; + } + d3dCtx->transform(&worldCoord[0], &screenCoord[0]); + d3dCtx->transform(&worldCoord[1], &screenCoord[1]); + d3dCtx->transform(&worldCoord[2], &screenCoord[2]); + screenCoord[0].sx -= screenCoord[1].sx; + screenCoord[0].sy -= screenCoord[1].sy; + screenCoord[2].sx -= screenCoord[1].sx; + screenCoord[2].sy -= screenCoord[1].sy; + if (d3dCtx->cullMode == D3DCULL_CW) { + // clip back face + if ((screenCoord[0].sx*screenCoord[2].sy - + screenCoord[2].sx*screenCoord[0].sy) >= 0) { + DrawPolygonLine(d3dCtx, + device, + vertexFormat, + strideData); + } + } else { // Clip front face + if ((screenCoord[0].sx*screenCoord[2].sy - + screenCoord[2].sx*screenCoord[0].sy) <= 0) { + DrawPolygonLine(d3dCtx, + device, + vertexFormat, + strideData); + } + } + } else { + // cullMode == D3DCULL_NONE + DrawPolygonLine(d3dCtx, + device, + vertexFormat, + strideData); + } + offsetPos += strideOffsetPos; + offsetNorm += strideOffsetNorm; + offsetColor += strideOffsetColor; + } + + if (((vertexFormat & D3DFVF_DIFFUSE) == 0) && + (!d3dCtx->isLightEnable)) { + d3dCtx->restoreDefaultLightMaterial(); + } + // Don't call vb->Renderer() at the end + return; + } + // fallthrough + case GEO_TYPE_TRI_SET: + if (renderTypeSet == false) { + d3dRenderType = D3DPT_TRIANGLELIST; + renderTypeSet = true; +#ifdef VBDEBUG + if (createNew) { + printf("tri set %d\n", vcount); + } +#endif + } + // fallthrough + case GEO_TYPE_LINE_SET: + if (renderTypeSet == false) { + d3dRenderType = D3DPT_LINELIST; + renderTypeSet = true; +#ifdef VBDEBUG + if (createNew) { + printf("line set %d\n", vcount); + } +#endif + } + // fallthrough + case GEO_TYPE_POINT_SET: + if (renderTypeSet == false) { + d3dRenderType = D3DPT_POINTLIST; +#ifdef VBDEBUG + if (createNew) { + printf("point set %d\n", vcount); + } +#endif + } + vb->primitiveType = d3dRenderType; + + if (vcount <= vb->vcount) { + copyVertexToVB(d3dCtx, strideData, vcount, &vbptr, + cDirty, true, xform, nxform); + } else { + if (vbptr != NULL) { + vb->buffer->Unlock(); + vbptr = NULL; + } + + splitVertexToMultipleVB(d3dCtx, strideData, vcount, + maxVertexLimit, + cDirty, xform, nxform); + vbptr = NULL; + } + break; + default: + printf("GeometryArrayRetained_execute:unknown geo_type %ld \n", geo_type); + } + + if (vbptr != NULL) { + // d3dCtx->pVB is the last reference in VB list + d3dCtx->pVB->buffer->Unlock(); + } + + for (i=0; i < d3dCtx->texSetUsed; i++) { + d3dCtx->pVB->texCoordPosition[i] = + strideData->texCoordPosition[i]; + } + + if (!buildDL) { + // Not in displaylist mode, directly render VB + // vb is the root reference in VB list + vb->render(d3dCtx); + } +} + + +void renderIndexGeometry(JNIEnv *env, + D3dCtx *d3dCtx, + LPDIRECT3DDEVICE8 device, + jobject geo, + jint geo_type, + D3DDRAWPRIMITIVESTRIDEDDATA *strideData, + DWORD vertexFormat, + jint vcount, + jint indexCount, + jdouble* xform, + jdouble* nxform, + jint cDirty) +{ + D3DPRIMITIVETYPE d3dRenderType; + BOOL renderTypeSet = false; + BOOL expandQuadIndex = false; + int i; + LPD3DVERTEXBUFFER vb = NULL; + D3dVertexBufferVector *vbVector; + float *vbptr; + +#ifdef VBDEBUG + BOOL createNew = false; +#endif + + if (indexCount <= 0) { + return; + } + + jclass geoClass = env->GetObjectClass(geo); + DWORD maxVertexLimit = + min(d3dCtx->deviceInfo->maxVertexCount[geo_type], + d3dCtx->deviceInfo->maxVertexIndex); + DWORD texSetUsed = d3dCtx->texSetUsed; + HRESULT hr; + BOOL needPointFlag = (geo_type == GEO_TYPE_INDEXED_POINT_SET) || + ((geo_type != GEO_TYPE_INDEXED_LINE_STRIP_SET) && + (geo_type != GEO_TYPE_INDEXED_LINE_SET) && + (d3dCtx->fillMode == D3DFILL_POINT)); + + BOOL buildDL = (d3dCtx->currDisplayListID > 0); + + if (geo_type == GEO_TYPE_INDEXED_QUAD_SET) { + // Since the index we create with be 1.5 times the original index + maxVertexLimit = 2*maxVertexLimit/3; + } + + + lockGeometry(); + + if (!buildDL) { + jfieldID fieldID = env->GetFieldID(geoClass, "pVertexBuffers", "J"); + vbVector = reinterpret_cast<D3dVertexBufferVector *> + (env->GetLongField(geo, fieldID)); + + if (vbVector == NULL) { + // This is the first time rendering is invoked on the + // first GeometryArray + vbVector = new D3dVertexBufferVector(); + if (vbVector == NULL) { + D3dCtx::d3dWarning(OUTOFMEMORY); + unlockGeometry(); + return; + } + env->SetLongField(geo, fieldID, reinterpret_cast<long>(vbVector)); + } else { + // Found the vb in the list of vbVector + for (LPD3DVERTEXBUFFER *s = vbVector->begin(); + s != vbVector->end(); ++s) { + if ((*s)->ctx == d3dCtx) { + vb = *s; + break; + } + } + } + } + + if (vb == NULL) { + // This is the first time rendering is invoked + // using this ctx + vb = new D3dVertexBuffer(); + + if (vb == NULL) { + D3dCtx::d3dWarning(OUTOFMEMORY); + unlockGeometry(); + return; + } + vb->ctx = d3dCtx; + vb->maxVertexLimit = maxVertexLimit; + + if (!buildDL) { + vb->vbVector = vbVector; + + // add it to the GeometryArray pVertexBuffers list + vbVector->push_back(vb); + + // add it to the ctx lists + vb->next = d3dCtx->vertexBufferTable.next; + vb->previous = &(d3dCtx->vertexBufferTable); + d3dCtx->vertexBufferTable.next = vb; + if (vb->next != NULL) { + vb->next->previous = vb; + } + } + } + + if (((vb->indexBuffer != NULL) && + (vb->totalIndexCount < indexCount)) || + ((vb->buffer != NULL) && + ((vb->vertexFormat != vertexFormat) || + (vb->totalVertexCount < vcount) || + (!vb->isPointFlagUsed && needPointFlag)))) { + // immediate release VB and reconstruct a new one + vb->release(); + } + + + if (vb->buffer == NULL) { + vb->stride = D3DXGetFVFVertexSize(vertexFormat); + vb->vertexFormat = vertexFormat; + vb->totalVertexCount = vcount; + vb->isIndexPrimitive = true; + vb->vcount = (vcount >= maxVertexLimit ? maxVertexLimit : vcount); +#ifdef VBDEBUG + printf("Create primary VertexBuffer of size %d, display list ID %d, pointFlag %d\n", + vb->vcount, d3dCtx->currDisplayListID, needPointFlag); +#endif + + if (!needPointFlag) { + hr = device->CreateVertexBuffer(vb->stride*vb->vcount, + D3DUSAGE_WRITEONLY, + vertexFormat, + D3DPOOL_DEFAULT, + &vb->buffer); + } else { + hr = device->CreateVertexBuffer(vb->stride*vb->vcount, + D3DUSAGE_WRITEONLY|D3DUSAGE_POINTS, + vertexFormat, + D3DPOOL_DEFAULT, + &vb->buffer); + vb->isPointFlagUsed = true; + } + + if (FAILED(hr)) { + vb->buffer = NULL; + D3dCtx::d3dWarning(CREATEVBFAIL, hr); + unlockGeometry(); + return; + } +#ifdef VBDEBUG + createNew = true; +#endif + cDirty = javax_media_j3d_GeometryArrayRetained_VERTEX_CHANGED; + } + + if (vb->indexBuffer == NULL) { + + vb->totalIndexCount = indexCount; + vb->indexCount = (indexCount >= maxVertexLimit ? + maxVertexLimit : indexCount); + + if (geo_type == GEO_TYPE_INDEXED_QUAD_SET) { + // Since we will construct another index with + // 1.5 times of the original. + vb->indexCount = (3*vb->indexCount) >> 1; + vb->totalIndexCount = (3*indexCount) >> 1; + } + + + if (indexCount <= 0xffff) { + hr = device->CreateIndexBuffer(vb->indexCount*sizeof(WORD), + D3DUSAGE_WRITEONLY, + D3DFMT_INDEX16, + D3DPOOL_DEFAULT, + &vb->indexBuffer); + } else { + hr = device->CreateIndexBuffer(vb->indexCount*sizeof(UINT), + D3DUSAGE_WRITEONLY, + D3DFMT_INDEX32, + D3DPOOL_DEFAULT, + &vb->indexBuffer); + } + + if (FAILED(hr)) { + vb->indexBuffer = NULL; + D3dCtx::d3dWarning(CREATEINDEXVBFAIL, hr); + unlockGeometry(); + return; + } + + cDirty |= javax_media_j3d_GeometryArrayRetained_INDEX_CHANGED; + } + + unlockGeometry(); + + if (buildDL) { + // In display list mode, add it to the displayList ID table + d3dCtx->displayListTable[d3dCtx->currDisplayListID]->add(vb); + } else { + + if (vb->primitiveType == D3DPT_FORCE_DWORD) { + // This happens when previous frame use Quad Line + // so buffer not yet initialize + cDirty = + javax_media_j3d_GeometryArrayRetained_VERTEX_CHANGED | + javax_media_j3d_GeometryArrayRetained_INDEX_CHANGED; + } + + if (!cDirty && + ((geo_type != GEO_TYPE_INDEXED_QUAD_SET) || + (d3dCtx->fillMode != D3DFILL_WIREFRAME))) { + for (i=0; i < d3dCtx->texSetUsed; i++) { + if ((strideData->texCoordPosition[i] != + vb->texCoordPosition[i]) + && + (strideData->texCoordPosition[i] != TEX_GEN_AUTO)) { + break; + } + } + if (i == d3dCtx->texSetUsed) { + vb->render(d3dCtx); + return; + } + } + } + + // Note that DWORD (use for color) is of same size + // as float (use for vertex/normal) + hr = vb->buffer->Lock(0, 0, (BYTE**)&vbptr, 0); + if (FAILED(hr)) { + D3dCtx::d3dWarning(LOCKVBFAIL, hr); + // recreate it next time + vb->release(); + return; + } + + d3dCtx->pVB = vb; + + // The current VB is not yet used. + vb->stripLen = 0; + + switch (geo_type) { + case GEO_TYPE_INDEXED_TRI_STRIP_SET: + d3dRenderType = D3DPT_TRIANGLESTRIP; + renderTypeSet = true; +#ifdef VBDEBUG + if (createNew) { + printf("Tri strip set %d\n", vcount); + } +#endif + // fall through + case GEO_TYPE_INDEXED_TRI_FAN_SET: + if (renderTypeSet == false) { +#ifdef VBDEBUG + if (createNew) { + printf("Tri fan set %d\n", vcount); + } +#endif + d3dRenderType = D3DPT_TRIANGLEFAN; + renderTypeSet = true; + } + // fall through + case GEO_TYPE_INDEXED_LINE_STRIP_SET: + { + if (renderTypeSet == false) { + d3dRenderType = D3DPT_LINESTRIP; + renderTypeSet = true; +#ifdef VBDEBUG + if (createNew) { + printf("Tri line set %d \n", vcount); + } +#endif + } + + jfieldID strip_field = env->GetFieldID(geoClass, + "stripIndexCounts", "[I"); + jarray sarray = (jarray)env->GetObjectField(geo, strip_field); + jsize strip_len = (jsize)env->GetArrayLength(sarray); + + jint* strips = (jint *)env->GetPrimitiveArrayCritical(sarray, NULL); + int nlastStrip = 0; + + vb->primitiveType = d3dRenderType; +#ifdef VBDEBUG + if (createNew) { + printf("Strip Length %d : ", strip_len); + } +#endif + + if ((vb->totalIndexCount <= vb->indexCount) && + (vcount <= vb->vcount)) { + copyIndexVertexToVB(d3dCtx, strideData, + indexCount, cDirty, false, false); + copyVertexToVB(d3dCtx, strideData, vcount, + &vbptr, cDirty, false, xform, nxform); + vb->addStrides(strip_len, strips); + } else { + vb->buffer->Unlock(); + vbptr = NULL; + strideData->indexPtr += strideData->initialIndexIndex; + strideData->initialIndexIndex = 0; + for (i = 0; i < strip_len; i++) { + strideData->indexPtr += nlastStrip; + + nlastStrip = strips[i]; + + if (nlastStrip <= 0) { + continue; + } +#ifdef VBDEBUG + if (createNew) { + printf(" %d", nlastStrip); + } +#endif + if (nlastStrip <= vb->indexCount) { + reIndexifyIndexVertexToVBs(d3dCtx, strideData, + nlastStrip, vcount, + cDirty, + false, + maxVertexLimit, + xform, nxform); + } else { + // Multiple VBs for large vertex size + splitIndexVertexToMultipleVB(d3dCtx, + strideData, + nlastStrip, + vcount, + maxVertexLimit, + cDirty, + false, + xform, nxform); + } + SafeDelete(d3dCtx->reIndexifyTable); + } +#ifdef VBDEBUG + if (createNew) { + printf("\n"); + } +#endif + } + env->ReleasePrimitiveArrayCritical(sarray, strips, NULL); + } + + break; + case GEO_TYPE_INDEXED_QUAD_SET: +#ifdef VBDEBUG + if (createNew) { + printf("quad set %d\n", vcount); + } +#endif + if (buildDL || + (d3dCtx->fillMode != D3DFILL_WIREFRAME)) { + d3dRenderType = D3DPT_TRIANGLELIST; + renderTypeSet = true; + expandQuadIndex = true; + // fall through + } else { // polygon line mode + // we don't want to see extra line appear in the + // diagonal of quads if it splits into two + // triangles. This is REALLY SLOW !!! + int posStride = strideData->positionStride; + D3DVERTEX worldCoord[3]; + D3DTLVERTEX screenCoord[3]; + jint *idxPtr = strideData->indexPtr; + jfloat *fspt; + jdouble *dspt; + jint idx0, idx1, idx2, idx3; + + if (((vertexFormat & D3DFVF_DIFFUSE) == 0) && + (!d3dCtx->isLightEnable)) { + d3dCtx->setAmbientLightMaterial(); + } + + vb->buffer->Unlock(); + vbptr = NULL; +#ifdef VBDEBUG + if (createNew) { + printf("indexed quad set polygon line %d\n", vcount); + } +#endif + if (d3dCtx->lineModeIndexBuffer == NULL) { + createLineModeIndexBuffer(d3dCtx); + } + + vb->primitiveType = D3DPT_FORCE_DWORD; + + for (i = 0; i < (indexCount >> 2); i++) { + if (d3dCtx->cullMode != D3DCULL_NONE) { + // Do back face culling here + idx0 = *idxPtr++; + idx1 = *idxPtr++; + idx2 = *idxPtr++; + idx3 = *idxPtr++; + if (strideData->fpositionPtr) { + fspt = strideData->fpositionPtr + posStride*idx0; + worldCoord[0].x = *fspt++; + worldCoord[0].y = *fspt++; + worldCoord[0].z = *fspt++; + fspt = strideData->fpositionPtr + posStride*idx1; + worldCoord[1].x = *fspt++; + worldCoord[1].y = *fspt++; + worldCoord[1].z = *fspt++; + fspt = strideData->fpositionPtr + posStride*idx2; + worldCoord[2].x = *fspt++; + worldCoord[2].y = *fspt++; + worldCoord[2].z = *fspt++; + } else { + dspt = strideData->dpositionPtr + posStride*idx0; + worldCoord[0].x = *dspt++; + worldCoord[0].y = *dspt++; + worldCoord[0].z = *dspt++; + dspt = strideData->dpositionPtr + posStride*idx1; + worldCoord[1].x = *dspt++; + worldCoord[1].y = *dspt++; + worldCoord[1].z = *dspt++; + dspt = strideData->dpositionPtr + posStride*idx2; + worldCoord[2].x = *dspt++; + worldCoord[2].y = *dspt++; + worldCoord[2].z = *dspt++; + } + + d3dCtx->transform(&worldCoord[0], &screenCoord[0]); + d3dCtx->transform(&worldCoord[1], &screenCoord[1]); + d3dCtx->transform(&worldCoord[2], &screenCoord[2]); + screenCoord[0].sx -= screenCoord[1].sx; + screenCoord[0].sy -= screenCoord[1].sy; + screenCoord[2].sx -= screenCoord[1].sx; + screenCoord[2].sy -= screenCoord[1].sy; + if (d3dCtx->cullMode == D3DCULL_CW) { + if ((screenCoord[0].sx*screenCoord[2].sy - + screenCoord[2].sx*screenCoord[0].sy) >= 0) { + DrawIndexPolygonLine(d3dCtx, + device, + vertexFormat, + strideData, + idx0, idx1, + idx2, idx3); + } + } else { // Clip front face + if ((screenCoord[0].sx*screenCoord[2].sy - + screenCoord[2].sx*screenCoord[0].sy) <= 0) { + DrawIndexPolygonLine(d3dCtx, + device, + vertexFormat, + strideData, + idx0, idx1, + idx2, idx3); + } + } + } else { + // cullMode == D3DCULL_NONE + DrawIndexPolygonLine(d3dCtx, + device, + vertexFormat, + strideData, + idx0, idx1, + idx2, idx3); + } + } + if (((vertexFormat & D3DFVF_DIFFUSE) == 0) && + (!d3dCtx->isLightEnable)) { + d3dCtx->restoreDefaultLightMaterial(); + } + // Don't call vb->Renderer() at the end + return; + } + // fall through + case GEO_TYPE_INDEXED_TRI_SET: + if (renderTypeSet == false) { + d3dRenderType = D3DPT_TRIANGLELIST; + renderTypeSet = true; +#ifdef VBDEBUG + if (createNew) { + printf("tri set %d\n", vcount); + } +#endif + } + // fallthrough + case GEO_TYPE_INDEXED_LINE_SET: + if (renderTypeSet == false) { + d3dRenderType = D3DPT_LINELIST; + renderTypeSet = true; +#ifdef VBDEBUG + if (createNew) { + printf("line set %d\n", vcount); + } +#endif + } + // fallthrough + case GEO_TYPE_INDEXED_POINT_SET: + if (renderTypeSet == false) { + d3dRenderType = D3DPT_POINTLIST; +#ifdef VBDEBUG + if (createNew) { + printf("point set %d\n", vcount); + } +#endif + } + vb->primitiveType = d3dRenderType; + + if (vb->totalIndexCount <= vb->indexCount) { + if (vcount <= vb->vcount) { + copyIndexVertexToVB(d3dCtx, strideData, + indexCount, + cDirty, true, expandQuadIndex); + copyVertexToVB(d3dCtx, strideData, vcount, &vbptr, + cDirty, false, xform, nxform); + } else { + vb->buffer->Unlock(); + vbptr = NULL; + reIndexifyIndexVertexToVBs(d3dCtx, strideData, + indexCount, vcount, + cDirty, + expandQuadIndex, + maxVertexLimit, + xform, nxform); + SafeDelete(d3dCtx->reIndexifyTable); + } + } else { + vb->buffer->Unlock(); + vbptr = NULL; + splitIndexVertexToMultipleVB(d3dCtx, + strideData, + indexCount, + vcount, + maxVertexLimit, + cDirty, + expandQuadIndex, + xform, nxform); + SafeDelete(d3dCtx->reIndexifyTable); + } + break; + default: + printf("IndexedGeometryArrayRetained_execute:unknown geo_type %ld \n", geo_type); + } + + if (vbptr != NULL) { + // d3dCtx->pVB is the last reference in VB list + d3dCtx->pVB->buffer->Unlock(); + } + + // Save new texture position to detect any change + // in next round. + for (i=0; i < d3dCtx->texSetUsed; i++) { + d3dCtx->pVB->texCoordPosition[i] = + strideData->texCoordPosition[i]; + } + + if (!buildDL) { + // Not in displaylist mode, directly render VB + // vb is the root reference in VB list + vb->render(d3dCtx); + } +} + + +/* + * Set the default texture coordinate pointers when automatically + * texture generation is used or when there is application error + */ +inline void setDefaultTextureCoordPointers(D3dCtx *d3dCtx, + D3DDRAWPRIMITIVESTRIDEDDATA *strideData, + DWORD* vertexFormat, + jint ts, + int genMode, + int tus) +{ + strideData->textureCoordsPtr[tus] = &defaultTexCoord[0]; + strideData->textureCoordsStride[tus] = 0; + strideData->texCoordPosition[tus] = genMode; + d3dCtx->texStride[tus] = ts; + *vertexFormat |= (TexFormatSizeTable[ts] << (tus*2 + 16)); +} + + +/* + * Set the textureCoordStride & textureCoordsPtr in strideData + */ +void setTextureCoordPointers(JNIEnv *env, + D3dCtx* d3dCtx, + LPDIRECT3DDEVICE8 device, + D3DDRAWPRIMITIVESTRIDEDDATA *strideData, + jint pass, + jint texoff, + jint texStride, + jint ts, + jboolean textureDefined, + jintArray tcoordsetmap, + jint texCoordMapLength, + jintArray texUnitOffset, + jint numActiveTexUnit, + jintArray tunitstatemap, + DWORD* vertexFormat, + // Used by executeGeometryArray() & + // executeIndexedGeometryArray() only + jfloat* verts, + // Used by executeGeometryArrayVA() & + // executeIndexedGeometryArrayVA() only + jfloat** texCoordPointer, + // Used by executeGeometryArrayVA() only + jintArray texindices) + +{ + jint *texUnitStateMap = NULL; + jint *texCoordSetMapOffset = NULL; + jint *initialTexIndices = NULL; + jint *texCoordSetMap = NULL; + jint textureUnitIndex; + int genMode; + jint offsetOrTexset; + BOOL nonVAGeom = (verts != NULL); + int texSetInVB = 0; + + /* + * In case of automatic texture generation, + * (vformat & GA_TEXTURE_COORDINATE) may equal to zero so we + * can't wrap around this whole block with the condition. + */ + d3dCtx->texSetUsed = 0; + + // For GA buildGA(), numActiveTexUnit is 1 even though texture + // is not used. This is only accurate for execute() immediate case. + if (numActiveTexUnit <= 0) { + return; + } + + if (texCoordMapLength > 0) { + if (nonVAGeom) { + // In executeGeometryArray() or executeIndexedGeometryArray() + texCoordSetMapOffset = (jint *) env->GetPrimitiveArrayCritical(texUnitOffset, NULL); + } else { + // In executeGeometryArrayVA() or executeIndexedGeometryArrayVA() + texCoordSetMap = (jint *) + env->GetPrimitiveArrayCritical(tcoordsetmap, NULL); + } + + } + + if (texindices != NULL) { + // In executeGeometryArrayVA() + initialTexIndices = (jint *) env->GetPrimitiveArrayCritical(texindices, NULL); + } + + if (pass >= 0) { + /* + * Single texture coordinate used or in multi-pass mode. + * In multi-pass mode, texture stage 0 is set so we + * should not use + * setTextureStage(d3dCtx, device, 0, pass); + */ + + genMode = setTextureStage(d3dCtx, device, 0, 0); + +#ifdef TEXDEBUG + printf("*** Single Pass *** %d, nonVAGeom %d, buildDL %d, numActiveTexUnit, texCoordMapLength %d, texDef %d, genMode %d \n", pass, nonVAGeom, (d3dCtx->currDisplayListID > 0), numActiveTexUnit, texCoordMapLength, textureDefined, genMode); +#endif + + if ((texCoordMapLength > 0) && + (pass < texCoordMapLength)) { + offsetOrTexset = (nonVAGeom ? + texCoordSetMapOffset[pass] : texCoordSetMap[pass]); + } else { + // TexUnitState is not used or disable, + // so by default we use texUnitIndex 0 + offsetOrTexset = 0; + } + + if (genMode != TEX_OBJ_LINEAR) { + // Only Object Linear Mode will not use DisplayList at + // all. That mean genMode must be correctly set before + // enter this Geometry execute() function/ + // In non displaylist mode genMode may not set correctly + // when so we can't rely on it. + if (textureDefined) { + if (offsetOrTexset != -1) { + if (nonVAGeom) { + // In executeGeometryArray() or executeIndexedGeometryArray() + strideData->textureCoordsPtr[0] = + &verts[texoff + offsetOrTexset]; + } else if (initialTexIndices != NULL) { + // executeGeometryArrayVA() + strideData->textureCoordsPtr[0] = + &(texCoordPointer[offsetOrTexset][initialTexIndices[offsetOrTexset]*texStride]); + } else { // executeIndexedGeometryArrayVA() + strideData->textureCoordsPtr[0] = + &(texCoordPointer[offsetOrTexset][0]); + } + + strideData->textureCoordsStride[0] = texStride; + *vertexFormat |= (TexFormatSizeTable[ts] << 16); + d3dCtx->texSetUsed = 1; + strideData->texCoordPosition[0] = offsetOrTexset; + d3dCtx->texStride[0] = ts; + setTexTransformStageFlag(d3dCtx, device, 0, ts, genMode); +#ifdef TEXDEBUG + printf("[pass 0] Non Object Linear, texDefined, ts=%d\n", ts); +#endif + } + } else { + // may be automatic texture generation used + // TexSetUsed remain unchange i.e. 0 since we will not + // allocate VB space for texture coords. + setTexTransformStageFlag(d3dCtx, device, 0, + d3dCtx->texCoordFormat[0], genMode); +#ifdef TEXDEBUG + printf("[pass 0] Non Object Linear, No texDefined, ts=%d\n", + d3dCtx->texCoordFormat[0]); +#endif + } + } else { + // Automatic texture generation Object Linear + // strideData->textureCoordsPtr[0] & + // strideData->textureCoordsStride[0] + // are not use in VertexBuffer texture copy so + // it doesn't matter to set them using default. + setDefaultTextureCoordPointers(d3dCtx, strideData, + vertexFormat, + d3dCtx->texCoordFormat[0], + genMode, 0); + setTexTransformStageFlag(d3dCtx, device, 0, + d3dCtx->texCoordFormat[0], genMode); + d3dCtx->texSetUsed = 1; +#ifdef TEXDEBUG + printf("[pass 0] Object Linear, ts=%d\n", d3dCtx->texCoordFormat[0]); +#endif + } + texSetInVB = d3dCtx->texSetUsed; + + } else { + // DisplayList is used for multiple texture single pass mode + // Or when go through the VertexArray in OGL, pass = -1 + int tus; +#ifdef TEXDEBUG + printf("*** Multiple Pass *** %d, nonVAGeom %d, buildDL %d, numActiveTexUnit %d, texCoordMapLength %d, texDef %d\n", pass, + nonVAGeom, (d3dCtx->currDisplayListID > 0), + numActiveTexUnit, texCoordMapLength, textureDefined); +#endif + + if (tunitstatemap != NULL) { + texUnitStateMap = (jint *) env->GetPrimitiveArrayCritical(tunitstatemap, NULL); + } + for (textureUnitIndex = 0; textureUnitIndex < numActiveTexUnit; + textureUnitIndex++) { + + tus = (texUnitStateMap != NULL ? + texUnitStateMap[textureUnitIndex]: textureUnitIndex); + + if (d3dCtx->currDisplayListID > 0) { + genMode = setTextureStage(d3dCtx, device, + textureUnitIndex, tus); + } else { + // This happen when we switch from displayList to + // vertexArray mode. The displayList is already + // built with 1-1 mapping so we can't use the + // textureUnitIndex Mapping + genMode = setTextureStage(d3dCtx, device, + textureUnitIndex, + textureUnitIndex); + } +#ifdef TEXDEBUG + printf("[pass %d] genMode %d, tus %d\n", textureUnitIndex, + genMode, tus); +#endif + if (genMode != TEX_OBJ_LINEAR) { + if (textureDefined) { + if (tus < texCoordMapLength) { + offsetOrTexset = (nonVAGeom ? + texCoordSetMapOffset[tus]:texCoordSetMap[tus]); + + if (offsetOrTexset != -1) { + if (nonVAGeom) { + strideData->textureCoordsPtr[textureUnitIndex] = + &verts[texoff + offsetOrTexset]; + } else if (initialTexIndices != NULL) { + strideData->textureCoordsPtr[textureUnitIndex] = + &(texCoordPointer[offsetOrTexset][initialTexIndices[offsetOrTexset]*texStride]); + } else { + strideData->textureCoordsPtr[textureUnitIndex] = + &(texCoordPointer[offsetOrTexset][0]); + } + strideData->textureCoordsStride[textureUnitIndex] = texStride; + strideData->texCoordPosition[textureUnitIndex] + = offsetOrTexset; + *vertexFormat |= (TexFormatSizeTable[ts] << (textureUnitIndex*2 + 16)); + d3dCtx->texStride[textureUnitIndex] = ts; + setTexTransformStageFlag(d3dCtx, device, + textureUnitIndex, + ts, genMode); + texSetInVB++; +#ifdef TEXDEBUG + printf("[pass %d] Non Object Linear, texDefined, ts=%d, tus %d\n", textureUnitIndex, ts, tus); +#endif + } else { + // This texture status is disable, this + // should not happen in D3D since + // TextureBin always compact unused state + // - unless when DisplayList is build and + // automatic texture generation + // used. Since if DL use + // updateAttributes() not yet invoke to + // set genMode correctly. + if (debug && (d3dCtx->currDisplayListID <= 0)) { + printf("[Java3D] TextureBin not compact textureUnitState correctly, numActiveTex %d, disableUnit %d, current mapped Texture Unit %d\n", numActiveTexUnit, tus, textureUnitIndex); + } + setDefaultTextureCoordPointers(d3dCtx, strideData, + vertexFormat, ts, + genMode, + textureUnitIndex); + setTexTransformStageFlag(d3dCtx, device, + textureUnitIndex, + ts, genMode); + texSetInVB++; +#ifdef TEXDEBUG + printf("[pass %d] Non Object Linear, texDefined, ts=%d\n", textureUnitIndex, ts); +#endif + } + } else { + // Internal error, should not happen. + if (debug) { + printf("[Java3D] TextureCoordMapLength length %d, is smaller than texture unit %d, map texture unit %d\n", texCoordMapLength, tus, textureUnitIndex); + } + setDefaultTextureCoordPointers(d3dCtx, strideData, + vertexFormat, ts, + TEX_GEN_INVALID, + textureUnitIndex); + setTexTransformStageFlag(d3dCtx, device, + textureUnitIndex, ts, + genMode); + + texSetInVB++; +#ifdef TEXDEBUG + printf("[pass %d] Non Object Linear, texDefined, offset/texset = -1, ts=%d\n", textureUnitIndex, ts); +#endif + } + } else { + // May be in automatically texture coordinate + // generation mode. + // May have trouble if automatically texture + // coordinate not used. Note that we pass ts = 0 + // so that copyVertexToVB() will not inc. the + // stride for this unused tex stage. + + // It is also the case in buildGA() case when + // numActiveTexUnit is 1 by default even though + // texture is not used. + /* + if ((d3dCtx->currDisplayListID <= 0) && + (genMode == TEX_GEN_NONE)) { + // application error, use default TexCoord + setDefaultTextureCoordPointers(d3dCtx, strideData, + vertexFormat, + ts, + TEX_GEN_NONE, + textureUnitIndex); + texSetInVB++; + } + */ + + setDefaultTextureCoordPointers(d3dCtx, strideData, + vertexFormat, + 0, + // This must be < 0 + TEX_GEN_AUTO, + textureUnitIndex); + setTexTransformStageFlag(d3dCtx, device, textureUnitIndex, + d3dCtx->texCoordFormat[textureUnitIndex], genMode); + + +#ifdef TEXDEBUG + printf("[pass %d] Non Object Linear, No texDefined, ts=0\n", textureUnitIndex); +#endif + } + } else { + // Automatic Texture generation Object Linear is used + setDefaultTextureCoordPointers(d3dCtx, strideData, + vertexFormat, + d3dCtx->texCoordFormat[textureUnitIndex], + genMode, + textureUnitIndex); + setTexTransformStageFlag(d3dCtx, device, textureUnitIndex, + d3dCtx->texCoordFormat[textureUnitIndex], genMode); + texSetInVB++; +#ifdef TEXDEBUG + printf("[pass %d] Object Linear, No texDefined, ts=%d\n", textureUnitIndex, d3dCtx->texCoordFormat[textureUnitIndex]); +#endif + } + } + d3dCtx->texSetUsed = numActiveTexUnit; +#ifdef TEXDEBUG + printf("No of texSetInVB %d, numActiveTexUnit %d\n", + texSetInVB, numActiveTexUnit); +#endif + if (texUnitStateMap != NULL) { + env->ReleasePrimitiveArrayCritical(tunitstatemap, texUnitStateMap, NULL); + } + } + + if (texCoordSetMapOffset != NULL) { + env->ReleasePrimitiveArrayCritical(texUnitOffset, + texCoordSetMapOffset, NULL); + } + + if (texCoordSetMap != NULL) { + env->ReleasePrimitiveArrayCritical(tcoordsetmap, + texCoordSetMap, NULL); + } + + if (initialTexIndices != NULL) { + env->ReleasePrimitiveArrayCritical(texindices, + initialTexIndices, NULL); + } + + // texSetInVB <= d3dCtx->TexSetUsed + *vertexFormat |= getVertexFormat(texSetInVB); +} + + + +void executeGeometryArrayVA( + JNIEnv *env, + jobject obj, + jlong ctx, + jobject geo, + jint geo_type, + jboolean isNonUniformScale, + jboolean modAlpha, + float alpha, + jboolean multiScreen, + jboolean ignoreVertexColors, + jint vcount, + jint vformat, + jint vdefined, + jint initialCoordIndex, + jfloat* fverts, + jdouble* dverts, + jint initialColorIndex, + jfloat* fclrs, + jbyte* bclrs, + jint initialNormalIndex, + jfloat* norms, + int pass, // or texUnitIndex + int texCoordMapLength, + jintArray tcoordsetmap, + jint numActiveTexUnit, + jintArray tunitstatemap, + jintArray texindices, + jint texStride, + jfloat** texCoordPointer, + jdoubleArray xform, + jdoubleArray nxform, + jint cDirty) +{ + D3DDRAWPRIMITIVESTRIDEDDATA strideData; + DWORD vertexFormat = 0; + + jboolean floatCoordDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_COORD_FLOAT) != 0); + jboolean doubleCoordDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_COORD_DOUBLE) != 0); + jboolean floatColorsDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_COLOR_FLOAT) != 0); + jboolean byteColorsDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_COLOR_BYTE) != 0); + jboolean normalsDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_NORMAL_FLOAT) != 0); + jboolean textureDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_TEXCOORD_FLOAT) != 0); + + GetDevice(); + + ZeroMemory(&strideData, sizeof(D3DDRAWPRIMITIVESTRIDEDDATA)); + + strideData.modulateAlpha = modAlpha; + strideData.alpha = alpha; + + + // setup coordinate pointers + if (floatCoordDefined || doubleCoordDefined) { + vertexFormat |= D3DFVF_XYZ; + + if (floatCoordDefined) { + strideData.fpositionPtr = &fverts[initialCoordIndex*3]; + } else if (doubleCoordDefined) { + strideData.dpositionPtr = &dverts[initialCoordIndex*3]; + } + + strideData.positionStride = 3; + + } else { + // nothing worth doing if no coordinates define + return; + } + + // setup normal pointers + if (normalsDefined) { + vertexFormat |= D3DFVF_NORMAL; + strideData.normalPtr = &norms[initialNormalIndex*3]; + strideData.normalStride = 3; + } + + + // setup color pointers + if (!(floatColorsDefined || byteColorsDefined) + || ignoreVertexColors) { + // Use Material color + // Assume VertexBuffer will recreate when ignoreVertexColors + // property changed. Otherwise we need to remove + // the following one line + vertexFormat &= ~D3DFVF_DIFFUSE; + } else { + if ((vformat & GA_WITH_ALPHA) != 0) { + strideData.diffuseStride = 4; + strideData.useAlpha = true; + } else { + strideData.diffuseStride = 3; + strideData.useAlpha = false; + } + if (floatColorsDefined) { + strideData.fdiffusePtr = &fclrs[initialColorIndex*strideData.diffuseStride]; + } else { + strideData.bdiffusePtr = &bclrs[initialColorIndex*strideData.diffuseStride]; + } + + vertexFormat |= D3DFVF_DIFFUSE; + } + + int ts = 2; // In case of automatic texture generation + + if ((vformat & GA_TEXTURE_COORDINATE_3) != 0) { + ts = 3; + } else if ((vformat & GA_TEXTURE_COORDINATE_4) != 0) { + ts = 4; + } + + + // setup texture pointer + setTextureCoordPointers(env, d3dCtx, device, + &strideData, + pass, 0, texStride, ts, + textureDefined, + tcoordsetmap, + texCoordMapLength, + NULL, + numActiveTexUnit, + tunitstatemap, + &vertexFormat, + NULL, texCoordPointer, + texindices); + + + + jdouble* xform_ptr = NULL; + jdouble* nxform_ptr = NULL; + + if (xform != NULL) { + xform_ptr = (jdouble *) env->GetPrimitiveArrayCritical(xform, NULL); + + } + + if (nxform != NULL) { + nxform_ptr = (jdouble *) env->GetPrimitiveArrayCritical(nxform, NULL); + } + + // Construct/update VertexBuffer, render() if not in display list mode + renderGeometry(env, d3dCtx, device, geo, geo_type, &strideData, + vertexFormat, vcount, xform_ptr, nxform_ptr, cDirty); + + if (xform_ptr != NULL) { + env->ReleasePrimitiveArrayCritical(xform, xform_ptr, 0); + } + if (nxform_ptr != NULL) { + env->ReleasePrimitiveArrayCritical(nxform, nxform_ptr, 0); + } + +} + + + + +/* execute geometry array with java array format */ +extern "C" JNIEXPORT +void JNICALL Java_javax_media_j3d_GeometryArrayRetained_executeVABuffer( + JNIEnv *env, + jobject obj, + jlong ctx, + jobject geo, + jint geo_type, + jboolean isNonUniformScale, + jboolean multiScreen, + jboolean ignoreVertexColors, + jint vcount, + jint vformat, + jint vdefined, + jint initialCoordIndex, + jobject vcoords, + jint initialColorIndex, + jobject cdataBuffer, + jfloatArray cfdata, + jbyteArray cbdata, + jint initialNormalIndex, + jobject ndata, + jint pass, + jint texCoordMapLength, + jintArray tcoordsetmap, + jint numActiveTexUnit, + jintArray tunitstatemap, + jintArray texindices, + jint texStride, + jobjectArray texCoords, + jint cdirty) +{ + + jfloat *fverts = NULL; + jdouble *dverts = NULL ; + jbyte *bclrs = NULL; + jfloat *fclrs = NULL, *norms = NULL; + jfloat* texCoordPointer[D3DDP_MAXTEXCOORD]; + jarray texobjs[D3DDP_MAXTEXCOORD]; + int i; + + jboolean floatCoordDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_COORD_FLOAT) != 0); + jboolean doubleCoordDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_COORD_DOUBLE) != 0); + jboolean floatColorsDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_COLOR_FLOAT) != 0); + jboolean byteColorsDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_COLOR_BYTE) != 0); + jboolean normalsDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_NORMAL_FLOAT) != 0); + jboolean textureDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_TEXCOORD_FLOAT) != 0); + + if (textureDefined) { + for (i = 0; i < texCoordMapLength; i++) { + texobjs[i] = (jarray)env->GetObjectArrayElement(texCoords, i); + } + } + + /* get coordinate array */ + if (floatCoordDefined) { + fverts = (jfloat *)env->GetDirectBufferAddress( vcoords ); + } else if (doubleCoordDefined) { + dverts = (jdouble *)env->GetDirectBufferAddress( vcoords ); + } + + if(fverts == NULL && dverts == NULL) + return; + + /* get color array */ + if (floatColorsDefined) { + if(cfdata != NULL) { + fclrs = (jfloat *) env->GetPrimitiveArrayCritical( cfdata, NULL); + } else { + fclrs = (jfloat *) env->GetDirectBufferAddress (cdataBuffer); + + } + } + else if (byteColorsDefined) { + if(cbdata != NULL) { + bclrs = (jbyte *) env->GetPrimitiveArrayCritical( cbdata, NULL); + } else { + bclrs = (jbyte *) env->GetDirectBufferAddress(cdataBuffer); + } + } + + /* get normal array */ + if (normalsDefined) { + norms = (jfloat *)env->GetDirectBufferAddress(ndata); + } + + /* get texture arrays */ + if (textureDefined) { + for (i = 0; i < texCoordMapLength; i++) { + if (texobjs[i] != NULL) + texCoordPointer[i] = (jfloat*)env->GetDirectBufferAddress(texobjs[i]); + else + texCoordPointer[i] = NULL; + + } + } + + executeGeometryArrayVA(env, obj, ctx, geo, geo_type, + isNonUniformScale, false, 0, + multiScreen, ignoreVertexColors, + vcount, vformat, vdefined, initialCoordIndex, + fverts, dverts, initialColorIndex, + fclrs, bclrs, initialNormalIndex, + norms, pass, texCoordMapLength, + tcoordsetmap,numActiveTexUnit, tunitstatemap, + texindices,texStride,texCoordPointer, NULL, + NULL, cdirty); + + if(floatColorsDefined && cfdata != NULL) + env->ReleasePrimitiveArrayCritical( cfdata, fclrs, 0); + else if(byteColorsDefined && cbdata != NULL) + env->ReleasePrimitiveArrayCritical(cbdata, bclrs, 0); +} + + +extern "C" JNIEXPORT +void JNICALL Java_javax_media_j3d_GeometryArrayRetained_executeVA( + JNIEnv *env, + jobject obj, + jlong ctx, + jobject geo, + jint geo_type, + jboolean isNonUniformScale, + jboolean multiScreen, + jboolean ignoreVertexColors, + jint vcount, + jint vformat, + jint vdefined, + jint initialCoordIndex, + jfloatArray vfcoords, + jdoubleArray vdcoords, + jint initialColorIndex, + jfloatArray cfdata, + jbyteArray cbdata, + jint initialNormalIndex, + jfloatArray ndata, + jint pass, // or texUnitIndex + jint texCoordMapLength, + jintArray tcoordsetmap, + jint numActiveTexUnit, + jintArray tunitstatemap, + jintArray texindices, + jint texStride, + jobjectArray texCoords, + jint cDirty) + { + + jfloat *fverts = NULL; + jdouble *dverts = NULL; + jfloat *fclrs = NULL; + jbyte *bclrs = NULL; + jfloat *norms = NULL; + jfloat* texCoordPointer[D3DDP_MAXTEXCOORD]; + jarray texobjs[D3DDP_MAXTEXCOORD]; + int i; + + jboolean floatCoordDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_COORD_FLOAT) != 0); + jboolean doubleCoordDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_COORD_DOUBLE) != 0); + jboolean floatColorsDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_COLOR_FLOAT) != 0); + jboolean byteColorsDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_COLOR_BYTE) != 0); + jboolean normalsDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_NORMAL_FLOAT) != 0); + jboolean textureDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_TEXCOORD_FLOAT) != 0); + + if (textureDefined) { + for (i = 0; i < texCoordMapLength; i++) { + texobjs[i] = (jarray)env->GetObjectArrayElement( texCoords, i); + } + } + + /* get coordinate array */ + if (floatCoordDefined) { + fverts= (jfloat *) env->GetPrimitiveArrayCritical( vfcoords, NULL); + } else if (doubleCoordDefined) { + dverts= (jdouble *) env->GetPrimitiveArrayCritical( vdcoords, NULL); + } + + if ((fverts == NULL) && (dverts == NULL)) { + return; + } + + /* get color array */ + if (floatColorsDefined) { + fclrs = (jfloat *) env->GetPrimitiveArrayCritical( cfdata, NULL); + } else if (byteColorsDefined) { + bclrs = (jbyte *)env->GetPrimitiveArrayCritical( cbdata, NULL); + } + + /* get normal array */ + if (normalsDefined) { + norms = (jfloat *) env->GetPrimitiveArrayCritical(ndata, NULL); + } + + /* get texture arrays */ + if (textureDefined) { + for (i = 0; i < texCoordMapLength; i++) { + if (texobjs[i] != NULL) { + texCoordPointer[i] = (jfloat*)env->GetPrimitiveArrayCritical(texobjs[i], NULL); + } else { + texCoordPointer[i] = NULL; + } + + } + } + executeGeometryArrayVA(env, obj, ctx, geo, geo_type, + isNonUniformScale, false, 0, + multiScreen, ignoreVertexColors, + vcount, vformat, vdefined, initialCoordIndex, + fverts, dverts, initialColorIndex, + fclrs, bclrs, initialNormalIndex, + norms, pass, texCoordMapLength, + tcoordsetmap,numActiveTexUnit, tunitstatemap, + texindices,texStride,texCoordPointer, + NULL, NULL, cDirty); + + if (floatCoordDefined) { + env->ReleasePrimitiveArrayCritical( vfcoords, fverts, 0); + } + else if (doubleCoordDefined) { + env->ReleasePrimitiveArrayCritical( vdcoords, dverts, 0); + } + + if (floatColorsDefined) { + env->ReleasePrimitiveArrayCritical( cfdata, fclrs, 0); + } + else if (byteColorsDefined) { + env->ReleasePrimitiveArrayCritical( cbdata, bclrs, 0); + } + + if (normalsDefined) { + env->ReleasePrimitiveArrayCritical( ndata, norms, 0); + } + + if (textureDefined) { + for (i = 0; i < texCoordMapLength; i++) { + if (texCoordPointer[i] != NULL) { + env->ReleasePrimitiveArrayCritical(texobjs[i], texCoordPointer[i], 0); + } + } + } +} + +extern "C" JNIEXPORT +void JNICALL Java_javax_media_j3d_GeometryArrayRetained_setGlobalAlpha( + JNIEnv *env, + jobject obj, + jlong ctx, + jfloat alpha) +{ + // not use in D3D +} + + +extern "C" JNIEXPORT +void JNICALL Java_javax_media_j3d_GeometryArrayRetained_disableGlobalAlpha( + JNIEnv *env, + jobject obj, + jlong ctx, + jint vformat, + jboolean useAlpha, + jboolean ignoreVertexColors) +{ + // not use in D3D +} + +extern "C" JNIEXPORT +void JNICALL Java_javax_media_j3d_GeometryArrayRetained_setVertexFormat( + JNIEnv *env, + jobject obj, + jint vformat, + jboolean useAlpha, + jboolean ignoreVertexColors, + jlong ctx) +{ + // not use in D3D +} + + +extern "C" JNIEXPORT +jboolean JNICALL Java_javax_media_j3d_GeometryArrayRetained_globalAlphaSUN + (JNIEnv *env, jobject obj, jlong ctx) +{ + return JNI_FALSE; +} + + + +void executeGeometryArray(JNIEnv *env, + jobject obj, jlong ctx, + jobject geo, jint geo_type, + jboolean isNonUniformScale, + jboolean modAlpha, // buildGA, should alpha be mode + jfloat alpha, + jboolean multiScreen, + jboolean ignoreVertexColors, + jint startVIndex, + jint vcount, jint vformat, jint texCoordSetCount, + jintArray texCoordSetMapArray, + jint texCoordMapLength, + jintArray texUnitOffset, + jint numActiveTexUnit, + jintArray tunitstatemap, + jfloat* verts, jfloatArray carray, jint pass, + jdoubleArray xform, jdoubleArray nxform, + jint cDirty, + jboolean useAlpha) // Should alpha be sent down +{ + D3DDRAWPRIMITIVESTRIDEDDATA strideData; + DWORD vertexFormat = 0; + jint stride, coordoff, normoff, coloroff, texoff; + int texStride, ts = 0; + + GetDevice(); + + ZeroMemory(&strideData, sizeof(D3DDRAWPRIMITIVESTRIDEDDATA)); + + strideData.modulateAlpha = modAlpha; + strideData.alpha = alpha; + + /* This matches the code in GeometryArrayRetained.java */ + stride = coordoff = normoff = coloroff = texoff = 0; + + if ((vformat & GA_COORDINATES) != 0) { + stride += 3; + vertexFormat |= D3DFVF_XYZ; + } else { + // nothing worth doing if no coordinates define + return; + } + + if ((vformat & GA_NORMALS) != 0) { + stride += 3; + coordoff += 3; + vertexFormat |= D3DFVF_NORMAL; + } + + if ((vformat & GA_COLOR) != 0) { + if ((vformat & GA_WITH_ALPHA) != 0 ) { + stride += 4; + normoff += 4; + coordoff += 4; + } else { // Handle the case of executeInterleaved 3f + stride += 3; + normoff += 3; + coordoff += 3; + } + vertexFormat |= D3DFVF_DIFFUSE; + } + + // In case of automatic texture generation + ts = 2; + + if (vformat & GA_TEXTURE_COORDINATE) { + if ((vformat & GA_TEXTURE_COORDINATE_2) != 0) { + texStride = texCoordSetCount << 1; + } else if ((vformat & GA_TEXTURE_COORDINATE_3) != 0) { + ts = 3; + texStride = texCoordSetCount*3; + } else { // GA_TEXTURE_COORDINATE_4 + ts = 4; + texStride = texCoordSetCount << 2; + } + stride += texStride; + normoff += texStride; + coloroff += texStride; + coordoff += texStride; + } + + jfloat *cverts = NULL; + + texoff = startVIndex*stride; + coordoff += texoff; + normoff += texoff; + + if (carray != NULL) { + // separate color array is used + coloroff = startVIndex*4; + } else { + coloroff += texoff; + } + + // setup coordinates pointer + strideData.fpositionPtr = &verts[coordoff]; + strideData.positionStride = stride; + + // setup color pointer + if (((vformat & GA_COLOR) == 0) || ignoreVertexColors) { + // Use Material color + // Assume VertexBuffer will recreate when ignoreVertexColors + // property changed. Otherwise we need to remove + // the following one line + vertexFormat &= ~D3DFVF_DIFFUSE; + } else { + if (carray == NULL) { + strideData.fdiffusePtr = &verts[coloroff]; + strideData.diffuseStride = stride; + strideData.useAlpha = (vformat & GA_WITH_ALPHA); + } else { + cverts = (jfloat*) env->GetPrimitiveArrayCritical(carray, NULL); + strideData.fdiffusePtr = &cverts[coloroff]; + strideData.diffuseStride = 4; + strideData.useAlpha = true; + } + } + + + // setup normal pointer + if ((vformat & GA_NORMALS) != 0) { + strideData.normalPtr = &verts[normoff]; + strideData.normalStride = stride; + } + + // setup texture pointer + setTextureCoordPointers(env, d3dCtx, device, + &strideData, + pass, texoff, stride, ts, + (vformat & GA_TEXTURE_COORDINATE), + NULL, + texCoordMapLength, + texUnitOffset, + numActiveTexUnit, + tunitstatemap, + &vertexFormat, + verts, NULL, NULL); + + + jdouble* xform_ptr = NULL; + jdouble* nxform_ptr = NULL; + + if (xform != NULL) { + xform_ptr = (jdouble *) env->GetPrimitiveArrayCritical(xform, NULL); + + } + + if (nxform != NULL) { + nxform_ptr = (jdouble *) env->GetPrimitiveArrayCritical(nxform, NULL); + } + + renderGeometry(env, d3dCtx, device, geo, geo_type, &strideData, + vertexFormat, vcount, xform_ptr, nxform_ptr, cDirty); + + if (xform_ptr != NULL) { + env->ReleasePrimitiveArrayCritical(xform, xform_ptr, 0); + } + if (nxform_ptr != NULL) { + env->ReleasePrimitiveArrayCritical(nxform, nxform_ptr, 0); + } + + + /* env->ReleasePrimitiveArrayCritical(varray, verts, NULL); */ + + if (cverts != NULL) { + env->ReleasePrimitiveArrayCritical(carray, cverts, NULL); + } +} + + +extern "C" JNIEXPORT +void JNICALL Java_javax_media_j3d_GeometryArrayRetained_buildGA(JNIEnv *env, + jobject obj, jlong ctx, jobject geo, jint geo_type, + jboolean isNonUniformScale, jboolean updateAlpha, float alpha, + jboolean ignoreVertexColors, + jint startVIndex, + jint vcount, jint vformat, + jint texCoordSetCount, + jintArray texCoordSetMapArray, + jint texCoordMapLength, + jintArray texUnitOffset, + jdoubleArray xform, jdoubleArray nxform, + jfloatArray varray) +{ + + jfloat *verts = NULL; + + if (varray != NULL) { + verts = (jfloat *) env->GetPrimitiveArrayCritical(varray, NULL); + } + + if (verts == NULL) { + return; + } + + if (((vformat & GA_COLOR) != 0) && + ((vformat & GA_BY_REFERENCE) == 0)) { + // alpha component is added for buildGA + vformat |= GA_WITH_ALPHA; + } + + + executeGeometryArray(env, + obj, ctx, geo, geo_type, isNonUniformScale, + updateAlpha, + alpha, + false, + ignoreVertexColors, + startVIndex, + vcount, + vformat, + texCoordSetCount, + texCoordSetMapArray, + texCoordMapLength, + texUnitOffset, + texCoordMapLength, + NULL, + verts, NULL, + -1, + xform, nxform, + javax_media_j3d_GeometryArrayRetained_VERTEX_CHANGED, + false); + + env->ReleasePrimitiveArrayCritical( varray, verts, 0); +} + + + +extern "C" JNIEXPORT +void JNICALL Java_javax_media_j3d_GeometryArrayRetained_execute(JNIEnv *env, + jobject obj, jlong ctx, + jobject geo, jint geo_type, + jboolean isNonUniformScale, jboolean useAlpha, + jboolean multiScreen, + jboolean ignoreVertexColors, + jint startVIndex, + jint vcount, jint vformat, jint texCoordSetCount, + jintArray texCoordSetMapArray, + jint texCoordMapLength, jintArray texUnitOffset, + jint numActiveTexUnit, + jintArray tunitstatemap, + jfloatArray varray, jfloatArray carray, + jint texUnitIndex, jint cDirty) +{ + jfloat *verts = NULL; + + if (varray != NULL) { + verts = (jfloat *) env->GetPrimitiveArrayCritical( varray, NULL); + } + + if (verts == NULL) { + return; + } + + executeGeometryArray(env, obj, ctx, geo, geo_type, + isNonUniformScale, + false, + 0, multiScreen, + ignoreVertexColors, startVIndex, + vcount, vformat, texCoordSetCount, + texCoordSetMapArray, + texCoordMapLength, texUnitOffset, + numActiveTexUnit, tunitstatemap, + verts, carray, texUnitIndex, NULL, NULL, cDirty,useAlpha); + + env->ReleasePrimitiveArrayCritical( varray, verts, 0); + +} + + +/* interleaved data with nio buffer as data format */ +extern "C" JNIEXPORT +void JNICALL Java_javax_media_j3d_GeometryArrayRetained_executeInterleavedBuffer(JNIEnv *env, + jobject obj, jlong ctx, jobject geo, jint geo_type, + jboolean isNonUniformScale, jboolean useAlpha, + jboolean multiScreen, + jboolean ignoreVertexColors, + jint startVIndex, + jint vcount, jint vformat, + jint texCoordSetCount, + jintArray texCoordSetMapArray, jint texCoordMapLength, + jintArray texUnitOffset, + jint numActiveTexUnit, + jintArray tunitstatemap, + jobject varray, jfloatArray carray, + jint texUnitIndex, jint cDirty) { + + jfloat *verts = NULL; + + /* get the direct buffer address */ + if (varray != NULL) { + verts = (jfloat *) env->GetDirectBufferAddress(varray); + } + + if (verts == NULL) { + return; + } + + /* call executeGeometryArray */ + executeGeometryArray(env, obj, ctx, geo, geo_type, + isNonUniformScale, + false, + 0, multiScreen, + ignoreVertexColors, startVIndex, + vcount, vformat, texCoordSetCount, + texCoordSetMapArray, + texCoordMapLength, texUnitOffset, + numActiveTexUnit, tunitstatemap, + verts, carray, texUnitIndex, NULL, NULL, cDirty,useAlpha); + +} + + +extern "C" JNIEXPORT +void JNICALL Java_javax_media_j3d_GeometryArrayRetained_freeD3DArray + (JNIEnv *env, jobject geo, jboolean deleteVB) +{ + + lockGeometry(); + + jclass geoClass = (jclass) env->GetObjectClass(geo); + // Free VertexBuffer associate with this GeometryArray + jfieldID fieldID = env->GetFieldID(geoClass, "pVertexBuffers", "J"); + + D3dVertexBufferVector *vbVector = + reinterpret_cast<D3dVertexBufferVector*> (env->GetLongField(geo, fieldID)); + + + if (vbVector != NULL) { + // clearLive() invoke this in Renderer thread + for (LPD3DVERTEXBUFFER *s = vbVector->begin(); + s != vbVector->end(); ++s) { + // This notify vb that parent vector is already free + // so there is no need to remove itself from vbVector + (*s)->vbVector = NULL; + (*s)->ctx->freeVB(*s); + } + env->SetLongField(geo, fieldID, 0); + vbVector->clear(); + delete vbVector; + } + + unlockGeometry(); +} + + + +void executeIndexedGeometryArray(JNIEnv *env, + jobject obj, jlong ctx, + jobject geo, jint geo_type, + jboolean isNonUniformScale, + jboolean modAlpha, // buildGA, should alpha be mode + jfloat alpha, + jboolean multiScreen, + jboolean ignoreVertexColors, + jint vcount, + jint vformat, + jint texCoordSetCount, + jintArray texCoordSetMapArray, + jint texCoordMapLength, + jintArray texUnitOffset, + jint numActiveTexUnit, + jintArray tunitstatemap, + jfloat* verts, jfloatArray carray, jint pass, + jdoubleArray xform, jdoubleArray nxform, + jint cDirty, + jboolean useAlpha, + jint initialIndexIndex, + jint indexCount, + jintArray indexCoord) // Should alpha be sent down +{ + D3DDRAWPRIMITIVESTRIDEDDATA strideData; + DWORD vertexFormat = 0; + jint stride, coordoff, normoff, coloroff, texoff; + int texStride, ts = 0; + + GetDevice(); + + ZeroMemory(&strideData, sizeof(D3DDRAWPRIMITIVESTRIDEDDATA)); + + strideData.modulateAlpha = modAlpha; + strideData.alpha = alpha; + + /* This matches the code in GeometryArrayRetained.java */ + stride = coordoff = normoff = coloroff = texoff = 0; + + if ((vformat & GA_COORDINATES) != 0) { + stride += 3; + vertexFormat |= D3DFVF_XYZ; + } else { + // nothing worth doing if no coordinates define + return; + } + + if ((vformat & GA_NORMALS) != 0) { + stride += 3; + coordoff += 3; + vertexFormat |= D3DFVF_NORMAL; + } + + if ((vformat & GA_COLOR) != 0) { + if ((vformat & GA_WITH_ALPHA) != 0 ) { + stride += 4; + normoff += 4; + coordoff += 4; + } else { // Handle the case of executeInterleaved 3f + stride += 3; + normoff += 3; + coordoff += 3; + } + vertexFormat |= D3DFVF_DIFFUSE; + } + + // In case of automatic texture generation + ts = 2; + + if (vformat & GA_TEXTURE_COORDINATE) { + if ((vformat & GA_TEXTURE_COORDINATE_2) != 0) { + texStride = texCoordSetCount << 1; + } else if ((vformat & GA_TEXTURE_COORDINATE_3) != 0) { + ts = 3; + texStride = texCoordSetCount*3; + } else { // GA_TEXTURE_COORDINATE_4 + ts = 4; + texStride = texCoordSetCount << 2; + } + stride += texStride; + normoff += texStride; + coloroff += texStride; + coordoff += texStride; + } + + jfloat *cverts = NULL; + + if (carray != NULL) { + // separate color array is used + coloroff = 0; + } else { + coloroff += texoff; + } + + // setup coordinates pointer + strideData.fpositionPtr = &verts[coordoff]; + strideData.positionStride = stride; + + // setup color pointer + if (((vformat & GA_COLOR) == 0) || ignoreVertexColors) { + // Use Material color + // Assume VertexBuffer will recreate when ignoreVertexColors + // property changed. Otherwise we need to remove + // the following one line + vertexFormat &= ~D3DFVF_DIFFUSE; + } else { + if (carray == NULL) { + strideData.fdiffusePtr = &verts[coloroff]; + strideData.diffuseStride = stride; + strideData.useAlpha = (vformat & GA_WITH_ALPHA); + } else { + cverts = (jfloat*) env->GetPrimitiveArrayCritical(carray, NULL); + strideData.fdiffusePtr = &cverts[coloroff]; + strideData.diffuseStride = 4; + strideData.useAlpha = true; + } + } + + + // setup normal pointer + if ((vformat & GA_NORMALS) != 0) { + strideData.normalPtr = &verts[normoff]; + strideData.normalStride = stride; + } + + + // setup texture pointer + setTextureCoordPointers(env, d3dCtx, device, + &strideData, + pass, texoff, stride, ts, + (vformat & GA_TEXTURE_COORDINATE), + NULL, + texCoordMapLength, + texUnitOffset, + numActiveTexUnit, + tunitstatemap, + &vertexFormat, + verts, NULL, NULL); + + // setup index pointer + strideData.indexPtr = (jint *) env->GetPrimitiveArrayCritical(indexCoord, NULL); + strideData.initialIndexIndex = initialIndexIndex; + + + jdouble* xform_ptr = NULL; + jdouble* nxform_ptr = NULL; + + if (xform != NULL) { + xform_ptr = (jdouble *) env->GetPrimitiveArrayCritical(xform, NULL); + + } + + if (nxform != NULL) { + nxform_ptr = (jdouble *) env->GetPrimitiveArrayCritical(nxform, NULL); + } + + renderIndexGeometry(env, d3dCtx, device, geo, geo_type, &strideData, + vertexFormat, vcount, indexCount, + xform_ptr, nxform_ptr, cDirty); + + + + if (xform_ptr != NULL) { + env->ReleasePrimitiveArrayCritical(xform, xform_ptr, 0); + } + if (nxform_ptr != NULL) { + env->ReleasePrimitiveArrayCritical(nxform, nxform_ptr, 0); + } + + if (cverts != NULL) { + env->ReleasePrimitiveArrayCritical(carray, cverts, NULL); + } + + env->ReleasePrimitiveArrayCritical(indexCoord, + strideData.indexPtr, NULL); +} + + +extern "C" JNIEXPORT +void JNICALL Java_javax_media_j3d_IndexedGeometryArrayRetained_executeIndexedGeometry( + JNIEnv *env, + jobject obj, jlong ctx, + jobject geo, jint geo_type, + jboolean isNonUniformScale, jboolean useAlpha, + jboolean multiScreen, + jboolean ignoreVertexColors, + jint initialIndexIndex, + jint indexCount, + jint vcount, + jint vformat, jint texCoordSetCount, + jintArray texCoordSetMapArray, + jint texCoordMapLength, jintArray texUnitOffset, + jint numActiveTexUnit, + jintArray tunitstatemap, + jfloatArray varray, jfloatArray carray, + jint texUnitIndex, jint cDirty, + jintArray indexCoord) +{ + jfloat *verts = NULL; + + if (varray != NULL) { + verts = (jfloat *) env->GetPrimitiveArrayCritical( varray, NULL); + } + + if (verts == NULL) { + return; + } + + executeIndexedGeometryArray(env, obj, ctx, geo, geo_type, + isNonUniformScale, + false, 0, multiScreen, + ignoreVertexColors, + vcount, + vformat, texCoordSetCount, + texCoordSetMapArray, + texCoordMapLength, + texUnitOffset, + numActiveTexUnit, + tunitstatemap, + verts, + carray, + texUnitIndex, + NULL, NULL, + cDirty, + useAlpha, + initialIndexIndex, + indexCount, + indexCoord); + + env->ReleasePrimitiveArrayCritical( varray, verts, 0); +} + +extern "C" JNIEXPORT +void JNICALL Java_javax_media_j3d_IndexedGeometryArrayRetained_executeIndexedGeometryBuffer( + JNIEnv *env, + jobject obj, jlong ctx, + jobject geo, jint geo_type, + jboolean isNonUniformScale, jboolean useAlpha, + jboolean multiScreen, + jboolean ignoreVertexColors, + jint initialIndexIndex, + jint indexCount, + jint vcount, + jint vformat, jint texCoordSetCount, + jintArray texCoordSetMapArray, + jint texCoordMapLength, jintArray texUnitOffset, + jint numActiveTexUnit, + jintArray tunitstatemap, + jobject varray, jfloatArray carray, + jint texUnitIndex, jint cDirty, + jintArray indexCoord) +{ + jfloat *verts = NULL; + + /* get the direct buffer address */ + if (varray != NULL) { + verts = (jfloat *) env->GetDirectBufferAddress(varray ); + } + + if (verts == NULL) + return; + + executeIndexedGeometryArray(env, obj, ctx, geo, geo_type, + isNonUniformScale, + false, 0, multiScreen, + ignoreVertexColors, + vcount, + vformat, texCoordSetCount, + texCoordSetMapArray, + texCoordMapLength, + texUnitOffset, + numActiveTexUnit, + tunitstatemap, + verts, + carray, + texUnitIndex, + NULL, NULL, + cDirty, + useAlpha, + initialIndexIndex, + indexCount, + indexCoord); +} + + +extern "C" JNIEXPORT +void JNICALL Java_javax_media_j3d_IndexedGeometryArrayRetained_buildIndexedGeometry( + JNIEnv *env, + jobject obj, jlong ctx, jobject geo, + jint geo_type, + jboolean isNonUniformScale, jboolean updateAlpha, float alpha, + jboolean ignoreVertexColors, + jint initialIndexIndex, + jint indexCount, + jint vertexCount, + jint vformat, + jint texCoordSetCount, + jintArray texCoordSetMapArray, + jint texCoordMapLength, + jintArray texUnitOffset, + jdoubleArray xform, jdoubleArray nxform, + jfloatArray varray, jintArray indexCoord) +{ + + jfloat *verts = NULL; + + if (varray != NULL) { + verts = (jfloat *) env->GetPrimitiveArrayCritical( varray, NULL); + } + + if (verts == NULL) { + return; + } + + if ((vformat & GA_COLOR) != 0) { + // alpha component is added for buildGA + vformat |= GA_WITH_ALPHA; + } + + executeIndexedGeometryArray(env, obj, ctx, geo, geo_type, + isNonUniformScale, + updateAlpha, alpha, + false, + ignoreVertexColors, + vertexCount, + vformat, + texCoordSetCount, + texCoordSetMapArray, + texCoordMapLength, + texUnitOffset, + texCoordMapLength, + NULL, + verts, + NULL, -1, + xform, nxform, + javax_media_j3d_GeometryArrayRetained_VERTEX_CHANGED| + javax_media_j3d_GeometryArrayRetained_INDEX_CHANGED, + false, + initialIndexIndex, + indexCount, + indexCoord); + + env->ReleasePrimitiveArrayCritical( varray, verts, 0); + +} + + + +void executeIndexedGeometryArrayVA( + JNIEnv *env, + jobject obj, + jlong ctx, + jobject geo, + jint geo_type, + jboolean isNonUniformScale, + jboolean multiScreen, + jboolean ignoreVertexColors, + jint initialIndexIndex, + jint indexCount, + jint vertexCount, + jint vformat, + jint vdefined, + jfloat* fverts, + jdouble* dverts, + jfloat* fclrs, + jbyte* bclrs, + jfloat* norms, + jint pass, + jint texCoordMapLength, + jintArray tcoordsetmap, + jint numActiveTexUnit, + jintArray tunitstatemap, + jint texStride, + jfloat** texCoordPointer, + jint cDirty, + jintArray indexCoord) +{ + D3DDRAWPRIMITIVESTRIDEDDATA strideData; + DWORD vertexFormat = 0; + jboolean floatCoordDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_COORD_FLOAT) != 0); + jboolean doubleCoordDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_COORD_DOUBLE) != 0); + jboolean floatColorsDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_COLOR_FLOAT) != 0); + jboolean byteColorsDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_COLOR_BYTE) != 0); + jboolean normalsDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_NORMAL_FLOAT) != 0); + jboolean textureDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_TEXCOORD_FLOAT) != 0); + + GetDevice(); + + ZeroMemory(&strideData, sizeof(D3DDRAWPRIMITIVESTRIDEDDATA)); + + // setup coordinate pointers + if (floatCoordDefined || doubleCoordDefined) { + vertexFormat |= D3DFVF_XYZ; + + if (floatCoordDefined ) { + strideData.fpositionPtr = &fverts[0]; + } else if (doubleCoordDefined) { + strideData.dpositionPtr = &dverts[0]; + } + strideData.positionStride = 3; + + } else { + // nothing worth doing if no coordinates define + return; + } + + // setup normal pointers + if (normalsDefined) { + vertexFormat |= D3DFVF_NORMAL; + strideData.normalPtr = &norms[0]; + strideData.normalStride = 3; + } + + // setup color pointers + if (!(floatColorsDefined || byteColorsDefined) + || ignoreVertexColors) { + // Use Material color + // Assume VertexBuffer will recreate when ignoreVertexColors + // property changed. Otherwise we need to remove + // the following one line + vertexFormat &= ~D3DFVF_DIFFUSE; + } else { + if ((vformat & GA_WITH_ALPHA) != 0) { + strideData.diffuseStride = 4; + strideData.useAlpha = true; + } else { + strideData.diffuseStride = 3; + strideData.useAlpha = false; + } + if (floatColorsDefined) { + strideData.fdiffusePtr = &fclrs[0]; + } else { + strideData.bdiffusePtr = &bclrs[0]; + } + + vertexFormat |= D3DFVF_DIFFUSE; + } + + + int ts = 2; // In case of automatic texture generation + + if ((vformat & GA_TEXTURE_COORDINATE_3) != 0) { + ts = 3; + } else if ((vformat & GA_TEXTURE_COORDINATE_4) != 0) { + ts = 4; + } + + // setup texture pointer + setTextureCoordPointers(env, d3dCtx, device, + &strideData, + pass, 0, + texStride, ts, + textureDefined, + tcoordsetmap, + texCoordMapLength, + NULL, + numActiveTexUnit, + tunitstatemap, + &vertexFormat, + NULL, texCoordPointer, + NULL); + + // setup index pointer + strideData.indexPtr = (jint *) env->GetPrimitiveArrayCritical(indexCoord, NULL); + strideData.initialIndexIndex = initialIndexIndex; + + // Construct/update VertexBuffer, render() if not in display list mode + renderIndexGeometry(env, d3dCtx, device, geo, geo_type, &strideData, + vertexFormat, vertexCount, indexCount, + NULL, NULL, cDirty); + + env->ReleasePrimitiveArrayCritical(indexCoord, + strideData.indexPtr, NULL); + + +} +extern "C" JNIEXPORT +void JNICALL Java_javax_media_j3d_IndexedGeometryArrayRetained_executeIndexedGeometryVA( + JNIEnv *env, + jobject obj, + jlong ctx, + jobject geo, + jint geo_type, + jboolean isNonUniformScale, + jboolean multiScreen, + jboolean ignoreVertexColors, + jint initialIndexIndex, + jint indexCount, + jint vertexCount, + jint vformat, + jint vdefined, + jfloatArray vfcoords, + jdoubleArray vdcoords, + jfloatArray cfdata, + jbyteArray cbdata, + jfloatArray ndata, + jint pass, + jint texCoordMapLength, + jintArray tcoordsetmap, + jint numActiveTexUnit, + jintArray tunitstatemap, + jint texStride, + jobjectArray texCoords, + jint cDirty, + jintArray indexCoord) +{ + jfloat *fverts = NULL; + jdouble *dverts = NULL; + jfloat *fclrs = NULL; + jbyte *bclrs = NULL; + jfloat *norms = NULL; + jfloat* texCoordPointer[D3DDP_MAXTEXCOORD]; + jarray texobjs[D3DDP_MAXTEXCOORD]; + int i; + + jboolean floatCoordDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_COORD_FLOAT) != 0); + jboolean doubleCoordDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_COORD_DOUBLE) != 0); + jboolean floatColorsDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_COLOR_FLOAT) != 0); + jboolean byteColorsDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_COLOR_BYTE) != 0); + jboolean normalsDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_NORMAL_FLOAT) != 0); + jboolean textureDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_TEXCOORD_FLOAT) != 0); + + /* get texture arrays */ + if (textureDefined) { + for (i = 0; i < texCoordMapLength; i++) { + texobjs[i] = (jarray)env->GetObjectArrayElement( texCoords, i); + } + } + + /* get coordinate array */ + if (floatCoordDefined) { + fverts= (jfloat *) env->GetPrimitiveArrayCritical( vfcoords, NULL); + } else if (doubleCoordDefined) { + dverts= (jdouble *) env->GetPrimitiveArrayCritical( vdcoords, NULL); + } + + if ((fverts == NULL) && (dverts == NULL)) { + return; + } + + /* get color array */ + if (floatColorsDefined) { + fclrs = (jfloat *) env->GetPrimitiveArrayCritical( cfdata, NULL); + } else if (byteColorsDefined) { + bclrs = (jbyte *)env->GetPrimitiveArrayCritical( cbdata, NULL); + } + + /* get normal array */ + if (normalsDefined) { + norms = (jfloat *) env->GetPrimitiveArrayCritical(ndata, NULL); + } + + /* get texture arrays */ + if (textureDefined) { + for (i = 0; i < texCoordMapLength; i++) { + if (texobjs[i] != NULL) { + texCoordPointer[i] = + (jfloat*)env->GetPrimitiveArrayCritical(texobjs[i], NULL); + } else { + texCoordPointer[i] = NULL; + } + + } + } + + + executeIndexedGeometryArrayVA(env, + obj, + ctx, + geo, + geo_type, + isNonUniformScale, + multiScreen, + ignoreVertexColors, + initialIndexIndex, + indexCount, + vertexCount, + vformat, + vdefined, + fverts, + dverts, + fclrs, + bclrs, + norms, + pass, + texCoordMapLength, + tcoordsetmap, + numActiveTexUnit, + tunitstatemap, + texStride, + texCoordPointer, + cDirty, + indexCoord); + + // Free memory + if (textureDefined) { + for (i = 0; i < texCoordMapLength; i++) { + if (texCoordPointer[i] != NULL) { + env->ReleasePrimitiveArrayCritical(texobjs[i], texCoordPointer[i], NULL); + } + } + } + + if (floatColorsDefined) { + env->ReleasePrimitiveArrayCritical(cfdata, fclrs, 0); + } else if (byteColorsDefined) { + env->ReleasePrimitiveArrayCritical(cbdata, bclrs, 0); + } + + if (normalsDefined) { + env->ReleasePrimitiveArrayCritical(ndata, norms, 0); + } + + if (floatCoordDefined) { + env->ReleasePrimitiveArrayCritical(vfcoords, fverts, 0); + } else if (doubleCoordDefined) { + env->ReleasePrimitiveArrayCritical(vdcoords, dverts, 0); + } +} + +extern "C" JNIEXPORT +void JNICALL Java_javax_media_j3d_IndexedGeometryArrayRetained_executeIndexedGeometryVABuffer( + JNIEnv *env, + jobject obj, + jlong ctx, + jobject geo, + jint geo_type, + jboolean isNonUniformScale, + jboolean multiScreen, + jboolean ignoreVertexColors, + jint initialIndexIndex, + jint indexCount, + jint vertexCount, + jint vformat, + jint vdefined, + jobject vcoords, + jobject cdataBuffer, + jfloatArray cfdata, + jbyteArray cbdata, + jobject ndata, + jint pass, + jint texCoordMapLength, + jintArray tcoordsetmap, + jint numActiveTexUnit, + jintArray tunitstatemap, + jint texStride, + jobjectArray texCoords, + jint cDirty, + jintArray indexCoord) +{ + jfloat *fverts = NULL; + jdouble *dverts = NULL; + jfloat *fclrs = NULL; + jbyte *bclrs = NULL; + jfloat *norms = NULL; + jfloat* texCoordPointer[D3DDP_MAXTEXCOORD]; + jarray texobjs[D3DDP_MAXTEXCOORD]; + int i; + + jboolean floatCoordDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_COORD_FLOAT) != 0); + jboolean doubleCoordDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_COORD_DOUBLE) != 0); + jboolean floatColorsDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_COLOR_FLOAT) != 0); + jboolean byteColorsDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_COLOR_BYTE) != 0); + jboolean normalsDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_NORMAL_FLOAT) != 0); + jboolean textureDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_TEXCOORD_FLOAT) != 0); + + /* get texture arrays */ + if (textureDefined) { + for (i = 0; i < texCoordMapLength; i++) { + texobjs[i] = (jarray)env->GetObjectArrayElement( texCoords, i); + } + } + + /* get coordinate array */ + if (floatCoordDefined) { + fverts = (jfloat *)env->GetDirectBufferAddress( vcoords ); + } else if (doubleCoordDefined) { + dverts = (jdouble *)env->GetDirectBufferAddress( vcoords ); + } + + if ((fverts == NULL) && (dverts == NULL)) { + return; + } + + /* get color array */ + if (floatColorsDefined) { + if(cfdata != NULL) { + fclrs = (jfloat *) env->GetPrimitiveArrayCritical( cfdata, NULL); + } else { + fclrs = (jfloat *) env->GetDirectBufferAddress (cdataBuffer); + } + } else if (byteColorsDefined) { + if (cbdata != NULL) { + bclrs = (jbyte *) env->GetPrimitiveArrayCritical( cbdata, NULL); + } else { + bclrs = (jbyte *) env->GetDirectBufferAddress(cdataBuffer); + } + } + + /* get normal array */ + if (normalsDefined) { + norms = (jfloat *)env->GetDirectBufferAddress(ndata); + } + /* get texture arrays */ + if (textureDefined) { + for (i = 0; i < texCoordMapLength; i++) { + if (texobjs[i] != NULL) + texCoordPointer[i] = (jfloat*)env->GetDirectBufferAddress(texobjs[i]); + else + texCoordPointer[i] = NULL; + + } + } + + + executeIndexedGeometryArrayVA( + env, + obj, + ctx, + geo, + geo_type, + isNonUniformScale, + multiScreen, + ignoreVertexColors, + initialIndexIndex, + indexCount, + vertexCount, + vformat, + vdefined, + fverts, + dverts, + fclrs, + bclrs, + norms, + pass, + texCoordMapLength, + tcoordsetmap, + numActiveTexUnit, + tunitstatemap, + texStride, + texCoordPointer, + cDirty, + indexCoord); + + if (floatColorsDefined && cfdata != NULL) { + env->ReleasePrimitiveArrayCritical( cfdata, fclrs, 0); + } else if (byteColorsDefined && cbdata != NULL) { + env->ReleasePrimitiveArrayCritical(cbdata, bclrs, 0); + } +} + +extern "C" JNIEXPORT +void JNICALL Java_javax_media_j3d_GeometryArrayRetained_buildGAForBuffer( + JNIEnv *env, + jobject obj, + jlong ctx, + jobject geo, + jint geo_type, + jboolean isNonUniformScale, + jboolean updateAlpha, + jfloat alpha, + jboolean ignoreVertexColors, + jint vcount, + jint vformat, + jint vdefined, + jint initialCoordIndex, + jobject vcoords, + jint initialColorIndex, + jobject cdataBuffer, + jint initialNormalIndex, + jobject ndata, + jint texCoordMapLength, + jintArray tcoordsetmap, + jintArray texindices, + jint texStride, + jobjectArray texCoords, + jdoubleArray xform, + jdoubleArray nxform) +{ + jfloat *fverts = NULL; + jdouble *dverts = NULL ; + jbyte *bclrs = NULL; + jfloat *fclrs = NULL, *norms = NULL; + jfloat* texCoordPointer[D3DDP_MAXTEXCOORD]; + jarray texobjs[D3DDP_MAXTEXCOORD]; + int i; + + jboolean floatCoordDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_COORD_FLOAT) != 0); + jboolean doubleCoordDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_COORD_DOUBLE) != 0); + jboolean floatColorsDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_COLOR_FLOAT) != 0); + jboolean byteColorsDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_COLOR_BYTE) != 0); + jboolean normalsDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_NORMAL_FLOAT) != 0); + jboolean textureDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_TEXCOORD_FLOAT) != 0); + + if (textureDefined) { + for (i = 0; i < texCoordMapLength; i++) { + texobjs[i] = (jarray)env->GetObjectArrayElement(texCoords, i); + } + } + + /* get coordinate array */ + if (floatCoordDefined) { + fverts = (jfloat *)env->GetDirectBufferAddress( vcoords ); + } else if (doubleCoordDefined) { + dverts = (jdouble *)env->GetDirectBufferAddress( vcoords ); + } + + if ((fverts == NULL) && (dverts == NULL)) { + return; + } + + /* get color array */ + if (floatColorsDefined) { + fclrs = (jfloat *) env->GetDirectBufferAddress(cdataBuffer); + } else if (byteColorsDefined) { + bclrs = (jbyte *) env->GetDirectBufferAddress(cdataBuffer); + } + + /* get normal array */ + if (normalsDefined) { + norms = (jfloat *)env->GetDirectBufferAddress(ndata); + } + + /* get texture arrays */ + if (textureDefined) { + for (i = 0; i < texCoordMapLength; i++) { + if (texobjs[i] != NULL) + texCoordPointer[i] = (jfloat*)env->GetDirectBufferAddress(texobjs[i]); + else + texCoordPointer[i] = NULL; + + } + } + + executeGeometryArrayVA(env, obj, ctx, geo, geo_type, + isNonUniformScale, updateAlpha, alpha, + false, ignoreVertexColors, + vcount, vformat, vdefined, initialCoordIndex, + fverts, dverts, initialColorIndex, + fclrs, bclrs, initialNormalIndex, + norms, -1, texCoordMapLength, + tcoordsetmap,texCoordMapLength, NULL, + texindices,texStride,texCoordPointer, + xform, nxform, + javax_media_j3d_GeometryArrayRetained_VERTEX_CHANGED); +} + + +extern "C" JNIEXPORT +void JNICALL Java_javax_media_j3d_GeometryArrayRetained_buildGAForByRef( + JNIEnv *env, + jobject obj, + jlong ctx, + jobject geo, + jint geo_type, + jboolean isNonUniformScale, + jboolean updateAlpha, + jfloat alpha, + jboolean ignoreVertexColors, + jint vcount, + jint vformat, + jint vdefined, + jint initialCoordIndex, + jfloatArray vfcoords, + jdoubleArray vdcoords, + jint initialColorIndex, + jfloatArray cfdata, + jbyteArray cbdata, + jint initialNormalIndex, + jfloatArray ndata, + jint texCoordMapLength, + jintArray tcoordsetmap, + jintArray texindices, + jint texStride, + jobjectArray texCoords, + jdoubleArray xform, + jdoubleArray nxform) +{ + jfloat *fverts = NULL; + jdouble *dverts = NULL; + jfloat *fclrs = NULL; + jbyte *bclrs = NULL; + jfloat *norms = NULL; + jfloat* texCoordPointer[D3DDP_MAXTEXCOORD]; + jarray texobjs[D3DDP_MAXTEXCOORD]; + int i; + + jboolean floatCoordDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_COORD_FLOAT) != 0); + jboolean doubleCoordDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_COORD_DOUBLE) != 0); + jboolean floatColorsDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_COLOR_FLOAT) != 0); + jboolean byteColorsDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_COLOR_BYTE) != 0); + jboolean normalsDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_NORMAL_FLOAT) != 0); + jboolean textureDefined = ((vdefined & javax_media_j3d_GeometryArrayRetained_TEXCOORD_FLOAT) != 0); + + + if (textureDefined) { + for (i = 0; i < texCoordMapLength; i++) { + texobjs[i] = (jarray)env->GetObjectArrayElement( texCoords, i); + } + } + + /* get coordinate array */ + if (floatCoordDefined) { + fverts= (jfloat *) env->GetPrimitiveArrayCritical( vfcoords, NULL); + } else if (doubleCoordDefined) { + dverts= (jdouble *) env->GetPrimitiveArrayCritical( vdcoords, NULL); + } + + if ((fverts == NULL) && (dverts == NULL)) { + return; + } + + /* get color array */ + if (floatColorsDefined) { + fclrs = (jfloat *) env->GetPrimitiveArrayCritical( cfdata, NULL); + } else if (byteColorsDefined) { + bclrs = (jbyte *)env->GetPrimitiveArrayCritical( cbdata, NULL); + } + + /* get normal array */ + if (normalsDefined) { + norms = (jfloat *) env->GetPrimitiveArrayCritical(ndata, NULL); + } + + /* get texture arrays */ + if (textureDefined) { + for (i = 0; i < texCoordMapLength; i++) { + if (texobjs[i] != NULL) { + texCoordPointer[i] = (jfloat*)env->GetPrimitiveArrayCritical(texobjs[i], NULL); + } else { + texCoordPointer[i] = NULL; + } + + } + } + + + executeGeometryArrayVA(env, obj, ctx, geo, geo_type, + isNonUniformScale, updateAlpha, alpha, + false, ignoreVertexColors, + vcount, vformat, vdefined, initialCoordIndex, + fverts, dverts, initialColorIndex, + fclrs, bclrs, initialNormalIndex, + norms, -1, texCoordMapLength, + tcoordsetmap,texCoordMapLength, NULL, + texindices,texStride,texCoordPointer, + xform, nxform, + javax_media_j3d_GeometryArrayRetained_VERTEX_CHANGED); + + if (floatCoordDefined) { + env->ReleasePrimitiveArrayCritical( vfcoords, fverts, 0); + } + else if (doubleCoordDefined) { + env->ReleasePrimitiveArrayCritical( vdcoords, dverts, 0); + } + + if (floatColorsDefined) { + env->ReleasePrimitiveArrayCritical( cfdata, fclrs, 0); + } + else if (byteColorsDefined) { + env->ReleasePrimitiveArrayCritical( cbdata, bclrs, 0); + } + + if (normalsDefined) { + env->ReleasePrimitiveArrayCritical( ndata, norms, 0); + } + + if (textureDefined) { + for (i = 0; i < texCoordMapLength; i++) { + if (texCoordPointer[i] != NULL) { + env->ReleasePrimitiveArrayCritical(texobjs[i], texCoordPointer[i], 0); + } + } + } +} |