aboutsummaryrefslogtreecommitdiffstats
path: root/src/native/d3d/GeometryArrayRetained.cpp
diff options
context:
space:
mode:
authorKevin Rushforth <[email protected]>2004-06-09 04:25:41 +0000
committerKevin Rushforth <[email protected]>2004-06-09 04:25:41 +0000
commit343b658c32a6473c545187c1e276ee5d06c2686a (patch)
treead2606538b7db1c3553c53a79ccccb2ed5b5e4e2 /src/native/d3d/GeometryArrayRetained.cpp
parent06cebb1e576da6f7222f999ab059dcfa3d8edd39 (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.cpp5254
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);
+ }
+ }
+ }
+}