375 lines
10 KiB
C
375 lines
10 KiB
C
/*
|
|
* PVVMUD a 3D MUD
|
|
* Copyright (C) 1998-1999 Programvareverkstedet (pvv@pvv.org)
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
*/
|
|
#include "pvvmud.H"
|
|
#include <stdlib.h>
|
|
#include <iostream.h>
|
|
#include "msggos.H"
|
|
#include "texture.H"
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// MsgGOSError
|
|
|
|
CMsgGOSError::CMsgGOSError():CMessage(MSG_GOSERROR, sizeof(BYTE)){
|
|
setName("MsgGOSError");
|
|
writeByte(1,0); // Error
|
|
}
|
|
|
|
CMsgGOSError::CMsgGOSError(BYTE error):CMessage(MSG_GOSERROR, sizeof(BYTE)){
|
|
setName("MsgGOSError");
|
|
writeByte(1,error);
|
|
}
|
|
|
|
BYTE CMsgGOSError::getError(){
|
|
return readByte(1);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// MsgGOSRequest
|
|
|
|
CMsgGOSRequest::CMsgGOSRequest():CMessage(MSG_GOSREQUEST, sizeof(BYTE) + sizeof(WORD)){
|
|
setName("MsgGOSRequest");
|
|
}
|
|
|
|
CMsgGOSRequest::CMsgGOSRequest(BYTE requestType,WORD objectId):CMessage(MSG_GOSREQUEST, sizeof(BYTE) + sizeof(WORD)){
|
|
setName("MsgGOSRequest");
|
|
writeByte(1,requestType);
|
|
writeWord(2,objectId);
|
|
}
|
|
|
|
BYTE CMsgGOSRequest::getRequestType(){
|
|
return readByte(1);
|
|
}
|
|
|
|
WORD CMsgGOSRequest::getObjectId(){
|
|
return readWord(2);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// MsgGeometry
|
|
|
|
CMsgGeometry::CMsgGeometry():CMsgVarLength(MSG_GEOMETRY){
|
|
setName("MsgGeometry");
|
|
}
|
|
|
|
#define HEADSIZE (sizeof(DWORD)+sizeof(WORD)*4)
|
|
#define VERTEXSIZE (3*sizeof(DWORD))
|
|
#define NORMALSIZE (3*sizeof(DWORD))
|
|
#define TEXCOORDSIZE (2*sizeof(DWORD))
|
|
#define POLYGONHEADSIZE (sizeof(DWORD)+4*sizeof(WORD))
|
|
|
|
CMsgGeometry::CMsgGeometry(CGeometry & geometry):CMsgVarLength(MSG_GEOMETRY){
|
|
setName("MsgGeometry");
|
|
WORD numV,numN,numTC,numP;
|
|
int type,materialId,numVI,numNI,numTCI;
|
|
|
|
DWORD size = sizeof(DWORD)+sizeof(WORD); // GeometryId + NumSubObjects
|
|
WORD numSubObjects = 0;
|
|
|
|
// Calculate size
|
|
CGeometry * geo = &geometry;
|
|
while (geo != NULL){
|
|
numSubObjects++;
|
|
size += HEADSIZE;
|
|
numV = geo->getNumVertices();
|
|
numN = geo->getNumNormals();
|
|
numTC = geo->getNumTexCoords();
|
|
numP = geo->getNumPolygons();
|
|
size += numV*VERTEXSIZE+numN*NORMALSIZE+numTC*TEXCOORDSIZE;
|
|
while (numP-- > 0){
|
|
size += POLYGONHEADSIZE;
|
|
CPolygon * poly = geo->getPolygon(numP);
|
|
poly->get(&type,&materialId,&numVI,&numNI,&numTCI);
|
|
size += (numVI + numNI + numTCI)*sizeof(WORD);
|
|
}
|
|
|
|
geo = geo->getNext();
|
|
}
|
|
// Then the size is known
|
|
setBodyLength(size);
|
|
|
|
cdebug << "Geometry: size " << size << "\n";
|
|
|
|
// Write geometry
|
|
writeDWord(getLength(),geometry.getId());
|
|
writeWord(MSGCURRPOS,numSubObjects);
|
|
geo = &geometry;
|
|
while (geo != NULL){
|
|
numV = geo->getNumVertices();
|
|
numN = geo->getNumNormals();
|
|
numTC = geo->getNumTexCoords();
|
|
numP = geo->getNumPolygons();
|
|
|
|
// Write geometry head
|
|
writeWord(MSGCURRPOS,numV);
|
|
writeWord(MSGCURRPOS,numN);
|
|
writeWord(MSGCURRPOS,numTC);
|
|
writeWord(MSGCURRPOS,numP);
|
|
writeDWord(MSGCURRPOS,geo->getSubId());
|
|
|
|
// Write geometry body
|
|
// Vertices
|
|
while (numV-- > 0){
|
|
CVertex * vertex = geo->getVertex(numV);
|
|
writeDouble(MSGCURRPOS,vertex->getZ());
|
|
writeDouble(MSGCURRPOS,vertex->getY());
|
|
writeDouble(MSGCURRPOS,vertex->getX());
|
|
}
|
|
// Normals
|
|
while (numN-- > 0){
|
|
CNormal * normal = geo->getNormal(numN);
|
|
writeDouble(MSGCURRPOS,normal->getZ());
|
|
writeDouble(MSGCURRPOS,normal->getY());
|
|
writeDouble(MSGCURRPOS,normal->getX());
|
|
}
|
|
// TexCoords
|
|
while (numTC-- > 0){
|
|
CTexCoord * texCoord = geo->getTexCoord(numTC);
|
|
writeDouble(MSGCURRPOS,texCoord->getV());
|
|
writeDouble(MSGCURRPOS,texCoord->getU());
|
|
}
|
|
// Polygons
|
|
while (numP-- > 0){
|
|
CPolygon * poly = geo->getPolygon(numP);
|
|
|
|
// Write polygon head
|
|
poly->get(&type,&materialId,&numVI,&numNI,&numTCI);
|
|
writeDWord(MSGCURRPOS,materialId);
|
|
writeWord(MSGCURRPOS,type);
|
|
writeWord(MSGCURRPOS,numVI);
|
|
writeWord(MSGCURRPOS,numNI);
|
|
writeWord(MSGCURRPOS,numTCI);
|
|
|
|
// Write polygon body
|
|
// Vertex index list
|
|
while (numVI-- > 0){
|
|
writeWord(MSGCURRPOS,poly->getVertexIndex(numVI));
|
|
}
|
|
|
|
// Normal index list
|
|
while (numNI-- > 0){
|
|
writeWord(MSGCURRPOS,poly->getNormalIndex(numNI));
|
|
}
|
|
|
|
// TexCoord index list
|
|
while (numTCI-- > 0){
|
|
writeWord(MSGCURRPOS,poly->getTexCoordIndex(numTCI));
|
|
}
|
|
|
|
}
|
|
|
|
geo = geo->getNext();
|
|
}
|
|
}
|
|
|
|
DWORD CMsgGeometry::getGeometryId(){
|
|
return readDWord(getLength());
|
|
}
|
|
|
|
CGeometry* CMsgGeometry::getGeometry(){
|
|
// cdebug << "CMsgGeometry::getGeometry: Not impl.!\n";
|
|
|
|
CGeometry *geo = NULL;
|
|
|
|
// Set the current read pointer in correct position
|
|
DWORD geometryId = getGeometryId();
|
|
|
|
// Get number of subobjects and read them
|
|
WORD numSubObjects = readWord(MSGCURRPOS);
|
|
while (numSubObjects-- > 0){
|
|
|
|
// Read geometry head and create geometry
|
|
WORD numV = readWord(MSGCURRPOS);
|
|
WORD numN = readWord(MSGCURRPOS);
|
|
WORD numTC = readWord(MSGCURRPOS);
|
|
WORD numP = readWord(MSGCURRPOS);
|
|
|
|
CGeometry * newgeo = newGeometry(geometryId,numV,numN,numTC,numP);
|
|
newgeo->setNext(geo);
|
|
geo = newgeo;
|
|
|
|
geo->setSubId(readDWord(MSGCURRPOS));
|
|
|
|
// Read geometry body
|
|
// Vertices
|
|
while (numV-- > 0){
|
|
geo->setVertex(numV,readDouble(MSGCURRPOS),readDouble(MSGCURRPOS),readDouble(MSGCURRPOS));
|
|
}
|
|
// Normals
|
|
while (numN-- > 0){
|
|
geo->setNormal(numN,readDouble(MSGCURRPOS),readDouble(MSGCURRPOS),readDouble(MSGCURRPOS));
|
|
}
|
|
// TexCoords
|
|
while (numTC-- > 0){
|
|
geo->setTexCoord(numTC,readDouble(MSGCURRPOS),readDouble(MSGCURRPOS));
|
|
}
|
|
// Polygons
|
|
while (numP-- > 0){
|
|
int type,materialId,numVI,numNI,numTCI;
|
|
|
|
// Read polygon head
|
|
materialId = readDWord(MSGCURRPOS);
|
|
type = readWord(MSGCURRPOS);
|
|
numVI = readWord(MSGCURRPOS);
|
|
numNI = readWord(MSGCURRPOS);
|
|
numTCI = readWord(MSGCURRPOS);
|
|
CPolygon * poly = new CPolygon(type,materialId,numVI,numNI,numTCI);
|
|
|
|
// Read polygon body
|
|
// Read vertex index list
|
|
while (numVI-- > 0){
|
|
poly->setVertexIndex(numVI,readWord(MSGCURRPOS));
|
|
}
|
|
|
|
// Read normal index list
|
|
while (numNI-- > 0){
|
|
poly->setNormalIndex(numNI,readWord(MSGCURRPOS));
|
|
}
|
|
|
|
// Read texCoord index list
|
|
while (numTCI-- > 0){
|
|
poly->setTexCoordIndex(numTCI,readWord(MSGCURRPOS));
|
|
}
|
|
|
|
geo->setPolygon(numP,poly);
|
|
|
|
}
|
|
|
|
}
|
|
return geo;
|
|
}
|
|
|
|
CGeometry * CMsgGeometry::newGeometry(int geometryId, int numVertices,
|
|
int numNormals, int numTexCoords, int numPolygons){
|
|
return new CGeometry(geometryId,numVertices,numNormals,
|
|
numTexCoords,numPolygons);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// MsgMaterial
|
|
|
|
CMsgMaterial::CMsgMaterial():CMessage(MSG_MATERIAL,sizeof(WORD)*2+4*4+1){
|
|
setName("MsgMaterial");
|
|
}
|
|
|
|
CMsgMaterial::CMsgMaterial(CMaterial & material):CMessage(MSG_MATERIAL,sizeof(WORD)*2+4*4+1){
|
|
cdebug << "CMegsMaterial\n";
|
|
setName("MsgMaterial");
|
|
writeWord(1,material.getId());
|
|
writeWord(3,material.getTextureId());
|
|
for (int ii = 0; ii < 4 ; ii++){
|
|
writeByte(5+ii,material.getAmbientByte(ii));
|
|
writeByte(9+ii,material.getDiffuseByte(ii));
|
|
writeByte(13+ii,material.getSpecularByte(ii));
|
|
writeByte(17+ii,material.getEmissionByte(ii));
|
|
}
|
|
writeByte(21,material.getShininessByte());
|
|
}
|
|
|
|
int CMsgMaterial::getMaterialId(){
|
|
return (short int)readWord(1);
|
|
}
|
|
|
|
int CMsgMaterial::getTextureId(){
|
|
return (short int)readWord(3);
|
|
}
|
|
|
|
BYTE CMsgMaterial::getAmbientByte(int num){
|
|
return readByte(5+num);
|
|
}
|
|
|
|
BYTE CMsgMaterial::getDiffuseByte(int num){
|
|
return readByte(9+num);
|
|
}
|
|
|
|
BYTE CMsgMaterial::getSpecularByte(int num){
|
|
return readByte(13+num);
|
|
}
|
|
|
|
BYTE CMsgMaterial::getEmissionByte(int num){
|
|
return readByte(17+num);
|
|
}
|
|
|
|
BYTE CMsgMaterial::getShininessByte(){
|
|
return readByte(21);
|
|
}
|
|
|
|
CMaterial* CMsgMaterial::getMaterial(){
|
|
CMaterial * material = newMaterial(getMaterialId());
|
|
material->setTextureId(getTextureId());
|
|
for (int ii = 0; ii < 4; ii++){
|
|
material->setAmbient(ii,getAmbientByte(ii));
|
|
material->setDiffuse(ii,getDiffuseByte(ii));
|
|
material->setSpecular(ii,getSpecularByte(ii));
|
|
material->setEmission(ii,getEmissionByte(ii));
|
|
}
|
|
material->setShininess(getShininessByte());
|
|
return material;
|
|
}
|
|
|
|
CMaterial * CMsgMaterial::newMaterial(int materialId){
|
|
return new CMaterial(materialId);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// MsgTexture
|
|
|
|
CMsgTexture::CMsgTexture():CMsgVarLength(MSG_TEXTURE){
|
|
setName("MsgTexture");
|
|
}
|
|
|
|
CMsgTexture::CMsgTexture(CTexture & texture):CMsgVarLength(MSG_TEXTURE){
|
|
setName("MsgTexture");
|
|
CTextureMap * map = texture.getTextureMap();
|
|
setBodyLength(sizeof(WORD)*3 + map->getWidth()*map->getHeight()*sizeof(DWORD));
|
|
writeWord(getLength(),texture.getId());
|
|
writeWord(getLength()+2,map->getWidth());
|
|
writeWord(getLength()+4,map->getHeight());
|
|
writeBuf(getLength()+6,map->getData(),map->getWidth()*map->getHeight()*sizeof(DWORD));
|
|
}
|
|
|
|
WORD CMsgTexture::getTextureId(){
|
|
return readWord(getLength());
|
|
}
|
|
|
|
WORD CMsgTexture::getMapWidth(){
|
|
return readWord(getLength()+2);
|
|
}
|
|
|
|
WORD CMsgTexture::getMapHeight(){
|
|
return readWord(getLength()+4);
|
|
}
|
|
|
|
CTexture * CMsgTexture::getTexture(){
|
|
CTexture * texture = newTexture(getTextureId());
|
|
WORD width = getMapWidth();
|
|
WORD height = getMapHeight();
|
|
BYTE * data = (BYTE*)malloc(width*height*sizeof(DWORD));
|
|
readBuf(getLength()+6,data,width*height*sizeof(DWORD));
|
|
CTextureMap * map = new CTextureMap(width,height,data);
|
|
texture->setTextureMap(map);
|
|
return texture;
|
|
}
|
|
|
|
CTexture * CMsgTexture::newTexture(int textureId){
|
|
return new CTexture(textureId);
|
|
}
|
|
|