⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 splines.cpp

📁 3D 游戏界的大牛人 John Carmack 终于放出了 Q3 的源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:

		Com_UngetToken();
		// read the control point
		idVec3_t point;
		Com_Parse1DMatrix( text, 3, point );
		addPoint(point.x, point.y, point.z);
	} while (1);
 
	//Com_UngetToken();
	//Com_MatchToken( text, "}" );
	dirty = true;
}

void idSplineList::write(fileHandle_t file, const char *p) {
	idStr s = va("\t\t%s {\n", p);
	FS_Write(s.c_str(), s.length(), file);
	//s = va("\t\tname %s\n", name.c_str());
	//FS_Write(s.c_str(), s.length(), file);
	s = va("\t\t\tgranularity %f\n", granularity);
	FS_Write(s.c_str(), s.length(), file);
	int count = controlPoints.Num();
	for (int i = 0; i < count; i++) {
		s = va("\t\t\t( %f %f %f )\n", controlPoints[i]->x, controlPoints[i]->y, controlPoints[i]->z);
		FS_Write(s.c_str(), s.length(), file);
	}
	s = "\t\t}\n";
	FS_Write(s.c_str(), s.length(), file);
}


void idCameraDef::getActiveSegmentInfo(int segment, idVec3_t &origin, idVec3_t &direction, float *fov) {
#if 0
	if (!cameraSpline.validTime()) {
		buildCamera();
	}
	double d = (double)segment / numSegments();
	getCameraInfo(d * totalTime * 1000, origin, direction, fov);
#endif
/*
	if (!cameraSpline.validTime()) {
		buildCamera();
	}
	origin = *cameraSpline.getSegmentPoint(segment);
	

	idVec3_t temp;

	int numTargets = getTargetSpline()->controlPoints.Num();
	int count = cameraSpline.splineTime.Num();
	if (numTargets == 0) {
		// follow the path
		if (cameraSpline.getActiveSegment() < count - 1) {
			temp = *cameraSpline.splinePoints[cameraSpline.getActiveSegment()+1];
		}
	} else if (numTargets == 1) {
		temp = *getTargetSpline()->controlPoints[0];
	} else {
		temp = *getTargetSpline()->getSegmentPoint(segment);
	}

	temp -= origin;
	temp.Normalize();
	direction = temp;
*/
}

bool idCameraDef::getCameraInfo(long time, idVec3_t &origin, idVec3_t &direction, float *fv) {


	if ((time - startTime) / 1000 > totalTime) {
		return false;
	}


	for (int i = 0; i < events.Num(); i++) {
		if (time >= startTime + events[i]->getTime() && !events[i]->getTriggered()) {
			events[i]->setTriggered(true);
			if (events[i]->getType() == idCameraEvent::EVENT_TARGET) {
				setActiveTargetByName(events[i]->getParam());
				getActiveTarget()->start(startTime + events[i]->getTime());
				//Com_Printf("Triggered event switch to target: %s\n",events[i]->getParam());
			} else if (events[i]->getType() == idCameraEvent::EVENT_TRIGGER) {
				//idEntity *ent = NULL;
				//ent = level.FindTarget( ent, events[i]->getParam());
				//if (ent) {
				//	ent->signal( SIG_TRIGGER );
				//	ent->ProcessEvent( &EV_Activate, world );
				//}
			} else if (events[i]->getType() == idCameraEvent::EVENT_FOV) {
				//*fv = fov = atof(events[i]->getParam());
			} else if (events[i]->getType() == idCameraEvent::EVENT_STOP) {
				return false;
			}
		}
	}

	origin = *cameraPosition->getPosition(time);
	
	*fv = fov.getFOV(time);

	idVec3_t temp = origin;

	int numTargets = targetPositions.Num();
	if (numTargets == 0) {
/*
		// follow the path
		if (cameraSpline.getActiveSegment() < count - 1) {
			temp = *cameraSpline.splinePoints[cameraSpline.getActiveSegment()+1];
			if (temp == origin) {
				int index = cameraSpline.getActiveSegment() + 2;
				while (temp == origin && index < count - 1) {
					temp = *cameraSpline.splinePoints[index++];
				}
			}
		}
*/
	} else {
		temp = *getActiveTarget()->getPosition(time);
	}
	
	temp -= origin;
	temp.Normalize();
	direction = temp;

	return true;
}

bool idCameraDef::waitEvent(int index) {
	//for (int i = 0; i < events.Num(); i++) {
	//	if (events[i]->getSegment() == index && events[i]->getType() == idCameraEvent::EVENT_WAIT) {
	//		return true;
	//	}
    //}
	return false;
}


#define NUM_CCELERATION_SEGS 10
#define CELL_AMT 5

void idCameraDef::buildCamera() {
	int i;
	//int lastSwitch = 0;
	idList<float> waits;
	idList<int> targets;

	totalTime = baseTime;
	cameraPosition->setTime(totalTime * 1000);
	// we have a base time layout for the path and the target path
	// now we need to layer on any wait or speed changes
	for (i = 0; i < events.Num(); i++) {
		//idCameraEvent *ev = events[i];
		events[i]->setTriggered(false);
		switch (events[i]->getType()) {
			case idCameraEvent::EVENT_TARGET : {
				targets.Append(i);
				break;
			}
			case idCameraEvent::EVENT_WAIT : {
				waits.Append(atof(events[i]->getParam()));
				cameraPosition->addVelocity(events[i]->getTime(), atof(events[i]->getParam()) * 1000, 0);
				break;
			}
			case idCameraEvent::EVENT_TARGETWAIT : {
				//targetWaits.Append(i);
				break;
			}
			case idCameraEvent::EVENT_SPEED : {
/*
				// take the average delay between up to the next five segments
				float adjust = atof(events[i]->getParam());
				int index = events[i]->getSegment();
				total = 0;
				count = 0;

				// get total amount of time over the remainder of the segment
				for (j = index; j < cameraSpline.numSegments() - 1; j++) {
					total += cameraSpline.getSegmentTime(j + 1) - cameraSpline.getSegmentTime(j);
					count++;
				}

				// multiply that by the adjustment
				double newTotal = total * adjust;
				// what is the difference.. 
				newTotal -= total;
				totalTime += newTotal / 1000;

				// per segment difference
				newTotal /= count;
				int additive = newTotal;

				// now propogate that difference out to each segment
				for (j = index; j < cameraSpline.numSegments(); j++) {
					cameraSpline.addSegmentTime(j, additive);
					additive += newTotal;
				}
				break;
*/
			}
    default: break; // FIXME: what about other idCameraEvent?
		}
	}


	for (i = 0; i < waits.Num(); i++) {
		totalTime += waits[i];
	}

	// on a new target switch, we need to take time to this point ( since last target switch ) 
	// and allocate it across the active target, then reset time to this point
	long timeSoFar = 0;
	long total = (int)(totalTime * 1000);
	for (i = 0; i < targets.Num(); i++) {
		long t;
		if (i < targets.Num() - 1) {
			t = events[targets[i+1]]->getTime();
		} else {
			t = total - timeSoFar;
		}
		// t is how much time to use for this target
		setActiveTargetByName(events[targets[i]]->getParam());
		getActiveTarget()->setTime(t);
		timeSoFar += t;
	}

	
}

void idCameraDef::startCamera(long t) {
	buildCamera();
	cameraPosition->start(t);
	//for (int i = 0; i < targetPositions.Num(); i++) {
	//	targetPositions[i]->
	//}
	startTime = t;
	cameraRunning = true;
}


void idCameraDef::parse(const char *(*text)  ) {

	const char	*token;
	do {
		token = Com_Parse( text );
	
		if ( !token[0] ) {
			break;
		}
		if ( !Q_stricmp (token, "}") ) {
			break;
		}

		if (Q_stricmp(token, "time") == 0) {
			baseTime = Com_ParseFloat(text);
		}

		if (Q_stricmp(token, "camera_fixed") == 0) {
			cameraPosition = new idFixedPosition();
			cameraPosition->parse(text);
		}

		if (Q_stricmp(token, "camera_interpolated") == 0) {
			cameraPosition = new idInterpolatedPosition();
			cameraPosition->parse(text);
		}

		if (Q_stricmp(token, "camera_spline") == 0) {
			cameraPosition = new idSplinePosition();
			cameraPosition->parse(text);
		}

		if (Q_stricmp(token, "target_fixed") == 0) {
			idFixedPosition *pos = new idFixedPosition();
			pos->parse(text);
			targetPositions.Append(pos);
		}
		
		if (Q_stricmp(token, "target_interpolated") == 0) {
			idInterpolatedPosition *pos = new idInterpolatedPosition();
			pos->parse(text);
			targetPositions.Append(pos);
		}

		if (Q_stricmp(token, "target_spline") == 0) {
			idSplinePosition *pos = new idSplinePosition();
			pos->parse(text);
			targetPositions.Append(pos);
		}

		if (Q_stricmp(token, "fov") == 0) {
			fov.parse(text);
		}

		if (Q_stricmp(token, "event") == 0) {
			idCameraEvent *event = new idCameraEvent();
			event->parse(text);
			addEvent(event);
		}


	} while (1);

	Com_UngetToken();
	Com_MatchToken( text, "}" );

}

qboolean idCameraDef::load(const char *filename) {
	char *buf;
	const char *buf_p;
	//int length = 
  FS_ReadFile( filename, (void **)&buf );
	if ( !buf ) {
		return qfalse;
	}

	clear();
	Com_BeginParseSession( filename );
	buf_p = buf;
	parse(&buf_p);
	Com_EndParseSession();
	FS_FreeFile( buf );

	return qtrue;
}

void idCameraDef::save(const char *filename) {
	fileHandle_t file = FS_FOpenFileWrite(filename);
	if (file) {
		int i;
		idStr s = "cameraPathDef { \n"; 
		FS_Write(s.c_str(), s.length(), file);
		s = va("\ttime %f\n", baseTime);
		FS_Write(s.c_str(), s.length(), file);

		cameraPosition->write(file, va("camera_%s",cameraPosition->typeStr()));

		for (i = 0; i < numTargets(); i++) {
			targetPositions[i]->write(file, va("target_%s", targetPositions[i]->typeStr()));
		}

		for (i = 0; i < events.Num(); i++) {
			events[i]->write(file, "event");
		}

		fov.write(file, "fov");

		s = "}\n";
		FS_Write(s.c_str(), s.length(), file);
	}
	FS_FCloseFile(file);
}

int idCameraDef::sortEvents(const void *p1, const void *p2) {
	idCameraEvent *ev1 = (idCameraEvent*)(p1);
	idCameraEvent *ev2 = (idCameraEvent*)(p2);

	if (ev1->getTime() > ev2->getTime()) {
		return -1;
	}
	if (ev1->getTime() < ev2->getTime()) {
		return 1;
	}
	return 0; 
}

void idCameraDef::addEvent(idCameraEvent *event) {
	events.Append(event);
	//events.Sort(&sortEvents);

}
void idCameraDef::addEvent(idCameraEvent::eventType t, const char *param, long time) {
	addEvent(new idCameraEvent(t, param, time));
	buildCamera();
}


const char *idCameraEvent::eventStr[] = {
	"NA",
	"WAIT",
	"TARGETWAIT",
	"SPEED",
	"TARGET",
	"SNAPTARGET",
	"FOV",
	"SCRIPT",
	"TRIGGER",
	"STOP"
};

void idCameraEvent::parse(const char *(*text)  ) {
	const char *token;
	Com_MatchToken( text, "{" );
	do {
		token = Com_Parse( text );
	
		if ( !token[0] ) {
			break;
		}
		if ( !strcmp (token, "}") ) {
			break;
		}

		// here we may have to jump over brush epairs ( only used in editor )
		do {
			// if token is not a brace, it is a key for a key/value pair
			if ( !token[0] || !strcmp (token, "(") || !strcmp(token, "}")) {
				break;
			}

			Com_UngetToken();
			idStr key = Com_ParseOnLine(text);
			const char *token = Com_Parse(text);
			if (Q_stricmp(key.c_str(), "type") == 0) {
				type = static_cast<idCameraEvent::eventType>(atoi(token));
			} else if (Q_stricmp(key.c_str(), "param") == 0) {
				paramStr = token;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -